Add JSI-based JSExecutor for the bridge

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
This commit is contained in:
Marc Horowitz
2018-10-18 00:47:04 -07:00
committed by Facebook Github Bot
parent a23fb1a22c
commit 749b18dbc9
10 changed files with 888 additions and 0 deletions

View File

@@ -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"),
],
)

View File

@@ -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);
}

View File

@@ -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";
}
}

View File

@@ -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();
});
}