mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-29 21:46:07 +08:00
[ReactNative] Ensure JS calls scheduled by a deallocated context don't fire
This commit is contained in:
@@ -82,7 +82,7 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||||||
{
|
{
|
||||||
__block NSError *initError;
|
__block NSError *initError;
|
||||||
dispatch_semaphore_t s = dispatch_semaphore_create(0);
|
dispatch_semaphore_t s = dispatch_semaphore_create(0);
|
||||||
[self sendMessage:@{@"method": @"prepareJSRuntime"} waitForReply:^(NSError *error, NSDictionary *reply) {
|
[self sendMessage:@{@"method": @"prepareJSRuntime"} context:nil waitForReply:^(NSError *error, NSDictionary *reply) {
|
||||||
initError = error;
|
initError = error;
|
||||||
dispatch_semaphore_signal(s);
|
dispatch_semaphore_signal(s);
|
||||||
}];
|
}];
|
||||||
@@ -111,7 +111,7 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||||||
RCTLogError(@"WebSocket connection failed with error %@", error);
|
RCTLogError(@"WebSocket connection failed with error %@", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendMessage:(NSDictionary *)message waitForReply:(WSMessageCallback)callback
|
- (void)sendMessage:(NSDictionary *)message context:(NSNumber *)executorID waitForReply:(WSMessageCallback)callback
|
||||||
{
|
{
|
||||||
static NSUInteger lastID = 10000;
|
static NSUInteger lastID = 10000;
|
||||||
|
|
||||||
@@ -122,6 +122,8 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||||||
}];
|
}];
|
||||||
callback(error, nil);
|
callback(error, nil);
|
||||||
return;
|
return;
|
||||||
|
} else if (executorID && ![RCTGetExecutorID(self) isEqualToNumber:executorID]) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSNumber *expectedID = @(lastID++);
|
NSNumber *expectedID = @(lastID++);
|
||||||
@@ -135,12 +137,12 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||||||
- (void)executeApplicationScript:(NSString *)script sourceURL:(NSURL *)URL onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
- (void)executeApplicationScript:(NSString *)script sourceURL:(NSURL *)URL onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||||
{
|
{
|
||||||
NSDictionary *message = @{@"method": NSStringFromSelector(_cmd), @"url": [URL absoluteString], @"inject": _injectedObjects};
|
NSDictionary *message = @{@"method": NSStringFromSelector(_cmd), @"url": [URL absoluteString], @"inject": _injectedObjects};
|
||||||
[self sendMessage:message waitForReply:^(NSError *error, NSDictionary *reply) {
|
[self sendMessage:message context:nil waitForReply:^(NSError *error, NSDictionary *reply) {
|
||||||
onComplete(error);
|
onComplete(error);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)executeJSCall:(NSString *)name method:(NSString *)method arguments:(NSArray *)arguments callback:(RCTJavaScriptCallback)onComplete
|
- (void)executeJSCall:(NSString *)name method:(NSString *)method arguments:(NSArray *)arguments context:(NSNumber *)executorID callback:(RCTJavaScriptCallback)onComplete
|
||||||
{
|
{
|
||||||
RCTAssert(onComplete != nil, @"callback was missing for exec JS call");
|
RCTAssert(onComplete != nil, @"callback was missing for exec JS call");
|
||||||
NSDictionary *message = @{
|
NSDictionary *message = @{
|
||||||
@@ -149,7 +151,7 @@ typedef void (^WSMessageCallback)(NSError *error, NSDictionary *reply);
|
|||||||
@"moduleMethod": method,
|
@"moduleMethod": method,
|
||||||
@"arguments": arguments
|
@"arguments": arguments
|
||||||
};
|
};
|
||||||
[self sendMessage:message waitForReply:^(NSError *socketError, NSDictionary *reply) {
|
[self sendMessage:message context:executorID waitForReply:^(NSError *socketError, NSDictionary *reply) {
|
||||||
if (socketError) {
|
if (socketError) {
|
||||||
onComplete(nil, socketError);
|
onComplete(nil, socketError);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -234,12 +234,13 @@ static NSArray *RCTBridgeModuleClassesByModuleID(void)
|
|||||||
|
|
||||||
- (void)_invokeAndProcessModule:(NSString *)module
|
- (void)_invokeAndProcessModule:(NSString *)module
|
||||||
method:(NSString *)method
|
method:(NSString *)method
|
||||||
arguments:(NSArray *)args;
|
arguments:(NSArray *)args
|
||||||
|
context:(NSNumber *)context;
|
||||||
|
|
||||||
- (void)_actuallyInvokeAndProcessModule:(NSString *)module
|
- (void)_actuallyInvokeAndProcessModule:(NSString *)module
|
||||||
method:(NSString *)method
|
method:(NSString *)method
|
||||||
arguments:(NSArray *)args;
|
arguments:(NSArray *)args
|
||||||
|
context:(NSNumber *)context;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -338,7 +339,7 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName)
|
|||||||
NSMutableArray *argumentBlocks = [[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2];
|
NSMutableArray *argumentBlocks = [[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2];
|
||||||
|
|
||||||
#define RCT_ARG_BLOCK(_logic) \
|
#define RCT_ARG_BLOCK(_logic) \
|
||||||
[argumentBlocks addObject:^(RCTBridge *bridge, NSInvocation *invocation, NSUInteger index, id json) { \
|
[argumentBlocks addObject:^(RCTBridge *bridge, NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { \
|
||||||
_logic \
|
_logic \
|
||||||
[invocation setArgument:&value atIndex:index]; \
|
[invocation setArgument:&value atIndex:index]; \
|
||||||
}]; \
|
}]; \
|
||||||
@@ -355,7 +356,8 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName)
|
|||||||
__autoreleasing id value = (json ? ^(NSArray *args) {
|
__autoreleasing id value = (json ? ^(NSArray *args) {
|
||||||
[bridge _invokeAndProcessModule:@"BatchedBridge"
|
[bridge _invokeAndProcessModule:@"BatchedBridge"
|
||||||
method:@"invokeCallbackAndReturnFlushedQueue"
|
method:@"invokeCallbackAndReturnFlushedQueue"
|
||||||
arguments:@[json, args]];
|
arguments:@[json, args]
|
||||||
|
context:context];
|
||||||
} : ^(NSArray *unused) {});
|
} : ^(NSArray *unused) {});
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -477,6 +479,7 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName)
|
|||||||
- (void)invokeWithBridge:(RCTBridge *)bridge
|
- (void)invokeWithBridge:(RCTBridge *)bridge
|
||||||
module:(id)module
|
module:(id)module
|
||||||
arguments:(NSArray *)arguments
|
arguments:(NSArray *)arguments
|
||||||
|
context:(NSNumber *)context
|
||||||
{
|
{
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -503,8 +506,8 @@ static NSString *RCTStringUpToFirstArgument(NSString *methodName)
|
|||||||
NSUInteger index = 0;
|
NSUInteger index = 0;
|
||||||
for (id json in arguments) {
|
for (id json in arguments) {
|
||||||
id arg = (json == [NSNull null]) ? nil : json;
|
id arg = (json == [NSNull null]) ? nil : json;
|
||||||
void (^block)(RCTBridge *, NSInvocation *, NSUInteger, id) = _argumentBlocks[index];
|
void (^block)(RCTBridge *, NSNumber *, NSInvocation *, NSUInteger, id) = _argumentBlocks[index];
|
||||||
block(bridge, invocation, index + 2, arg);
|
block(bridge, context, invocation, index + 2, arg);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,7 +656,6 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName)
|
|||||||
return moduleConfig;
|
return moduleConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As above, but for local modules/methods, which represent JS classes
|
* As above, but for local modules/methods, which represent JS classes
|
||||||
* and methods that will be called by the native code via the bridge.
|
* and methods that will be called by the native code via the bridge.
|
||||||
@@ -801,7 +803,7 @@ static NSDictionary *RCTLocalModulesConfig()
|
|||||||
RCTDisplayLink *_displayLink;
|
RCTDisplayLink *_displayLink;
|
||||||
NSMutableSet *_frameUpdateObservers;
|
NSMutableSet *_frameUpdateObservers;
|
||||||
NSMutableArray *_scheduledCalls;
|
NSMutableArray *_scheduledCalls;
|
||||||
NSMutableArray *_scheduledCallbacks;
|
RCTSparseArray *_scheduledCallbacks;
|
||||||
BOOL _loading;
|
BOOL _loading;
|
||||||
|
|
||||||
NSUInteger _startingTime;
|
NSUInteger _startingTime;
|
||||||
@@ -829,13 +831,13 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
- (void)setUp
|
- (void)setUp
|
||||||
{
|
{
|
||||||
Class executorClass = _executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class];
|
Class executorClass = _executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class];
|
||||||
_javaScriptExecutor = [[executorClass alloc] init];
|
_javaScriptExecutor = RCTCreateExecutor(executorClass);
|
||||||
_latestJSExecutor = _javaScriptExecutor;
|
_latestJSExecutor = _javaScriptExecutor;
|
||||||
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
|
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
|
||||||
_displayLink = [[RCTDisplayLink alloc] initWithBridge:self];
|
_displayLink = [[RCTDisplayLink alloc] initWithBridge:self];
|
||||||
_frameUpdateObservers = [[NSMutableSet alloc] init];
|
_frameUpdateObservers = [[NSMutableSet alloc] init];
|
||||||
_scheduledCalls = [[NSMutableArray alloc] init];
|
_scheduledCalls = [[NSMutableArray alloc] init];
|
||||||
_scheduledCallbacks = [[NSMutableArray alloc] init];
|
_scheduledCallbacks = [[RCTSparseArray alloc] init];
|
||||||
|
|
||||||
// Register passed-in module instances
|
// Register passed-in module instances
|
||||||
NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init];
|
||||||
@@ -991,7 +993,6 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (NSDictionary *)modules
|
- (NSDictionary *)modules
|
||||||
{
|
{
|
||||||
RCTAssert(_modulesByName != nil, @"Bridge modules have not yet been initialized. "
|
RCTAssert(_modulesByName != nil, @"Bridge modules have not yet been initialized. "
|
||||||
@@ -1072,7 +1073,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
if (!_loading) {
|
if (!_loading) {
|
||||||
[self _invokeAndProcessModule:@"BatchedBridge"
|
[self _invokeAndProcessModule:@"BatchedBridge"
|
||||||
method:@"callFunctionReturnFlushedQueue"
|
method:@"callFunctionReturnFlushedQueue"
|
||||||
arguments:@[moduleID, methodID, args ?: @[]]];
|
arguments:@[moduleID, methodID, args ?: @[]]
|
||||||
|
context:RCTGetExecutorID(_javaScriptExecutor)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1093,13 +1095,15 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
#if BATCHED_BRIDGE
|
#if BATCHED_BRIDGE
|
||||||
[self _actuallyInvokeAndProcessModule:@"BatchedBridge"
|
[self _actuallyInvokeAndProcessModule:@"BatchedBridge"
|
||||||
method:@"callFunctionReturnFlushedQueue"
|
method:@"callFunctionReturnFlushedQueue"
|
||||||
arguments:@[moduleID, methodID, @[@[timer]]]];
|
arguments:@[moduleID, methodID, @[@[timer]]]
|
||||||
|
context:RCTGetExecutorID(_javaScriptExecutor)];
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
[self _invokeAndProcessModule:@"BatchedBridge"
|
[self _invokeAndProcessModule:@"BatchedBridge"
|
||||||
method:@"callFunctionReturnFlushedQueue"
|
method:@"callFunctionReturnFlushedQueue"
|
||||||
arguments:@[moduleID, methodID, @[@[timer]]]];
|
arguments:@[moduleID, methodID, @[@[timer]]]
|
||||||
|
context:RCTGetExecutorID(_javaScriptExecutor)];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1112,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
{
|
{
|
||||||
RCTAssert(onComplete != nil, @"onComplete block passed in should be non-nil");
|
RCTAssert(onComplete != nil, @"onComplete block passed in should be non-nil");
|
||||||
RCT_PROFILE_START();
|
RCT_PROFILE_START();
|
||||||
|
NSNumber *context = RCTGetExecutorID(_javaScriptExecutor);
|
||||||
[_javaScriptExecutor executeApplicationScript:script sourceURL:url onComplete:^(NSError *scriptLoadError) {
|
[_javaScriptExecutor executeApplicationScript:script sourceURL:url onComplete:^(NSError *scriptLoadError) {
|
||||||
RCT_PROFILE_END(js_call, scriptLoadError, @"initial_script");
|
RCT_PROFILE_END(js_call, scriptLoadError, @"initial_script");
|
||||||
if (scriptLoadError) {
|
if (scriptLoadError) {
|
||||||
@@ -1119,10 +1124,11 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
[_javaScriptExecutor executeJSCall:@"BatchedBridge"
|
[_javaScriptExecutor executeJSCall:@"BatchedBridge"
|
||||||
method:@"flushedQueue"
|
method:@"flushedQueue"
|
||||||
arguments:@[]
|
arguments:@[]
|
||||||
|
context:context
|
||||||
callback:^(id json, NSError *error) {
|
callback:^(id json, NSError *error) {
|
||||||
RCT_PROFILE_END(js_call, error, @"initial_call", @"BatchedBridge.flushedQueue");
|
RCT_PROFILE_END(js_call, error, @"initial_call", @"BatchedBridge.flushedQueue");
|
||||||
RCT_PROFILE_START();
|
RCT_PROFILE_START();
|
||||||
[self _handleBuffer:json];
|
[self _handleBuffer:json context:context];
|
||||||
RCT_PROFILE_END(objc_call, json, @"batched_js_calls");
|
RCT_PROFILE_END(objc_call, json, @"batched_js_calls");
|
||||||
onComplete(error);
|
onComplete(error);
|
||||||
}];
|
}];
|
||||||
@@ -1131,7 +1137,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
|
|
||||||
#pragma mark - Payload Generation
|
#pragma mark - Payload Generation
|
||||||
|
|
||||||
- (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args
|
- (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context
|
||||||
{
|
{
|
||||||
#if BATCHED_BRIDGE
|
#if BATCHED_BRIDGE
|
||||||
RCT_PROFILE_START();
|
RCT_PROFILE_START();
|
||||||
@@ -1148,10 +1154,11 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
@"module": module,
|
@"module": module,
|
||||||
@"method": method,
|
@"method": method,
|
||||||
@"args": args,
|
@"args": args,
|
||||||
|
@"context": context ?: @0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if ([method isEqualToString:@"invokeCallbackAndReturnFlushedQueue"]) {
|
if ([method isEqualToString:@"invokeCallbackAndReturnFlushedQueue"]) {
|
||||||
[_scheduledCallbacks addObject:call];
|
_scheduledCallbacks[args[0]] = call;
|
||||||
} else {
|
} else {
|
||||||
[_scheduledCalls addObject:call];
|
[_scheduledCalls addObject:call];
|
||||||
}
|
}
|
||||||
@@ -1159,7 +1166,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
RCT_PROFILE_END(js_call, args, @"schedule", module, method);
|
RCT_PROFILE_END(js_call, args, @"schedule", module, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_actuallyInvokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args
|
- (void)_actuallyInvokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil];
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil];
|
||||||
@@ -1171,19 +1178,20 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
RCT_PROFILE_END(js_call, args, moduleDotMethod);
|
RCT_PROFILE_END(js_call, args, moduleDotMethod);
|
||||||
|
|
||||||
RCT_PROFILE_START();
|
RCT_PROFILE_START();
|
||||||
[self _handleBuffer:json];
|
[self _handleBuffer:json context:context];
|
||||||
RCT_PROFILE_END(objc_call, json, @"batched_js_calls");
|
RCT_PROFILE_END(objc_call, json, @"batched_js_calls");
|
||||||
};
|
};
|
||||||
|
|
||||||
[_javaScriptExecutor executeJSCall:module
|
[_javaScriptExecutor executeJSCall:module
|
||||||
method:method
|
method:method
|
||||||
arguments:args
|
arguments:args
|
||||||
|
context:context
|
||||||
callback:processResponse];
|
callback:processResponse];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Payload Processing
|
#pragma mark - Payload Processing
|
||||||
|
|
||||||
- (void)_handleBuffer:(id)buffer
|
- (void)_handleBuffer:(id)buffer context:(NSNumber *)context
|
||||||
{
|
{
|
||||||
if (buffer == nil || buffer == (id)kCFNull) {
|
if (buffer == nil || buffer == (id)kCFNull) {
|
||||||
return;
|
return;
|
||||||
@@ -1228,7 +1236,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
[self _handleRequestNumber:i
|
[self _handleRequestNumber:i
|
||||||
moduleID:[moduleIDs[i] integerValue]
|
moduleID:[moduleIDs[i] integerValue]
|
||||||
methodID:[methodIDs[i] integerValue]
|
methodID:[methodIDs[i] integerValue]
|
||||||
params:paramsArrays[i]];
|
params:paramsArrays[i]
|
||||||
|
context:context];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,6 +1256,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
moduleID:(NSUInteger)moduleID
|
moduleID:(NSUInteger)moduleID
|
||||||
methodID:(NSUInteger)methodID
|
methodID:(NSUInteger)methodID
|
||||||
params:(NSArray *)params
|
params:(NSArray *)params
|
||||||
|
context:(NSNumber *)context
|
||||||
{
|
{
|
||||||
if (![params isKindOfClass:[NSArray class]]) {
|
if (![params isKindOfClass:[NSArray class]]) {
|
||||||
RCTLogError(@"Invalid module/method/params tuple for request #%zd", i);
|
RCTLogError(@"Invalid module/method/params tuple for request #%zd", i);
|
||||||
@@ -1280,7 +1290,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
[method invokeWithBridge:strongSelf module:module arguments:params];
|
[method invokeWithBridge:strongSelf module:module arguments:params context:context];
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, module, params, exception);
|
||||||
@@ -1313,13 +1323,18 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
{
|
{
|
||||||
#if BATCHED_BRIDGE
|
#if BATCHED_BRIDGE
|
||||||
|
|
||||||
NSArray *calls = [_scheduledCallbacks arrayByAddingObjectsFromArray:_scheduledCalls];
|
NSArray *calls = [_scheduledCallbacks.allObjects arrayByAddingObjectsFromArray:_scheduledCalls];
|
||||||
|
NSNumber *currentExecutorID = RCTGetExecutorID(_javaScriptExecutor);
|
||||||
|
calls = [calls filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSDictionary *call, NSDictionary *bindings) {
|
||||||
|
return [call[@"context"] isEqualToNumber:currentExecutorID];
|
||||||
|
}]];
|
||||||
if (calls.count > 0) {
|
if (calls.count > 0) {
|
||||||
_scheduledCalls = [[NSMutableArray alloc] init];
|
_scheduledCalls = [[NSMutableArray alloc] init];
|
||||||
_scheduledCallbacks = [[NSMutableArray alloc] init];
|
_scheduledCallbacks = [[RCTSparseArray alloc] init];
|
||||||
[self _actuallyInvokeAndProcessModule:@"BatchedBridge"
|
[self _actuallyInvokeAndProcessModule:@"BatchedBridge"
|
||||||
method:@"processBatch"
|
method:@"processBatch"
|
||||||
arguments:@[calls]];
|
arguments:@[calls]
|
||||||
|
context:RCTGetExecutorID(_javaScriptExecutor)];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1357,6 +1372,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||||||
[_latestJSExecutor executeJSCall:@"RCTLog"
|
[_latestJSExecutor executeJSCall:@"RCTLog"
|
||||||
method:@"logIfNoNativeHook"
|
method:@"logIfNoNativeHook"
|
||||||
arguments:@[level, message]
|
arguments:@[level, message]
|
||||||
|
context:RCTGetExecutorID(_latestJSExecutor)
|
||||||
callback:^(id json, NSError *error) {}];
|
callback:^(id json, NSError *error) {}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
#import <JavaScriptCore/JavaScriptCore.h>
|
#import <JavaScriptCore/JavaScriptCore.h>
|
||||||
|
|
||||||
#import "RCTInvalidating.h"
|
#import "RCTInvalidating.h"
|
||||||
@@ -27,6 +29,7 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error);
|
|||||||
- (void)executeJSCall:(NSString *)name
|
- (void)executeJSCall:(NSString *)name
|
||||||
method:(NSString *)method
|
method:(NSString *)method
|
||||||
arguments:(NSArray *)arguments
|
arguments:(NSArray *)arguments
|
||||||
|
context:(NSNumber *)executorID
|
||||||
callback:(RCTJavaScriptCallback)onComplete;
|
callback:(RCTJavaScriptCallback)onComplete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,3 +43,17 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error);
|
|||||||
asGlobalObjectNamed:(NSString *)objectName
|
asGlobalObjectNamed:(NSString *)objectName
|
||||||
callback:(RCTJavaScriptCompleteBlock)onComplete;
|
callback:(RCTJavaScriptCompleteBlock)onComplete;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static const char *RCTJavaScriptExecutorID = "RCTJavaScriptExecutorID";
|
||||||
|
__used static id<RCTJavaScriptExecutor> RCTCreateExecutor(Class executorClass)
|
||||||
|
{
|
||||||
|
static NSUInteger executorID = 0;
|
||||||
|
id<RCTJavaScriptExecutor> executor = [[executorClass alloc] init];
|
||||||
|
objc_setAssociatedObject(executor, RCTJavaScriptExecutorID, @(++executorID), OBJC_ASSOCIATION_RETAIN);
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
__used static NSNumber *RCTGetExecutorID(id<RCTJavaScriptExecutor> executor)
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(executor, RCTJavaScriptExecutorID);
|
||||||
|
}
|
||||||
|
|||||||
@@ -140,9 +140,9 @@
|
|||||||
sourceCodeModule.scriptURL = scriptURL;
|
sourceCodeModule.scriptURL = scriptURL;
|
||||||
sourceCodeModule.scriptText = rawText;
|
sourceCodeModule.scriptText = rawText;
|
||||||
|
|
||||||
[_bridge enqueueApplicationScript:rawText url:scriptURL onComplete:^(NSError *_error) {
|
[_bridge enqueueApplicationScript:rawText url:scriptURL onComplete:^(NSError *scriptError) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
onComplete(_error);
|
onComplete(scriptError);
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -229,13 +229,14 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
|||||||
- (void)executeJSCall:(NSString *)name
|
- (void)executeJSCall:(NSString *)name
|
||||||
method:(NSString *)method
|
method:(NSString *)method
|
||||||
arguments:(NSArray *)arguments
|
arguments:(NSArray *)arguments
|
||||||
|
context:(NSNumber *)executorID
|
||||||
callback:(RCTJavaScriptCallback)onComplete
|
callback:(RCTJavaScriptCallback)onComplete
|
||||||
{
|
{
|
||||||
RCTAssert(onComplete != nil, @"onComplete block should not be nil");
|
RCTAssert(onComplete != nil, @"onComplete block should not be nil");
|
||||||
__weak RCTContextExecutor *weakSelf = self;
|
__weak RCTContextExecutor *weakSelf = self;
|
||||||
[self executeBlockOnJavaScriptQueue:^{
|
[self executeBlockOnJavaScriptQueue:^{
|
||||||
RCTContextExecutor *strongSelf = weakSelf;
|
RCTContextExecutor *strongSelf = weakSelf;
|
||||||
if (!strongSelf || !strongSelf.isValid) {
|
if (!strongSelf || !strongSelf.isValid || ![RCTGetExecutorID(strongSelf) isEqualToNumber:executorID]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
|||||||
@@ -76,10 +76,15 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||||||
- (void)executeJSCall:(NSString *)name
|
- (void)executeJSCall:(NSString *)name
|
||||||
method:(NSString *)method
|
method:(NSString *)method
|
||||||
arguments:(NSArray *)arguments
|
arguments:(NSArray *)arguments
|
||||||
|
context:(NSNumber *)executorID
|
||||||
callback:(RCTJavaScriptCallback)onComplete
|
callback:(RCTJavaScriptCallback)onComplete
|
||||||
{
|
{
|
||||||
RCTAssert(onComplete != nil, @"");
|
RCTAssert(onComplete != nil, @"");
|
||||||
[self executeBlockOnJavaScriptQueue:^{
|
[self executeBlockOnJavaScriptQueue:^{
|
||||||
|
if (!self.isValid || ![RCTGetExecutorID(self) isEqualToNumber:executorID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
NSString *argsString = RCTJSONStringify(arguments, &error);
|
NSString *argsString = RCTJSONStringify(arguments, &error);
|
||||||
if (!argsString) {
|
if (!argsString) {
|
||||||
|
|||||||
Reference in New Issue
Block a user