diff --git a/ReactAndroid/Android-prebuilt.mk b/ReactAndroid/Android-prebuilt.mk index 45db144a4263..726a8a1d025e 100644 --- a/ReactAndroid/Android-prebuilt.mk +++ b/ReactAndroid/Android-prebuilt.mk @@ -82,6 +82,7 @@ LOCAL_MODULE := react_nativemodule_core LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_nativemodule_core.so LOCAL_EXPORT_C_INCLUDES := \ $(REACT_ANDROID_SRC_DIR)/jni \ + $(REACT_COMMON_DIR) \ $(REACT_COMMON_DIR)/callinvoker \ $(REACT_COMMON_DIR)/jsi \ $(REACT_COMMON_DIR)/react/nativemodule/core \ diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index cd4dc1693e1f..2dffbe2bd71f 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -32,13 +32,14 @@ Pod::Spec.new do |s| s.source = source s.header_dir = "ReactCommon" # Use global header_dir for all subspecs for use_frameworks! compatibility s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Headers/Private/React-Core\"", + s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Headers/Private/React-Core\" \"$(PODS_ROOT)/Headers/Private/React-bridging\"", "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } # TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..." # Note: Update this only when ready to minimize breaking changes. s.subspec "turbomodule" do |ss| + ss.dependency "React-bridging", version ss.dependency "React-callinvoker", version ss.dependency "React-perflogger", version ss.dependency "React-Core", version diff --git a/ReactCommon/react/bridging/Android.mk b/ReactCommon/react/bridging/Android.mk new file mode 100644 index 000000000000..63ffe3603b3b --- /dev/null +++ b/ReactCommon/react/bridging/Android.mk @@ -0,0 +1,27 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_bridging + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) + +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../ + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := jsi + +include $(BUILD_STATIC_LIBRARY) + +$(call import-module,butter) +$(call import-module,folly) +$(call import-module,jsi) diff --git a/ReactCommon/react/bridging/BUCK b/ReactCommon/react/bridging/BUCK new file mode 100644 index 000000000000..eb5b3ae0ae4d --- /dev/null +++ b/ReactCommon/react/bridging/BUCK @@ -0,0 +1,19 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "CXX", "react_native_xplat_shared_library_target", "react_native_xplat_target", "rn_xplat_cxx_library") + +rn_xplat_cxx_library( + name = "bridging", + srcs = glob(["*.cpp"]), + header_namespace = "react/bridging", + exported_headers = glob(["*.h"]), + labels = ["supermodule:xplat/default/public.react_native.infra"], + platforms = (ANDROID, APPLE, CXX), + visibility = ["PUBLIC"], + deps = [ + "//xplat/folly:headers_only", + ], + exported_deps = [ + react_native_xplat_target("butter:butter"), + react_native_xplat_target("callinvoker:callinvoker"), + react_native_xplat_shared_library_target("jsi:jsi"), + ], +) diff --git a/ReactCommon/react/bridging/CallbackWrapper.h b/ReactCommon/react/bridging/CallbackWrapper.h new file mode 100644 index 000000000000..92bba36ccb35 --- /dev/null +++ b/ReactCommon/react/bridging/CallbackWrapper.h @@ -0,0 +1,99 @@ +/* + * 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 +#include + +#include + +namespace facebook { +namespace react { + +// Helper for passing jsi::Function arg to other methods. +class CallbackWrapper : public LongLivedObject { + private: + CallbackWrapper( + jsi::Function &&callback, + jsi::Runtime &runtime, + std::shared_ptr jsInvoker) + : longLivedObjectCollection_(), + callback_(std::move(callback)), + runtime_(runtime), + jsInvoker_(std::move(jsInvoker)) {} + + CallbackWrapper( + std::shared_ptr longLivedObjectCollection, + jsi::Function &&callback, + jsi::Runtime &runtime, + std::shared_ptr jsInvoker) + : longLivedObjectCollection_(longLivedObjectCollection), + callback_(std::move(callback)), + runtime_(runtime), + jsInvoker_(std::move(jsInvoker)) {} + + // Use a weak_ptr to avoid a retain cycle: LongLivedObjectCollection owns all + // CallbackWrappers. So, CallbackWrapper cannot own its + // LongLivedObjectCollection. + std::weak_ptr longLivedObjectCollection_; + jsi::Function callback_; + jsi::Runtime &runtime_; + std::shared_ptr jsInvoker_; + + public: + static std::weak_ptr createWeak( + jsi::Function &&callback, + jsi::Runtime &runtime, + std::shared_ptr jsInvoker) { + auto wrapper = std::shared_ptr( + new CallbackWrapper(std::move(callback), runtime, jsInvoker)); + LongLivedObjectCollection::get().add(wrapper); + return wrapper; + } + + static std::weak_ptr createWeak( + std::shared_ptr longLivedObjectCollection, + jsi::Function &&callback, + jsi::Runtime &runtime, + std::shared_ptr jsInvoker) { + auto wrapper = std::shared_ptr(new CallbackWrapper( + longLivedObjectCollection, std::move(callback), runtime, jsInvoker)); + longLivedObjectCollection->add(wrapper); + return wrapper; + } + + // Delete the enclosed jsi::Function + void destroy() { + allowRelease(); + } + + jsi::Function &callback() { + return callback_; + } + + jsi::Runtime &runtime() { + return runtime_; + } + + CallInvoker &jsInvoker() { + return *(jsInvoker_); + } + + void allowRelease() override { + if (auto longLivedObjectCollection = longLivedObjectCollection_.lock()) { + if (longLivedObjectCollection != nullptr) { + longLivedObjectCollection->remove(this); + return; + } + } + LongLivedObject::allowRelease(); + } +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.cpp b/ReactCommon/react/bridging/LongLivedObject.cpp similarity index 100% rename from ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.cpp rename to ReactCommon/react/bridging/LongLivedObject.cpp diff --git a/ReactCommon/react/bridging/LongLivedObject.h b/ReactCommon/react/bridging/LongLivedObject.h new file mode 100644 index 000000000000..332dccb16594 --- /dev/null +++ b/ReactCommon/react/bridging/LongLivedObject.h @@ -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. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/** + * A simple wrapper class that can be registered to a collection that keep it + * alive for extended period of time. This object can be removed from the + * collection when needed. + * + * The subclass of this class must be created using std::make_shared(). + * After creation, add it to the `LongLivedObjectCollection`. + * When done with the object, call `allowRelease()` to allow the OS to release + * it. + */ +class LongLivedObject { + public: + virtual void allowRelease(); + + protected: + LongLivedObject(); + virtual ~LongLivedObject(); +}; + +/** + * A singleton, thread-safe, write-only collection for the `LongLivedObject`s. + */ +class LongLivedObjectCollection { + public: + static LongLivedObjectCollection &get(); + + LongLivedObjectCollection(); + LongLivedObjectCollection(LongLivedObjectCollection const &) = delete; + void operator=(LongLivedObjectCollection const &) = delete; + + void add(std::shared_ptr o) const; + void remove(const LongLivedObject *o) const; + void clear() const; + + private: + mutable std::unordered_set> collection_; + mutable std::mutex collectionMutex_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/bridging/React-bridging.podspec b/ReactCommon/react/bridging/React-bridging.podspec new file mode 100644 index 000000000000..bf467f7263e5 --- /dev/null +++ b/ReactCommon/react/bridging/React-bridging.podspec @@ -0,0 +1,41 @@ +# 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_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2021.06.28.00-v2' + +Pod::Spec.new do |s| + s.name = "React-bridging" + s.version = version + s.summary = "-" # TODO + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Facebook, Inc. and its affiliates" + s.platforms = { :ios => "11.0" } + s.source = source + s.source_files = "**/*.{cpp,h}" + s.exclude_files = "tests" + s.header_dir = "react/bridging" + s.compiler_flags = folly_compiler_flags + s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\"", + "USE_HEADERMAP" => "YES", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } + + s.dependency "RCT-Folly", folly_version + s.dependency "React-jsi", version +end diff --git a/ReactCommon/react/nativemodule/core/Android.mk b/ReactCommon/react/nativemodule/core/Android.mk index adbe95626318..8689f2bfe11c 100644 --- a/ReactCommon/react/nativemodule/core/Android.mk +++ b/ReactCommon/react/nativemodule/core/Android.mk @@ -9,11 +9,11 @@ include $(CLEAR_VARS) LOCAL_MODULE := react_nativemodule_core -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../ $(LOCAL_PATH)/ReactCommon $(LOCAL_PATH)/platform/android/ReactCommon +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ReactCommon $(LOCAL_PATH)/platform/android/ReactCommon LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) $(wildcard $(LOCAL_PATH)/platform/android/ReactCommon/*.cpp) -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/platform/android/ +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../ $(LOCAL_PATH) $(LOCAL_PATH)/platform/android/ LOCAL_SHARED_LIBRARIES := \ libfbjni \ @@ -22,7 +22,9 @@ LOCAL_SHARED_LIBRARIES := \ libreact_debug \ libreactnativejni -LOCAL_STATIC_LIBRARIES := libreactperflogger +LOCAL_STATIC_LIBRARIES := \ + libreact_bridging \ + libreactperflogger LOCAL_CFLAGS := \ -DLOG_TAG=\"ReactNative\" @@ -34,3 +36,4 @@ include $(BUILD_SHARED_LIBRARY) $(call import-module,folly) $(call import-module,jsi) $(call import-module,reactperflogger) +$(call import-module,react/bridging) diff --git a/ReactCommon/react/nativemodule/core/BUCK b/ReactCommon/react/nativemodule/core/BUCK index b0e29b37c244..52e6c812f359 100644 --- a/ReactCommon/react/nativemodule/core/BUCK +++ b/ReactCommon/react/nativemodule/core/BUCK @@ -78,6 +78,7 @@ rn_xplat_cxx_library( react_native_xplat_target("reactperflogger:reactperflogger"), ], exported_deps = [ + react_native_xplat_target("react/bridging:bridging"), react_native_xplat_shared_library_target("jsi:jsi"), ], ) diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h b/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h index 332dccb16594..1e1fa0cdb5d7 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h @@ -7,51 +7,5 @@ #pragma once -#include -#include -#include - -namespace facebook { -namespace react { - -/** - * A simple wrapper class that can be registered to a collection that keep it - * alive for extended period of time. This object can be removed from the - * collection when needed. - * - * The subclass of this class must be created using std::make_shared(). - * After creation, add it to the `LongLivedObjectCollection`. - * When done with the object, call `allowRelease()` to allow the OS to release - * it. - */ -class LongLivedObject { - public: - virtual void allowRelease(); - - protected: - LongLivedObject(); - virtual ~LongLivedObject(); -}; - -/** - * A singleton, thread-safe, write-only collection for the `LongLivedObject`s. - */ -class LongLivedObjectCollection { - public: - static LongLivedObjectCollection &get(); - - LongLivedObjectCollection(); - LongLivedObjectCollection(LongLivedObjectCollection const &) = delete; - void operator=(LongLivedObjectCollection const &) = delete; - - void add(std::shared_ptr o) const; - void remove(const LongLivedObject *o) const; - void clear() const; - - private: - mutable std::unordered_set> collection_; - mutable std::mutex collectionMutex_; -}; - -} // namespace react -} // namespace facebook +// This header is left here for compatibility reasons. +#include diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h index 4515841cc086..92e10268daf0 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h @@ -13,7 +13,8 @@ #include #include -#include +#include +#include namespace facebook { namespace react { @@ -38,86 +39,6 @@ jsi::Value createPromiseAsJSIValue( jsi::Runtime &rt, const PromiseSetupFunctionType func); -// Helper for passing jsi::Function arg to other methods. -class CallbackWrapper : public LongLivedObject { - private: - CallbackWrapper( - jsi::Function &&callback, - jsi::Runtime &runtime, - std::shared_ptr jsInvoker) - : longLivedObjectCollection_(), - callback_(std::move(callback)), - runtime_(runtime), - jsInvoker_(std::move(jsInvoker)) {} - - CallbackWrapper( - std::shared_ptr longLivedObjectCollection, - jsi::Function &&callback, - jsi::Runtime &runtime, - std::shared_ptr jsInvoker) - : longLivedObjectCollection_(longLivedObjectCollection), - callback_(std::move(callback)), - runtime_(runtime), - jsInvoker_(std::move(jsInvoker)) {} - - // Use a weak_ptr to avoid a retain cycle: LongLivedObjectCollection owns all - // CallbackWrappers. So, CallbackWrapper cannot own its - // LongLivedObjectCollection. - std::weak_ptr longLivedObjectCollection_; - jsi::Function callback_; - jsi::Runtime &runtime_; - std::shared_ptr jsInvoker_; - - public: - static std::weak_ptr createWeak( - jsi::Function &&callback, - jsi::Runtime &runtime, - std::shared_ptr jsInvoker) { - auto wrapper = std::shared_ptr( - new CallbackWrapper(std::move(callback), runtime, jsInvoker)); - LongLivedObjectCollection::get().add(wrapper); - return wrapper; - } - - static std::weak_ptr createWeak( - std::shared_ptr longLivedObjectCollection, - jsi::Function &&callback, - jsi::Runtime &runtime, - std::shared_ptr jsInvoker) { - auto wrapper = std::shared_ptr(new CallbackWrapper( - longLivedObjectCollection, std::move(callback), runtime, jsInvoker)); - longLivedObjectCollection->add(wrapper); - return wrapper; - } - - // Delete the enclosed jsi::Function - void destroy() { - allowRelease(); - } - - jsi::Function &callback() { - return callback_; - } - - jsi::Runtime &runtime() { - return runtime_; - } - - CallInvoker &jsInvoker() { - return *(jsInvoker_); - } - - void allowRelease() override { - if (auto longLivedObjectCollection = longLivedObjectCollection_.lock()) { - if (longLivedObjectCollection != nullptr) { - longLivedObjectCollection->remove(this); - return; - } - } - LongLivedObject::allowRelease(); - } -}; - class RAIICallbackWrapperDestroyer { public: RAIICallbackWrapperDestroyer(std::weak_ptr callbackWrapper) diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 703accf39381..233f8977598c 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -110,6 +110,9 @@ PODS: - React-RCTSettings (= 1000.0.0) - React-RCTText (= 1000.0.0) - React-RCTVibration (= 1000.0.0) + - React-bridging (1000.0.0): + - RCT-Folly (= 2021.06.28.00-v2) + - React-jsi (= 1000.0.0) - React-callinvoker (1000.0.0) - React-Codegen (1000.0.0): - FBReactNativeSpec (= 1000.0.0) @@ -691,6 +694,7 @@ PODS: - DoubleConversion - glog - RCT-Folly (= 2021.06.28.00-v2) + - React-bridging (= 1000.0.0) - React-callinvoker (= 1000.0.0) - React-Core (= 1000.0.0) - React-cxxreact (= 1000.0.0) @@ -701,6 +705,7 @@ PODS: - DoubleConversion - glog - RCT-Folly (= 2021.06.28.00-v2) + - React-bridging (= 1000.0.0) - React-callinvoker (= 1000.0.0) - React-Core (= 1000.0.0) - React-cxxreact (= 1000.0.0) @@ -749,6 +754,7 @@ DEPENDENCIES: - RCTRequired (from `../../Libraries/RCTRequired`) - RCTTypeSafety (from `../../Libraries/TypeSafety`) - React (from `../../`) + - React-bridging (from `../../ReactCommon/react/bridging`) - React-callinvoker (from `../../ReactCommon/callinvoker`) - React-Codegen (from `build/generated/ios`) - React-Core (from `../../`) @@ -820,6 +826,8 @@ EXTERNAL SOURCES: :path: "../../Libraries/TypeSafety" React: :path: "../../" + React-bridging: + :path: "../../ReactCommon/react/bridging" React-callinvoker: :path: "../../ReactCommon/callinvoker" React-Codegen: @@ -902,6 +910,7 @@ SPEC CHECKSUMS: RCTRequired: af2d6080a4b9ba0885b28ca78879a92066c71cab RCTTypeSafety: 2d6c5149fd3b8f2ba89987b47169423efb740300 React: f64c9f6db5428717922a3292ba6a448615a2e143 + React-bridging: a86401f93edb5564d437595060e55306c877462d React-callinvoker: c5d61e29df57793f0dc10ec2bc01c846f863e51f React-Codegen: c4ae835565487e494740b756ce953d8f635a76df React-Core: 30784d0eacbd709a3a6a5ae7c02c928634a6247e @@ -928,7 +937,7 @@ SPEC CHECKSUMS: React-RCTVibration: 9a73a3550a0ee184530341f91f9b85ad9cf3465a React-rncore: b6e9b49eb1c7c045b98c77b1f94932e3c0be7cec React-runtimeexecutor: 4b0c6eb341c7d3ceb5e2385cb0fdb9bf701024f3 - ReactCommon: 9607f2246289d573adcbd144c02c19ae5246d6a5 + ReactCommon: f5fd5011a78235afb572a4618bd04a672b41da9d ScreenshotManager: 8a08e488cb533b83ebe069ad6109d9c1df9cea79 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: faebdb8710c7e742c6ab99e14ed4270b8da27f1f diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 3a168f2fd578..97beacb7308d 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -63,6 +63,7 @@ def use_react_native! (options={}) pod 'React-Core/DevSupport', :path => "#{prefix}/" end + pod 'React-bridging', :path => "#{prefix}/ReactCommon/react/bridging" pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact" pod 'React-jsi', :path => "#{prefix}/ReactCommon/jsi" pod 'React-jsiexecutor', :path => "#{prefix}/ReactCommon/jsiexecutor"