This is an automated email from the ASF dual-hosted git repository.

jianhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new c371398  Pass immutable arguments to JS to avoid JSC crash. (#2714)
c371398 is described below

commit c371398f9a802ee815abfe4c5c8e0751de99a488
Author: wqyfavor <[email protected]>
AuthorDate: Tue Jul 16 18:04:50 2019 +0800

    Pass immutable arguments to JS to avoid JSC crash. (#2714)
---
 ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m  | 18 ++++++++--------
 ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h   |  2 +-
 ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m   |  6 +++---
 ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm  | 26 +++++++++++++++++++++++
 ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m      |  2 +-
 ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m | 10 +++++++--
 ios/sdk/WeexSDK/Sources/Utility/WXUtility.h       |  8 +++++++
 ios/sdk/WeexSDK/Sources/Utility/WXUtility.m       | 24 +++++++++++++++++++++
 8 files changed, 80 insertions(+), 16 deletions(-)

diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m 
b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index fabc1fe..e351ef0 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -510,7 +510,10 @@ _Pragma("clang diagnostic pop") \
         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;
@@ -536,7 +539,8 @@ _Pragma("clang diagnostic pop") \
             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",
@@ -544,7 +548,7 @@ _Pragma("clang diagnostic pop") \
                                                                  
@"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];
                 }
@@ -929,10 +933,6 @@ _Pragma("clang diagnostic pop") \
         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") ]) ) {
@@ -1100,9 +1100,9 @@ _Pragma("clang diagnostic pop") \
         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;
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h 
b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h
index 366efe1..40c9f9a 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.h
@@ -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
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m 
b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m
index f50ad2b..0cbf9bb 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeMethod.m
@@ -32,7 +32,7 @@
 {
     if (self = [super init]) {
         _methodName = methodName;
-        _arguments = [NSMutableArray arrayWithArray:arguments];
+        _arguments = arguments ? [arguments copy] : @[];
         _instance = instance;
     }
     
@@ -124,8 +124,8 @@
         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
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm 
b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
index 5283bda..9293fa5 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
@@ -114,9 +114,35 @@
     [_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];
 }
 
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m 
b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index 12c4cc4..ad181ac 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -315,7 +315,7 @@ static NSDictionary *_customEnvironment = nil;
 + (void)setCustomEnvironment:(NSDictionary *)environment
 {
     @synchronized (self) {
-        _customEnvironment = environment;
+        _customEnvironment = [environment copy];
     }
 }
 
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m 
b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index 9b5cfae..4cab6a6 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -36,6 +36,7 @@
 #import "WXCoreBridge.h"
 #import "WXDataRenderHandler.h"
 #import "WXHandlerFactory.h"
+#import "WXUtility.h"
 
 @interface WXBridgeManager ()
 
@@ -483,6 +484,8 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void 
(^block) (void), NSString*
 {
     if (!modules) return;
     
+    modules = [WXUtility convertContainerToImmutable:modules];
+    
     __weak typeof(self) weakSelf = self;
     WXPerformBlockOnBridgeThread(^(){
         [weakSelf.bridgeCtx registerModules:modules];
@@ -496,6 +499,8 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void 
(^block) (void), NSString*
 {
     if (!components) return;
     
+    components = [WXUtility convertContainerToImmutable:components];
+    
     __weak typeof(self) weakSelf = self;
     WXPerformBlockOnBridgeThread(^(){
         [weakSelf.bridgeCtx registerComponents:components];
@@ -558,7 +563,7 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void 
(^block) (void), NSString*
         [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];
 }
 
@@ -622,7 +627,8 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void 
(^block) (void), NSString*
     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
 {
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h 
b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 71c77d5..d3636ec 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -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]
 
 /**
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m 
b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
index 28119f0..87d16f0 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
@@ -259,6 +259,30 @@ CGFloat WXFloorPixelValue(CGFloat value)
     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;

Reply via email to