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

Pass immutable arguments to JS to avoid JSC crash. #2714

Merged
merged 1 commit into from
Jul 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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