Pass jsc config to JSC

Reviewed By: astreet

Differential Revision: D2965497

fb-gh-sync-id: 1aef5a1f2d7ccb8de8ca403e51ebcf247bd6b034
shipit-source-id: 1aef5a1f2d7ccb8de8ca403e51ebcf247bd6b034
This commit is contained in:
Andrei Coman 2016-02-26 03:23:19 -08:00 committed by Facebook Github Bot 6
parent 542432fc3e
commit d032cc967d
10 changed files with 71 additions and 26 deletions

View File

@ -12,6 +12,7 @@ import javax.annotation.Nullable;
import android.app.Instrumentation;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.view.View;
import android.view.ViewGroup;
@ -24,9 +25,9 @@ import com.facebook.react.bridge.JavaScriptModulesConfig;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
import com.facebook.react.bridge.NativeModuleRegistry;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
import android.support.test.InstrumentationRegistry;
import com.android.internal.util.Predicate;
public class ReactTestHelper {
@ -60,7 +61,7 @@ public class ReactTestHelper {
public CatalystInstance build() {
return new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(new JSCJavaScriptExecutor())
.setJSExecutor(new JSCJavaScriptExecutor(new WritableNativeMap()))
.setRegistry(mNativeModuleRegistryBuilder.build())
.setJSModulesConfig(mJSModulesConfigBuilder.build())
.setJSBundleLoader(JSBundleLoader.createFileLoader(

View File

@ -0,0 +1,12 @@
// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react;
import com.facebook.react.bridge.WritableNativeMap;
/**
* Interface for the configuration object that is passed to JSC.
*/
public interface JSCConfig {
public WritableNativeMap getConfigMap();
}

View File

@ -181,6 +181,7 @@ public abstract class ReactInstanceManager {
protected @Nullable LifecycleState mInitialLifecycleState;
protected @Nullable UIImplementationProvider mUIImplementationProvider;
protected @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
protected @Nullable JSCConfig mJSCConfig;
protected Builder() {
}
@ -274,6 +275,11 @@ public abstract class ReactInstanceManager {
return this;
}
public Builder setJSCConfig(JSCConfig jscConfig) {
mJSCConfig = jscConfig;
return this;
}
/**
* Instantiates a new {@link ReactInstanceManagerImpl}.
* Before calling {@code build}, the following must be called:
@ -307,7 +313,8 @@ public abstract class ReactInstanceManager {
mBridgeIdleDebugListener,
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),
mUIImplementationProvider,
mNativeModuleCallExceptionHandler);
mNativeModuleCallExceptionHandler,
mJSCConfig);
}
}
}

View File

@ -127,6 +127,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START
private final UIImplementationProvider mUIImplementationProvider;
private final MemoryPressureRouter mMemoryPressureRouter;
private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
private final @Nullable JSCConfig mJSCConfig;
private final ReactInstanceDevCommandsHandler mDevInterface =
new ReactInstanceDevCommandsHandler() {
@ -193,7 +194,9 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START
protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) {
Assertions.assertCondition(params != null && params.length > 0 && params[0] != null);
try {
JavaScriptExecutor jsExecutor = params[0].getJsExecutorFactory().create();
JavaScriptExecutor jsExecutor =
params[0].getJsExecutorFactory().create(
mJSCConfig == null ? new WritableNativeMap() : mJSCConfig.getConfigMap());
return Result.of(createReactContext(jsExecutor, params[0].getJsBundleLoader()));
} catch (Exception e) {
// Pass exception to onPostExecute() so it can be handled on the main thread
@ -274,7 +277,8 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
LifecycleState initialLifecycleState,
UIImplementationProvider uiImplementationProvider,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
@Nullable JSCConfig jscConfig) {
initializeSoLoaderIfNecessary(applicationContext);
// TODO(9577825): remove this
@ -296,6 +300,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START
mUIImplementationProvider = uiImplementationProvider;
mMemoryPressureRouter = new MemoryPressureRouter(applicationContext);
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mJSCConfig = jscConfig;
}
@Override

View File

@ -16,8 +16,8 @@ import com.facebook.soloader.SoLoader;
public class JSCJavaScriptExecutor extends JavaScriptExecutor {
public static class Factory implements JavaScriptExecutor.Factory {
@Override
public JavaScriptExecutor create() throws Exception {
return new JSCJavaScriptExecutor();
public JavaScriptExecutor create(WritableNativeMap jscConfig) throws Exception {
return new JSCJavaScriptExecutor(jscConfig);
}
}
@ -25,10 +25,10 @@ public class JSCJavaScriptExecutor extends JavaScriptExecutor {
SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB);
}
public JSCJavaScriptExecutor() {
initialize();
public JSCJavaScriptExecutor(WritableNativeMap jscConfig) {
initialize(jscConfig);
}
private native void initialize();
private native void initialize(WritableNativeMap jscConfig);
}

View File

@ -15,7 +15,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public abstract class JavaScriptExecutor extends Countable {
public interface Factory {
JavaScriptExecutor create() throws Exception;
JavaScriptExecutor create(WritableNativeMap jscConfig) throws Exception;
}
/**

View File

@ -32,7 +32,7 @@ public class ProxyJavaScriptExecutor extends JavaScriptExecutor {
}
@Override
public JavaScriptExecutor create() throws Exception {
public JavaScriptExecutor create(WritableNativeMap jscConfig) throws Exception {
return new ProxyJavaScriptExecutor(mJavaJSExecutorFactory.create());
}
}

View File

@ -7,7 +7,7 @@
#include <mutex>
#include <sstream>
#include <string>
#include <glog/logging.h>
#include <folly/json.h>
#include <folly/String.h>
#include <sys/time.h>
@ -83,13 +83,14 @@ static std::string executeJSCallWithJSC(
}
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(Bridge *bridge) {
return std::unique_ptr<JSExecutor>(new JSCExecutor(bridge, cacheDir_));
return std::unique_ptr<JSExecutor>(new JSCExecutor(bridge, cacheDir_, m_jscConfig));
}
JSCExecutor::JSCExecutor(Bridge *bridge, const std::string& cacheDir) :
JSCExecutor::JSCExecutor(Bridge *bridge, const std::string& cacheDir, const folly::dynamic& jscConfig) :
m_bridge(bridge),
m_deviceCacheDir(cacheDir),
m_messageQueueThread(MessageQueues::getCurrentMessageQueueThread()) {
m_messageQueueThread(MessageQueues::getCurrentMessageQueueThread()),
m_jscConfig(jscConfig) {
initOnJSVMThread();
}
@ -98,12 +99,14 @@ JSCExecutor::JSCExecutor(
int workerId,
JSCExecutor *owner,
const std::string& script,
const std::unordered_map<std::string, std::string>& globalObjAsJSON) :
const std::unordered_map<std::string, std::string>& globalObjAsJSON,
const folly::dynamic& jscConfig) :
m_bridge(bridge),
m_workerId(workerId),
m_owner(owner),
m_deviceCacheDir(owner->m_deviceCacheDir),
m_messageQueueThread(MessageQueues::getCurrentMessageQueueThread()) {
m_messageQueueThread(MessageQueues::getCurrentMessageQueueThread()),
m_jscConfig(jscConfig) {
// We post initOnJSVMThread here so that the owner doesn't have to wait for
// initialization on its own thread
m_messageQueueThread->runOnQueue([this, script, globalObjAsJSON] () {
@ -145,6 +148,8 @@ void JSCExecutor::initOnJSVMThread() {
installGlobalFunction(m_context, "nativeLoggingHook", JSLogging::nativeHook);
// TODO (t10136849): Pass the config options from map to JSC
#ifdef WITH_FB_JSC_TUNING
configureJSCForAndroid();
#endif
@ -317,7 +322,7 @@ int JSCExecutor::addWebWorker(
auto workerMQT = WebWorkerUtil::createWebWorkerThread(workerId, m_messageQueueThread.get());
std::unique_ptr<JSCExecutor> worker;
workerMQT->runOnQueueSync([this, &worker, &script, &globalObj, workerId] () {
worker.reset(new JSCExecutor(m_bridge, workerId, this, script, globalObj.toJSONMap()));
worker.reset(new JSCExecutor(m_bridge, workerId, this, script, globalObj.toJSONMap(), m_jscConfig));
});
Object workerObj = Value(m_context, workerRef).asObject();

View File

@ -5,6 +5,7 @@
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <folly/json.h>
#include <JavaScriptCore/JSContextRef.h>
#include "Executor.h"
@ -18,10 +19,13 @@ class MessageQueueThread;
class JSCExecutorFactory : public JSExecutorFactory {
public:
JSCExecutorFactory(const std::string& cacheDir) : cacheDir_(cacheDir) {}
JSCExecutorFactory(const std::string& cacheDir, const folly::dynamic& jscConfig) :
cacheDir_(cacheDir),
m_jscConfig(jscConfig) {}
virtual std::unique_ptr<JSExecutor> createJSExecutor(Bridge *bridge) override;
private:
std::string cacheDir_;
folly::dynamic m_jscConfig;
};
class JSCExecutor;
@ -45,7 +49,7 @@ public:
/**
* Must be invoked from thread this Executor will run on.
*/
explicit JSCExecutor(Bridge *bridge, const std::string& cacheDir);
explicit JSCExecutor(Bridge *bridge, const std::string& cacheDir, const folly::dynamic& jscConfig);
~JSCExecutor() override;
virtual void loadApplicationScript(
@ -84,6 +88,7 @@ private:
std::string m_deviceCacheDir;
std::shared_ptr<MessageQueueThread> m_messageQueueThread;
std::unique_ptr<JSModulesUnbundle> m_unbundle;
folly::dynamic m_jscConfig;
/**
* WebWorker constructor. Must be invoked from thread this Executor will run on.
@ -93,7 +98,8 @@ private:
int workerId,
JSCExecutor *owner,
const std::string& script,
const std::unordered_map<std::string, std::string>& globalObjAsJSON);
const std::unordered_map<std::string, std::string>& globalObjAsJSON,
const folly::dynamic& jscConfig);
void initOnJSVMThread();
void terminateOnJSVMThread();

View File

@ -819,13 +819,21 @@ std::string getDeviceCacheDir() {
}
struct CountableJSCExecutorFactory : CountableJSExecutorFactory {
public:
CountableJSCExecutorFactory(folly::dynamic jscConfig) : m_jscConfig(jscConfig) {}
virtual std::unique_ptr<JSExecutor> createJSExecutor(Bridge *bridge) override {
return JSCExecutorFactory(getDeviceCacheDir()).createJSExecutor(bridge);
return JSCExecutorFactory(getDeviceCacheDir(), m_jscConfig).createJSExecutor(bridge);
}
private:
folly::dynamic m_jscConfig;
};
static void createJSCExecutor(JNIEnv *env, jobject obj) {
auto executor = createNew<CountableJSCExecutorFactory>();
static void createJSCExecutor(JNIEnv *env, jobject obj, jobject jscConfig) {
auto nativeMap = extractRefPtr<NativeMap>(env, jscConfig);
exceptions::throwIfObjectAlreadyConsumed(nativeMap, "Map to push already consumed");
auto executor = createNew<CountableJSCExecutorFactory>(std::move(nativeMap->map));
nativeMap->isConsumed = true;
setCountableForJava(env, obj, std::move(executor));
}
@ -920,7 +928,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
});
registerNatives("com/facebook/react/bridge/JSCJavaScriptExecutor", {
makeNativeMethod("initialize", executors::createJSCExecutor),
makeNativeMethod("initialize", "(Lcom/facebook/react/bridge/WritableNativeMap;)V",
executors::createJSCExecutor),
});
registerNatives("com/facebook/react/bridge/ProxyJavaScriptExecutor", {