Skip to content

Commit

Permalink
Add JSI-based JSExecutor for the bridge
Browse files Browse the repository at this point in the history
Summary:
This is similar in function to the old JSCExecutor, but uses the more abstract JSI API to interact with the JSVM.
@public

Reviewed By: axe-fb

Differential Revision: D9328241

fbshipit-source-id: 3212ff4f43d0589a70d7bebc4d463d4433590f1d
  • Loading branch information
mhorowitz authored and facebook-github-bot committed Oct 18, 2018
1 parent a23fb1a commit 749b18d
Show file tree
Hide file tree
Showing 10 changed files with 888 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rn_android_library(
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/devsupport:interfaces"),
react_native_target("java/com/facebook/react/fabric:fabric"),
react_native_target("java/com/facebook/react/jscexecutor:jscexecutor"),
react_native_target("java/com/facebook/react/module/annotations:annotations"),
react_native_target("java/com/facebook/react/module/model:model"),
react_native_target("java/com/facebook/react/modules/core:core"),
Expand Down
35 changes: 35 additions & 0 deletions ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "rn_xplat_cxx_library", "react_native_xplat_target", "react_native_target", "react_native_dep", "rn_android_library")

rn_android_library(
name = "jscexecutor",
srcs = glob(["*.java"]),
visibility = [
"PUBLIC",
],
deps = [
":jni",
react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"),
react_native_target("java/com/facebook/react/bridge:bridge"),
],
)

rn_xplat_cxx_library(
name = "jni",
srcs = glob(["*.cpp"]),
headers = glob(["*.h"]),
header_namespace = "",
compiler_flags = ["-fexceptions"],
platforms = ANDROID,
fbandroid_allow_jni_merging = True,
soname = "libjscexecutor.$(ext)",
visibility = [
react_native_target("java/com/facebook/react/jscexecutor:jscexecutor"),
],
deps = [
"xplat//folly:molly",
FBJNI_TARGET,
react_native_target("jni/react/jni:jni"),
react_native_xplat_target("jsi:JSCRuntime"),
react_native_xplat_target("jsiexecutor:jsiexecutor"),
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* <p>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.jscexecutor;

import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.JavaScriptExecutor;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.soloader.SoLoader;

@DoNotStrip
/* package */ class JSCExecutor extends JavaScriptExecutor {
static {
SoLoader.loadLibrary("jscexecutor");
}

/* package */ JSCExecutor(ReadableNativeMap jscConfig) {
super(initHybrid(jscConfig));
}

@Override
public String getName() {
return "JSCExecutor";
}

private static native HybridData initHybrid(ReadableNativeMap jscConfig);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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.jscexecutor;

import com.facebook.react.bridge.JavaScriptExecutor;
import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.WritableNativeMap;

public class JSCExecutorFactory implements JavaScriptExecutorFactory {
private final String mAppName;
private final String mDeviceName;

public JSCExecutorFactory(String appName, String deviceName) {
this.mAppName = appName;
this.mDeviceName = deviceName;
}

@Override
public JavaScriptExecutor create() throws Exception {
WritableNativeMap jscConfig = new WritableNativeMap();
jscConfig.putString("OwnerIdentity", "ReactNative");
jscConfig.putString("AppIdentity", mAppName);
jscConfig.putString("DeviceIdentity", mDeviceName);
return new JSCExecutor(jscConfig);
}

@Override
public String toString() {
return "JSIExecutor+JSCRuntime";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2004-present Facebook. All Rights Reserved.

#include <fb/fbjni.h>
#include <folly/Memory.h>
#include <jsi/JSCRuntime.h>
#include <jsireact/JSIExecutor.h>
#include <react/jni/JavaScriptExecutorHolder.h>
#include <react/jni/JReactMarker.h>
#include <react/jni/JSLogging.h>
#include <react/jni/ReadableNativeMap.h>

namespace facebook {
namespace react {

namespace {

class JSCExecutorFactory : public JSExecutorFactory {
public:
std::unique_ptr<JSExecutor> createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue) override {
return folly::make_unique<JSIExecutor>(
jsc::makeJSCRuntime(),
delegate,
[](const std::string& message, unsigned int logLevel) {
reactAndroidLoggingHook(message, logLevel);
},
JSIExecutor::defaultTimeoutInvoker,
nullptr);
}
};

}

// This is not like JSCJavaScriptExecutor, which calls JSC directly. This uses
// JSIExecutor with JSCRuntime.
class JSCExecutorHolder
: public jni::HybridClass<JSCExecutorHolder, JavaScriptExecutorHolder> {
public:
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/jscexecutor/JSCExecutor;";

static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>, ReadableNativeMap*) {
// This is kind of a weird place for stuff, but there's no other
// good place for initialization which is specific to JSC on
// Android.
JReactMarker::setLogPerfMarkerIfNeeded();
// TODO mhorowitz T28461666 fill in some missing nice to have glue
return makeCxxInstance(folly::make_unique<JSCExecutorFactory>());
}

static void registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", JSCExecutorHolder::initHybrid),
});
}

private:
friend HybridBase;
using HybridBase::HybridBase;
};

} // namespace react
} // namespace facebook

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
return facebook::jni::initialize(vm, [] {
facebook::react::JSCExecutorHolder::registerNatives();
});
}
39 changes: 39 additions & 0 deletions ReactCommon/jsiexecutor/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
load("//tools/build_defs/oss:rn_defs.bzl", "cxx_library", "react_native_xplat_dep", "react_native_xplat_target")

cxx_library(
name = "jsiexecutor",
srcs = [
"jsireact/JSIExecutor.cpp",
"jsireact/JSINativeModules.cpp",
],
header_namespace = "",
exported_headers = {
"jsireact/JSIExecutor.h": "jsireact/JSIExecutor.h",
"jsireact/JSINativeModules.h": "jsireact/JSINativeModules.h",
},
compiler_flags = [
"-fexceptions",
"-frtti",
],
fbandroid_deps = [
"xplat//folly:molly",
"xplat//third-party/glog:glog",
"xplat//third-party/linker_lib:atomic",
],
fbobjc_force_static = True,
fbobjc_header_path_prefix = "",
platforms = (ANDROID, APPLE),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
visibility = [
"PUBLIC",
],
xcode_public_headers_symlinks = True,
deps = [
react_native_xplat_dep("jsi:jsi"),
react_native_xplat_dep("jsi:JSIDynamic"),
react_native_xplat_target("cxxreact:bridge"),
],
)
Loading

0 comments on commit 749b18d

Please sign in to comment.