Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ReactAndroid/Android-prebuilt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/ReactCommon.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions ReactCommon/react/bridging/Android.mk
Original file line number Diff line number Diff line change
@@ -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)
19 changes: 19 additions & 0 deletions ReactCommon/react/bridging/BUCK
Original file line number Diff line number Diff line change
@@ -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"),
],
)
99 changes: 99 additions & 0 deletions ReactCommon/react/bridging/CallbackWrapper.h
Original file line number Diff line number Diff line change
@@ -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 <jsi/jsi.h>
#include <react/bridging/LongLivedObject.h>

#include <memory>

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<CallInvoker> jsInvoker)
: longLivedObjectCollection_(),
callback_(std::move(callback)),
runtime_(runtime),
jsInvoker_(std::move(jsInvoker)) {}

CallbackWrapper(
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection,
jsi::Function &&callback,
jsi::Runtime &runtime,
std::shared_ptr<CallInvoker> 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> longLivedObjectCollection_;
jsi::Function callback_;
jsi::Runtime &runtime_;
std::shared_ptr<CallInvoker> jsInvoker_;

public:
static std::weak_ptr<CallbackWrapper> createWeak(
jsi::Function &&callback,
jsi::Runtime &runtime,
std::shared_ptr<CallInvoker> jsInvoker) {
auto wrapper = std::shared_ptr<CallbackWrapper>(
new CallbackWrapper(std::move(callback), runtime, jsInvoker));
LongLivedObjectCollection::get().add(wrapper);
return wrapper;
}

static std::weak_ptr<CallbackWrapper> createWeak(
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection,
jsi::Function &&callback,
jsi::Runtime &runtime,
std::shared_ptr<CallInvoker> jsInvoker) {
auto wrapper = std::shared_ptr<CallbackWrapper>(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
57 changes: 57 additions & 0 deletions ReactCommon/react/bridging/LongLivedObject.h
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.
*/

#pragma once

#include <memory>
#include <mutex>
#include <unordered_set>

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<T>().
* 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<LongLivedObject> o) const;
void remove(const LongLivedObject *o) const;
void clear() const;

private:
mutable std::unordered_set<std::shared_ptr<LongLivedObject>> collection_;
mutable std::mutex collectionMutex_;
};

} // namespace react
} // namespace facebook
41 changes: 41 additions & 0 deletions ReactCommon/react/bridging/React-bridging.podspec
Original file line number Diff line number Diff line change
@@ -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
9 changes: 6 additions & 3 deletions ReactCommon/react/nativemodule/core/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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\"
Expand All @@ -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)
1 change: 1 addition & 0 deletions ReactCommon/react/nativemodule/core/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
],
)
50 changes: 2 additions & 48 deletions ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,5 @@

#pragma once

#include <memory>
#include <mutex>
#include <unordered_set>

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<T>().
* 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<LongLivedObject> o) const;
void remove(const LongLivedObject *o) const;
void clear() const;

private:
mutable std::unordered_set<std::shared_ptr<LongLivedObject>> collection_;
mutable std::mutex collectionMutex_;
};

} // namespace react
} // namespace facebook
// This header is left here for compatibility reasons.
#include <react/bridging/LongLivedObject.h>
Loading