Skip to content

Commit

Permalink
Share re-defined defineReadOnlyGlobal(...) (facebook#42801)
Browse files Browse the repository at this point in the history
Summary:

Fixes some tech debug

Changelog: [Internal] [Fixed] Share re-defined defineReadOnlyGlobal(...)

Reviewed By: javache

Differential Revision: D53340274
  • Loading branch information
christophpurrer authored and facebook-github-bot committed Feb 19, 2024
1 parent 475a156 commit d21e735
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 74 deletions.
3 changes: 2 additions & 1 deletion packages/react-native/ReactCommon/ReactCommon.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ Pod::Spec.new do |s|

ss.subspec "core" do |sss|
sss.source_files = "react/nativemodule/core/ReactCommon/**/*.{cpp,h}"
sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers\"" }
sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-jsiutils/React_jsiutils.framework/Headers\"" }
sss.dependency "React-debug", version
sss.dependency "React-jsiutils", version
end
end
end
23 changes: 23 additions & 0 deletions packages/react-native/ReactCommon/react/jsiutils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)

add_compile_options(
-fexceptions
-frtti
-std=c++20
-Wall
-Wpedantic
-DLOG_TAG=\"Fabric\")

file(GLOB react_jsiutils_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_jsiutils STATIC ${react_jsiutils_SRC})

target_include_directories(react_jsiutils PUBLIC ${REACT_COMMON_DIR})

target_link_libraries(react_jsiutils
jsireact)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

require "json"

package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "package.json")))
version = package['version']

source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end

folly_config = get_folly_config()
folly_compiler_flags = folly_config[:compiler_flags]
folly_version = folly_config[:version]

header_search_paths = [
"\"$(PODS_TARGET_SRCROOT)\"",
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
]

Pod::Spec.new do |s|
s.name = "React-jsiutils"
s.version = version
s.summary = "-" # TODO
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = "*.{cpp,h}"
s.compiler_flags = folly_compiler_flags
s.header_dir = "react/jsiutils"
s.exclude_files = "tests"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES" }

if ENV['USE_FRAMEWORKS']
s.module_name = "React_jsiutils"
s.header_mappings_dir = "../.."
end

s.dependency "React-jsi", version

if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
s.dependency "hermes-engine"
else
s.dependency "React-jsc"
end
end
39 changes: 39 additions & 0 deletions packages/react-native/ReactCommon/react/jsiutils/globals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "globals.h"

namespace facebook::react {

void defineReadOnlyGlobal(
jsi::Runtime& runtime,
const std::string& propName,
jsi::Value&& value) {
auto global = runtime.global();
if (global.hasProperty(runtime, propName.c_str())) {
throw jsi::JSError(
runtime,
"Tried to redefine read-only global \"" + propName +
"\", but read-only globals can only be defined once.");
}
jsi::Object jsObject =
global.getProperty(runtime, "Object").asObject(runtime);
jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty")
.asObject(runtime)
.asFunction(runtime);

jsi::Object descriptor = jsi::Object(runtime);
descriptor.setProperty(runtime, "value", std::move(value));
defineProperty.callWithThis(
runtime,
jsObject,
global,
jsi::String::createFromUtf8(runtime, propName),
descriptor);
}

} // namespace facebook::react
31 changes: 31 additions & 0 deletions packages/react-native/ReactCommon/react/jsiutils/globals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <jsi/jsi.h>
#include <string>

namespace facebook::react {

/**
* Defines a property on the global object that is neither enumerable, nor
* configurable, nor writable. This ensures that the private globals exposed by
* ReactInstance cannot overwritten by third-party JavaScript code. It also
* ensures that third-party JavaScript code unaware of these globals isn't able
* to accidentally access them. In JavaScript, equivalent to:
*
* Object.defineProperty(global, propName, {
* value: value
* })
*/
void defineReadOnlyGlobal(
jsi::Runtime& runtime,
const std::string& propName,
jsi::Value&& value);

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ add_library(react_nativemodule_core

target_include_directories(react_nativemodule_core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/platform/android/
)
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/platform/android/
)

target_link_libraries(react_nativemodule_core
fbjni
Expand All @@ -35,5 +35,6 @@ target_link_libraries(react_nativemodule_core
jsi
react_bridging
react_debug
react_jsiutils
reactperflogger
reactnativejni)
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

#include "TurboModuleBinding.h"

#include <cxxreact/SystraceSection.h>
#include <react/jsiutils/globals.h>
#include <stdexcept>
#include <string>

#include <cxxreact/SystraceSection.h>

using namespace facebook;

namespace facebook::react {
Expand Down Expand Up @@ -62,33 +62,6 @@ class BridgelessNativeModuleProxy : public jsi::HostObject {
}
};

// TODO(148359183): Merge this with the Bridgeless defineReadOnlyGlobal util
static void defineReadOnlyGlobal(
jsi::Runtime& runtime,
std::string propName,
jsi::Value&& value) {
if (runtime.global().hasProperty(runtime, propName.c_str())) {
throw jsi::JSError(
runtime,
"Tried to redefine read-only global \"" + propName +
"\", but read-only globals can only be defined once.");
}
jsi::Object jsObject =
runtime.global().getProperty(runtime, "Object").asObject(runtime);
jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty")
.asObject(runtime)
.asFunction(runtime);

jsi::Object descriptor = jsi::Object(runtime);
descriptor.setProperty(runtime, "value", std::move(value));
defineProperty.callWithThis(
runtime,
jsObject,
runtime.global(),
jsi::String::createFromUtf8(runtime, propName),
descriptor);
}

/**
* Public API to install the TurboModule system.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ target_include_directories(bridgeless PUBLIC .)

find_library(LIBHERMES NAMES hermes-engine::libhermes)
if (LIBHERMES)
target_link_libraries(bridgeless hermes-engine::libhermes)
target_link_libraries(bridgeless hermes-engine::libhermes)
endif ()

target_link_libraries(
Expand All @@ -35,6 +35,7 @@ target_link_libraries(
fb
jsi
jsireact
react_jsiutils
react_utils
jsinspector
react_featureflags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ Pod::Spec.new do |s|
s.dependency folly_dep_name, folly_version
s.dependency "React-nativeconfig"
s.dependency "React-jsitracing"
s.dependency "React-utils"
s.dependency "React-jsi"
s.dependency "React-jsiutils"
s.dependency "React-utils"
s.dependency "React-RuntimeCore"
s.dependency "React-featureflags"
add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern')
Expand Down
41 changes: 2 additions & 39 deletions packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
#include <cxxreact/ErrorUtils.h>
#include <cxxreact/JSBigString.h>
#include <cxxreact/JSExecutor.h>
#include <cxxreact/ReactMarker.h>
#include <cxxreact/SystraceSection.h>
#include <glog/logging.h>
#include <jsi/JSIDynamic.h>
#include <jsi/instrumentation.h>
#include <jsireact/JSIExecutor.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/jsiutils/globals.h>
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>

#include <cxxreact/ReactMarker.h>
#include <iostream>
#include <tuple>
#include <utility>
Expand Down Expand Up @@ -140,43 +140,6 @@ ReactInstance::getRuntimeScheduler() noexcept {
return runtimeScheduler_;
}

/**
* Defines a property on the global object that is neither enumerable, nor
* configurable, nor writable. This ensures that the private globals exposed by
* ReactInstance cannot overwritten by third-party JavaScript code. It also
* ensures that third-party JavaScript code unaware of these globals isn't able
* to accidentally access them. In JavaScript, equivalent to:
*
* Object.defineProperty(global, propName, {
* value: value
* })
*/
static void defineReadOnlyGlobal(
jsi::Runtime& runtime,
std::string propName,
jsi::Value&& value) {
if (runtime.global().hasProperty(runtime, propName.c_str())) {
throw jsi::JSError(
runtime,
"Tried to redefine read-only global \"" + propName +
"\", but read-only globals can only be defined once.");
}
jsi::Object jsObject =
runtime.global().getProperty(runtime, "Object").asObject(runtime);
jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty")
.asObject(runtime)
.asFunction(runtime);

jsi::Object descriptor = jsi::Object(runtime);
descriptor.setProperty(runtime, "value", std::move(value));
defineProperty.callWithThis(
runtime,
jsObject,
runtime.global(),
jsi::String::createFromUtf8(runtime, propName),
descriptor);
}

namespace {

// Copied from JSIExecutor.cpp
Expand Down

0 comments on commit d21e735

Please sign in to comment.