Merge pull request #3053 from AMoraga/feature/wkwebview

[iOS] Replace UIWebView with WKWebView
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 44e65c5..86f7fdc 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -619,6 +619,10 @@
 		D735F1B222D761F800B53CDF /* log_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D735F1AC22D761F800B53CDF /* log_utils.cpp */; };
 		D735F1B322D761F800B53CDF /* log_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D735F1AC22D761F800B53CDF /* log_utils.cpp */; };
 		D77286FF22C9B22C00E1DA7D /* eagle_bridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD9205FA223651D800EDF93D /* eagle_bridge.cpp */; };
+		D7D15AF723960F5D0024BC33 /* WXDarkSchemeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D15AF523960F5C0024BC33 /* WXDarkSchemeModule.m */; };
+		D7D15AF823960F5D0024BC33 /* WXDarkSchemeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D15AF523960F5C0024BC33 /* WXDarkSchemeModule.m */; };
+		D7D15AF923960F5D0024BC33 /* WXDarkSchemeModule.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D15AF623960F5D0024BC33 /* WXDarkSchemeModule.h */; };
+		D7D15AFA23960F5D0024BC33 /* WXDarkSchemeModule.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D15AF623960F5D0024BC33 /* WXDarkSchemeModule.h */; };
 		D7D6B6E2238E1B1D00BE56DD /* WXDarkSchemeProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6B6E1238E1B1D00BE56DD /* WXDarkSchemeProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		D7D6B6E3238E1B1D00BE56DD /* WXDarkSchemeProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6B6E1238E1B1D00BE56DD /* WXDarkSchemeProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		D7D6B6E6238E1B2A00BE56DD /* WXDarkSchemeDefaultImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6B6E4238E1B2A00BE56DD /* WXDarkSchemeDefaultImpl.m */; };
@@ -1359,6 +1363,8 @@
 		D3FC0DF61C508B2A002B9E31 /* WXTimerModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModule.m; sourceTree = "<group>"; };
 		D735F1AB22D761F800B53CDF /* log_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log_utils.h; sourceTree = "<group>"; };
 		D735F1AC22D761F800B53CDF /* log_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log_utils.cpp; sourceTree = "<group>"; };
+		D7D15AF523960F5C0024BC33 /* WXDarkSchemeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDarkSchemeModule.m; sourceTree = "<group>"; };
+		D7D15AF623960F5D0024BC33 /* WXDarkSchemeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDarkSchemeModule.h; sourceTree = "<group>"; };
 		D7D6B6E1238E1B1D00BE56DD /* WXDarkSchemeProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDarkSchemeProtocol.h; sourceTree = "<group>"; };
 		D7D6B6E4238E1B2A00BE56DD /* WXDarkSchemeDefaultImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDarkSchemeDefaultImpl.m; sourceTree = "<group>"; };
 		D7D6B6E5238E1B2A00BE56DD /* WXDarkSchemeDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDarkSchemeDefaultImpl.h; sourceTree = "<group>"; };
@@ -1952,6 +1958,8 @@
 		77E659D71C07F585008B8775 /* Module */ = {
 			isa = PBXGroup;
 			children = (
+				D7D15AF623960F5D0024BC33 /* WXDarkSchemeModule.h */,
+				D7D15AF523960F5C0024BC33 /* WXDarkSchemeModule.m */,
 				7704894622AA358400E7606F /* WXConsoleLogModule.h */,
 				BD35ADE92303BEA60050ED82 /* WXConsoleLogModule.mm */,
 				BA5F00EF1FC5AFFE00F76B5C /* WXLocaleModule.h */,
@@ -2634,6 +2642,7 @@
 				B8D66CA921255730003960BD /* wson_util.h in Headers */,
 				7704894822AA358500E7606F /* WXConsoleLogModule.h in Headers */,
 				B8D66C8B21255730003960BD /* render_list_factory.h in Headers */,
+				D7D15AF923960F5D0024BC33 /* WXDarkSchemeModule.h in Headers */,
 				745B2D681E5A8E1E0092D38A /* WXMultiColumnLayout.h in Headers */,
 				B89543F720EB18B5006EAD63 /* WXCoreBridge.h in Headers */,
 				2A60CE9C1C91733E00857B9F /* WXSwitchComponent.h in Headers */,
@@ -2842,6 +2851,7 @@
 				B8D66C3E21255730003960BD /* render_action_createfinish.h in Headers */,
 				DCA445F21EFA5A2300D0CFA8 /* WXHeaderComponent.h in Headers */,
 				DCA445DD1EFA59B300D0CFA8 /* WXRecyclerUpdateController.h in Headers */,
+				D7D15AFA23960F5D0024BC33 /* WXDarkSchemeModule.h in Headers */,
 				DCA4461E1EFA5AAF00D0CFA8 /* WXComponentFactory.h in Headers */,
 				33CE190F2153443000CF9670 /* WXJSFrameworkLoadDefaultImpl.h in Headers */,
 				B87B9E7E21539B3300B6DC61 /* WXVersion.h in Headers */,
@@ -3338,6 +3348,7 @@
 				742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */,
 				7461F8931CFB373100F62D44 /* WXLayer.m in Sources */,
 				74D205211E091B8000128F44 /* WXCallJSMethod.m in Sources */,
+				D7D15AF723960F5D0024BC33 /* WXDarkSchemeModule.m in Sources */,
 				BD88C14522F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */,
 				C41E1A981DC1FD15009C7F90 /* WXDatePickerManager.m in Sources */,
 				BDEEADBA22F2902E0099F1D7 /* time_calculator.cpp in Sources */,
@@ -3530,6 +3541,7 @@
 				DCA445931EFA55B300D0CFA8 /* WXComponentManager.mm in Sources */,
 				DCA445941EFA55B300D0CFA8 /* WXComponentFactory.m in Sources */,
 				DCA445951EFA55B300D0CFA8 /* WXRuleManager.m in Sources */,
+				D7D15AF823960F5D0024BC33 /* WXDarkSchemeModule.m in Sources */,
 				BD88C14622F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */,
 				DCA445961EFA55B300D0CFA8 /* WXMonitor.m in Sources */,
 				BDEEADBB22F2902E0099F1D7 /* time_calculator.cpp in Sources */,
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
index 0c3d251..413b6d9 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
@@ -401,7 +401,7 @@
 
 - (void)resetEnvironment
 {
-    NSDictionary *data = [WXUtility getEnvironment];
+    NSDictionary *data = [WXUtility getEnvironmentForJSContext];
     _jsContext[@"WXEnvironment"] = data;
 }
 
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm b/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
index 341c2a7..d007d60 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
@@ -190,7 +190,7 @@
             [self recursivelyAddChildNode:dict toSuperNode:rootNode];
         }
         
-        _backgroundColor = rootNode.backgroundColor?:[UIColor whiteColor];
+        _backgroundColor = rootNode.backgroundColor?:[UIColor clearColor];
     }
 }
 
@@ -319,7 +319,7 @@
         if (_styles) {
             [self fillCSSStyles:_styles toNode:rootNode superNode:nil];
         }
-        _backgroundColor = rootNode.backgroundColor?:[UIColor whiteColor];
+        _backgroundColor = rootNode.backgroundColor?:[UIColor clearColor];
     }
 
     WXRichNode* superNode = [self findRichNode:@"_root"];
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index 2039300..993e427 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -43,6 +43,7 @@
 #import "WXConfigCenterProtocol.h"
 #import "WXComponent+Layout.h"
 #import "WXCoreBridge.h"
+#import "WXDarkSchemeModule.h"
 
 @implementation WXSDKEngine
 
@@ -69,6 +70,7 @@
     [self registerModule:@"webSocket" withClass:NSClassFromString(@"WXWebSocketModule")];
     [self registerModule:@"voice-over" withClass:NSClassFromString(@"WXVoiceOverModule")];
     [self registerModule:@"sdk-console-log" withClass:NSClassFromString(@"WXConsoleLogModule")];
+    [self registerModule:@"dark-scheme" withClass:NSClassFromString(@"WXDarkSchemeModule")];
 }
 
 + (void)registerModule:(NSString *)name withClass:(Class)clazz
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
index 3f228ee..6fa35be 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
@@ -43,6 +43,7 @@
 #import "WXAnalyzerCenter.h"
 #import "WXDisplayLinkManager.h"
 #import "WXDarkSchemeProtocol.h"
+#import "WXSDKInstance_private.h"
 
 static NSThread *WXComponentThread;
 
@@ -264,7 +265,16 @@
     
     if ([WXUtility isDarkSchemeSupportEnabled]) {
         if (attributes[@"invertForDarkScheme"] == nil) {
-            _rootComponent.invertForDarkScheme = [[WXSDKInstance darkSchemeColorHandler] defaultInvertValueForRootComponent];
+            WXAutoInvertingBehavior invertingBehavior = _weexInstance.autoInvertingBehavior;
+            if (invertingBehavior == WXAutoInvertingBehaviorDefault) {
+                _rootComponent.invertForDarkScheme = [[WXSDKInstance darkSchemeColorHandler] defaultInvertValueForRootComponent];
+            }
+            else if (invertingBehavior == WXAutoInvertingBehaviorAlways) {
+                _rootComponent.invertForDarkScheme = YES;
+            }
+            else {
+                _rootComponent.invertForDarkScheme = NO;
+            }
         }
     }
     
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
index cb6251c..a2dab80 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
@@ -406,31 +406,12 @@
             _layer.borderWidth = _borderTopWidth;
             [self _resetNativeBorderRadius];
             _layer.opacity = _opacity;
-            
-            /* Also set background color to view to fix that problem that system may
-             set dynamic color to UITableView. Without these codes, event if we set
-             clear color to layer, the table view could not be transparent. */
+
             if ([WXUtility isDarkSchemeSupportEnabled]) {
                 UIColor* choosedColor = [self.weexInstance chooseColor:self.styleBackgroundColor lightSchemeColor:self.lightSchemeBackgroundColor darkSchemeColor:self.darkSchemeBackgroundColor invert:_invertForDarkScheme scene:[self colorSceneType]];
-                if (choosedColor == [UIColor clearColor]) {
-                    _view.backgroundColor = choosedColor;
-                }
-                _layer.backgroundColor = choosedColor.CGColor;
+                _view.backgroundColor = choosedColor;
             }
             else {
-                /* On iOS10, there is an annoying problem that if we only
-                 set backgroundColor to layer(not to view), for UIScrollView
-                 the background color would be black. So we have to set
-                 background color to UIView itself on iOS10(or lower).
-                 
-                 For iOS13, we have SDK which hooked setBackgroundColor
-                 of UIView to support autoinverting(no in WeexSDK).
-                 But that SDK would finally set a UIDynamicColor to view.
-                 Weex can handle dark mode, so we don't want background
-                 color of a UIView in Weex page to be set to UIDynamicColor.
-                 So in code above, we only set color to layer but which
-                 also caused the black problem that on iOS10.
-                 */
                 _view.backgroundColor = self.styleBackgroundColor;
             }
         }
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
index 088d8ac..e7d4fb1 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
@@ -451,6 +451,27 @@
 
 #pragma mark - Scheme Support
 
+typedef enum : NSUInteger {
+    WXAutoInvertingBehaviorDefault,
+    WXAutoInvertingBehaviorAlways,
+    WXAutoInvertingBehaviorNever,
+} WXAutoInvertingBehavior;
+
+/**
+ Set auto-inverting behavior for dark scheme.
+    WXAutoInvertingBehaviorDefault: Use components attribute and
+        defaultInvertValueForRootComponent of WXDarkSchemeProtocol.
+    WXAutoInvertingBehaviorAlways: Always set 'autoInvertForDarkScheme' as
+        true for root component.
+    WXAutoInvertingBehaviorNever: Always set 'autoInvertForDarkScheme' as
+        false for root component.
+ 
+ This function should be called before rendering URL.
+
+ @return Handler instance.
+*/
+- (void)setAutoInvertingBehavior:(WXAutoInvertingBehavior)behavior;
+
 /**
  Handler for handling color invert.
 
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 70c7493..d033379 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -53,6 +53,7 @@
 #import "WXCoreBridge.h"
 #import "WXDataRenderHandler.h"
 #import "WXDarkSchemeProtocol.h"
+#import "WXDarkSchemeModule.h"
 
 #define WEEX_LITE_URL_SUFFIX           @"wlasm"
 #define WEEX_RENDER_TYPE_PLATFORM       @"platform"
@@ -110,6 +111,13 @@
             self.schemeName = @"light";
         }
         
+        // Update scheme value in JS environment.
+        if (([WXUtility isEnvironmentUsingDarkScheme] && [self.schemeName isEqualToString:@"light"]) ||
+            (![WXUtility isEnvironmentUsingDarkScheme] && [self.schemeName isEqualToString:@"dark"])) {
+            [[WXBridgeManager sharedManager] resetEnvironment];
+        }
+        
+        _autoInvertingBehavior = WXAutoInvertingBehaviorDefault;
         _renderType = renderType;
         _appearState = YES;
         
@@ -1185,6 +1193,11 @@
     return result;
 }
 
+- (void)setAutoInvertingBehavior:(WXAutoInvertingBehavior)behavior
+{
+    _autoInvertingBehavior = behavior;
+}
+
 + (id<WXDarkSchemeProtocol>)darkSchemeColorHandler
 {
     static id<WXDarkSchemeProtocol> colorHandler;
@@ -1219,6 +1232,9 @@
             return;
         }
         
+        WXDarkSchemeModule* darkSchemeModule = [self moduleForClass:[WXDarkSchemeModule class]];
+        [darkSchemeModule onInstanceSchemeChanged];
+        
         // Recursively visit all components and notify that scheme had changed.
         __weak WXSDKInstance* weakSelf = self;
         WXPerformBlockOnComponentThread(^{
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
index d3811c7..30cd209 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
@@ -39,6 +39,7 @@
 @property (nonatomic, strong) NSString *createInstanceContextResult;
 @property (nonatomic, strong) NSString *executeRaxApiResult;
 
+@property (nonatomic, assign) WXAutoInvertingBehavior autoInvertingBehavior;
 @property (atomic, strong) NSString* schemeName;
 
 - (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId option:(NSDictionary*)option moduleClassName:(NSString*)moduleClassName;
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.h b/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.h
new file mode 100644
index 0000000..fce05b4
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.h
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXModuleProtocol.h"
+
+@interface WXDarkSchemeModule : NSObject <WXModuleProtocol>
+
+- (void)onInstanceSchemeChanged;
+
+@end
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.m b/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.m
new file mode 100644
index 0000000..7cf14d1
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXDarkSchemeModule.m
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXDarkSchemeModule.h"
+#import "WXSDKInstance_private.h"
+
+@implementation WXDarkSchemeModule
+{
+    WXModuleKeepAliveCallback _schemeChangedCallback;
+}
+
+@synthesize weexInstance;
+
+WX_EXPORT_METHOD_SYNC(@selector(getCurrentScheme))
+WX_EXPORT_METHOD(@selector(registerSchemeChangeListener:))
+WX_EXPORT_METHOD(@selector(unregisterSchemeChangeListener))
+
+- (NSString*)getCurrentScheme
+{
+    return [self.weexInstance isDarkScheme] ? @"dark" : @"light";
+}
+
+- (void)registerSchemeChangeListener:(WXModuleKeepAliveCallback)callback
+{
+    _schemeChangedCallback = callback;
+}
+
+- (void)onInstanceSchemeChanged
+{
+    if (_schemeChangedCallback) {
+        _schemeChangedCallback(@{@"instanceId": self.weexInstance.instanceId?:@"",
+                                 @"scheme": self.weexInstance.schemeName?:@"light"},
+                               YES);
+    }
+}
+
+- (void)unregisterSchemeChangeListener
+{
+    _schemeChangedCallback = nil;
+}
+
+@end
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 49d2d71..91d3365 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -145,6 +145,8 @@
  *
  */
 + (NSDictionary *_Nonnull)getEnvironment;
++ (NSDictionary *_Nonnull)getEnvironmentForJSContext;
++ (BOOL)isEnvironmentUsingDarkScheme;
 
 + (NSDictionary *_Nonnull)getDebugEnvironment;
 
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
index 12d4911..3e2eb17 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
@@ -234,6 +234,20 @@
     return data;
 }
 
+static BOOL gIsEnvironmentUsingDarkScheme = NO;
+
++ (NSDictionary *_Nonnull)getEnvironmentForJSContext
+{
+    NSDictionary* result = [self getEnvironment];
+    gIsEnvironmentUsingDarkScheme = [result[@"scheme"] isEqualToString:@"dark"];
+    return result;
+}
+
++ (BOOL)isEnvironmentUsingDarkScheme
+{
+    return gIsEnvironmentUsingDarkScheme;
+}
+
 + (NSDictionary *)getDebugEnvironment {
     NSString *platform = @"iOS";
     NSString *weexVersion = [WXSDKEngine SDKEngineVersion];
diff --git a/ios/sdk/WeexSDK/Sources/View/WXRootView.m b/ios/sdk/WeexSDK/Sources/View/WXRootView.m
index 0df4760..8651ec6 100644
--- a/ios/sdk/WeexSDK/Sources/View/WXRootView.m
+++ b/ios/sdk/WeexSDK/Sources/View/WXRootView.m
@@ -21,6 +21,8 @@
 #import "WXSDKInstance.h"
 #import "WXPageEventNotifyEvent.h"
 #import "WXSDKEngine.h"
+#import "WXUtility.h"
+#import "WXBridgeManager.h"
 
 @interface WXRootView()
 {
@@ -63,6 +65,18 @@
     return _mHasEvent;
 }
 
+- (void)checkUpdateEnvironment:(NSInteger)currentStyle
+{
+    if (@available(iOS 13.0, *)) {
+        if (([WXUtility isEnvironmentUsingDarkScheme] && (UIUserInterfaceStyle)currentStyle == UIUserInterfaceStyleLight) ||
+            (![WXUtility isEnvironmentUsingDarkScheme] && (UIUserInterfaceStyle)currentStyle == UIUserInterfaceStyleDark)) {
+            // Update scheme value in JS environment.
+            [WXUtility getEnvironmentForJSContext]; // Update gIsEnvironmentUsingDarkScheme
+            [[WXBridgeManager sharedManager] resetEnvironment];
+        }
+    }
+}
+
 - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
 {
     [super traitCollectionDidChange:previousTraitCollection];
@@ -73,6 +87,7 @@
         if (currentStyle != previousTraitCollection.userInterfaceStyle) {
             if (_hasFirstTraitCollectionChange) {
                 _allowFirstTraitCollectionChange = NO;
+                [self checkUpdateEnvironment:(NSInteger)currentStyle];
                 [self.instance setCurrentSchemeName:currentStyle == UIUserInterfaceStyleDark ? @"dark" : @"light"];
             }
             else {
@@ -84,6 +99,7 @@
                     if (strongSelf) {
                         if (strongSelf->_allowFirstTraitCollectionChange) {
                             if (strongSelf.instance) {
+                                [self checkUpdateEnvironment:(NSInteger)currentStyle];
                                 [strongSelf.instance setCurrentSchemeName:currentStyle == UIUserInterfaceStyleDark ? @"dark" : @"light"];
                             }
                         }
diff --git a/weex_core/Source/core/render/page/render_page_custom.cpp b/weex_core/Source/core/render/page/render_page_custom.cpp
index 2317511..3d464ff 100644
--- a/weex_core/Source/core/render/page/render_page_custom.cpp
+++ b/weex_core/Source/core/render/page/render_page_custom.cpp
@@ -21,11 +21,6 @@
 #include "render_page_custom.h"
 
 namespace WeexCore {
-    
-    template<typename T>
-    static std::shared_ptr<T> SharedMove(T& source) {
-        return std::make_shared<T>(std::move(source));
-    }
 
     RenderPageCustom::RenderPageCustom(const std::string& page_id, const std::string& page_type, const PageOptions& options): RenderPageBase(page_id, page_type) {
         valid_ = true;
@@ -37,7 +32,7 @@
             targetOptions.is_round_off = options.is_round_off;
             targetOptions.viewport_width = options.viewport_width;
             targetOptions.device_width = options.device_width;
-            target_->createPage(page_id, targetOptions);;
+            target_->createPage(page_id, targetOptions);
         }
     }
     
@@ -46,10 +41,8 @@
                             std::map<std::string, std::string>* attrs,
                             std::set<std::string>* events) {
         if (target_) {
-            auto managedStyles = SharedMove(*styles);
-            auto managedAttrs = SharedMove(*attrs);
-            auto managedEvents = SharedMove(*events);
-            target_->createBody(page_id_, ref, type, managedStyles, managedAttrs, managedEvents);
+            target_->createBody(page_id_, ref, type, styles, attrs, events);
+            return true;
         }
         delete styles;
         delete attrs;
@@ -63,10 +56,8 @@
                                            std::map<std::string, std::string>* attrs,
                                            std::set<std::string>* events) {
         if (target_) {
-            auto managedStyles = SharedMove(*styles);
-            auto managedAttrs = SharedMove(*attrs);
-            auto managedEvents = SharedMove(*events);
-            target_->addElement(page_id_, ref, type, parent_ref, index, managedStyles, managedAttrs, managedEvents);
+            target_->addElement(page_id_, ref, type, parent_ref, index, styles, attrs, events);
+            return true;
         }
         delete styles;
         delete attrs;
@@ -90,11 +81,11 @@
     
     bool RenderPageCustom::UpdateStyle(const std::string &ref, std::vector<std::pair<std::string, std::string>> *styles) {
         if (target_) {
-            std::shared_ptr<std::map<std::string, std::string>> managedStyles = std::make_shared<std::map<std::string, std::string>>();
+            std::map<std::string, std::string>* stylesMap = new std::map<std::string, std::string>();
             for (auto& p : *styles) {
-                (*managedStyles)[std::move(p.first)] = std::move(p.second);
+                (*stylesMap)[std::move(p.first)] = std::move(p.second);
             }
-            target_->updateStyles(page_id_, ref, managedStyles);
+            target_->updateStyles(page_id_, ref, stylesMap);
         }
         delete styles;
         return true;
@@ -102,11 +93,11 @@
     
     bool RenderPageCustom::UpdateAttr(const std::string &ref, std::vector<std::pair<std::string, std::string>> *attrs) {
         if (target_) {
-            std::shared_ptr<std::map<std::string, std::string>> managedAttrs = std::make_shared<std::map<std::string, std::string>>();
+            std::map<std::string, std::string>* attrsMap = new std::map<std::string, std::string>();
             for (auto& p : *attrs) {
-                (*managedAttrs)[std::move(p.first)] = std::move(p.second);
+                (*attrsMap)[std::move(p.first)] = std::move(p.second);
             }
-            target_->updateAttributes(page_id_, ref, managedAttrs);
+            target_->updateAttributes(page_id_, ref, attrsMap);
         }
         delete attrs;
         return true;
diff --git a/weex_core/Source/core/render/target/render_target.h b/weex_core/Source/core/render/target/render_target.h
index 81f7fc4..6b89455 100644
--- a/weex_core/Source/core/render/target/render_target.h
+++ b/weex_core/Source/core/render/target/render_target.h
@@ -56,23 +56,23 @@
         virtual void deletePage(const std::string& page) = 0;
 
         virtual void createBody(const std::string& page, const std::string& ref, const std::string& type,
-                                std::shared_ptr<std::map<std::string, std::string>> styles,
-                                std::shared_ptr<std::map<std::string, std::string>> attrs,
-                                std::shared_ptr<std::set<std::string>> events) = 0;
+                                std::map<std::string, std::string>* styles,
+                                std::map<std::string, std::string>* attrs,
+                                std::set<std::string>* events) = 0;
 
         virtual void addElement(const std::string& page, const std::string& ref, const std::string& type,
                                 const std::string &parent_ref, int index,
-                                std::shared_ptr<std::map<std::string, std::string>> styles,
-                                std::shared_ptr<std::map<std::string, std::string>> attrs,
-                                std::shared_ptr<std::set<std::string>> events) = 0;
+                                std::map<std::string, std::string>* styles,
+                                std::map<std::string, std::string>* attrs,
+                                std::set<std::string>* events) = 0;
 
         virtual void removeElement(const std::string& page, const std::string &ref) = 0;
 
         virtual void moveElement(const std::string& page, const std::string &ref, const std::string &parent_ref, int index) = 0;
 
-        virtual void updateStyles(const std::string& page, const std::string &ref, std::shared_ptr<std::map<std::string, std::string>> styles) = 0;
+        virtual void updateStyles(const std::string& page, const std::string &ref, std::map<std::string, std::string>* styles) = 0;
 
-        virtual void updateAttributes(const std::string& page, const std::string &ref, std::shared_ptr<std::map<std::string, std::string>> attrs) = 0;
+        virtual void updateAttributes(const std::string& page, const std::string &ref, std::map<std::string, std::string>* attrs) = 0;
 
         virtual void addEvent(const std::string& page, const std::string &ref, const std::string &event) = 0;