mirror of
https://github.com/status-im/react-native.git
synced 2025-02-03 13:14:42 +00:00
Drop support for webworkers
Reviewed By: AaaChiuuu Differential Revision: D4916449 fbshipit-source-id: a447233d3b7cfee98db2ce00f1c0505d513e2429
This commit is contained in:
parent
a20882f62e
commit
34bc6bd2ae
@ -121,10 +121,6 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
}
|
||||
void incrementPendingJSCalls() override {}
|
||||
void decrementPendingJSCalls() override {}
|
||||
ExecutorToken createExecutorToken() override {
|
||||
return ExecutorToken(std::make_shared<PlatformExecutorToken>());
|
||||
}
|
||||
void onExecutorStopped(ExecutorToken) override {}
|
||||
};
|
||||
|
||||
@implementation RCTCxxBridge
|
||||
@ -289,7 +285,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
[self.delegate respondsToSelector:@selector(shouldBridgeUseCustomJSC:)] &&
|
||||
[self.delegate shouldBridgeUseCustomJSC:self];
|
||||
// The arg is a cache dir. It's not used with standard JSC.
|
||||
executorFactory.reset(new JSCExecutorFactory("", folly::dynamic::object
|
||||
executorFactory.reset(new JSCExecutorFactory(folly::dynamic::object
|
||||
("UseCustomJSC", (bool)useCustomJSC)
|
||||
#if RCT_PROFILE
|
||||
("StartSamplingProfilerOnInit", (bool)self.devSettings.startSamplingProfilerOnLaunch)
|
||||
@ -1000,8 +996,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
RCTProfileEndFlowEvent();
|
||||
|
||||
if (self->_reactInstance) {
|
||||
self->_reactInstance->callJSFunction(self->_reactInstance->getMainExecutorToken(),
|
||||
[module UTF8String], [method UTF8String],
|
||||
self->_reactInstance->callJSFunction([module UTF8String], [method UTF8String],
|
||||
[RCTConvert folly_dynamic:args ?: @[]]);
|
||||
|
||||
if (completion) {
|
||||
@ -1033,7 +1028,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
|
||||
if (self->_reactInstance)
|
||||
self->_reactInstance->callJSCallback(
|
||||
self->_reactInstance->getMainExecutorToken(), [cbID unsignedLongLongValue],
|
||||
[cbID unsignedLongLongValue],
|
||||
[RCTConvert folly_dynamic:args ?: @[]]);
|
||||
}];
|
||||
}
|
||||
@ -1046,8 +1041,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
RCTAssertJSThread();
|
||||
|
||||
if (_reactInstance)
|
||||
_reactInstance->callJSFunction(_reactInstance->getMainExecutorToken(),
|
||||
"JSTimersExecution", "callTimers",
|
||||
_reactInstance->callJSFunction("JSTimersExecution", "callTimers",
|
||||
folly::dynamic::array(folly::dynamic::array([timer doubleValue])));
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,8 @@ class RCTNativeModule : public NativeModule {
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
folly::dynamic getConstants() override;
|
||||
bool supportsWebWorkers() override;
|
||||
void invoke(ExecutorToken token, unsigned int methodId, folly::dynamic &¶ms) override;
|
||||
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId,
|
||||
folly::dynamic &¶ms) override;
|
||||
void invoke(unsigned int methodId, folly::dynamic &¶ms) override;
|
||||
MethodCallResult callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic &¶ms) override;
|
||||
|
||||
private:
|
||||
__weak RCTBridge *m_bridge;
|
||||
|
@ -50,11 +50,7 @@ folly::dynamic RCTNativeModule::getConstants() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool RCTNativeModule::supportsWebWorkers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RCTNativeModule::invoke(ExecutorToken token, unsigned int methodId, folly::dynamic &¶ms) {
|
||||
void RCTNativeModule::invoke(unsigned int methodId, folly::dynamic &¶ms) {
|
||||
// The BatchedBridge version of this buckets all the callbacks by thread, and
|
||||
// queues one block on each. This is much simpler; we'll see how it goes and
|
||||
// iterate.
|
||||
@ -103,8 +99,7 @@ void RCTNativeModule::invoke(ExecutorToken token, unsigned int methodId, folly::
|
||||
}
|
||||
}
|
||||
|
||||
MethodCallResult RCTNativeModule::callSerializableNativeHook(
|
||||
ExecutorToken token, unsigned int reactMethodId, folly::dynamic &¶ms) {
|
||||
MethodCallResult RCTNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic &¶ms) {
|
||||
RCTFatal(RCTErrorWithMessage(@"callSerializableNativeHook is not yet supported on iOS"));
|
||||
return folly::none;
|
||||
}
|
||||
|
@ -168,7 +168,6 @@
|
||||
13F887771E29726200C3C7A1 /* JSCPerfStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BC1E03699D0018521A /* JSCPerfStats.cpp */; };
|
||||
13F887781E29726200C3C7A1 /* JSCSamplingProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BE1E03699D0018521A /* JSCSamplingProfiler.cpp */; };
|
||||
13F887791E29726200C3C7A1 /* JSCUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C21E03699D0018521A /* JSCUtils.cpp */; };
|
||||
13F8877A1E29726200C3C7A1 /* JSCWebWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C41E03699D0018521A /* JSCWebWorker.cpp */; };
|
||||
13F8877B1E29726200C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C61E03699D0018521A /* JSIndexedRAMBundle.cpp */; };
|
||||
13F8877C1E29726200C3C7A1 /* MethodCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0CA1E03699D0018521A /* MethodCall.cpp */; };
|
||||
13F8877D1E29726200C3C7A1 /* ModuleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0CC1E03699D0018521A /* ModuleRegistry.cpp */; };
|
||||
@ -185,7 +184,6 @@
|
||||
13F8878A1E29726300C3C7A1 /* JSCPerfStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BC1E03699D0018521A /* JSCPerfStats.cpp */; };
|
||||
13F8878B1E29726300C3C7A1 /* JSCSamplingProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BE1E03699D0018521A /* JSCSamplingProfiler.cpp */; };
|
||||
13F8878C1E29726300C3C7A1 /* JSCUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C21E03699D0018521A /* JSCUtils.cpp */; };
|
||||
13F8878D1E29726300C3C7A1 /* JSCWebWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C41E03699D0018521A /* JSCWebWorker.cpp */; };
|
||||
13F8878E1E29726300C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0C61E03699D0018521A /* JSIndexedRAMBundle.cpp */; };
|
||||
13F8878F1E29726300C3C7A1 /* MethodCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0CA1E03699D0018521A /* MethodCall.cpp */; };
|
||||
13F887901E29726300C3C7A1 /* ModuleRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0CC1E03699D0018521A /* ModuleRegistry.cpp */; };
|
||||
@ -226,8 +224,6 @@
|
||||
27595AA41E575C7800CCE2B1 /* CxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A71E03699D0018521A /* CxxModule.h */; };
|
||||
27595AA51E575C7800CCE2B1 /* CxxNativeModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A91E03699D0018521A /* CxxNativeModule.h */; };
|
||||
27595AA61E575C7800CCE2B1 /* Executor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AB1E03699D0018521A /* Executor.h */; };
|
||||
27595AA71E575C7800CCE2B1 /* ExecutorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AC1E03699D0018521A /* ExecutorToken.h */; };
|
||||
27595AA81E575C7800CCE2B1 /* ExecutorTokenFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */; };
|
||||
27595AA91E575C7800CCE2B1 /* Instance.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AF1E03699D0018521A /* Instance.h */; };
|
||||
27595AAA1E575C7800CCE2B1 /* JsArgumentHelpers-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
27595AAB1E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
@ -239,7 +235,6 @@
|
||||
27595AB11E575C7800CCE2B1 /* JSCPerfStats.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BD1E03699D0018521A /* JSCPerfStats.h */; };
|
||||
27595AB21E575C7800CCE2B1 /* JSCSamplingProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */; };
|
||||
27595AB31E575C7800CCE2B1 /* JSCUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C31E03699D0018521A /* JSCUtils.h */; };
|
||||
27595AB41E575C7800CCE2B1 /* JSCWebWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C51E03699D0018521A /* JSCWebWorker.h */; };
|
||||
27595AB51E575C7800CCE2B1 /* JSIndexedRAMBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */; };
|
||||
27595AB61E575C7800CCE2B1 /* MessageQueueThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C91E03699D0018521A /* MessageQueueThread.h */; };
|
||||
27595AB71E575C7800CCE2B1 /* MethodCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0CB1E03699D0018521A /* MethodCall.h */; };
|
||||
@ -252,8 +247,6 @@
|
||||
27595ABF1E575C7800CCE2B1 /* CxxModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A71E03699D0018521A /* CxxModule.h */; };
|
||||
27595AC01E575C7800CCE2B1 /* CxxNativeModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A91E03699D0018521A /* CxxNativeModule.h */; };
|
||||
27595AC11E575C7800CCE2B1 /* Executor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AB1E03699D0018521A /* Executor.h */; };
|
||||
27595AC21E575C7800CCE2B1 /* ExecutorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AC1E03699D0018521A /* ExecutorToken.h */; };
|
||||
27595AC31E575C7800CCE2B1 /* ExecutorTokenFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */; };
|
||||
27595AC41E575C7800CCE2B1 /* Instance.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AF1E03699D0018521A /* Instance.h */; };
|
||||
27595AC51E575C7800CCE2B1 /* JsArgumentHelpers-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
27595AC61E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
@ -265,7 +258,6 @@
|
||||
27595ACC1E575C7800CCE2B1 /* JSCPerfStats.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BD1E03699D0018521A /* JSCPerfStats.h */; };
|
||||
27595ACD1E575C7800CCE2B1 /* JSCSamplingProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */; };
|
||||
27595ACE1E575C7800CCE2B1 /* JSCUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C31E03699D0018521A /* JSCUtils.h */; };
|
||||
27595ACF1E575C7800CCE2B1 /* JSCWebWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C51E03699D0018521A /* JSCWebWorker.h */; };
|
||||
27595AD01E575C7800CCE2B1 /* JSIndexedRAMBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */; };
|
||||
27595AD11E575C7800CCE2B1 /* MessageQueueThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C91E03699D0018521A /* MessageQueueThread.h */; };
|
||||
27595AD21E575C7800CCE2B1 /* MethodCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0CB1E03699D0018521A /* MethodCall.h */; };
|
||||
@ -756,8 +748,6 @@
|
||||
3DA981A01E5B0E34004F2374 /* CxxModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A71E03699D0018521A /* CxxModule.h */; };
|
||||
3DA981A11E5B0E34004F2374 /* CxxNativeModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A91E03699D0018521A /* CxxNativeModule.h */; };
|
||||
3DA981A21E5B0E34004F2374 /* Executor.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AB1E03699D0018521A /* Executor.h */; };
|
||||
3DA981A31E5B0E34004F2374 /* ExecutorToken.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AC1E03699D0018521A /* ExecutorToken.h */; };
|
||||
3DA981A41E5B0E34004F2374 /* ExecutorTokenFactory.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */; };
|
||||
3DA981A51E5B0E34004F2374 /* Instance.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AF1E03699D0018521A /* Instance.h */; };
|
||||
3DA981A61E5B0E34004F2374 /* JsArgumentHelpers-inl.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
3DA981A71E5B0E34004F2374 /* JsArgumentHelpers.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
@ -771,7 +761,6 @@
|
||||
3DA981AF1E5B0E34004F2374 /* JSCPerfStats.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BD1E03699D0018521A /* JSCPerfStats.h */; };
|
||||
3DA981B01E5B0E34004F2374 /* JSCSamplingProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */; };
|
||||
3DA981B11E5B0E34004F2374 /* JSCUtils.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C31E03699D0018521A /* JSCUtils.h */; };
|
||||
3DA981B21E5B0E34004F2374 /* JSCWebWorker.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C51E03699D0018521A /* JSCWebWorker.h */; };
|
||||
3DA981B31E5B0E34004F2374 /* JSIndexedRAMBundle.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */; };
|
||||
3DA981B41E5B0E34004F2374 /* JSModulesUnbundle.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C81E03699D0018521A /* JSModulesUnbundle.h */; };
|
||||
3DA981B51E5B0E34004F2374 /* MessageQueueThread.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C91E03699D0018521A /* MessageQueueThread.h */; };
|
||||
@ -899,8 +888,6 @@
|
||||
3DA9823B1E5B1053004F2374 /* CxxModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A71E03699D0018521A /* CxxModule.h */; };
|
||||
3DA9823C1E5B1053004F2374 /* CxxNativeModule.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0A91E03699D0018521A /* CxxNativeModule.h */; };
|
||||
3DA9823D1E5B1053004F2374 /* Executor.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AB1E03699D0018521A /* Executor.h */; };
|
||||
3DA9823E1E5B1053004F2374 /* ExecutorToken.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AC1E03699D0018521A /* ExecutorToken.h */; };
|
||||
3DA9823F1E5B1053004F2374 /* ExecutorTokenFactory.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */; };
|
||||
3DA982401E5B1053004F2374 /* Instance.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0AF1E03699D0018521A /* Instance.h */; };
|
||||
3DA982411E5B1053004F2374 /* JsArgumentHelpers-inl.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
3DA982421E5B1053004F2374 /* JsArgumentHelpers.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
@ -914,7 +901,6 @@
|
||||
3DA9824A1E5B1053004F2374 /* JSCPerfStats.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BD1E03699D0018521A /* JSCPerfStats.h */; };
|
||||
3DA9824B1E5B1053004F2374 /* JSCSamplingProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */; };
|
||||
3DA9824C1E5B1053004F2374 /* JSCUtils.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C31E03699D0018521A /* JSCUtils.h */; };
|
||||
3DA9824D1E5B1053004F2374 /* JSCWebWorker.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C51E03699D0018521A /* JSCWebWorker.h */; };
|
||||
3DA9824E1E5B1053004F2374 /* JSIndexedRAMBundle.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */; };
|
||||
3DA9824F1E5B1053004F2374 /* JSModulesUnbundle.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C81E03699D0018521A /* JSModulesUnbundle.h */; };
|
||||
3DA982501E5B1053004F2374 /* MessageQueueThread.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0C91E03699D0018521A /* MessageQueueThread.h */; };
|
||||
@ -1234,8 +1220,6 @@
|
||||
3DA9823B1E5B1053004F2374 /* CxxModule.h in Copy Headers */,
|
||||
3DA9823C1E5B1053004F2374 /* CxxNativeModule.h in Copy Headers */,
|
||||
3DA9823D1E5B1053004F2374 /* Executor.h in Copy Headers */,
|
||||
3DA9823E1E5B1053004F2374 /* ExecutorToken.h in Copy Headers */,
|
||||
3DA9823F1E5B1053004F2374 /* ExecutorTokenFactory.h in Copy Headers */,
|
||||
3DA982401E5B1053004F2374 /* Instance.h in Copy Headers */,
|
||||
3DA982411E5B1053004F2374 /* JsArgumentHelpers-inl.h in Copy Headers */,
|
||||
3DA982421E5B1053004F2374 /* JsArgumentHelpers.h in Copy Headers */,
|
||||
@ -1249,7 +1233,6 @@
|
||||
3DA9824A1E5B1053004F2374 /* JSCPerfStats.h in Copy Headers */,
|
||||
3DA9824B1E5B1053004F2374 /* JSCSamplingProfiler.h in Copy Headers */,
|
||||
3DA9824C1E5B1053004F2374 /* JSCUtils.h in Copy Headers */,
|
||||
3DA9824D1E5B1053004F2374 /* JSCWebWorker.h in Copy Headers */,
|
||||
3DA9824E1E5B1053004F2374 /* JSIndexedRAMBundle.h in Copy Headers */,
|
||||
3DA9824F1E5B1053004F2374 /* JSModulesUnbundle.h in Copy Headers */,
|
||||
3DA982501E5B1053004F2374 /* MessageQueueThread.h in Copy Headers */,
|
||||
@ -1431,8 +1414,6 @@
|
||||
3DA981A01E5B0E34004F2374 /* CxxModule.h in Copy Headers */,
|
||||
3DA981A11E5B0E34004F2374 /* CxxNativeModule.h in Copy Headers */,
|
||||
3DA981A21E5B0E34004F2374 /* Executor.h in Copy Headers */,
|
||||
3DA981A31E5B0E34004F2374 /* ExecutorToken.h in Copy Headers */,
|
||||
3DA981A41E5B0E34004F2374 /* ExecutorTokenFactory.h in Copy Headers */,
|
||||
3DA981A51E5B0E34004F2374 /* Instance.h in Copy Headers */,
|
||||
3DA981A61E5B0E34004F2374 /* JsArgumentHelpers-inl.h in Copy Headers */,
|
||||
3DA981A71E5B0E34004F2374 /* JsArgumentHelpers.h in Copy Headers */,
|
||||
@ -1446,7 +1427,6 @@
|
||||
3DA981AF1E5B0E34004F2374 /* JSCPerfStats.h in Copy Headers */,
|
||||
3DA981B01E5B0E34004F2374 /* JSCSamplingProfiler.h in Copy Headers */,
|
||||
3DA981B11E5B0E34004F2374 /* JSCUtils.h in Copy Headers */,
|
||||
3DA981B21E5B0E34004F2374 /* JSCWebWorker.h in Copy Headers */,
|
||||
3DA981B31E5B0E34004F2374 /* JSIndexedRAMBundle.h in Copy Headers */,
|
||||
3DA981B41E5B0E34004F2374 /* JSModulesUnbundle.h in Copy Headers */,
|
||||
3DA981B51E5B0E34004F2374 /* MessageQueueThread.h in Copy Headers */,
|
||||
@ -1761,8 +1741,6 @@
|
||||
3D92B0A81E03699D0018521A /* CxxNativeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CxxNativeModule.cpp; sourceTree = "<group>"; };
|
||||
3D92B0A91E03699D0018521A /* CxxNativeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CxxNativeModule.h; sourceTree = "<group>"; };
|
||||
3D92B0AB1E03699D0018521A /* Executor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Executor.h; sourceTree = "<group>"; };
|
||||
3D92B0AC1E03699D0018521A /* ExecutorToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutorToken.h; sourceTree = "<group>"; };
|
||||
3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutorTokenFactory.h; sourceTree = "<group>"; };
|
||||
3D92B0AE1E03699D0018521A /* Instance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Instance.cpp; sourceTree = "<group>"; };
|
||||
3D92B0AF1E03699D0018521A /* Instance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Instance.h; sourceTree = "<group>"; };
|
||||
3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JsArgumentHelpers-inl.h"; sourceTree = "<group>"; };
|
||||
@ -1783,8 +1761,6 @@
|
||||
3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCSamplingProfiler.h; sourceTree = "<group>"; };
|
||||
3D92B0C21E03699D0018521A /* JSCUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCUtils.cpp; sourceTree = "<group>"; };
|
||||
3D92B0C31E03699D0018521A /* JSCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCUtils.h; sourceTree = "<group>"; };
|
||||
3D92B0C41E03699D0018521A /* JSCWebWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCWebWorker.cpp; sourceTree = "<group>"; };
|
||||
3D92B0C51E03699D0018521A /* JSCWebWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCWebWorker.h; sourceTree = "<group>"; };
|
||||
3D92B0C61E03699D0018521A /* JSIndexedRAMBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIndexedRAMBundle.cpp; sourceTree = "<group>"; };
|
||||
3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIndexedRAMBundle.h; sourceTree = "<group>"; };
|
||||
3D92B0C81E03699D0018521A /* JSModulesUnbundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModulesUnbundle.h; sourceTree = "<group>"; };
|
||||
@ -2474,8 +2450,6 @@
|
||||
3D92B0A81E03699D0018521A /* CxxNativeModule.cpp */,
|
||||
3D92B0A91E03699D0018521A /* CxxNativeModule.h */,
|
||||
3D92B0AB1E03699D0018521A /* Executor.h */,
|
||||
3D92B0AC1E03699D0018521A /* ExecutorToken.h */,
|
||||
3D92B0AD1E03699D0018521A /* ExecutorTokenFactory.h */,
|
||||
3D92B0AE1E03699D0018521A /* Instance.cpp */,
|
||||
3D92B0AF1E03699D0018521A /* Instance.h */,
|
||||
3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */,
|
||||
@ -2500,8 +2474,6 @@
|
||||
3D92B0BF1E03699D0018521A /* JSCSamplingProfiler.h */,
|
||||
3D92B0C21E03699D0018521A /* JSCUtils.cpp */,
|
||||
3D92B0C31E03699D0018521A /* JSCUtils.h */,
|
||||
3D92B0C41E03699D0018521A /* JSCWebWorker.cpp */,
|
||||
3D92B0C51E03699D0018521A /* JSCWebWorker.h */,
|
||||
3D92B0C61E03699D0018521A /* JSIndexedRAMBundle.cpp */,
|
||||
3D92B0C71E03699D0018521A /* JSIndexedRAMBundle.h */,
|
||||
3D92B0C81E03699D0018521A /* JSModulesUnbundle.h */,
|
||||
@ -2726,11 +2698,8 @@
|
||||
27595AC01E575C7800CCE2B1 /* CxxNativeModule.h in Headers */,
|
||||
27595AD01E575C7800CCE2B1 /* JSIndexedRAMBundle.h in Headers */,
|
||||
27595AD31E575C7800CCE2B1 /* ModuleRegistry.h in Headers */,
|
||||
27595ACF1E575C7800CCE2B1 /* JSCWebWorker.h in Headers */,
|
||||
27595ACC1E575C7800CCE2B1 /* JSCPerfStats.h in Headers */,
|
||||
27595AC31E575C7800CCE2B1 /* ExecutorTokenFactory.h in Headers */,
|
||||
27595AC11E575C7800CCE2B1 /* Executor.h in Headers */,
|
||||
27595AC21E575C7800CCE2B1 /* ExecutorToken.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -2801,11 +2770,8 @@
|
||||
27595AA51E575C7800CCE2B1 /* CxxNativeModule.h in Headers */,
|
||||
27595AB51E575C7800CCE2B1 /* JSIndexedRAMBundle.h in Headers */,
|
||||
27595AB81E575C7800CCE2B1 /* ModuleRegistry.h in Headers */,
|
||||
27595AB41E575C7800CCE2B1 /* JSCWebWorker.h in Headers */,
|
||||
27595AB11E575C7800CCE2B1 /* JSCPerfStats.h in Headers */,
|
||||
27595AA81E575C7800CCE2B1 /* ExecutorTokenFactory.h in Headers */,
|
||||
27595AA61E575C7800CCE2B1 /* Executor.h in Headers */,
|
||||
27595AA71E575C7800CCE2B1 /* ExecutorToken.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -3478,7 +3444,6 @@
|
||||
13F8877B1E29726200C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */,
|
||||
13F8877D1E29726200C3C7A1 /* ModuleRegistry.cpp in Sources */,
|
||||
13F8876E1E29726200C3C7A1 /* CxxNativeModule.cpp in Sources */,
|
||||
13F8877A1E29726200C3C7A1 /* JSCWebWorker.cpp in Sources */,
|
||||
13F887721E29726200C3C7A1 /* JSCExecutor.cpp in Sources */,
|
||||
13F887741E29726200C3C7A1 /* JSCLegacyTracing.cpp in Sources */,
|
||||
13F887771E29726200C3C7A1 /* JSCPerfStats.cpp in Sources */,
|
||||
@ -3503,7 +3468,6 @@
|
||||
3DC159E61E83E1FA007B1282 /* JSBigString.cpp in Sources */,
|
||||
13F8878E1E29726300C3C7A1 /* JSIndexedRAMBundle.cpp in Sources */,
|
||||
13F887901E29726300C3C7A1 /* ModuleRegistry.cpp in Sources */,
|
||||
13F8878D1E29726300C3C7A1 /* JSCWebWorker.cpp in Sources */,
|
||||
13F887851E29726300C3C7A1 /* JSCExecutor.cpp in Sources */,
|
||||
13F887871E29726300C3C7A1 /* JSCLegacyTracing.cpp in Sources */,
|
||||
13F8878A1E29726300C3C7A1 /* JSCPerfStats.cpp in Sources */,
|
||||
|
@ -28,7 +28,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.SoftAssertions;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.ApplicationHolder;
|
||||
import com.facebook.react.common.futures.SimpleSettableFuture;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.modules.core.Timing;
|
||||
@ -178,7 +177,6 @@ public abstract class ReactIntegrationTestCase extends AndroidTestCase {
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SoLoader.init(getContext(), /* native exopackage */ false);
|
||||
ApplicationHolder.setApplication((Application) getContext().getApplicationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,7 +42,6 @@ import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
||||
import com.facebook.react.common.ApplicationHolder;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
@ -229,8 +228,6 @@ public class ReactInstanceManager {
|
||||
|
||||
initializeSoLoaderIfNecessary(applicationContext);
|
||||
|
||||
// TODO(9577825): remove this
|
||||
ApplicationHolder.setApplication((Application) applicationContext.getApplicationContext());
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
|
||||
|
||||
mApplicationContext = applicationContext;
|
||||
|
@ -66,11 +66,6 @@ public abstract class BaseJavaModule implements NativeModule {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsWebWorkers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasConstants() {
|
||||
return false;
|
||||
}
|
||||
|
@ -15,13 +15,11 @@ package com.facebook.react.bridge;
|
||||
public final class CallbackImpl implements Callback {
|
||||
|
||||
private final JSInstance mJSInstance;
|
||||
private final ExecutorToken mExecutorToken;
|
||||
private final int mCallbackId;
|
||||
private boolean mInvoked;
|
||||
|
||||
public CallbackImpl(JSInstance jsInstance, ExecutorToken executorToken, int callbackId) {
|
||||
public CallbackImpl(JSInstance jsInstance, int callbackId) {
|
||||
mJSInstance = jsInstance;
|
||||
mExecutorToken = executorToken;
|
||||
mCallbackId = callbackId;
|
||||
mInvoked = false;
|
||||
}
|
||||
@ -33,7 +31,7 @@ public final class CallbackImpl implements Callback {
|
||||
"module. This callback type only permits a single invocation from "+
|
||||
"native code.");
|
||||
}
|
||||
mJSInstance.invokeCallback(mExecutorToken, mCallbackId, Arguments.fromJavaArgs(args));
|
||||
mJSInstance.invokeCallback(mCallbackId, Arguments.fromJavaArgs(args));
|
||||
mInvoked = true;
|
||||
}
|
||||
}
|
||||
|
@ -37,12 +37,10 @@ public interface CatalystInstance
|
||||
// which this prevents.
|
||||
@Override @DoNotStrip
|
||||
void invokeCallback(
|
||||
ExecutorToken executorToken,
|
||||
int callbackID,
|
||||
NativeArray arguments);
|
||||
@DoNotStrip
|
||||
void callFunction(
|
||||
ExecutorToken executorToken,
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments);
|
||||
@ -63,7 +61,6 @@ public interface CatalystInstance
|
||||
ReactQueueConfiguration getReactQueueConfiguration();
|
||||
|
||||
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
|
||||
<T extends JavaScriptModule> T getJSModule(ExecutorToken executorToken, Class<T> jsInterface);
|
||||
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
|
||||
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
|
||||
Collection<NativeModule> getNativeModules();
|
||||
|
@ -1,24 +0,0 @@
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/**
|
||||
* Class corresponding to a JS VM that can call into native modules. In Java, this should
|
||||
* just be treated as a black box to be used to help the framework route native->JS calls back to
|
||||
* the proper JS VM. See {@link ReactContext#getJSModule(ExecutorToken, Class)} and
|
||||
* {@link BaseJavaModule#supportsWebWorkers()}.
|
||||
*
|
||||
* Note: If your application doesn't use web workers, it will only have a single ExecutorToken
|
||||
* per instance of React Native.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class ExecutorToken {
|
||||
|
||||
private final HybridData mHybridData;
|
||||
|
||||
@DoNotStrip
|
||||
private ExecutorToken(HybridData hybridData) {
|
||||
mHybridData = hybridData;
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ package com.facebook.react.bridge;
|
||||
*/
|
||||
public interface JSInstance {
|
||||
void invokeCallback(
|
||||
ExecutorToken executorToken,
|
||||
int callbackID,
|
||||
NativeArray arguments);
|
||||
// TODO if this interface survives refactoring, think about adding
|
||||
|
@ -31,11 +31,11 @@ import com.facebook.react.common.ReactConstants;
|
||||
* JavaScript.
|
||||
*/
|
||||
public class JavaScriptModuleRegistry {
|
||||
private final WeakHashMap<ExecutorToken, HashMap<Class<? extends JavaScriptModule>, JavaScriptModule>> mModuleInstances;
|
||||
private final HashMap<Class<? extends JavaScriptModule>, JavaScriptModule> mModuleInstances;
|
||||
private final HashMap<Class<? extends JavaScriptModule>, JavaScriptModuleRegistration> mModuleRegistrations;
|
||||
|
||||
public JavaScriptModuleRegistry(List<JavaScriptModuleRegistration> config) {
|
||||
mModuleInstances = new WeakHashMap<>();
|
||||
mModuleInstances = new HashMap<>();
|
||||
mModuleRegistrations = new HashMap<>();
|
||||
for (JavaScriptModuleRegistration registration : config) {
|
||||
mModuleRegistrations.put(registration.getModuleInterface(), registration);
|
||||
@ -43,17 +43,9 @@ public class JavaScriptModuleRegistry {
|
||||
}
|
||||
|
||||
public synchronized <T extends JavaScriptModule> T getJavaScriptModule(
|
||||
CatalystInstance instance,
|
||||
ExecutorToken executorToken,
|
||||
Class<T> moduleInterface) {
|
||||
HashMap<Class<? extends JavaScriptModule>, JavaScriptModule> instancesForContext =
|
||||
mModuleInstances.get(executorToken);
|
||||
if (instancesForContext == null) {
|
||||
instancesForContext = new HashMap<>();
|
||||
mModuleInstances.put(executorToken, instancesForContext);
|
||||
}
|
||||
|
||||
JavaScriptModule module = instancesForContext.get(moduleInterface);
|
||||
CatalystInstance instance,
|
||||
Class<T> moduleInterface) {
|
||||
JavaScriptModule module = mModuleInstances.get(moduleInterface);
|
||||
if (module != null) {
|
||||
return (T) module;
|
||||
}
|
||||
@ -65,8 +57,8 @@ public class JavaScriptModuleRegistry {
|
||||
JavaScriptModule interfaceProxy = (JavaScriptModule) Proxy.newProxyInstance(
|
||||
moduleInterface.getClassLoader(),
|
||||
new Class[]{moduleInterface},
|
||||
new JavaScriptModuleInvocationHandler(executorToken, instance, registration));
|
||||
instancesForContext.put(moduleInterface, interfaceProxy);
|
||||
new JavaScriptModuleInvocationHandler(instance, registration));
|
||||
mModuleInstances.put(moduleInterface, interfaceProxy);
|
||||
return (T) interfaceProxy;
|
||||
}
|
||||
|
||||
@ -85,30 +77,20 @@ public class JavaScriptModuleRegistry {
|
||||
}
|
||||
|
||||
private static class JavaScriptModuleInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final WeakReference<ExecutorToken> mExecutorToken;
|
||||
private final CatalystInstance mCatalystInstance;
|
||||
private final JavaScriptModuleRegistration mModuleRegistration;
|
||||
|
||||
public JavaScriptModuleInvocationHandler(
|
||||
ExecutorToken executorToken,
|
||||
CatalystInstance catalystInstance,
|
||||
JavaScriptModuleRegistration moduleRegistration) {
|
||||
mExecutorToken = new WeakReference<>(executorToken);
|
||||
mCatalystInstance = catalystInstance;
|
||||
mModuleRegistration = moduleRegistration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
|
||||
ExecutorToken executorToken = mExecutorToken.get();
|
||||
if (executorToken == null) {
|
||||
FLog.w(ReactConstants.TAG, "Dropping JS call, ExecutorToken went away...");
|
||||
return null;
|
||||
}
|
||||
NativeArray jsArgs = args != null ? Arguments.fromJavaArgs(args) : new WritableNativeArray();
|
||||
mCatalystInstance.callFunction(
|
||||
executorToken,
|
||||
mModuleRegistration.getName(),
|
||||
method.getName(),
|
||||
jsArgs
|
||||
|
@ -9,10 +9,7 @@
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A native module whose API can be provided to JS catalyst instances. {@link NativeModule}s whose
|
||||
@ -23,7 +20,7 @@ import java.util.Map;
|
||||
*/
|
||||
public interface NativeModule {
|
||||
interface NativeMethod {
|
||||
void invoke(JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray parameters);
|
||||
void invoke(JSInstance jsInstance, ReadableNativeArray parameters);
|
||||
String getType();
|
||||
}
|
||||
|
||||
@ -52,27 +49,4 @@ public interface NativeModule {
|
||||
* Called before {CatalystInstance#onHostDestroy}
|
||||
*/
|
||||
void onCatalystInstanceDestroy();
|
||||
|
||||
/**
|
||||
* In order to support web workers, a module must be aware that it can be invoked from multiple
|
||||
* different JS VMs. Supporting web workers means recognizing things like:
|
||||
*
|
||||
* 1) ids (e.g. timer ids, request ids, etc.) may only unique on a per-VM basis
|
||||
* 2) the module needs to make sure to enqueue callbacks and JS module calls to the correct VM
|
||||
*
|
||||
* In order to facilitate this, modules that support web workers will have all their @ReactMethod-
|
||||
* annotated methods passed a {@link ExecutorToken} as the first parameter before any arguments
|
||||
* from JS. This ExecutorToken internally maps to a specific JS VM and can be used by the
|
||||
* framework to route calls appropriately. In order to make JS module calls correctly, start using
|
||||
* the version of {@link ReactContext#getJSModule(ExecutorToken, Class)} that takes an
|
||||
* ExecutorToken. It will ensure that any calls you dispatch to the returned object will go to
|
||||
* the right VM. For Callbacks, you don't have to do anything special -- the framework
|
||||
* automatically tags them with the correct ExecutorToken when the are created.
|
||||
*
|
||||
* Note: even though calls can come from multiple JS VMs on multiple threads, calls to this module
|
||||
* will still only occur on a single thread.
|
||||
*
|
||||
* @return whether this module supports web workers.
|
||||
*/
|
||||
boolean supportsWebWorkers();
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
/**
|
||||
* Interface for a module that will be notified when JS executors have been unregistered from the bridge.
|
||||
* Note that this will NOT notify listeners about the main executor being destroyed: use
|
||||
* {@link NativeModule#onCatalystInstanceDestroy()} for that. Once a module has received a
|
||||
* {@link NativeModule#onCatalystInstanceDestroy()} call, it will not receive any onExecutorUnregistered
|
||||
* calls.
|
||||
*/
|
||||
public interface OnExecutorUnregisteredListener {
|
||||
|
||||
void onExecutorDestroyed(ExecutorToken executorToken);
|
||||
}
|
@ -107,15 +107,6 @@ public class ReactContext extends ContextWrapper {
|
||||
return mCatalystInstance.getJSModule(jsInterface);
|
||||
}
|
||||
|
||||
public <T extends JavaScriptModule> T getJSModule(
|
||||
ExecutorToken executorToken,
|
||||
Class<T> jsInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new RuntimeException(EARLY_JS_ACCESS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
return mCatalystInstance.getJSModule(executorToken, jsInterface);
|
||||
}
|
||||
|
||||
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new RuntimeException(
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Annotation indicating that a JS module should be made available to web
|
||||
* workers spawned by the main JS executor.
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
public @interface SupportsWebWorkers {
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.common;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/**
|
||||
* Holds the current Application Object.
|
||||
*
|
||||
* TODO(9577825): This is a bad pattern, we should thread through an Environment object instead.
|
||||
* Remove once bridge is unforked.
|
||||
*/
|
||||
@DoNotStrip
|
||||
@Deprecated
|
||||
public class ApplicationHolder {
|
||||
|
||||
private static Application sApplication;
|
||||
|
||||
public static void setApplication(Application application) {
|
||||
sApplication = application;
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public static Application getApplication() {
|
||||
return Assertions.assertNotNull(sApplication);
|
||||
}
|
||||
}
|
@ -24,7 +24,6 @@ import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.ExecutorToken;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.JavaScriptModuleRegistry;
|
||||
import com.facebook.react.bridge.MemoryPressure;
|
||||
@ -60,17 +59,14 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
|
||||
private static class PendingJSCall {
|
||||
|
||||
public ExecutorToken mExecutorToken;
|
||||
public String mModule;
|
||||
public String mMethod;
|
||||
public NativeArray mArguments;
|
||||
|
||||
public PendingJSCall(
|
||||
ExecutorToken executorToken,
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments) {
|
||||
mExecutorToken = executorToken;
|
||||
mModule = module;
|
||||
mMethod = method;
|
||||
mArguments = arguments;
|
||||
@ -89,7 +85,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
private final JSBundleLoader mJSBundleLoader;
|
||||
private final ArrayList<PendingJSCall> mJSCallsPendingInit = new ArrayList<PendingJSCall>();
|
||||
private final Object mJSCallsPendingInitLock = new Object();
|
||||
private ExecutorToken mMainExecutorToken;
|
||||
|
||||
private final NativeModuleRegistry mJavaRegistry;
|
||||
private final NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
|
||||
@ -134,7 +129,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
mJavaRegistry.getJavaModules(this),
|
||||
mJavaRegistry.getCxxModules());
|
||||
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
|
||||
mMainExecutorToken = getMainExecutorToken();
|
||||
}
|
||||
|
||||
private static class BridgeCallback implements ReactCallback {
|
||||
@ -224,7 +218,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
mAcceptCalls = true;
|
||||
|
||||
for (PendingJSCall call : mJSCallsPendingInit) {
|
||||
jniCallJSFunction(call.mExecutorToken, call.mModule, call.mMethod, call.mArguments);
|
||||
jniCallJSFunction(call.mModule, call.mMethod, call.mArguments);
|
||||
}
|
||||
mJSCallsPendingInit.clear();
|
||||
}
|
||||
@ -239,14 +233,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
}
|
||||
|
||||
private native void jniCallJSFunction(
|
||||
ExecutorToken token,
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments);
|
||||
|
||||
@Override
|
||||
public void callFunction(
|
||||
ExecutorToken executorToken,
|
||||
final String module,
|
||||
final String method,
|
||||
final NativeArray arguments) {
|
||||
@ -258,25 +250,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
// Most of the time the instance is initialized and we don't need to acquire the lock
|
||||
synchronized (mJSCallsPendingInitLock) {
|
||||
if (!mAcceptCalls) {
|
||||
mJSCallsPendingInit.add(new PendingJSCall(executorToken, module, method, arguments));
|
||||
mJSCallsPendingInit.add(new PendingJSCall(module, method, arguments));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jniCallJSFunction(executorToken, module, method, arguments);
|
||||
jniCallJSFunction(module, method, arguments);
|
||||
}
|
||||
|
||||
private native void jniCallJSCallback(ExecutorToken executorToken, int callbackID, NativeArray arguments);
|
||||
private native void jniCallJSCallback(int callbackID, NativeArray arguments);
|
||||
|
||||
@Override
|
||||
public void invokeCallback(ExecutorToken executorToken, final int callbackID, final NativeArray arguments) {
|
||||
public void invokeCallback(final int callbackID, final NativeArray arguments) {
|
||||
if (mDestroyed) {
|
||||
FLog.w(ReactConstants.TAG, "Invoking JS callback after bridge has been destroyed.");
|
||||
return;
|
||||
}
|
||||
|
||||
jniCallJSCallback(executorToken, callbackID, arguments);
|
||||
jniCallJSCallback(callbackID, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -348,17 +340,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
|
||||
@Override
|
||||
public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
|
||||
return getJSModule(mMainExecutorToken, jsInterface);
|
||||
return mJSModuleRegistry.getJavaScriptModule(this, jsInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends JavaScriptModule> T getJSModule(ExecutorToken executorToken, Class<T> jsInterface) {
|
||||
return Assertions.assertNotNull(mJSModuleRegistry)
|
||||
.getJavaScriptModule(this, executorToken, jsInterface);
|
||||
}
|
||||
|
||||
private native ExecutorToken getMainExecutorToken();
|
||||
|
||||
@Override
|
||||
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
||||
return mJavaRegistry.hasModule(nativeModuleInterface);
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
package com.facebook.react.cxxbridge;
|
||||
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
@ -37,11 +36,6 @@ public class CxxModuleWrapperBase implements NativeModule
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsWebWorkers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
mHybridData.resetNative();
|
||||
|
@ -14,11 +14,22 @@ import javax.annotation.Nullable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.facebook.react.bridge.*;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.cxxbridge.JavaModuleWrapper;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.react.bridge.BaseJavaModule;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.DynamicFromArray;
|
||||
import com.facebook.react.bridge.JSInstance;
|
||||
import com.facebook.react.bridge.NativeArgumentsParseException;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.PromiseImpl;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableNativeArray;
|
||||
import com.facebook.react.bridge.UnexpectedNativeTypeException;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
|
||||
import static com.facebook.infer.annotation.Assertions.assertNotNull;
|
||||
@ -32,14 +43,14 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
}
|
||||
|
||||
public abstract @Nullable T extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex);
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex);
|
||||
}
|
||||
|
||||
static final private ArgumentExtractor<Boolean> ARGUMENT_EXTRACTOR_BOOLEAN =
|
||||
new ArgumentExtractor<Boolean>() {
|
||||
@Override
|
||||
public Boolean extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return jsArguments.getBoolean(atIndex);
|
||||
}
|
||||
};
|
||||
@ -48,7 +59,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<Double>() {
|
||||
@Override
|
||||
public Double extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
@ -57,7 +68,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<Float>() {
|
||||
@Override
|
||||
public Float extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return (float) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
@ -66,7 +77,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<Integer>() {
|
||||
@Override
|
||||
public Integer extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return (int) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
@ -75,7 +86,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<String>() {
|
||||
@Override
|
||||
public String extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return jsArguments.getString(atIndex);
|
||||
}
|
||||
};
|
||||
@ -84,7 +95,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<ReadableNativeArray>() {
|
||||
@Override
|
||||
public ReadableNativeArray extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return jsArguments.getArray(atIndex);
|
||||
}
|
||||
};
|
||||
@ -93,7 +104,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<Dynamic>() {
|
||||
@Override
|
||||
public Dynamic extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return DynamicFromArray.create(jsArguments, atIndex);
|
||||
}
|
||||
};
|
||||
@ -102,7 +113,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<ReadableMap>() {
|
||||
@Override
|
||||
public ReadableMap extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
return jsArguments.getMap(atIndex);
|
||||
}
|
||||
};
|
||||
@ -111,12 +122,12 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
new ArgumentExtractor<Callback>() {
|
||||
@Override
|
||||
public @Nullable Callback extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
if (jsArguments.isNull(atIndex)) {
|
||||
return null;
|
||||
} else {
|
||||
int id = (int) jsArguments.getDouble(atIndex);
|
||||
return new com.facebook.react.bridge.CallbackImpl(jsInstance, executorToken, id);
|
||||
return new com.facebook.react.bridge.CallbackImpl(jsInstance, id);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -130,11 +141,11 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
|
||||
@Override
|
||||
public Promise extractArgument(
|
||||
JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray jsArguments, int atIndex) {
|
||||
JSInstance jsInstance, ReadableNativeArray jsArguments, int atIndex) {
|
||||
Callback resolve = ARGUMENT_EXTRACTOR_CALLBACK
|
||||
.extractArgument(jsInstance, executorToken, jsArguments, atIndex);
|
||||
.extractArgument(jsInstance, jsArguments, atIndex);
|
||||
Callback reject = ARGUMENT_EXTRACTOR_CALLBACK
|
||||
.extractArgument(jsInstance, executorToken, jsArguments, atIndex + 1);
|
||||
.extractArgument(jsInstance, jsArguments, atIndex + 1);
|
||||
return new PromiseImpl(resolve, reject);
|
||||
}
|
||||
};
|
||||
@ -144,9 +155,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
if (tryCommon != '\0') {
|
||||
return tryCommon;
|
||||
}
|
||||
if (paramClass == ExecutorToken.class) {
|
||||
return 'T';
|
||||
} else if (paramClass == Callback.class) {
|
||||
if (paramClass == Callback.class) {
|
||||
return 'X';
|
||||
} else if (paramClass == Promise.class) {
|
||||
return 'P';
|
||||
@ -269,50 +278,20 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
Class paramClass = paramTypes[i];
|
||||
if (paramClass == ExecutorToken.class) {
|
||||
if (!mModuleWrapper.supportsWebWorkers()) {
|
||||
throw new RuntimeException(
|
||||
"Module " + mModuleWrapper.getName() + " doesn't support web workers, but " +
|
||||
mMethod.getName() +
|
||||
" takes an ExecutorToken.");
|
||||
}
|
||||
} else if (paramClass == Promise.class) {
|
||||
if (paramClass == Promise.class) {
|
||||
Assertions.assertCondition(
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
}
|
||||
builder.append(paramTypeToChar(paramClass));
|
||||
}
|
||||
|
||||
// Modules that support web workers are expected to take an ExecutorToken as the first
|
||||
// parameter to all their @ReactMethod-annotated methods.
|
||||
if (mModuleWrapper.supportsWebWorkers()) {
|
||||
if (builder.charAt(2) != 'T') {
|
||||
throw new RuntimeException(
|
||||
"Module " + mModuleWrapper.getName() + " supports web workers, but " + mMethod.getName() +
|
||||
"does not take an ExecutorToken as its first parameter.");
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private ArgumentExtractor[] buildArgumentExtractors(Class[] paramTypes) {
|
||||
// Modules that support web workers are expected to take an ExecutorToken as the first
|
||||
// parameter to all their @ReactMethod-annotated methods. We compensate for that here.
|
||||
int executorTokenOffset = 0;
|
||||
if (mModuleWrapper.supportsWebWorkers()) {
|
||||
if (paramTypes[0] != ExecutorToken.class) {
|
||||
throw new RuntimeException(
|
||||
"Module " + mModuleWrapper.getName() + " supports web workers, but " + mMethod.getName() +
|
||||
"does not take an ExecutorToken as its first parameter.");
|
||||
}
|
||||
executorTokenOffset = 1;
|
||||
}
|
||||
|
||||
ArgumentExtractor[] argumentExtractors = new ArgumentExtractor[paramTypes.length - executorTokenOffset];
|
||||
for (int i = 0; i < paramTypes.length - executorTokenOffset; i += argumentExtractors[i].getJSArgumentsNeeded()) {
|
||||
int paramIndex = i + executorTokenOffset;
|
||||
Class argumentClass = paramTypes[paramIndex];
|
||||
ArgumentExtractor[] argumentExtractors = new ArgumentExtractor[paramTypes.length];
|
||||
for (int i = 0; i < paramTypes.length; i += argumentExtractors[i].getJSArgumentsNeeded()) {
|
||||
Class argumentClass = paramTypes[i];
|
||||
if (argumentClass == Boolean.class || argumentClass == boolean.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_BOOLEAN;
|
||||
} else if (argumentClass == Integer.class || argumentClass == int.class) {
|
||||
@ -328,7 +307,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
} else if (argumentClass == Promise.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_PROMISE;
|
||||
Assertions.assertCondition(
|
||||
paramIndex == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
} else if (argumentClass == ReadableMap.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_MAP;
|
||||
} else if (argumentClass == ReadableArray.class) {
|
||||
@ -357,7 +336,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray parameters) {
|
||||
public void invoke(JSInstance jsInstance, ReadableNativeArray parameters) {
|
||||
String traceName = mModuleWrapper.getName() + "." + mMethod.getName();
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "callJavaModuleMethod")
|
||||
.arg("method", traceName)
|
||||
@ -374,18 +353,11 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
|
||||
}
|
||||
|
||||
// Modules that support web workers are expected to take an ExecutorToken as the first
|
||||
// parameter to all their @ReactMethod-annotated methods. We compensate for that here.
|
||||
int i = 0, jsArgumentsConsumed = 0;
|
||||
int executorTokenOffset = 0;
|
||||
if (mModuleWrapper.supportsWebWorkers()) {
|
||||
mArguments[0] = executorToken;
|
||||
executorTokenOffset = 1;
|
||||
}
|
||||
try {
|
||||
for (; i < mArgumentExtractors.length; i++) {
|
||||
mArguments[i + executorTokenOffset] = mArgumentExtractors[i].extractArgument(
|
||||
jsInstance, executorToken, parameters, jsArgumentsConsumed);
|
||||
mArguments[i] = mArgumentExtractors[i].extractArgument(
|
||||
jsInstance, parameters, jsArgumentsConsumed);
|
||||
jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded();
|
||||
}
|
||||
} catch (UnexpectedNativeTypeException e) {
|
||||
|
@ -20,7 +20,6 @@ import java.util.Set;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.BaseJavaModule;
|
||||
import com.facebook.react.bridge.ExecutorToken;
|
||||
import com.facebook.react.bridge.JSInstance;
|
||||
import com.facebook.react.bridge.NativeArray;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
@ -155,16 +154,11 @@ public class JavaModuleWrapper {
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public boolean supportsWebWorkers() {
|
||||
return mModuleHolder.getSupportsWebWorkers();
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public void invoke(ExecutorToken token, int methodId, ReadableNativeArray parameters) {
|
||||
public void invoke(int methodId, ReadableNativeArray parameters) {
|
||||
if (mMethods == null || methodId >= mMethods.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMethods.get(methodId).invoke(mJSInstance, token, parameters);
|
||||
mMethods.get(methodId).invoke(mJSInstance, parameters);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ public class ModuleHolder {
|
||||
|
||||
private final String mName;
|
||||
private final boolean mCanOverrideExistingModule;
|
||||
private final boolean mSupportsWebWorkers;
|
||||
private final boolean mHasConstants;
|
||||
|
||||
private @Nullable Provider<? extends NativeModule> mProvider;
|
||||
@ -42,7 +41,6 @@ public class ModuleHolder {
|
||||
public ModuleHolder(ReactModuleInfo moduleInfo, Provider<? extends NativeModule> provider) {
|
||||
mName = moduleInfo.name();
|
||||
mCanOverrideExistingModule = moduleInfo.canOverrideExistingModule();
|
||||
mSupportsWebWorkers = moduleInfo.supportsWebWorkers();
|
||||
mHasConstants = moduleInfo.hasConstants();
|
||||
mProvider = provider;
|
||||
if (moduleInfo.needsEagerInit()) {
|
||||
@ -53,7 +51,6 @@ public class ModuleHolder {
|
||||
public ModuleHolder(NativeModule nativeModule) {
|
||||
mName = nativeModule.getName();
|
||||
mCanOverrideExistingModule = nativeModule.canOverrideExistingModule();
|
||||
mSupportsWebWorkers = nativeModule.supportsWebWorkers();
|
||||
mHasConstants = true;
|
||||
mModule = nativeModule;
|
||||
}
|
||||
@ -85,10 +82,6 @@ public class ModuleHolder {
|
||||
return mCanOverrideExistingModule;
|
||||
}
|
||||
|
||||
public boolean getSupportsWebWorkers() {
|
||||
return mSupportsWebWorkers;
|
||||
}
|
||||
|
||||
public boolean getHasConstants() {
|
||||
return mHasConstants;
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.facebook.react.bridge.BaseJavaModule;
|
||||
import com.facebook.react.bridge.ExecutorToken;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
@ -38,29 +36,6 @@ public @interface ReactModule {
|
||||
*/
|
||||
boolean canOverrideExistingModule() default false;
|
||||
|
||||
/**
|
||||
* In order to support web workers, a module must be aware that it can be invoked from multiple
|
||||
* different JS VMs. Supporting web workers means recognizing things like:
|
||||
*
|
||||
* 1) ids (e.g. timer ids, request ids, etc.) may only unique on a per-VM basis
|
||||
* 2) the module needs to make sure to enqueue callbacks and JS module calls to the correct VM
|
||||
*
|
||||
* In order to facilitate this, modules that support web workers will have all their @ReactMethod-
|
||||
* annotated methods passed a {@link ExecutorToken} as the first parameter before any arguments
|
||||
* from JS. This ExecutorToken internally maps to a specific JS VM and can be used by the
|
||||
* framework to route calls appropriately. In order to make JS module calls correctly, start using
|
||||
* the version of {@link ReactContext#getJSModule(ExecutorToken, Class)} that takes an
|
||||
* ExecutorToken. It will ensure that any calls you dispatch to the returned object will go to
|
||||
* the right VM. For Callbacks, you don't have to do anything special -- the framework
|
||||
* automatically tags them with the correct ExecutorToken when the are created.
|
||||
*
|
||||
* Note: even though calls can come from multiple JS VMs on multiple threads, calls to this module
|
||||
* will still only occur on a single thread.
|
||||
*
|
||||
* @return whether this module supports web workers.
|
||||
*/
|
||||
boolean supportsWebWorkers() default false;
|
||||
|
||||
/**
|
||||
* Whether this module needs to be loaded immediately.
|
||||
*/
|
||||
|
@ -10,19 +10,16 @@ public class ReactModuleInfo {
|
||||
|
||||
private final String mName;
|
||||
private final boolean mCanOverrideExistingModule;
|
||||
private final boolean mSupportsWebWorkers;
|
||||
private final boolean mNeedsEagerInit;
|
||||
private final boolean mHasConstants;
|
||||
|
||||
public ReactModuleInfo(
|
||||
String name,
|
||||
boolean canOverrideExistingModule,
|
||||
boolean supportsWebWorkers,
|
||||
boolean needsEagerInit,
|
||||
boolean hasConstants) {
|
||||
mName = name;
|
||||
mCanOverrideExistingModule = canOverrideExistingModule;
|
||||
mSupportsWebWorkers = supportsWebWorkers;
|
||||
mNeedsEagerInit = needsEagerInit;
|
||||
mHasConstants = hasConstants;
|
||||
}
|
||||
@ -35,10 +32,6 @@ public class ReactModuleInfo {
|
||||
return mCanOverrideExistingModule;
|
||||
}
|
||||
|
||||
public boolean supportsWebWorkers() {
|
||||
return mSupportsWebWorkers;
|
||||
}
|
||||
|
||||
public boolean needsEagerInit() {
|
||||
return mNeedsEagerInit;
|
||||
}
|
||||
|
@ -175,7 +175,6 @@ public class ReactModuleSpecProcessor extends AbstractProcessor {
|
||||
.append("new ReactModuleInfo(")
|
||||
.append("\"").append(reactModule.name()).append("\"").append(", ")
|
||||
.append(reactModule.canOverrideExistingModule()).append(", ")
|
||||
.append(reactModule.supportsWebWorkers()).append(", ")
|
||||
.append(reactModule.needsEagerInit()).append(", ")
|
||||
.append(hasConstants)
|
||||
.append(")")
|
||||
|
@ -18,7 +18,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.SupportsWebWorkers;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
@ -29,7 +28,6 @@ import com.facebook.react.module.annotations.ReactModule;
|
||||
@ReactModule(name = "DeviceEventManager")
|
||||
public class DeviceEventManagerModule extends ReactContextBaseJavaModule {
|
||||
|
||||
@SupportsWebWorkers
|
||||
public interface RCTDeviceEventEmitter extends JavaScriptModule {
|
||||
void emit(String eventName, @Nullable Object data);
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ LOCAL_SRC_FILES := \
|
||||
CatalystInstanceImpl.cpp \
|
||||
CxxModuleWrapper.cpp \
|
||||
JavaModuleWrapper.cpp \
|
||||
JExecutorToken.cpp \
|
||||
JMessageQueueThread.cpp \
|
||||
JniJSModulesUnbundle.cpp \
|
||||
JSCPerfLogging.cpp \
|
||||
|
@ -8,7 +8,6 @@ LOCAL_SRC_FILES := \
|
||||
CatalystInstanceImpl.cpp \
|
||||
CxxModuleWrapper.cpp \
|
||||
JavaModuleWrapper.cpp \
|
||||
JExecutorToken.cpp \
|
||||
JMessageQueueThread.cpp \
|
||||
JSCPerfLogging.cpp \
|
||||
JSLoader.cpp \
|
||||
|
@ -5,7 +5,6 @@ EXPORTED_HEADERS = [
|
||||
"CxxModuleWrapperBase.h",
|
||||
"CxxSharedModuleWrapper.h",
|
||||
"JavaModuleWrapper.h",
|
||||
"JExecutorToken.h",
|
||||
"JSLoader.h",
|
||||
"MethodInvoker.h",
|
||||
"ModuleRegistryBuilder.h",
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "JavaScriptExecutorHolder.h"
|
||||
#include "JniJSModulesUnbundle.h"
|
||||
#include "JNativeRunnable.h"
|
||||
#include "JSLoader.h"
|
||||
#include "NativeArray.h"
|
||||
|
||||
using namespace facebook::jni;
|
||||
@ -71,13 +70,6 @@ class JInstanceCallback : public InstanceCallback {
|
||||
method(jobj_);
|
||||
}
|
||||
|
||||
ExecutorToken createExecutorToken() override {
|
||||
auto jobj = JExecutorToken::newObjectCxxArgs();
|
||||
return jobj->cthis()->getExecutorToken(jobj);
|
||||
}
|
||||
|
||||
void onExecutorStopped(ExecutorToken) override {}
|
||||
|
||||
private:
|
||||
global_ref<ReactCallback::javaobject> jobj_;
|
||||
std::shared_ptr<JMessageQueueThread> messageQueueThread_;
|
||||
@ -107,7 +99,6 @@ void CatalystInstanceImpl::registerNatives() {
|
||||
makeNativeMethod("jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile),
|
||||
makeNativeMethod("jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction),
|
||||
makeNativeMethod("jniCallJSCallback", CatalystInstanceImpl::jniCallJSCallback),
|
||||
makeNativeMethod("getMainExecutorToken", CatalystInstanceImpl::getMainExecutorToken),
|
||||
makeNativeMethod("setGlobalVariable", CatalystInstanceImpl::setGlobalVariable),
|
||||
makeNativeMethod("getJavaScriptContext", CatalystInstanceImpl::getJavaScriptContext),
|
||||
makeNativeMethod("handleMemoryPressureUiHidden", CatalystInstanceImpl::handleMemoryPressureUiHidden),
|
||||
@ -167,8 +158,8 @@ void CatalystInstanceImpl::jniLoadScriptFromAssets(
|
||||
const int kAssetsLength = 9; // strlen("assets://");
|
||||
auto sourceURL = assetURL.substr(kAssetsLength);
|
||||
|
||||
auto manager = react::extractAssetManager(assetManager);
|
||||
auto script = react::loadScriptFromAssets(manager, sourceURL);
|
||||
auto manager = extractAssetManager(assetManager);
|
||||
auto script = loadScriptFromAssets(manager, sourceURL);
|
||||
if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) {
|
||||
instance_->loadUnbundle(
|
||||
folly::make_unique<JniJSModulesUnbundle>(manager, sourceURL),
|
||||
@ -206,8 +197,7 @@ void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName,
|
||||
}
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::jniCallJSFunction(
|
||||
JExecutorToken* token, std::string module, std::string method, NativeArray* arguments) {
|
||||
void CatalystInstanceImpl::jniCallJSFunction(std::string module, std::string method, NativeArray* arguments) {
|
||||
// We want to share the C++ code, and on iOS, modules pass module/method
|
||||
// names as strings all the way through to JS, and there's no way to do
|
||||
// string -> id mapping on the objc side. So on Android, we convert the
|
||||
@ -215,18 +205,13 @@ void CatalystInstanceImpl::jniCallJSFunction(
|
||||
// used as ids if isFinite(), which handles this case, and looked up as
|
||||
// strings otherwise. Eventually, we'll probably want to modify the stack
|
||||
// from the JS proxy through here to use strings, too.
|
||||
instance_->callJSFunction(token->getExecutorToken(nullptr),
|
||||
std::move(module),
|
||||
instance_->callJSFunction(std::move(module),
|
||||
std::move(method),
|
||||
arguments->consume());
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::jniCallJSCallback(JExecutorToken* token, jint callbackId, NativeArray* arguments) {
|
||||
instance_->callJSCallback(token->getExecutorToken(nullptr), callbackId, arguments->consume());
|
||||
}
|
||||
|
||||
local_ref<JExecutorToken::JavaPart> CatalystInstanceImpl::getMainExecutorToken() {
|
||||
return JExecutorToken::extractJavaPartFromToken(instance_->getMainExecutorToken());
|
||||
void CatalystInstanceImpl::jniCallJSCallback(jint callbackId, NativeArray* arguments) {
|
||||
instance_->callJSCallback(callbackId, arguments->consume());
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::setGlobalVariable(std::string propName,
|
||||
|
@ -6,10 +6,9 @@
|
||||
#include <folly/Memory.h>
|
||||
|
||||
#include "CxxModuleWrapper.h"
|
||||
#include "JExecutorToken.h"
|
||||
#include "JavaModuleWrapper.h"
|
||||
#include "JMessageQueueThread.h"
|
||||
#include "JSLoader.h"
|
||||
#include "JavaModuleWrapper.h"
|
||||
#include "ModuleRegistryBuilder.h"
|
||||
|
||||
namespace facebook {
|
||||
@ -59,9 +58,8 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
|
||||
|
||||
void jniLoadScriptFromAssets(jni::alias_ref<JAssetManager::javaobject> assetManager, const std::string& assetURL);
|
||||
void jniLoadScriptFromFile(const std::string& fileName, const std::string& sourceURL);
|
||||
void jniCallJSFunction(JExecutorToken* token, std::string module, std::string method, NativeArray* arguments);
|
||||
void jniCallJSCallback(JExecutorToken* token, jint callbackId, NativeArray* arguments);
|
||||
local_ref<JExecutorToken::JavaPart> getMainExecutorToken();
|
||||
void jniCallJSFunction(std::string module, std::string method, NativeArray* arguments);
|
||||
void jniCallJSCallback(jint callbackId, NativeArray* arguments);
|
||||
void setGlobalVariable(std::string propName,
|
||||
std::string&& jsonValue);
|
||||
jlong getJavaScriptContext();
|
||||
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JExecutorToken.h"
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ExecutorToken JExecutorToken::getExecutorToken(alias_ref<JExecutorToken::javaobject> jobj) {
|
||||
std::lock_guard<std::mutex> guard(createTokenGuard_);
|
||||
auto sharedOwner = owner_.lock();
|
||||
if (!sharedOwner) {
|
||||
sharedOwner = std::shared_ptr<PlatformExecutorToken>(new JExecutorTokenHolder(jobj));
|
||||
owner_ = sharedOwner;
|
||||
}
|
||||
return ExecutorToken(sharedOwner);
|
||||
}
|
||||
|
||||
local_ref<JExecutorToken::JavaPart> JExecutorToken::extractJavaPartFromToken(ExecutorToken token) {
|
||||
return make_local(static_cast<JExecutorTokenHolder*>(token.getPlatformExecutorToken().get())->getJobj());
|
||||
}
|
||||
|
||||
|
||||
} }
|
@ -1,61 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <fb/fbjni.h>
|
||||
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <jschelpers/noncopyable.h>
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JExecutorTokenHolder;
|
||||
class JExecutorToken : public HybridClass<JExecutorToken> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/ExecutorToken;";
|
||||
|
||||
ExecutorToken getExecutorToken(alias_ref<JExecutorToken::javaobject> jobj);
|
||||
|
||||
static local_ref<JavaPart> extractJavaPartFromToken(ExecutorToken token);
|
||||
private:
|
||||
friend HybridBase;
|
||||
friend JExecutorTokenHolder;
|
||||
|
||||
JExecutorToken() {}
|
||||
|
||||
std::weak_ptr<PlatformExecutorToken> owner_;
|
||||
std::mutex createTokenGuard_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper class to hold references to both the c++ and Java parts of the
|
||||
* ExecutorToken object. The goal is to allow a reference to a token from either
|
||||
* c++ or Java to keep both the Java object and c++ hybrid part alive. For c++
|
||||
* references, we accomplish this by having JExecutorTokenHolder keep a reference
|
||||
* to the Java object (which has a reference to the JExecutorToken hybrid part).
|
||||
* For Java references, we allow the JExecutorTokenHolder to be deallocated if there
|
||||
* are no references to it in c++ from a PlatformExecutorToken, but will dynamically
|
||||
* create a new one in JExecutorToken.getExecutorToken if needed.
|
||||
*/
|
||||
class JExecutorTokenHolder : public PlatformExecutorToken, public noncopyable {
|
||||
public:
|
||||
explicit JExecutorTokenHolder(alias_ref<JExecutorToken::javaobject> jobj) :
|
||||
jobj_(make_global(jobj)),
|
||||
impl_(cthis(jobj)) {
|
||||
}
|
||||
|
||||
JExecutorToken::javaobject getJobj() {
|
||||
return jobj_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
global_ref<JExecutorToken::javaobject> jobj_;
|
||||
JExecutorToken *impl_;
|
||||
};
|
||||
|
||||
} }
|
@ -21,31 +21,6 @@ using namespace facebook::jni;
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct JApplication : JavaClass<JApplication> {
|
||||
static constexpr auto kJavaDescriptor = "Landroid/app/Application;";
|
||||
|
||||
local_ref<JAssetManager::javaobject> getAssets() {
|
||||
static auto method = javaClassStatic()->getMethod<JAssetManager::javaobject()>("getAssets");
|
||||
return method(self());
|
||||
}
|
||||
};
|
||||
|
||||
struct JApplicationHolder : JavaClass<JApplicationHolder> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/common/ApplicationHolder;";
|
||||
|
||||
static local_ref<JApplication::javaobject> getApplication() {
|
||||
static auto method = javaClassStatic()
|
||||
->getStaticMethod<JApplication::javaobject()>("getApplication");
|
||||
return method(javaClassStatic());
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<const JSBigString> loadScriptFromAssets(const std::string& assetName) {
|
||||
auto env = Environment::current();
|
||||
auto assetManager = JApplicationHolder::getApplication()->getAssets();
|
||||
return loadScriptFromAssets(AAssetManager_fromJava(env, assetManager.get()), assetName);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
AAssetManager *extractAssetManager(alias_ref<JAssetManager::javaobject> assetManager) {
|
||||
auto env = Environment::current();
|
||||
|
@ -15,12 +15,6 @@ struct JAssetManager : jni::JavaClass<JAssetManager> {
|
||||
static constexpr auto kJavaDescriptor = "Landroid/content/res/AssetManager;";
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method for loading a JS script from Android assets without
|
||||
* a reference to an AssetManager.
|
||||
*/
|
||||
std::unique_ptr<const JSBigString> loadScriptFromAssets(const std::string& assetName);
|
||||
|
||||
/**
|
||||
* Helper method for loading JS script from android asset
|
||||
*/
|
||||
|
@ -80,24 +80,17 @@ folly::dynamic JavaNativeModule::getConstants() {
|
||||
}
|
||||
}
|
||||
|
||||
bool JavaNativeModule::supportsWebWorkers() {
|
||||
static auto supportsWebWorkersMethod =
|
||||
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
|
||||
return supportsWebWorkersMethod(wrapper_);
|
||||
}
|
||||
|
||||
void JavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
messageQueueThread_->runOnQueue([this, token, reactMethodId, params=std::move(params)] {
|
||||
static auto invokeMethod = wrapper_->getClass()->
|
||||
getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
|
||||
invokeMethod(wrapper_,
|
||||
JExecutorToken::extractJavaPartFromToken(token).get(),
|
||||
static_cast<jint>(reactMethodId),
|
||||
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
|
||||
void JavaNativeModule::invoke(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
messageQueueThread_->runOnQueue([this, reactMethodId, params=std::move(params)] {
|
||||
static auto invokeMethod = wrapper_->getClass()->getMethod<void(jint, ReadableNativeArray::javaobject)>("invoke");
|
||||
invokeMethod(
|
||||
wrapper_,
|
||||
static_cast<jint>(reactMethodId),
|
||||
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult JavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
MethodCallResult JavaNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
// TODO: evaluate whether calling through invoke is potentially faster
|
||||
if (reactMethodId >= syncMethods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
@ -106,7 +99,7 @@ MethodCallResult JavaNativeModule::callSerializableNativeHook(ExecutorToken toke
|
||||
|
||||
auto& method = syncMethods_[reactMethodId];
|
||||
CHECK(method.hasValue() && method->isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
|
||||
return method->invoke(instance_, wrapper_->getModule(), token, params);
|
||||
return method->invoke(instance_, wrapper_->getModule(), params);
|
||||
}
|
||||
|
||||
NewJavaNativeModule::NewJavaNativeModule(
|
||||
@ -155,34 +148,28 @@ folly::dynamic NewJavaNativeModule::getConstants() {
|
||||
}
|
||||
}
|
||||
|
||||
bool NewJavaNativeModule::supportsWebWorkers() {
|
||||
static auto supportsWebWorkersMethod =
|
||||
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
|
||||
return supportsWebWorkersMethod(wrapper_);
|
||||
}
|
||||
|
||||
void NewJavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
void NewJavaNativeModule::invoke(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
if (reactMethodId >= methods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
|
||||
}
|
||||
CHECK(!methods_[reactMethodId].isSyncHook()) << "Trying to invoke a synchronous hook asynchronously";
|
||||
messageQueueThread_->runOnQueue([this, token, reactMethodId, params=std::move(params)] () mutable {
|
||||
invokeInner(token, reactMethodId, std::move(params));
|
||||
messageQueueThread_->runOnQueue([this, reactMethodId, params=std::move(params)] () mutable {
|
||||
invokeInner(reactMethodId, std::move(params));
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult NewJavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
MethodCallResult NewJavaNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
if (reactMethodId >= methods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
|
||||
}
|
||||
CHECK(methods_[reactMethodId].isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
|
||||
return invokeInner(token, reactMethodId, std::move(params));
|
||||
return invokeInner(reactMethodId, std::move(params));
|
||||
}
|
||||
|
||||
MethodCallResult NewJavaNativeModule::invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
return methods_[reactMethodId].invoke(instance_, module_.get(), token, params);
|
||||
MethodCallResult NewJavaNativeModule::invokeInner(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
return methods_[reactMethodId].invoke(instance_, module_.get(), params);
|
||||
}
|
||||
|
||||
jni::local_ref<JReflectMethod::javaobject> JMethodDescriptor::getMethod() const {
|
||||
|
@ -54,9 +54,8 @@ class JavaNativeModule : public NativeModule {
|
||||
std::string getName() override;
|
||||
folly::dynamic getConstants() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
bool supportsWebWorkers() override;
|
||||
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
void invoke(unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<Instance> instance_;
|
||||
@ -76,9 +75,8 @@ class NewJavaNativeModule : public NativeModule {
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
folly::dynamic getConstants() override;
|
||||
bool supportsWebWorkers() override;
|
||||
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
void invoke(unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<Instance> instance_;
|
||||
@ -88,7 +86,7 @@ class NewJavaNativeModule : public NativeModule {
|
||||
std::vector<MethodInvoker> methods_;
|
||||
std::vector<MethodDescriptor> methodDescriptors_;
|
||||
|
||||
MethodCallResult invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params);
|
||||
MethodCallResult invokeInner(unsigned int reactMethodId, folly::dynamic&& params);
|
||||
};
|
||||
|
||||
}}
|
||||
|
@ -1,32 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <jni.h>
|
||||
#include <folly/Memory.h>
|
||||
|
||||
#include "JMessageQueueThread.h"
|
||||
#include <react/MessageQueue.h>
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JniWebWorkers : public JavaClass<JniWebWorkers> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/webworkers/WebWorkers;";
|
||||
|
||||
static std::unique_ptr<MessageQueue> createWebWorkerQueue(int id, MessageQueue* ownerMessageQueue) {
|
||||
static auto method = JniWebWorkers::javaClassStatic()->
|
||||
getStaticMethod<MessageQueueThread::javaobject(jint, MessageQueueThread::javaobject)>("createWebWorkerThread");
|
||||
|
||||
JMessageQueueThread* ownerMessageQueueThread = static_cast<JMessageQueueThread*>(ownerMessageQueue);
|
||||
auto res = method(JniWebWorkers::javaClassStatic(), id, ownerMessageQueueThread->jobj());
|
||||
return folly::make_unique<JMessageQueueThread>(res);
|
||||
}
|
||||
};
|
||||
|
||||
} }
|
@ -7,14 +7,16 @@
|
||||
#endif
|
||||
|
||||
#include <cxxreact/CxxNativeModule.h>
|
||||
#include <fb/fbjni.h>
|
||||
|
||||
#include "JCallback.h"
|
||||
#include "JExecutorToken.h"
|
||||
#include "ReadableNativeArray.h"
|
||||
#include "ReadableNativeMap.h"
|
||||
#include "WritableNativeArray.h"
|
||||
#include "WritableNativeMap.h"
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
@ -22,10 +24,10 @@ namespace {
|
||||
|
||||
using dynamic_iterator = folly::dynamic::const_iterator;
|
||||
|
||||
struct JPromiseImpl : public jni::JavaClass<JPromiseImpl> {
|
||||
struct JPromiseImpl : public JavaClass<JPromiseImpl> {
|
||||
constexpr static auto kJavaDescriptor = "Lcom/facebook/react/bridge/PromiseImpl;";
|
||||
|
||||
static jni::local_ref<javaobject> create(jni::local_ref<JCallback::javaobject> resolve, jni::local_ref<JCallback::javaobject> reject) {
|
||||
static local_ref<javaobject> create(local_ref<JCallback::javaobject> resolve, local_ref<JCallback::javaobject> reject) {
|
||||
return newInstance(resolve, reject);
|
||||
}
|
||||
};
|
||||
@ -44,18 +46,18 @@ jdouble extractDouble(const folly::dynamic& value) {
|
||||
}
|
||||
}
|
||||
|
||||
jni::local_ref<JCallbackImpl::jhybridobject> extractCallback(std::weak_ptr<Instance>& instance, ExecutorToken token, const folly::dynamic& value) {
|
||||
local_ref<JCallbackImpl::jhybridobject> extractCallback(std::weak_ptr<Instance>& instance, const folly::dynamic& value) {
|
||||
if (value.isNull()) {
|
||||
return jni::local_ref<JCallbackImpl::jhybridobject>(nullptr);
|
||||
return local_ref<JCallbackImpl::jhybridobject>(nullptr);
|
||||
} else {
|
||||
return JCallbackImpl::newObjectCxxArgs(makeCallback(instance, token, value));
|
||||
return JCallbackImpl::newObjectCxxArgs(makeCallback(instance, value));
|
||||
}
|
||||
}
|
||||
|
||||
jni::local_ref<JPromiseImpl::javaobject> extractPromise(std::weak_ptr<Instance>& instance, ExecutorToken token, dynamic_iterator& it, dynamic_iterator& end) {
|
||||
auto resolve = extractCallback(instance, token, *it++);
|
||||
local_ref<JPromiseImpl::javaobject> extractPromise(std::weak_ptr<Instance>& instance, dynamic_iterator& it, dynamic_iterator& end) {
|
||||
auto resolve = extractCallback(instance, *it++);
|
||||
CHECK(it != end);
|
||||
auto reject = extractCallback(instance, token, *it++);
|
||||
auto reject = extractCallback(instance, *it++);
|
||||
return JPromiseImpl::create(resolve, reject);
|
||||
}
|
||||
|
||||
@ -74,14 +76,11 @@ bool isNullable(char type) {
|
||||
}
|
||||
}
|
||||
|
||||
jvalue extract(std::weak_ptr<Instance>& instance, ExecutorToken token, char type, dynamic_iterator& it, dynamic_iterator& end) {
|
||||
jvalue extract(std::weak_ptr<Instance>& instance, char type, dynamic_iterator& it, dynamic_iterator& end) {
|
||||
CHECK(it != end);
|
||||
jvalue value;
|
||||
if (type == 'P') {
|
||||
value.l = extractPromise(instance, token, it, end).release();
|
||||
return value;
|
||||
} else if (type == 'T') {
|
||||
value.l = JExecutorToken::extractJavaPartFromToken(token).release();
|
||||
value.l = extractPromise(instance, it, end).release();
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -117,7 +116,7 @@ jvalue extract(std::weak_ptr<Instance>& instance, ExecutorToken token, char type
|
||||
value.l = JDouble::valueOf(extractDouble(arg)).release();
|
||||
break;
|
||||
case 'S':
|
||||
value.l = jni::make_jstring(arg.getString().c_str()).release();
|
||||
value.l = make_jstring(arg.getString().c_str()).release();
|
||||
break;
|
||||
case 'A':
|
||||
value.l = ReadableNativeArray::newObjectCxxArgs(arg).release();
|
||||
@ -126,7 +125,7 @@ jvalue extract(std::weak_ptr<Instance>& instance, ExecutorToken token, char type
|
||||
value.l = ReadableNativeMap::newObjectCxxArgs(arg).release();
|
||||
break;
|
||||
case 'X':
|
||||
value.l = extractCallback(instance, token, arg).release();
|
||||
value.l = extractCallback(instance, arg).release();
|
||||
break;
|
||||
default:
|
||||
LOG(FATAL) << "Unknown param type: " << type;
|
||||
@ -138,8 +137,6 @@ std::size_t countJsArgs(const std::string& signature) {
|
||||
std::size_t count = 0;
|
||||
for (char c : signature) {
|
||||
switch (c) {
|
||||
case 'T':
|
||||
break;
|
||||
case 'P':
|
||||
count += 2;
|
||||
break;
|
||||
@ -153,7 +150,7 @@ std::size_t countJsArgs(const std::string& signature) {
|
||||
|
||||
}
|
||||
|
||||
MethodInvoker::MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync)
|
||||
MethodInvoker::MethodInvoker(alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync)
|
||||
: method_(method->getMethodID()),
|
||||
signature_(signature),
|
||||
jsArgCount_(countJsArgs(signature) -2),
|
||||
@ -163,7 +160,7 @@ MethodInvoker::MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method,
|
||||
CHECK(isSync_ || signature_.at(0) == 'v') << "Non-sync hooks cannot have a non-void return type";
|
||||
}
|
||||
|
||||
MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, jni::alias_ref<JBaseJavaModule::javaobject> module, ExecutorToken token, const folly::dynamic& params) {
|
||||
MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, alias_ref<JBaseJavaModule::javaobject> module, const folly::dynamic& params) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
fbsystrace::FbSystraceSection s(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
@ -176,29 +173,29 @@ MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, jni::a
|
||||
throw std::invalid_argument(folly::to<std::string>("expected ", jsArgCount_, " arguments, got ", params.size()));
|
||||
}
|
||||
|
||||
auto env = jni::Environment::current();
|
||||
auto env = Environment::current();
|
||||
auto argCount = signature_.size() - 2;
|
||||
jni::JniLocalScope scope(env, argCount);
|
||||
JniLocalScope scope(env, argCount);
|
||||
jvalue args[argCount];
|
||||
std::transform(
|
||||
signature_.begin() + 2,
|
||||
signature_.end(),
|
||||
args,
|
||||
[&instance, token, it = params.begin(), end = params.end()] (char type) mutable {
|
||||
return extract(instance, token, type, it, end);
|
||||
[&instance, it = params.begin(), end = params.end()] (char type) mutable {
|
||||
return extract(instance, type, it, end);
|
||||
});
|
||||
|
||||
#define CASE_PRIMITIVE(KEY, TYPE, METHOD) \
|
||||
case KEY: { \
|
||||
auto result = env->Call ## METHOD ## MethodA(module.get(), method_, args); \
|
||||
jni::throwPendingJniExceptionAsCppException(); \
|
||||
throwPendingJniExceptionAsCppException(); \
|
||||
return folly::dynamic(result); \
|
||||
}
|
||||
|
||||
#define CASE_OBJECT(KEY, JNI_CLASS, ACTIONS) \
|
||||
case KEY: { \
|
||||
auto jobject = env->CallObjectMethodA(module.get(), method_, args); \
|
||||
jni::throwPendingJniExceptionAsCppException(); \
|
||||
throwPendingJniExceptionAsCppException(); \
|
||||
auto result = adopt_local(static_cast<JNI_CLASS::javaobject>(jobject)); \
|
||||
return folly::dynamic(result->ACTIONS); \
|
||||
}
|
||||
@ -207,7 +204,7 @@ MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, jni::a
|
||||
switch (returnType) {
|
||||
case 'v':
|
||||
env->CallVoidMethodA(module.get(), method_, args);
|
||||
jni::throwPendingJniExceptionAsCppException();
|
||||
throwPendingJniExceptionAsCppException();
|
||||
return folly::none;
|
||||
|
||||
CASE_PRIMITIVE('z', jboolean, Boolean)
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <fb/fbjni.h>
|
||||
#include <folly/dynamic.h>
|
||||
#include <cxxreact/Executor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
@ -31,7 +31,7 @@ class MethodInvoker {
|
||||
public:
|
||||
MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync);
|
||||
|
||||
MethodCallResult invoke(std::weak_ptr<Instance>& instance, jni::alias_ref<JBaseJavaModule::javaobject> module, ExecutorToken token, const folly::dynamic& params);
|
||||
MethodCallResult invoke(std::weak_ptr<Instance>& instance, jni::alias_ref<JBaseJavaModule::javaobject> module, const folly::dynamic& params);
|
||||
|
||||
bool isSyncHook() const {
|
||||
return isSync_;
|
||||
|
@ -12,9 +12,7 @@
|
||||
#include "CxxModuleWrapper.h"
|
||||
#include "JavaScriptExecutorHolder.h"
|
||||
#include "JSCPerfLogging.h"
|
||||
#include "JSLoader.h"
|
||||
#include "ProxyExecutor.h"
|
||||
#include "WebWorkers.h"
|
||||
#include "JCallback.h"
|
||||
#include "JSLogging.h"
|
||||
|
||||
@ -34,51 +32,6 @@ namespace react {
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string getApplicationCacheDir(void) {
|
||||
// Get the Application Context object
|
||||
auto getApplicationClass = findClassLocal(
|
||||
"com/facebook/react/common/ApplicationHolder");
|
||||
auto getApplicationMethod = getApplicationClass->getStaticMethod<jobject()>(
|
||||
"getApplication",
|
||||
"()Landroid/app/Application;"
|
||||
);
|
||||
auto application = getApplicationMethod(getApplicationClass);
|
||||
|
||||
// Get getCacheDir() from the context
|
||||
auto getDirMethod = findClassLocal("android/app/Application")
|
||||
->getMethod<jobject()>("getCacheDir",
|
||||
"()Ljava/io/File;"
|
||||
);
|
||||
auto dirObj = getDirMethod(application);
|
||||
|
||||
// Call getAbsolutePath() on the returned File object
|
||||
auto getAbsolutePathMethod = findClassLocal("java/io/File")
|
||||
->getMethod<jstring()>("getAbsolutePath");
|
||||
return getAbsolutePathMethod(dirObj)->toStdString();
|
||||
}
|
||||
|
||||
static JSValueRef nativePerformanceNow(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[], JSValueRef *exception) {
|
||||
static const int64_t NANOSECONDS_IN_SECOND = 1000000000LL;
|
||||
static const int64_t NANOSECONDS_IN_MILLISECOND = 1000000LL;
|
||||
|
||||
// Since SystemClock.uptimeMillis() is commonly used for performance measurement in Java
|
||||
// and uptimeMillis() internally uses clock_gettime(CLOCK_MONOTONIC),
|
||||
// we use the same API here.
|
||||
// We need that to make sure we use the same time system on both JS and Java sides.
|
||||
// Links to the source code:
|
||||
// https://android.googlesource.com/platform/frameworks/native/+/jb-mr1-release/libs/utils/SystemClock.cpp
|
||||
// https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
int64_t nano = now.tv_sec * NANOSECONDS_IN_SECOND + now.tv_nsec;
|
||||
return Value::makeNumber(ctx, (nano / (double)NANOSECONDS_IN_MILLISECOND));
|
||||
}
|
||||
|
||||
class JSCJavaScriptExecutorHolder : public HybridClass<JSCJavaScriptExecutorHolder,
|
||||
JavaScriptExecutorHolder> {
|
||||
public:
|
||||
@ -87,8 +40,7 @@ class JSCJavaScriptExecutorHolder : public HybridClass<JSCJavaScriptExecutorHold
|
||||
static local_ref<jhybriddata> initHybrid(alias_ref<jclass>, ReadableNativeArray* jscConfigArray) {
|
||||
// See JSCJavaScriptExecutor.Factory() for the other side of this hack.
|
||||
folly::dynamic jscConfigMap = jscConfigArray->consume()[0];
|
||||
return makeCxxInstance(
|
||||
std::make_shared<JSCExecutorFactory>(getApplicationCacheDir(), std::move(jscConfigMap)));
|
||||
return makeCxxInstance(std::make_shared<JSCExecutorFactory>(std::move(jscConfigMap)));
|
||||
}
|
||||
|
||||
static void registerNatives() {
|
||||
@ -129,7 +81,6 @@ class ProxyJavaScriptExecutorHolder : public HybridClass<ProxyJavaScriptExecutor
|
||||
using HybridBase::HybridBase;
|
||||
};
|
||||
|
||||
|
||||
class JReactMarker : public JavaClass<JReactMarker> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/ReactMarker;";
|
||||
@ -140,41 +91,59 @@ class JReactMarker : public JavaClass<JReactMarker> {
|
||||
}
|
||||
};
|
||||
|
||||
static JSValueRef nativePerformanceNow(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[], JSValueRef *exception) {
|
||||
static const int64_t NANOSECONDS_IN_SECOND = 1000000000LL;
|
||||
static const int64_t NANOSECONDS_IN_MILLISECOND = 1000000LL;
|
||||
|
||||
// Since SystemClock.uptimeMillis() is commonly used for performance measurement in Java
|
||||
// and uptimeMillis() internally uses clock_gettime(CLOCK_MONOTONIC),
|
||||
// we use the same API here.
|
||||
// We need that to make sure we use the same time system on both JS and Java sides.
|
||||
// Links to the source code:
|
||||
// https://android.googlesource.com/platform/frameworks/native/+/jb-mr1-release/libs/utils/SystemClock.cpp
|
||||
// https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
int64_t nano = now.tv_sec * NANOSECONDS_IN_SECOND + now.tv_nsec;
|
||||
return Value::makeNumber(ctx, (nano / (double)NANOSECONDS_IN_MILLISECOND));
|
||||
}
|
||||
|
||||
static void logPerfMarker(const ReactMarker::ReactMarkerId markerId) {
|
||||
switch (markerId) {
|
||||
case ReactMarker::RUN_JS_BUNDLE_START:
|
||||
JReactMarker::logMarker("RUN_JS_BUNDLE_START");
|
||||
break;
|
||||
case ReactMarker::RUN_JS_BUNDLE_STOP:
|
||||
JReactMarker::logMarker("RUN_JS_BUNDLE_END");
|
||||
break;
|
||||
case ReactMarker::CREATE_REACT_CONTEXT_STOP:
|
||||
JReactMarker::logMarker("CREATE_REACT_CONTEXT_END");
|
||||
break;
|
||||
case ReactMarker::JS_BUNDLE_STRING_CONVERT_START:
|
||||
JReactMarker::logMarker("loadApplicationScript_startStringConvert");
|
||||
break;
|
||||
case ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP:
|
||||
JReactMarker::logMarker("loadApplicationScript_endStringConvert");
|
||||
break;
|
||||
case ReactMarker::NATIVE_REQUIRE_START:
|
||||
case ReactMarker::NATIVE_REQUIRE_STOP:
|
||||
// These are not used on Android.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return initialize(vm, [] {
|
||||
gloginit::initialize();
|
||||
// Inject some behavior into react/
|
||||
ReactMarker::logMarker = [](const ReactMarker::ReactMarkerId markerId) {
|
||||
switch (markerId) {
|
||||
case ReactMarker::RUN_JS_BUNDLE_START:
|
||||
JReactMarker::logMarker("RUN_JS_BUNDLE_START");
|
||||
break;
|
||||
case ReactMarker::RUN_JS_BUNDLE_STOP:
|
||||
JReactMarker::logMarker("RUN_JS_BUNDLE_END");
|
||||
break;
|
||||
case ReactMarker::CREATE_REACT_CONTEXT_STOP:
|
||||
JReactMarker::logMarker("CREATE_REACT_CONTEXT_END");
|
||||
break;
|
||||
case ReactMarker::JS_BUNDLE_STRING_CONVERT_START:
|
||||
JReactMarker::logMarker("loadApplicationScript_startStringConvert");
|
||||
break;
|
||||
case ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP:
|
||||
JReactMarker::logMarker("loadApplicationScript_endStringConvert");
|
||||
break;
|
||||
case ReactMarker::NATIVE_REQUIRE_START:
|
||||
case ReactMarker::NATIVE_REQUIRE_STOP:
|
||||
// These are not used on Android.
|
||||
break;
|
||||
}
|
||||
};
|
||||
WebWorkerUtil::createWebWorkerThread = WebWorkers::createWebWorkerThread;
|
||||
WebWorkerUtil::loadScriptFromAssets =
|
||||
[] (const std::string& assetName) {
|
||||
return loadScriptFromAssets(assetName);
|
||||
};
|
||||
WebWorkerUtil::loadScriptFromNetworkSync = WebWorkers::loadScriptFromNetworkSync;
|
||||
ReactMarker::logMarker = logPerfMarker;
|
||||
PerfLogging::installNativeHooks = addNativePerfLoggingHooks;
|
||||
JSNativeHooks::loggingHook = nativeLoggingHook;
|
||||
JSNativeHooks::nowHook = nativePerformanceNow;
|
||||
|
@ -1,50 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <jni.h>
|
||||
#include <folly/Memory.h>
|
||||
|
||||
#include "JMessageQueueThread.h"
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class WebWorkers : public JavaClass<WebWorkers> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/webworkers/WebWorkers;";
|
||||
|
||||
static std::unique_ptr<JMessageQueueThread> createWebWorkerThread(int id, MessageQueueThread *ownerMessageQueueThread) {
|
||||
static auto method = WebWorkers::javaClassStatic()->
|
||||
getStaticMethod<JavaMessageQueueThread::javaobject(jint, JavaMessageQueueThread::javaobject)>("createWebWorkerThread");
|
||||
auto res = method(WebWorkers::javaClassStatic(), id, static_cast<JMessageQueueThread*>(ownerMessageQueueThread)->jobj());
|
||||
return folly::make_unique<JMessageQueueThread>(res);
|
||||
}
|
||||
|
||||
static std::string loadScriptFromNetworkSync(const std::string& url, const std::string& tempfileName) {
|
||||
static auto method = WebWorkers::javaClassStatic()->
|
||||
getStaticMethod<void(jstring, jstring)>("downloadScriptToFileSync");
|
||||
method(
|
||||
WebWorkers::javaClassStatic(),
|
||||
jni::make_jstring(url).get(),
|
||||
jni::make_jstring(tempfileName).get());
|
||||
|
||||
std::ifstream tempFile(tempfileName);
|
||||
if (!tempFile.good()) {
|
||||
throw std::runtime_error("Didn't find worker script file at " + tempfileName);
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << tempFile.rdbuf();
|
||||
std::remove(tempfileName.c_str());
|
||||
return buffer.str();
|
||||
}
|
||||
};
|
||||
|
||||
} }
|
@ -71,14 +71,14 @@ public class BaseJavaModuleTest {
|
||||
public void testCallMethodWithoutEnoughArgs() throws Exception {
|
||||
int methodId = findMethod("regularMethod",mMethods);
|
||||
Mockito.stub(mArguments.size()).toReturn(1);
|
||||
mWrapper.invoke(null, methodId, mArguments);
|
||||
mWrapper.invoke(methodId, mArguments);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallMethodWithEnoughArgs() {
|
||||
int methodId = findMethod("regularMethod", mMethods);
|
||||
Mockito.stub(mArguments.size()).toReturn(2);
|
||||
mWrapper.invoke(null, methodId, mArguments);
|
||||
mWrapper.invoke(methodId, mArguments);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -86,14 +86,14 @@ public class BaseJavaModuleTest {
|
||||
// Promise block evaluates to 2 args needing to be passed from JS
|
||||
int methodId = findMethod("asyncMethod", mMethods);
|
||||
Mockito.stub(mArguments.size()).toReturn(3);
|
||||
mWrapper.invoke(null, methodId, mArguments);
|
||||
mWrapper.invoke(methodId, mArguments);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallSyncMethod() {
|
||||
int methodId = findMethod("syncMethod", mMethods);
|
||||
Mockito.stub(mArguments.size()).toReturn(2);
|
||||
mWrapper.invoke(null, methodId, mArguments);
|
||||
mWrapper.invoke(methodId, mArguments);
|
||||
}
|
||||
|
||||
private static class MethodsModule extends BaseJavaModule {
|
||||
|
@ -16,7 +16,6 @@ LOCAL_SRC_FILES := \
|
||||
JSCNativeModules.cpp \
|
||||
JSCPerfStats.cpp \
|
||||
JSCTracing.cpp \
|
||||
JSCWebWorker.cpp \
|
||||
JSIndexedRAMBundle.cpp \
|
||||
MethodCall.cpp \
|
||||
ModuleRegistry.cpp \
|
||||
|
@ -129,14 +129,11 @@ cxx_library(
|
||||
CXXREACT_PUBLIC_HEADERS = [
|
||||
"CxxNativeModule.h",
|
||||
"Executor.h",
|
||||
"ExecutorToken.h",
|
||||
"ExecutorTokenFactory.h",
|
||||
"Instance.h",
|
||||
"JSBigString.h",
|
||||
"JSBundleType.h",
|
||||
"JSCExecutor.h",
|
||||
"JSCNativeModules.h",
|
||||
"JSCWebWorker.h",
|
||||
"JSIndexedRAMBundle.h",
|
||||
"JSModulesUnbundle.h",
|
||||
"MessageQueueThread.h",
|
||||
|
@ -15,15 +15,15 @@ namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::function<void(folly::dynamic)> makeCallback(
|
||||
std::weak_ptr<Instance> instance, ExecutorToken token, const folly::dynamic& callbackId) {
|
||||
std::weak_ptr<Instance> instance, const folly::dynamic& callbackId) {
|
||||
if (!callbackId.isInt()) {
|
||||
throw std::invalid_argument("Expected callback(s) as final argument");
|
||||
}
|
||||
|
||||
auto id = callbackId.getInt();
|
||||
return [winstance = std::move(instance), token, id](folly::dynamic args) {
|
||||
return [winstance = std::move(instance), id](folly::dynamic args) {
|
||||
if (auto instance = winstance.lock()) {
|
||||
instance->callJSCallback(token, id, std::move(args));
|
||||
instance->callJSCallback(id, std::move(args));
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -75,12 +75,7 @@ folly::dynamic CxxNativeModule::getConstants() {
|
||||
return constants;
|
||||
}
|
||||
|
||||
bool CxxNativeModule::supportsWebWorkers() {
|
||||
// TODO(andrews): web worker support in cxxmodules
|
||||
return false;
|
||||
}
|
||||
|
||||
void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
void CxxNativeModule::invoke(unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
if (reactMethodId >= methods_.size()) {
|
||||
throw std::invalid_argument(folly::to<std::string>("methodId ", reactMethodId,
|
||||
" out of range [0..", methods_.size(), "]"));
|
||||
@ -106,10 +101,10 @@ void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, fo
|
||||
}
|
||||
|
||||
if (method.callbacks == 1) {
|
||||
first = convertCallback(makeCallback(instance_, token, params[params.size() - 1]));
|
||||
first = convertCallback(makeCallback(instance_, params[params.size() - 1]));
|
||||
} else if (method.callbacks == 2) {
|
||||
first = convertCallback(makeCallback(instance_, token, params[params.size() - 2]));
|
||||
second = convertCallback(makeCallback(instance_, token, params[params.size() - 1]));
|
||||
first = convertCallback(makeCallback(instance_, params[params.size() - 2]));
|
||||
second = convertCallback(makeCallback(instance_, params[params.size() - 1]));
|
||||
}
|
||||
|
||||
params.resize(params.size() - method.callbacks);
|
||||
@ -146,8 +141,7 @@ void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, fo
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult CxxNativeModule::callSerializableNativeHook(
|
||||
ExecutorToken token, unsigned int hookId, folly::dynamic&& args) {
|
||||
MethodCallResult CxxNativeModule::callSerializableNativeHook(unsigned int hookId, folly::dynamic&& args) {
|
||||
if (hookId >= methods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", hookId, " out of range [0..", methods_.size(), "]"));
|
||||
|
@ -11,7 +11,7 @@ namespace react {
|
||||
class Instance;
|
||||
|
||||
std::function<void(folly::dynamic)> makeCallback(
|
||||
std::weak_ptr<Instance> instance, ExecutorToken token, const folly::dynamic& callbackId);
|
||||
std::weak_ptr<Instance> instance, const folly::dynamic& callbackId);
|
||||
|
||||
class CxxNativeModule : public NativeModule {
|
||||
public:
|
||||
@ -27,10 +27,8 @@ public:
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
folly::dynamic getConstants() override;
|
||||
bool supportsWebWorkers() override;
|
||||
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
ExecutorToken token, unsigned int hookId, folly::dynamic&& args) override;
|
||||
void invoke(unsigned int reactMethodId, folly::dynamic&& params) override;
|
||||
MethodCallResult callSerializableNativeHook(unsigned int hookId, folly::dynamic&& args) override;
|
||||
|
||||
private:
|
||||
void lazyInit();
|
||||
|
@ -38,10 +38,6 @@ class ExecutorDelegate {
|
||||
public:
|
||||
virtual ~ExecutorDelegate() {}
|
||||
|
||||
virtual void registerExecutor(std::unique_ptr<JSExecutor> executor,
|
||||
std::shared_ptr<MessageQueueThread> queue) = 0;
|
||||
virtual std::unique_ptr<JSExecutor> unregisterExecutor(JSExecutor& executor) = 0;
|
||||
|
||||
virtual std::shared_ptr<ModuleRegistry> getModuleRegistry() = 0;
|
||||
|
||||
virtual void callNativeModules(
|
||||
|
@ -1,54 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cxxreact/Executor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* This class exists so that we have a type for the shared_ptr on ExecutorToken
|
||||
* that implements a virtual destructor.
|
||||
*/
|
||||
class PlatformExecutorToken {
|
||||
public:
|
||||
virtual ~PlatformExecutorToken() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class corresponding to a JS VM that can call into native modules. This is
|
||||
* passed to native modules to allow their JS module calls/callbacks to be
|
||||
* routed back to the proper JS VM on the proper thread.
|
||||
*/
|
||||
class ExecutorToken {
|
||||
public:
|
||||
/**
|
||||
* This should only be used by the implementation of the platform ExecutorToken.
|
||||
* Do not use as a client of ExecutorToken.
|
||||
*/
|
||||
explicit ExecutorToken(std::shared_ptr<PlatformExecutorToken> platformToken) :
|
||||
platformToken_(platformToken) {}
|
||||
|
||||
std::shared_ptr<PlatformExecutorToken> getPlatformExecutorToken() const {
|
||||
return platformToken_;
|
||||
}
|
||||
|
||||
bool operator==(const ExecutorToken& other) const {
|
||||
return platformToken_.get() == other.platformToken_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<PlatformExecutorToken> platformToken_;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<facebook::react::ExecutorToken> {
|
||||
size_t operator()(const facebook::react::ExecutorToken& token) const {
|
||||
return (size_t) token.getPlatformExecutorToken().get();
|
||||
}
|
||||
};
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cxxreact/Executor.h>
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* Class that knows how to create the platform-specific implementation
|
||||
* of ExecutorToken.
|
||||
*/
|
||||
class ExecutorTokenFactory {
|
||||
public:
|
||||
virtual ~ExecutorTokenFactory() {}
|
||||
|
||||
/**
|
||||
* Creates a new ExecutorToken.
|
||||
*/
|
||||
virtual ExecutorToken createExecutorToken() const = 0;
|
||||
};
|
||||
|
||||
} }
|
@ -128,20 +128,15 @@ void *Instance::getJavaScriptContext() {
|
||||
return nativeToJsBridge_->getJavaScriptContext();
|
||||
}
|
||||
|
||||
void Instance::callJSFunction(ExecutorToken token, std::string&& module, std::string&& method,
|
||||
folly::dynamic&& params) {
|
||||
void Instance::callJSFunction(std::string&& module, std::string&& method, folly::dynamic&& params) {
|
||||
callback_->incrementPendingJSCalls();
|
||||
nativeToJsBridge_->callFunction(token, std::move(module), std::move(method), std::move(params));
|
||||
nativeToJsBridge_->callFunction(std::move(module), std::move(method), std::move(params));
|
||||
}
|
||||
|
||||
void Instance::callJSCallback(ExecutorToken token, uint64_t callbackId, folly::dynamic&& params) {
|
||||
void Instance::callJSCallback(uint64_t callbackId, folly::dynamic&& params) {
|
||||
SystraceSection s("<callback>");
|
||||
callback_->incrementPendingJSCalls();
|
||||
nativeToJsBridge_->invokeCallback(token, (double) callbackId, std::move(params));
|
||||
}
|
||||
|
||||
ExecutorToken Instance::getMainExecutorToken() {
|
||||
return nativeToJsBridge_->getMainExecutorToken();
|
||||
nativeToJsBridge_->invokeCallback((double) callbackId, std::move(params));
|
||||
}
|
||||
|
||||
void Instance::handleMemoryPressureUiHidden() {
|
||||
|
@ -19,8 +19,6 @@ struct InstanceCallback {
|
||||
virtual void onBatchComplete() = 0;
|
||||
virtual void incrementPendingJSCalls() = 0;
|
||||
virtual void decrementPendingJSCalls() = 0;
|
||||
virtual ExecutorToken createExecutorToken() = 0;
|
||||
virtual void onExecutorStopped(ExecutorToken) = 0;
|
||||
};
|
||||
|
||||
class Instance {
|
||||
@ -50,11 +48,9 @@ class Instance {
|
||||
void stopProfiler(const std::string& title, const std::string& filename);
|
||||
void setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue);
|
||||
void *getJavaScriptContext();
|
||||
void callJSFunction(ExecutorToken token, std::string&& module, std::string&& method,
|
||||
folly::dynamic&& params);
|
||||
void callJSCallback(ExecutorToken token, uint64_t callbackId, folly::dynamic&& params);
|
||||
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int moduleId,
|
||||
unsigned int methodId, folly::dynamic&& args);
|
||||
void callJSFunction(std::string&& module, std::string&& method, folly::dynamic&& params);
|
||||
void callJSCallback(uint64_t callbackId, folly::dynamic&& params);
|
||||
MethodCallResult callSerializableNativeHook(unsigned int moduleId, unsigned int methodId, folly::dynamic&& args);
|
||||
// This method is experimental, and may be modified or removed.
|
||||
template <typename T>
|
||||
Value callFunctionSync(const std::string& module, const std::string& method, T&& args) {
|
||||
@ -62,13 +58,12 @@ class Instance {
|
||||
return nativeToJsBridge_->callFunctionSync(module, method, std::forward<T>(args));
|
||||
}
|
||||
|
||||
ExecutorToken getMainExecutorToken();
|
||||
void handleMemoryPressureUiHidden();
|
||||
void handleMemoryPressureModerate();
|
||||
void handleMemoryPressureCritical();
|
||||
|
||||
private:
|
||||
void callNativeModules(ExecutorToken token, folly::dynamic&& calls, bool isEndOfBatch);
|
||||
void callNativeModules(folly::dynamic&& calls, bool isEndOfBatch);
|
||||
|
||||
std::shared_ptr<InstanceCallback> callback_;
|
||||
std::unique_ptr<NativeToJsBridge> nativeToJsBridge_;
|
||||
|
@ -132,16 +132,13 @@ static JSValueRef nativeInjectHMRUpdate(
|
||||
|
||||
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
|
||||
std::shared_ptr<ExecutorDelegate> delegate, std::shared_ptr<MessageQueueThread> jsQueue) {
|
||||
return std::unique_ptr<JSExecutor>(
|
||||
new JSCExecutor(delegate, jsQueue, m_cacheDir, m_jscConfig));
|
||||
return folly::make_unique<JSCExecutor>(delegate, jsQueue, m_jscConfig);
|
||||
}
|
||||
|
||||
JSCExecutor::JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread,
|
||||
const std::string& cacheDir,
|
||||
const folly::dynamic& jscConfig) throw(JSException) :
|
||||
m_delegate(delegate),
|
||||
m_deviceCacheDir(cacheDir),
|
||||
m_messageQueueThread(messageQueueThread),
|
||||
m_nativeModules(delegate ? delegate->getModuleRegistry() : nullptr),
|
||||
m_jscConfig(jscConfig) {
|
||||
@ -154,52 +151,6 @@ JSCExecutor::JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
|
||||
}
|
||||
}
|
||||
|
||||
JSCExecutor::JSCExecutor(
|
||||
std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread,
|
||||
int workerId,
|
||||
JSCExecutor *owner,
|
||||
std::string scriptURL,
|
||||
std::unordered_map<std::string, std::string> globalObjAsJSON,
|
||||
const folly::dynamic& jscConfig) :
|
||||
m_delegate(delegate),
|
||||
m_workerId(workerId),
|
||||
m_owner(owner),
|
||||
m_deviceCacheDir(owner->m_deviceCacheDir),
|
||||
m_messageQueueThread(messageQueueThread),
|
||||
m_nativeModules(delegate->getModuleRegistry()),
|
||||
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, scriptURL,
|
||||
globalObjAsJSON=std::move(globalObjAsJSON)] () {
|
||||
initOnJSVMThread();
|
||||
|
||||
installNativeHook<&JSCExecutor::nativePostMessage>("postMessage");
|
||||
|
||||
for (auto& it : globalObjAsJSON) {
|
||||
setGlobalVariable(std::move(it.first),
|
||||
folly::make_unique<JSBigStdString>(std::move(it.second)));
|
||||
}
|
||||
|
||||
// Try to load the script from the network if script is a URL
|
||||
// NB: For security, this will only work in debug builds
|
||||
std::unique_ptr<const JSBigString> script;
|
||||
if (scriptURL.find("http://") == 0 || scriptURL.find("https://") == 0) {
|
||||
std::stringstream outfileBuilder;
|
||||
outfileBuilder << m_deviceCacheDir << "/workerScript" << m_workerId << ".js";
|
||||
script = folly::make_unique<JSBigStdString>(
|
||||
WebWorkerUtil::loadScriptFromNetworkSync(scriptURL, outfileBuilder.str()));
|
||||
} else {
|
||||
// TODO(9604438): Protect against script does not exist
|
||||
script = WebWorkerUtil::loadScriptFromAssets(scriptURL);
|
||||
}
|
||||
|
||||
// TODO(9994180): Throw on error
|
||||
loadApplicationScript(std::move(script), std::move(scriptURL));
|
||||
});
|
||||
}
|
||||
|
||||
JSCExecutor::~JSCExecutor() {
|
||||
CHECK(*m_isDestroyed) << "JSCExecutor::destroy() must be called before its destructor!";
|
||||
}
|
||||
@ -260,11 +211,6 @@ void JSCExecutor::initOnJSVMThread() throw(JSException) {
|
||||
installNativeHook<&JSCExecutor::nativeFlushQueueImmediate>("nativeFlushQueueImmediate");
|
||||
installNativeHook<&JSCExecutor::nativeCallSyncHook>("nativeCallSyncHook");
|
||||
|
||||
// Webworker support
|
||||
installNativeHook<&JSCExecutor::nativeStartWorker>("nativeStartWorker");
|
||||
installNativeHook<&JSCExecutor::nativePostMessageToWorker>("nativePostMessageToWorker");
|
||||
installNativeHook<&JSCExecutor::nativeTerminateWorker>("nativeTerminateWorker");
|
||||
|
||||
installGlobalFunction(m_context, "nativeLoggingHook", JSNativeHooks::loggingHook);
|
||||
installGlobalFunction(m_context, "nativePerformanceNow", JSNativeHooks::nowHook);
|
||||
|
||||
@ -299,16 +245,6 @@ void JSCExecutor::initOnJSVMThread() throw(JSException) {
|
||||
}
|
||||
|
||||
void JSCExecutor::terminateOnJSVMThread() {
|
||||
// terminateOwnedWebWorker mutates m_ownedWorkers so collect all the workers
|
||||
// to terminate first
|
||||
std::vector<int> workerIds;
|
||||
for (auto& it : m_ownedWorkers) {
|
||||
workerIds.push_back(it.first);
|
||||
}
|
||||
for (int workerId : workerIds) {
|
||||
terminateOwnedWebWorker(workerId);
|
||||
}
|
||||
|
||||
m_nativeModules.reset();
|
||||
|
||||
#ifdef WITH_INSPECTOR
|
||||
@ -635,115 +571,6 @@ void JSCExecutor::loadModule(uint32_t moduleId) {
|
||||
evaluateScript(m_context, source, sourceUrl);
|
||||
}
|
||||
|
||||
int JSCExecutor::addWebWorker(
|
||||
std::string scriptURL,
|
||||
JSValueRef workerRef,
|
||||
JSValueRef globalObjRef) {
|
||||
static std::atomic_int nextWorkerId(1);
|
||||
int workerId = nextWorkerId++;
|
||||
|
||||
Object globalObj = Value(m_context, globalObjRef).asObject();
|
||||
|
||||
auto workerJscConfig = m_jscConfig;
|
||||
workerJscConfig["isWebWorker"] = true;
|
||||
|
||||
std::shared_ptr<MessageQueueThread> workerMQT =
|
||||
WebWorkerUtil::createWebWorkerThread(workerId, m_messageQueueThread.get());
|
||||
std::unique_ptr<JSCExecutor> worker;
|
||||
workerMQT->runOnQueueSync([this, &worker, &workerMQT, &scriptURL, &globalObj, workerId, &workerJscConfig] () {
|
||||
worker.reset(new JSCExecutor(m_delegate, workerMQT, workerId, this, std::move(scriptURL),
|
||||
globalObj.toJSONMap(), workerJscConfig));
|
||||
});
|
||||
|
||||
Object workerObj = Value(m_context, workerRef).asObject();
|
||||
workerObj.makeProtected();
|
||||
|
||||
JSCExecutor *workerPtr = worker.get();
|
||||
std::shared_ptr<MessageQueueThread> sharedMessageQueueThread = worker->m_messageQueueThread;
|
||||
m_delegate->registerExecutor(
|
||||
std::move(worker),
|
||||
std::move(sharedMessageQueueThread));
|
||||
|
||||
m_ownedWorkers.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(workerId),
|
||||
std::forward_as_tuple(workerPtr, std::move(workerObj)));
|
||||
|
||||
return workerId;
|
||||
}
|
||||
|
||||
void JSCExecutor::postMessageToOwnedWebWorker(int workerId, JSValueRef message) {
|
||||
auto worker = m_ownedWorkers.at(workerId).executor;
|
||||
std::string msgString = Value(m_context, message).toJSONString();
|
||||
|
||||
std::shared_ptr<bool> isWorkerDestroyed = worker->m_isDestroyed;
|
||||
worker->m_messageQueueThread->runOnQueue([isWorkerDestroyed, worker, msgString] () {
|
||||
if (*isWorkerDestroyed) {
|
||||
return;
|
||||
}
|
||||
worker->receiveMessageFromOwner(msgString);
|
||||
});
|
||||
}
|
||||
|
||||
void JSCExecutor::postMessageToOwner(JSValueRef msg) {
|
||||
std::string msgString = Value(m_context, msg).toJSONString();
|
||||
std::shared_ptr<bool> ownerIsDestroyed = m_owner->m_isDestroyed;
|
||||
m_owner->m_messageQueueThread->runOnQueue([workerId=m_workerId, owner=m_owner, ownerIsDestroyed, msgString] () {
|
||||
if (*ownerIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
owner->receiveMessageFromOwnedWebWorker(workerId, msgString);
|
||||
});
|
||||
}
|
||||
|
||||
void JSCExecutor::receiveMessageFromOwnedWebWorker(int workerId, const std::string& json) {
|
||||
Object* workerObj;
|
||||
try {
|
||||
workerObj = &m_ownedWorkers.at(workerId).jsObj;
|
||||
} catch (std::out_of_range& e) {
|
||||
// Worker was already terminated
|
||||
return;
|
||||
}
|
||||
|
||||
Value onmessageValue = workerObj->getProperty("onmessage");
|
||||
if (onmessageValue.isUndefined()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSValueRef args[] = { createMessageObject(json) };
|
||||
onmessageValue.asObject().callAsFunction(1, args);
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
void JSCExecutor::receiveMessageFromOwner(const std::string& msgString) {
|
||||
CHECK(m_owner) << "Received message in a Executor that doesn't have an owner!";
|
||||
|
||||
JSValueRef args[] = { createMessageObject(msgString) };
|
||||
Value onmessageValue = Object::getGlobalObject(m_context).getProperty("onmessage");
|
||||
onmessageValue.asObject().callAsFunction(1, args);
|
||||
}
|
||||
|
||||
void JSCExecutor::terminateOwnedWebWorker(int workerId) {
|
||||
auto& workerRegistration = m_ownedWorkers.at(workerId);
|
||||
std::shared_ptr<MessageQueueThread> workerMQT = workerRegistration.executor->m_messageQueueThread;
|
||||
m_ownedWorkers.erase(workerId);
|
||||
|
||||
workerMQT->runOnQueueSync([this, &workerMQT] {
|
||||
workerMQT->quitSynchronous();
|
||||
std::unique_ptr<JSExecutor> worker = m_delegate->unregisterExecutor(*this);
|
||||
worker->destroy();
|
||||
worker.reset();
|
||||
});
|
||||
}
|
||||
|
||||
Object JSCExecutor::createMessageObject(const std::string& msgJson) {
|
||||
Value rebornJSMsg = Value::fromJSON(m_context, String(m_context, msgJson.c_str()));
|
||||
Object messageObject = Object::create(m_context);
|
||||
messageObject.setProperty("data", rebornJSMsg);
|
||||
return messageObject;
|
||||
}
|
||||
|
||||
// Native JS hooks
|
||||
template<JSValueRef (JSCExecutor::*method)(size_t, const JSValueRef[])>
|
||||
void JSCExecutor::installNativeHook(const char* name) {
|
||||
@ -758,18 +585,6 @@ JSValueRef JSCExecutor::getNativeModule(JSObjectRef object, JSStringRef property
|
||||
return m_nativeModules.getModule(m_context, propertyName);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativePostMessage(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
if (argumentCount != 1) {
|
||||
throw std::invalid_argument("Got wrong number of args");
|
||||
}
|
||||
JSValueRef msg = arguments[0];
|
||||
postMessageToOwner(msg);
|
||||
|
||||
return Value::makeUndefined(m_context);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativeRequire(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
@ -801,57 +616,6 @@ JSValueRef JSCExecutor::nativeFlushQueueImmediate(
|
||||
return Value::makeUndefined(m_context);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativeStartWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
if (argumentCount != 3) {
|
||||
throw std::invalid_argument("Got wrong number of args");
|
||||
}
|
||||
|
||||
std::string scriptFile = Value(m_context, arguments[0]).toString().str();
|
||||
|
||||
JSValueRef worker = arguments[1];
|
||||
JSValueRef globalObj = arguments[2];
|
||||
|
||||
int workerId = addWebWorker(scriptFile, worker, globalObj);
|
||||
|
||||
return Value::makeNumber(m_context, workerId);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativePostMessageToWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
if (argumentCount != 2) {
|
||||
throw std::invalid_argument("Got wrong number of args");
|
||||
}
|
||||
|
||||
double workerDouble = Value(m_context, arguments[0]).asNumber();
|
||||
if (workerDouble != workerDouble) {
|
||||
throw std::invalid_argument("Got invalid worker id");
|
||||
}
|
||||
|
||||
postMessageToOwnedWebWorker((int) workerDouble, arguments[1]);
|
||||
|
||||
return Value::makeUndefined(m_context);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativeTerminateWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
if (argumentCount != 1) {
|
||||
throw std::invalid_argument("Got wrong number of args");
|
||||
}
|
||||
|
||||
double workerDouble = Value(m_context, arguments[0]).asNumber();
|
||||
if (workerDouble != workerDouble) {
|
||||
std::invalid_argument("Got invalid worker id");
|
||||
}
|
||||
|
||||
terminateOwnedWebWorker((int) workerDouble);
|
||||
|
||||
return Value::makeUndefined(m_context);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativeCallSyncHook(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]) {
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <cxxreact/Executor.h>
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <cxxreact/JSCNativeModules.h>
|
||||
#include <folly/Optional.h>
|
||||
#include <folly/json.h>
|
||||
@ -23,10 +22,9 @@ class MessageQueueThread;
|
||||
|
||||
class RN_EXPORT JSCExecutorFactory : public JSExecutorFactory {
|
||||
public:
|
||||
JSCExecutorFactory(const std::string& cacheDir, const folly::dynamic& jscConfig) :
|
||||
m_cacheDir(cacheDir),
|
||||
m_jscConfig(jscConfig) {}
|
||||
virtual std::unique_ptr<JSExecutor> createJSExecutor(
|
||||
JSCExecutorFactory(const folly::dynamic& jscConfig) :
|
||||
m_jscConfig(jscConfig) {}
|
||||
std::unique_ptr<JSExecutor> createJSExecutor(
|
||||
std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue) override;
|
||||
private:
|
||||
@ -34,17 +32,6 @@ private:
|
||||
folly::dynamic m_jscConfig;
|
||||
};
|
||||
|
||||
class JSCExecutor;
|
||||
class WorkerRegistration : public noncopyable {
|
||||
public:
|
||||
explicit WorkerRegistration(JSCExecutor* executor_, Object jsObj_) :
|
||||
executor(executor_),
|
||||
jsObj(std::move(jsObj_)) {}
|
||||
|
||||
JSCExecutor *executor;
|
||||
Object jsObj;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ValueEncoder;
|
||||
|
||||
@ -55,7 +42,6 @@ public:
|
||||
*/
|
||||
explicit JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread,
|
||||
const std::string& cacheDir,
|
||||
const folly::dynamic& jscConfig) throw(JSException);
|
||||
~JSCExecutor() override;
|
||||
|
||||
@ -104,11 +90,7 @@ public:
|
||||
private:
|
||||
JSGlobalContextRef m_context;
|
||||
std::shared_ptr<ExecutorDelegate> m_delegate;
|
||||
int m_workerId = 0; // if this is a worker executor, this is non-zero
|
||||
JSCExecutor *m_owner = nullptr; // if this is a worker executor, this is non-null
|
||||
std::shared_ptr<bool> m_isDestroyed = std::shared_ptr<bool>(new bool(false));
|
||||
std::unordered_map<int, WorkerRegistration> m_ownedWorkers;
|
||||
std::string m_deviceCacheDir;
|
||||
std::shared_ptr<MessageQueueThread> m_messageQueueThread;
|
||||
std::unique_ptr<JSModulesUnbundle> m_unbundle;
|
||||
JSCNativeModules m_nativeModules;
|
||||
@ -120,18 +102,6 @@ private:
|
||||
folly::Optional<Object> m_flushedQueueJS;
|
||||
folly::Optional<Object> m_callFunctionReturnResultAndFlushedQueueJS;
|
||||
|
||||
/**
|
||||
* WebWorker constructor. Must be invoked from thread this Executor will run on.
|
||||
*/
|
||||
JSCExecutor(
|
||||
std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread,
|
||||
int workerId,
|
||||
JSCExecutor *owner,
|
||||
std::string scriptURL,
|
||||
std::unordered_map<std::string, std::string> globalObjAsJSON,
|
||||
const folly::dynamic& jscConfig);
|
||||
|
||||
void initOnJSVMThread() throw(JSException);
|
||||
// This method is experimental, and may be modified or removed.
|
||||
Value callFunctionSyncWithValue(
|
||||
@ -143,30 +113,10 @@ private:
|
||||
void flushQueueImmediate(Value&&);
|
||||
void loadModule(uint32_t moduleId);
|
||||
|
||||
int addWebWorker(std::string scriptURL, JSValueRef workerRef, JSValueRef globalObjRef);
|
||||
void postMessageToOwnedWebWorker(int worker, JSValueRef message);
|
||||
void postMessageToOwner(JSValueRef result);
|
||||
void receiveMessageFromOwnedWebWorker(int workerId, const std::string& message);
|
||||
void receiveMessageFromOwner(const std::string &msgString);
|
||||
void terminateOwnedWebWorker(int worker);
|
||||
Object createMessageObject(const std::string& msgData);
|
||||
|
||||
template<JSValueRef (JSCExecutor::*method)(size_t, const JSValueRef[])>
|
||||
void installNativeHook(const char* name);
|
||||
JSValueRef getNativeModule(JSObjectRef object, JSStringRef propertyName);
|
||||
|
||||
JSValueRef nativeStartWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]);
|
||||
JSValueRef nativePostMessageToWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]);
|
||||
JSValueRef nativeTerminateWorker(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]);
|
||||
JSValueRef nativePostMessage(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]);
|
||||
JSValueRef nativeRequire(
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[]);
|
||||
|
@ -1,135 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JSCWebWorker.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <folly/Memory.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "MessageQueueThread.h"
|
||||
#include "Platform.h"
|
||||
#include "JSCUtils.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// TODO(9604425): thread safety
|
||||
static std::unordered_map<JSContextRef, JSCWebWorker*> s_globalContextRefToJSCWebWorker;
|
||||
|
||||
JSCWebWorker::JSCWebWorker(int id, JSCWebWorkerOwner *owner, std::string scriptSrc) :
|
||||
id_(id),
|
||||
scriptName_(std::move(scriptSrc)),
|
||||
owner_(owner) {
|
||||
ownerMessageQueueThread_ = owner->getMessageQueueThread();
|
||||
CHECK(ownerMessageQueueThread_) << "Owner MessageQueue must not be null";
|
||||
workerMessageQueueThread_ = WebWorkerUtil::createWebWorkerThread(id, ownerMessageQueueThread_.get());
|
||||
CHECK(workerMessageQueueThread_) << "Failed to create worker thread";
|
||||
|
||||
workerMessageQueueThread_->runOnQueue([this] () {
|
||||
initJSVMAndLoadScript();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
JSCWebWorker::~JSCWebWorker() {
|
||||
CHECK(isTerminated()) << "Didn't terminate the web worker before releasing it!";;
|
||||
}
|
||||
|
||||
void JSCWebWorker::postMessage(JSValueRef msg) {
|
||||
std::string msgString = Value(owner_->getContext(), msg).toJSONString();
|
||||
|
||||
workerMessageQueueThread_->runOnQueue([this, msgString] () {
|
||||
if (isTerminated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSValueRef args[] = { createMessageObject(context_, msgString) };
|
||||
Value onmessageValue = Object::getGlobalObject(context_).getProperty("onmessage");
|
||||
onmessageValue.asObject().callAsFunction(1, args);
|
||||
});
|
||||
}
|
||||
|
||||
void JSCWebWorker::terminate() {
|
||||
if (isTerminated()) {
|
||||
return;
|
||||
}
|
||||
isTerminated_.store(true, std::memory_order_release);
|
||||
|
||||
workerMessageQueueThread_->runOnQueueSync([this] {
|
||||
terminateOnWorkerThread();
|
||||
});
|
||||
}
|
||||
|
||||
void JSCWebWorker::terminateOnWorkerThread() {
|
||||
s_globalContextRefToJSCWebWorker.erase(context_);
|
||||
JSC_JSGlobalContextRelease(context_);
|
||||
context_ = nullptr;
|
||||
workerMessageQueueThread_->quitSynchronous();
|
||||
}
|
||||
|
||||
bool JSCWebWorker::isTerminated() {
|
||||
return isTerminated_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void JSCWebWorker::initJSVMAndLoadScript() {
|
||||
CHECK(!isTerminated()) << "Worker was already finished!";
|
||||
CHECK(!context_) << "Worker JS VM was already created!";
|
||||
|
||||
context_ = JSC_JSGlobalContextCreateInGroup(
|
||||
false, // no support required for custom JSC
|
||||
NULL, // use default JS 'global' object
|
||||
NULL // create new group (i.e. new VM)
|
||||
);
|
||||
s_globalContextRefToJSCWebWorker[context_] = this;
|
||||
|
||||
// TODO(9604438): Protect against script does not exist
|
||||
std::unique_ptr<const JSBigString> script = WebWorkerUtil::loadScriptFromAssets(scriptName_);
|
||||
evaluateScript(context_, jsStringFromBigString(context_, *script), String(context_, scriptName_.c_str()));
|
||||
|
||||
installGlobalFunction(context_, "postMessage", nativePostMessage);
|
||||
}
|
||||
|
||||
void JSCWebWorker::postMessageToOwner(JSValueRef msg) {
|
||||
std::string msgString = Value(context_, msg).toJSONString();
|
||||
ownerMessageQueueThread_->runOnQueue([this, msgString] () {
|
||||
owner_->onMessageReceived(id_, msgString);
|
||||
});
|
||||
}
|
||||
|
||||
JSValueRef JSCWebWorker::nativePostMessage(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception) {
|
||||
if (argumentCount != 1) {
|
||||
*exception = Value::makeError(ctx, "postMessage got wrong number of arguments");
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
JSValueRef msg = arguments[0];
|
||||
JSCWebWorker *webWorker = s_globalContextRefToJSCWebWorker.at(JSC_JSContextGetGlobalContext(ctx));
|
||||
|
||||
if (!webWorker->isTerminated()) {
|
||||
webWorker->postMessageToOwner(msg);
|
||||
}
|
||||
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
Object JSCWebWorker::createMessageObject(JSContextRef context, const std::string& msgJson) {
|
||||
Value rebornJSMsg = Value::fromJSON(context, String(context, msgJson.c_str()));
|
||||
Object messageObject = Object::create(context);
|
||||
messageObject.setProperty("data", rebornJSMsg);
|
||||
return messageObject;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class MessageQueueThread;
|
||||
|
||||
/**
|
||||
* A class that can own the lifecycle, receive messages from, and dispatch messages
|
||||
* to JSCWebWorkers.
|
||||
*/
|
||||
class JSCWebWorkerOwner {
|
||||
public:
|
||||
/**
|
||||
* Called when a worker has posted a message with `postMessage`.
|
||||
*/
|
||||
virtual void onMessageReceived(int workerId, const std::string& message) = 0;
|
||||
virtual JSGlobalContextRef getContext() = 0;
|
||||
|
||||
/**
|
||||
* Should return the owner's MessageQueueThread. Calls to onMessageReceived will be enqueued
|
||||
* on this thread.
|
||||
*/
|
||||
virtual std::shared_ptr<MessageQueueThread> getMessageQueueThread() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of a web worker for JSC. The web worker should be created from the owner's
|
||||
* (e.g., owning JSCExecutor instance) JS MessageQueueThread. The worker is responsible for
|
||||
* creating its own MessageQueueThread.
|
||||
*
|
||||
* During operation, the JSCExecutor should call postMessage **from its own MessageQueueThread**
|
||||
* to send messages to the worker. The worker will handle enqueueing those messages on its own
|
||||
* MessageQueueThread as appropriate. When the worker has a message to post to the owner, it will
|
||||
* enqueue a call to owner->onMessageReceived on the owner's MessageQueueThread.
|
||||
*/
|
||||
class JSCWebWorker {
|
||||
public:
|
||||
explicit JSCWebWorker(int id, JSCWebWorkerOwner *owner, std::string script);
|
||||
~JSCWebWorker();
|
||||
|
||||
/**
|
||||
* Post a message to be received by the worker on its thread. This must be called from
|
||||
* ownerMessageQueueThread_.
|
||||
*/
|
||||
void postMessage(JSValueRef msg);
|
||||
|
||||
/**
|
||||
* Synchronously quits the current worker and cleans up its VM.
|
||||
*/
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
* Whether terminate() has been called on this worker.
|
||||
*/
|
||||
bool isTerminated();
|
||||
|
||||
static Object createMessageObject(JSContextRef context, const std::string& msgData);
|
||||
private:
|
||||
void initJSVMAndLoadScript();
|
||||
void postRunnableToEventLoop(std::function<void()>&& runnable);
|
||||
void postMessageToOwner(JSValueRef result);
|
||||
void terminateOnWorkerThread();
|
||||
|
||||
int id_;
|
||||
std::atomic_bool isTerminated_ = ATOMIC_VAR_INIT(false);
|
||||
std::string scriptName_;
|
||||
JSCWebWorkerOwner *owner_ = nullptr;
|
||||
std::shared_ptr<MessageQueueThread> ownerMessageQueueThread_;
|
||||
std::unique_ptr<MessageQueueThread> workerMessageQueueThread_;
|
||||
JSGlobalContextRef context_ = nullptr;
|
||||
|
||||
static JSValueRef nativePostMessage(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -113,8 +113,7 @@ folly::Optional<ModuleConfig> ModuleRegistry::getConfig(const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId, unsigned int methodId,
|
||||
folly::dynamic&& params, int callId) {
|
||||
void ModuleRegistry::callNativeMethod(unsigned int moduleId, unsigned int methodId, folly::dynamic&& params, int callId) {
|
||||
if (moduleId >= modules_.size()) {
|
||||
throw std::runtime_error(
|
||||
folly::to<std::string>("moduleId ", moduleId, " out of range [0..", modules_.size(), ")"));
|
||||
@ -126,15 +125,15 @@ void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId
|
||||
}
|
||||
#endif
|
||||
|
||||
modules_[moduleId]->invoke(token, methodId, std::move(params));
|
||||
modules_[moduleId]->invoke(methodId, std::move(params));
|
||||
}
|
||||
|
||||
MethodCallResult ModuleRegistry::callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& params) {
|
||||
MethodCallResult ModuleRegistry::callSerializableNativeHook(unsigned int moduleId, unsigned int methodId, folly::dynamic&& params) {
|
||||
if (moduleId >= modules_.size()) {
|
||||
throw std::runtime_error(
|
||||
folly::to<std::string>("moduleId ", moduleId, "out of range [0..", modules_.size(), ")"));
|
||||
}
|
||||
return modules_[moduleId]->callSerializableNativeHook(token, methodId, std::move(params));
|
||||
return modules_[moduleId]->callSerializableNativeHook(methodId, std::move(params));
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <cxxreact/NativeModule.h>
|
||||
#include <folly/Optional.h>
|
||||
#include <folly/dynamic.h>
|
||||
@ -36,9 +35,8 @@ class ModuleRegistry {
|
||||
|
||||
folly::Optional<ModuleConfig> getConfig(const std::string& name);
|
||||
|
||||
void callNativeMethod(ExecutorToken token, unsigned int moduleId, unsigned int methodId,
|
||||
folly::dynamic&& params, int callId);
|
||||
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& args);
|
||||
void callNativeMethod(unsigned int moduleId, unsigned int methodId, folly::dynamic&& params, int callId);
|
||||
MethodCallResult callSerializableNativeHook(unsigned int moduleId, unsigned int methodId, folly::dynamic&& args);
|
||||
|
||||
private:
|
||||
// This is always populated
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <folly/dynamic.h>
|
||||
#include <cxxreact/Executor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
@ -27,11 +27,10 @@ class NativeModule {
|
||||
virtual std::string getName() = 0;
|
||||
virtual std::vector<MethodDescriptor> getMethods() = 0;
|
||||
virtual folly::dynamic getConstants() = 0;
|
||||
virtual bool supportsWebWorkers() = 0;
|
||||
// TODO mhorowitz: do we need initialize()/onCatalystInstanceDestroy() in C++
|
||||
// or only Java?
|
||||
virtual void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) = 0;
|
||||
virtual MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& args) = 0;
|
||||
virtual void invoke(unsigned int reactMethodId, folly::dynamic&& params) = 0;
|
||||
virtual MethodCallResult callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& args) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -22,23 +22,11 @@ namespace react {
|
||||
// This class manages calls from JS to native code.
|
||||
class JsToNativeBridge : public react::ExecutorDelegate {
|
||||
public:
|
||||
JsToNativeBridge(NativeToJsBridge* nativeToJs,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
JsToNativeBridge(std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_nativeToJs(nativeToJs)
|
||||
, m_registry(registry)
|
||||
: m_registry(registry)
|
||||
, m_callback(callback) {}
|
||||
|
||||
void registerExecutor(std::unique_ptr<JSExecutor> executor,
|
||||
std::shared_ptr<MessageQueueThread> queue) override {
|
||||
m_nativeToJs->registerExecutor(m_callback->createExecutorToken(), std::move(executor), queue);
|
||||
}
|
||||
|
||||
std::unique_ptr<JSExecutor> unregisterExecutor(JSExecutor& executor) override {
|
||||
m_callback->onExecutorStopped(m_nativeToJs->getTokenForExecutor(executor));
|
||||
return m_nativeToJs->unregisterExecutor(executor);
|
||||
}
|
||||
|
||||
std::shared_ptr<ModuleRegistry> getModuleRegistry() override {
|
||||
return m_registry;
|
||||
}
|
||||
@ -48,15 +36,13 @@ public:
|
||||
|
||||
CHECK(m_registry || calls.empty()) <<
|
||||
"native module calls cannot be completed with no native modules";
|
||||
ExecutorToken token = m_nativeToJs->getTokenForExecutor(executor);
|
||||
m_batchHadNativeModuleCalls = m_batchHadNativeModuleCalls || !calls.empty();
|
||||
|
||||
// An exception anywhere in here stops processing of the batch. This
|
||||
// was the behavior of the Android bridge, and since exception handling
|
||||
// terminates the whole bridge, there's not much point in continuing.
|
||||
for (auto& call : parseMethodCalls(std::move(calls))) {
|
||||
m_registry->callNativeMethod(
|
||||
token, call.moduleId, call.methodId, std::move(call.arguments), call.callId);
|
||||
m_registry->callNativeMethod(call.moduleId, call.methodId, std::move(call.arguments), call.callId);
|
||||
}
|
||||
if (isEndOfBatch) {
|
||||
// onBatchComplete will be called on the native (module) queue, but
|
||||
@ -73,18 +59,14 @@ public:
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
JSExecutor& executor, unsigned int moduleId, unsigned int methodId,
|
||||
folly::dynamic&& args) override {
|
||||
ExecutorToken token = m_nativeToJs->getTokenForExecutor(executor);
|
||||
return m_registry->callSerializableNativeHook(token, moduleId, methodId, std::move(args));
|
||||
return m_registry->callSerializableNativeHook(moduleId, methodId, std::move(args));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// These methods are always invoked from an Executor. The NativeToJsBridge
|
||||
// keeps a reference to the root executor, and when destroy() is
|
||||
// called, the Executors are all destroyed synchronously on their
|
||||
// bridges. So, the bridge pointer will will always point to a
|
||||
// valid object during a call to a delegate method from an exectuto.
|
||||
NativeToJsBridge* m_nativeToJs;
|
||||
// keeps a reference to the executor, and when destroy() is called, the
|
||||
// executor is destroyed synchronously on its queue.
|
||||
std::shared_ptr<ModuleRegistry> m_registry;
|
||||
std::shared_ptr<InstanceCallback> m_callback;
|
||||
bool m_batchHadNativeModuleCalls = false;
|
||||
@ -96,14 +78,9 @@ NativeToJsBridge::NativeToJsBridge(
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_destroyed(std::make_shared<bool>(false))
|
||||
, m_mainExecutorToken(callback->createExecutorToken())
|
||||
, m_delegate(std::make_shared<JsToNativeBridge>(this, registry, callback)) {
|
||||
std::unique_ptr<JSExecutor> mainExecutor =
|
||||
jsExecutorFactory->createJSExecutor(m_delegate, jsQueue);
|
||||
// cached to avoid locked map lookup in the common case
|
||||
m_mainExecutor = mainExecutor.get();
|
||||
registerExecutor(m_mainExecutorToken, std::move(mainExecutor), jsQueue);
|
||||
}
|
||||
, m_delegate(std::make_shared<JsToNativeBridge>(registry, callback))
|
||||
, m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue))
|
||||
, m_executorMessageQueueThread(std::move(jsQueue)) {}
|
||||
|
||||
// This must be called on the same thread on which the constructor was called.
|
||||
NativeToJsBridge::~NativeToJsBridge() {
|
||||
@ -116,7 +93,6 @@ void NativeToJsBridge::loadApplication(
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL) {
|
||||
runOnExecutorQueue(
|
||||
m_mainExecutorToken,
|
||||
[unbundleWrap=folly::makeMoveWrapper(std::move(unbundle)),
|
||||
startupScript=folly::makeMoveWrapper(std::move(startupScript)),
|
||||
startupScriptSourceURL=std::move(startupScriptSourceURL)]
|
||||
@ -135,14 +111,13 @@ void NativeToJsBridge::loadApplicationSync(
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL) {
|
||||
if (unbundle) {
|
||||
m_mainExecutor->setJSModulesUnbundle(std::move(unbundle));
|
||||
m_executor->setJSModulesUnbundle(std::move(unbundle));
|
||||
}
|
||||
m_mainExecutor->loadApplicationScript(std::move(startupScript),
|
||||
m_executor->loadApplicationScript(std::move(startupScript),
|
||||
std::move(startupScriptSourceURL));
|
||||
}
|
||||
|
||||
void NativeToJsBridge::callFunction(
|
||||
ExecutorToken executorToken,
|
||||
std::string&& module,
|
||||
std::string&& method,
|
||||
folly::dynamic&& arguments) {
|
||||
@ -160,23 +135,24 @@ void NativeToJsBridge::callFunction(
|
||||
std::string tracingName;
|
||||
#endif
|
||||
|
||||
runOnExecutorQueue(executorToken, [module = std::move(module), method = std::move(method), arguments = std::move(arguments), tracingName = std::move(tracingName), systraceCookie] (JSExecutor* executor) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
tracingName.c_str(),
|
||||
systraceCookie);
|
||||
SystraceSection s(tracingName.c_str());
|
||||
#endif
|
||||
runOnExecutorQueue([module = std::move(module), method = std::move(method), arguments = std::move(arguments), tracingName = std::move(tracingName), systraceCookie]
|
||||
(JSExecutor* executor) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
tracingName.c_str(),
|
||||
systraceCookie);
|
||||
SystraceSection s(tracingName.c_str());
|
||||
#endif
|
||||
|
||||
// This is safe because we are running on the executor's thread: it won't
|
||||
// destruct until after it's been unregistered (which we check above) and
|
||||
// that will happen on this thread
|
||||
executor->callFunction(module, method, arguments);
|
||||
});
|
||||
// This is safe because we are running on the executor's thread: it won't
|
||||
// destruct until after it's been unregistered (which we check above) and
|
||||
// that will happen on this thread
|
||||
executor->callFunction(module, method, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::invokeCallback(ExecutorToken executorToken, double callbackId, folly::dynamic&& arguments) {
|
||||
void NativeToJsBridge::invokeCallback(double callbackId, folly::dynamic&& arguments) {
|
||||
int systraceCookie = -1;
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
systraceCookie = m_systraceCookie++;
|
||||
@ -186,24 +162,23 @@ void NativeToJsBridge::invokeCallback(ExecutorToken executorToken, double callba
|
||||
systraceCookie);
|
||||
#endif
|
||||
|
||||
runOnExecutorQueue(executorToken, [callbackId, arguments = std::move(arguments), systraceCookie] (JSExecutor* executor) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
"<callback>",
|
||||
systraceCookie);
|
||||
SystraceSection s("NativeToJsBridge.invokeCallback");
|
||||
#endif
|
||||
runOnExecutorQueue([callbackId, arguments = std::move(arguments), systraceCookie]
|
||||
(JSExecutor* executor) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
"<callback>",
|
||||
systraceCookie);
|
||||
SystraceSection s("NativeToJsBridge.invokeCallback");
|
||||
#endif
|
||||
|
||||
executor->invokeCallback(callbackId, arguments);
|
||||
});
|
||||
executor->invokeCallback(callbackId, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::setGlobalVariable(std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue) {
|
||||
runOnExecutorQueue(
|
||||
m_mainExecutorToken,
|
||||
[propName=std::move(propName), jsonValue=folly::makeMoveWrapper(std::move(jsonValue))]
|
||||
runOnExecutorQueue([propName=std::move(propName), jsonValue=folly::makeMoveWrapper(std::move(jsonValue))]
|
||||
(JSExecutor* executor) mutable {
|
||||
executor->setGlobalVariable(propName, jsonValue.move());
|
||||
});
|
||||
@ -211,149 +186,72 @@ void NativeToJsBridge::setGlobalVariable(std::string propName,
|
||||
|
||||
void* NativeToJsBridge::getJavaScriptContext() {
|
||||
// TODO(cjhopman): this seems unsafe unless we require that it is only called on the main js queue.
|
||||
return m_mainExecutor->getJavaScriptContext();
|
||||
return m_executor->getJavaScriptContext();
|
||||
}
|
||||
|
||||
bool NativeToJsBridge::supportsProfiling() {
|
||||
// Intentionally doesn't post to jsqueue. supportsProfiling() can be called from any thread.
|
||||
return m_mainExecutor->supportsProfiling();
|
||||
return m_executor->supportsProfiling();
|
||||
}
|
||||
|
||||
void NativeToJsBridge::startProfiler(const std::string& title) {
|
||||
runOnExecutorQueue(m_mainExecutorToken, [=] (JSExecutor* executor) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->startProfiler(title);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::stopProfiler(const std::string& title, const std::string& filename) {
|
||||
runOnExecutorQueue(m_mainExecutorToken, [=] (JSExecutor* executor) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->stopProfiler(title, filename);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::handleMemoryPressureUiHidden() {
|
||||
runOnExecutorQueue(m_mainExecutorToken, [=] (JSExecutor* executor) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->handleMemoryPressureUiHidden();
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::handleMemoryPressureModerate() {
|
||||
runOnExecutorQueue(m_mainExecutorToken, [=] (JSExecutor* executor) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->handleMemoryPressureModerate();
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::handleMemoryPressureCritical() {
|
||||
runOnExecutorQueue(m_mainExecutorToken, [=] (JSExecutor* executor) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->handleMemoryPressureCritical();
|
||||
});
|
||||
}
|
||||
|
||||
ExecutorToken NativeToJsBridge::getMainExecutorToken() const {
|
||||
return m_mainExecutorToken;
|
||||
}
|
||||
|
||||
ExecutorToken NativeToJsBridge::registerExecutor(
|
||||
ExecutorToken token,
|
||||
std::unique_ptr<JSExecutor> executor,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread) {
|
||||
std::lock_guard<std::mutex> registrationGuard(m_registrationMutex);
|
||||
|
||||
CHECK(m_executorTokenMap.find(executor.get()) == m_executorTokenMap.end())
|
||||
<< "Trying to register an already registered executor!";
|
||||
|
||||
m_executorTokenMap.emplace(executor.get(), token);
|
||||
m_executorMap.emplace(
|
||||
token,
|
||||
ExecutorRegistration(std::move(executor), messageQueueThread));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
std::unique_ptr<JSExecutor> NativeToJsBridge::unregisterExecutor(JSExecutor& executor) {
|
||||
std::unique_ptr<JSExecutor> ret;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> registrationGuard(m_registrationMutex);
|
||||
|
||||
auto it = m_executorTokenMap.find(&executor);
|
||||
CHECK(it != m_executorTokenMap.end())
|
||||
<< "Trying to unregister an executor that was never registered!";
|
||||
auto it2 = m_executorMap.find(it->second);
|
||||
ret = std::move(it2->second.executor_);
|
||||
|
||||
m_executorTokenMap.erase(it);
|
||||
m_executorMap.erase(it2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MessageQueueThread* NativeToJsBridge::getMessageQueueThread(const ExecutorToken& executorToken) {
|
||||
std::lock_guard<std::mutex> registrationGuard(m_registrationMutex);
|
||||
auto it = m_executorMap.find(executorToken);
|
||||
if (it == m_executorMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second.messageQueueThread_.get();
|
||||
}
|
||||
|
||||
JSExecutor* NativeToJsBridge::getExecutor(const ExecutorToken& executorToken) {
|
||||
std::lock_guard<std::mutex> registrationGuard(m_registrationMutex);
|
||||
auto it = m_executorMap.find(executorToken);
|
||||
if (it == m_executorMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second.executor_.get();
|
||||
}
|
||||
|
||||
ExecutorToken NativeToJsBridge::getTokenForExecutor(JSExecutor& executor) {
|
||||
std::lock_guard<std::mutex> registrationGuard(m_registrationMutex);
|
||||
return m_executorTokenMap.at(&executor);
|
||||
}
|
||||
|
||||
void NativeToJsBridge::destroy() {
|
||||
auto* executorMessageQueueThread = getMessageQueueThread(m_mainExecutorToken);
|
||||
// All calls made through runOnExecutorQueue have an early exit if
|
||||
// m_destroyed is true. Setting this before the runOnQueueSync will cause
|
||||
// pending work to be cancelled and we won't have to wait for it.
|
||||
*m_destroyed = true;
|
||||
executorMessageQueueThread->runOnQueueSync([this, executorMessageQueueThread] {
|
||||
m_mainExecutor->destroy();
|
||||
executorMessageQueueThread->quitSynchronous();
|
||||
m_delegate->unregisterExecutor(*m_mainExecutor);
|
||||
m_mainExecutor = nullptr;
|
||||
m_executorMessageQueueThread->runOnQueueSync([this] {
|
||||
m_executor->destroy();
|
||||
m_executorMessageQueueThread->quitSynchronous();
|
||||
m_executor = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::runOnExecutorQueue(ExecutorToken executorToken, std::function<void(JSExecutor*)> task) {
|
||||
void NativeToJsBridge::runOnExecutorQueue(std::function<void(JSExecutor*)> task) {
|
||||
if (*m_destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto executorMessageQueueThread = getMessageQueueThread(executorToken);
|
||||
if (executorMessageQueueThread == nullptr) {
|
||||
LOG(WARNING) << "Dropping JS action for executor that has been unregistered...";
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<bool> isDestroyed = m_destroyed;
|
||||
executorMessageQueueThread->runOnQueue([this, isDestroyed, executorToken, task=std::move(task)] {
|
||||
m_executorMessageQueueThread->runOnQueue([this, isDestroyed, task=std::move(task)] {
|
||||
if (*isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSExecutor *executor = getExecutor(executorToken);
|
||||
if (executor == nullptr) {
|
||||
LOG(WARNING) << "Dropping JS call for executor that has been unregistered...";
|
||||
return;
|
||||
}
|
||||
|
||||
// The executor is guaranteed to be valid for the duration of the task because:
|
||||
// 1. the executor is only destroyed after it is unregistered
|
||||
// 2. the executor is unregistered on this queue
|
||||
// 3. we just confirmed that the executor hasn't been unregistered above
|
||||
task(executor);
|
||||
task(m_executor.get());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/Executor.h>
|
||||
#include <cxxreact/ExecutorToken.h>
|
||||
#include <cxxreact/JSCExecutor.h>
|
||||
#include <cxxreact/JSModulesUnbundle.h>
|
||||
#include <cxxreact/MessageQueueThread.h>
|
||||
@ -26,22 +25,9 @@ struct dynamic;
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct InstanceCallback;
|
||||
class ModuleRegistry;
|
||||
|
||||
class ExecutorRegistration {
|
||||
public:
|
||||
ExecutorRegistration(
|
||||
std::unique_ptr<JSExecutor> executor,
|
||||
std::shared_ptr<MessageQueueThread> executorMessageQueueThread) :
|
||||
executor_(std::move(executor)),
|
||||
messageQueueThread_(executorMessageQueueThread) {}
|
||||
|
||||
std::unique_ptr<JSExecutor> executor_;
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||
};
|
||||
|
||||
class JsToNativeBridge;
|
||||
struct InstanceCallback;
|
||||
|
||||
// This class manages calls from native code to JS. It also manages
|
||||
// executors and their threads. All functions here can be called from
|
||||
@ -68,16 +54,12 @@ public:
|
||||
* Executes a function with the module ID and method ID and any additional
|
||||
* arguments in JS.
|
||||
*/
|
||||
void callFunction(
|
||||
ExecutorToken executorToken,
|
||||
std::string&& module,
|
||||
std::string&& method,
|
||||
folly::dynamic&& args);
|
||||
void callFunction(std::string&& module, std::string&& method, folly::dynamic&& args);
|
||||
|
||||
/**
|
||||
* Invokes a callback with the cbID, and optional additional arguments in JS.
|
||||
*/
|
||||
void invokeCallback(ExecutorToken executorToken, double callbackId, folly::dynamic&& args);
|
||||
void invokeCallback(double callbackId, folly::dynamic&& args);
|
||||
|
||||
/**
|
||||
* Executes a JS method on the given executor synchronously, returning its
|
||||
@ -98,10 +80,10 @@ public:
|
||||
" after bridge is destroyed"));
|
||||
}
|
||||
|
||||
JSCExecutor *jscExecutor = dynamic_cast<JSCExecutor*>(m_mainExecutor);
|
||||
JSCExecutor *jscExecutor = dynamic_cast<JSCExecutor*>(m_executor.get());
|
||||
if (!jscExecutor) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("Executor type ", typeid(*m_mainExecutor).name(),
|
||||
folly::to<std::string>("Executor type ", typeid(m_executor.get()).name(),
|
||||
" does not support synchronous calls"));
|
||||
}
|
||||
|
||||
@ -131,56 +113,25 @@ public:
|
||||
void handleMemoryPressureModerate();
|
||||
void handleMemoryPressureCritical();
|
||||
|
||||
/**
|
||||
* Returns the ExecutorToken corresponding to the main JSExecutor.
|
||||
*/
|
||||
ExecutorToken getMainExecutorToken() const;
|
||||
|
||||
/**
|
||||
* Synchronously tears down the bridge and the main executor.
|
||||
*/
|
||||
void destroy();
|
||||
private:
|
||||
/**
|
||||
* Registers the given JSExecutor which runs on the given MessageQueueThread
|
||||
* with the NativeToJsBridge. Part of this registration is transfering
|
||||
* ownership of this JSExecutor to the NativeToJsBridge for the duration of
|
||||
* the registration.
|
||||
*
|
||||
* Returns a ExecutorToken which can be used to refer to this JSExecutor
|
||||
* in the NativeToJsBridge.
|
||||
*/
|
||||
ExecutorToken registerExecutor(
|
||||
ExecutorToken token,
|
||||
std::unique_ptr<JSExecutor> executor,
|
||||
std::shared_ptr<MessageQueueThread> executorMessageQueueThread);
|
||||
|
||||
/**
|
||||
* Unregisters a JSExecutor that was previously registered with this NativeToJsBridge
|
||||
* using registerExecutor.
|
||||
*/
|
||||
std::unique_ptr<JSExecutor> unregisterExecutor(JSExecutor& executorToken);
|
||||
|
||||
void runOnExecutorQueue(ExecutorToken token, std::function<void(JSExecutor*)> task);
|
||||
void runOnExecutorQueue(std::function<void(JSExecutor*)> task);
|
||||
|
||||
// This is used to avoid a race condition where a proxyCallback gets queued
|
||||
// after ~NativeToJsBridge(), on the same thread. In that case, the callback
|
||||
// will try to run the task on m_callback which will have been destroyed
|
||||
// within ~NativeToJsBridge(), thus causing a SIGSEGV.
|
||||
std::shared_ptr<bool> m_destroyed;
|
||||
JSExecutor* m_mainExecutor;
|
||||
ExecutorToken m_mainExecutorToken;
|
||||
std::shared_ptr<JsToNativeBridge> m_delegate;
|
||||
std::unordered_map<JSExecutor*, ExecutorToken> m_executorTokenMap;
|
||||
std::unordered_map<ExecutorToken, ExecutorRegistration> m_executorMap;
|
||||
std::mutex m_registrationMutex;
|
||||
std::unique_ptr<JSExecutor> m_executor;
|
||||
std::shared_ptr<MessageQueueThread> m_executorMessageQueueThread;
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
std::atomic_uint_least32_t m_systraceCookie = ATOMIC_VAR_INIT();
|
||||
#endif
|
||||
|
||||
MessageQueueThread* getMessageQueueThread(const ExecutorToken& executorToken);
|
||||
JSExecutor* getExecutor(const ExecutorToken& executorToken);
|
||||
ExecutorToken getTokenForExecutor(JSExecutor& executor);
|
||||
};
|
||||
|
||||
} }
|
||||
|
@ -9,12 +9,6 @@ namespace ReactMarker {
|
||||
LogMarker logMarker;
|
||||
};
|
||||
|
||||
namespace WebWorkerUtil {
|
||||
WebWorkerQueueFactory createWebWorkerThread;
|
||||
LoadScriptFromAssets loadScriptFromAssets;
|
||||
LoadScriptFromNetworkSync loadScriptFromNetworkSync;
|
||||
};
|
||||
|
||||
namespace PerfLogging {
|
||||
InstallNativeHooks installNativeHooks;
|
||||
};
|
||||
|
@ -27,17 +27,6 @@ using LogMarker = std::function<void(const ReactMarkerId)>;
|
||||
extern LogMarker logMarker;
|
||||
};
|
||||
|
||||
namespace WebWorkerUtil {
|
||||
using WebWorkerQueueFactory = std::function<std::unique_ptr<MessageQueueThread>(int id, MessageQueueThread* ownerMessageQueue)>;
|
||||
extern WebWorkerQueueFactory createWebWorkerThread;
|
||||
|
||||
using LoadScriptFromAssets = std::function<std::unique_ptr<const JSBigString>(const std::string& assetName)>;
|
||||
extern LoadScriptFromAssets loadScriptFromAssets;
|
||||
|
||||
using LoadScriptFromNetworkSync = std::function<std::string(const std::string& url, const std::string& tempfileName)>;
|
||||
extern LoadScriptFromNetworkSync loadScriptFromNetworkSync;
|
||||
};
|
||||
|
||||
namespace PerfLogging {
|
||||
using InstallNativeHooks = std::function<void(JSGlobalContextRef)>;
|
||||
extern InstallNativeHooks installNativeHooks;
|
||||
|
Loading…
x
Reference in New Issue
Block a user