Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Commit

Permalink
Pass immutable arguments to JS to avoid JSC crash. (#2714)
Browse files Browse the repository at this point in the history
  • Loading branch information
wqyfavor authored and jianhan-he committed Jul 16, 2019
1 parent 3481119 commit c371398
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 16 deletions.
18 changes: 9 additions & 9 deletions ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
Expand Up @@ -510,7 +510,10 @@ - (void)createInstance:(NSString *)instanceIdString
if (!options) {
newOptions = [NSMutableDictionary new];
}
[newOptions addEntriesFromDictionary:@{@"env":[WXUtility getEnvironment]}];
NSDictionary* immutableEnvDict = [[WXUtility getEnvironment] copy];
if (immutableEnvDict) {
[newOptions addEntriesFromDictionary:@{@"env":immutableEnvDict}];
}
newOptions[@"bundleType"] = bundleType;
__block NSString *raxAPIScript = nil;
__block NSString *raxAPIScriptPath = nil;
Expand All @@ -536,15 +539,16 @@ - (void)createInstance:(NSString *)instanceIdString
WX_MONITOR_INSTANCE_PERF_END(WXPTJSCreateInstance, [WXSDKManager instanceForID:instanceIdString]);
[sdkInstance.apmInstance onStage:KEY_PAGE_STAGES_EXECUTE_BUNDLE_END];
} else {
sdkInstance.callCreateInstanceContext = [NSString stringWithFormat:@"instanceId:%@\noptions:%@\ndata:%@", instanceIdString, newOptions, data];
NSDictionary* immutableOptions = [newOptions copy];
sdkInstance.callCreateInstanceContext = [NSString stringWithFormat:@"instanceId:%@\noptions:%@\ndata:%@", instanceIdString, immutableOptions, data];
//add instanceId to weexContext ,if fucn createInstanceContext failure ,then we will know which instance has problem (exceptionhandler)
self.jsBridge.javaScriptContext[@"wxExtFuncInfo"]= @{
@"func":@"createInstanceContext",
@"arg":@"start",
@"instanceId":sdkInstance.instanceId?:@"unknownId"
};
__weak typeof(self) weakSelf = self;
[self callJSMethod:@"createInstanceContext" args:@[instanceIdString, newOptions, data?:@[]] onContext:nil completion:^(JSValue *instanceContextEnvironment) {
[self callJSMethod:@"createInstanceContext" args:@[instanceIdString, immutableOptions, data?:@[]] onContext:nil completion:^(JSValue *instanceContextEnvironment) {
if (sdkInstance.pageName) {
[sdkInstance.instanceJavaScriptContext.javaScriptContext setName:sdkInstance.pageName];
}
Expand Down Expand Up @@ -929,10 +933,6 @@ - (void)callJSMethod:(NSString *)method args:(NSArray *)args onContext:(id<WXBri
bridge = self.jsBridge;
}
if (self.frameworkLoadFinished) {
newArg = [args mutableCopy];
if ([newArg containsObject:completion]) {
[newArg removeObject:completion];
}
WXLogDebug(@"Calling JS... method:%@, args:%@", method, args);
if (([bridge isKindOfClass:[WXJSCoreBridge class]]) ||
([bridge isKindOfClass:NSClassFromString(@"WXDebugger") ]) ) {
Expand Down Expand Up @@ -1100,9 +1100,9 @@ - (void)_sendQueueLoop
NSTimeInterval start = CACurrentMediaTime()*1000;

if (execInstance.instanceJavaScriptContext && execInstance.bundleType) {
[self callJSMethod:@"__WEEX_CALL_JAVASCRIPT__" args:@[execIns, tasks] onContext:execInstance.instanceJavaScriptContext completion:nil];
[self callJSMethod:@"__WEEX_CALL_JAVASCRIPT__" args:@[execIns, [tasks copy]] onContext:execInstance.instanceJavaScriptContext completion:nil];
} else {
[self callJSMethod:@"callJS" args:@[execIns, tasks]];
[self callJSMethod:@"callJS" args:@[execIns, [tasks copy]]];
}
if (execInstance && !(execInstance.isJSCreateFinish)) {
NSTimeInterval diff = CACurrentMediaTime()*1000 - start;
Expand Down
2 changes: 1 addition & 1 deletion ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h
Expand Up @@ -23,7 +23,7 @@
@interface WXBridgeMethod : NSObject

@property (nonatomic, strong, readonly) NSString *methodName;
@property (nonatomic, copy, readonly) NSMutableArray *arguments;
@property (nonatomic, copy, readonly) NSArray *arguments;
@property (nonatomic, weak, readonly) WXSDKInstance *instance;

- (instancetype)initWithMethodName:(NSString *)methodName
Expand Down
6 changes: 3 additions & 3 deletions ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m
Expand Up @@ -32,7 +32,7 @@ - (instancetype)initWithMethodName:(NSString *)methodName arguments:(NSArray *)a
{
if (self = [super init]) {
_methodName = methodName;
_arguments = [NSMutableArray arrayWithArray:arguments];
_arguments = arguments ? [arguments copy] : @[];
_instance = instance;
}

Expand Down Expand Up @@ -124,8 +124,8 @@ - (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector
id argument;
if (!strcmp(parameterType, blockType)) {
// callback
argument = [^void(NSString *result, BOOL keepAlive) {
[[WXSDKManager bridgeMgr] callBack:instanceId funcId:(NSString *)obj params:result keepAlive:keepAlive];
argument = [^void(id result, BOOL keepAlive) {
[[WXSDKManager bridgeMgr] callBack:instanceId funcId:(NSString *)obj params:[WXUtility convertContainerToImmutable:result] keepAlive:keepAlive];
} copy];

// retain block
Expand Down
26 changes: 26 additions & 0 deletions ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
Expand Up @@ -114,9 +114,35 @@ - (void)executeJSFramework:(NSString *)frameworkScript
[_jsContext evaluateScript:frameworkScript withSourceURL:[NSURL URLWithString:@"weex-main-jsfm.js"]];
}

//static void __checkMutable(id container) {
// if ([container isKindOfClass:[NSArray class]]) {
// if ([container isKindOfClass:[NSMutableArray class]]) {
// printf("This is mutable.");
// }
// else {
// NSUInteger count = [container count];
// for (NSUInteger index = 0; index < count; ++index) {
// __checkMutable(container[index]);
// }
// }
// }
// else if ([container isKindOfClass:[NSDictionary class]]) {
// if ([container isKindOfClass:[NSMutableDictionary class]]) {
// printf("This is mutable.");
// }
// else {
// NSArray* allKeys = [container allKeys];
// for (id key in allKeys) {
// __checkMutable(container[key]);
// }
// }
// }
//}

- (JSValue *)callJSMethod:(NSString *)method args:(NSArray *)args
{
WXLogDebug(@"Calling JS... method:%@, args:%@", method, args);
// __checkMutable(args);
return [[_jsContext globalObject] invokeMethod:method withArguments:args];
}

Expand Down
2 changes: 1 addition & 1 deletion ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
Expand Up @@ -315,7 +315,7 @@ + (WXSDKInstance *)topInstance
+ (void)setCustomEnvironment:(NSDictionary *)environment
{
@synchronized (self) {
_customEnvironment = environment;
_customEnvironment = [environment copy];
}
}

Expand Down
10 changes: 8 additions & 2 deletions ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
Expand Up @@ -36,6 +36,7 @@
#import "WXCoreBridge.h"
#import "WXDataRenderHandler.h"
#import "WXHandlerFactory.h"
#import "WXUtility.h"

@interface WXBridgeManager ()

Expand Down Expand Up @@ -483,6 +484,8 @@ - (void)registerModules:(NSDictionary *)modules
{
if (!modules) return;

modules = [WXUtility convertContainerToImmutable:modules];

__weak typeof(self) weakSelf = self;
WXPerformBlockOnBridgeThread(^(){
[weakSelf.bridgeCtx registerModules:modules];
Expand All @@ -496,6 +499,8 @@ - (void)registerComponents:(NSArray *)components
{
if (!components) return;

components = [WXUtility convertContainerToImmutable:components];

__weak typeof(self) weakSelf = self;
WXPerformBlockOnBridgeThread(^(){
[weakSelf.bridgeCtx registerComponents:components];
Expand Down Expand Up @@ -558,7 +563,7 @@ - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)ty
[instance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_EVENT_NUM withDiffValue:1];
}

WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance];
WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:[WXUtility convertContainerToImmutable:args] instance:instance];
[self callJsMethod:method];
}

Expand Down Expand Up @@ -622,7 +627,8 @@ - (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)par
else {
WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:@"jsBridge" methodName:@"callback" arguments:args instance:instance];
[self callJsMethod:method];
}}
}
}

- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)params
{
Expand Down
8 changes: 8 additions & 0 deletions ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
Expand Up @@ -159,6 +159,14 @@ _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
*/
+ (id _Nullable)objectFromJSON:(NSString * _Nonnull)json;

/**
Convert all sub-structure objects of source to immutable container.
@param source Source object.
@return Converted object using immutable container.
*/
+ (id _Nullable)convertContainerToImmutable:(id _Nullable)source;

#define WXDecodeJson(json) [WXUtility objectFromJSON:json]

/**
Expand Down
24 changes: 24 additions & 0 deletions ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
Expand Up @@ -259,6 +259,30 @@ + (id)objectFromJSON:(NSString *)json
return [self JSONObject:[json dataUsingEncoding:NSUTF8StringEncoding] error:nil];
}

+ (id _Nullable)convertContainerToImmutable:(id _Nullable)source
{
if (source == nil) {
return nil;
}

if ([source isKindOfClass:[NSArray class]]) {
NSMutableArray* tmpArray = [[NSMutableArray alloc] init];
for (id obj in source) {
[tmpArray addObject:[self convertContainerToImmutable:obj]];
}
return [NSArray arrayWithArray:tmpArray];
}
else if ([source isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary* tmpDictionary = [[NSMutableDictionary alloc] init];
for (id key in [source keyEnumerator]) {
tmpDictionary[key] = [self convertContainerToImmutable:[source objectForKey:key]];
}
return [NSDictionary dictionaryWithDictionary:tmpDictionary];
}

return source;
}

+ (id)JSONObject:(NSData*)data error:(NSError **)error
{
if (!data) return nil;
Expand Down

0 comments on commit c371398

Please sign in to comment.