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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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.
*/

package com.facebook.react.turbomodule.core

import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip

/**
* A Java holder for a C++ BindingsInstallerHolder.
*/
@DoNotStrip
public class BindingsInstallerHolder(@field:DoNotStrip private val mHybridData: HybridData)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.
*/

package com.facebook.react.turbomodule.core.interfaces

import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.turbomodule.core.BindingsInstallerHolder

/**
* Implements this interface if a TurboModule needs to install its own JSI bindings.
*/
@DoNotStrip
public interface TurboModuleWithJSIBindings {
/**
* Returns the [BindingsInstallerHolder] that the core will later invoke with
* an `facebook::jsi::Runtime` instance.
* The implementation will typically mix with JNI and C++.
*/
@DoNotStrip
public fun getBindingsInstaller(): BindingsInstallerHolder
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ target_link_libraries(callinvokerholder
add_library(
turbomodulejsijni
SHARED
ReactCommon/BindingsInstallerHolder.cpp
ReactCommon/CompositeTurboModuleManagerDelegate.cpp
ReactCommon/OnLoad.cpp
ReactCommon/TurboModuleManager.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 "BindingsInstallerHolder.h"

namespace facebook::react {

BindingsInstallerHolder::BindingsInstallerHolder(
TurboModule::BindingsInstaller bindingsInstaller)
: bindingsInstaller_(bindingsInstaller) {}

TurboModule::BindingsInstaller BindingsInstallerHolder::get() {
return bindingsInstaller_;
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 <ReactCommon/TurboModule.h>
#include <fbjni/fbjni.h>

namespace facebook::react {

class BindingsInstallerHolder
: public jni::HybridClass<BindingsInstallerHolder> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/turbomodule/core/BindingsInstallerHolder;";

TurboModule::BindingsInstaller get();

private:
friend HybridBase;
BindingsInstallerHolder(TurboModule::BindingsInstaller bindingsInstaller);
TurboModule::BindingsInstaller bindingsInstaller_;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <fbjni/fbjni.h>
#include <jsi/jsi.h>

#include <ReactCommon/BindingsInstallerHolder.h>
#include <ReactCommon/CxxTurboModuleUtils.h>
#include <ReactCommon/JavaInteropTurboModule.h>
#include <ReactCommon/TurboCxxModule.h>
Expand Down Expand Up @@ -128,8 +129,10 @@ void TurboModuleManager::registerNatives() {

TurboModuleProviderFunctionType TurboModuleManager::createTurboModuleProvider(
jni::alias_ref<jhybridobject> javaPart,
jsi::Runtime* runtime,
bool enableSyncVoidMethods) {
return [turboModuleCache_ = std::weak_ptr<ModuleCache>(turboModuleCache_),
runtime,
jsCallInvoker_ = std::weak_ptr<CallInvoker>(jsCallInvoker_),
nativeMethodCallInvoker_ =
std::weak_ptr<NativeMethodCallInvoker>(nativeMethodCallInvoker_),
Expand Down Expand Up @@ -208,6 +211,18 @@ TurboModuleProviderFunctionType TurboModuleManager::createTurboModuleProvider(
.shouldVoidMethodsExecuteSync = enableSyncVoidMethods};

auto turboModule = delegate->cthis()->getTurboModule(name, params);
if (moduleInstance->isInstanceOf(
JTurboModuleWithJSIBindings::javaClassStatic())) {
auto getBindingsInstaller =
moduleInstance->getClass()
->getMethod<BindingsInstallerHolder::javaobject()>(
"getBindingsInstaller");
auto installer = getBindingsInstaller(moduleInstance);
if (installer) {
installer->cthis()->get()(*runtime);
}
}

turboModuleCache->insert({name, turboModule});
TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName);
return turboModule;
Expand Down Expand Up @@ -325,7 +340,8 @@ void TurboModuleManager::installJSIBindings(
enableSyncVoidMethods](jsi::Runtime& runtime) {
TurboModuleBinding::install(
runtime,
cxxPart->createTurboModuleProvider(javaPart, enableSyncVoidMethods),
cxxPart->createTurboModuleProvider(
javaPart, &runtime, enableSyncVoidMethods),
shouldCreateLegacyModules
? cxxPart->createLegacyModuleProvider(javaPart)
: nullptr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class TurboModuleManager : public jni::HybridClass<TurboModuleManager> {

TurboModuleProviderFunctionType createTurboModuleProvider(
jni::alias_ref<jhybridobject> javaPart,
jsi::Runtime* runtime,
bool enableSyncVoidMethods);
TurboModuleProviderFunctionType createLegacyModuleProvider(
jni::alias_ref<jhybridobject> javaPart);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject {
public:
TurboModule(std::string name, std::shared_ptr<CallInvoker> jsInvoker);

using BindingsInstaller = std::function<void(jsi::Runtime& runtime)>;

// Note: keep this method declared inline to avoid conflicts
// between RTTI and non-RTTI compilation units
facebook::jsi::Value get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ struct JTurboModule : jni::JavaClass<JTurboModule> {
"Lcom/facebook/react/turbomodule/core/interfaces/TurboModule;";
};

struct JTurboModuleWithJSIBindings
: jni::JavaClass<JTurboModuleWithJSIBindings> {
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/turbomodule/core/interfaces/TurboModuleWithJSIBindings;";
};

class JSI_EXPORT JavaTurboModule : public TurboModule {
public:
// TODO(T65603471): Should we unify this with a Fabric abstraction?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ target_include_directories(sampleturbomodule PUBLIC .)
target_link_libraries(sampleturbomodule
fbjni
jsi
react_nativemodule_core)
react_nativemodule_core
turbomodulejsijni)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 <ReactCommon/SampleTurboModuleJSIBindings.h>

namespace facebook::react {

// static
void SampleTurboModuleJSIBindings::registerNatives() {
javaClassLocal()->registerNatives({
makeNativeMethod(
"getBindingsInstallerCxx",
SampleTurboModuleJSIBindings::getBindingsInstallerCxx),
});
}

// static
jni::local_ref<BindingsInstallerHolder::javaobject>
SampleTurboModuleJSIBindings::getBindingsInstallerCxx(
jni::alias_ref<jni::JClass> clazz) {
return jni::make_local(
BindingsInstallerHolder::newObjectCxxArgs([](jsi::Runtime& runtime) {
runtime.global().setProperty(
runtime, "__SampleTurboModuleJSIBindings", "Hello JSI!");
}));
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 <ReactCommon/BindingsInstallerHolder.h>
#include <fbjni/fbjni.h>
#include <jsi/jsi.h>

namespace facebook::react {

class SampleTurboModuleJSIBindings
: public jni::JavaClass<SampleTurboModuleJSIBindings> {
public:
static constexpr const char* kJavaDescriptor =
"Lcom/facebook/fbreact/specs/SampleTurboModule;";

SampleTurboModuleJSIBindings() = default;

static void registerNatives();

private:
// Using static function as a simple demonstration
static jni::local_ref<BindingsInstallerHolder::javaobject>
getBindingsInstallerCxx(jni::alias_ref<jni::JClass> clazz);
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.turbomodule.core.BindingsInstallerHolder;
import com.facebook.react.turbomodule.core.interfaces.TurboModuleWithJSIBindings;
import java.util.HashMap;
import java.util.Map;

@ReactModule(name = SampleTurboModule.NAME)
public class SampleTurboModule extends NativeSampleTurboModuleSpec {
public class SampleTurboModule extends NativeSampleTurboModuleSpec
implements TurboModuleWithJSIBindings {

public static final String NAME = "SampleTurboModule";

Expand Down Expand Up @@ -251,4 +254,12 @@ public void invalidate() {}
public String getName() {
return NAME;
}

@Override
@DoNotStrip
public BindingsInstallerHolder getBindingsInstaller() {
return getBindingsInstallerCxx();
}

private static native BindingsInstallerHolder getBindingsInstallerCxx();
}
2 changes: 2 additions & 0 deletions packages/rn-tester/android/app/src/main/jni/OnLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <DefaultComponentsRegistry.h>
#include <DefaultTurboModuleManagerDelegate.h>
#include <NativeCxxModuleExample.h>
#include <ReactCommon/SampleTurboModuleJSIBindings.h>
#include <ReactCommon/SampleTurboModuleSpec.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
Expand Down Expand Up @@ -73,5 +74,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
facebook::react::DefaultComponentsRegistry::
registerComponentDescriptorsFromEntryPoint =
&facebook::react::registerComponents;
facebook::react::SampleTurboModuleJSIBindings::registerNatives();
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import styles from './TurboModuleExampleCommon';
import * as React from 'react';
import {
FlatList,
Platform,
RootTagContext,
Text,
TouchableOpacity,
Expand Down Expand Up @@ -128,6 +129,9 @@ class SampleTurboModuleExample extends React.Component<{||}, State> {
this._setResult('promiseAssert', e.message);
});
},
installJSIBindings: () => {
return global.__SampleTurboModuleJSIBindings;
},
};

_setResult(
Expand Down Expand Up @@ -194,6 +198,14 @@ class SampleTurboModuleExample extends React.Component<{||}, State> {
'Cannot load this example because TurboModule is not configured.',
);
}
if (
global.__SampleTurboModuleJSIBindings == null &&
Platform.OS === 'android' // TODO: Add iOS support
) {
throw new Error(
'The JSI bindings for SampleTurboModule are not installed.',
);
}
}

render(): React.Node {
Expand Down