* [iOS] support multi-context

Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/492663a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/492663a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/492663a9

Branch: refs/heads/master
Commit: 492663a960efb1b56332431f026c4aeb65e9cea1
Parents: bfd1d31
Author: acton393 <zhangxing610...@gmail.com>
Authored: Tue Dec 12 14:58:51 2017 +0800
Committer: acton393 <zhangxing610...@gmail.com>
Committed: Wed Dec 20 17:44:28 2017 +0800

----------------------------------------------------------------------
 .../WeexSDK/Sources/Bridge/WXBridgeContext.m    | 168 +++++++++++++++++--
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m   |  12 ++
 .../Sources/Model/WXSDKInstance_private.h       |   2 +
 3 files changed, 167 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/492663a9/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m 
b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index 24801cc..46a9dc7 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -41,6 +41,11 @@
 #import "WXPrerenderManager.h"
 #import "WXTracingManager.h"
 #import "WXExceptionUtils.h"
+#import "WXSDKEngine.h"
+#import "WXPolyfillSet.h"
+#import "WXJSExceptionProtocol.h"
+#import "WXMonitor.h"
+#import "WXAppMonitorProtocol.h"
 
 #define SuppressPerformSelectorLeakWarning(Stuff) \
 do { \
@@ -416,36 +421,54 @@ _Pragma("clang diagnostic pop") \
     return 1;
 }
 
-- (void)createInstance:(NSString *)instance
-              template:(NSString *)temp
+- (void)createInstance:(NSString *)instanceIdString
+              template:(NSString *)jsBundleString
                options:(NSDictionary *)options
                   data:(id)data
 {
     WXAssertBridgeThread();
-    WXAssertParam(instance);
+    WXAssertParam(instanceIdString);
     
-    if (![self.insStack containsObject:instance]) {
+    if (![self.insStack containsObject:instanceIdString]) {
         if ([options[@"RENDER_IN_ORDER"] boolValue]) {
-            [self.insStack addObject:instance];
+            [self.insStack addObject:instanceIdString];
         } else {
-            [self.insStack insertObject:instance atIndex:0];
+            [self.insStack insertObject:instanceIdString atIndex:0];
         }
     }
     
     //create a sendQueue bind to the current instance
     NSMutableArray *sendQueue = [NSMutableArray array];
-    [self.sendQueue setValue:sendQueue forKey:instance];
-    
+    [self.sendQueue setValue:sendQueue forKey:instanceIdString];
     NSArray *args = nil;
-    if (data){
-        args = @[instance, temp, options ?: @{}, data];
+    NSString * bundleType = @"Vue"; // bundleType can be Vue and Rax.
+    WX_MONITOR_INSTANCE_PERF_START(WXFirstScreenJSFExecuteTime, [WXSDKManager 
instanceForID:instanceIdString]);
+    WX_MONITOR_INSTANCE_PERF_START(WXPTJSCreateInstance, [WXSDKManager 
instanceForID:instanceIdString]);
+    __weak typeof(self) weakSelf = self;
+    JSContext *globalContex = ([(JSContext*)weakSelf.jsBridge 
valueForKey:@"jsContext"]);
+   
+    if (bundleType) {
+        [self callJSMethod:@"createInstanceContext" args:@[instanceIdString, 
@{@"bundleType":bundleType}, data?:@[]] onContext:globalContex 
completion:^(JSValue *instanceContextEnvironment) {
+             WXSDKInstance *sdkInstance = [WXSDKManager 
instanceForID:instanceIdString];
+            JSContextGroupRef contextGroup = JSContextGetGroup([globalContex 
JSGlobalContextRef]);
+            JSClassDefinition classDefinition = kJSClassDefinitionEmpty;
+            classDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+            JSClassRef globalObjectClass = JSClassCreate(&classDefinition);
+            JSGlobalContextRef sandboxGlobalContextRef = 
JSGlobalContextCreateInGroup(contextGroup, globalObjectClass);
+            JSObjectRef sandBoxGlobalObjectRef = 
JSContextGetGlobalObject(sandboxGlobalContextRef);
+            JSObjectSetPrototype(sandboxGlobalContextRef, 
sandBoxGlobalObjectRef, [instanceContextEnvironment JSValueRef]);
+            sdkInstance.instanceJavaScriptContext = [JSContext 
contextWithJSGlobalContextRef:sandboxGlobalContextRef];
+            [sdkInstance.instanceJavaScriptContext 
evaluateScript:jsBundleString];
+        }];
     } else {
-        args = @[instance, temp, options ?: @{}];
+        if (data){
+            args = @[instanceIdString, jsBundleString, options ?: @{}, data];
+        } else {
+            args = @[instanceIdString, jsBundleString, options ?: @{}];
+        }
+        [self callJSMethod:@"createInstance" args:args];
     }
-    WX_MONITOR_INSTANCE_PERF_START(WXFirstScreenJSFExecuteTime, [WXSDKManager 
instanceForID:instance]);
-    WX_MONITOR_INSTANCE_PERF_START(WXPTJSCreateInstance, [WXSDKManager 
instanceForID:instance]);
-    [self callJSMethod:@"createInstance" args:args];
-    WX_MONITOR_INSTANCE_PERF_END(WXPTJSCreateInstance, [WXSDKManager 
instanceForID:instance]);
+    WX_MONITOR_INSTANCE_PERF_END(WXPTJSCreateInstance, [WXSDKManager 
instanceForID:instanceIdString]);
 }
 
 - (void)destroyInstance:(NSString *)instance
@@ -467,6 +490,8 @@ _Pragma("clang diagnostic pop") \
     }
     
     [self callJSMethod:@"destroyInstance" args:@[instance]];
+    WXSDKInstance *sdkIntance = [WXSDKManager instanceForID:instance];
+    sdkIntance.instanceJavaScriptContext = NULL;
 }
 
 - (void)forceGarbageCollection
@@ -613,6 +638,27 @@ _Pragma("clang diagnostic pop") \
     }
 }
 
+- (void)callJSMethod:(NSString *)method args:(NSArray *)args 
onContext:(JSContext*)context completion:(void (^)(JSValue * value))complection
+{
+    NSMutableArray *newArg = nil;
+    if (self.frameworkLoadFinished) {
+        newArg = [args mutableCopy];
+        if ([newArg containsObject:complection]) {
+            [newArg removeObject:complection];
+        }
+        WXLogDebug(@"Calling JS... method:%@, args:%@", method, args);
+        JSValue *value = [[context globalObject] invokeMethod:method 
withArguments:args];
+        complection(value);
+    } else {
+        newArg = [args mutableCopy];
+        if (complection) {
+            [newArg addObject:complection];
+        }
+        [_methodQueue addObject:@{@"method":method, @"args":[newArg copy]}];
+    }
+}
+
+
 - (void)resetEnvironment
 {
     [_jsBridge resetEnvironment];
@@ -677,4 +723,96 @@ _Pragma("clang diagnostic pop") \
     }
 }
 
++ (void)mountContextEnvironment:(JSContext*)context
+{
+    NSDictionary *data = [WXUtility getEnvironment];
+    context[@"WXEnvironment"] = data;
+    context[@"btoa"] = ^(JSValue *value ) {
+        NSData *nsdata = [[value toString]
+                          dataUsingEncoding:NSUTF8StringEncoding];
+        NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
+        return base64Encoded;
+    };
+    context[@"atob"] = ^(JSValue *value ) {
+        NSData *nsdataFromBase64String = [[NSData alloc]
+                                          initWithBase64EncodedString:[value 
toString] options:0];
+        NSString *base64Decoded = [[NSString alloc]
+                                   initWithData:nsdataFromBase64String 
encoding:NSUTF8StringEncoding];
+        return base64Decoded;
+    };
+    context.exceptionHandler = ^(JSContext *context, JSValue *exception){
+        context.exception = exception;
+        
+        WXSDKInstance *instance = [WXSDKEngine topInstance];
+        NSString *bundleUrl = instance.pageName?:([instance.scriptURL 
absoluteString]?:@"WX_KEY_EXCEPTION_WXBRIDGE");
+        NSString *errorCode = [NSString stringWithFormat:@"%d", 
WX_KEY_EXCEPTION_WXBRIDGE];
+        NSString *message = [NSString 
stringWithFormat:@"[WX_KEY_EXCEPTION_WXBRIDGE] [%@:%@:%@] %@\n%@", 
exception[@"sourceURL"], exception[@"line"], exception[@"column"], [exception 
toString], [exception[@"stack"] toObject]];
+        NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionaryWithObjectsAndKeys:
+                                         
instance.userInfo[@"jsMainBundleStringContentLength"]?:@"",@"jsMainBundleStringContentLength",
+                                         
instance.userInfo[@"jsMainBundleStringContentMd5"]?:@"",@"jsMainBundleStringContentMd5",nil];
+        WXJSExceptionInfo * jsExceptionInfo = [[WXJSExceptionInfo alloc] 
initWithInstanceId:instance.instanceId bundleUrl:bundleUrl errorCode:errorCode 
functionName:@"" exception:message userInfo:userInfo];
+        
+        [WXExceptionUtils commitCriticalExceptionRT:jsExceptionInfo];
+        WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_JS_EXECUTE, message);
+        if (instance.onJSRuntimeException) {
+            instance.onJSRuntimeException(jsExceptionInfo);
+        }
+    };
+    
+    if (WX_SYS_VERSION_LESS_THAN(@"8.0")) {
+        // solve iOS7 memory problem
+        context[@"nativeSet"] = [WXPolyfillSet class];
+    }
+    context[@"console"][@"error"] = ^(){
+        [WXBridgeContext handleConsoleOutputWithArgument:[JSContext 
currentArguments] logLevel:WXLogFlagError];
+    };
+    context[@"console"][@"warn"] = ^(){
+        [WXBridgeContext handleConsoleOutputWithArgument:[JSContext 
currentArguments] logLevel:WXLogFlagWarning];
+    };
+    context[@"console"][@"info"] = ^(){
+        [WXBridgeContext handleConsoleOutputWithArgument:[JSContext 
currentArguments] logLevel:WXLogFlagInfo];
+    };
+    context[@"console"][@"debug"] = ^(){
+        [WXBridgeContext handleConsoleOutputWithArgument:[JSContext 
currentArguments] logLevel:WXLogFlagDebug];
+    };
+    context[@"console"][@"log"] = ^(){
+        [WXBridgeContext handleConsoleOutputWithArgument:[JSContext 
currentArguments] logLevel:WXLogFlagLog];
+    };
+    context[@"nativeLog"] = ^() {
+        static NSDictionary *levelMap;
+        static dispatch_once_t onceToken;
+        dispatch_once(&onceToken, ^{
+            levelMap = @{
+                         @"__ERROR": @(WXLogFlagError),
+                         @"__WARN": @(WXLogFlagWarning),
+                         @"__INFO": @(WXLogFlagInfo),
+                         @"__DEBUG": @(WXLogFlagDebug),
+                         @"__LOG": @(WXLogFlagLog)
+                         };
+        });
+        
+    };
+}
++ (void)handleConsoleOutputWithArgument:(NSArray*)arguments 
logLevel:(WXLogFlag)logLevel
+{
+    NSMutableString *string = [NSMutableString string];
+    [string appendString:@"jsLog: "];
+    [arguments enumerateObjectsUsingBlock:^(JSValue *jsVal, NSUInteger idx, 
BOOL *stop) {
+        [string appendFormat:@"%@ ", jsVal];
+        if (idx == arguments.count - 1) {
+            if (logLevel) {
+                if (WXLogFlagWarning == logLevel) {
+                    id<WXAppMonitorProtocol> appMonitorHandler = [WXSDKEngine 
handlerForProtocol:@protocol(WXAppMonitorProtocol)];
+                    if ([appMonitorHandler 
respondsToSelector:@selector(commitAppMonitorAlarm:monitorPoint:success:errorCode:errorMsg:arg:)])
 {
+                        [appMonitorHandler commitAppMonitorAlarm:@"weex" 
monitorPoint:@"jswarning" success:FALSE errorCode:@"99999" errorMsg:string 
arg:[WXSDKEngine topInstance].pageName];
+                    }
+                }
+                WX_LOG(logLevel, @"%@", string);
+            } else {
+                [string appendFormat:@"%@ ", jsVal]                            
      ;
+                WXLogInfo(@"%@", string);
+            }
+        }
+    }];
+}
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/492663a9/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m 
b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 581c16d..36e6af5 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -46,6 +46,7 @@
 #import "WXJSExceptionProtocol.h"
 #import "WXTracingManager.h"
 #import "WXExceptionUtils.h"
+#import "WXBridgeContext.h"
 
 NSString *const bundleUrlOptionKey = @"bundleUrl";
 
@@ -349,6 +350,17 @@ typedef enum : NSUInteger {
     [self _renderWithRequest:request options:_options data:_jsData];
 }
 
+- (void)setInstanceJavaScriptContext:(JSContext*)instanceJavaScriptContext
+{
+    _instanceJavaScriptContext = instanceJavaScriptContext;
+    if (@available(iOS 8.0, *)) {
+        _instanceJavaScriptContext.name = self.pageName;
+    } else {
+        // Fallback
+    }
+    [WXBridgeContext mountContextEnvironment:_instanceJavaScriptContext];
+}
+
 - (void)refreshInstance:(id)data
 {
     WXLogDebug(@"refresh instance: %@, data:%@", self, [WXUtility 
JSONString:data]);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/492663a9/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h 
b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
index 93343b1..09d308e 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
@@ -21,6 +21,7 @@
 #import "WXSDKInstance.h"
 #import "WXComponentManager.h"
 #import "WXModuleMethod.h"
+#import <JavaScriptCore/JavaScriptCore.h>
 
 @interface WXSDKInstance ()
 
@@ -31,6 +32,7 @@
 @property (nonatomic, strong) NSMutableDictionary *styleConfigs;
 @property (nonatomic, strong) NSMutableDictionary *attrConfigs;
 
+@property (nonatomic, strong) JSContext *instanceJavaScriptContext; // sandbox 
javaScript context
 @property (nonatomic, readonly, strong) WXComponentManager *componentManager;
 
 - (void)addModuleEventObservers:(NSString*)event 
callback:(NSString*)callbackId option:(NSDictionary*)option 
moduleClassName:(NSString*)moduleClassName;

Reply via email to