From cd5e715adea376322872708636c924702a6a7a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Thu, 8 Dec 2016 11:18:59 +0800 Subject: [PATCH 001/144] + [ios] add location module and resource request. --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 24 ++ ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 28 ++- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 237 +++++++++++------- .../WeexSDK/Sources/Module/WXLocationModule.h | 14 ++ .../WeexSDK/Sources/Module/WXLocationModule.m | 31 +++ ios/sdk/WeexSDK/Sources/WXResourceRequest.h | 20 ++ ios/sdk/WeexSDK/Sources/WXResourceRequest.m | 51 ++++ 7 files changed, 304 insertions(+), 101 deletions(-) create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXLocationModule.h create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXLocationModule.m create mode 100644 ios/sdk/WeexSDK/Sources/WXResourceRequest.h create mode 100644 ios/sdk/WeexSDK/Sources/WXResourceRequest.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 3047af0750..52f2f79573 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -117,6 +117,10 @@ 7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 746319281C71B92600EFEBD4 /* WXModalUIModule.m */; }; 7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */ = {isa = PBXBuildFile; fileRef = 7469869D1C4E2C000054A57E /* NSArray+Weex.h */; }; 746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */ = {isa = PBXBuildFile; fileRef = 7469869E1C4E2C000054A57E /* NSArray+Weex.m */; }; + 746A2F3F1DF808E6004719D0 /* WXLocationModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */; }; + 746A2F401DF808E6004719D0 /* WXLocationModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */; }; + 746A2F461DF826A9004719D0 /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 746A2F441DF826A9004719D0 /* WXResourceRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 746A2F471DF826A9004719D0 /* WXResourceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 746A2F451DF826A9004719D0 /* WXResourceRequest.m */; }; 747A787C1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h in Headers */ = {isa = PBXBuildFile; fileRef = 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */; }; 747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m in Sources */ = {isa = PBXBuildFile; fileRef = 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */; }; 74896F301D1AC79400D1D593 /* NSObject+WXSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */; }; @@ -367,6 +371,10 @@ 7469869B1C4DEAC20054A57E /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; }; 7469869D1C4E2C000054A57E /* NSArray+Weex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Weex.h"; sourceTree = ""; }; 7469869E1C4E2C000054A57E /* NSArray+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Weex.m"; sourceTree = ""; }; + 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLocationModule.h; sourceTree = ""; }; + 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXLocationModule.m; sourceTree = ""; }; + 746A2F441DF826A9004719D0 /* WXResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXResourceRequest.h; sourceTree = ""; }; + 746A2F451DF826A9004719D0 /* WXResourceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXResourceRequest.m; sourceTree = ""; }; 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+ViewManagement.h"; sourceTree = ""; }; 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+ViewManagement.m"; sourceTree = ""; }; 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+WXSwizzle.h"; sourceTree = ""; }; @@ -612,6 +620,15 @@ path = Display; sourceTree = ""; }; + 746A2F431DF82607004719D0 /* Network */ = { + isa = PBXGroup; + children = ( + 746A2F441DF826A9004719D0 /* WXResourceRequest.h */, + 746A2F451DF826A9004719D0 /* WXResourceRequest.m */, + ); + name = Network; + sourceTree = ""; + }; 749DC2781D408265009E1C91 /* Monitor */ = { isa = PBXGroup; children = ( @@ -738,6 +755,7 @@ 77D1611A1C02DD3C0010B15B /* Manager */, 749DC2781D408265009E1C91 /* Monitor */, 77D1611B1C02DD3C0010B15B /* Model */, + 746A2F431DF82607004719D0 /* Network */, 77D1611C1C02DD3C0010B15B /* Protocol */, 74C27A001CEC4371004E488E /* Supporting Files */, ); @@ -890,6 +908,8 @@ D362F94E1C83EDA20003F546 /* WXWebViewModule.m */, D334510A1D3E19B80083598A /* WXCanvasModule.h */, D334510B1D3E19B80083598A /* WXCanvasModule.m */, + 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */, + 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */, ); path = Module; sourceTree = ""; @@ -986,6 +1006,7 @@ 7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */, 74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */, 74FD6E041C7C0E9600DBEB6D /* WXScrollerProtocol.h in Headers */, + 746A2F3F1DF808E6004719D0 /* WXLocationModule.h in Headers */, 77D161201C02DDB40010B15B /* WXSDKEngine.h in Headers */, 745ED2DA1C5F2C7E002DB5A8 /* WXView.h in Headers */, 59D3CA411CF9ED57008835DC /* Layout.h in Headers */, @@ -1045,6 +1066,7 @@ 2AC750241C7565690041D390 /* WXIndicatorComponent.h in Headers */, DCAB35FE1D658EB700C0EA70 /* WXRuleManager.h in Headers */, 748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */, + 746A2F461DF826A9004719D0 /* WXResourceRequest.h in Headers */, 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */, C41E1A971DC1FD15009C7F90 /* WXDatePickerManager.h in Headers */, 7461F8901CFB373100F62D44 /* WXDisplayQueue.h in Headers */, @@ -1348,6 +1370,7 @@ D33451091D3E19480083598A /* WXCanvasComponent.m in Sources */, 74A4BA971CB365D100195969 /* WXAppConfiguration.m in Sources */, 59A583091CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m in Sources */, + 746A2F401DF808E6004719D0 /* WXLocationModule.m in Sources */, 7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */, 77D161501C02E3880010B15B /* WXUtility.m in Sources */, 74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */, @@ -1358,6 +1381,7 @@ 77D1614C1C02E3790010B15B /* WXConvert.m in Sources */, 749DC27C1D40827B009E1C91 /* WXMonitor.m in Sources */, 77E659FB1C0EE579008B8775 /* WXBridgeMethod.m in Sources */, + 746A2F471DF826A9004719D0 /* WXResourceRequest.m in Sources */, C4B834271DE69B09007AD27E /* WXPickerModule.m in Sources */, 77D161391C02DE940010B15B /* WXBridgeManager.m in Sources */, ); diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index 38fd09b905..965047b1c1 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -8,6 +8,7 @@ #import #import "WXComponent.h" +@class WXResourceRequest; extern NSString *const bundleUrlOptionKey; @@ -151,21 +152,40 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code * * @param url The url of bundle rendered to a weex view. * - * @param options The params passed by user, sometimes you should pass the value of "bundleUrl". + * @param options The params passed by user * - * @param data The data the bundle needs when rendered. + * @param data The data the bundle needs when rendered. Defalut is nil. **/ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data; +/** + * Renders weex view with resource request. + * + * @param request The resource request specifying the URL to render with. + * + * @param options The params passed by user. + * + * @param data The data the bundle needs when rendered. Defalut is nil. + **/ +- (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; + /** * Renders weex view with source string of bundle and some others. * - * @param options The params passed by user, sometimes you should pass the value of "bundleUrl". + * @param options The params passed by user. * - * @param data The data the bundle needs when rendered. + * @param data The data the bundle needs when rendered. Defalut is nil. **/ - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data; +/** + * Reload the js bundle from the current URL and rerender. + * + * @param forcedReload when this parameter is true, the js bundle will always be reloaded from the server. If it is false, the instance may reload the js bundle from its cache. Default is false. + * + **/ +- (void)reload:(BOOL)forcedReload; + /** * Refreshes current instance with data. * diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index bc2590e7d0..fc65830c82 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -22,13 +22,25 @@ #import "WXView.h" #import "WXRootView.h" #import "WXThreadSafeMutableDictionary.h" +#import "WXResourceRequest.h" NSString *const bundleUrlOptionKey = @"bundleUrl"; NSTimeInterval JSLibInitTime = 0; +typedef enum : NSUInteger { + WXLoadTypeNormal, + WXLoadTypeBack, + WXLoadTypeForward, + WXLoadTypeReload, + WXLoadTypeReplace +} WXLoadType; + @implementation WXSDKInstance { + NSDictionary *_options; + id _data; + id _networkHandler; WXComponentManager *_componentManager; WXRootView *_rootView; @@ -74,6 +86,22 @@ - (UIView *)rootView return _rootView; } + +- (void)setFrame:(CGRect)frame +{ + if (!CGRectEqualToRect(frame, _frame)) { + _frame = frame; + WXPerformBlockOnMainThread(^{ + if (_rootView) { + _rootView.frame = frame; + WXPerformBlockOnComponentThread(^{ + [self.componentManager rootViewFrameDidChange:frame]; + }); + } + }); + } +} + - (void)renderWithURL:(NSURL *)url { [self renderWithURL:url options:nil data:nil]; @@ -86,100 +114,17 @@ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data return; } - _scriptURL = url; - NSMutableDictionary *newOptions = [options mutableCopy]; - if (!newOptions) { - newOptions = [[NSMutableDictionary alloc] init]; - } - if (!newOptions[bundleUrlOptionKey]) { - newOptions[bundleUrlOptionKey] = url.absoluteString; - } - if ([newOptions[bundleUrlOptionKey] isKindOfClass:[NSURL class]]) { - newOptions[bundleUrlOptionKey] = ((NSURL*)newOptions[bundleUrlOptionKey]).absoluteString; - } - - if (!self.pageName || [self.pageName isEqualToString:@""]) { - self.pageName = [WXUtility urlByDeletingParameters:url].absoluteString ? : @""; - } - - __weak typeof(self) weakSelf = self; - if ([url isFileURL]) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSString *path = [url path]; - NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path]; - NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding]; - if (!script || script.length <= 0) { - NSString *errorDesc = [NSString stringWithFormat:@"File read error at url: %@", url]; - WXLogError(@"%@", errorDesc); - if (weakSelf.onFailed) { - weakSelf.onFailed([NSError errorWithDomain:WX_ERROR_DOMAIN code:0 userInfo:@{NSLocalizedDescriptionKey: errorDesc}]); - } - return; - } - [weakSelf renderView:script options:newOptions data:data]; - }); - } else { - WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self); - - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; - [request setValue:@"weex" forHTTPHeaderField:@"f-refer"]; - - id networkHandler = [self networkHandler]; - - __block NSURLResponse *urlResponse; - [networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} - withResponse:^(NSURLResponse *response) { - urlResponse = response; - } - withReceiveData:^(NSData *data) {} - withCompeletion:^(NSData *totalData, NSError *error) { - //TODO 304 - if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { - error = [NSError errorWithDomain:WX_ERROR_DOMAIN - code:((NSHTTPURLResponse *)urlResponse).statusCode - userInfo:@{@"message":@"status code error."}]; - } - - if (error) { - NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ occurs an error:%@", request.URL, error.localizedDescription]; - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); - - if (weakSelf.onFailed) { - weakSelf.onFailed(error); - } - return; - } - - if (!totalData) { - NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ but no data return", request.URL]; - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); - - if (weakSelf.onFailed) { - weakSelf.onFailed(error); - } - return; - } - - NSString *script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding]; - if (!script) { - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", weakSelf.pageName) - return; - } - - WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, weakSelf.pageName); - WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, weakSelf); - - [weakSelf renderView:script options:newOptions data:data]; - }]; - } + WXResourceRequest *request = [WXResourceRequest requestWithURL:url referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; + [self renderWithRequest:request options:options data:data]; } - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data { WXLogDebug(@"Render view: %@, data:%@", self, [WXUtility JSONString:data]); + _options = options; + _data = data; + if (!self.instanceId) { WXLogError(@"Fail to find instance!"); return; @@ -217,19 +162,117 @@ - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)d WX_MONITOR_PERF_SET(WXPTBundleSize, [source lengthOfBytesUsingEncoding:NSUTF8StringEncoding], self); } -- (void)setFrame:(CGRect)frame + +- (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; { - if (!CGRectEqualToRect(frame, _frame)) { - _frame = frame; - WXPerformBlockOnMainThread(^{ - if (_rootView) { - _rootView.frame = frame; - WXPerformBlockOnComponentThread(^{ - [self.componentManager rootViewFrameDidChange:frame]; - }); + NSURL *url = request.URL; + _scriptURL = url; + NSMutableDictionary *newOptions = [options mutableCopy] ?: [NSMutableDictionary new]; + + if (!newOptions[bundleUrlOptionKey]) { + newOptions[bundleUrlOptionKey] = url.absoluteString; + } + // compatible with some wrong type, remove this hopefully in the future. + if ([newOptions[bundleUrlOptionKey] isKindOfClass:[NSURL class]]) { + WXLogWarning(@"Error type in options with key:bundleUrl, should be of type NSString, not NSURL!"); + newOptions[bundleUrlOptionKey] = ((NSURL*)newOptions[bundleUrlOptionKey]).absoluteString; + } + + if (!self.pageName || [self.pageName isEqualToString:@""]) { + self.pageName = [WXUtility urlByDeletingParameters:url].absoluteString ? : @""; + } + + [self loadRequest:request loadType:WXLoadTypeNormal options:newOptions data:data]; +} + +- (void)loadRequest:(WXResourceRequest *)request loadType:(WXLoadType)loadType options:(NSDictionary *)options data:(id)data; +{ + request.userAgent = [WXUtility userAgent]; + __weak typeof(self) weakSelf = self; + if ([url isFileURL]) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSString *path = [url path]; + NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path]; + NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding]; + if (!script || script.length <= 0) { + NSString *errorDesc = [NSString stringWithFormat:@"File read error at url: %@", url]; + WXLogError(@"%@", errorDesc); + if (weakSelf.onFailed) { + weakSelf.onFailed([NSError errorWithDomain:WX_ERROR_DOMAIN code:0 userInfo:@{NSLocalizedDescriptionKey: errorDesc}]); + } + return; } + [weakSelf renderView:script options:newOptions data:data]; }); + } else { + WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self); + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; + [request setValue:@"weex" forHTTPHeaderField:@"f-refer"]; + + id networkHandler = [self networkHandler]; + + __block NSURLResponse *urlResponse; + [networkHandler sendRequest:request + withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} + withResponse:^(NSURLResponse *response) { + urlResponse = response; + } + withReceiveData:^(NSData *data) {} + withCompeletion:^(NSData *totalData, NSError *error) { + //TODO 304 + if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { + error = [NSError errorWithDomain:WX_ERROR_DOMAIN + code:((NSHTTPURLResponse *)urlResponse).statusCode + userInfo:@{@"message":@"status code error."}]; + } + + if (error) { + NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ occurs an error:%@", request.URL, error.localizedDescription]; + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); + + if (weakSelf.onFailed) { + weakSelf.onFailed(error); + } + return; + } + + if (!totalData) { + NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ but no data return", request.URL]; + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); + + if (weakSelf.onFailed) { + weakSelf.onFailed(error); + } + return; + } + + NSString *script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding]; + if (!script) { + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", weakSelf.pageName) + return; + } + + WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, weakSelf.pageName); + WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, weakSelf); + + [weakSelf renderView:script options:newOptions data:data]; + }]; + } +} + +- (void)reload:(BOOL)forcedReload +{ + // TODO: [self cancel] + if (!_scriptURL) { + WXLogError(@"No script URL found while reloading!"); + return; } + + NSURLRequestCachePolicy cachePolicy = forcedReload ? NSURLRequestReloadIgnoringCacheData : NSURLRequestUseProtocolCachePolicy; + WXResourceRequest *request = [WXResourceRequest requestWithURL:_scriptURL referrer:_scriptURL.absoluteString cachePolicy:cachePolicy]; + [self renderWithRequest:request options:_options data:_data]; } - (void)reloadData:(id)data diff --git a/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.h b/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.h new file mode 100644 index 0000000000..ecfb19b64f --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.h @@ -0,0 +1,14 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import +#import "WXModuleProtocol.h" + +@interface WXLocationModule : NSObject + +@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.m new file mode 100644 index 0000000000..19f3793dbb --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXLocationModule.m @@ -0,0 +1,31 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXLocationModule.h" +#import "WXSDKInstance.h" + +@implementation WXLocationModule + +WX_EXPORT_METHOD(@selector(reload:)) +WX_EXPORT_METHOD(@selector(replace:)) + +@synthesize weexInstance; + +- (void)reload:(BOOL)forcedReload +{ + WXSDKInstance *instance = self.weexInstance; + [instance reload:forcedReload]; +} + +- (void)replace:(NSString *)url +{ + +} + + +@end diff --git a/ios/sdk/WeexSDK/Sources/WXResourceRequest.h b/ios/sdk/WeexSDK/Sources/WXResourceRequest.h new file mode 100644 index 0000000000..bd6c22dab1 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/WXResourceRequest.h @@ -0,0 +1,20 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import + +@interface WXResourceRequest : NSMutableURLRequest + +@property (nonatomic, strong) NSString *referrer; +@property (nonatomic, strong) NSString *userAgent; + ++ (instancetype)requestWithURL:(NSURL *)url + referrer:(NSString *)referrer + cachePolicy:(NSURLRequestCachePolicy)cachePolicy; + +@end diff --git a/ios/sdk/WeexSDK/Sources/WXResourceRequest.m b/ios/sdk/WeexSDK/Sources/WXResourceRequest.m new file mode 100644 index 0000000000..2a060a8fcc --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/WXResourceRequest.m @@ -0,0 +1,51 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXResourceRequest.h" + +NSString * const kHTTPHeaderNameUserAgent = @"User-Agent"; +NSString * const kHTTPHeaderNameReferrer = @"Referer"; // The misspelling referer originated in the original proposal by computer "scientist" Phillip Hallam-Baker to incorporate the field into the HTTP specification. ╮(╯_╰)╭ + +@implementation WXResourceRequest + ++ (instancetype)requestWithURL:(NSURL *)url referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy +{ + return [[self alloc] initWithURL:url referrer:referrer cachePolicy:cachePolicy]; +} + +- (instancetype)initWithURL:(NSURL *)url referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy +{ + if (self = [super initWithURL:url]) { + self.cachePolicy = cachePolicy; + [self setValue:referrer forHTTPHeaderField:kHTTPHeaderNameReferrer]; + } + + return self; +} + +- (NSString *)referrer +{ + return [self valueForKey:kHTTPHeaderNameReferrer]; +} + +- (void)setReferrer:(NSString *)referrer +{ + [self setValue:referrer forKey:kHTTPHeaderNameReferrer]; +} + +- (NSString *)userAgent +{ + return [self valueForKey:kHTTPHeaderNameUserAgent]; +} + +- (void)setUserAgent:(NSString *)userAgent +{ + [self setValue:userAgent forKey:kHTTPHeaderNameUserAgent]; +} + +@end From 4e66859d41ff46dca875d36b22c4bb327fc31dad Mon Sep 17 00:00:00 2001 From: mingyi Date: Thu, 8 Dec 2016 16:29:34 +0800 Subject: [PATCH 002/144] add blur to image --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 8 ++ .../Sources/Component/WXImageComponent.m | 81 +++++++++++++++---- .../WeexSDK/Sources/Utility/WXImageUtils.h | 15 ++++ .../WeexSDK/Sources/Utility/WXImageUtils.m | 35 ++++++++ 4 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.h create mode 100644 ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 3047af0750..a9be7ed3b9 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -34,6 +34,8 @@ 2AE5B7561CABA04E0082FDDB /* WXEventModuleProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2AFEB17B1C747139000507FA /* WXInstanceWrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AFEB1791C747139000507FA /* WXInstanceWrap.h */; }; 2AFEB17C1C747139000507FA /* WXInstanceWrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */; }; + 4162A33F1DF94024007C9EAB /* WXImageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4162A33D1DF94024007C9EAB /* WXImageUtils.h */; }; + 4162A3401DF94024007C9EAB /* WXImageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 4162A33E1DF94024007C9EAB /* WXImageUtils.m */; }; 591324A31D49B7F1004E89ED /* WXTimerModuleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */; }; 591DD3311D23AD5800BE8709 /* WXErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 591DD32F1D23AD5800BE8709 /* WXErrorView.m */; }; 591DD3321D23AD5800BE8709 /* WXErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 591DD3301D23AD5800BE8709 /* WXErrorView.h */; }; @@ -284,6 +286,8 @@ 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXEventModuleProtocol.h; sourceTree = ""; }; 2AFEB1791C747139000507FA /* WXInstanceWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXInstanceWrap.h; sourceTree = ""; }; 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInstanceWrap.m; sourceTree = ""; }; + 4162A33D1DF94024007C9EAB /* WXImageUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXImageUtils.h; sourceTree = ""; }; + 4162A33E1DF94024007C9EAB /* WXImageUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXImageUtils.m; sourceTree = ""; }; 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModuleTests.m; sourceTree = ""; }; 591DD32F1D23AD5800BE8709 /* WXErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXErrorView.m; sourceTree = ""; }; 591DD3301D23AD5800BE8709 /* WXErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXErrorView.h; sourceTree = ""; }; @@ -857,6 +861,8 @@ 7461F8A71CFC33A800F62D44 /* WXThreadSafeMutableArray.m */, 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */, 74896F2F1D1AC79400D1D593 /* NSObject+WXSwizzle.m */, + 4162A33D1DF94024007C9EAB /* WXImageUtils.h */, + 4162A33E1DF94024007C9EAB /* WXImageUtils.m */, ); path = Utility; sourceTree = ""; @@ -1043,6 +1049,7 @@ 77E65A191C155F25008B8775 /* WXScrollerComponent.h in Headers */, DC03ADBA1D508719003F76E7 /* WXTextAreaComponent.h in Headers */, 2AC750241C7565690041D390 /* WXIndicatorComponent.h in Headers */, + 4162A33F1DF94024007C9EAB /* WXImageUtils.h in Headers */, DCAB35FE1D658EB700C0EA70 /* WXRuleManager.h in Headers */, 748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */, 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */, @@ -1317,6 +1324,7 @@ 746319031C60AFC100EFEBD4 /* WXThreadSafeCounter.m in Sources */, 74A4BAA71CB4F98300195969 /* WXStreamModule.m in Sources */, 59597F991D2A041700EE9317 /* WXDebugLoggerBridge.m in Sources */, + 4162A3401DF94024007C9EAB /* WXImageUtils.m in Sources */, 77E659F21C0C3612008B8775 /* WXModuleFactory.m in Sources */, 59CE27E91CC387DB000BE37A /* WXEmbedComponent.m in Sources */, DCA0EF651D6EED6F00CB18B9 /* WXGlobalEventModule.m in Sources */, diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 6baac1d9a7..51d4fddce7 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -14,6 +14,7 @@ #import "WXType.h" #import "WXConvert.h" #import "WXURLRewriteProtocol.h" +#import "WXImageUtils.h" @interface WXImageView : UIImageView @@ -34,6 +35,7 @@ @interface WXImageComponent () @property (nonatomic, strong) NSString *imageSrc; @property (nonatomic, strong) NSString *placeholdSrc; +@property (nonatomic, assign) CGFloat blurRadius; @property (nonatomic, assign) UIViewContentMode resizeMode; @property (nonatomic, assign) WXImageQuality imageQuality; @property (nonatomic, assign) WXImageSharp imageSharp; @@ -60,6 +62,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict } [self configPlaceHolder:attributes]; _resizeMode = [WXConvert UIViewContentMode:attributes[@"resize"]]; + [self configFilter:styles]; _imageQuality = [WXConvert WXImageQuality:styles[@"quality"]]; _imageSharp = [WXConvert WXImageSharp:styles[@"sharpen"]]; _imageLoadEvent = NO; @@ -74,8 +77,34 @@ - (void)configPlaceHolder:(NSDictionary*)attributes { } } +- (void)configFilter:(NSDictionary *)styles { + if (styles[@"filter"]) { + NSString *filter = styles[@"filter"]; + + NSString *pattern = @"blur\\((\\d+)(px)?\\)"; + NSError *error = nil; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern + options:NSRegularExpressionCaseInsensitive + error:&error]; + NSArray *matches = [regex matchesInString:filter options:0 range:NSMakeRange(0, filter.length)]; + if (matches && matches.count > 0) { + NSTextCheckingResult *match = matches[matches.count - 1]; + NSRange matchRange = [match rangeAtIndex:1]; + NSString *matchString = [filter substringWithRange:matchRange]; + NSLog(@"----blur: %@",matchString); + if (matchString && matchString.length > 0) { + _blurRadius = [matchString doubleValue]; + + + } + } + } +} + - (UIView *)loadView { + WXImageView *view = [[WXImageView alloc] init]; + return [[WXImageView alloc] init]; } @@ -102,6 +131,7 @@ - (void)updateStyles:(NSDictionary *)styles _imageSharp = [WXConvert WXImageSharp:styles[@"sharpen"]]; [self updateImage]; } + [self configFilter:styles]; } - (void)updateAttributes:(NSDictionary *)attributes @@ -246,30 +276,49 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.imageOperation = [[weakSelf imageLoader] downloadImageWithURL:newURL imageFrame:weakSelf.calculatedFrame userInfo:userInfo completed:^(UIImage *image, NSError *error, BOOL finished) { + + if (_blurRadius > 0 && image) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + UIImage *newImage = [WXImageUtils toGaussianBluredImage:image blurRadius:_blurRadius]; + dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(self) strongSelf = weakSelf; + [strongSelf imageDownloaded:newImage imageSrc:imageSrc error:error downloadFailedBlock:downloadFailedBlock]; + }); + }); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(self) strongSelf = weakSelf; - - if (weakSelf.imageLoadEvent) { - [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true"}]; - } - if (error) { - downloadFailedBlock(imageSrc, error); - return ; - } - - if (![imageSrc isEqualToString:strongSelf.imageSrc]) { - return ; - } - - if ([strongSelf isViewLoaded]) { - ((UIImageView *)strongSelf.view).image = image; - } + [strongSelf imageDownloaded:image imageSrc:imageSrc error:error downloadFailedBlock:downloadFailedBlock]; }); }]; }); } } +- (void)imageDownloaded:(UIImage *)image + imageSrc:(NSString *)imageSrc + error:(NSError *)error + downloadFailedBlock:(void(^)(NSString *, NSError *))downloadFailedBlock { + + if (self.imageLoadEvent) { + [self fireEvent:@"load" params:@{ @"success": error? @"false" : @"true"}]; + } + if (error) { + downloadFailedBlock(imageSrc, error); + return ; + } + + if (![imageSrc isEqualToString:self.imageSrc]) { + return ; + } + + if ([self isViewLoaded]) { + ((UIImageView *)self.view).image = image; + } +} + - (void)cancelImage { [_imageOperation cancel]; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.h b/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.h new file mode 100644 index 0000000000..c2a170f037 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.h @@ -0,0 +1,15 @@ +// +// WXImageUtils.h +// WeexSDK +// +// Created by xiayun on 16/12/8. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import + +@interface WXImageUtils : NSObject + ++ (UIImage *)toGaussianBluredImage:(UIImage *)originalImage blurRadius:(CGFloat)blurRadius; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.m b/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.m new file mode 100644 index 0000000000..1a744b558a --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Utility/WXImageUtils.m @@ -0,0 +1,35 @@ +// +// WXImageUtils.m +// WeexSDK +// +// Created by xiayun on 16/12/8. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXImageUtils.h" + +@implementation WXImageUtils + ++ (UIImage *)toGaussianBluredImage:(UIImage *)originalImage blurRadius:(CGFloat)blurRadius { + CIImage *imageToBlur = [CIImage imageWithCGImage:originalImage.CGImage]; + + CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; + [gaussianBlurFilter setValue:imageToBlur forKey:kCIInputImageKey]; + [gaussianBlurFilter setValue:[NSNumber numberWithFloat:blurRadius] forKey:kCIInputRadiusKey]; + CIImage *ciImage = gaussianBlurFilter.outputImage; + + CIContext *context = [CIContext contextWithOptions:nil]; + CGRect rect = CGRectMake(0, 0, originalImage.size.width * originalImage.scale, originalImage.size.height * originalImage.scale); + CGImageRef cgImage = [context createCGImage:ciImage fromRect:rect];; + + if (cgImage) { + UIImage *resultImage = [UIImage imageWithCGImage:cgImage]; + CGImageRelease(cgImage); + + return resultImage; + } + + return nil; +} + +@end From f009835ac6b5e13c28a2e7b12fb8692932db0347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Thu, 8 Dec 2016 21:26:55 +0800 Subject: [PATCH 003/144] * [ios] change WXNetworkProtocol to WXResourceRequestHandler, compatible with old logic. --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 60 +++-- .../Sources/Component/WXImageComponent.m | 4 +- .../Sources/Component/WXVideoComponent.m | 2 +- ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m | 5 +- ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m | 5 +- ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h | 5 +- .../Sources/Handler/WXNetworkDefaultImpl.m | 111 ---------- .../WeexSDK/Sources/Loader/WXResourceLoader.h | 30 +++ .../WeexSDK/Sources/Loader/WXResourceLoader.m | 174 +++++++++++++++ .../Sources/Manager/WXHandlerFactory.m | 1 - .../WeexSDK/Sources/Manager/WXRuleManager.m | 2 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 28 ++- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 206 ++++++++---------- .../WeexSDK/Sources/Module/WXStreamModule.m | 9 + .../Sources/{ => Network}/WXResourceRequest.h | 14 ++ .../Sources/{ => Network}/WXResourceRequest.m | 20 +- .../Network/WXResourceRequestHandler.h | 45 ++++ .../WXResourceRequestHandlerDefaultImpl.h | 15 ++ .../WXResourceRequestHandlerDefaultImpl.m | 90 ++++++++ .../WXResourceResponse.h} | 4 +- .../Sources/Network/WXResourceResponse.m | 14 ++ .../Sources/Protocol/WXNetworkProtocol.h | 1 + .../Sources/Protocol/WXURLRewriteProtocol.h | 10 +- ios/sdk/WeexSDKTests/WXURLRewriteTests.m | 4 +- 24 files changed, 577 insertions(+), 282 deletions(-) delete mode 100644 ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.m create mode 100644 ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h create mode 100644 ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.m rename ios/sdk/WeexSDK/Sources/{ => Network}/WXResourceRequest.h (64%) rename ios/sdk/WeexSDK/Sources/{ => Network}/WXResourceRequest.m (54%) create mode 100644 ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h create mode 100644 ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h create mode 100644 ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m rename ios/sdk/WeexSDK/Sources/{Handler/WXNetworkDefaultImpl.h => Network/WXResourceResponse.h} (73%) create mode 100644 ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 52f2f79573..4890c55631 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -54,8 +54,6 @@ 59A582FD1CF5B17B0081FD3E /* WXBridgeContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A582FB1CF5B17B0081FD3E /* WXBridgeContext.m */; }; 59A583081CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A583041CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h */; }; 59A583091CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A583051CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m */; }; - 59A5830A1CF5B2FD0081FD3E /* WXNetworkDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A583061CF5B2FD0081FD3E /* WXNetworkDefaultImpl.h */; }; - 59A5830B1CF5B2FD0081FD3E /* WXNetworkDefaultImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A583071CF5B2FD0081FD3E /* WXNetworkDefaultImpl.m */; }; 59A596191CB630E50012CD52 /* WXNavigationProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A596171CB630E50012CD52 /* WXNavigationProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 59A5961C1CB630F10012CD52 /* WXComponent+Navigation.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A5961A1CB630F10012CD52 /* WXComponent+Navigation.h */; }; 59A5961D1CB630F10012CD52 /* WXComponent+Navigation.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A5961B1CB630F10012CD52 /* WXComponent+Navigation.m */; }; @@ -97,6 +95,15 @@ 7423899B1C3174EB00D748CA /* WXWeakObjectWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */; }; 7423899C1C3174EB00D748CA /* WXWeakObjectWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */; }; 7423899F1C32733800D748CA /* WXType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423899D1C32733800D748CA /* WXType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7251DF98C45007DC46C /* WXResourceRequest.h */; }; + 742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD7261DF98C45007DC46C /* WXResourceRequest.m */; }; + 742AD7301DF98C45007DC46C /* WXResourceRequestHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */; }; + 742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7281DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h */; }; + 742AD7321DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD7291DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m */; }; + 742AD7331DF98C45007DC46C /* WXResourceResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD72A1DF98C45007DC46C /* WXResourceResponse.h */; }; + 742AD7341DF98C45007DC46C /* WXResourceResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD72B1DF98C45007DC46C /* WXResourceResponse.m */; }; + 742AD73A1DF98C8B007DC46C /* WXResourceLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7381DF98C8B007DC46C /* WXResourceLoader.h */; }; + 742AD73B1DF98C8B007DC46C /* WXResourceLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD7391DF98C8B007DC46C /* WXResourceLoader.m */; }; 743933B41C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.h in Headers */ = {isa = PBXBuildFile; fileRef = 743933B21C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.h */; }; 743933B51C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.m in Sources */ = {isa = PBXBuildFile; fileRef = 743933B31C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.m */; }; 744BEA551D05178F00452B5D /* WXComponent+Display.h in Headers */ = {isa = PBXBuildFile; fileRef = 744BEA531D05178F00452B5D /* WXComponent+Display.h */; }; @@ -119,8 +126,6 @@ 746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */ = {isa = PBXBuildFile; fileRef = 7469869E1C4E2C000054A57E /* NSArray+Weex.m */; }; 746A2F3F1DF808E6004719D0 /* WXLocationModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */; }; 746A2F401DF808E6004719D0 /* WXLocationModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */; }; - 746A2F461DF826A9004719D0 /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 746A2F441DF826A9004719D0 /* WXResourceRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 746A2F471DF826A9004719D0 /* WXResourceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 746A2F451DF826A9004719D0 /* WXResourceRequest.m */; }; 747A787C1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h in Headers */ = {isa = PBXBuildFile; fileRef = 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */; }; 747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m in Sources */ = {isa = PBXBuildFile; fileRef = 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */; }; 74896F301D1AC79400D1D593 /* NSObject+WXSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */; }; @@ -309,8 +314,6 @@ 59A582FB1CF5B17B0081FD3E /* WXBridgeContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXBridgeContext.m; sourceTree = ""; }; 59A583041CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXNavigationDefaultImpl.h; sourceTree = ""; }; 59A583051CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXNavigationDefaultImpl.m; sourceTree = ""; }; - 59A583061CF5B2FD0081FD3E /* WXNetworkDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXNetworkDefaultImpl.h; sourceTree = ""; }; - 59A583071CF5B2FD0081FD3E /* WXNetworkDefaultImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXNetworkDefaultImpl.m; sourceTree = ""; }; 59A596171CB630E50012CD52 /* WXNavigationProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXNavigationProtocol.h; sourceTree = ""; }; 59A5961A1CB630F10012CD52 /* WXComponent+Navigation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+Navigation.h"; sourceTree = ""; }; 59A5961B1CB630F10012CD52 /* WXComponent+Navigation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+Navigation.m"; sourceTree = ""; }; @@ -350,6 +353,15 @@ 742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXWeakObjectWrapper.h; sourceTree = ""; }; 7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXWeakObjectWrapper.m; sourceTree = ""; }; 7423899D1C32733800D748CA /* WXType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXType.h; sourceTree = ""; }; + 742AD7251DF98C45007DC46C /* WXResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequest.h; path = Network/WXResourceRequest.h; sourceTree = ""; }; + 742AD7261DF98C45007DC46C /* WXResourceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceRequest.m; path = Network/WXResourceRequest.m; sourceTree = ""; }; + 742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequestHandler.h; path = Network/WXResourceRequestHandler.h; sourceTree = ""; }; + 742AD7281DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequestHandlerDefaultImpl.h; path = Network/WXResourceRequestHandlerDefaultImpl.h; sourceTree = ""; }; + 742AD7291DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceRequestHandlerDefaultImpl.m; path = Network/WXResourceRequestHandlerDefaultImpl.m; sourceTree = ""; }; + 742AD72A1DF98C45007DC46C /* WXResourceResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceResponse.h; path = Network/WXResourceResponse.h; sourceTree = ""; }; + 742AD72B1DF98C45007DC46C /* WXResourceResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceResponse.m; path = Network/WXResourceResponse.m; sourceTree = ""; }; + 742AD7381DF98C8B007DC46C /* WXResourceLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceLoader.h; path = Loader/WXResourceLoader.h; sourceTree = ""; }; + 742AD7391DF98C8B007DC46C /* WXResourceLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceLoader.m; path = Loader/WXResourceLoader.m; sourceTree = ""; }; 743933B21C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXSimulatorShortcutMananger.h; sourceTree = ""; }; 743933B31C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXSimulatorShortcutMananger.m; sourceTree = ""; }; 744BEA531D05178F00452B5D /* WXComponent+Display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+Display.h"; sourceTree = ""; }; @@ -373,8 +385,6 @@ 7469869E1C4E2C000054A57E /* NSArray+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Weex.m"; sourceTree = ""; }; 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLocationModule.h; sourceTree = ""; }; 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXLocationModule.m; sourceTree = ""; }; - 746A2F441DF826A9004719D0 /* WXResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXResourceRequest.h; sourceTree = ""; }; - 746A2F451DF826A9004719D0 /* WXResourceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXResourceRequest.m; sourceTree = ""; }; 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+ViewManagement.h"; sourceTree = ""; }; 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+ViewManagement.m"; sourceTree = ""; }; 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+WXSwizzle.h"; sourceTree = ""; }; @@ -560,8 +570,6 @@ children = ( 59A583041CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h */, 59A583051CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m */, - 59A583061CF5B2FD0081FD3E /* WXNetworkDefaultImpl.h */, - 59A583071CF5B2FD0081FD3E /* WXNetworkDefaultImpl.m */, 74EF31AB1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h */, 74EF31AC1DE58BE200667A07 /* WXURLRewriteDefaultImpl.m */, ); @@ -588,6 +596,15 @@ path = Events; sourceTree = ""; }; + 742AD7371DF98C72007DC46C /* Loader */ = { + isa = PBXGroup; + children = ( + 742AD7381DF98C8B007DC46C /* WXResourceLoader.h */, + 742AD7391DF98C8B007DC46C /* WXResourceLoader.m */, + ); + name = Loader; + sourceTree = ""; + }; 745ED2D31C5F2C7E002DB5A8 /* View */ = { isa = PBXGroup; children = ( @@ -623,8 +640,13 @@ 746A2F431DF82607004719D0 /* Network */ = { isa = PBXGroup; children = ( - 746A2F441DF826A9004719D0 /* WXResourceRequest.h */, - 746A2F451DF826A9004719D0 /* WXResourceRequest.m */, + 742AD7251DF98C45007DC46C /* WXResourceRequest.h */, + 742AD7261DF98C45007DC46C /* WXResourceRequest.m */, + 742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */, + 742AD7281DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h */, + 742AD7291DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m */, + 742AD72A1DF98C45007DC46C /* WXResourceResponse.h */, + 742AD72B1DF98C45007DC46C /* WXResourceResponse.m */, ); name = Network; sourceTree = ""; @@ -741,6 +763,7 @@ children = ( DC0F99301D48E5320087C6AF /* WeexSDK.h */, 2AF626C61C191E2200E71A38 /* Layout */, + 742AD7371DF98C72007DC46C /* Loader */, 7408C48B1CFB345D000BCCD0 /* Events */, 7461F88B1CFB373100F62D44 /* Display */, 74A4BA581CABBBA300195969 /* Debug */, @@ -1062,11 +1085,12 @@ D312CE3B1C730DEB00046D68 /* WXWebComponent.h in Headers */, 741081261CEDB4EC001BC6E5 /* WXComponent_internal.h in Headers */, 77E65A191C155F25008B8775 /* WXScrollerComponent.h in Headers */, + 742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */, DC03ADBA1D508719003F76E7 /* WXTextAreaComponent.h in Headers */, 2AC750241C7565690041D390 /* WXIndicatorComponent.h in Headers */, DCAB35FE1D658EB700C0EA70 /* WXRuleManager.h in Headers */, 748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */, - 746A2F461DF826A9004719D0 /* WXResourceRequest.h in Headers */, + 742AD7331DF98C45007DC46C /* WXResourceResponse.h in Headers */, 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */, C41E1A971DC1FD15009C7F90 /* WXDatePickerManager.h in Headers */, 7461F8901CFB373100F62D44 /* WXDisplayQueue.h in Headers */, @@ -1080,6 +1104,7 @@ C4B834281DE69B09007AD27E /* WXPickerModule.h in Headers */, 59A596311CB632050012CD52 /* WXRootViewController.h in Headers */, DCF087611DCAE161005CD6EB /* WXInvocationConfig.h in Headers */, + 742AD7301DF98C45007DC46C /* WXResourceRequestHandler.h in Headers */, 77E65A151C155EB5008B8775 /* WXTextComponent.h in Headers */, 74CC7A1C1C2BC5F800829368 /* WXCellComponent.h in Headers */, 74896F301D1AC79400D1D593 /* NSObject+WXSwizzle.h in Headers */, @@ -1095,8 +1120,8 @@ 746319021C60AFC100EFEBD4 /* WXThreadSafeCounter.h in Headers */, 77D1613C1C02DEA60010B15B /* WXJSCoreBridge.h in Headers */, 741DFE061DDD9B30009B020F /* UIBezierPath+Weex.h in Headers */, - 59A5830A1CF5B2FD0081FD3E /* WXNetworkDefaultImpl.h in Headers */, 2AAFC1B61C48DFF70026D2FE /* WXSDKError.h in Headers */, + 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */, D317338C1C57257000BB7539 /* WXTransform.h in Headers */, 77D161301C02DE4E0010B15B /* WXComponent.h in Headers */, 2AFEB17B1C747139000507FA /* WXInstanceWrap.h in Headers */, @@ -1104,6 +1129,7 @@ 741081231CED6756001BC6E5 /* WXComponentFactory.h in Headers */, 59D3CA4A1CFC3CE1008835DC /* NSTimer+Weex.h in Headers */, D334510C1D3E19B80083598A /* WXCanvasModule.h in Headers */, + 742AD73A1DF98C8B007DC46C /* WXResourceLoader.h in Headers */, 746319291C71B92600EFEBD4 /* WXModalUIModule.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1303,6 +1329,7 @@ 74896F311D1AC79400D1D593 /* NSObject+WXSwizzle.m in Sources */, 746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */, 74B8BEFF1DC47B72004A6027 /* WXRootView.m in Sources */, + 742AD7321DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m in Sources */, 77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */, 2A60CE9D1C91733E00857B9F /* WXSwitchComponent.m in Sources */, 2A837AB71CD9DE9200AEDF03 /* WXRefreshComponent.m in Sources */, @@ -1311,7 +1338,6 @@ 747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m in Sources */, 2A837AB51CD9DE9200AEDF03 /* WXLoadingIndicator.m in Sources */, 59D3CA401CF9ED57008835DC /* Layout.c in Sources */, - 59A5830B1CF5B2FD0081FD3E /* WXNetworkDefaultImpl.m in Sources */, DCF087621DCAE161005CD6EB /* WXInvocationConfig.m in Sources */, 77D161311C02DE4E0010B15B /* WXComponent.m in Sources */, 77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */, @@ -1335,6 +1361,7 @@ 59A596321CB632050012CD52 /* WXRootViewController.m in Sources */, DCC77C131D770AE300CE7288 /* WXSliderNeighborComponent.m in Sources */, 2A8E658B1C7C7AA20025C7B7 /* WXVideoComponent.m in Sources */, + 742AD7341DF98C45007DC46C /* WXResourceResponse.m in Sources */, 77E65A161C155EB5008B8775 /* WXTextComponent.m in Sources */, 746319031C60AFC100EFEBD4 /* WXThreadSafeCounter.m in Sources */, 74A4BAA71CB4F98300195969 /* WXStreamModule.m in Sources */, @@ -1349,6 +1376,7 @@ 59A596251CB6311F0012CD52 /* WXStorageModule.m in Sources */, 2AFEB17C1C747139000507FA /* WXInstanceWrap.m in Sources */, 74A4BA5C1CABBBD000195969 /* WXDebugTool.m in Sources */, + 742AD73B1DF98C8B007DC46C /* WXResourceLoader.m in Sources */, D334510D1D3E19B80083598A /* WXCanvasModule.m in Sources */, 741081241CED6756001BC6E5 /* WXComponentFactory.m in Sources */, D362F9501C83EDA20003F546 /* WXWebViewModule.m in Sources */, @@ -1374,6 +1402,7 @@ 7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */, 77D161501C02E3880010B15B /* WXUtility.m in Sources */, 74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */, + 742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */, 7461F8931CFB373100F62D44 /* WXLayer.m in Sources */, 59D3CA471CFC3CC0008835DC /* WXSliderComponent.m in Sources */, 77D1613D1C02DEA60010B15B /* WXJSCoreBridge.m in Sources */, @@ -1381,7 +1410,6 @@ 77D1614C1C02E3790010B15B /* WXConvert.m in Sources */, 749DC27C1D40827B009E1C91 /* WXMonitor.m in Sources */, 77E659FB1C0EE579008B8775 /* WXBridgeMethod.m in Sources */, - 746A2F471DF826A9004719D0 /* WXResourceRequest.m in Sources */, C4B834271DE69B09007AD27E /* WXPickerModule.m in Sources */, 77D161391C02DE940010B15B /* WXBridgeManager.m in Sources */, ); diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 6baac1d9a7..ecf978bbf0 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -208,7 +208,7 @@ - (void)updatePlaceHolderWithFailedBlock:(void(^)(NSString *, NSError *))downloa if (placeholderSrc) { WXLogDebug(@"Updating image, component:%@, placeholder:%@ ", self.ref, placeholderSrc); NSMutableString *newURL = [_placeholdSrc mutableCopy]; - WX_REWRITE_URL(_placeholdSrc, WXResourceTypeLink, self.weexInstance, &newURL) + WX_REWRITE_URL(_placeholdSrc, WXResourceTypeImage, self.weexInstance, &newURL) __weak typeof(self) weakSelf = self; self.placeholderOperation = [[self imageLoader] downloadImageWithURL:newURL imageFrame:self.calculatedFrame userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) { @@ -242,7 +242,7 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo WXLogDebug(@"Updating image:%@, component:%@", self.imageSrc, self.ref); NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp)}; NSMutableString * newURL = [imageSrc mutableCopy]; - WX_REWRITE_URL(imageSrc, WXResourceTypeLink, self.weexInstance, &newURL) + WX_REWRITE_URL(imageSrc, WXResourceTypeImage, self.weexInstance, &newURL) __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.imageOperation = [[weakSelf imageLoader] downloadImageWithURL:newURL imageFrame:weakSelf.calculatedFrame userInfo:userInfo completed:^(UIImage *image, NSError *error, BOOL finished) { diff --git a/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m index 4b8cad2bd3..135ba96215 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m @@ -140,7 +140,7 @@ - (void)setFrame:(CGRect)frame - (void)setURL:(NSURL *)URL { NSMutableString *urlStr = nil; - WX_REWRITE_URL(URL.absoluteString, WXResourceTypeLink, self.weexSDKInstance, &urlStr) + WX_REWRITE_URL(URL.absoluteString, WXResourceTypeVideo, self.weexSDKInstance, &urlStr) if (!urlStr) { return; diff --git a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m index 99cef4753a..4cee17838e 100644 --- a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m +++ b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m @@ -90,8 +90,11 @@ + (void)getData:(NSURL*)url key:(NSString*)key{ // HTTP/HTTPS URL NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; - + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; +#pragma GCC diagnostic pop __block NSURLResponse *urlResponse; [networkHandler sendRequest:request diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m index d9804923f7..bb75540200 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m @@ -12,9 +12,10 @@ #import "WXComponentFactory.h" #import "WXAppConfiguration.h" -#import "WXNetworkDefaultImpl.h" +#import "WXResourceRequestHandlerDefaultImpl.h" #import "WXNavigationDefaultImpl.h" #import "WXURLRewriteDefaultImpl.h" + #import "WXSDKManager.h" #import "WXSDKError.h" #import "WXMonitor.h" @@ -119,7 +120,7 @@ + (void)registerComponent:(NSString *)name withClass:(Class)clazz withProperties // register some default handlers when the engine initializes. + (void)_registerDefaultHandlers { - [self registerHandler:[WXNetworkDefaultImpl new] withProtocol:@protocol(WXNetworkProtocol)]; + [self registerHandler:[WXResourceRequestHandlerDefaultImpl new] withProtocol:@protocol(WXResourceRequestHandler)]; [self registerHandler:[WXNavigationDefaultImpl new] withProtocol:@protocol(WXNavigationProtocol)]; [self registerHandler:[WXURLRewriteDefaultImpl new] withProtocol:@protocol(WXURLRewriteProtocol)]; } diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h index 160a2229b8..a0d69c76aa 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h @@ -34,9 +34,10 @@ typedef NS_ENUM(int, WXSDKErrCode) WX_ERR_RENDER_SCROLLTOELEMENT = -2110, WX_ERR_RENDER_END = -2199, - WX_ERR_JSDOWNLOAD_START = -2201, + WX_ERR_DOWNLOAD_START = -2201, WX_ERR_JSBUNDLE_DOWNLOAD = -2202, WX_ERR_JSBUNDLE_STRING_CONVERT = -2203, - WX_ERR_JSDOWNLOAD_END = -2299, + WX_ERR_CANCEL = -2204, + WX_ERR_DOWNLOAD_END = -2299, }; diff --git a/ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.m b/ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.m deleted file mode 100644 index 55f9af584a..0000000000 --- a/ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.m +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Created by Weex. - * Copyright (c) 2016, Alibaba, Inc. All rights reserved. - * - * This source code is licensed under the Apache Licence 2.0. - * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. - */ - -#import "WXNetworkDefaultImpl.h" -#import "WXAppConfiguration.h" - -@interface WXNetworkCallbackInfo : NSObject - -@property (nonatomic, copy) void(^sendDataCallback)(int64_t, int64_t); -@property (nonatomic, copy) void(^responseCallback)(NSURLResponse *); -@property (nonatomic, copy) void(^receiveDataCallback)(NSData *); -@property (nonatomic, strong) NSMutableData *data; -@property (nonatomic, copy) void(^compeletionCallback)(NSData *, NSError *); - -@end - -@implementation WXNetworkCallbackInfo - -@end - -@implementation WXNetworkDefaultImpl -{ - NSMutableDictionary *_callbacks; - NSURLSession *_session; -} - -- (id)sendRequest:(NSURLRequest *)request withSendingData:(void (^)(int64_t, int64_t))sendDataCallback - withResponse:(void (^)(NSURLResponse *))responseCallback - withReceiveData:(void (^)(NSData *))receiveDataCallback - withCompeletion:(void (^)(NSData *, NSError *))compeletionCallback -{ - WXNetworkCallbackInfo *info = [WXNetworkCallbackInfo new]; - info.sendDataCallback = sendDataCallback; - info.responseCallback = responseCallback; - info.receiveDataCallback = receiveDataCallback; - info.compeletionCallback = compeletionCallback; - - if (!_session) { - NSURLSessionConfiguration *urlSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - if ([WXAppConfiguration customizeProtocolClasses] && [WXAppConfiguration customizeProtocolClasses].count > 0) { - NSArray *defaultProtocols = urlSessionConfig.protocolClasses; - urlSessionConfig.protocolClasses = [[WXAppConfiguration customizeProtocolClasses] arrayByAddingObjectsFromArray:defaultProtocols]; - } - _session = [NSURLSession sessionWithConfiguration:urlSessionConfig - delegate:self - delegateQueue:[NSOperationQueue mainQueue]]; - } - - NSURLSessionDataTask *task = [_session dataTaskWithRequest:request]; - if (!_callbacks) { - _callbacks = [NSMutableDictionary dictionary]; - } - [_callbacks setObject:info forKey:task]; - [task resume]; - - return task; -} - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task - didSendBodyData:(int64_t)bytesSent - totalBytesSent:(int64_t)totalBytesSent - totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend -{ - WXNetworkCallbackInfo *info = [_callbacks objectForKey:task]; - if (info.sendDataCallback) { - info.sendDataCallback(totalBytesSent, totalBytesExpectedToSend); - } -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task - didReceiveResponse:(NSURLResponse *)response - completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler -{ - WXNetworkCallbackInfo *info = [_callbacks objectForKey:task]; - if (info.responseCallback) { - info.responseCallback(response); - } - completionHandler(NSURLSessionResponseAllow); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data -{ - WXNetworkCallbackInfo *info = [_callbacks objectForKey:task]; - if (info.receiveDataCallback) { - info.receiveDataCallback(data); - } - - NSMutableData *mutableData = info.data; - if (!mutableData) { - mutableData = [NSMutableData new]; - info.data = mutableData; - } - - [mutableData appendData:data]; -} - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error -{ - WXNetworkCallbackInfo *info = [_callbacks objectForKey:task]; - if (info.compeletionCallback) { - info.compeletionCallback(info.data, error); - } - [_callbacks removeObjectForKey:task]; -} - -@end diff --git a/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h new file mode 100644 index 0000000000..1d6fbe5357 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h @@ -0,0 +1,30 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import +@class WXResourceRequest; +@class WXResourceResponse; + + +@interface WXResourceLoader : NSObject + +@property (nonatomic, strong) WXResourceRequest *request; + +@property (nonatomic, copy) void (^onDataSent)(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */); +@property (nonatomic, copy) void (^onResponseReceived)(const WXResourceResponse *); +@property (nonatomic, copy) void (^onDataReceived)(NSData *); +@property (nonatomic, copy) void (^onFinished)(const WXResourceResponse *, NSData *); +@property (nonatomic, copy) void (^onFailed)(NSError *); + +- (instancetype)initWithRequest:(WXResourceRequest *)request; + +- (void)start; + +- (void)cancel:(NSError **)error; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.m b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.m new file mode 100644 index 0000000000..4232b7fa2f --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.m @@ -0,0 +1,174 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ +#import "WXResourceLoader.h" +#import "WXResourceRequestHandler.h" +#import "WXSDKInstance.h" +#import "WXLog.h" +#import "WXHandlerFactory.h" +#import "WXSDKError.h" + +//deprecated +#import "WXNetworkProtocol.h" + +@interface WXResourceLoader () + +@end + +@implementation WXResourceLoader +{ + NSMutableData *_data; + WXResourceResponse *_response; +} + +- (instancetype)initWithRequest:(WXResourceRequest *)request +{ + if (self = [super init]) { + self.request = request; + } + + return self; +} + +- (void)setRequest:(WXResourceRequest *)request +{ + if (_request) { + [self cancel:nil]; + } + + _request = request; +} + +- (void)start +{ + if ([_request.URL isFileURL]) { + [self _handleFileURL:_request.URL]; + return; + } + + id requestHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXResourceRequestHandler)]; + if (requestHandler) { + [requestHandler sendRequest:_request withDelegate:self]; + } else if ([WXHandlerFactory handlerForProtocol:NSProtocolFromString(@"WXNetworkProtocol")]){ + // deprecated logic + [self _handleDEPRECATEDNetworkHandler]; + } else { + WXLogError(@"No resource request handler found!"); + } +} + +- (void)cancel:(NSError *__autoreleasing *)error +{ + id requestHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXResourceRequestHandler)]; + if ([requestHandler respondsToSelector:@selector(cancelRequest:)]) { + [requestHandler cancelRequest:_request]; + } else if (error) { + *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:WX_ERR_CANCEL userInfo:@{NSLocalizedDescriptionKey: @"handle:%@ not respond to cancelRequest"}]; + } +} + +- (void)_handleFileURL:(NSURL *)url +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSData *fileData = [[NSFileManager defaultManager] contentsAtPath:[url path]]; + if (self.onFinished) { + self.onFinished([WXResourceResponse new], fileData); + } + }); +} + +- (void)_handleDEPRECATEDNetworkHandler +{ + WXLogWarning(@"WXNetworkProtocol is deprecated, use WXResourceRequestHandler instead!"); + id networkHandler = [WXHandlerFactory handlerForProtocol:NSProtocolFromString(@"WXNetworkProtocol")]; + __weak typeof(self) weakSelf = self; + [networkHandler sendRequest:_request withSendingData:^(int64_t bytesSent, int64_t totalBytes) { + if (weakSelf.onDataSent) { + weakSelf.onDataSent(bytesSent, totalBytes); + } + } withResponse:^(NSURLResponse *response) { + _response = (WXResourceResponse *)response; + if (weakSelf.onResponseReceived) { + weakSelf.onResponseReceived((WXResourceResponse *)response); + } + } withReceiveData:^(NSData *data) { + if (weakSelf.onDataReceived) { + weakSelf.onDataReceived(data); + } + } withCompeletion:^(NSData *totalData, NSError *error) { + if (error) { + if (weakSelf.onFailed) { + weakSelf.onFailed(error); + } + } else { + weakSelf.onFinished(_response, totalData); + _response = nil; + } + }]; +} + +#pragma mark - WXResourceRequestDelegate + +- (void)request:(WXResourceRequest *)request didSendData:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent +{ + WXLogDebug(@"request:%@ didSendData:%llu totalBytesToBeSent:%llu", request, bytesSent, totalBytesToBeSent); + + if (self.onDataSent) { + self.onDataSent(bytesSent, totalBytesToBeSent); + } +} + +- (void)request:(WXResourceRequest *)request didReceiveResponse:(WXResourceResponse *)response +{ + WXLogDebug(@"request:%@ didReceiveResponse:%@ ", request, response); + + _response = response; + + if (self.onResponseReceived) { + self.onResponseReceived(response); + } +} + +- (void)request:(WXResourceRequest *)request didReceiveData:(NSData *)data +{ + WXLogDebug(@"request:%@ didReceiveDataLength:%ld", request, data.length); + + if (!_data) { + _data = [NSMutableData new]; + } + [_data appendData:data]; + + if (self.onDataReceived) { + self.onDataReceived(data); + } +} + +- (void)requestDidFinishLoading:(WXResourceRequest *)request +{ + WXLogDebug(@"request:%@ requestDidFinishLoading", request); + + if (self.onFinished) { + self.onFinished(_response, _data); + } + + _data = nil; + _response = nil; +} + +- (void)request:(WXResourceRequest *)request didFailWithError:(NSError *)error +{ + WXLogDebug(@"request:%@ didFailWithError:%@", request, error.localizedDescription); + + if (self.onFailed) { + self.onFailed(error); + } + + _data = nil; + _response = nil; +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m index 652af2bf19..2703883bfa 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m @@ -8,7 +8,6 @@ #import "WXHandlerFactory.h" #import "WXThreadSafeMutableDictionary.h" -#import "WXNetworkDefaultImpl.h" #import "WXNavigationDefaultImpl.h" #import "WXAssert.h" diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXRuleManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXRuleManager.m index f45882db3d..4802638ccc 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXRuleManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXRuleManager.m @@ -63,7 +63,7 @@ - (void)addRule:(NSString*)type rule:(NSDictionary *)rule NSString *fontSrc = [rule[@"src"] substringWithRange:NSMakeRange(start, end-start)]; NSMutableString *newFontSrc = [fontSrc mutableCopy]; - WX_REWRITE_URL(fontSrc, WXResourceTypeLink, self.instance, &newFontSrc) + WX_REWRITE_URL(fontSrc, WXResourceTypeFont, self.instance, &newFontSrc) if (!newFontSrc) { return; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index 965047b1c1..786f98294d 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -158,16 +158,16 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code **/ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data; -/** - * Renders weex view with resource request. - * - * @param request The resource request specifying the URL to render with. - * - * @param options The params passed by user. - * - * @param data The data the bundle needs when rendered. Defalut is nil. - **/ -- (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; +///** +// * Renders weex view with resource request. +// * +// * @param request The resource request specifying the URL to render with. +// * +// * @param options The params passed by user. +// * +// * @param data The data the bundle needs when rendered. Defalut is nil. +// **/ +//- (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; /** * Renders weex view with source string of bundle and some others. @@ -232,12 +232,18 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code @property (nonatomic, strong) NSMutableDictionary *performanceDict; +/** + * Deprecated + */ @property (nonatomic, strong) NSDictionary *properties DEPRECATED_MSG_ATTRIBUTE(); @property (nonatomic, assign) NSTimeInterval networkTime DEPRECATED_MSG_ATTRIBUTE(); @property (nonatomic, copy) void (^updateFinish)(UIView *); -- (void)finishPerformance DEPRECATED_MSG_ATTRIBUTE(); +@end + +@interface WXSDKInstance (Deprecated) +- (void)finishPerformance DEPRECATED_MSG_ATTRIBUTE(); - (void)reloadData:(id)data DEPRECATED_MSG_ATTRIBUTE("Use refreshInstance: method instead."); - (void)creatFinish DEPRECATED_MSG_ATTRIBUTE(); diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index fc65830c82..d9ef7191bd 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -23,6 +23,8 @@ #import "WXRootView.h" #import "WXThreadSafeMutableDictionary.h" #import "WXResourceRequest.h" +#import "WXResourceResponse.h" +#import "WXResourceLoader.h" NSString *const bundleUrlOptionKey = @"bundleUrl"; @@ -39,14 +41,14 @@ @implementation WXSDKInstance { NSDictionary *_options; - id _data; + id _jsData; - id _networkHandler; + WXResourceLoader *_mainBundleLoader; WXComponentManager *_componentManager; WXRootView *_rootView; } -- (void) dealloc +- (void)dealloc { [self removeObservers]; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -114,17 +116,22 @@ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data return; } - WXResourceRequest *request = [WXResourceRequest requestWithURL:url referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; - [self renderWithRequest:request options:options data:data]; + WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; + [self _renderWithRequest:request options:options data:data]; } - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data { - WXLogDebug(@"Render view: %@, data:%@", self, [WXUtility JSONString:data]); + WXLogDebug(@"Render source: %@, data:%@", self, [WXUtility JSONString:data]); _options = options; - _data = data; + _jsData = data; + [self _renderWithMainBundleString:source]; +} + +- (void)_renderWithMainBundleString:(NSString *)mainBundleString +{ if (!self.instanceId) { WXLogError(@"Fail to find instance!"); return; @@ -139,13 +146,13 @@ - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)d WX_MONITOR_INSTANCE_PERF_START(WXPTFirstScreenRender, self); WX_MONITOR_INSTANCE_PERF_START(WXPTAllRender, self); - NSMutableDictionary *dictionary = [options mutableCopy]; + NSMutableDictionary *dictionary = [_options mutableCopy]; if ([WXLog logLevel] >= WXLogLevelLog) { dictionary[@"debug"] = @(YES); } if ([WXDebugTool getReplacedBundleJS]) { - source = [WXDebugTool getReplacedBundleJS]; + mainBundleString = [WXDebugTool getReplacedBundleJS]; } //TODO WXRootView @@ -156,17 +163,19 @@ - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)d self.onCreate(_rootView); } }); - - [[WXSDKManager bridgeMgr] createInstance:self.instanceId template:source options:dictionary data:data]; - - WX_MONITOR_PERF_SET(WXPTBundleSize, [source lengthOfBytesUsingEncoding:NSUTF8StringEncoding], self); + + [[WXSDKManager bridgeMgr] createInstance:self.instanceId template:mainBundleString options:dictionary data:_jsData]; + + WX_MONITOR_PERF_SET(WXPTBundleSize, [mainBundleString lengthOfBytesUsingEncoding:NSUTF8StringEncoding], self); } -- (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; +- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data; { NSURL *url = request.URL; _scriptURL = url; + _options = options; + _jsData = data; NSMutableDictionary *newOptions = [options mutableCopy] ?: [NSMutableDictionary new]; if (!newOptions[bundleUrlOptionKey]) { @@ -182,102 +191,69 @@ - (void)renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)o self.pageName = [WXUtility urlByDeletingParameters:url].absoluteString ? : @""; } - [self loadRequest:request loadType:WXLoadTypeNormal options:newOptions data:data]; -} - -- (void)loadRequest:(WXResourceRequest *)request loadType:(WXLoadType)loadType options:(NSDictionary *)options data:(id)data; -{ request.userAgent = [WXUtility userAgent]; + + WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self); __weak typeof(self) weakSelf = self; - if ([url isFileURL]) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSString *path = [url path]; - NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path]; - NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding]; - if (!script || script.length <= 0) { - NSString *errorDesc = [NSString stringWithFormat:@"File read error at url: %@", url]; - WXLogError(@"%@", errorDesc); - if (weakSelf.onFailed) { - weakSelf.onFailed([NSError errorWithDomain:WX_ERROR_DOMAIN code:0 userInfo:@{NSLocalizedDescriptionKey: errorDesc}]); - } - return; - } - [weakSelf renderView:script options:newOptions data:data]; - }); - } else { - WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self); + _mainBundleLoader = [[WXResourceLoader alloc] initWithRequest:request];; + _mainBundleLoader.onFinished = ^(WXResourceResponse *response, NSData *data) { + __strong typeof(weakSelf) strongSelf = weakSelf; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; - [request setValue:@"weex" forHTTPHeaderField:@"f-refer"]; + if ([response isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)response).statusCode != 200) { + NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN + code:((NSHTTPURLResponse *)response).statusCode + userInfo:@{@"message":@"status code error."}]; + if (strongSelf.onFailed) { + strongSelf.onFailed(error); + } + return ; + } + + if (!data) { + NSString *errorMessage = [NSString stringWithFormat:@"Request to %@ With no data return", request.URL]; + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, strongSelf.pageName); + + if (strongSelf.onFailed) { + strongSelf.onFailed(error); + } + return; + } - id networkHandler = [self networkHandler]; + NSString *jsBundleString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (!jsBundleString) { + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", strongSelf.pageName) + return; + } + + WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, strongSelf.pageName); + WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, strongSelf); + + [strongSelf _renderWithMainBundleString:jsBundleString]; + }; + + _mainBundleLoader.onFailed = ^(NSError *loadError) { + NSString *errorMessage = [NSString stringWithFormat:@"Request to %@ occurs an error:%@", request.URL, loadError.localizedDescription]; + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); - __block NSURLResponse *urlResponse; - [networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} - withResponse:^(NSURLResponse *response) { - urlResponse = response; - } - withReceiveData:^(NSData *data) {} - withCompeletion:^(NSData *totalData, NSError *error) { - //TODO 304 - if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { - error = [NSError errorWithDomain:WX_ERROR_DOMAIN - code:((NSHTTPURLResponse *)urlResponse).statusCode - userInfo:@{@"message":@"status code error."}]; - } - - if (error) { - NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ occurs an error:%@", request.URL, error.localizedDescription]; - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); - - if (weakSelf.onFailed) { - weakSelf.onFailed(error); - } - return; - } - - if (!totalData) { - NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ but no data return", request.URL]; - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); - - if (weakSelf.onFailed) { - weakSelf.onFailed(error); - } - return; - } - - NSString *script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding]; - if (!script) { - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", weakSelf.pageName) - return; - } - - WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, weakSelf.pageName); - WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, weakSelf); - - [weakSelf renderView:script options:newOptions data:data]; - }]; - } + if (weakSelf.onFailed) { + weakSelf.onFailed(loadError); + } + }; + + [_mainBundleLoader start]; } - (void)reload:(BOOL)forcedReload { - // TODO: [self cancel] + // TODO: [self unload] if (!_scriptURL) { WXLogError(@"No script URL found while reloading!"); return; } NSURLRequestCachePolicy cachePolicy = forcedReload ? NSURLRequestReloadIgnoringCacheData : NSURLRequestUseProtocolCachePolicy; - WXResourceRequest *request = [WXResourceRequest requestWithURL:_scriptURL referrer:_scriptURL.absoluteString cachePolicy:cachePolicy]; - [self renderWithRequest:request options:_options data:_data]; -} - -- (void)reloadData:(id)data -{ - [self refreshInstance:data]; + WXResourceRequest *request = [WXResourceRequest requestWithURL:_scriptURL resourceType:WXResourceTypeMainBundle referrer:_scriptURL.absoluteString cachePolicy:cachePolicy]; + [self _renderWithRequest:request options:_options data:_jsData]; } - (void)refreshInstance:(id)data @@ -355,16 +331,6 @@ - (NSUInteger)numberOfComponents return [_componentManager numberOfComponents]; } -- (void)finishPerformance -{ - //deperacated -} - -- (void)creatFinish -{ - -} - - (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params { if (!params){ @@ -411,15 +377,6 @@ - (WXComponentManager *)componentManager return _componentManager; } -- (id)networkHandler -{ - if (!_networkHandler) { - _networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; - } - - return _networkHandler; -} - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"state"]) { @@ -433,3 +390,24 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } @end + +@implementation WXSDKInstance (Deprecated) + +# pragma mark - Deprecated + +- (void)reloadData:(id)data +{ + [self refreshInstance:data]; +} + +- (void)finishPerformance +{ + //deperacated +} + +- (void)creatFinish +{ + +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m index 594c0d29ba..2c9cd63764 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m @@ -38,8 +38,13 @@ - (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback } [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; +#pragma GCC diagnostic pop + [networkHandler sendRequest:request withSendingData:^(int64_t bytesSent, int64_t totalBytes) { } withResponse:^(NSURLResponse *response) { @@ -101,7 +106,11 @@ - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progre progressCallback(callbackRsp, TRUE); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; +#pragma GCC diagnostic pop + __block NSString *respEncode = nil; __weak typeof(self) weakSelf = self; [networkHandler sendRequest:request diff --git a/ios/sdk/WeexSDK/Sources/WXResourceRequest.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h similarity index 64% rename from ios/sdk/WeexSDK/Sources/WXResourceRequest.h rename to ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h index bd6c22dab1..eea31266b4 100644 --- a/ios/sdk/WeexSDK/Sources/WXResourceRequest.h +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h @@ -8,12 +8,26 @@ #import +typedef enum : NSUInteger { + WXResourceTypeMainBundle, + WXResourceTypeImage, + WXResourceTypeFont, + WXResourceTypeVideo, + WXResourceTypeLink, + WXResourceTypeOthers +} WXResourceType; + + @interface WXResourceRequest : NSMutableURLRequest +@property (nonatomic, strong) id taskIdentifier; +@property (nonatomic, assign) WXResourceType type; + @property (nonatomic, strong) NSString *referrer; @property (nonatomic, strong) NSString *userAgent; + (instancetype)requestWithURL:(NSURL *)url + resourceType:(WXResourceType)type referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy; diff --git a/ios/sdk/WeexSDK/Sources/WXResourceRequest.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m similarity index 54% rename from ios/sdk/WeexSDK/Sources/WXResourceRequest.m rename to ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m index 2a060a8fcc..b161d8fff5 100644 --- a/ios/sdk/WeexSDK/Sources/WXResourceRequest.m +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m @@ -13,14 +13,20 @@ @implementation WXResourceRequest -+ (instancetype)requestWithURL:(NSURL *)url referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy ++ (instancetype)requestWithURL:(NSURL *)url + resourceType:(WXResourceType)type + referrer:(NSString *)referrer + cachePolicy:(NSURLRequestCachePolicy)cachePolicy { - return [[self alloc] initWithURL:url referrer:referrer cachePolicy:cachePolicy]; + return [[self alloc] initWithURL:url resourceType:type referrer:referrer cachePolicy:cachePolicy]; } -- (instancetype)initWithURL:(NSURL *)url referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy +- (instancetype)initWithURL:(NSURL *)url + resourceType:(WXResourceType)type + referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy { if (self = [super initWithURL:url]) { + self.type = type; self.cachePolicy = cachePolicy; [self setValue:referrer forHTTPHeaderField:kHTTPHeaderNameReferrer]; } @@ -30,22 +36,22 @@ - (instancetype)initWithURL:(NSURL *)url referrer:(NSString *)referrer cachePoli - (NSString *)referrer { - return [self valueForKey:kHTTPHeaderNameReferrer]; + return [self valueForHTTPHeaderField:kHTTPHeaderNameReferrer]; } - (void)setReferrer:(NSString *)referrer { - [self setValue:referrer forKey:kHTTPHeaderNameReferrer]; + [self setValue:referrer forHTTPHeaderField:kHTTPHeaderNameReferrer]; } - (NSString *)userAgent { - return [self valueForKey:kHTTPHeaderNameUserAgent]; + return [self valueForHTTPHeaderField:kHTTPHeaderNameUserAgent]; } - (void)setUserAgent:(NSString *)userAgent { - [self setValue:userAgent forKey:kHTTPHeaderNameUserAgent]; + [self setValue:userAgent forHTTPHeaderField:kHTTPHeaderNameUserAgent]; } @end diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h new file mode 100644 index 0000000000..7f5393b0ef --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h @@ -0,0 +1,45 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + + +#import +#import "WXResourceRequest.h" +#import "WXResourceResponse.h" + +@protocol WXResourceRequestDelegate + +// Periodically informs the delegate of the progress of sending content to the server. +- (void)request:(WXResourceRequest *)request didSendData:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent; + +// Tells the delegate that the request received the initial reply (headers) from the server. +- (void)request:(WXResourceRequest *)request didReceiveResponse:(WXResourceResponse *)response; + +// Tells the delegate that the request has received some of the expected data. +- (void)request:(WXResourceRequest *)request didReceiveData:(NSData *)data; + +// Tells the delegate that the request finished transferring data. +- (void)requestDidFinishLoading:(WXResourceRequest *)request; + +// Tells the delegate that the request failed to load successfully. +- (void)request:(WXResourceRequest *)request didFailWithError:(NSError *)error; + +@end + +@protocol WXResourceRequestHandler + +// Send a resource request with a delegate +- (void)sendRequest:(WXResourceRequest *)request withDelegate:(id)delegate; + +@optional + +// Cancel the ongoing request +- (void)cancelRequest:(WXResourceRequest *)request; + +@end + + diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h new file mode 100644 index 0000000000..d68ca8c724 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h @@ -0,0 +1,15 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + + +#import +#import "WXResourceRequestHandler.h" + +@interface WXResourceRequestHandlerDefaultImpl : NSObject + +@end diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m new file mode 100644 index 0000000000..211471f95a --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m @@ -0,0 +1,90 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + + +#import "WXResourceRequestHandlerDefaultImpl.h" +#import "WXThreadSafeMutableDictionary.h" +#import "WXAppConfiguration.h" + +@interface WXResourceRequestHandlerDefaultImpl () + +@end + +@implementation WXResourceRequestHandlerDefaultImpl +{ + NSURLSession *_session; + WXThreadSafeMutableDictionary> *_delegates; +} + +#pragma mark - WXResourceRequestHandler + +- (void)sendRequest:(WXResourceRequest *)request withDelegate:(id)delegate +{ + if (!_session) { + NSURLSessionConfiguration *urlSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + if ([WXAppConfiguration customizeProtocolClasses].count > 0) { + NSArray *defaultProtocols = urlSessionConfig.protocolClasses; + urlSessionConfig.protocolClasses = [[WXAppConfiguration customizeProtocolClasses] arrayByAddingObjectsFromArray:defaultProtocols]; + } + _session = [NSURLSession sessionWithConfiguration:urlSessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + _delegates = [WXThreadSafeMutableDictionary new]; + } + + NSURLSessionDataTask *task = [_session dataTaskWithRequest:request]; + request.taskIdentifier = task; + [_delegates setObject:delegate forKey:task]; + [task resume]; +} + +- (void)cancelRequest:(WXResourceRequest *)request +{ + if ([request.taskIdentifier isKindOfClass:[NSURLSessionTask class]]) { + NSURLSessionTask *task = (NSURLSessionTask *)request.taskIdentifier; + [task cancel]; + [_delegates removeObjectForKey:task]; + } +} + +#pragma mark - NSURLSessionTaskDelegate & NSURLSessionDataDelegate + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend +{ + id delegate = [_delegates objectForKey:task]; + [delegate request:(WXResourceRequest *)task.originalRequest didSendData:bytesSent totalBytesToBeSent:totalBytesExpectedToSend]; +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler +{ + id delegate = [_delegates objectForKey:task]; + [delegate request:(WXResourceRequest *)task.originalRequest didReceiveResponse:(WXResourceResponse *)response]; + completionHandler(NSURLSessionResponseAllow); +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data +{ + id delegate = [_delegates objectForKey:task]; + [delegate request:(WXResourceRequest *)task.originalRequest didReceiveData:data]; +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error +{ + id delegate = [_delegates objectForKey:task]; + [delegate requestDidFinishLoading:(WXResourceRequest *)task.originalRequest]; + [_delegates removeObjectForKey:task]; +} + + +@end diff --git a/ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h similarity index 73% rename from ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.h rename to ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h index 3578dd59e8..06ec6bd0b5 100644 --- a/ios/sdk/WeexSDK/Sources/Handler/WXNetworkDefaultImpl.h +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h @@ -6,9 +6,9 @@ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. */ + #import -#import "WXNetworkProtocol.h" -@interface WXNetworkDefaultImpl : NSObject +@interface WXResourceResponse : NSURLResponse @end diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m new file mode 100644 index 0000000000..b7b5e59852 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m @@ -0,0 +1,14 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + + +#import "WXResourceResponse.h" + +@implementation WXResourceResponse + +@end diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h index ced6ce7f92..0f0f3359c1 100644 --- a/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h +++ b/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h @@ -9,6 +9,7 @@ #import #import "WXModuleProtocol.h" +__attribute__ ((deprecated("Use WXResourceRequestHandler instead"))) @protocol WXNetworkProtocol /** diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h index a48f8a06d8..9f065ad08d 100644 --- a/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h +++ b/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h @@ -7,18 +7,10 @@ */ #import +#import "WXResourceRequest.h" @class WXSDKInstance; -typedef enum : NSUInteger { - WXResourceTypeBundle, - WXResourceTypeImage, - WXResourceTypeFont, - WXResourceTypeVideo, - WXResourceTypeLink, - WXResourceTypeOthers -} WXResourceType; - #define WX_REWRITE_URL(url, resourceType, instance, newUrl)\ do {\ (*newUrl) = nil;\ diff --git a/ios/sdk/WeexSDKTests/WXURLRewriteTests.m b/ios/sdk/WeexSDKTests/WXURLRewriteTests.m index 0612aa38aa..7a1f334b33 100644 --- a/ios/sdk/WeexSDKTests/WXURLRewriteTests.m +++ b/ios/sdk/WeexSDKTests/WXURLRewriteTests.m @@ -79,7 +79,7 @@ - (void)testRelativeURL { - (void)testFileURL { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSURL *fileURL = [bundle URLForResource:@"testRootView" withExtension:@"js"]; - NSURL *rewriteURL = [_rewriteHandler rewriteURL:fileURL.absoluteString withResourceType:WXResourceTypeBundle withInstance:_instance]; + NSURL *rewriteURL = [_rewriteHandler rewriteURL:fileURL.absoluteString withResourceType:WXResourceTypeMainBundle withInstance:_instance]; XCTAssertEqualObjects(fileURL.absoluteString, [rewriteURL absoluteString]); } @@ -87,7 +87,7 @@ - (void)testLocalURL { NSString *testURL = @"local://testRootView.js"; NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSURL *fileURL = [bundle URLForResource:@"testRootView" withExtension:@"js"]; - NSURL *rewriteURL = [_rewriteHandler rewriteURL:testURL withResourceType:WXResourceTypeBundle withInstance:_instance]; + NSURL *rewriteURL = [_rewriteHandler rewriteURL:testURL withResourceType:WXResourceTypeMainBundle withInstance:_instance]; XCTAssertEqualObjects(fileURL.absoluteString, [rewriteURL absoluteString]); } From dad5ee477b1fe0b145d3ecb6be8d5770c85b83c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Mon, 12 Dec 2016 17:44:34 +0800 Subject: [PATCH 004/144] * [ios] change network handler to request handler --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 8 +- ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m | 49 ++-- .../WeexSDK/Sources/Loader/WXResourceLoader.h | 4 +- .../WeexSDK/Sources/Module/WXStreamModule.h | 2 +- .../WeexSDK/Sources/Module/WXStreamModule.m | 229 +++++++++--------- ios/sdk/WeexSDKTests/WXNetworkTests.m | 116 --------- ios/sdk/WeexSDKTests/WXSDKEngineTests.m | 13 +- ios/sdk/WeexSDKTests/WXStreamModuleTests.m | 4 +- 8 files changed, 148 insertions(+), 277 deletions(-) delete mode 100644 ios/sdk/WeexSDKTests/WXNetworkTests.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 4890c55631..fe639becf8 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -47,7 +47,6 @@ 597334B31D4DE1A600988789 /* WXBridgeMethodTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 597334B21D4DE1A600988789 /* WXBridgeMethodTests.m */; }; 598805AD1D52D8C800EDED2C /* WXStorageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 598805AC1D52D8C800EDED2C /* WXStorageTests.m */; }; 5996BD701D49EC0600C0FEA6 /* WXInstanceWrapTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5996BD6F1D49EC0600C0FEA6 /* WXInstanceWrapTests.m */; }; - 5996BD721D4A219300C0FEA6 /* WXNetworkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5996BD711D4A219300C0FEA6 /* WXNetworkTests.m */; }; 5996BD751D4D8A0E00C0FEA6 /* WXSDKEngineTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5996BD741D4D8A0E00C0FEA6 /* WXSDKEngineTests.m */; }; 59A582D41CF481110081FD3E /* WXAppMonitorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A582D31CF481110081FD3E /* WXAppMonitorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 59A582FC1CF5B17B0081FD3E /* WXBridgeContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A582FA1CF5B17B0081FD3E /* WXBridgeContext.h */; }; @@ -307,7 +306,6 @@ 597334B21D4DE1A600988789 /* WXBridgeMethodTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXBridgeMethodTests.m; sourceTree = ""; }; 598805AC1D52D8C800EDED2C /* WXStorageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXStorageTests.m; sourceTree = ""; }; 5996BD6F1D49EC0600C0FEA6 /* WXInstanceWrapTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInstanceWrapTests.m; sourceTree = ""; }; - 5996BD711D4A219300C0FEA6 /* WXNetworkTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXNetworkTests.m; sourceTree = ""; }; 5996BD741D4D8A0E00C0FEA6 /* WXSDKEngineTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXSDKEngineTests.m; sourceTree = ""; }; 59A582D31CF481110081FD3E /* WXAppMonitorProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXAppMonitorProtocol.h; sourceTree = ""; }; 59A582FA1CF5B17B0081FD3E /* WXBridgeContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXBridgeContext.h; sourceTree = ""; }; @@ -704,7 +702,6 @@ 74EF31C11DE6932900667A07 /* handler */ = { isa = PBXGroup; children = ( - 5996BD711D4A219300C0FEA6 /* WXNetworkTests.m */, 74EF31C21DE6935600667A07 /* WXURLRewriteTests.m */, ); name = handler; @@ -1315,7 +1312,6 @@ 597334B11D4D9E7F00988789 /* WXSDKManagerTests.m in Sources */, 74C896401D2AC2210043B82A /* WeexSDKTests.m in Sources */, 598805AD1D52D8C800EDED2C /* WXStorageTests.m in Sources */, - 5996BD721D4A219300C0FEA6 /* WXNetworkTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1454,6 +1450,7 @@ 74C896461D2AC2210043B82A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; HEADER_SEARCH_PATHS = ( @@ -1477,6 +1474,7 @@ 74C896471D2AC2210043B82A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; HEADER_SEARCH_PATHS = ( @@ -1598,6 +1596,7 @@ 77D161121C02DBE70010B15B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1641,6 +1640,7 @@ 77D161131C02DBE70010B15B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; diff --git a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m index 4cee17838e..bc099eb1b0 100644 --- a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m +++ b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m @@ -13,6 +13,9 @@ #import "WXUtility.h" #import "WXSDKManager.h" #import "WXSDKEngine.h" +#import "WXResourceRequest.h" +#import "WXResourceResponse.h" +#import "WXResourceLoader.h" static BOOL WXIsDebug; static BOOL WXIsDevToolDebug; @@ -88,36 +91,24 @@ + (void)getData:(NSURL*)url key:(NSString*)key{ }); } else { // HTTP/HTTPS URL - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; -#pragma GCC diagnostic pop + WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:nil cachePolicy:NSURLRequestUseProtocolCachePolicy]; + request.userAgent = [WXUtility userAgent]; + WXResourceLoader *loader = [[WXResourceLoader alloc] initWithRequest:request]; + + loader.onFinished = ^(const WXResourceResponse * response, NSData *data) { + if ([response isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)response).statusCode != 200) { + __unused NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN + code:((NSHTTPURLResponse *)response).statusCode + userInfo:@{@"message":@"status code error."}]; + + return ; + } + + NSString * script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + scriptLoadFinish(key, script); + }; - __block NSURLResponse *urlResponse; - [networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} - withResponse:^(NSURLResponse *response) { - urlResponse = response; - } - withReceiveData:^(NSData *data) {} - withCompeletion:^(NSData *totalData, NSError *error) { - if (error) { - - } else { - if ([urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { - __unused NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN - code:((NSHTTPURLResponse *)urlResponse).statusCode - userInfo:@{@"message":@"status code error."}]; - - return ; - } - NSString * script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding]; - scriptLoadFinish(key, script); - } - }]; + [loader start]; } } diff --git a/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h index 1d6fbe5357..8b77a2c76b 100644 --- a/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h +++ b/ios/sdk/WeexSDK/Sources/Loader/WXResourceLoader.h @@ -7,8 +7,8 @@ */ #import -@class WXResourceRequest; -@class WXResourceResponse; +#import "WXResourceRequest.h" +#import "WXResourceResponse.h" @interface WXResourceLoader : NSObject diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h index be1e75db2c..2eb949f34d 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h +++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h @@ -12,6 +12,6 @@ @interface WXStreamModule : NSObject - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progressCallback:(WXModuleKeepAliveCallback)progressCallback; -- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback; +- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback DEPRECATED_MSG_ATTRIBUTE("Use fetch method instead."); @end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m index 2c9cd63764..bfa1ec0848 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m @@ -12,6 +12,7 @@ #import "WXHandlerFactory.h" #import "WXNetworkProtocol.h" #import "WXURLRewriteProtocol.h" +#import "WXResourceLoader.h" @implementation WXStreamModule @@ -20,45 +21,6 @@ @implementation WXStreamModule WX_EXPORT_METHOD(@selector(sendHttp:callback:)) WX_EXPORT_METHOD(@selector(fetch:callback:progressCallback:)) -- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback -{ - NSString* method = [param objectForKey:@"method"]; - NSString* urlStr = [param objectForKey:@"url"]; - NSDictionary* header = [param objectForKey:@"header"]; - NSString* body = [param objectForKey:@"body"]; - - NSURL *url = [NSURL URLWithString:urlStr]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setHTTPMethod:method]; - [request setTimeoutInterval:60.0]; - [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; - for (NSString *key in header) { - NSString *value = [header objectForKey:key]; - [request setValue:value forHTTPHeaderField:key]; - } - [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - - id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; - -#pragma GCC diagnostic pop - - [networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) { - } withResponse:^(NSURLResponse *response) { - } withReceiveData:^(NSData *data) { - } withCompeletion:^(NSData *totalData, NSError *error) { - NSString *responseData = nil; - if (!error) { - responseData = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding]; - } - //else ok - callback(responseData); - }]; -} - - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progressCallback:(WXModuleKeepAliveCallback)progressCallback { __block NSInteger received = 0; @@ -87,99 +49,96 @@ - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progre NSString *body = [options objectForKey:@"body"]; NSString *type = [options objectForKey:@"type"]; NSURL *url = [NSURL URLWithString:urlStr]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - [request setHTTPMethod:method]; - [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"]; + //TODO:referrer + WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeOthers referrer:nil cachePolicy:NSURLRequestUseProtocolCachePolicy]; + request.HTTPMethod = method; if ([options valueForKey:@"timeout"]){ //ms [request setTimeoutInterval:([[options valueForKey:@"timeout"] floatValue])/1000]; } + request.userAgent = [WXUtility userAgent]; for (NSString *header in headers) { NSString *value = [headers objectForKey:header]; [request setValue:value forHTTPHeaderField:header]; } [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; - - [callbackRsp setObject:@{ @"OPENED": @1 } forKey:@"readyState"]; + [callbackRsp setObject:@{ @"OPENED": @1 } forKey:@"readyState"]; progressCallback(callbackRsp, TRUE); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - id networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; -#pragma GCC diagnostic pop - - __block NSString *respEncode = nil; + WXResourceLoader *loader = [[WXResourceLoader alloc] initWithRequest:request]; __weak typeof(self) weakSelf = self; - [networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) { - } withResponse:^(NSURLResponse *response) { - httpResponse = (NSHTTPURLResponse*)response; - respEncode = httpResponse.textEncodingName; - if (weakSelf) { - [callbackRsp setObject:@{ @"HEADERS_RECEIVED" : @2 } forKey:@"readyState"]; - [callbackRsp setObject:[NSNumber numberWithInteger:httpResponse.statusCode] forKey:@"status"]; - [callbackRsp setObject:httpResponse.allHeaderFields forKey:@"headers"]; - statusText = [WXStreamModule getStatusText:httpResponse.statusCode]; - [callbackRsp setObject:statusText forKey:@"statusText"]; - [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"]; - progressCallback(callbackRsp, TRUE); - } - - } withReceiveData:^(NSData *data) { - [callbackRsp setObject:@{ @"LOADING" : @3 } forKey:@"readyState"]; - received += [data length]; - [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"]; - progressCallback(callbackRsp, TRUE); - - } withCompeletion:^(NSData *totalData, NSError *error) { - - [callbackRsp removeObjectForKey:@"readyState"]; - [callbackRsp removeObjectForKey:@"length"]; - [callbackRsp removeObjectForKey:@"keepalive"]; - [callbackRsp setObject:httpResponse.statusCode >= 200 && httpResponse.statusCode <= 299 ? @true : @false forKey:@"ok"]; - if (error) { - //error - [callbackRsp setObject:@(-1) forKey:@"status"]; - [callbackRsp setObject:[NSString stringWithFormat:@"%@(%ld)",[error localizedDescription], (long)[error code]] forKey:@"data"]; - - switch ([error code]) { - case -1000: - case -1002: - case -1003: - statusText = @"ERR_INVALID_REQUEST"; - break; - default: - break; - } - [callbackRsp setObject:statusText forKey:@"statusText"]; - - }else { - // no error - NSString *responseData = [self stringfromData:totalData encode:respEncode]; - if ([type isEqualToString:@"json"] || [type isEqualToString:@"jsonp"]) { - if ([type isEqualToString:@"jsonp"]) { - NSUInteger start = [responseData rangeOfString:@"("].location + 1 ; - NSUInteger end = [responseData rangeOfString:@")" options:NSBackwardsSearch].location; - if (end < [responseData length] && end > start) { - responseData = [responseData substringWithRange:NSMakeRange(start, end-start)]; - } - } - id jsonObj = [self JSONObjFromData:[responseData dataUsingEncoding:NSUTF8StringEncoding]]; - if (jsonObj) { - [callbackRsp setObject:jsonObj forKey:@"data"]; - } - - } else { - if (responseData) { - [callbackRsp setObject:responseData forKey:@"data"]; - } - } - } - callback(callbackRsp); - }]; + loader.onResponseReceived = ^(const WXResourceResponse *response) { + httpResponse = (NSHTTPURLResponse*)response; + if (weakSelf) { + [callbackRsp setObject:@{ @"HEADERS_RECEIVED" : @2 } forKey:@"readyState"]; + [callbackRsp setObject:[NSNumber numberWithInteger:httpResponse.statusCode] forKey:@"status"]; + [callbackRsp setObject:httpResponse.allHeaderFields forKey:@"headers"]; + statusText = [WXStreamModule getStatusText:httpResponse.statusCode]; + [callbackRsp setObject:statusText forKey:@"statusText"]; + [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"]; + progressCallback(callbackRsp, TRUE); + } + }; + + loader.onDataReceived = ^(NSData *data) { + [callbackRsp setObject:@{ @"LOADING" : @3 } forKey:@"readyState"]; + received += [data length]; + [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"]; + progressCallback(callbackRsp, TRUE); + }; + + loader.onFinished = ^(const WXResourceResponse * response, NSData *data) { + [callbackRsp removeObjectForKey:@"readyState"]; + [callbackRsp removeObjectForKey:@"length"]; + [callbackRsp removeObjectForKey:@"keepalive"]; + [callbackRsp setObject:httpResponse.statusCode >= 200 && httpResponse.statusCode <= 299 ? @true : @false forKey:@"ok"]; + + NSString *responseData = [self stringfromData:data encode:httpResponse.textEncodingName]; + if ([type isEqualToString:@"json"] || [type isEqualToString:@"jsonp"]) { + if ([type isEqualToString:@"jsonp"]) { + NSUInteger start = [responseData rangeOfString:@"("].location + 1 ; + NSUInteger end = [responseData rangeOfString:@")" options:NSBackwardsSearch].location; + if (end < [responseData length] && end > start) { + responseData = [responseData substringWithRange:NSMakeRange(start, end-start)]; + } + } + id jsonObj = [self JSONObjFromData:[responseData dataUsingEncoding:NSUTF8StringEncoding]]; + if (jsonObj) { + [callbackRsp setObject:jsonObj forKey:@"data"]; + } + + } else { + if (responseData) { + [callbackRsp setObject:responseData forKey:@"data"]; + } + } + + callback(callbackRsp); + }; + + loader.onFailed = ^(NSError *error) { + [callbackRsp removeObjectForKey:@"readyState"]; + [callbackRsp removeObjectForKey:@"length"]; + [callbackRsp removeObjectForKey:@"keepalive"]; + [callbackRsp setObject:@(-1) forKey:@"status"]; + [callbackRsp setObject:[NSString stringWithFormat:@"%@(%ld)",[error localizedDescription], (long)[error code]] forKey:@"data"]; + + switch ([error code]) { + case -1000: + case -1002: + case -1003: + statusText = @"ERR_INVALID_REQUEST"; + break; + default: + break; + } + [callbackRsp setObject:statusText forKey:@"statusText"]; + }; + + [loader start]; } - (NSString*)stringfromData:(NSData *)data encode:(NSString *)encoding @@ -349,4 +308,40 @@ + (NSString*)getStatusText:(NSInteger)code return @"Unknown"; } +#pragma mark - Deperecated + +- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback +{ + NSString* method = [param objectForKey:@"method"]; + NSString* urlStr = [param objectForKey:@"url"]; + NSDictionary* headers = [param objectForKey:@"header"]; + NSString* body = [param objectForKey:@"body"]; + + NSURL *url = [NSURL URLWithString:urlStr]; + + //TODO:referrer + WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeOthers referrer:nil cachePolicy:NSURLRequestUseProtocolCachePolicy]; + request.HTTPMethod = method; + request.timeoutInterval = 60.0; + request.userAgent = [WXUtility userAgent]; + + for (NSString *key in headers) { + NSString *value = [headers objectForKey:key]; + [request setValue:value forHTTPHeaderField:key]; + } + [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; + + WXResourceLoader *loader = [[WXResourceLoader alloc] initWithRequest:request]; + loader.onFinished = ^(const WXResourceResponse * response, NSData *data) { + NSString* responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + callback(responseData); + }; + + loader.onFailed = ^(NSError *error) { + callback(nil); + }; + + [loader start]; +} + @end diff --git a/ios/sdk/WeexSDKTests/WXNetworkTests.m b/ios/sdk/WeexSDKTests/WXNetworkTests.m deleted file mode 100644 index eda53d88e4..0000000000 --- a/ios/sdk/WeexSDKTests/WXNetworkTests.m +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Created by Weex. - * Copyright (c) 2016, Alibaba, Inc. All rights reserved. - * - * This source code is licensed under the Apache Licence 2.0. - * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. - */ - -#import -#import "WXNetworkDefaultImpl.h" -#import "WXUtility.h" - -@interface WXNetworkTests : XCTestCase - -@property (nonatomic, strong) WXNetworkDefaultImpl *networkHandler; - -@end - -@implementation WXNetworkTests - -- (void)setUp { - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. - - self.networkHandler = [[WXNetworkDefaultImpl alloc] init]; -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testExample { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. -} - -- (void)testPerformanceExample { - // This is an example of a performance test case. - [self measureBlock:^{ - // Put the code you want to measure the time of here. - }]; -} - -- (void) testSendRequestSuccess { - - XCTestExpectation *exp = [self expectationWithDescription:@"SendRequestSuccess Unit Test Error!"]; - - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.taobao.com"]]; - - __block NSURLResponse *urlResponse; - __block NSError *respError; - __block NSData *respData; - - [_networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} - withResponse:^(NSURLResponse *response) { - urlResponse = response; - } - withReceiveData:^(NSData *data) {} - withCompeletion:^(NSData *totalData, NSError *error) { - - if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { - error = [NSError errorWithDomain:WX_ERROR_DOMAIN - code:((NSHTTPURLResponse *)urlResponse).statusCode - userInfo:@{@"message":@"status code error."}]; - } - - respError = error; - respData = totalData; - - [exp fulfill]; - }]; - - [self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) { - XCTAssertNil(respError); - XCTAssertNotNil(respData); - }]; -} - -/*- (void) testSendRequestFailure { - - XCTestExpectation *exp = [self expectationWithDescription:@"SendRequestFailure Unit Test Error!"]; - - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.123.abc"]]; - - __block NSURLResponse *urlResponse; - __block NSError *respError; - __block NSData *respData; - - [_networkHandler sendRequest:request - withSendingData:^(int64_t bytesSent, int64_t totalBytes) {} - withResponse:^(NSURLResponse *response) { - urlResponse = response; - } - withReceiveData:^(NSData *data) {} - withCompeletion:^(NSData *totalData, NSError *error) { - - if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) { - error = [NSError errorWithDomain:WX_ERROR_DOMAIN - code:((NSHTTPURLResponse *)urlResponse).statusCode - userInfo:@{@"message":@"status code error."}]; - } - - respError = error; - respData = totalData; - [exp fulfill]; - }]; - - [self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) { - XCTAssertNotNil(respError); - XCTAssertNil(respData); - }]; -}*/ - -@end diff --git a/ios/sdk/WeexSDKTests/WXSDKEngineTests.m b/ios/sdk/WeexSDKTests/WXSDKEngineTests.m index 7f06d4fdc3..f506d8849c 100644 --- a/ios/sdk/WeexSDKTests/WXSDKEngineTests.m +++ b/ios/sdk/WeexSDKTests/WXSDKEngineTests.m @@ -11,7 +11,8 @@ #import "WXModuleFactory.h" #import "WXComponentFactory.h" #import "WXHandlerFactory.h" -#import "WXNetworkDefaultImpl.h" +#import "WXResourceRequest.h" +#import "WXResourceRequestHandlerDefaultImpl.h" @interface WXSDKEngineTests : XCTestCase @@ -92,15 +93,15 @@ - (void)testRegisterComponentwithProperties { - (void)testRegisterHandler { - [WXSDKEngine registerHandler:[WXNetworkDefaultImpl new] withProtocol:@protocol(WXNetworkProtocol)]; - id handler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)]; + [WXSDKEngine registerHandler:[WXResourceRequestHandlerDefaultImpl new] withProtocol:@protocol(WXResourceRequestHandler)]; + id handler = [WXHandlerFactory handlerForProtocol:@protocol(WXResourceRequestHandler)]; XCTAssertNotNil(handler); - XCTAssertTrue([handler conformsToProtocol:@protocol(WXNetworkProtocol)]); + XCTAssertTrue([handler conformsToProtocol:@protocol(WXResourceRequestHandler)]); NSDictionary *handlerConfigs = [WXHandlerFactory handlerConfigs]; - handler = [handlerConfigs objectForKey:NSStringFromProtocol(@protocol(WXNetworkProtocol))]; + handler = [handlerConfigs objectForKey:NSStringFromProtocol(@protocol(WXResourceRequestHandler))]; XCTAssertNotNil(handler); - XCTAssertTrue([handler conformsToProtocol:@protocol(WXNetworkProtocol)]); + XCTAssertTrue([handler conformsToProtocol:@protocol(WXResourceRequestHandler)]); } - (void)testComponentFactory { diff --git a/ios/sdk/WeexSDKTests/WXStreamModuleTests.m b/ios/sdk/WeexSDKTests/WXStreamModuleTests.m index cf654635cb..587c429fda 100644 --- a/ios/sdk/WeexSDKTests/WXStreamModuleTests.m +++ b/ios/sdk/WeexSDKTests/WXStreamModuleTests.m @@ -9,7 +9,7 @@ #import #import "WXStreamModule.h" #import -#import "WXNetworkDefaultImpl.h" +#import "WXResourceRequestHandlerDefaultImpl.h" @interface WXStreamModuleTests : XCTestCase @property (nonatomic, strong) WXStreamModule *streamModule; @@ -22,7 +22,7 @@ @implementation WXStreamModuleTests - (void)setUp { [super setUp]; _streamModule = [[WXStreamModule alloc] init]; - [WXSDKEngine registerHandler:[WXNetworkDefaultImpl new] withProtocol:@protocol(WXNetworkProtocol)]; + [WXSDKEngine registerHandler:[WXResourceRequestHandlerDefaultImpl new] withProtocol:@protocol(WXResourceRequestHandler)]; _exp = [self expectationWithDescription:@"SendRequestSuccess Unit Test Error!"]; } From 17a093fdc27474ccc1bc61cf2446f33d6d649fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Mon, 12 Dec 2016 20:32:37 +0800 Subject: [PATCH 005/144] * [ios] fix typo in [WXSDKEngine initSDKEnvironment] --- ios/playground/WeexDemo/AppDelegate.m | 2 +- ios/playground/WeexDemo/Scanner/WXScannerVC.m | 2 +- ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m | 2 +- ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h | 11 ++++++++-- ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m | 20 ++++++++++++++++--- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/ios/playground/WeexDemo/AppDelegate.m b/ios/playground/WeexDemo/AppDelegate.m index 5f28954861..f90c5751e1 100644 --- a/ios/playground/WeexDemo/AppDelegate.m +++ b/ios/playground/WeexDemo/AppDelegate.m @@ -73,7 +73,7 @@ - (void)initWeexSDK [WXAppConfiguration setAppName:@"WeexDemo"]; [WXAppConfiguration setExternalUserAgent:@"ExternalUA"]; - [WXSDKEngine initSDKEnviroment]; + [WXSDKEngine initSDKEnvironment]; [WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)]; [WXSDKEngine registerHandler:[WXEventModule new] withProtocol:@protocol(WXEventModuleProtocol)]; diff --git a/ios/playground/WeexDemo/Scanner/WXScannerVC.m b/ios/playground/WeexDemo/Scanner/WXScannerVC.m index 6bb5a343b6..52f415a4ef 100644 --- a/ios/playground/WeexDemo/Scanner/WXScannerVC.m +++ b/ios/playground/WeexDemo/Scanner/WXScannerVC.m @@ -177,7 +177,7 @@ - (BOOL)remoteDebug:(NSURL *)url { if ([url.scheme isEqualToString:@"ws"]) { [WXSDKEngine connectDebugServer:url.absoluteString]; - [WXSDKEngine initSDKEnviroment]; + [WXSDKEngine initSDKEnvironment]; return YES; } diff --git a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m index 99cef4753a..36919215c6 100644 --- a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m +++ b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m @@ -69,7 +69,7 @@ + (void)getData:(NSURL*)url key:(NSString*)key{ if ([key isEqualToString:@"jsframework"]) { WXDebugrepJSFramework = script; [WXSDKManager unload]; - [WXSDKEngine initSDKEnviroment:script]; + [WXSDKEngine initSDKEnvironment:script]; }else { WXDebugrepBundleJS = script; } diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h index 159513cb51..636894f49c 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h @@ -60,13 +60,13 @@ * @discussion Injects main.js in app bundle as default JSFramework script. * **/ -+ (void)initSDKEnviroment; ++ (void)initSDKEnvironment; /** * @abstract Initializes the enviroment with a given JSFramework script. * **/ -+ (void)initSDKEnviroment:(NSString *)script; ++ (void)initSDKEnvironment:(NSString *)script; /** * @abstract Unloads the bridge context @@ -108,3 +108,10 @@ + (void)connectDevToolServer:(NSString *)URL; @end + +@interface WXSDKEngine (Deprecated) + ++ (void)initSDKEnviroment DEPRECATED_MSG_ATTRIBUTE("To fix typo, use initSDKEnvironment method instead."); ++ (void)initSDKEnviroment:(NSString *)script DEPRECATED_MSG_ATTRIBUTE("To fix typo, use initSDKEnvironment: method instead."); + +@end diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m index d9804923f7..bebca38078 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m @@ -133,14 +133,14 @@ + (void)registerHandler:(id)handler withProtocol:(Protocol *)protocol # pragma mark SDK Initialize -+ (void)initSDKEnviroment ++ (void)initSDKEnvironment { WX_MONITOR_PERF_START(WXPTInitalize) WX_MONITOR_PERF_START(WXPTInitalizeSync) NSString *filePath = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"]; NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - [WXSDKEngine initSDKEnviroment:script]; + [WXSDKEngine initSDKEnvironment:script]; WX_MONITOR_PERF_END(WXPTInitalizeSync) @@ -170,7 +170,7 @@ + (void)initSDKEnviroment #endif } -+ (void)initSDKEnviroment:(NSString *)script ++ (void)initSDKEnvironment:(NSString *)script { if (!script || script.length <= 0) { WX_MONITOR_FAIL(WXMTJSFramework, WX_ERR_JSFRAMEWORK_LOAD, @"framework loading is failure!"); @@ -261,3 +261,17 @@ + (void)_originalRegisterHandlers:(NSDictionary *)handlers { } @end + +@implementation WXSDKEngine (Deprecated) + ++ (void)initSDKEnviroment +{ + [self initSDKEnvironment]; +} + ++ (void)initSDKEnviroment:(NSString *)script +{ + [self initSDKEnvironment:script]; +} + +@end From 61e1f9016e9f9d28266642325983e2d8820071ae Mon Sep 17 00:00:00 2001 From: acton393 Date: Mon, 12 Dec 2016 22:55:32 +0800 Subject: [PATCH 006/144] * [ios] add moduleEvent support --- .../WeexDemo.xcodeproj/project.pbxproj | 43 +++++++++---------- .../WeexSDK/Sources/Manager/WXModuleFactory.m | 2 + .../WeexSDK/Sources/Manager/WXModuleManager.m | 14 ++++++ ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 11 +++++ ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 43 ++++++++++++++++++- .../Sources/Model/WXSDKInstance_private.h | 3 ++ 6 files changed, 93 insertions(+), 23 deletions(-) diff --git a/ios/playground/WeexDemo.xcodeproj/project.pbxproj b/ios/playground/WeexDemo.xcodeproj/project.pbxproj index 31a50f4d76..a67e73585e 100644 --- a/ios/playground/WeexDemo.xcodeproj/project.pbxproj +++ b/ios/playground/WeexDemo.xcodeproj/project.pbxproj @@ -302,13 +302,13 @@ isa = PBXNativeTarget; buildConfigurationList = 775BEEA81C1E8ECC008D1629 /* Build configuration list for PBXNativeTarget "WeexDemo" */; buildPhases = ( - 359BEE13DD78032A2CB791E8 /* Check Pods Manifest.lock */, + 359BEE13DD78032A2CB791E8 /* [CP] Check Pods Manifest.lock */, 74CC7A221C2C13BF00829368 /* Start Samples */, 775BEE771C1E8ECC008D1629 /* Sources */, 775BEE781C1E8ECC008D1629 /* Frameworks */, 775BEE791C1E8ECC008D1629 /* Resources */, - 0B3B6C05EE2F8A3B30DE551F /* Copy Pods Resources */, - 5ED24D6A09B32268BB031206 /* Embed Pods Frameworks */, + 0B3B6C05EE2F8A3B30DE551F /* [CP] Copy Pods Resources */, + 5ED24D6A09B32268BB031206 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -341,12 +341,12 @@ isa = PBXNativeTarget; buildConfigurationList = 84361D711CA10F8E00F43825 /* Build configuration list for PBXNativeTarget "WeexUITestDemo" */; buildPhases = ( - 84361D271CA10F8E00F43825 /* Check Pods Manifest.lock */, + 84361D271CA10F8E00F43825 /* [CP] Check Pods Manifest.lock */, 84361D291CA10F8E00F43825 /* Sources */, 84361D3C1CA10F8E00F43825 /* Frameworks */, 84361D431CA10F8E00F43825 /* Resources */, - 84361D6F1CA10F8E00F43825 /* Copy Pods Resources */, - 84361D701CA10F8E00F43825 /* Embed Pods Frameworks */, + 84361D6F1CA10F8E00F43825 /* [CP] Copy Pods Resources */, + 84361D701CA10F8E00F43825 /* [CP] Embed Pods Frameworks */, 567369891CE436EB000A646C /* ShellScript */, ); buildRules = ( @@ -430,14 +430,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 0B3B6C05EE2F8A3B30DE551F /* Copy Pods Resources */ = { + 0B3B6C05EE2F8A3B30DE551F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -445,19 +445,19 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexDemo/Pods-WeexDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 359BEE13DD78032A2CB791E8 /* Check Pods Manifest.lock */ = { + 359BEE13DD78032A2CB791E8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 567369891CE436EB000A646C /* ShellScript */ = { @@ -473,20 +473,19 @@ shellPath = /bin/sh; shellScript = "myFile=\"XcodeCoverage/exportenv.sh\"\n\nif [ -f \"$myFile\" ]; then\nXcodeCoverage/exportenv.sh\nfi"; }; - 5ED24D6A09B32268BB031206 /* Embed Pods Frameworks */ = { + 5ED24D6A09B32268BB031206 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = " -"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexDemo/Pods-WeexDemo-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 74CC7A221C2C13BF00829368 /* Start Samples */ = { @@ -503,29 +502,29 @@ shellPath = /bin/sh; shellScript = "set -x\n\nif nc -w 5 -z localhost 12580 ; then\n echo \"Port 12580 already in use, server is running\"\nelse\n open \"$SRCROOT/../../start\"\nfi\n\n"; }; - 84361D271CA10F8E00F43825 /* Check Pods Manifest.lock */ = { + 84361D271CA10F8E00F43825 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 84361D6F1CA10F8E00F43825 /* Copy Pods Resources */ = { + 84361D6F1CA10F8E00F43825 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -533,14 +532,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexUITestDemo/Pods-WeexUITestDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 84361D701CA10F8E00F43825 /* Embed Pods Frameworks */ = { + 84361D701CA10F8E00F43825 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m index 3ab7f50c1e..5b7bd38aac 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m @@ -123,6 +123,8 @@ - (NSMutableDictionary *)_moduleMethodMapsWithName:(NSString *)name { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; NSMutableArray *methods = [NSMutableArray array]; + [methods addObject:@"addEventListener"]; + [methods addObject:@"removeEventListener"]; [_moduleLock lock]; [dict setValue:methods forKey:name]; diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m index 579f441473..beb830a91d 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m @@ -16,6 +16,7 @@ #import "WXSDKManager.h" #import "WXThreadSafeMutableDictionary.h" #import "WXInvocationConfig.h" +#import "WXSDKInstance_private.h" #import @@ -80,6 +81,19 @@ - (void)dispatchMethod:(WXBridgeMethod *)method WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance]; id moduleInstance = [weexInstance moduleForClass:module]; + if ([method.method isEqualToString:@"addEventListener"]) { + if([method.arguments[0] isKindOfClass:[NSString class]] && method.arguments[1]) { + [weexInstance addModuleEventObservers:method.arguments[0] callback:method.arguments[1] module:moduleInstance]; + } + return; + } + + if ([method.method isEqualToString:@"removeEventListener"]) { + if ([method.arguments[0] isKindOfClass:[NSString class]]) { + [weexInstance removeModuleEventObserver:method.arguments[0] module:moduleInstance]; + } + return; + } // dispatch to user specified queue or thread, default is main thread __weak typeof(self) weakSelf = self; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index 38fd09b905..273a9045d2 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -193,6 +193,17 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code */ - (NSUInteger)numberOfComponents; + +/** + * check whether the module eventName is registered + */ +- (BOOL)checkModuleEventRegistered:(NSString*)event module:(id)module; + +/** + * fire module event; + */ +- (void)fireModuleEvent:(id)module eventName:(NSString *)eventName params:(NSDictionary*)params; + /** * fire global event */ diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index bc2590e7d0..6d4bca2d02 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -32,9 +32,10 @@ @implementation WXSDKInstance id _networkHandler; WXComponentManager *_componentManager; WXRootView *_rootView; + WXThreadSafeMutableDictionary *_moduleEventObservers; } -- (void) dealloc +- (void)dealloc { [self removeObservers]; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -61,6 +62,7 @@ - (instancetype)init _moduleInstances = [NSMutableDictionary new]; _styleConfigs = [NSMutableDictionary new]; _attrConfigs = [NSMutableDictionary new]; + _moduleEventObservers = [WXThreadSafeMutableDictionary new]; [self addObservers]; } @@ -334,6 +336,16 @@ - (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params [[NSNotificationCenter defaultCenter] postNotificationName:eventName object:self userInfo:userInfo]; } +- (void)fireModuleEvent:(id)module eventName:(NSString *)eventName params:(NSDictionary*)params +{ + NSDictionary * userInfo = @{ + @"moduleId":[module description]?:@"", + @"param":params?:@{} + }; + + [[NSNotificationCenter defaultCenter] postNotificationName:eventName object:self userInfo:userInfo]; +} + - (NSURL *)completeURL:(NSString *)url { if (!_scriptURL) { @@ -347,8 +359,37 @@ - (NSURL *)completeURL:(NSString *)url return [NSURL URLWithString:url relativeToURL:_scriptURL]; } +- (BOOL)checkModuleEventRegistered:(NSString*)event module:(id)module +{ + return [_moduleEventObservers[module] objectForKey:event] ? TRUE:FALSE; +} + #pragma mark Private Methods +- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId module:(id)module +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moduleEventNotif:) name:event object:nil]; + [_moduleEventObservers setObject:@{event:callbackId} forKey:module]; +} + +- (void)removeModuleEventObserver:(NSString*)event module:(id)module +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:event object:nil]; + [_moduleEventObservers[module] removeObjectForKey:event]; + if ([_moduleEventObservers[module] count] == 0) { + [_moduleEventObservers removeObjectForKey:module]; + } +} + +- (void)moduleEventNotif:(NSNotification *)notification +{ + NSDictionary * moduleEventObserversCpy = [_moduleEventObservers copy]; + NSDictionary * userInfo = notification.userInfo; + for (WXModuleKeepAliveCallback callback in [moduleEventObserversCpy[userInfo[@"moduleId"]] objectForKey:notification.name]) { + callback(userInfo[@"param"], true); + } +} + - (void)addObservers { [self addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil]; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h index 3ec305965d..367f296a1e 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h @@ -19,4 +19,7 @@ @property (nonatomic, readonly, strong) WXComponentManager *componentManager; +- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId module:(id)module; +- (void)removeModuleEventObserver:(NSString*)event module:(id)module; + @end From db7ae05ae2ee5611005598fa820a51fb29928f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Tue, 13 Dec 2016 21:34:17 +0800 Subject: [PATCH 007/144] * [ios] Support meta.setViewport to git rid of 750px adapter --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 10 +- .../Sources/Component/WXCanvasComponent.m | 16 ++-- .../Sources/Component/WXIndicatorComponent.m | 5 +- .../Sources/Component/WXListComponent.m | 2 +- .../Sources/Component/WXScrollerComponent.m | 5 +- .../Component/WXSliderNeighborComponent.m | 2 +- .../Sources/Component/WXTextAreaComponent.m | 8 +- .../Sources/Component/WXTextComponent.m | 20 +++- .../Sources/Component/WXTextInputComponent.m | 6 +- .../WeexSDK/Sources/Component/WXTransform.h | 3 + .../WeexSDK/Sources/Component/WXTransform.m | 20 +++- .../Sources/Display/WXComponent+Display.m | 40 +++++++- .../Sources/Events/WXComponent+Events.m | 18 ++-- .../Sources/Layout/WXComponent+Layout.m | 87 +++++++++++------- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 2 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 5 + ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 9 ++ .../Sources/Model/WXSDKInstance_private.h | 2 + .../Sources/Module/WXAnimationModule.m | 6 +- ios/sdk/WeexSDK/Sources/Module/WXDomModule.m | 26 +++--- ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h | 14 +++ ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m | 40 ++++++++ .../WeexSDK/Sources/Module/WXStreamModule.m | 2 +- ios/sdk/WeexSDK/Sources/Utility/WXConvert.h | 9 +- ios/sdk/WeexSDK/Sources/Utility/WXConvert.m | 15 ++- ios/sdk/WeexSDK/Sources/Utility/WXDefine.h | 2 +- ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 51 +++++------ ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 91 ++++++++++--------- .../Sources/View/WXComponent+ViewManagement.m | 2 +- ios/sdk/WeexSDK/Sources/WeexSDK.h | 1 + 30 files changed, 351 insertions(+), 168 deletions(-) create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index fe639becf8..745fdb594b 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -94,7 +94,7 @@ 7423899B1C3174EB00D748CA /* WXWeakObjectWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */; }; 7423899C1C3174EB00D748CA /* WXWeakObjectWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */; }; 7423899F1C32733800D748CA /* WXType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423899D1C32733800D748CA /* WXType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7251DF98C45007DC46C /* WXResourceRequest.h */; }; + 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7251DF98C45007DC46C /* WXResourceRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD7261DF98C45007DC46C /* WXResourceRequest.m */; }; 742AD7301DF98C45007DC46C /* WXResourceRequestHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */; }; 742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7281DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h */; }; @@ -152,6 +152,8 @@ 74B8BEFE1DC47B72004A6027 /* WXRootView.h in Headers */ = {isa = PBXBuildFile; fileRef = 74B8BEFC1DC47B72004A6027 /* WXRootView.h */; }; 74B8BEFF1DC47B72004A6027 /* WXRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 74B8BEFD1DC47B72004A6027 /* WXRootView.m */; }; 74B8BF011DC49AFE004A6027 /* WXRootViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 74B8BF001DC49AFE004A6027 /* WXRootViewTests.m */; }; + 74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */; }; + 74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */; }; 74C896401D2AC2210043B82A /* WeexSDKTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 74C8963F1D2AC2210043B82A /* WeexSDKTests.m */; }; 74C896421D2AC2210043B82A /* WeexSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77D160FD1C02DBE70010B15B /* WeexSDK.framework */; }; 74CC7A1C1C2BC5F800829368 /* WXCellComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CC7A1A1C2BC5F800829368 /* WXCellComponent.h */; }; @@ -410,6 +412,8 @@ 74B8BEFC1DC47B72004A6027 /* WXRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXRootView.h; sourceTree = ""; }; 74B8BEFD1DC47B72004A6027 /* WXRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootView.m; sourceTree = ""; }; 74B8BF001DC49AFE004A6027 /* WXRootViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootViewTests.m; sourceTree = ""; }; + 74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXMetaModule.h; sourceTree = ""; }; + 74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXMetaModule.m; sourceTree = ""; }; 74C27A011CEC441D004E488E /* WeexSDK-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WeexSDK-Prefix.pch"; sourceTree = ""; }; 74C8963D1D2AC2210043B82A /* WeexSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WeexSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 74C8963F1D2AC2210043B82A /* WeexSDKTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WeexSDKTests.m; sourceTree = ""; }; @@ -930,6 +934,8 @@ D334510B1D3E19B80083598A /* WXCanvasModule.m */, 746A2F3D1DF808E6004719D0 /* WXLocationModule.h */, 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */, + 74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */, + 74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */, ); path = Module; sourceTree = ""; @@ -1057,6 +1063,7 @@ 77D161381C02DE940010B15B /* WXBridgeManager.h in Headers */, 77D161281C02DE1A0010B15B /* WXSDKManager.h in Headers */, 59CE27E81CC387DB000BE37A /* WXEmbedComponent.h in Headers */, + 74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */, DCA0EF641D6EED6F00CB18B9 /* WXGlobalEventModule.h in Headers */, 2A837AB21CD9DE9200AEDF03 /* WXLoadingComponent.h in Headers */, 7423899F1C32733800D748CA /* WXType.h in Headers */, @@ -1344,6 +1351,7 @@ 744BEA5A1D0520F300452B5D /* WXComponent+Layout.m in Sources */, 59A582FD1CF5B17B0081FD3E /* WXBridgeContext.m in Sources */, 743933B51C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.m in Sources */, + 74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */, 741081201CED585A001BC6E5 /* WXComponentManager.m in Sources */, 1D3000F21D40B9AC004F3B4F /* WXClipboardModule.m in Sources */, 741DFE071DDD9B30009B020F /* UIBezierPath+Weex.m in Sources */, diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m index f83f1c936a..8dbba332b8 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m @@ -165,7 +165,7 @@ - (void)addEvent:(NSString *)eventName // OpenGL ES methods map -#define WX_CANVAS_PIXEL(name, index) WXPixelType name = [WXConvert WXPixelType:params[index]]; +#define WX_CANVAS_PIXEL(name, index) WXPixelType name = [WXConvert WXPixelType:params[index] scaleFactor:self.weexInstance.pixelScaleFactor]; #define WX_CANVAS_CGFLOAT(name, index) CGFloat name = [WXConvert CGFloat:params[index]]; #define WX_CANVAS_PARAMS_CHECK(num) if ([params count] < num) return; @@ -196,10 +196,10 @@ - (void) drawImages:(NSArray *)params CGFloat sy = [WXConvert CGFloat:curParams[1]]; CGFloat sw = [WXConvert CGFloat:curParams[2]]; CGFloat sh = [WXConvert CGFloat:curParams[3]]; - CGFloat dx = [WXConvert WXPixelType:curParams[4]]; - CGFloat dy = [WXConvert WXPixelType:curParams[5]]; - CGFloat dw = [WXConvert WXPixelType:curParams[6]]; - CGFloat dh = [WXConvert WXPixelType:curParams[7]]; + CGFloat dx = [WXConvert WXPixelType:curParams[4] scaleFactor:self.weexInstance.pixelScaleFactor]; + CGFloat dy = [WXConvert WXPixelType:curParams[5] scaleFactor:self.weexInstance.pixelScaleFactor]; + CGFloat dw = [WXConvert WXPixelType:curParams[6] scaleFactor:self.weexInstance.pixelScaleFactor]; + CGFloat dh = [WXConvert WXPixelType:curParams[7] scaleFactor:self.weexInstance.pixelScaleFactor]; geometrys[i * 4] = GLKVector3Make(dx, dh + dy, 1); geometrys[i * 4 + 1] = GLKVector3Make(dw + dx, dh + dy, 1); @@ -221,7 +221,7 @@ - (void) drawImages:(NSArray *)params [WXConvert CGFloat:curParams[16]] ); // Because the params are base on 750, so we should make scale for the transform matrix - matrix = GLKMatrix3Scale(matrix, 1, 1, WXScreenResizeRadio()); + matrix = GLKMatrix3Scale(matrix, 1, 1, self.weexInstance.pixelScaleFactor); geometrys[i * 4] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4]); geometrys[i * 4 + 1] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4 + 1]); geometrys[i * 4 + 2] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4 + 2]); @@ -311,7 +311,7 @@ - (void) setStrokeStyle:(NSArray *)params - (void) setLineWidth:(NSArray *)params { WX_CANVAS_PARAMS_CHECK(1); - _curLineWidth = [WXConvert WXPixelType:params[0]]; + _curLineWidth = [WXConvert WXPixelType:params[0] scaleFactor:self.weexInstance.pixelScaleFactor]; } // ["M", 0, 0, "L", 100, 100, "L", 0, 100, "L", 0, 0] it made a triangle @@ -327,7 +327,7 @@ - (void) strokeLines:(NSArray *)params for (GLint i = 0; i < params.count; i += 3) { NSString *type = [WXConvert NSString:params[i]]; - points[pointIndex] = GLKVector2Make([WXConvert WXPixelType:params[i + 1]], [WXConvert WXPixelType:params[i + 2]]); + points[pointIndex] = GLKVector2Make([WXConvert WXPixelType:params[i + 1] scaleFactor:self.weexInstance.pixelScaleFactor], [WXConvert WXPixelType:params[i + 2] scaleFactor:self.weexInstance.pixelScaleFactor]); if ([type isEqualToString:@"L"]) { if (isLastMove) { diff --git a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m index 00fc7e1b64..5b2b85854a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m @@ -10,6 +10,7 @@ #import "WXSliderComponent.h" #import "WXConvert.h" #import "WXSliderNeighborComponent.h" +#import "WXSDKInstance.h" @implementation WXIndicatorView @@ -136,7 +137,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { _itemColor = styles[@"itemColor"] ? [WXConvert UIColor:styles[@"itemColor"]]:[UIColor colorWithRed:0xff/255.0f green:0xff/255.0f blue:0xff/255.0f alpha:0.5f]; _itemSelectedColor = styles[@"itemSelectedColor"] ? [WXConvert UIColor:styles[@"itemSelectedColor"]]:[UIColor colorWithRed:0xff/255.0f green:0xd5/255.0f blue:0x45/255.0f alpha:1.0f]; - _itemSize = styles[@"itemSize"] ? [WXConvert WXPixelType:styles[@"itemSize"]] : 5.0f; + _itemSize = styles[@"itemSize"] ? [WXConvert WXPixelType:styles[@"itemSize"] scaleFactor:self.weexInstance.pixelScaleFactor] : 5.0f; } return self; } @@ -185,7 +186,7 @@ - (void)updateStyles:(NSDictionary *)styles if (styles[@"itemSize"]) { styleChange = YES; - _itemSize = [WXConvert WXPixelType:styles[@"itemSize"]]; + _itemSize = [WXConvert WXPixelType:styles[@"itemSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; [_indicatorView setPointSize:_itemSize]; } diff --git a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m index 8e6a611099..37bca8de6a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m @@ -209,7 +209,7 @@ - (void)scrollToComponent:(WXComponent *)component withOffset:(CGFloat)offset NSIndexPath *toIndexPath = [self indexPathForCell:(WXCellComponent*)cellComponent sections:_completedSections]; CGRect cellRect = [_tableView rectForRowAtIndexPath:toIndexPath]; contentOffsetY += cellRect.origin.y; - contentOffsetY += offset * WXScreenResizeRadio(); + contentOffsetY += offset * self.weexInstance.pixelScaleFactor; if (contentOffsetY > _tableView.contentSize.height - _tableView.frame.size.height) { contentOffset.y = _tableView.contentSize.height - _tableView.frame.size.height; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m index 7a728839d0..1423f966e5 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m @@ -299,10 +299,11 @@ - (void)scrollToComponent:(WXComponent *)component withOffset:(CGFloat)offset { UIScrollView *scrollView = (UIScrollView *)self.view; CGPoint contentOffset = scrollView.contentOffset; + CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; if (_scrollDirection == WXScrollDirectionHorizontal) { CGFloat contentOffetX = [component.supercomponent.view convertPoint:component.view.frame.origin toView:self.view].x; - contentOffetX += offset * WXScreenResizeRadio(); + contentOffetX += offset * scaleFactor; if (contentOffetX > scrollView.contentSize.width - scrollView.frame.size.width) { contentOffset.x = scrollView.contentSize.width - scrollView.frame.size.width; @@ -311,7 +312,7 @@ - (void)scrollToComponent:(WXComponent *)component withOffset:(CGFloat)offset } } else { CGFloat contentOffetY = [component.supercomponent.view convertPoint:component.view.frame.origin toView:self.view].y; - contentOffetY += offset * WXScreenResizeRadio(); + contentOffetY += offset * scaleFactor; if (contentOffetY > scrollView.contentSize.height - scrollView.frame.size.height) { contentOffset.y = scrollView.contentSize.height - scrollView.frame.size.height; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m index d09d213413..93e50142e5 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m @@ -1557,7 +1557,7 @@ - (void)setIndicatorView:(WXIndicatorView *)indicatorView } - (void)setNeighborSpace:(NSDictionary *)attributes{ - self->neighborSpace = [WXConvert WXPixelType:@(25)]; + self->neighborSpace = [WXConvert WXPixelType:@(25) scaleFactor:self.weexInstance.pixelScaleFactor ]; } - (void)setNeighborAlpha:(NSDictionary *)attributes { diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m index f25fc40be6..54b4afdcb5 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m @@ -140,7 +140,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _color = [WXConvert UIColor:styles[@"color"]]; } if (styles[@"fontSize"]) { - _fontSize = [WXConvert WXPixelType:styles[@"fontSize"]]; + _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; } if (styles[@"fontWeight"]) { _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; @@ -333,7 +333,7 @@ - (void)updateStyles:(NSDictionary *)styles [_textView setTextColor:_color]; } if (styles[@"fontSize"]) { - _fontSize = [WXConvert WXPixelType:styles[@"fontSize"]]; + _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; } if (styles[@"fontWeight"]) { _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; @@ -450,7 +450,7 @@ - (void)textViewDidEndEditing:(UITextView *)textView - (void)setPlaceholderAttributedString { NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:_placeholderString]; - UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily]; + UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; if (_placeholderColor) { [attributedString addAttribute:NSForegroundColorAttributeName value:_placeholderColor range:NSMakeRange(0, _placeholderString.length)]; [attributedString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _placeholderString.length)]; @@ -480,7 +480,7 @@ - (void)setAutofocus - (void)setTextFont { - UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily]; + UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; [_textView setFont:font]; } diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 3896d04bc1..d7e4587e61 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -154,6 +154,8 @@ - (void)dealloc } } + + #define WX_STYLE_FILL_TEXT(key, prop, type, needLayout)\ do {\ id value = styles[@#key];\ @@ -166,18 +168,30 @@ - (void)dealloc }\ } while(0); +#define WX_STYLE_FILL_TEXT_PIXEL(key, prop, needLayout)\ +do {\ + id value = styles[@#key];\ + if (value) {\ + _##prop = [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor];\ + [self setNeedsRepaint];\ + if (needLayout) {\ + [self setNeedsLayout];\ + }\ +}\ +} while(0); + - (void)fillCSSStyles:(NSDictionary *)styles { WX_STYLE_FILL_TEXT(color, color, UIColor, NO) WX_STYLE_FILL_TEXT(fontFamily, fontFamily, NSString, YES) - WX_STYLE_FILL_TEXT(fontSize, fontSize, WXPixelType, YES) + WX_STYLE_FILL_TEXT_PIXEL(fontSize, fontSize, YES) WX_STYLE_FILL_TEXT(fontWeight, fontWeight, WXTextWeight, YES) WX_STYLE_FILL_TEXT(fontStyle, fontStyle, WXTextStyle, YES) WX_STYLE_FILL_TEXT(lines, lines, NSUInteger, YES) WX_STYLE_FILL_TEXT(textAlign, textAlign, NSTextAlignment, NO) WX_STYLE_FILL_TEXT(textDecoration, textDecoration, WXTextDecoration, YES) WX_STYLE_FILL_TEXT(textOverflow, textOverflow, NSString, NO) - WX_STYLE_FILL_TEXT(lineHeight, lineHeight, WXPixelType, YES) + WX_STYLE_FILL_TEXT_PIXEL(lineHeight, lineHeight, YES) UIEdgeInsets padding = { WXFloorPixelValue(self.cssNode->style.padding[CSS_TOP] + self.cssNode->style.border[CSS_TOP]), @@ -310,7 +324,7 @@ - (NSAttributedString *)buildAttributeString } // set font - UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily]; + UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; if (font) { [attributedString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, string.length)]; } diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m index f0e03352ff..269665e5a0 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m @@ -144,7 +144,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict } if (styles[@"fontSize"]) { - _fontSize = [WXConvert WXPixelType:styles[@"fontSize"]]; + _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; } if (styles[@"fontWeight"]) { _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; @@ -338,7 +338,7 @@ - (void)updateStyles:(NSDictionary *)styles [_inputView setTextColor:[WXConvert UIColor:styles[@"color"]]]; } if (styles[@"fontSize"]) { - _fontSize = [WXConvert WXPixelType:styles[@"fontSize"]]; + _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; } if (styles[@"fontWeight"]) { _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; @@ -528,7 +528,7 @@ - (void)setPlaceholderAttributedString - (void)setTextFont { - UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily]; + UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; [_inputView setFont:font]; } diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTransform.h b/ios/sdk/WeexSDK/Sources/Component/WXTransform.h index aab6d593db..1fed421281 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTransform.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXTransform.h @@ -8,11 +8,14 @@ #import #import +@class WXSDKInstance; @interface WXTransform : NSObject @property CGAffineTransform transform; +- (instancetype)initWithInstance:(WXSDKInstance *)instance NS_DESIGNATED_INITIALIZER; + - (CATransform3D)getTransform:(NSString *)cssValue; - (CATransform3D)getTransform:(NSString *)cssValue withView:(UIView *)view; - (CATransform3D)getTransform:(NSString *)cssValue withView:(UIView *)view withOrigin:(NSString *)origin; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTransform.m b/ios/sdk/WeexSDK/Sources/Component/WXTransform.m index b10dbd5c69..646ba08da4 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTransform.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTransform.m @@ -9,22 +9,30 @@ #import "WXTransform.h" #import "math.h" #import "WXUtility.h" +#import "WXSDKInstance.h" @interface WXTransform() @property (nonatomic, weak) UIView *view; @property (nonatomic, assign) float rotateAngle; @property (nonatomic, assign) BOOL isTransformRotate; +@property (nonatomic, weak) WXSDKInstance *weexInstance; @end @implementation WXTransform - (instancetype)init +{ + return [self initWithInstance:nil]; +} + +- (instancetype)initWithInstance:(WXSDKInstance *)weexInstance; { if (self = [super init]) { _isTransformRotate = YES; _rotateAngle = 0.0; + _weexInstance = weexInstance; } return self; @@ -124,14 +132,14 @@ - (CGPoint)getTransformOrigin:(NSString *)cssValue withView:(UIView *)view if ([value hasSuffix:@"%"]) { val *= width / 100; } else { - val = WXPixelResize(val); + val = WXPixelScale(val, self.weexInstance.pixelScaleFactor); } x = val; } else { if ([value hasSuffix:@"%"]) { val *= height / 100; } else { - val = WXPixelResize(val); + val = WXPixelScale(val, self.weexInstance.pixelScaleFactor); } y = val; } @@ -139,7 +147,9 @@ - (CGPoint)getTransformOrigin:(NSString *)cssValue withView:(UIView *)view } x -= width / 2.0; y -= height / 2.0; - return CGPointMake(round(x / WXScreenResizeRadio()), round(y / WXScreenResizeRadio())); + + CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; + return CGPointMake(round(x / scaleFactor), round(y / scaleFactor)); } // Angle in radians @@ -159,7 +169,7 @@ - (void)doTranslate:(NSArray *)value if ([value[0] hasSuffix:@"%"] && _view) { x *= _view.bounds.size.width / 100; } else { - x = WXPixelResize(x); + x = WXPixelScale(x, self.weexInstance.pixelScaleFactor); } double y = 0; @@ -169,7 +179,7 @@ - (void)doTranslate:(NSArray *)value if ([value[1] hasSuffix:@"%"] && _view) { y *= _view.bounds.size.height / 100; } else { - y = WXPixelResize(y); + y = WXPixelScale(y, self.weexInstance.pixelScaleFactor); } } _transform = CGAffineTransformTranslate(_transform, x, y); diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m index 59d65f09eb..bead23bacd 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m +++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m @@ -16,6 +16,7 @@ #import "WXThreadSafeCounter.h" #import "UIBezierPath+Weex.h" #import "WXRoundedRect.h" +#import "WXSDKInstance.h" #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" @@ -435,10 +436,45 @@ - (void)_handleBorders:(NSDictionary *)styles isUpdating:(BOOL)updating }\ } while (0); +// TODO: refactor this hopefully +#define WX_CHECK_BORDER_PROP_PIXEL(prop, direction1, direction2, direction3, direction4)\ +do {\ + BOOL needsDisplay = NO; \ + NSString *styleProp= WX_NSSTRING(WX_CONCAT(border, prop));\ + if (styles[styleProp]) {\ + _border##direction1##prop = _border##direction2##prop = _border##direction3##prop = _border##direction4##prop = [WXConvert WXPixelType:styles[styleProp] scaleFactor:self.weexInstance.pixelScaleFactor];\ + needsDisplay = YES;\ + }\ + NSString *styleDirection1Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction1, prop));\ + if (styles[styleDirection1Prop]) {\ + _border##direction1##prop = [WXConvert WXPixelType:styles[styleDirection1Prop] scaleFactor:self.weexInstance.pixelScaleFactor];\ + needsDisplay = YES;\ + }\ + NSString *styleDirection2Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction2, prop));\ + if (styles[styleDirection2Prop]) {\ + _border##direction2##prop = [WXConvert WXPixelType:styles[styleDirection2Prop] scaleFactor:self.weexInstance.pixelScaleFactor];\ + needsDisplay = YES;\ + }\ + NSString *styleDirection3Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction3, prop));\ + if (styles[styleDirection3Prop]) {\ + _border##direction3##prop = [WXConvert WXPixelType:styles[styleDirection2Prop] scaleFactor:self.weexInstance.pixelScaleFactor];\ + needsDisplay = YES;\ + }\ + NSString *styleDirection4Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction4, prop));\ + if (styles[styleDirection4Prop]) {\ + _border##direction4##prop = [WXConvert WXPixelType:styles[styleDirection2Prop] scaleFactor:self.weexInstance.pixelScaleFactor];\ + needsDisplay = YES;\ + }\ + if (needsDisplay && updating) {\ + [self setNeedsDisplay];\ + }\ +} while (0); + + WX_CHECK_BORDER_PROP(Style, Top, Left, Bottom, Right, WXBorderStyle) WX_CHECK_BORDER_PROP(Color, Top, Left, Bottom, Right, UIColor) - WX_CHECK_BORDER_PROP(Width, Top, Left, Bottom, Right, WXPixelType) - WX_CHECK_BORDER_PROP(Radius, TopLeft, TopRight, BottomLeft, BottomRight, WXPixelType) + WX_CHECK_BORDER_PROP_PIXEL(Width, Top, Left, Bottom, Right) + WX_CHECK_BORDER_PROP_PIXEL(Radius, TopLeft, TopRight, BottomLeft, BottomRight) if (updating) { BOOL nowNeedsDrawBorder = [self _needsDrawBorder]; diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m index 8d1ee670d4..f81ec3221b 100644 --- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m +++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m @@ -231,13 +231,14 @@ - (void)removeClickEvent - (void)onClick:(__unused UITapGestureRecognizer *)recognizer { NSMutableDictionary *position = [[NSMutableDictionary alloc] initWithCapacity:4]; + CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) { CGRect frame = [self.view.superview convertRect:self.calculatedFrame toView:self.view.window]; - position[@"x"] = @(frame.origin.x/WXScreenResizeRadio()); - position[@"y"] = @(frame.origin.y/WXScreenResizeRadio()); - position[@"width"] = @(frame.size.width/WXScreenResizeRadio()); - position[@"height"] = @(frame.size.height/WXScreenResizeRadio()); + position[@"x"] = @(frame.origin.x/scaleFactor); + position[@"y"] = @(frame.origin.y/scaleFactor); + position[@"width"] = @(frame.size.width/scaleFactor); + position[@"height"] = @(frame.size.height/scaleFactor); } [self fireEvent:@"click" params:@{@"position":position}]; @@ -539,10 +540,11 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni - (NSDictionary *)touchResultWithScreenLocation:(CGPoint)screenLocation pageLocation:(CGPoint)pageLocation identifier:(NSNumber *)identifier { NSMutableDictionary *resultTouch = [[NSMutableDictionary alloc] initWithCapacity:5]; - resultTouch[@"screenX"] = @(screenLocation.x/WXScreenResizeRadio()); - resultTouch[@"screenY"] = @(screenLocation.y/WXScreenResizeRadio()); - resultTouch[@"pageX"] = @(pageLocation.x/WXScreenResizeRadio()); - resultTouch[@"pageY"] = @(pageLocation.y/WXScreenResizeRadio()); + CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; + resultTouch[@"screenX"] = @(screenLocation.x/scaleFactor); + resultTouch[@"screenY"] = @(screenLocation.y/scaleFactor); + resultTouch[@"pageX"] = @(pageLocation.x/scaleFactor); + resultTouch[@"pageY"] = @(pageLocation.y/scaleFactor); resultTouch[@"identifier"] = identifier; return resultTouch; diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m index 63542b2e02..e6cfaba52d 100644 --- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m +++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m @@ -119,7 +119,8 @@ - (void)_frameDidCalculated:(BOOL)isChanged strongSelf.view.frame = strongSelf.calculatedFrame; if (strongSelf->_transform) { - strongSelf.layer.transform = [[WXTransform new] getTransform:strongSelf->_transform withView:strongSelf.view withOrigin:strongSelf->_transformOrigin]; + WXTransform *transform = [[WXTransform alloc] initWithInstance:strongSelf.weexInstance]; + strongSelf.layer.transform = [transform getTransform:strongSelf->_transform withView:strongSelf.view withOrigin:strongSelf->_transformOrigin]; } [strongSelf setNeedsDisplay]; @@ -199,23 +200,39 @@ - (void)_layoutDidFinish id value = styles[@#key];\ if (value) {\ typeof(_cssNode->style.cssProp) convertedValue = (typeof(_cssNode->style.cssProp))[WXConvert type:value];\ - if([@"WXPixelType" isEqualToString:@#type] && isnan(convertedValue)) {\ + _cssNode->style.cssProp = convertedValue;\ + [self setNeedsLayout];\ + }\ +} while(0); + +#define WX_STYLE_FILL_CSS_NODE_PIXEL(key, cssProp)\ +do {\ + id value = styles[@#key];\ + if (value) {\ + CGFloat pixel = [self WXPixelType:value];\ + if (isnan(pixel)) {\ WXLogError(@"Invalid NaN value for style:%@, ref:%@", @#key, self.ref);\ - } else { \ - _cssNode->style.cssProp = convertedValue;\ + } else {\ + _cssNode->style.cssProp = pixel;\ [self setNeedsLayout];\ - } \ + }\ }\ } while(0); -#define WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(key, cssProp, type) \ +#define WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(key, cssProp)\ do {\ - WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_TOP], type)\ - WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_LEFT], type)\ - WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_RIGHT], type)\ - WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_BOTTOM], type)\ + WX_STYLE_FILL_CSS_NODE_PIXEL(key, cssProp[CSS_TOP])\ + WX_STYLE_FILL_CSS_NODE_PIXEL(key, cssProp[CSS_LEFT])\ + WX_STYLE_FILL_CSS_NODE_PIXEL(key, cssProp[CSS_RIGHT])\ + WX_STYLE_FILL_CSS_NODE_PIXEL(key, cssProp[CSS_BOTTOM])\ } while(0); + +- (CGFloat)WXPixelType:(id)value +{ + return [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor]; +} + - (void)_fillCSSNode:(NSDictionary *)styles; { // flex @@ -228,39 +245,39 @@ - (void)_fillCSSNode:(NSDictionary *)styles; // position WX_STYLE_FILL_CSS_NODE(position, position_type, css_position_type_t) - WX_STYLE_FILL_CSS_NODE(top, position[CSS_TOP], WXPixelType) - WX_STYLE_FILL_CSS_NODE(left, position[CSS_LEFT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(right, position[CSS_RIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(bottom, position[CSS_BOTTOM], WXPixelType) + WX_STYLE_FILL_CSS_NODE_PIXEL(top, position[CSS_TOP]) + WX_STYLE_FILL_CSS_NODE_PIXEL(left, position[CSS_LEFT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(right, position[CSS_RIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(bottom, position[CSS_BOTTOM]) // dimension - WX_STYLE_FILL_CSS_NODE(width, dimensions[CSS_WIDTH], WXPixelType) - WX_STYLE_FILL_CSS_NODE(height, dimensions[CSS_HEIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(minWidth, minDimensions[CSS_WIDTH], WXPixelType) - WX_STYLE_FILL_CSS_NODE(minHeight, minDimensions[CSS_HEIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(maxWidth, maxDimensions[CSS_WIDTH], WXPixelType) - WX_STYLE_FILL_CSS_NODE(maxHeight, maxDimensions[CSS_HEIGHT], WXPixelType) + WX_STYLE_FILL_CSS_NODE_PIXEL(width, dimensions[CSS_WIDTH]) + WX_STYLE_FILL_CSS_NODE_PIXEL(height, dimensions[CSS_HEIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(minWidth, minDimensions[CSS_WIDTH]) + WX_STYLE_FILL_CSS_NODE_PIXEL(minHeight, minDimensions[CSS_HEIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(maxWidth, maxDimensions[CSS_WIDTH]) + WX_STYLE_FILL_CSS_NODE_PIXEL(maxHeight, maxDimensions[CSS_HEIGHT]) // margin - WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(margin, margin, WXPixelType) - WX_STYLE_FILL_CSS_NODE(marginTop, margin[CSS_TOP], WXPixelType) - WX_STYLE_FILL_CSS_NODE(marginLeft, margin[CSS_LEFT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(marginRight, margin[CSS_RIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(marginBottom, margin[CSS_BOTTOM], WXPixelType) + WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(margin, margin) + WX_STYLE_FILL_CSS_NODE_PIXEL(marginTop, margin[CSS_TOP]) + WX_STYLE_FILL_CSS_NODE_PIXEL(marginLeft, margin[CSS_LEFT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(marginRight, margin[CSS_RIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(marginBottom, margin[CSS_BOTTOM]) // border - WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(borderWidth, border, WXPixelType) - WX_STYLE_FILL_CSS_NODE(borderTopWidth, border[CSS_TOP], WXPixelType) - WX_STYLE_FILL_CSS_NODE(borderLeftWidth, border[CSS_LEFT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(borderRightWidth, border[CSS_RIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(borderBottomWidth, border[CSS_BOTTOM], WXPixelType) + WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(borderWidth, border) + WX_STYLE_FILL_CSS_NODE_PIXEL(borderTopWidth, border[CSS_TOP]) + WX_STYLE_FILL_CSS_NODE_PIXEL(borderLeftWidth, border[CSS_LEFT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(borderRightWidth, border[CSS_RIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(borderBottomWidth, border[CSS_BOTTOM]) // padding - WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(padding, padding, WXPixelType) - WX_STYLE_FILL_CSS_NODE(paddingTop, padding[CSS_TOP], WXPixelType) - WX_STYLE_FILL_CSS_NODE(paddingLeft, padding[CSS_LEFT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(paddingRight, padding[CSS_RIGHT], WXPixelType) - WX_STYLE_FILL_CSS_NODE(paddingBottom, padding[CSS_BOTTOM], WXPixelType) + WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(padding, padding) + WX_STYLE_FILL_CSS_NODE_PIXEL(paddingTop, padding[CSS_TOP]) + WX_STYLE_FILL_CSS_NODE_PIXEL(paddingLeft, padding[CSS_LEFT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(paddingRight, padding[CSS_RIGHT]) + WX_STYLE_FILL_CSS_NODE_PIXEL(paddingBottom, padding[CSS_BOTTOM]) } #define WX_STYLE_RESET_CSS_NODE(key, cssProp, defaultValue)\ diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index 8c04d8c03d..398ebd1da7 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -190,7 +190,7 @@ - (UIView *)view } if (_transform) { - _layer.transform = [[WXTransform new] getTransform:_transform withView:_view withOrigin:_transformOrigin]; + _layer.transform = [[[WXTransform alloc] initWithInstance:self.weexInstance] getTransform:_transform withView:_view withOrigin:_transformOrigin]; } _view.wx_component = self; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index 786f98294d..788f1cfa0f 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -140,6 +140,11 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code */ @property (nonatomic, strong) NSMutableDictionary *userInfo; +/** + * scale factor from css unit to device pixel. + */ +@property (nonatomic, assign, readonly) CGFloat pixelScaleFactor; + /** * Renders weex view with bundle url. * diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index d9ef7191bd..976e03d57f 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -343,6 +343,15 @@ - (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params [[NSNotificationCenter defaultCenter] postNotificationName:eventName object:self userInfo:userInfo]; } +- (CGFloat)pixelScaleFactor +{ + if (self.viewportWidth > 0) { + return [WXUtility portraitScreenSize].width / self.viewportWidth; + } else { + return [WXUtility defaultPixelScaleFactor]; + } +} + - (NSURL *)completeURL:(NSString *)url { if (!_scriptURL) { diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h index 3ec305965d..3455b2fe9e 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h @@ -12,6 +12,8 @@ @interface WXSDKInstance () +@property (nonatomic, assign) CGFloat viewportWidth; + @property (nonatomic, strong) NSMutableDictionary *moduleInstances; @property (nonatomic, strong) NSMutableDictionary *naviBarStyles; @property (nonatomic, strong) NSMutableDictionary *styleConfigs; diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index 2197299b8c..3368f53000 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -57,7 +57,7 @@ - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callb for (NSString *property in styles) { if ([property isEqualToString:@"transform"]) { NSString *transformOrigin = styles[@"transformOrigin"]; - WXTransform *wxTransform = [WXTransform new]; + WXTransform *wxTransform = [[WXTransform alloc] initWithInstance:self.weexInstance]; transform = [wxTransform getTransform:styles[property] withView:view withOrigin:transformOrigin isTransformRotate:NO]; rotateAngle = [wxTransform getRotateAngle]; if (rotateAngle > M_PI+0.0001) { @@ -75,10 +75,10 @@ - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callb opacity = [styles[property] floatValue]; isAnimateOpacity = YES; } else if ([property isEqualToString:@"width"]) { - newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, [WXConvert WXPixelType:styles[property]], newFrame.size.height); + newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, [WXConvert WXPixelType:styles[property] scaleFactor:self.weexInstance.pixelScaleFactor], newFrame.size.height); isAnimateFrame = YES; } else if ([property isEqualToString:@"height"]) { - newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, [WXConvert WXPixelType:styles[property]]); + newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, [WXConvert WXPixelType:styles[property] scaleFactor:self.weexInstance.pixelScaleFactor]); isAnimateFrame = YES; } } diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m index d0d85cc704..c6f080be41 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m @@ -173,16 +173,16 @@ - (void)getComponentRect:(NSString*)ref callback:(WXModuleKeepAliveCallback)call NSMutableDictionary * callbackRsp = [[NSMutableDictionary alloc] init]; UIView *rootView = manager.weexInstance.rootView; CGRect rootRect = [rootView.superview convertRect:rootView.frame toView:rootView.superview.superview]; - CGFloat resize = WXScreenResizeRadio(); + CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; if ([ref isEqualToString:@"viewport"]) { [callbackRsp setObject:@(true) forKey:@"result"]; [callbackRsp setObject:@{ - @"width":@(rootRect.size.width/resize), - @"height":@(rootRect.size.height/resize), - @"bottom":@(CGRectGetMaxY(rootRect)/WXScreenResizeRadio()), - @"left":@(rootRect.origin.x/resize), - @"right":@(CGRectGetMaxX(rootRect)/resize), - @"top":@(rootRect.origin.y/resize) + @"width":@(rootRect.size.width / scaleFactor), + @"height":@(rootRect.size.height / scaleFactor), + @"bottom":@(CGRectGetMaxY(rootRect) / scaleFactor), + @"left":@(rootRect.origin.x / scaleFactor), + @"right":@(CGRectGetMaxX(rootRect) / scaleFactor), + @"top":@(rootRect.origin.y / scaleFactor) } forKey:@"size"]; callback(callbackRsp, false); }else { @@ -195,12 +195,12 @@ - (void)getComponentRect:(NSString*)ref callback:(WXModuleKeepAliveCallback)call CGRect componentRect = [component.view.superview convertRect:component.calculatedFrame toView:rootView.superview.superview]; [callbackRsp setObject:@(true)forKey:@"result"]; [callbackRsp setObject:@{ - @"width":@(componentRect.size.width /resize), - @"height":@(componentRect.size.height / resize), - @"bottom":@(CGRectGetMaxY(componentRect) / resize), - @"left":@(componentRect.origin.x / resize), - @"right":@(CGRectGetMaxX(componentRect) / resize), - @"top":@(componentRect.origin.y / resize) + @"width":@(componentRect.size.width / scaleFactor), + @"height":@(componentRect.size.height / scaleFactor), + @"bottom":@(CGRectGetMaxY(componentRect) / scaleFactor), + @"left":@(componentRect.origin.x / scaleFactor), + @"right":@(CGRectGetMaxX(componentRect) / scaleFactor), + @"top":@(componentRect.origin.y / scaleFactor) } forKey:@"size"]; } callback(callbackRsp, false); diff --git a/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h new file mode 100644 index 0000000000..7d5c80c5ce --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h @@ -0,0 +1,14 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import +#import "WXModuleProtocol.h" + +@interface WXMetaModule : NSObject + +@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m new file mode 100644 index 0000000000..af8c2d0cb0 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m @@ -0,0 +1,40 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ +#import "WXMetaModule.h" +#import "WXConvert.h" +#import "WXUtility.h" +#import "WXSDKInstance_private.h" + +@implementation WXMetaModule + +@synthesize weexInstance; + +WX_EXPORT_METHOD(@selector(setViewport:)) + +- (void)setViewport:(NSDictionary *)viewportArguments +{ + CGFloat viewportWidthFloat; + id viewportWidth = viewportArguments[@"width"]; + if ([viewportWidth isKindOfClass:[NSString class]]) { + if ([viewportWidth isEqualToString:@"device-width"]) { + viewportWidthFloat = [WXUtility portraitScreenSize].width; + } else if ([viewportWidth isEqualToString:@"device-height"]) { + viewportWidthFloat = [WXUtility portraitScreenSize].height; + } else { + viewportWidthFloat = [WXConvert CGFloat:viewportWidth]; + } + } else { + viewportWidthFloat = [WXConvert CGFloat:viewportWidth]; + } + + if (viewportWidthFloat > 0) { + self.weexInstance.viewportWidth = viewportWidthFloat; + } +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m index bfa1ec0848..96fe87515a 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m @@ -308,7 +308,7 @@ + (NSString*)getStatusText:(NSInteger)code return @"Unknown"; } -#pragma mark - Deperecated +#pragma mark - Deprecated - (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback { diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h index c502229ae4..0045bf4ae0 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h @@ -24,7 +24,8 @@ * 750px Adaptive */ typedef CGFloat WXPixelType; -+ (WXPixelType)WXPixelType:(id)value; +// @prameter scaleFactor: please use weexInstance's pixelScaleFactor property ++ (WXPixelType)WXPixelType:(id)value scaleFactor:(CGFloat)scaleFactor; + (css_flex_direction_t)css_flex_direction_t:(id)value; + (css_align_t)css_align_t:(id)value; @@ -56,3 +57,9 @@ typedef BOOL WXClipType; + (WXVisibility)WXVisibility:(id)value; @end + +@interface WXConvert (Deprecated) + ++ (WXPixelType)WXPixelType:(id)value DEPRECATED_MSG_ATTRIBUTE("Use [WXConvert WXPixelType:scaleFactor:] instead"); + +@end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index 4e27178ad6..f4e940d81e 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -70,11 +70,11 @@ + (NSString *)NSString:(id)value return nil; } -+ (WXPixelType)WXPixelType:(id)value ++ (WXPixelType)WXPixelType:(id)value scaleFactor:(CGFloat)scaleFactor { CGFloat pixel = [self CGFloat:value]; - return pixel * WXScreenResizeRadio(); + return pixel * scaleFactor; } #pragma mark CSS Layout @@ -637,3 +637,14 @@ + (WXVisibility)WXVisibility:(id)value } @end + +@implementation WXConvert (Deprecated) + ++ (WXPixelType)WXPixelType:(id)value +{ + CGFloat pixel = [self CGFloat:value]; + + return pixel * WXScreenResizeRadio(); +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h index 9d39a48cc6..29372bdcb3 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h @@ -34,7 +34,7 @@ #define WX_SDK_ROOT_REF @"_root" -#define WX_TEXT_FONT_SIZE (32.0 * WXScreenResizeRadio()) +#define WX_TEXT_FONT_SIZE (32.0 * self.weexInstance.pixelScaleFactor) #define WX_UPDATE_CONFIG(prefix, name, configs) \ NSString *selStr = [NSString stringWithFormat:@"%@_%@", prefix, name];\ diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h index 8237d3984e..f2562f3a4e 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h @@ -211,7 +211,7 @@ extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector); * @return A font object according to the above params. * */ -+ (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily; ++ (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily scaleFactor:(CGFloat)scaleFactor; /** * @abstract download remote font from specified url @@ -221,24 +221,21 @@ extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector); + (void)getIconfont:(NSURL * _Nonnull)fontURL completion:( void(^ _Nullable )(NSURL * _Nonnull url, NSError * _Nullable error)) completionBlock; /** - * @abstract Returns the scale of the main screen. - * + * @abstract Returns the main screen's size when the device is in portrait mode,. */ -CGFloat WXScreenScale(); ++ (CGSize)portraitScreenSize; /** - * @abstract Returns the metrics of the main screen. - * + * @abstract Returns the default pixel scale factor + * @discussion If orientation is equal to landscape, the value is caculated as follows: WXScreenSize().height / WXDefaultScreenWidth, otherwise, WXScreenSize().width / WXDefaultScreenWidth. */ -CGSize WXScreenSize(); ++ (CGFloat)defaultPixelScaleFactor; /** - * @abstract Returns the resize radio of the main screen. - * - * @discussion If orientation is equal to landscape, the value is caculated as follows: WXScreenSize().height / WXDefaultScreenWidth, otherwise, WXScreenSize().width / WXDefaultScreenWidth. + * @abstract Returns the scale of the main screen. * */ -CGFloat WXScreenResizeRadio(void); +CGFloat WXScreenScale(); /** * @abstract Returns a Round float coordinates to the main screen pixel. @@ -258,24 +255,6 @@ CGFloat WXFloorPixelValue(CGFloat value); */ CGFloat WXCeilPixelValue(CGFloat value); -/** - * @abstract Returns a resized pixel which is caculated according to the WXScreenResizeRadio. - * - */ -CGFloat WXPixelResize(CGFloat value); - -/** - * @abstract Returns a resized frame which is caculated according to the WXScreenResizeRadio. - * - */ -CGRect WXPixelFrameResize(CGRect value); - -/** - * @abstract Returns a resized point which is caculated according to the WXScreenResizeRadio. - * - */ -CGPoint WXPixelPointResize(CGPoint value); - /** * @abstract check whether the file is exist * @@ -358,4 +337,18 @@ CGPoint WXPixelPointResize(CGPoint value); */ + (NSString *_Nullable)timeToString:(NSDate *_Nullable)date; + +/** + * @abstract Returns a resized pixel which is caculated according to the WXScreenResizeRadio. + * + */ +CGFloat WXPixelScale(CGFloat value, CGFloat scaleFactor); + + +CGFloat WXScreenResizeRadio(void) DEPRECATED_MSG_ATTRIBUTE("Use [WXUtility defaultPixelScaleFactor] instead"); +CGFloat WXPixelResize(CGFloat value) DEPRECATED_MSG_ATTRIBUTE("Use WXPixelScale Instead"); +CGRect WXPixelFrameResize(CGRect value) DEPRECATED_MSG_ATTRIBUTE("Use WXPixelScale Instead"); +CGPoint WXPixelPointResize(CGPoint value) DEPRECATED_MSG_ATTRIBUTE("Use WXPixelScale Instead"); + + @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index bac9288a63..e0344eff94 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -92,9 +92,9 @@ CGFloat WXScreenScale(void) return _scale; } -CGSize WXScreenSize(void) +CGFloat WXPixelScale(CGFloat value, CGFloat scaleFactor) { - return [UIScreen mainScreen].bounds.size; + return WXCeilPixelValue(value * scaleFactor); } CGFloat WXRoundPixelValue(CGFloat value) @@ -115,26 +115,6 @@ CGFloat WXFloorPixelValue(CGFloat value) return floor(value * scale) / scale; } -CGFloat WXPixelResize(CGFloat value) -{ - return WXCeilPixelValue(value * WXScreenResizeRadio()); -} - -CGRect WXPixelFrameResize(CGRect value) -{ - CGRect new = CGRectMake(value.origin.x * WXScreenResizeRadio(), - value.origin.y * WXScreenResizeRadio(), - value.size.width * WXScreenResizeRadio(), - value.size.height * WXScreenResizeRadio()); - return new; -} - -CGPoint WXPixelPointResize(CGPoint value) -{ - CGPoint new = CGPointMake(value.x * WXScreenResizeRadio(), - value.y * WXScreenResizeRadio()); - return new; -} static BOOL WXNotStat; @implementation WXUtility @@ -167,8 +147,8 @@ + (NSDictionary *)getEnvironment NSString *appVersion = [WXAppConfiguration appVersion] ? : @""; NSString *appName = [WXAppConfiguration appName] ? : @""; - CGFloat deviceWidth = [[UIScreen mainScreen] bounds].size.width; - CGFloat deviceHeight = [[UIScreen mainScreen] bounds].size.height; + CGFloat deviceWidth = [self portraitScreenSize].width; + CGFloat deviceHeight = [self portraitScreenSize].height; CGFloat scale = [[UIScreen mainScreen] scale]; NSMutableDictionary *data = [NSMutableDictionary dictionaryWithDictionary:@{ @@ -340,9 +320,9 @@ + (NSError *)errorWithCode:(NSInteger)code message:(NSString *)message return [NSError errorWithDomain:@"WeexErrorDomain" code:code userInfo:@{@"errMsg":message}]; } -+ (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily ++ (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily scaleFactor:(CGFloat)scaleFactor { - CGFloat fontSize = (isnan(size) || size == 0) ? WX_TEXT_FONT_SIZE : size; + CGFloat fontSize = (isnan(size) || size == 0) ? 32 * scaleFactor : size; UIFont *font = nil; WXThreadSafeMutableDictionary *fontFace = [[WXRuleManager sharedInstance] getRule:@"fontFace"]; @@ -495,31 +475,31 @@ + (NSString *)registeredDeviceName return model; } -CGFloat WXScreenResizeRadio(void) ++ (CGSize)portraitScreenSize { - return [WXUtility screenResizeScale]; + static CGSize portraitScreenSize; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CGSize screenSize = [UIScreen mainScreen].bounds.size; + portraitScreenSize = CGSizeMake(MIN(screenSize.width, screenSize.height), + MAX(screenSize.width, screenSize.height)); + }); + + return portraitScreenSize; } -+ (CGFloat)screenResizeScale ++ (CGFloat)defaultPixelScaleFactor { - static CGFloat resizeScale; + static CGFloat defaultScaleFactor; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - CGSize size = WXScreenSize(); - CGFloat deviceWidth; - if (size.width > size.height) { - // Landscape - deviceWidth = size.height; - } else { - deviceWidth = size.width; - } - - resizeScale = deviceWidth / WXDefaultScreenWidth; + defaultScaleFactor = [self portraitScreenSize].width / WXDefaultScreenWidth; }); - return resizeScale; + return defaultScaleFactor; } + #pragma mark - get deviceID + (NSString *)getDeviceID { NSMutableDictionary *usernamepasswordKVPairs = (NSMutableDictionary *)[self load:KEY_USERNAME_PASSWORD]; @@ -667,3 +647,32 @@ + (NSString *)timeToString:(NSDate *)date } @end + + +//Deprecated +CGFloat WXScreenResizeRadio(void) +{ + return [WXUtility defaultPixelScaleFactor]; +} + +CGFloat WXPixelResize(CGFloat value) +{ + return WXCeilPixelValue(value * WXScreenResizeRadio()); +} + +CGRect WXPixelFrameResize(CGRect value) +{ + CGRect new = CGRectMake(value.origin.x * WXScreenResizeRadio(), + value.origin.y * WXScreenResizeRadio(), + value.size.width * WXScreenResizeRadio(), + value.size.height * WXScreenResizeRadio()); + return new; +} + +CGPoint WXPixelPointResize(CGPoint value) +{ + CGPoint new = CGPointMake(value.x * WXScreenResizeRadio(), + value.y * WXScreenResizeRadio()); + return new; +} + diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m index 5cc5094cc9..1a53833f54 100644 --- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m +++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m @@ -156,7 +156,7 @@ - (void)_updateViewStyles:(NSDictionary *)styles if (styles[@"transform"]) { if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) { _transform = [WXConvert NSString:styles[@"transform"]]; - _layer.transform = [[WXTransform new] getTransform:_transform withView:_view withOrigin:_transformOrigin]; + _layer.transform = [[[WXTransform alloc] initWithInstance:self.weexInstance] getTransform:_transform withView:_view withOrigin:_transformOrigin]; [_layer setNeedsDisplay]; } } diff --git a/ios/sdk/WeexSDK/Sources/WeexSDK.h b/ios/sdk/WeexSDK/Sources/WeexSDK.h index d55203144d..33eb2bb11d 100644 --- a/ios/sdk/WeexSDK/Sources/WeexSDK.h +++ b/ios/sdk/WeexSDK/Sources/WeexSDK.h @@ -18,6 +18,7 @@ #import "WXSDKError.h" #import "WXSDKEngine.h" #import "WXRootViewController.h" +#import "WXResourceRequest.h" #import "WXNetworkProtocol.h" #import "WXNavigationProtocol.h" #import "WXMonitor.h" From f0d06d51d66bd8eec3717e69da477138b0597ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Tue, 13 Dec 2016 21:35:03 +0800 Subject: [PATCH 008/144] * [ios] public resource request --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index fe639becf8..fede7504d7 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -94,7 +94,7 @@ 7423899B1C3174EB00D748CA /* WXWeakObjectWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */; }; 7423899C1C3174EB00D748CA /* WXWeakObjectWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */; }; 7423899F1C32733800D748CA /* WXType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423899D1C32733800D748CA /* WXType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7251DF98C45007DC46C /* WXResourceRequest.h */; }; + 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7251DF98C45007DC46C /* WXResourceRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 742AD7261DF98C45007DC46C /* WXResourceRequest.m */; }; 742AD7301DF98C45007DC46C /* WXResourceRequestHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */; }; 742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 742AD7281DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h */; }; From 563fc55ea26ea48a6b8a527475765a79472bfa17 Mon Sep 17 00:00:00 2001 From: mingyi Date: Wed, 14 Dec 2016 15:06:23 +0800 Subject: [PATCH 009/144] add attribute-scrollable to scrller&slider&sliderNeighbor --- ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m | 2 -- ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m | 7 +++++++ ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m | 9 +++++++++ .../Sources/Component/WXSliderNeighborComponent.m | 9 +++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 51d4fddce7..0a3cd19bf7 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -103,8 +103,6 @@ - (void)configFilter:(NSDictionary *)styles { - (UIView *)loadView { - WXImageView *view = [[WXImageView alloc] init]; - return [[WXImageView alloc] init]; } diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m index 7a728839d0..1edafab4de 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m @@ -44,6 +44,7 @@ @implementation WXScrollerComponent CGFloat _loadMoreOffset; CGFloat _previousLoadMoreContentHeight; CGPoint _lastContentOffset; + BOOL _scrollable; // vertical & horizontal WXScrollDirection _scrollDirection; @@ -91,6 +92,7 @@ -(instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDicti _loadMoreOffset = attributes[@"loadmoreoffset"] ? [WXConvert CGFloat:attributes[@"loadmoreoffset"]] : 0; _loadmoreretry = attributes[@"loadmoreretry"] ? [WXConvert NSUInteger:attributes[@"loadmoreretry"]] : 0; _listenLoadMore = [events containsObject:@"loadmore"]; + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; _scrollerCSSNode = new_css_node(); @@ -123,6 +125,7 @@ - (void)viewDidLoad scrollView.clipsToBounds = YES; scrollView.showsVerticalScrollIndicator = _showScrollBar; scrollView.showsHorizontalScrollIndicator = _showScrollBar; + scrollView.scrollEnabled = _scrollable; if (self.ancestorScroller) { scrollView.scrollsToTop = NO; @@ -174,6 +177,10 @@ - (void)updateAttributes:(NSDictionary *)attributes } self.loadmoreretry = loadmoreretry; } + if (attributes[@"scrollable"]) { + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + ((UIScrollView *)self.view).scrollEnabled = _scrollable; + } } - (void)addEvent:(NSString *)eventName diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m index 79bfce37d4..dd19ea4fd7 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m @@ -291,6 +291,7 @@ @interface WXSliderComponent () @property (nonatomic, assign) NSInteger index; @property (nonatomic, assign) BOOL sliderChangeEvent; @property (nonatomic, strong) NSMutableArray *childrenView; +@property (nonatomic, assign) BOOL scrollable; @end @@ -320,6 +321,8 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _index = [attributes[@"index"] integerValue]; } + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW; } return self; @@ -338,6 +341,7 @@ - (void)viewDidLoad _sliderView.delegate = self; _sliderView.scrollView.pagingEnabled = YES; _sliderView.exclusiveTouch = YES; + _sliderView.scrollView.scrollEnabled = _scrollable; if (_autoPlay) { [self _startAutoPlayTimer]; @@ -444,6 +448,11 @@ - (void)updateAttributes:(NSDictionary *)attributes self.currentIndex = _index; [_sliderView scroll2ItemView:self.currentIndex animated:YES]; } + + if (attributes[@"scrollable"]) { + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + ((WXSliderView *)self.view).scrollView.scrollEnabled = _scrollable; + } } - (void)addEvent:(NSString *)eventName diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m index d09d213413..130d06b63d 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m @@ -1374,6 +1374,8 @@ @interface WXSliderNeighborComponent() { @property (nonatomic, assign) BOOL sliderChangeEvent; @property (nonatomic, assign) NSInteger currentIndex; @property (nonatomic) CGRect itemRect; +@property (nonatomic, assign) BOOL scrollable; + @end @implementation WXSliderNeighborComponent @@ -1411,6 +1413,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _interval = [attributes[@"interval"] integerValue]; } + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; } self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW; @@ -1431,6 +1434,7 @@ - (void)viewDidLoad _sliderView.delegate = self; _sliderView.dataSource = self; _sliderView.contentView.clipsToBounds = YES; + _sliderView.scrollEnabled = _scrollable; if (_autoPlay) { [self _startAutoPlayTimer]; } else { @@ -1526,6 +1530,11 @@ - (void)updateAttributes:(NSDictionary *)attributes [self setNeighborSpace:attributes]; } + if (attributes[@"scrollable"]) { + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + ((WXSliderNeighborView *)self.view).scrollEnabled = _scrollable; + } + [self.sliderView setCurrentItemIndex:_index]; [self updateSliderPage:YES]; } From e24283b1aee186058780fbd75a5ad7d75147ee2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 14 Dec 2016 16:24:23 +0800 Subject: [PATCH 010/144] =?UTF-8?q?+=20[ios]=20when=20image=20load=20?= =?UTF-8?q?=EF=BC=8Ctell=20weex=20image=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 6baac1d9a7..349f11aaab 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -250,6 +250,9 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo __strong typeof(self) strongSelf = weakSelf; if (weakSelf.imageLoadEvent) { + NSMutableDictionary *sizeDict = [NSMutableDictionary new]; + sizeDict[@"naturalWidth"] = @(image.size.width); + sizeDict[@"naturalHeight"] = @(image.size.height); [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true"}]; } if (error) { From 8956b39e18bdef4b66c43fe8a82ccaba4d7b00fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 14 Dec 2016 17:16:49 +0800 Subject: [PATCH 011/144] + [ios] add size params for image --- ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 349f11aaab..701716dcb8 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -253,7 +253,7 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo NSMutableDictionary *sizeDict = [NSMutableDictionary new]; sizeDict[@"naturalWidth"] = @(image.size.width); sizeDict[@"naturalHeight"] = @(image.size.height); - [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true"}]; + [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true",@"size":sizeDict}]; } if (error) { downloadFailedBlock(imageSrc, error); From 97334dc907f362fc70ef17e4227e4030ff92b90f Mon Sep 17 00:00:00 2001 From: acton393 Date: Wed, 14 Dec 2016 17:26:37 +0800 Subject: [PATCH 012/144] * [ios] add option param support --- .../WeexSDK/Sources/Manager/WXModuleManager.m | 6 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 2 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 67 ++++++++++++++----- .../Sources/Model/WXSDKInstance_private.h | 4 +- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m index beb830a91d..af7ffcd924 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m @@ -82,15 +82,15 @@ - (void)dispatchMethod:(WXBridgeMethod *)method WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance]; id moduleInstance = [weexInstance moduleForClass:module]; if ([method.method isEqualToString:@"addEventListener"]) { - if([method.arguments[0] isKindOfClass:[NSString class]] && method.arguments[1]) { - [weexInstance addModuleEventObservers:method.arguments[0] callback:method.arguments[1] module:moduleInstance]; + if([method.arguments[0] isKindOfClass:[NSString class]] && method.arguments[1] && method.arguments[2]) { + [weexInstance addModuleEventObservers:method.arguments[0] callback:method.arguments[1] option:method.arguments[2] moduleClassName:NSStringFromClass(module)]; } return; } if ([method.method isEqualToString:@"removeEventListener"]) { if ([method.arguments[0] isKindOfClass:[NSString class]]) { - [weexInstance removeModuleEventObserver:method.arguments[0] module:moduleInstance]; + [weexInstance removeModuleEventObserver:method.arguments[0] moduleClassName:NSStringFromClass(module)]; } return; } diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index 273a9045d2..7f5c1f66a1 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -197,7 +197,7 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code /** * check whether the module eventName is registered */ -- (BOOL)checkModuleEventRegistered:(NSString*)event module:(id)module; +- (BOOL)checkModuleEventRegistered:(NSString*)event moduleClassName:(NSString*)moduleClassName; /** * fire module event; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index 6d4bca2d02..8e47714c94 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -23,6 +23,8 @@ #import "WXRootView.h" #import "WXThreadSafeMutableDictionary.h" +#define WX_MODULE_EVENT_FIRE_NOTIFICATION @"WX_MODULE_EVENT_FIRE_NOTIFICATION" + NSString *const bundleUrlOptionKey = @"bundleUrl"; NSTimeInterval JSLibInitTime = 0; @@ -339,11 +341,12 @@ - (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params - (void)fireModuleEvent:(id)module eventName:(NSString *)eventName params:(NSDictionary*)params { NSDictionary * userInfo = @{ - @"moduleId":[module description]?:@"", - @"param":params?:@{} + @"moduleId":NSStringFromClass(module)?:@"", + @"param":params?:@{}, + @"eventName":eventName }; - [[NSNotificationCenter defaultCenter] postNotificationName:eventName object:self userInfo:userInfo]; + [[NSNotificationCenter defaultCenter] postNotificationName:WX_MODULE_EVENT_FIRE_NOTIFICATION object:self userInfo:userInfo]; } - (NSURL *)completeURL:(NSString *)url @@ -359,34 +362,66 @@ - (NSURL *)completeURL:(NSString *)url return [NSURL URLWithString:url relativeToURL:_scriptURL]; } -- (BOOL)checkModuleEventRegistered:(NSString*)event module:(id)module +- (BOOL)checkModuleEventRegistered:(NSString*)event moduleClassName:(NSString*)moduleClassName { - return [_moduleEventObservers[module] objectForKey:event] ? TRUE:FALSE; + NSDictionary * observer = _moduleEventObservers[moduleClassName]; + return observer && observer[event]? YES:NO; } #pragma mark Private Methods -- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId module:(id)module +- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId option:(NSDictionary *)option moduleClassName:(NSString*)moduleClassName { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moduleEventNotif:) name:event object:nil]; - [_moduleEventObservers setObject:@{event:callbackId} forKey:module]; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moduleEventNotification:) name:WX_MODULE_EVENT_FIRE_NOTIFICATION object:nil]; + }); + BOOL once = [[option objectForKey:@"once"] boolValue]; + NSMutableDictionary * observer = nil; + NSMutableDictionary * callbackInfo = @{@"callbackId":callbackId,@"once":@(once)}; + if(![self checkModuleEventRegistered:event moduleClassName:moduleClassName]) { + //had not registered yet + observer = [NSMutableDictionary new]; + + [observer setObject:@{event:@[callbackInfo]} forKey:moduleClassName]; + [_moduleEventObservers addEntriesFromDictionary:observer]; + } else { + observer = _moduleEventObservers[moduleClassName]; + [[observer objectForKey:event] addObject:callbackInfo]; + } } -- (void)removeModuleEventObserver:(NSString*)event module:(id)module +- (void)removeModuleEventObserver:(NSString*)event moduleClassName:(NSString*)moduleClassName { - [[NSNotificationCenter defaultCenter] removeObserver:self name:event object:nil]; - [_moduleEventObservers[module] removeObjectForKey:event]; - if ([_moduleEventObservers[module] count] == 0) { - [_moduleEventObservers removeObjectForKey:module]; + if (![self checkModuleEventRegistered:event moduleClassName:moduleClassName]) { + return; } + [_moduleEventObservers[moduleClassName] removeObjectForKey:event]; } -- (void)moduleEventNotif:(NSNotification *)notification +- (void)moduleEventNotification:(NSNotification *)notification { NSDictionary * moduleEventObserversCpy = [_moduleEventObservers copy]; NSDictionary * userInfo = notification.userInfo; - for (WXModuleKeepAliveCallback callback in [moduleEventObserversCpy[userInfo[@"moduleId"]] objectForKey:notification.name]) { - callback(userInfo[@"param"], true); + NSMutableArray * listeners = [moduleEventObserversCpy[userInfo[@"moduleId"]] objectForKey:userInfo[@"eventName"]]; + if (![listeners isKindOfClass:[NSArray class]]) { + return; + // something wrong + } + for (int i = 0;i < [listeners count]; i ++) { + NSDictionary * callbackInfo = listeners[i]; + NSString *callbackId = callbackInfo[@"callbackId"]; + BOOL once = [callbackInfo[@"once"] boolValue]; + [[WXSDKManager bridgeMgr] callBack:self.instanceId funcId:callbackId params:userInfo[@"param"] keepAlive:!once]; + // if callback function is not once, then it is keepalive + if (once) { + NSMutableArray * moduleEventListener = [_moduleEventObservers[userInfo[@"moduleId"]] objectForKey:userInfo[@"eventName"]]; + [moduleEventListener removeObjectAtIndex:i]; + if ([_moduleEventObservers count] == 0) { + [self removeModuleEventObserver:userInfo[@"eventName"] moduleClassName:userInfo[@"moduleId"]]; + } + // if callback function is once. clear it after fire it. + } } } diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h index 367f296a1e..25a5be20a7 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h @@ -19,7 +19,7 @@ @property (nonatomic, readonly, strong) WXComponentManager *componentManager; -- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId module:(id)module; -- (void)removeModuleEventObserver:(NSString*)event module:(id)module; +- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId option:(NSDictionary*)option moduleClassName:(NSString*)moduleClassName; +- (void)removeModuleEventObserver:(NSString*)event moduleClassName:(NSString*)moduleClassName; @end From 542d8edfe7ee8aad57f47081009e2b4e010ad3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 14 Dec 2016 17:27:20 +0800 Subject: [PATCH 013/144] + [ios] add image scale .iphone render image user image scale --- ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 701716dcb8..acbcba580b 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -251,8 +251,8 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo if (weakSelf.imageLoadEvent) { NSMutableDictionary *sizeDict = [NSMutableDictionary new]; - sizeDict[@"naturalWidth"] = @(image.size.width); - sizeDict[@"naturalHeight"] = @(image.size.height); + sizeDict[@"naturalWidth"] = @(image.size.width * image.scale); + sizeDict[@"naturalHeight"] = @(image.size.height * image.scale); [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true",@"size":sizeDict}]; } if (error) { From 0af470b51d1842bf62974cd3ed682c14e6fc47c0 Mon Sep 17 00:00:00 2001 From: acton393 Date: Wed, 14 Dec 2016 17:56:26 +0800 Subject: [PATCH 014/144] * [ios] revert weexDemo.project file --- .../WeexDemo.xcodeproj/project.pbxproj | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/ios/playground/WeexDemo.xcodeproj/project.pbxproj b/ios/playground/WeexDemo.xcodeproj/project.pbxproj index a67e73585e..31a50f4d76 100644 --- a/ios/playground/WeexDemo.xcodeproj/project.pbxproj +++ b/ios/playground/WeexDemo.xcodeproj/project.pbxproj @@ -302,13 +302,13 @@ isa = PBXNativeTarget; buildConfigurationList = 775BEEA81C1E8ECC008D1629 /* Build configuration list for PBXNativeTarget "WeexDemo" */; buildPhases = ( - 359BEE13DD78032A2CB791E8 /* [CP] Check Pods Manifest.lock */, + 359BEE13DD78032A2CB791E8 /* Check Pods Manifest.lock */, 74CC7A221C2C13BF00829368 /* Start Samples */, 775BEE771C1E8ECC008D1629 /* Sources */, 775BEE781C1E8ECC008D1629 /* Frameworks */, 775BEE791C1E8ECC008D1629 /* Resources */, - 0B3B6C05EE2F8A3B30DE551F /* [CP] Copy Pods Resources */, - 5ED24D6A09B32268BB031206 /* [CP] Embed Pods Frameworks */, + 0B3B6C05EE2F8A3B30DE551F /* Copy Pods Resources */, + 5ED24D6A09B32268BB031206 /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -341,12 +341,12 @@ isa = PBXNativeTarget; buildConfigurationList = 84361D711CA10F8E00F43825 /* Build configuration list for PBXNativeTarget "WeexUITestDemo" */; buildPhases = ( - 84361D271CA10F8E00F43825 /* [CP] Check Pods Manifest.lock */, + 84361D271CA10F8E00F43825 /* Check Pods Manifest.lock */, 84361D291CA10F8E00F43825 /* Sources */, 84361D3C1CA10F8E00F43825 /* Frameworks */, 84361D431CA10F8E00F43825 /* Resources */, - 84361D6F1CA10F8E00F43825 /* [CP] Copy Pods Resources */, - 84361D701CA10F8E00F43825 /* [CP] Embed Pods Frameworks */, + 84361D6F1CA10F8E00F43825 /* Copy Pods Resources */, + 84361D701CA10F8E00F43825 /* Embed Pods Frameworks */, 567369891CE436EB000A646C /* ShellScript */, ); buildRules = ( @@ -430,14 +430,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 0B3B6C05EE2F8A3B30DE551F /* [CP] Copy Pods Resources */ = { + 0B3B6C05EE2F8A3B30DE551F /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Copy Pods Resources"; + name = "Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -445,19 +445,19 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexDemo/Pods-WeexDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 359BEE13DD78032A2CB791E8 /* [CP] Check Pods Manifest.lock */ = { + 359BEE13DD78032A2CB791E8 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Check Pods Manifest.lock"; + name = "Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 567369891CE436EB000A646C /* ShellScript */ = { @@ -473,19 +473,20 @@ shellPath = /bin/sh; shellScript = "myFile=\"XcodeCoverage/exportenv.sh\"\n\nif [ -f \"$myFile\" ]; then\nXcodeCoverage/exportenv.sh\nfi"; }; - 5ED24D6A09B32268BB031206 /* [CP] Embed Pods Frameworks */ = { + 5ED24D6A09B32268BB031206 /* Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; + name = "Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexDemo/Pods-WeexDemo-frameworks.sh\"\n"; + shellScript = " +"; showEnvVarsInLog = 0; }; 74CC7A221C2C13BF00829368 /* Start Samples */ = { @@ -502,29 +503,29 @@ shellPath = /bin/sh; shellScript = "set -x\n\nif nc -w 5 -z localhost 12580 ; then\n echo \"Port 12580 already in use, server is running\"\nelse\n open \"$SRCROOT/../../start\"\nfi\n\n"; }; - 84361D271CA10F8E00F43825 /* [CP] Check Pods Manifest.lock */ = { + 84361D271CA10F8E00F43825 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Check Pods Manifest.lock"; + name = "Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 84361D6F1CA10F8E00F43825 /* [CP] Copy Pods Resources */ = { + 84361D6F1CA10F8E00F43825 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Copy Pods Resources"; + name = "Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -532,14 +533,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WeexUITestDemo/Pods-WeexUITestDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 84361D701CA10F8E00F43825 /* [CP] Embed Pods Frameworks */ = { + 84361D701CA10F8E00F43825 /* Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; + name = "Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; From 1e33aac280cd893d07e55ff152a73c98c7052702 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 15 Dec 2016 10:59:13 +0800 Subject: [PATCH 015/144] * [ios] add removeObserver for globalEvent module dealloc --- ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m b/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m index 18cac7ce19..452b427abe 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m @@ -63,4 +63,9 @@ - (void)fireGlobalEvent:(NSNotification *)notification } } +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + @end From 8b0fca5902ac389348b8be4ab3ad94f1eeaf9a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A4=E5=89=91?= Date: Thu, 15 Dec 2016 11:19:53 +0800 Subject: [PATCH 016/144] * [ios] add :Slider component add onscroll event and support to set the monitoring accuracy. --- .../Sources/Component/WXSliderComponent.m | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m index 79bfce37d4..d96cfa2ca9 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m @@ -18,6 +18,7 @@ @protocol WXSliderViewDelegate +- (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView *)scrollView; - (void)sliderView:(WXSliderView *)sliderView didScrollToItemAtIndex:(NSInteger)index; @end @@ -263,6 +264,9 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView if (itemView) { self.currentIndex = itemView.tag; } + if (self.delegate && [self.delegate respondsToSelector:@selector(sliderView:sliderViewDidScroll:)]) { + [self.delegate sliderView:self sliderViewDidScroll:self.scrollView]; + } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView @@ -289,7 +293,10 @@ @interface WXSliderComponent () @property (nonatomic, assign) BOOL autoPlay; @property (nonatomic, assign) NSUInteger interval; @property (nonatomic, assign) NSInteger index; +@property (nonatomic, assign) CGFloat lastXDeviationPercent; +@property (nonatomic, assign) CGFloat scrollAccuracy; @property (nonatomic, assign) BOOL sliderChangeEvent; +@property (nonatomic, assign) BOOL sliderScrollEvent; @property (nonatomic, strong) NSMutableArray *childrenView; @end @@ -305,8 +312,10 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict { if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { _sliderChangeEvent = NO; + _sliderScrollEvent = NO; _interval = 3000; _childrenView = [NSMutableArray new]; + _lastXDeviationPercent = 0; if (attributes[@"autoPlay"]) { _autoPlay = [attributes[@"autoPlay"] boolValue]; @@ -320,6 +329,10 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _index = [attributes[@"index"] integerValue]; } + if (attributes[@"xDeviationAccuracy"]) { + _scrollAccuracy = [WXConvert CGFloat:attributes[@"xDeviationAccuracy"]]; + } + self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW; } return self; @@ -444,6 +457,10 @@ - (void)updateAttributes:(NSDictionary *)attributes self.currentIndex = _index; [_sliderView scroll2ItemView:self.currentIndex animated:YES]; } + + if (attributes[@"xDeviationAccuracy"]) { + _scrollAccuracy = [WXConvert CGFloat:attributes[@"xDeviationAccuracy"]]; + } } - (void)addEvent:(NSString *)eventName @@ -451,6 +468,9 @@ - (void)addEvent:(NSString *)eventName if ([eventName isEqualToString:@"change"]) { _sliderChangeEvent = YES; } + if ([eventName isEqualToString:@"scroll"]) { + _sliderScrollEvent = YES; + } } - (void)removeEvent:(NSString *)eventName @@ -458,6 +478,9 @@ - (void)removeEvent:(NSString *)eventName if ([eventName isEqualToString:@"change"]) { _sliderChangeEvent = NO; } + if ([eventName isEqualToString:@"scroll"]) { + _sliderScrollEvent = NO; + } } #pragma mark Public Methods @@ -509,10 +532,24 @@ - (void)_autoPlayOnTimer } } +#pragma mark ScrollView Delegate + +- (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView *)scrollView +{ + if (_sliderScrollEvent) { + CGFloat width = scrollView.frame.size.width; + CGFloat XDeviation = scrollView.frame.origin.x - (scrollView.contentOffset.x - width); + CGFloat XDeviationPercent = (XDeviation / width); + if (ABS(XDeviationPercent - _lastXDeviationPercent) >= _scrollAccuracy) { + _lastXDeviationPercent = XDeviationPercent; + [self fireEvent:@"scroll" params:@{@"XDeviationPercent":[NSNumber numberWithFloat:XDeviationPercent]} domChanges:nil]; + } + } +} + - (void)sliderView:(WXSliderView *)sliderView didScrollToItemAtIndex:(NSInteger)index { self.currentIndex = index; - if (_sliderChangeEvent) { [self fireEvent:@"change" params:@{@"index":@(index)} domChanges:@{@"attrs": @{@"index": @(index)}}]; } From 675777b9df5499eeb71050837a9f6b14008e1f78 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 15 Dec 2016 16:25:10 +0800 Subject: [PATCH 017/144] * [ios] enable set neighbor-space for slider-neighbor --- .../WeexSDK/Sources/Component/WXSliderNeighborComponent.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m index d09d213413..b3ec0de313 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m @@ -1557,7 +1557,11 @@ - (void)setIndicatorView:(WXIndicatorView *)indicatorView } - (void)setNeighborSpace:(NSDictionary *)attributes{ - self->neighborSpace = [WXConvert WXPixelType:@(25)]; + if(attributes[@"neighborSpace"]) { + self->neighborSpace = [WXConvert WXPixelType:attributes[@"neighborSpace"]]; + } else { + self->neighborSpace = [WXConvert WXPixelType:@(25)]; + } } - (void)setNeighborAlpha:(NSDictionary *)attributes { From 182414842f21c4d754cd76aa114632324914f099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A4=E5=89=91?= Date: Fri, 16 Dec 2016 13:16:39 +0800 Subject: [PATCH 018/144] * [example] fix : update the demo for slider-neighbor --- .../slider-neighbor/silder-neighbor.we | 259 ++++-------------- 1 file changed, 58 insertions(+), 201 deletions(-) diff --git a/examples/component/slider-neighbor/silder-neighbor.we b/examples/component/slider-neighbor/silder-neighbor.we index 83e9f1595e..f908680374 100644 --- a/examples/component/slider-neighbor/silder-neighbor.we +++ b/examples/component/slider-neighbor/silder-neighbor.we @@ -1,206 +1,63 @@ + - - From 869da544bfc65201651db220800374c727ac7305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A4=E5=89=91?= Date: Fri, 16 Dec 2016 14:05:51 +0800 Subject: [PATCH 019/144] * [ios] fix : Change the parameter wording to make it more in line with development habits. --- .../Sources/Component/WXSliderComponent.m | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m index d96cfa2ca9..6ed9783643 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m @@ -293,8 +293,8 @@ @interface WXSliderComponent () @property (nonatomic, assign) BOOL autoPlay; @property (nonatomic, assign) NSUInteger interval; @property (nonatomic, assign) NSInteger index; -@property (nonatomic, assign) CGFloat lastXDeviationPercent; -@property (nonatomic, assign) CGFloat scrollAccuracy; +@property (nonatomic, assign) CGFloat lastoffsetXRatio; +@property (nonatomic, assign) CGFloat offsetXAccuracy; @property (nonatomic, assign) BOOL sliderChangeEvent; @property (nonatomic, assign) BOOL sliderScrollEvent; @property (nonatomic, strong) NSMutableArray *childrenView; @@ -315,7 +315,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _sliderScrollEvent = NO; _interval = 3000; _childrenView = [NSMutableArray new]; - _lastXDeviationPercent = 0; + _lastoffsetXRatio = 0; if (attributes[@"autoPlay"]) { _autoPlay = [attributes[@"autoPlay"] boolValue]; @@ -329,8 +329,8 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _index = [attributes[@"index"] integerValue]; } - if (attributes[@"xDeviationAccuracy"]) { - _scrollAccuracy = [WXConvert CGFloat:attributes[@"xDeviationAccuracy"]]; + if (attributes[@"offsetXAccuracy"]) { + _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]]; } self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW; @@ -458,8 +458,8 @@ - (void)updateAttributes:(NSDictionary *)attributes [_sliderView scroll2ItemView:self.currentIndex animated:YES]; } - if (attributes[@"xDeviationAccuracy"]) { - _scrollAccuracy = [WXConvert CGFloat:attributes[@"xDeviationAccuracy"]]; + if (attributes[@"offsetXAccuracy"]) { + _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]]; } } @@ -539,10 +539,10 @@ - (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView if (_sliderScrollEvent) { CGFloat width = scrollView.frame.size.width; CGFloat XDeviation = scrollView.frame.origin.x - (scrollView.contentOffset.x - width); - CGFloat XDeviationPercent = (XDeviation / width); - if (ABS(XDeviationPercent - _lastXDeviationPercent) >= _scrollAccuracy) { - _lastXDeviationPercent = XDeviationPercent; - [self fireEvent:@"scroll" params:@{@"XDeviationPercent":[NSNumber numberWithFloat:XDeviationPercent]} domChanges:nil]; + CGFloat offsetXRatio = (XDeviation / width); + if (ABS(offsetXRatio - _lastoffsetXRatio) >= _offsetXAccuracy) { + _lastoffsetXRatio = offsetXRatio; + [self fireEvent:@"scroll" params:@{@"offsetXRatio":[NSNumber numberWithFloat:offsetXRatio]} domChanges:nil]; } } } From 6bac71c78595efd43c4cc86b927137a7b30bf3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Fri, 16 Dec 2016 20:11:04 +0800 Subject: [PATCH 020/144] * [ios] feature: when jsfm send variable parameter , iOS will set the parameter the gain value and other parameter which not set with default value --- ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m index 1935d62872..e25b818cd5 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m @@ -97,7 +97,7 @@ - (NSInvocation*)invocationWithTargetMethod:(id)target method:(WXBridgeMethod*)m return nil; } - if (signature.numberOfArguments - 2 != method.arguments.count) { + if (signature.numberOfArguments - 2 < method.arguments.count) { NSString *errorMessage = [NSString stringWithFormat:@"%@, the parameters in calling method [%@] and registered method [%@] are not consistent!", method.targets[@"component"]?:method.module, method.method, NSStringFromSelector(selector)]; WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); return nil; From de8f24648b40e66300cd409d99493f45e3bf834e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A4=E5=89=91?= Date: Mon, 19 Dec 2016 15:22:22 +0800 Subject: [PATCH 021/144] * [ios] fix : Change the lastoffsetXRatio to lastOffsetXRatio --- ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m index 6ed9783643..9c267f55c9 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m @@ -293,7 +293,7 @@ @interface WXSliderComponent () @property (nonatomic, assign) BOOL autoPlay; @property (nonatomic, assign) NSUInteger interval; @property (nonatomic, assign) NSInteger index; -@property (nonatomic, assign) CGFloat lastoffsetXRatio; +@property (nonatomic, assign) CGFloat lastOffsetXRatio; @property (nonatomic, assign) CGFloat offsetXAccuracy; @property (nonatomic, assign) BOOL sliderChangeEvent; @property (nonatomic, assign) BOOL sliderScrollEvent; @@ -315,7 +315,7 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict _sliderScrollEvent = NO; _interval = 3000; _childrenView = [NSMutableArray new]; - _lastoffsetXRatio = 0; + _lastOffsetXRatio = 0; if (attributes[@"autoPlay"]) { _autoPlay = [attributes[@"autoPlay"] boolValue]; @@ -540,8 +540,8 @@ - (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView CGFloat width = scrollView.frame.size.width; CGFloat XDeviation = scrollView.frame.origin.x - (scrollView.contentOffset.x - width); CGFloat offsetXRatio = (XDeviation / width); - if (ABS(offsetXRatio - _lastoffsetXRatio) >= _offsetXAccuracy) { - _lastoffsetXRatio = offsetXRatio; + if (ABS(offsetXRatio - _lastOffsetXRatio) >= _offsetXAccuracy) { + _lastOffsetXRatio = offsetXRatio; [self fireEvent:@"scroll" params:@{@"offsetXRatio":[NSNumber numberWithFloat:offsetXRatio]} domChanges:nil]; } } From 40244c16fddf17727e0f24e0f33116ed2e9d986f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Mon, 19 Dec 2016 21:26:56 +0800 Subject: [PATCH 022/144] + [ios] add font weight for iOS weex sdk, use the font value not macro, because font weight macro is only enable in os version 8.2 --- ios/sdk/WeexSDK/Sources/Utility/WXConvert.m | 25 +++++++++-- ios/sdk/WeexSDK/Sources/Utility/WXType.h | 12 +++++- ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 46 +++++++++++++++++++-- 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index 4e27178ad6..e98ed8be3d 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -483,11 +483,30 @@ + (WXTextWeight)WXTextWeight:(id)value if([value isKindOfClass:[NSString class]]){ NSString *string = (NSString *)value; if ([string isEqualToString:@"normal"]) - return WXTextWeightNormal; + return WXFontWeightRegular; else if ([string isEqualToString:@"bold"]) - return WXTextWeightBold; + return WXFontWeightBold; + else if ([string isEqualToString:@"100"]) + return WXFontWeightUltraLight; + else if ([string isEqualToString:@"200"]) + return WXFontWeightThin; + else if ([string isEqualToString:@"300"]) + return WXFontWeightLight; + else if ([string isEqualToString:@"400"]) + return WXFontWeightRegular; + else if ([string isEqualToString:@"500"]) + return WXFontWeightMedium; + else if ([string isEqualToString:@"600"]) + return WXFontWeightSemibold; + else if ([string isEqualToString:@"700"]) + return WXFontWeightBold; + else if ([string isEqualToString:@"800"]) + return WXFontWeightHeavy; + else if ([string isEqualToString:@"900"]) + return WXFontWeightBlack; + } - return WXTextWeightNormal; + return WXFontWeightRegular; } + (WXTextDecoration)WXTextDecoration:(id)value diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXType.h b/ios/sdk/WeexSDK/Sources/Utility/WXType.h index 8043cc2369..14c31f2f07 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXType.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXType.h @@ -21,8 +21,16 @@ typedef NS_ENUM(NSUInteger, WXTextStyle) { }; typedef NS_ENUM(NSUInteger, WXTextWeight) { - WXTextWeightNormal = 0, - WXTextWeightBold, + WXFontWeightRegular = 0, + WXFontWeightUltraLight, + WXFontWeightThin, + WXFontWeightLight, + WXFontWeightMedium, + WXFontWeightSemibold, + WXFontWeightBold, + WXFontWeightHeavy, + WXFontWeightBlack + }; typedef NS_ENUM(NSInteger, WXTextDecoration) { diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index bac9288a63..b2e53b4c67 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -363,22 +363,23 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textS [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; } } + CGFloat weight = WXFontWeightRegular; + weight = [WXUtility textWeight:textWeight]; if (!font) { if (fontFamily) { font = [UIFont fontWithName:fontFamily size:fontSize]; if (!font) { WXLogWarning(@"Unknown fontFamily:%@", fontFamily); - font = [UIFont systemFontOfSize:fontSize]; + font = [UIFont systemFontOfSize:fontSize weight:weight]; } } else { - font = [UIFont systemFontOfSize:fontSize]; + font = [UIFont systemFontOfSize:fontSize weight:weight]; } } - UIFontDescriptor *fontD = font.fontDescriptor; UIFontDescriptorSymbolicTraits traits = 0; traits = (textStyle == WXTextStyleItalic) ? (traits | UIFontDescriptorTraitItalic) : traits; - traits = (textWeight == WXTextWeightBold) ? (traits | UIFontDescriptorTraitBold) : traits; + traits = (textWeight == WXFontWeightBold) ? (traits | UIFontDescriptorTraitBold) : traits; if (traits != 0) { fontD = [fontD fontDescriptorWithSymbolicTraits:traits]; UIFont *tempFont = [UIFont fontWithDescriptor:fontD size:0]; @@ -390,6 +391,43 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textS return font; } ++ (CGFloat )textWeight:(WXTextWeight)type +{ + CGFloat weight = WXFontWeightRegular; + switch (type) { + case WXFontWeightUltraLight: + weight = -0.8; + break; + case WXFontWeightThin: + weight = -0.6; + break; + case WXFontWeightLight: + weight = -0.4; + break; + case WXFontWeightRegular: + weight = 0; + break; + case WXFontWeightMedium: + weight = 0.23; + break; + case WXFontWeightSemibold: + weight = 0.3; + break; + case WXFontWeightBold: + weight = 0.4; + break; + case WXFontWeightHeavy: + weight = 0.56; + break; + case WXFontWeightBlack: + weight = 0.62; + break; + default: + break; + } + return weight; +} + + (void)getIconfont:(NSURL *)url completion:(void(^)(NSURL *url, NSError *error))completionBlock { if ([url isFileURL]) { From 03ab948bc7a7e8d5851ec7dd2016494431329122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Tue, 20 Dec 2016 19:49:06 +0800 Subject: [PATCH 023/144] * [ios] refactor module and component bridge method to be ready for supporting sync return values - Add category to support converting a NSInvocation's return value to JSValue - To be more clear for module and component method invoking, add WXModuleMethod and WXComponentMethod inheriting from WXBridgeMethod which are used separately. - Add WXCallJSMethod inheriting from WXBridgeMethod to be used for callJS - Move method dispatch logic from component/module manager to WXModuleMethod and WXComponentMethod --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 48 +++++-- ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h | 15 +++ ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m | 87 +++++++++++++ .../WeexSDK/Sources/Bridge/WXBridgeContext.h | 4 +- .../WeexSDK/Sources/Bridge/WXBridgeContext.m | 90 ++++++++----- .../WeexSDK/Sources/Bridge/WXCallJSMethod.h | 20 +++ .../WeexSDK/Sources/Bridge/WXCallJSMethod.m | 35 ++++++ .../Sources/Bridge/WXComponentMethod.h | 22 ++++ .../Sources/Bridge/WXComponentMethod.m | 53 ++++++++ .../WeexSDK/Sources/Bridge/WXJSCoreBridge.m | 21 +++- .../WeexSDK/Sources/Bridge/WXModuleMethod.h | 28 +++++ .../WeexSDK/Sources/Bridge/WXModuleMethod.m | 83 ++++++++++++ .../WeexSDK/Sources/Manager/WXBridgeManager.h | 14 +-- .../WeexSDK/Sources/Manager/WXBridgeManager.m | 40 +++--- .../Sources/Manager/WXComponentManager.h | 2 - .../Sources/Manager/WXComponentManager.m | 27 ---- .../Sources/Manager/WXInvocationConfig.h | 3 +- .../Sources/Manager/WXInvocationConfig.m | 81 ------------ .../WeexSDK/Sources/Manager/WXModuleManager.h | 16 --- .../WeexSDK/Sources/Manager/WXModuleManager.m | 111 ---------------- .../WeexSDK/Sources/Manager/WXSDKManager.h | 10 +- .../WeexSDK/Sources/Manager/WXSDKManager.m | 19 +-- .../WeexSDK/Sources/Model/WXBridgeMethod.h | 18 +-- .../WeexSDK/Sources/Model/WXBridgeMethod.m | 118 ++++++++++++++---- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 5 + ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h | 1 + .../Sources/Protocol/WXBridgeProtocol.h | 18 ++- ios/sdk/WeexSDK/Sources/WeexSDK.h | 1 + ios/sdk/WeexSDKTests/WXBridgeMethodTests.m | 24 ++-- ios/sdk/WeexSDKTests/WXSDKManagerTests.m | 10 -- 30 files changed, 639 insertions(+), 385 deletions(-) create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h create mode 100644 ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m delete mode 100644 ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h delete mode 100644 ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index fede7504d7..776a8e3c0d 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -127,6 +127,12 @@ 746A2F401DF808E6004719D0 /* WXLocationModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */; }; 747A787C1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h in Headers */ = {isa = PBXBuildFile; fileRef = 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */; }; 747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m in Sources */ = {isa = PBXBuildFile; fileRef = 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */; }; + 74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */ = {isa = PBXBuildFile; fileRef = 74862F771E02B88D00B7A041 /* JSValue+Weex.h */; }; + 74862F7A1E02B88D00B7A041 /* JSValue+Weex.m in Sources */ = {isa = PBXBuildFile; fileRef = 74862F781E02B88D00B7A041 /* JSValue+Weex.m */; }; + 74862F7D1E03A0F300B7A041 /* WXModuleMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 74862F7B1E03A0F300B7A041 /* WXModuleMethod.h */; }; + 74862F7E1E03A0F300B7A041 /* WXModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 74862F7C1E03A0F300B7A041 /* WXModuleMethod.m */; }; + 74862F811E03A24500B7A041 /* WXComponentMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 74862F7F1E03A24500B7A041 /* WXComponentMethod.h */; }; + 74862F821E03A24500B7A041 /* WXComponentMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 74862F801E03A24500B7A041 /* WXComponentMethod.m */; }; 74896F301D1AC79400D1D593 /* NSObject+WXSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */; }; 74896F311D1AC79400D1D593 /* NSObject+WXSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 74896F2F1D1AC79400D1D593 /* NSObject+WXSwizzle.m */; }; 748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 748B25161C44A6F9005D491E /* WXSDKInstance_private.h */; }; @@ -158,6 +164,8 @@ 74CC7A1D1C2BC5F800829368 /* WXCellComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CC7A1B1C2BC5F800829368 /* WXCellComponent.m */; }; 74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CC7A1E1C2BF9DC00829368 /* WXListComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; 74CC7A211C2BF9DC00829368 /* WXListComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CC7A1F1C2BF9DC00829368 /* WXListComponent.m */; }; + 74D205201E091B8000128F44 /* WXCallJSMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 74D2051E1E091B8000128F44 /* WXCallJSMethod.h */; }; + 74D205211E091B8000128F44 /* WXCallJSMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 74D2051F1E091B8000128F44 /* WXCallJSMethod.m */; }; 74EF31AA1DE58AE600667A07 /* WXURLRewriteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 74EF31A91DE58AE600667A07 /* WXURLRewriteProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 74EF31AD1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 74EF31AB1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h */; }; 74EF31AE1DE58BE200667A07 /* WXURLRewriteDefaultImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 74EF31AC1DE58BE200667A07 /* WXURLRewriteDefaultImpl.m */; }; @@ -194,8 +202,6 @@ 77E659F21C0C3612008B8775 /* WXModuleFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E659F01C0C3612008B8775 /* WXModuleFactory.m */; }; 77E659FA1C0EE579008B8775 /* WXBridgeMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E659F81C0EE579008B8775 /* WXBridgeMethod.h */; }; 77E659FB1C0EE579008B8775 /* WXBridgeMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E659F91C0EE579008B8775 /* WXBridgeMethod.m */; }; - 77E65A061C10507B008B8775 /* WXModuleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E65A041C10507B008B8775 /* WXModuleManager.h */; }; - 77E65A071C10507B008B8775 /* WXModuleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E65A051C10507B008B8775 /* WXModuleManager.m */; }; 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E65A0B1C155E99008B8775 /* WXDivComponent.h */; }; 77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E65A0C1C155E99008B8775 /* WXDivComponent.m */; }; 77E65A111C155EA8008B8775 /* WXImageComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E65A0F1C155EA8008B8775 /* WXImageComponent.h */; }; @@ -385,6 +391,12 @@ 746A2F3E1DF808E6004719D0 /* WXLocationModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXLocationModule.m; sourceTree = ""; }; 747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+ViewManagement.h"; sourceTree = ""; }; 747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+ViewManagement.m"; sourceTree = ""; }; + 74862F771E02B88D00B7A041 /* JSValue+Weex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JSValue+Weex.h"; sourceTree = ""; }; + 74862F781E02B88D00B7A041 /* JSValue+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JSValue+Weex.m"; sourceTree = ""; }; + 74862F7B1E03A0F300B7A041 /* WXModuleMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXModuleMethod.h; sourceTree = ""; }; + 74862F7C1E03A0F300B7A041 /* WXModuleMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXModuleMethod.m; sourceTree = ""; }; + 74862F7F1E03A24500B7A041 /* WXComponentMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXComponentMethod.h; sourceTree = ""; }; + 74862F801E03A24500B7A041 /* WXComponentMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXComponentMethod.m; sourceTree = ""; }; 74896F2E1D1AC79400D1D593 /* NSObject+WXSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+WXSwizzle.h"; sourceTree = ""; }; 74896F2F1D1AC79400D1D593 /* NSObject+WXSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+WXSwizzle.m"; sourceTree = ""; }; 748B25161C44A6F9005D491E /* WXSDKInstance_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXSDKInstance_private.h; sourceTree = ""; }; @@ -418,6 +430,8 @@ 74CC7A1B1C2BC5F800829368 /* WXCellComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCellComponent.m; sourceTree = ""; }; 74CC7A1E1C2BF9DC00829368 /* WXListComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXListComponent.h; sourceTree = ""; }; 74CC7A1F1C2BF9DC00829368 /* WXListComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXListComponent.m; sourceTree = ""; }; + 74D2051E1E091B8000128F44 /* WXCallJSMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXCallJSMethod.h; sourceTree = ""; }; + 74D2051F1E091B8000128F44 /* WXCallJSMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCallJSMethod.m; sourceTree = ""; }; 74EF31A91DE58AE600667A07 /* WXURLRewriteProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXURLRewriteProtocol.h; sourceTree = ""; }; 74EF31AB1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXURLRewriteDefaultImpl.h; sourceTree = ""; }; 74EF31AC1DE58BE200667A07 /* WXURLRewriteDefaultImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXURLRewriteDefaultImpl.m; sourceTree = ""; }; @@ -454,10 +468,8 @@ 77E659D91C07F594008B8775 /* WXDomModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDomModule.m; sourceTree = ""; }; 77E659EF1C0C3612008B8775 /* WXModuleFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXModuleFactory.h; sourceTree = ""; }; 77E659F01C0C3612008B8775 /* WXModuleFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXModuleFactory.m; sourceTree = ""; }; - 77E659F81C0EE579008B8775 /* WXBridgeMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXBridgeMethod.h; sourceTree = ""; }; - 77E659F91C0EE579008B8775 /* WXBridgeMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXBridgeMethod.m; sourceTree = ""; }; - 77E65A041C10507B008B8775 /* WXModuleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXModuleManager.h; sourceTree = ""; }; - 77E65A051C10507B008B8775 /* WXModuleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXModuleManager.m; sourceTree = ""; }; + 77E659F81C0EE579008B8775 /* WXBridgeMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXBridgeMethod.h; path = ../Model/WXBridgeMethod.h; sourceTree = ""; }; + 77E659F91C0EE579008B8775 /* WXBridgeMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXBridgeMethod.m; path = ../Model/WXBridgeMethod.m; sourceTree = ""; }; 77E65A0B1C155E99008B8775 /* WXDivComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDivComponent.h; sourceTree = ""; }; 77E65A0C1C155E99008B8775 /* WXDivComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDivComponent.m; sourceTree = ""; }; 77E65A0F1C155EA8008B8775 /* WXImageComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXImageComponent.h; sourceTree = ""; }; @@ -785,6 +797,14 @@ 77D161191C02DD3C0010B15B /* Bridge */ = { isa = PBXGroup; children = ( + 77E659F81C0EE579008B8775 /* WXBridgeMethod.h */, + 77E659F91C0EE579008B8775 /* WXBridgeMethod.m */, + 74862F7B1E03A0F300B7A041 /* WXModuleMethod.h */, + 74862F7C1E03A0F300B7A041 /* WXModuleMethod.m */, + 74862F7F1E03A24500B7A041 /* WXComponentMethod.h */, + 74862F801E03A24500B7A041 /* WXComponentMethod.m */, + 74D2051E1E091B8000128F44 /* WXCallJSMethod.h */, + 74D2051F1E091B8000128F44 /* WXCallJSMethod.m */, 59597F961D2A041700EE9317 /* WXDebugLoggerBridge.h */, 59597F971D2A041700EE9317 /* WXDebugLoggerBridge.m */, 59A582FA1CF5B17B0081FD3E /* WXBridgeContext.h */, @@ -793,6 +813,8 @@ 77D1613B1C02DEA60010B15B /* WXJSCoreBridge.m */, 74AD99821D5B0E59008F0336 /* WXPolyfillSet.h */, 74AD99831D5B0E59008F0336 /* WXPolyfillSet.m */, + 74862F771E02B88D00B7A041 /* JSValue+Weex.h */, + 74862F781E02B88D00B7A041 /* JSValue+Weex.m */, ); path = Bridge; sourceTree = ""; @@ -808,8 +830,6 @@ 77D161271C02DE1A0010B15B /* WXSDKManager.m */, 77D161361C02DE940010B15B /* WXBridgeManager.h */, 77D161371C02DE940010B15B /* WXBridgeManager.m */, - 77E65A041C10507B008B8775 /* WXModuleManager.h */, - 77E65A051C10507B008B8775 /* WXModuleManager.m */, 77E659EF1C0C3612008B8775 /* WXModuleFactory.h */, 77E659F01C0C3612008B8775 /* WXModuleFactory.m */, 74A4BA9C1CB3C0A100195969 /* WXHandlerFactory.h */, @@ -832,8 +852,6 @@ 748B25161C44A6F9005D491E /* WXSDKInstance_private.h */, 77D161221C02DDD10010B15B /* WXSDKInstance.h */, 77D161231C02DDD10010B15B /* WXSDKInstance.m */, - 77E659F81C0EE579008B8775 /* WXBridgeMethod.h */, - 77E659F91C0EE579008B8775 /* WXBridgeMethod.m */, ); path = Model; sourceTree = ""; @@ -1033,6 +1051,7 @@ 2AE5B7521CAB7DBD0082FDDB /* WXAComponent.h in Headers */, 77D1614F1C02E3880010B15B /* WXUtility.h in Headers */, 743933B41C7ED9AA00773BB7 /* WXSimulatorShortcutMananger.h in Headers */, + 74862F811E03A24500B7A041 /* WXComponentMethod.h in Headers */, 74915F471C8EB02B00BEBCC0 /* WXAssert.h in Headers */, 2A8E658A1C7C7AA20025C7B7 /* WXVideoComponent.h in Headers */, 59A5961C1CB630F10012CD52 /* WXComponent+Navigation.h in Headers */, @@ -1048,7 +1067,6 @@ 74A4BA5B1CABBBD000195969 /* WXDebugTool.h in Headers */, 2A837AB41CD9DE9200AEDF03 /* WXLoadingIndicator.h in Headers */, 747A787C1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h in Headers */, - 77E65A061C10507B008B8775 /* WXModuleManager.h in Headers */, DC0F99311D48E5320087C6AF /* WeexSDK.h in Headers */, 77E659FA1C0EE579008B8775 /* WXBridgeMethod.h in Headers */, 2AE5B7561CABA04E0082FDDB /* WXEventModuleProtocol.h in Headers */, @@ -1067,6 +1085,7 @@ 749DC27B1D40827B009E1C91 /* WXMonitor.h in Headers */, 77E659DA1C07F594008B8775 /* WXDomModule.h in Headers */, 74EF31AD1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h in Headers */, + 74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */, 2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */, 74A4BA9A1CB3BAA100195969 /* WXThreadSafeMutableDictionary.h in Headers */, 74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h in Headers */, @@ -1087,6 +1106,7 @@ 2AC750241C7565690041D390 /* WXIndicatorComponent.h in Headers */, DCAB35FE1D658EB700C0EA70 /* WXRuleManager.h in Headers */, 748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */, + 74862F7D1E03A0F300B7A041 /* WXModuleMethod.h in Headers */, 742AD7331DF98C45007DC46C /* WXResourceResponse.h in Headers */, 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */, C41E1A971DC1FD15009C7F90 /* WXDatePickerManager.h in Headers */, @@ -1116,6 +1136,7 @@ 2A4445BF1CA8FD56009E7C6D /* WXTextComponentProtocol.h in Headers */, 746319021C60AFC100EFEBD4 /* WXThreadSafeCounter.h in Headers */, 77D1613C1C02DEA60010B15B /* WXJSCoreBridge.h in Headers */, + 74D205201E091B8000128F44 /* WXCallJSMethod.h in Headers */, 741DFE061DDD9B30009B020F /* UIBezierPath+Weex.h in Headers */, 2AAFC1B61C48DFF70026D2FE /* WXSDKError.h in Headers */, 742AD72E1DF98C45007DC46C /* WXResourceRequest.h in Headers */, @@ -1319,7 +1340,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 77E65A071C10507B008B8775 /* WXModuleManager.m in Sources */, 77D161291C02DE1A0010B15B /* WXSDKManager.m in Sources */, 7461F8911CFB373100F62D44 /* WXDisplayQueue.m in Sources */, 74896F311D1AC79400D1D593 /* NSObject+WXSwizzle.m in Sources */, @@ -1336,6 +1356,7 @@ 59D3CA401CF9ED57008835DC /* Layout.c in Sources */, DCF087621DCAE161005CD6EB /* WXInvocationConfig.m in Sources */, 77D161311C02DE4E0010B15B /* WXComponent.m in Sources */, + 74862F7A1E02B88D00B7A041 /* JSValue+Weex.m in Sources */, 77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */, D3FC0DF81C508B2A002B9E31 /* WXTimerModule.m in Sources */, 594C28921CF9E61A009793A4 /* WXAnimationModule.m in Sources */, @@ -1357,6 +1378,7 @@ 59A596321CB632050012CD52 /* WXRootViewController.m in Sources */, DCC77C131D770AE300CE7288 /* WXSliderNeighborComponent.m in Sources */, 2A8E658B1C7C7AA20025C7B7 /* WXVideoComponent.m in Sources */, + 74862F7E1E03A0F300B7A041 /* WXModuleMethod.m in Sources */, 742AD7341DF98C45007DC46C /* WXResourceResponse.m in Sources */, 77E65A161C155EB5008B8775 /* WXTextComponent.m in Sources */, 746319031C60AFC100EFEBD4 /* WXThreadSafeCounter.m in Sources */, @@ -1378,6 +1400,7 @@ D362F9501C83EDA20003F546 /* WXWebViewModule.m in Sources */, 2A1F57B81C75C6A600B58017 /* WXTextInputComponent.m in Sources */, 74CC7A1D1C2BC5F800829368 /* WXCellComponent.m in Sources */, + 74862F821E03A24500B7A041 /* WXComponentMethod.m in Sources */, 77E65A121C155EA8008B8775 /* WXImageComponent.m in Sources */, 2A837AB31CD9DE9200AEDF03 /* WXLoadingComponent.m in Sources */, 2AE5B7531CAB7DBD0082FDDB /* WXAComponent.m in Sources */, @@ -1400,6 +1423,7 @@ 74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */, 742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */, 7461F8931CFB373100F62D44 /* WXLayer.m in Sources */, + 74D205211E091B8000128F44 /* WXCallJSMethod.m in Sources */, 59D3CA471CFC3CC0008835DC /* WXSliderComponent.m in Sources */, 77D1613D1C02DEA60010B15B /* WXJSCoreBridge.m in Sources */, C41E1A981DC1FD15009C7F90 /* WXDatePickerManager.m in Sources */, diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h new file mode 100644 index 0000000000..942b0c9923 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h @@ -0,0 +1,15 @@ +// +// JSValue+Weex.h +// WeexSDK +// +// Created by yinfeng on 2016/12/15. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import + +@interface JSValue (Weex) + ++ (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m new file mode 100644 index 0000000000..5734434e80 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m @@ -0,0 +1,87 @@ +// +// JSValue+Weex.m +// WeexSDK +// +// Created by yinfeng on 2016/12/15. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "JSValue+Weex.h" +#import + +@implementation JSValue (Weex) + ++ (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context +{ + char returnType[255]; + strcpy(returnType, [invocation.methodSignature methodReturnType]); + + JSValue *returnValue; + switch (returnType[0] == _C_CONST ? returnType[1] : returnType[0]) { + case _C_VOID: { + // 1.void + returnValue = nil; + break; + } + + case _C_ID: { + // 2.id + id result; + [invocation getReturnValue:&result]; + returnValue = [JSValue valueWithObject:result inContext:context]; + break; + } + +#define WX_JS_VALUE_RET_CASE(typeString, type) \ + case typeString: { \ + type value; \ + [invocation getReturnValue:&value]; \ + returnValue = [JSValue valueWithObject:@(value) inContext:context]; \ + break; \ + } + // 3.number + WX_JS_VALUE_RET_CASE(_C_CHR, char) + WX_JS_VALUE_RET_CASE(_C_UCHR, unsigned char) + WX_JS_VALUE_RET_CASE(_C_SHT, short) + WX_JS_VALUE_RET_CASE(_C_USHT, unsigned short) + WX_JS_VALUE_RET_CASE(_C_INT, int) + WX_JS_VALUE_RET_CASE(_C_UINT, unsigned int) + WX_JS_VALUE_RET_CASE(_C_LNG, long) + WX_JS_VALUE_RET_CASE(_C_ULNG, unsigned long) + WX_JS_VALUE_RET_CASE(_C_LNG_LNG, long long) + WX_JS_VALUE_RET_CASE(_C_ULNG_LNG, unsigned long long) + WX_JS_VALUE_RET_CASE(_C_FLT, float) + WX_JS_VALUE_RET_CASE(_C_DBL, double) + WX_JS_VALUE_RET_CASE(_C_BOOL, BOOL) + + case _C_STRUCT_B: { + NSString *typeString = [NSString stringWithUTF8String:returnType]; + +#define WX_JS_VALUE_RET_STRUCT(_type, _methodName) \ + if ([typeString rangeOfString:@#_type].location != NSNotFound) { \ + _type value; \ + [invocation getReturnValue:&value]; \ + returnValue = [JSValue _methodName:value inContext:context]; \ + break; \ + } + // 4.struct + WX_JS_VALUE_RET_STRUCT(CGRect, valueWithRect) + WX_JS_VALUE_RET_STRUCT(CGPoint, valueWithPoint) + WX_JS_VALUE_RET_STRUCT(CGSize, valueWithSize) + WX_JS_VALUE_RET_STRUCT(NSRange, valueWithRange) + + } + case _C_CHARPTR: + case _C_PTR: + case _C_CLASS: { + returnValue = nil; + break; + } + } + + return returnValue; +} + + + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h index 4388bdf13e..e8782d30a8 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h @@ -8,7 +8,7 @@ #import -@class WXBridgeMethod; +@class WXCallJSMethod; @class WXSDKInstance; @interface WXBridgeContext : NSObject @@ -62,7 +62,7 @@ * Execute JS Method * @param method : object of bridge method **/ -- (void)executeJsMethod:(WXBridgeMethod *)method; +- (void)executeJsMethod:(WXCallJSMethod *)method; /** * Register Modules Method * @param modules : module list diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m index 79e22f39f0..31618c5a74 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m @@ -12,7 +12,6 @@ #import "WXDebugLoggerBridge.h" #import "WXLog.h" #import "WXUtility.h" -#import "WXBridgeMethod.h" #import "WXModuleFactory.h" #import "WXModuleProtocol.h" #import "WXUtility.h" @@ -21,11 +20,14 @@ #import "WXAssert.h" #import "WXSDKManager.h" #import "WXDebugTool.h" -#import "WXModuleManager.h" #import "WXSDKInstance_private.h" #import "WXThreadSafeMutableArray.h" #import "WXAppConfiguration.h" #import "WXInvocationConfig.h" +#import "WXComponentMethod.h" +#import "WXModuleMethod.h" +#import "WXCallJSMethod.h" +#import "WXSDKInstance_private.h" #define SuppressPerformSelectorLeakWarning(Stuff) \ do { \ @@ -80,12 +82,20 @@ - (instancetype) init } _jsBridge = _debugJS ? [NSClassFromString(@"WXDebugger") alloc] : [[WXJSCoreBridge alloc] init]; - __weak typeof(self) weakSelf = self; + + [self registerGlobalFuntions]; + + return _jsBridge; +} + +- (void)registerGlobalFuntions +{ + __weak typeof(self) weakSelf = self; [_jsBridge registerCallNative:^NSInteger(NSString *instance, NSArray *tasks, NSString *callback) { return [weakSelf invokeNative:instance tasks:tasks callback:callback]; }]; [_jsBridge registerCallAddElement:^NSInteger(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index) { - + // Temporary here , in order to improve performance, will be refactored next version. WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; @@ -106,7 +116,21 @@ - (instancetype) init return 0; }]; - return _jsBridge; + [_jsBridge registerCallNativeModule:^id(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options) { + + WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; + + if (!instance) { + WXLogInfo(@"instance not found for callNativeModule:%@.%@, maybe already destroyed", moduleName, methodName); + return nil; + } + + return nil; + }]; + + [_jsBridge registerCallNativeComponent:^id(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) { + return nil; + }]; } - (NSMutableArray *)insStack @@ -141,24 +165,34 @@ - (NSMutableDictionary *)sendQueue #pragma mark JS Bridge Management -- (NSInteger)invokeNative:(NSString *)instance tasks:(NSArray *)tasks callback:(NSString __unused*)callback +- (NSInteger)invokeNative:(NSString *)instanceId tasks:(NSArray *)tasks callback:(NSString __unused*)callback { WXAssertBridgeThread(); - if (!instance || !tasks) { + if (!instanceId || !tasks) { WX_MONITOR_FAIL(WXMTNativeRender, WX_ERR_JSFUNC_PARAM, @"JS call Native params error!"); return 0; } - if (![WXSDKManager instanceForID:instance]) { - WXLogInfo(@"instance already destroyed"); + WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; + if (!instance) { + WXLogInfo(@"instance already destroyed, task ignored"); return -1; } for (NSDictionary *task in tasks) { - WXBridgeMethod *method = [[WXBridgeMethod alloc] initWihData:task]; - method.instance = instance; - [[WXInvocationConfig sharedInstance] dispatchMethod:method]; + NSString *methodName = task[@"method"]; + NSArray *arguments = task[@"args"]; + if (task[@"component"]) { + NSString *componentName = task[@"component"]; + NSString *ref = task[@"ref"]; + WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentName:componentName componentRef:ref methodName:methodName arguments:arguments instance:instance]; + [method invoke]; + } else { + NSString *moduleName = task[@"module"]; + WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:arguments instance:instance]; + [method invoke]; + } } [self performSelector:@selector(_sendQueueLoop) withObject:nil]; @@ -271,7 +305,7 @@ - (void)executeJsFramework:(NSString *)script }; } -- (void)executeJsMethod:(WXBridgeMethod *)method +- (void)executeJsMethod:(WXCallJSMethod *)method { WXAssertBridgeThread(); @@ -280,9 +314,9 @@ - (void)executeJsMethod:(WXBridgeMethod *)method return; } - NSMutableArray *sendQueue = self.sendQueue[method.instance]; + NSMutableArray *sendQueue = self.sendQueue[method.instance.instanceId]; if (!sendQueue) { - WXLogInfo(@"No send queue for instance:%@, may it has been destroyed so method:%@ is ignored", method.instance, method.method); + WXLogInfo(@"No send queue for instance:%@, may it has been destroyed so method:%@ is ignored", method.instance, method.methodName); return; } @@ -312,8 +346,7 @@ - (void)callJSMethod:(NSString *)method args:(NSArray *)args { if (self.frameworkLoadFinished) { [self.jsBridge callJSMethod:method args:args]; - } - else { + } else { [_methodQueue addObject:@{@"method":method, @"args":args}]; } } @@ -349,40 +382,30 @@ - (void)logToWebSocket:(NSString *)flag message:(NSString *)message #pragma mark Private Mehtods -- (WXBridgeMethod *)_methodWithCallback:(NSString *)callback -{ - WXAssertBridgeThread(); - - if (!callback) return nil; - - NSDictionary *method = @{@"module":@"jsBridge", @"method":@"callback", @"args":@[callback]}; - - return [[WXBridgeMethod alloc] initWihData:method]; -} - - (void)_sendQueueLoop { WXAssertBridgeThread(); BOOL hasTask = NO; - NSMutableArray *methods = [NSMutableArray array]; + NSMutableArray *tasks = [NSMutableArray array]; NSString *execIns = nil; for (NSString *instance in self.insStack) { NSMutableArray *sendQueue = self.sendQueue[instance]; if(sendQueue.count > 0){ hasTask = YES; - for(WXBridgeMethod *method in sendQueue){ - [methods addObject:[method dataDesc]]; + for(WXCallJSMethod *method in sendQueue){ + [tasks addObject:[method callJSTask]]; } + [sendQueue removeAllObjects]; execIns = instance; break; } } - if ([methods count] > 0 && execIns) { - [self callJSMethod:@"callJS" args:@[execIns, methods]]; + if ([tasks count] > 0 && execIns) { + [self callJSMethod:@"callJS" args:@[execIns, tasks]]; } if (hasTask) { @@ -390,4 +413,5 @@ - (void)_sendQueueLoop } } + @end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h new file mode 100644 index 0000000000..3eebe62d0c --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h @@ -0,0 +1,20 @@ +// +// WXCallJSMethod.h +// WeexSDK +// +// Created by yinfeng on 2016/12/20. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXBridgeMethod.h" + +@interface WXCallJSMethod : WXBridgeMethod + +- (instancetype)initWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance; + +- (NSDictionary *)callJSTask; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m new file mode 100644 index 0000000000..a0e3208cd6 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m @@ -0,0 +1,35 @@ +// +// WXCallJSMethod.m +// WeexSDK +// +// Created by yinfeng on 2016/12/20. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXCallJSMethod.h" + +@implementation WXCallJSMethod +{ + NSString *_moduleName; +} + +- (instancetype)initWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance +{ + if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) { + _moduleName = moduleName; + } + + return self; +} + +- (NSDictionary *)callJSTask +{ + return @{@"module":_moduleName ?: @"", + @"method":self.methodName ?: @"", + @"args":self.arguments ?: @[]}; +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h new file mode 100644 index 0000000000..9bb205377a --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h @@ -0,0 +1,22 @@ +// +// WXComponentMethod.h +// WeexSDK +// +// Created by yinfeng on 2016/12/16. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXBridgeMethod.h" +@class WXComponent; + +@interface WXComponentMethod : WXBridgeMethod + +- (instancetype)initWithComponentName:(NSString *)componentName + componentRef:(NSString *)ref + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance; + +- (void)invoke; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m new file mode 100644 index 0000000000..c832267025 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m @@ -0,0 +1,53 @@ +// +// WXComponentMethod.m +// WeexSDK +// +// Created by yinfeng on 2016/12/16. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXComponentMethod.h" +#import "WXComponentFactory.h" +#import "WXComponentManager.h" +#import "WXSDKInstance.h" +#import "WXLog.h" +#import "WXUtility.h" + +@implementation WXComponentMethod +{ + NSString *_componentName; + NSString *_componentRef; +} + +- (instancetype)initWithComponentName:(NSString *)componentName + componentRef:(NSString *)ref + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance +{ + if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) { + _componentName = componentName; + _componentRef = ref; + } + + return self; +} + +- (void)invoke +{ + WXPerformBlockOnComponentThread(^{ + WXComponent *component = [self.instance componentForRef:_componentRef]; + if (!component) { + WXLogError(@"component not found for ref:%@, type:%@", _componentRef, _componentName); + } + SEL selector = [WXComponentFactory methodWithComponentName:_componentName withMethod:self.methodName]; + NSInvocation * invocation = [self invocationWithTarget:component selector:selector]; + WXPerformBlockOnMainThread(^{ + [invocation invoke]; + }); + }); + + +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m index d1c6551acf..ad1d5142af 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m @@ -143,7 +143,6 @@ - (void)registerCallAddElement:(WXJSCallAddElement)callAddElement { id callAddElementBlock = ^(JSValue *instanceId, JSValue *ref, JSValue *element, JSValue *index, JSValue *ifCallback) { - // Temporary here , in order to improve performance, will be refactored next version. NSString *instanceIdString = [instanceId toString]; NSDictionary *componentData = [element toDictionary]; NSString *parentRef = [ref toString]; @@ -157,6 +156,26 @@ - (void)registerCallAddElement:(WXJSCallAddElement)callAddElement _jsContext[@"callAddElement"] = callAddElementBlock; } +- (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock +{ + _jsContext[@"callNativeModule"] = ^JSValue *(JSValue *instanceId, JSValue *moduleName, JSValue *methodName, JSValue *args, JSValue *options) { + NSString *instanceIdString = [instanceId toString]; + NSString *moduleNameString = [moduleName toString]; + NSString *methodNameString = [methodName toString]; + NSArray *argsArray = [args toArray]; + NSDictionary *optionsDic = [options toDictionary]; + + WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, moduleNameString, methodNameString, argsArray); + + return callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic); + }; +} + +- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock +{ + +} + - (JSValue*)exception { return _jsContext.exception; diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h new file mode 100644 index 0000000000..9c25182fb5 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h @@ -0,0 +1,28 @@ +// +// WXModuleMethod.h +// WeexSDK +// +// Created by yinfeng on 2016/12/16. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXBridgeMethod.h" + +typedef enum : NSUInteger { + WXModuleMethodTypeSync, + WXModuleMethodTypeAsync, +} WXModuleMethodType; + +@interface WXModuleMethod : WXBridgeMethod + +@property (nonatomic, assign) WXModuleMethodType methodType; +@property (nonatomic, strong, readonly) NSString *moduleName; + +- (instancetype)initWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance; + +- (NSInvocation *)invoke; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m new file mode 100644 index 0000000000..6a87bcf6f6 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m @@ -0,0 +1,83 @@ +// +// WXModuleMethod.m +// WeexSDK +// +// Created by yinfeng on 2016/12/16. +// Copyright © 2016年 taobao. All rights reserved. +// + +#import "WXModuleMethod.h" +#import "WXModuleFactory.h" +#import "WXMonitor.h" +#import "WXModuleProtocol.h" +#import "WXAssert.h" +#import "WXUtility.h" + +@implementation WXModuleMethod + +- (instancetype)initWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance +{ + if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) { + _moduleName = moduleName; + } + + return self; +} + +- (NSInvocation *)invoke +{ + Class moduleClass = [WXModuleFactory classWithModuleName:_moduleName]; + if (!moduleClass) { + NSString *errorMessage = [NSString stringWithFormat:@"Module:%@ doesn't exist, maybe it has not been registered", _moduleName]; + WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); + return nil; + } + + id moduleInstance = [self.instance moduleForClass:moduleClass]; + WXAssert(moduleInstance, @"No instance found for module name:%@, class:%@", _moduleName, moduleClass); + SEL selector = [WXModuleFactory methodWithModuleName:self.moduleName withMethod:self.methodName]; + if (!selector) { + NSString *errorMessage = [NSString stringWithFormat:@"method:%@ for module:%@ doesn't exist, maybe it has not been registered", self.methodName, _moduleName]; + WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); + return nil;; + } + + NSInvocation *invocation = [self invocationWithTarget:moduleInstance selector:selector]; + + [self _dispatchInvovation:invocation moduleInstance:moduleInstance]; + + return nil; +} + +- (void)_dispatchInvovation:(NSInvocation *)invocation moduleInstance:(id)moduleInstance +{ + // dispatch to user specified queue or thread, default is main thread + dispatch_block_t dipatchBlock = ^ (){ + [invocation invoke]; + }; + + NSThread *targetThread = nil; + dispatch_queue_t targetQueue = nil; + if([moduleInstance respondsToSelector:@selector(targetExecuteQueue)]){ + targetQueue = [moduleInstance targetExecuteQueue] ?: dispatch_get_main_queue(); + } else if([moduleInstance respondsToSelector:@selector(targetExecuteThread)]){ + targetThread = [moduleInstance targetExecuteThread] ?: [NSThread mainThread]; + } else { + targetThread = [NSThread mainThread]; + } + + WXAssert(targetQueue || targetThread, @"No queue or thread found for module:%@", moduleInstance); + + if (targetQueue) { + dispatch_async(targetQueue, dipatchBlock); + } else { + WXPerformBlockOnThread(^{ + dipatchBlock(); + }, targetThread); + } +} + +@end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h index 8576d355f7..589bd891df 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h @@ -67,12 +67,6 @@ **/ - (void)executeJsFramework:(NSString *)script; -/** - * Execute JS Method - * @param method : object of bridge method - **/ -- (void)executeJsMethod:(WXBridgeMethod *)method; - /** * Register Modules Method * @param modules : module list @@ -85,8 +79,6 @@ **/ - (void)registerComponents:(NSArray* )components; -- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params DEPRECATED_MSG_ATTRIBUTE("Use fireEvent:ref:type:params:domChanges: method instead."); - /** * FireEvent * @param instanceId: instance id @@ -139,4 +131,10 @@ **/ - (void)resetEnvironment; + +- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params DEPRECATED_MSG_ATTRIBUTE("Use fireEvent:ref:type:params:domChanges: method instead."); + +- (void)executeJsMethod:(WXBridgeMethod *)method DEPRECATED_MSG_ATTRIBUTE(); + + @end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m index 6fb2ac0242..f1ffd3fbc0 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m @@ -11,6 +11,8 @@ #import "WXLog.h" #import "WXAssert.h" #import "WXBridgeMethod.h" +#import "WXCallJSMethod.h" +#import "WXSDKManager.h" @interface WXBridgeManager () @@ -188,7 +190,7 @@ - (void)executeJsFramework:(NSString *)script }); } -- (void)executeJsMethod:(WXBridgeMethod *)method +- (void)callJsMethod:(WXCallJSMethod *)method { if (!method) return; @@ -231,28 +233,24 @@ - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)ty } NSArray *args = @[ref, type, params?:@{}, domChanges?:@{}]; - NSMutableDictionary *methodDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: - @"fireEvent", @"method", - args, @"args", nil]; - WXBridgeMethod *method = [[WXBridgeMethod alloc] initWithInstance:instanceId data:methodDict]; - [self executeJsMethod:method]; + WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; + + WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance]; + [self callJsMethod:method]; } -- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)params keepAlive:(BOOL)keepAlive { +- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)params keepAlive:(BOOL)keepAlive +{ NSArray *args = nil; if (keepAlive) { args = @[[funcId copy], params? [params copy]:@"\"{}\"", @true]; }else { args = @[[funcId copy], params? [params copy]:@"\"{}\""]; } - NSMutableDictionary *methodDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: - @"callback", @"method", - @"jsBridge",@"module", - args, @"args", nil]; - - WXBridgeMethod *method = [[WXBridgeMethod alloc] initWithInstance:instanceId data:methodDict]; - - [self executeJsMethod:method]; + WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; + + 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 @@ -290,4 +288,16 @@ - (void)resetEnvironment }); } +#pragma mark - Deprecated + +- (void)executeJsMethod:(WXCallJSMethod *)method +{ + if (!method) return; + + __weak typeof(self) weakSelf = self; + WXPerformBlockOnBridgeThread(^(){ + [weakSelf.bridgeCtx executeJsMethod:method]; + }); +} + @end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h index 1afb054206..ba3b0d7f65 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h @@ -107,8 +107,6 @@ extern void WXPerformBlockOnComponentThread(void (^block)()); **/ - (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options; -- (void)dispatchComponentMethod:(WXBridgeMethod*)method; - ///-------------------------------------- /// @name Life Cycle ///-------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m index 804e06ebc8..0e2978cf43 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m @@ -419,33 +419,6 @@ - (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options }]; } -- (void)dispatchComponentMethod:(WXBridgeMethod *)method -{ - if (!method) { - return; - } - Class componentClazz = [WXComponentFactory classWithComponentName:method.targets[@"component"]]; - if (!componentClazz) { - NSString *errorMessage = [NSString stringWithFormat:@"Module:%@ doesn't exist!", method.module]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - return; - } - WXPerformBlockOnComponentThread(^{ - WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance]; - WXComponent *componentInstance = [weexInstance componentForRef:method.targets[@"ref"]]; - - [self _executeComponentMethod:componentInstance withMethod:method]; - }); -} - -- (void)_executeComponentMethod:(id)target withMethod:(WXBridgeMethod*)method -{ - NSInvocation * invocation = [[WXInvocationConfig sharedInstance] invocationWithTargetMethod:target method:method]; - WXPerformBlockOnMainThread(^{ - [invocation invoke]; - }); -} - #pragma mark Life Cycle - (void)createFinish diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h index 82d68a8937..6d5db6062c 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h @@ -22,6 +22,5 @@ + (instancetype)sharedInstance; - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz; - (void)registerMethods; -- (void)dispatchMethod:(WXBridgeMethod*)method; -- (NSInvocation*)invocationWithTargetMethod:(id)target method:(WXBridgeMethod*)method; + @end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m index 1935d62872..71b90112ab 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m @@ -11,7 +11,6 @@ #import "WXSDKInstance.h" #import "WXSDKManager.h" #import "WXSDKInstance_private.h" -#import "WXModuleManager.h" #import "WXMonitor.h" #import "WXSDKError.h" #import "WXComponentFactory.h" @@ -56,86 +55,6 @@ - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz return self; } -- (void)dispatchMethod:(WXBridgeMethod *)method -{ - if(method.targets) { - WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance]; - [[weexInstance componentManager] dispatchComponentMethod:method]; - } - if (method.module) { - [[WXSDKManager moduleMgr] dispatchMethod:method]; - } -} - -- (NSInvocation*)invocationWithTargetMethod:(id)target method:(WXBridgeMethod*)method -{ - if (!target) { - NSString *errorMessage = [NSString stringWithFormat:@"%@ doesn't exist!",method.targets[@"component"]?:method.module]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - - return nil; - } - SEL selector = nil; - if ([target conformsToProtocol:NSProtocolFromString(@"WXModuleProtocol")]) { - selector = [WXModuleFactory methodWithModuleName:method.module withMethod:method.method]; - }else if ([target isKindOfClass:NSClassFromString(@"WXComponent")]) { - selector = [WXComponentFactory methodWithComponentName:method.targets[@"component"] withMethod:method.method]; - } - - // neither a component nor a module - if (!selector) { - NSString *errorMessage = [NSString stringWithFormat:@"%@ is not a component or module", method.targets[@"component"]?:method.module]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - return nil; - } - - NSArray *arguments = method.arguments; - NSMethodSignature *signature = [target methodSignatureForSelector:selector]; - if (!signature) { - NSString *errorMessage = [NSString stringWithFormat:@"%@, method:%@ doesn't exist", method.targets[@"component"]?:method.module, method.method]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - return nil; - } - - if (signature.numberOfArguments - 2 != method.arguments.count) { - NSString *errorMessage = [NSString stringWithFormat:@"%@, the parameters in calling method [%@] and registered method [%@] are not consistent!", method.targets[@"component"]?:method.module, method.method, NSStringFromSelector(selector)]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - return nil; - } - - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; - invocation.target = target; - invocation.selector = selector; - NSString *instanceId = method.instance; - void **freeList = NULL; - - NSMutableArray *blockArray = [NSMutableArray array]; - WX_ALLOC_FLIST(freeList, arguments.count); - for (int i = 0; i < arguments.count; i ++ ) { - id obj = arguments[i]; - const char *parameterType = [signature getArgumentTypeAtIndex:i + 2]; - static const char *blockType = @encode(typeof(^{})); - id argument; - if (!strcmp(parameterType, blockType)) { - // callback - argument = [^void(NSString *result, BOOL keepAlive) { - [[WXSDKManager bridgeMgr]callBack:instanceId funcId:(NSString *)obj params:result keepAlive:keepAlive]; - } copy]; - - // retain block - [blockArray addObject:argument]; - [invocation setArgument:&argument atIndex:i + 2]; - } else { - argument = obj; - WX_ARGUMENTS_SET(invocation, signature, i, argument, freeList); - } - } - [invocation retainArguments]; - WX_FREE_FLIST(freeList, arguments.count); - - return invocation; -} - - (void)registerMethods { Class currentClass = NSClassFromString(_clazz); diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h deleted file mode 100644 index 4e66665c8e..0000000000 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Created by Weex. - * Copyright (c) 2016, Alibaba, Inc. All rights reserved. - * - * This source code is licensed under the Apache Licence 2.0. - * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. - */ - -#import -#import "WXBridgeMethod.h" - -@interface WXModuleManager : NSObject - -- (void)dispatchMethod:(WXBridgeMethod *)method; - -@end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m deleted file mode 100644 index 579f441473..0000000000 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Created by Weex. - * Copyright (c) 2016, Alibaba, Inc. All rights reserved. - * - * This source code is licensed under the Apache Licence 2.0. - * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. - */ - -#import "WXModuleManager.h" -#import "WXModuleProtocol.h" -#import "WXUtility.h" -#import "WXAssert.h" -#import "WXModuleFactory.h" -#import "WXSDKError.h" -#import "WXMonitor.h" -#import "WXSDKManager.h" -#import "WXThreadSafeMutableDictionary.h" -#import "WXInvocationConfig.h" - -#import - -@interface WXModuleManager () - -@property (nonatomic, strong) WXThreadSafeMutableDictionary *indexDict; - -@end - -@implementation WXModuleManager - -- (instancetype)init -{ - self = [super init]; - if(self){ - _indexDict = [[WXThreadSafeMutableDictionary alloc]init]; - } - return self; -} - -#pragma mark Private Methods - -- (void)_executeModuleThead:(NSThread *)thread withBlock:(dispatch_block_t)block -{ - if (!thread || !block) return; - - if ([NSThread currentThread] == thread) { - block(); - } else { - [self performSelector:@selector(_executeModuleBlock:) - onThread:thread - withObject:[block copy] - waitUntilDone:NO]; - } -} - -- (void)_executeModuleBlock:(dispatch_block_t)block -{ - if (block) block(); -} - -- (void)_executeModuleMethod:(id)module withMethod:(WXBridgeMethod *)method -{ - NSInvocation *invocation = [[WXInvocationConfig sharedInstance] invocationWithTargetMethod:module method:method]; - [invocation invoke]; -} - -#pragma mark Public Methods - -- (void)dispatchMethod:(WXBridgeMethod *)method -{ - if (!method) return; - - Class module = [WXModuleFactory classWithModuleName:method.module]; - if (!module) { - NSString *errorMessage = [NSString stringWithFormat:@"Module:%@ doesn't exist!", method.module]; - WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); - return; - } - -// WXLogDebug(@"execute:[module %@], [method %@], [parameter %@]", method.module, method.method, method.arguments); - - WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance]; - id moduleInstance = [weexInstance moduleForClass:module]; - - // dispatch to user specified queue or thread, default is main thread - __weak typeof(self) weakSelf = self; - dispatch_block_t dipatchMethodBlock = ^ (){ - [weakSelf _executeModuleMethod:moduleInstance withMethod:method]; - }; - - NSThread *targetThread = nil; - dispatch_queue_t targetQueue = nil; - if([moduleInstance respondsToSelector:@selector(targetExecuteQueue)]){ - targetQueue = [moduleInstance targetExecuteQueue] ?: dispatch_get_main_queue(); - } else if([moduleInstance respondsToSelector:@selector(targetExecuteThread)]){ - targetThread = [moduleInstance targetExecuteThread] ?: [NSThread mainThread]; - } else { - targetThread = [NSThread mainThread]; - } - - WXAssert(targetQueue || targetThread, @"No queue or thread found for module:%@", moduleInstance); - - if (targetQueue) { - dispatch_async(targetQueue, dipatchMethodBlock); - } else { - WXPerformBlockOnThread(^{ - dipatchMethodBlock(); - }, targetThread); - } -} - -@end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h index f1968ee70f..0f904208a2 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h @@ -19,11 +19,6 @@ **/ + (WXBridgeManager *)bridgeMgr; -/** - * @abstract Returns module manager - **/ -+ (WXModuleManager *)moduleMgr; - /** * @abstract Returns weex instance for specific identifier **/ @@ -44,4 +39,9 @@ **/ + (void)unload; +/** + * @abstract Returns module manager + **/ ++ (WXModuleManager *)moduleMgr DEPRECATED_MSG_ATTRIBUTE(); + @end diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m index c3347afc85..071bc2bbf5 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m @@ -8,14 +8,11 @@ #import "WXSDKManager.h" #import "WXThreadSafeMutableDictionary.h" -#import "WXModuleManager.h" @interface WXSDKManager () @property (nonatomic, strong) WXBridgeManager *bridgeMgr; -@property (nonatomic, strong) WXModuleManager *moduleMgr; - @property (nonatomic, strong) WXThreadSafeMutableDictionary *instanceDict; @end @@ -46,16 +43,6 @@ + (WXBridgeManager *)bridgeMgr return bridgeMgr; } -+ (WXModuleManager *)moduleMgr -{ - WXModuleManager *moduleMgr = [self sharedInstance].moduleMgr; - if (!moduleMgr) { - moduleMgr = [[WXModuleManager alloc] init]; - [self sharedInstance].moduleMgr = moduleMgr; - } - return moduleMgr; -} - + (id)instanceForID:(NSString *)identifier { return [[self sharedInstance].instanceDict objectForKey:identifier]; @@ -81,7 +68,11 @@ + (void)unload } [self sharedInstance].bridgeMgr = nil; - [self sharedInstance].moduleMgr = nil; +} + ++ (WXModuleManager *)moduleMgr +{ + return nil; } @end diff --git a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h index f8dc62efd2..5cfc657994 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h @@ -7,19 +7,19 @@ */ #import +@class WXSDKInstance; @interface WXBridgeMethod : NSObject -@property (nonatomic, strong) NSString *instance; -@property (nonatomic, strong) NSString *module; -@property (nonatomic, strong) NSString *method; -@property (nonatomic, strong) NSArray *arguments; -@property (nonatomic, strong) NSDictionary *targets; +@property (nonatomic, strong, readonly) NSString *methodName; +@property (nonatomic, copy, readonly) NSArray *arguments; +@property (nonatomic, weak, readonly) WXSDKInstance *instance; -- (instancetype)initWihData:(NSDictionary *)data; +- (instancetype)initWithMethodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance; -- (instancetype)initWithInstance:(NSString *)instance data:(NSMutableDictionary *)data; - -- (NSDictionary *)dataDesc; +- (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector; @end + diff --git a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m index d01a06635e..7caf58eda6 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m @@ -7,40 +7,114 @@ */ #import "WXBridgeMethod.h" +#import "WXSDKInstance.h" +#import "WXMonitor.h" +#import "WXAssert.h" +#import "WXUtility.h" +#import "WXSDKManager.h" +#import @implementation WXBridgeMethod -- (instancetype)initWihData:(NSDictionary *)data +- (instancetype)initWithMethodName:(NSString *)methodName arguments:(NSArray *)arguments instance:(WXSDKInstance *)instance { - self = [super init]; - if(self){ - _module = [data valueForKey:@"module"]; - _method = [data valueForKey:@"method"]; - _arguments = [data valueForKey:@"args"]; - if (data[@"component"]) { - self.targets = [NSMutableDictionary new]; - [self.targets setValue:data[@"component"] forKey:@"component"]; - [self.targets setValue:data[@"ref"]?:@"" forKey:@"ref"]; - } + if (self = [super init]) { + _methodName = methodName; + _arguments = arguments; + _instance = instance; } + return self; } -- (instancetype)initWithInstance:(NSString *)instance data:(NSMutableDictionary *)data +- (NSString *)description { - self = [self initWihData:data]; - if (self) { - _instance = instance; - } - return self; + return [NSString stringWithFormat:@"<%@: %p; instance = %@; method = %@; arguments= %@>", NSStringFromClass([self class]), self, _instance.instanceId, _methodName, _arguments]; } -- (NSDictionary *)dataDesc +- (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector { - NSString *module = _module ? : @""; - NSString *method = _method ? : @""; - NSArray *arguments = _arguments ? : @[]; - return @{@"module":module, @"method":method, @"args":arguments}; + WXAssert(target, @"No target for method:%@", self); + WXAssert(selector, @"No selector for method:%@", self); + + NSMethodSignature *signature = [target methodSignatureForSelector:selector]; + if (!signature) { + NSString *errorMessage = [NSString stringWithFormat:@"target:%@, selector:%@ doesn't have a method signature", target, NSStringFromSelector(selector)]; + WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); + return nil; + } + + NSArray *arguments = _arguments; + if (signature.numberOfArguments - 2 != arguments.count) { + NSString *errorMessage = [NSString stringWithFormat:@"%@, the parameters in calling method [%@] and registered method [%@] are not consistent!", target, _methodName, NSStringFromSelector(selector)]; + WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); + return nil; + } + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.target = target; + invocation.selector = selector; + NSString *instanceId = _instance.instanceId; + void **freeList = NULL; + + NSMutableArray *blockArray = [NSMutableArray array]; + WX_ALLOC_FLIST(freeList, arguments.count); + for (int i = 0; i < arguments.count; i ++ ) { + id obj = arguments[i]; + const char *parameterType = [signature getArgumentTypeAtIndex:i + 2]; + static const char *blockType = @encode(typeof(^{})); + id argument; + if (!strcmp(parameterType, blockType)) { + // callback + argument = [^void(NSString *result, BOOL keepAlive) { + [[WXSDKManager bridgeMgr] callBack:instanceId funcId:(NSString *)obj params:result keepAlive:keepAlive]; + } copy]; + + // retain block + [blockArray addObject:argument]; + [invocation setArgument:&argument atIndex:i + 2]; + } else { + argument = obj; + WX_ARGUMENTS_SET(invocation, signature, i, argument, freeList); + } + } + [invocation retainArguments]; + WX_FREE_FLIST(freeList, arguments.count); + + return invocation; } +// +//- (instancetype)initWihData:(NSDictionary *)data +//{ +// self = [super init]; +// if(self){ +// _module = [data valueForKey:@"module"]; +// _method = [data valueForKey:@"method"]; +// _arguments = [data valueForKey:@"args"]; +// if (data[@"component"]) { +// self.targets = [NSMutableDictionary new]; +// [self.targets setValue:data[@"component"] forKey:@"component"]; +// [self.targets setValue:data[@"ref"]?:@"" forKey:@"ref"]; +// } +// } +// return self; +//} +// +//- (instancetype)initWithInstance:(NSString *)instance data:(NSMutableDictionary *)data +//{ +// self = [self initWihData:data]; +// if (self) { +// _instance = instance; +// } +// return self; +//} +// +//- (NSDictionary *)dataDesc +//{ +// NSString *module = _module ? : @""; +// NSString *method = _method ? : @""; +// NSArray *arguments = _arguments ? : @[]; +// return @{@"module":module, @"method":method, @"args":arguments}; +//} @end diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index d9ef7191bd..b9cbb11e8d 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -81,6 +81,11 @@ - (instancetype)init return self; } +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p; id = %@; rootView = %@; url= %@>", NSStringFromClass([self class]), self, _instanceId, _rootView, _scriptURL]; +} + #pragma mark Public Mehtods - (UIView *)rootView diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h index c874935de6..2685082718 100644 --- a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h +++ b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h @@ -8,6 +8,7 @@ #import #import "WXDefine.h" +#import "WXSDKError.h" @class WXSDKInstance; diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h index 035b5b7984..8808700c87 100644 --- a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h +++ b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h @@ -10,7 +10,8 @@ typedef NSInteger (^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback); typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index); - +typedef id (^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options); +typedef id (^WXJSCallNativeComponent)(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options); @protocol WXBridgeProtocol @@ -39,14 +40,25 @@ typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId, NSString *parentR @optional +/** + * Called when garbage collection is wanted by sdk. + */ +- (void)garbageCollect; + /** * Register callback when addElement tasks occur */ - (void)registerCallAddElement:(WXJSCallAddElement)callAddElement; /** - * Called when garbage collection is wanted by sdk. + * Register callback for global js function `callNativeModule` */ -- (void)garbageCollect; +- (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock; + +/** + * Register callback for global js function `callNativeComponent` + */ +- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock; + @end diff --git a/ios/sdk/WeexSDK/Sources/WeexSDK.h b/ios/sdk/WeexSDK/Sources/WeexSDK.h index d55203144d..33eb2bb11d 100644 --- a/ios/sdk/WeexSDK/Sources/WeexSDK.h +++ b/ios/sdk/WeexSDK/Sources/WeexSDK.h @@ -18,6 +18,7 @@ #import "WXSDKError.h" #import "WXSDKEngine.h" #import "WXRootViewController.h" +#import "WXResourceRequest.h" #import "WXNetworkProtocol.h" #import "WXNavigationProtocol.h" #import "WXMonitor.h" diff --git a/ios/sdk/WeexSDKTests/WXBridgeMethodTests.m b/ios/sdk/WeexSDKTests/WXBridgeMethodTests.m index 26ecffe841..05ab11cdd1 100644 --- a/ios/sdk/WeexSDKTests/WXBridgeMethodTests.m +++ b/ios/sdk/WeexSDKTests/WXBridgeMethodTests.m @@ -7,7 +7,7 @@ */ #import -#import "WXBridgeMethod.h" +#import "WXCallJSMethod.h" #import "WXSDKInstance.h" @interface WXBridgeMethodTests : XCTestCase @@ -29,27 +29,27 @@ - (void)tearDown { - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. + WXSDKInstance *instance = [[WXSDKInstance alloc] init]; - NSDictionary *data = @{@"module":@"dom", @"method":@"test", @"args":@[@"1", @"2", @"3"]}; - WXBridgeMethod *method = [[WXBridgeMethod alloc] initWithInstance:@"0" data:[NSMutableDictionary dictionaryWithDictionary:data]]; + WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:@"dom" methodName:@"test" arguments:@[@"1", @"2", @"3"] instance:instance]; - NSDictionary *desc = [method dataDesc]; - XCTAssertEqualObjects(desc[@"module"], @"dom"); - XCTAssertEqualObjects(desc[@"method"], @"test"); + NSDictionary *task = [method callJSTask]; + XCTAssertEqualObjects(task[@"module"], @"dom"); + XCTAssertEqualObjects(task[@"method"], @"test"); - NSArray *args = desc[@"args"]; + NSArray *args = task[@"args"]; XCTAssertTrue(args.count == 3); XCTAssertEqualObjects(args[0], @"1"); XCTAssertEqualObjects(args[1], @"2"); XCTAssertEqualObjects(args[2], @"3"); - method = [[WXBridgeMethod alloc] initWithInstance:@"1" data:[NSMutableDictionary dictionary]]; + WXCallJSMethod *method2 = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:nil arguments:nil instance:[[WXSDKInstance alloc] init]]; - desc = [method dataDesc]; - XCTAssertEqualObjects(desc[@"module"], @""); - XCTAssertEqualObjects(desc[@"method"], @""); + task = [method2 callJSTask]; + XCTAssertEqualObjects(task[@"module"], @""); + XCTAssertEqualObjects(task[@"method"], @""); - args = desc[@"args"]; + args = task[@"args"]; XCTAssertNotNil(args); XCTAssertTrue(args.count == 0); } diff --git a/ios/sdk/WeexSDKTests/WXSDKManagerTests.m b/ios/sdk/WeexSDKTests/WXSDKManagerTests.m index f3e65bbc75..b3a15b590e 100644 --- a/ios/sdk/WeexSDKTests/WXSDKManagerTests.m +++ b/ios/sdk/WeexSDKTests/WXSDKManagerTests.m @@ -32,22 +32,12 @@ - (void)testExample { // Use XCTAssert and related functions to verify your tests produce the correct results. } -- (void)testPerformanceExample { - // This is an example of a performance test case. - [self measureBlock:^{ - // Put the code you want to measure the time of here. - }]; -} - (void)testWXSDKManager { id bridgeMgr = [WXSDKManager bridgeMgr]; XCTAssertNotNil(bridgeMgr); XCTAssertTrue([bridgeMgr isKindOfClass:NSClassFromString(@"WXBridgeManager")]); - id moduleMgr = [WXSDKManager moduleMgr]; - XCTAssertNotNil(moduleMgr); - XCTAssertTrue([moduleMgr isKindOfClass:NSClassFromString(@"WXModuleManager")]); - [WXSDKManager storeInstance:[WXSDKInstance new] forID:@"0"]; WXSDKInstance *instance0 = [WXSDKManager instanceForID:@"0"]; XCTAssertNotNil(instance0); From 0b24ec05f6b1a265473d01b3bb5e464eb1d365d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 21 Dec 2016 15:01:40 +0800 Subject: [PATCH 024/144] + [ios] support font weight with better solution --- .../Sources/Component/WXTextAreaComponent.m | 2 +- .../Sources/Component/WXTextComponent.m | 2 +- .../Sources/Component/WXTextInputComponent.m | 2 +- ios/sdk/WeexSDK/Sources/Utility/WXConvert.h | 8 +++- ios/sdk/WeexSDK/Sources/Utility/WXConvert.m | 26 +++++----- ios/sdk/WeexSDK/Sources/Utility/WXType.h | 13 ----- ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 4 +- ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 48 ++----------------- 8 files changed, 30 insertions(+), 75 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m index f25fc40be6..a6df57ce69 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.m @@ -67,7 +67,7 @@ @interface WXTextAreaComponent() //style @property (nonatomic) WXPixelType fontSize; @property (nonatomic) WXTextStyle fontStyle; -@property (nonatomic) WXTextWeight fontWeight; +@property (nonatomic) CGFloat fontWeight; @property (nonatomic, strong) NSString *fontFamily; @property (nonatomic, strong) UIColor *color; @property (nonatomic) NSTextAlignment textAlign; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 3896d04bc1..84e7b7b8f3 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -105,7 +105,7 @@ @implementation WXTextComponent UIColor *_color; NSString *_fontFamily; CGFloat _fontSize; - WXTextWeight _fontWeight; + CGFloat _fontWeight; WXTextStyle _fontStyle; NSUInteger _lines; NSTextAlignment _textAlign; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m index f0e03352ff..96ce2e6d23 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextInputComponent.m @@ -61,7 +61,7 @@ @interface WXTextInputComponent() //style @property (nonatomic) WXPixelType fontSize; @property (nonatomic) WXTextStyle fontStyle; -@property (nonatomic) WXTextWeight fontWeight; +@property (nonatomic) CGFloat fontWeight; @property (nonatomic, strong) NSString *fontFamily; @property (nonatomic, copy) NSString *inputType; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h index c502229ae4..f406338cfd 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h @@ -44,7 +44,13 @@ typedef BOOL WXClipType; + (WXPositionType)WXPositionType:(id)value; + (WXTextStyle)WXTextStyle:(id)value; -+ (WXTextWeight)WXTextWeight:(id)value; +/** + * @abstract UIFontWeightRegular ,UIFontWeightBold,etc are not support by the system which is less than 8.2. weex sdk set the float value. + * + * @param value, support normal,blod,100,200,300,400,500,600,700,800,900 + * + */ ++ (CGFloat)WXTextWeight:(id)value; + (WXTextDecoration)WXTextDecoration:(id)value; + (NSTextAlignment)NSTextAlignment:(id)value; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index e98ed8be3d..56ad357d5a 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -478,35 +478,35 @@ + (WXTextStyle)WXTextStyle:(id)value return WXTextStyleNormal; } -+ (WXTextWeight)WXTextWeight:(id)value ++ (CGFloat )WXTextWeight:(id)value { if([value isKindOfClass:[NSString class]]){ NSString *string = (NSString *)value; if ([string isEqualToString:@"normal"]) - return WXFontWeightRegular; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular; else if ([string isEqualToString:@"bold"]) - return WXFontWeightBold; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.4:UIFontWeightBold; else if ([string isEqualToString:@"100"]) - return WXFontWeightUltraLight; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.8:UIFontWeightUltraLight; else if ([string isEqualToString:@"200"]) - return WXFontWeightThin; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.6:UIFontWeightThin; else if ([string isEqualToString:@"300"]) - return WXFontWeightLight; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.4:UIFontWeightLight; else if ([string isEqualToString:@"400"]) - return WXFontWeightRegular; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular; else if ([string isEqualToString:@"500"]) - return WXFontWeightMedium; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.23:UIFontWeightMedium; else if ([string isEqualToString:@"600"]) - return WXFontWeightSemibold; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.3:UIFontWeightSemibold; else if ([string isEqualToString:@"700"]) - return WXFontWeightBold; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.4:UIFontWeightBold; else if ([string isEqualToString:@"800"]) - return WXFontWeightHeavy; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.56:UIFontWeightHeavy; else if ([string isEqualToString:@"900"]) - return WXFontWeightBlack; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.62:UIFontWeightBlack; } - return WXFontWeightRegular; + return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular; } + (WXTextDecoration)WXTextDecoration:(id)value diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXType.h b/ios/sdk/WeexSDK/Sources/Utility/WXType.h index 14c31f2f07..42f09a89a4 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXType.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXType.h @@ -20,19 +20,6 @@ typedef NS_ENUM(NSUInteger, WXTextStyle) { WXTextStyleItalic }; -typedef NS_ENUM(NSUInteger, WXTextWeight) { - WXFontWeightRegular = 0, - WXFontWeightUltraLight, - WXFontWeightThin, - WXFontWeightLight, - WXFontWeightMedium, - WXFontWeightSemibold, - WXFontWeightBold, - WXFontWeightHeavy, - WXFontWeightBlack - -}; - typedef NS_ENUM(NSInteger, WXTextDecoration) { WXTextDecorationNone = 0, WXTextDecorationUnderline, diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h index 8237d3984e..1ab320eebb 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h @@ -202,7 +202,7 @@ extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector); * * @param textSize. * - * @param textWeight. The type of WXTextWeight (Normal or Bold). + * @param textWeight. * * @param textStyle. The type of WXTextStyle (Normal or Italic). * @@ -211,7 +211,7 @@ extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector); * @return A font object according to the above params. * */ -+ (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily; ++ (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily; /** * @abstract download remote font from specified url diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index b2e53b4c67..e492856117 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -340,7 +340,7 @@ + (NSError *)errorWithCode:(NSInteger)code message:(NSString *)message return [NSError errorWithDomain:@"WeexErrorDomain" code:code userInfo:@{@"errMsg":message}]; } -+ (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily ++ (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily { CGFloat fontSize = (isnan(size) || size == 0) ? WX_TEXT_FONT_SIZE : size; UIFont *font = nil; @@ -363,23 +363,22 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textS [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; } } - CGFloat weight = WXFontWeightRegular; - weight = [WXUtility textWeight:textWeight]; if (!font) { if (fontFamily) { font = [UIFont fontWithName:fontFamily size:fontSize]; if (!font) { WXLogWarning(@"Unknown fontFamily:%@", fontFamily); - font = [UIFont systemFontOfSize:fontSize weight:weight]; + font = [UIFont systemFontOfSize:fontSize weight:textWeight]; } } else { - font = [UIFont systemFontOfSize:fontSize weight:weight]; + font = [UIFont systemFontOfSize:fontSize weight:textWeight]; } } UIFontDescriptor *fontD = font.fontDescriptor; UIFontDescriptorSymbolicTraits traits = 0; + traits = (textStyle == WXTextStyleItalic) ? (traits | UIFontDescriptorTraitItalic) : traits; - traits = (textWeight == WXFontWeightBold) ? (traits | UIFontDescriptorTraitBold) : traits; + traits = (fabs(textWeight-(WX_SYS_VERSION_LESS_THAN(@"8.2")?0.4:UIFontWeightBold)) <= 1e-6) ? (traits | UIFontDescriptorTraitBold) : traits; if (traits != 0) { fontD = [fontD fontDescriptorWithSymbolicTraits:traits]; UIFont *tempFont = [UIFont fontWithDescriptor:fontD size:0]; @@ -391,43 +390,6 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(WXTextWeight)textWeight textS return font; } -+ (CGFloat )textWeight:(WXTextWeight)type -{ - CGFloat weight = WXFontWeightRegular; - switch (type) { - case WXFontWeightUltraLight: - weight = -0.8; - break; - case WXFontWeightThin: - weight = -0.6; - break; - case WXFontWeightLight: - weight = -0.4; - break; - case WXFontWeightRegular: - weight = 0; - break; - case WXFontWeightMedium: - weight = 0.23; - break; - case WXFontWeightSemibold: - weight = 0.3; - break; - case WXFontWeightBold: - weight = 0.4; - break; - case WXFontWeightHeavy: - weight = 0.56; - break; - case WXFontWeightBlack: - weight = 0.62; - break; - default: - break; - } - return weight; -} - + (void)getIconfont:(NSURL *)url completion:(void(^)(NSURL *url, NSError *error))completionBlock { if ([url isFileURL]) { From e93e9c24d9eef19ad14910a069755007151574da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 21 Dec 2016 15:06:36 +0800 Subject: [PATCH 025/144] * [ios] add description --- ios/sdk/WeexSDK/Sources/Utility/WXConvert.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h index f406338cfd..62d9a2a011 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h @@ -48,6 +48,7 @@ typedef BOOL WXClipType; * @abstract UIFontWeightRegular ,UIFontWeightBold,etc are not support by the system which is less than 8.2. weex sdk set the float value. * * @param value, support normal,blod,100,200,300,400,500,600,700,800,900 + * @return A float value. * */ + (CGFloat)WXTextWeight:(id)value; From 35e4aeb864bef4e0de609e019e5dc57adc7b40f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 21 Dec 2016 15:07:31 +0800 Subject: [PATCH 026/144] + [ios] add description --- ios/sdk/WeexSDK/Sources/Utility/WXConvert.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h index 62d9a2a011..ef152c0375 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h @@ -48,6 +48,7 @@ typedef BOOL WXClipType; * @abstract UIFontWeightRegular ,UIFontWeightBold,etc are not support by the system which is less than 8.2. weex sdk set the float value. * * @param value, support normal,blod,100,200,300,400,500,600,700,800,900 + * * @return A float value. * */ From ac1ca570119902c28c6e7e28165389a725851858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=90=E5=B1=B1?= Date: Wed, 21 Dec 2016 15:09:55 +0800 Subject: [PATCH 027/144] + [ios] remove blank --- ios/sdk/WeexSDK/Sources/Utility/WXConvert.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index 56ad357d5a..925b51932e 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -478,7 +478,7 @@ + (WXTextStyle)WXTextStyle:(id)value return WXTextStyleNormal; } -+ (CGFloat )WXTextWeight:(id)value ++ (CGFloat)WXTextWeight:(id)value { if([value isKindOfClass:[NSString class]]){ NSString *string = (NSString *)value; From eb9efb11038211e7da0f4a46810f985c583ff149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Wed, 21 Dec 2016 15:58:24 +0800 Subject: [PATCH 028/144] * [ios] register meta module to default modules. --- ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m index 36bc3cbc2e..5fa8e47fae 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m @@ -44,6 +44,7 @@ + (void)_registerDefaultModules [self registerModule:@"globalEvent" withClass:NSClassFromString(@"WXGlobalEventModule")]; [self registerModule:@"canvas" withClass:NSClassFromString(@"WXCanvasModule")]; [self registerModule:@"picker" withClass:NSClassFromString(@"WXPickerModule")]; + [self registerModule:@"meta" withClass:NSClassFromString(@"WXMetaModule")]; } + (void)registerModule:(NSString *)name withClass:(Class)clazz From aa50df0d5e0d26997aca479324317854ba099932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Wed, 21 Dec 2016 17:27:02 +0800 Subject: [PATCH 029/144] * [ios] feature: separate callNativeModule and callNativeComponent from callName and support calling module method synchronously. --- ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m | 4 ++++ .../WeexSDK/Sources/Bridge/WXBridgeContext.m | 14 ++++++----- .../Sources/Bridge/WXComponentMethod.h | 9 ++++--- .../Sources/Bridge/WXComponentMethod.m | 12 ++++------ .../WeexSDK/Sources/Bridge/WXJSCoreBridge.m | 18 +++++++++++--- .../WeexSDK/Sources/Bridge/WXModuleMethod.m | 13 ++++++---- .../Sources/Manager/WXComponentFactory.m | 6 ++--- .../Sources/Manager/WXInvocationConfig.h | 3 ++- .../Sources/Manager/WXInvocationConfig.m | 19 ++++++++++----- .../WeexSDK/Sources/Manager/WXModuleFactory.h | 4 ++-- .../WeexSDK/Sources/Manager/WXModuleFactory.m | 24 +++++++++++-------- .../Sources/Protocol/WXBridgeProtocol.h | 10 ++++---- ios/sdk/WeexSDK/Sources/Utility/WXDefine.h | 17 +++++++++---- ios/sdk/WeexSDKTests/WXSDKEngineTests.m | 2 +- 14 files changed, 97 insertions(+), 58 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m index 5734434e80..d0a2daa75d 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m @@ -13,6 +13,10 @@ @implementation JSValue (Weex) + (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context { + if (!invocation || !context) { + return nil; + } + char returnType[255]; strcpy(returnType, [invocation.methodSignature methodReturnType]); diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m index 31618c5a74..61d87bae5d 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m @@ -116,7 +116,7 @@ - (void)registerGlobalFuntions return 0; }]; - [_jsBridge registerCallNativeModule:^id(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options) { + [_jsBridge registerCallNativeModule:^NSInvocation*(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *arguments, NSDictionary *options) { WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; @@ -125,11 +125,14 @@ - (void)registerGlobalFuntions return nil; } - return nil; + WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:arguments instance:instance]; + return [method invoke]; }]; - [_jsBridge registerCallNativeComponent:^id(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) { - return nil; + [_jsBridge registerCallNativeComponent:^void(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) { + WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId]; + WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:componentRef methodName:methodName arguments:args instance:instance]; + [method invoke]; }]; } @@ -184,9 +187,8 @@ - (NSInteger)invokeNative:(NSString *)instanceId tasks:(NSArray *)tasks callback NSString *methodName = task[@"method"]; NSArray *arguments = task[@"args"]; if (task[@"component"]) { - NSString *componentName = task[@"component"]; NSString *ref = task[@"ref"]; - WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentName:componentName componentRef:ref methodName:methodName arguments:arguments instance:instance]; + WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:ref methodName:methodName arguments:arguments instance:instance]; [method invoke]; } else { NSString *moduleName = task[@"module"]; diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h index 9bb205377a..f8cd5a904d 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h @@ -11,11 +11,10 @@ @interface WXComponentMethod : WXBridgeMethod -- (instancetype)initWithComponentName:(NSString *)componentName - componentRef:(NSString *)ref - methodName:(NSString *)methodName - arguments:(NSArray *)arguments - instance:(WXSDKInstance *)instance; +- (instancetype)initWithComponentRef:(NSString *)ref + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance; - (void)invoke; diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m index c832267025..b97c3d7e65 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m @@ -19,14 +19,12 @@ @implementation WXComponentMethod NSString *_componentRef; } -- (instancetype)initWithComponentName:(NSString *)componentName - componentRef:(NSString *)ref - methodName:(NSString *)methodName - arguments:(NSArray *)arguments - instance:(WXSDKInstance *)instance +- (instancetype)initWithComponentRef:(NSString *)ref + methodName:(NSString *)methodName + arguments:(NSArray *)arguments + instance:(WXSDKInstance *)instance { if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) { - _componentName = componentName; _componentRef = ref; } @@ -40,7 +38,7 @@ - (void)invoke if (!component) { WXLogError(@"component not found for ref:%@, type:%@", _componentRef, _componentName); } - SEL selector = [WXComponentFactory methodWithComponentName:_componentName withMethod:self.methodName]; + SEL selector = [WXComponentFactory methodWithComponentName:component.type withMethod:self.methodName]; NSInvocation * invocation = [self invocationWithTarget:component selector:selector]; WXPerformBlockOnMainThread(^{ [invocation invoke]; diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m index ad1d5142af..eb51b828e3 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m @@ -20,6 +20,7 @@ #import #import #import "WXPolyfillSet.h" +#import "JSValue+Weex.h" #import @@ -167,13 +168,24 @@ - (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, moduleNameString, methodNameString, argsArray); - return callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic); + NSInvocation *invocation = callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic); + return [JSValue wx_valueWithReturnValueFromInvocation:invocation inContext:[JSContext currentContext]]; }; } -- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock +- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock { - + _jsContext[@"callNativeComponent"] = ^void(JSValue *instanceId, JSValue *componentName, JSValue *methodName, JSValue *args, JSValue *options) { + NSString *instanceIdString = [instanceId toString]; + NSString *componentNameString = [componentName toString]; + NSString *methodNameString = [methodName toString]; + NSArray *argsArray = [args toArray]; + NSDictionary *optionsDic = [options toDictionary]; + + WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, componentNameString, methodNameString, argsArray); + + callNativeComponentBlock(instanceIdString, componentNameString, methodNameString, argsArray, optionsDic); + }; } - (JSValue*)exception diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m index 6a87bcf6f6..c7c5502966 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m @@ -38,7 +38,8 @@ - (NSInvocation *)invoke id moduleInstance = [self.instance moduleForClass:moduleClass]; WXAssert(moduleInstance, @"No instance found for module name:%@, class:%@", _moduleName, moduleClass); - SEL selector = [WXModuleFactory methodWithModuleName:self.moduleName withMethod:self.methodName]; + BOOL isSync; + SEL selector = [WXModuleFactory selectorWithModuleName:self.moduleName methodName:self.methodName isSync:&isSync]; if (!selector) { NSString *errorMessage = [NSString stringWithFormat:@"method:%@ for module:%@ doesn't exist, maybe it has not been registered", self.methodName, _moduleName]; WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage); @@ -47,9 +48,13 @@ - (NSInvocation *)invoke NSInvocation *invocation = [self invocationWithTarget:moduleInstance selector:selector]; - [self _dispatchInvovation:invocation moduleInstance:moduleInstance]; - - return nil; + if (isSync) { + [invocation invoke]; + return invocation; + } else { + [self _dispatchInvovation:invocation moduleInstance:moduleInstance]; + return nil; + } } - (void)_dispatchInvovation:(NSInvocation *)invocation moduleInstance:(id)moduleInstance diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m index 8c55cdfbde..d3c972a3f5 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m @@ -117,7 +117,7 @@ - (NSMutableDictionary *)_componentMethodMapsWithName:(NSString *)name void (^mBlock)(id, id, BOOL *) = ^(id mKey, id mObj, BOOL * mStop) { [methods addObject:mKey]; }; - [config.methods enumerateKeysAndObjectsUsingBlock:mBlock]; + [config.asyncMethods enumerateKeysAndObjectsUsingBlock:mBlock]; [_configLock unlock]; return dict; @@ -132,8 +132,8 @@ - (SEL)_methodWithComponnetName:(NSString *)name withMethod:(NSString *)method [_configLock lock]; config = [_componentConfigs objectForKey:name]; - if (config.methods) { - selStr = [config.methods objectForKey:method]; + if (config.asyncMethods) { + selStr = [config.asyncMethods objectForKey:method]; } if (selStr) { selector = NSSelectorFromString(selStr); diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h index 6d5db6062c..1bcef92017 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.h @@ -17,7 +17,8 @@ /** * The methods map **/ -@property (nonatomic, strong) NSMutableDictionary *methods; +@property (nonatomic, strong) NSMutableDictionary *asyncMethods; +@property (nonatomic, strong) NSMutableDictionary *syncMethods; + (instancetype)sharedInstance; - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz; diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m index 71b90112ab..7fa0838a15 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXInvocationConfig.m @@ -39,7 +39,8 @@ - (instancetype)init { if (self = [super init]) { - _methods = [NSMutableDictionary new]; + _asyncMethods = [NSMutableDictionary new]; + _syncMethods = [NSMutableDictionary new]; } return self; @@ -47,8 +48,7 @@ - (instancetype)init - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz { - if (self = [super init]) { - _methods = [NSMutableDictionary new]; + if (self = [self init]) { _name = name; _clazz = clazz; } @@ -69,8 +69,14 @@ - (void)registerMethods Method *methodList = class_copyMethodList(object_getClass(currentClass), &methodCount); for (unsigned int i = 0; i < methodCount; i++) { NSString *selStr = [NSString stringWithCString:sel_getName(method_getName(methodList[i])) encoding:NSUTF8StringEncoding]; - - if (![selStr hasPrefix:@"wx_export_method_"]) continue; + BOOL isSyncMethod; + if ([selStr hasPrefix:@"wx_export_method_sync_"]) { + isSyncMethod = YES; + } else if ([selStr hasPrefix:@"wx_export_method_"]) { + isSyncMethod = NO; + } else { + continue; + } NSString *name = nil, *method = nil; SEL selector = NSSelectorFromString(selStr); @@ -90,7 +96,8 @@ - (void)registerMethods name = method; } - [_methods setObject:method forKey:name]; + NSMutableDictionary *methods = isSyncMethod ? _syncMethods : _asyncMethods; + [methods setObject:method forKey:name]; } free(methodList); diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h index 94d0404b62..e96c89b208 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h @@ -26,12 +26,12 @@ * @param method The module method * **/ -+ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method; ++ (SEL)selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync; /** * @abstract Registers a module for a given name and the implemented class * - * @param module The module name to register + * @param name The module name to register * * @param clazz The module class to register * diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m index 3ab7f50c1e..74d8e29d31 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m @@ -83,24 +83,27 @@ - (Class)_classWithModuleName:(NSString *)name return NSClassFromString(config.clazz); } -- (SEL)_methodWithModuleName:(NSString *)name withMethod:(NSString *)method +- (SEL)_selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync { WXAssert(name && method, @"Fail to find selector with module name and method, please check if the parameters are correct !"); - NSString *selStr = nil; SEL selector = nil; + NSString *selectorString = nil;; WXModuleConfig *config = nil; [_moduleLock lock]; config = [_moduleMap objectForKey:name]; - if (config.methods) { - selStr = [config.methods objectForKey:method]; + if (config.syncMethods) { + selectorString = [config.syncMethods objectForKey:method]; + if (selectorString && isSync) { + *isSync = YES; + } } - if (selStr) { - selector = NSSelectorFromString(selStr); + if (!selectorString && config.asyncMethods) { + selectorString = [config.asyncMethods objectForKey:method];; } [_moduleLock unlock]; - return selector; + return NSSelectorFromString(selectorString); } - (NSString *)_registerModule:(NSString *)name withClass:(Class)clazz @@ -131,7 +134,8 @@ - (NSMutableDictionary *)_moduleMethodMapsWithName:(NSString *)name void (^mBlock)(id, id, BOOL *) = ^(id mKey, id mObj, BOOL * mStop) { [methods addObject:mKey]; }; - [config.methods enumerateKeysAndObjectsUsingBlock:mBlock]; + [config.syncMethods enumerateKeysAndObjectsUsingBlock:mBlock]; + [config.asyncMethods enumerateKeysAndObjectsUsingBlock:mBlock]; [_moduleLock unlock]; return dict; @@ -160,9 +164,9 @@ + (Class)classWithModuleName:(NSString *)name return [[self _sharedInstance] _classWithModuleName:name]; } -+ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method ++ (SEL)selectorWithModuleName:(NSString *)name methodName:(NSString *)method isSync:(BOOL *)isSync { - return [[self _sharedInstance] _methodWithModuleName:name withMethod:method]; + return [[self _sharedInstance] _selectorWithModuleName:name methodName:method isSync:isSync]; } + (NSString *)registerModule:(NSString *)name withClass:(Class)clazz diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h index 8808700c87..cd3656ffb1 100644 --- a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h +++ b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h @@ -8,10 +8,10 @@ #import -typedef NSInteger (^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback); -typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index); -typedef id (^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options); -typedef id (^WXJSCallNativeComponent)(NSString *instancdId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options); +typedef NSInteger(^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback); +typedef NSInteger(^WXJSCallAddElement)(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index); +typedef NSInvocation *(^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options); +typedef void (^WXJSCallNativeComponent)(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options); @protocol WXBridgeProtocol @@ -58,7 +58,7 @@ typedef id (^WXJSCallNativeComponent)(NSString *instancdId, NSString *componentR /** * Register callback for global js function `callNativeComponent` */ -- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callComponentModuleBlock; +- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock; @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h index 9d39a48cc6..37e0d5782e 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h @@ -70,16 +70,23 @@ parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];\ #define WX_FONT_DOWNLOAD_DIR [[WXUtility cacheDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:@"wxdownload"]] +#define WX_EXPORT_METHOD_INTERNAL(method, token) \ ++ (NSString *)WX_CONCAT_WRAPPER(token, __LINE__) { \ + return NSStringFromSelector(method); \ +} + /** * @abstract export public method */ +#define WX_EXPORT_METHOD(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_) -#define WX_EXPORT_METHOD(method) \ -+ (NSString *)WX_CONCAT_WRAPPER(wx_export_method_, __LINE__) { \ -return NSStringFromSelector(method); \ -} +/** + * @abstract export public method, support sync return value + * @warning the method can only be called on js thread + */ +#define WX_EXPORT_METHOD_SYNC(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_sync_) -/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) +/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) * so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function. * http://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c */ diff --git a/ios/sdk/WeexSDKTests/WXSDKEngineTests.m b/ios/sdk/WeexSDKTests/WXSDKEngineTests.m index f506d8849c..260e10b09b 100644 --- a/ios/sdk/WeexSDKTests/WXSDKEngineTests.m +++ b/ios/sdk/WeexSDKTests/WXSDKEngineTests.m @@ -57,7 +57,7 @@ - (void)testRegisterModule { Class cls = [WXModuleFactory classWithModuleName:@"stream"]; XCTAssertEqualObjects(NSStringFromClass(cls), @"WXStreamModule"); - SEL selector = [WXModuleFactory methodWithModuleName:@"stream" withMethod:@"fetch"]; + SEL selector = [WXModuleFactory selectorWithModuleName:@"stream" methodName:@"fetch" isSync:nil]; XCTAssertEqualObjects(NSStringFromSelector(selector), @"fetch:callback:progressCallback:"); } From 93c074e1ecc5f62ebf7963b8a34fe3f27d7cddc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Thu, 22 Dec 2016 11:02:50 +0800 Subject: [PATCH 030/144] * [ios] in the latest Xcode, no need to disable OS_ACTIVITY_MODE --- .../WeexDemo.xcodeproj/xcshareddata/xcschemes/WeexDemo.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/playground/WeexDemo.xcodeproj/xcshareddata/xcschemes/WeexDemo.xcscheme b/ios/playground/WeexDemo.xcodeproj/xcshareddata/xcschemes/WeexDemo.xcscheme index c718bd87b2..a33c31da75 100644 --- a/ios/playground/WeexDemo.xcodeproj/xcshareddata/xcschemes/WeexDemo.xcscheme +++ b/ios/playground/WeexDemo.xcodeproj/xcshareddata/xcschemes/WeexDemo.xcscheme @@ -86,7 +86,7 @@ + isEnabled = "NO"> Date: Thu, 22 Dec 2016 16:34:21 +0800 Subject: [PATCH 031/144] * [ios] fix issue that there will be 1px space remaining between list's top and navigator when UITableView is pulled down and finger releases. --- .../Sources/Component/WXListComponent.m | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m index 8e6a611099..c69e5abebf 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m @@ -36,6 +36,20 @@ - (void)layoutSubviews [self.wx_component layoutDidFinish]; } +- (void)setContentOffset:(CGPoint)contentOffset +{ + // FIXME: side effect caused by hooking _adjustContentOffsetIfNecessary. + // When UITableView is pulled down and finger releases,contentOffset will be set from -xxxx to about -0.5(greater than -0.5), then contentOffset will be reset to zero by calling _adjustContentOffsetIfNecessary. + // So hooking _adjustContentOffsetIfNecessary will always cause remaining 1px space between list's top and navigator. + // Demo: http://dotwe.org/895630945793a9a044e49abe39cbb77f + // Have to reset contentOffset to zero manually here. + if (fabs(contentOffset.y) < 0.5) { + contentOffset.y = 0; + } + + [super setContentOffset:contentOffset]; +} + @end @interface WXHeaderComponent : WXComponent @@ -603,7 +617,11 @@ - (void)fixFlicker { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - //(ง •̀_•́)ง┻━┻ Stupid scoll view, always reset content offset to zero after insert cells, any other more elegant way? + // FIXME:(ง •̀_•́)ง┻━┻ Stupid scoll view, always reset content offset to zero by calling _adjustContentOffsetIfNecessary after insert cells. + // So if you pull down list while list is rendering, the list will be flickering. + // Demo: + // Have to hook _adjustContentOffsetIfNecessary here. + // Any other more elegant way? NSString *a = @"ntOffsetIfNe"; NSString *b = @"adjustConte"; From 4f5276bbd8051da47037cda1bc16ae12077ff23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Fri, 23 Dec 2016 12:18:41 +0800 Subject: [PATCH 032/144] * [ios] fix crash after returning id type, need to copy here. --- ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m index d0a2daa75d..9c2e59c1ee 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m @@ -17,22 +17,23 @@ + (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation in return nil; } - char returnType[255]; - strcpy(returnType, [invocation.methodSignature methodReturnType]); + const char * returnType = [invocation.methodSignature methodReturnType]; JSValue *returnValue; switch (returnType[0] == _C_CONST ? returnType[1] : returnType[0]) { case _C_VOID: { // 1.void - returnValue = nil; + returnValue = [JSValue valueWithUndefinedInContext:context]; break; } case _C_ID: { // 2.id - id result; - [invocation getReturnValue:&result]; - returnValue = [JSValue valueWithObject:result inContext:context]; + void *value; + [invocation getReturnValue:&value]; + id object = (__bridge id)value; + + returnValue = [JSValue valueWithObject:[object copy] inContext:context]; break; } @@ -78,7 +79,7 @@ + (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation in case _C_CHARPTR: case _C_PTR: case _C_CLASS: { - returnValue = nil; + returnValue = [JSValue valueWithUndefinedInContext:context]; break; } } From e67826dcee3a878ba7517ff2b8e090b95552c4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Fri, 23 Dec 2016 12:19:42 +0800 Subject: [PATCH 033/144] * [ios] upgrade JSFM for sync return value. --- ios/sdk/WeexSDK/Resources/main.js | 14080 +++++++++++++++++++++++++++- 1 file changed, 14073 insertions(+), 7 deletions(-) diff --git a/ios/sdk/WeexSDK/Resources/main.js b/ios/sdk/WeexSDK/Resources/main.js index 0374b41414..ebd0d988b5 100644 --- a/ios/sdk/WeexSDK/Resources/main.js +++ b/ios/sdk/WeexSDK/Resources/main.js @@ -1,7 +1,14073 @@ -(this.nativeLog||function(s){console.log(s)})("START JS FRAMEWORK: 0.16.18 Build 20161103");this.getJSFMVersion=function(){return"0.16.18"};(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={exports:{},id:moduleId,loaded:false};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.loaded=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.p="";return __webpack_require__(0)})([function(module,exports,__webpack_require__){(function(global){"use strict";__webpack_require__(1);var methods=__webpack_require__(121);var _global=global,registerMethods=_global.registerMethods;registerMethods(methods)}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){"use strict";__webpack_require__(2)},function(module,exports,__webpack_require__){(function(global){"use strict";__webpack_require__(3);var _runtime=__webpack_require__(79);var _runtime2=_interopRequireDefault(_runtime);var _package=__webpack_require__(119);var _methods=__webpack_require__(120);var methods=_interopRequireWildcard(_methods);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key]}}newObj.default=obj;return newObj}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var native=_package.subversion.native,transformer=_package.subversion.transformer;var _loop=function _loop(methodName){global[methodName]=function(){var ret=_runtime2.default[methodName].apply(_runtime2.default,arguments);if(ret instanceof Error){console.error(ret.toString())}return ret}};for(var methodName in _runtime2.default){_loop(methodName)}global.frameworkVersion=native;global.transformerVersion=transformer;global.registerMethods(methods)}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.isPlainObject=exports.isObject=exports.toArray=exports.bind=exports.hasOwn=exports.remove=exports.def=exports.extend=undefined;var _utils=__webpack_require__(4);Object.defineProperty(exports,"extend",{enumerable:true,get:function get(){return _utils.extend}});Object.defineProperty(exports,"def",{enumerable:true,get:function get(){return _utils.def}});Object.defineProperty(exports,"remove",{enumerable:true,get:function get(){return _utils.remove}});Object.defineProperty(exports,"hasOwn",{enumerable:true,get:function get(){return _utils.hasOwn}});Object.defineProperty(exports,"bind",{enumerable:true,get:function get(){return _utils.bind}});Object.defineProperty(exports,"toArray",{enumerable:true,get:function get(){return _utils.toArray}});Object.defineProperty(exports,"isObject",{enumerable:true,get:function get(){return _utils.isObject}});Object.defineProperty(exports,"isPlainObject",{enumerable:true,get:function get(){return _utils.isPlainObject}});__webpack_require__(5);__webpack_require__(6);__webpack_require__(70);__webpack_require__(71);__webpack_require__(77);__webpack_require__(78)},function(module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};exports.extend=extend;exports.def=def;exports.remove=remove;exports.hasOwn=hasOwn;exports.bind=bind;exports.toArray=toArray;exports.isObject=isObject;exports.isPlainObject=isPlainObject;function extend(target){for(var _len=arguments.length,src=Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){src[_key-1]=arguments[_key]}if(typeof Object.assign==="function"){Object.assign.apply(Object,[target].concat(src))}else{var first=src.shift();for(var key in first){target[key]=first[key]}if(src.length){extend.apply(undefined,[target].concat(src))}}return target}function def(obj,key,val,enumerable){Object.defineProperty(obj,key,{value:val,enumerable:!!enumerable,writable:true,configurable:true})}function remove(arr,item){if(arr.length){var index=arr.indexOf(item);if(index>-1){return arr.splice(index,1)}}}var hasOwnProperty=Object.prototype.hasOwnProperty;function hasOwn(obj,key){return hasOwnProperty.call(obj,key)}function bind(fn,ctx){return function(a){var l=arguments.length;return l?l>1?fn.apply(ctx,arguments):fn.call(ctx,a):fn.call(ctx)}}function toArray(list,start){start=start||0;var i=list.length-start;var ret=new Array(i);while(i--){ret[i]=list[i+start]}return ret}function isObject(obj){return obj!==null&&(typeof obj==="undefined"?"undefined":_typeof(obj))==="object"}var toString=Object.prototype.toString;var OBJECT_STRING="[object Object]";function isPlainObject(obj){return toString.call(obj)===OBJECT_STRING}},function(module,exports){(function(global){"use strict";var _global=global,setTimeout=_global.setTimeout,setTimeoutNative=_global.setTimeoutNative;if(typeof setTimeout==="undefined"&&typeof setTimeoutNative==="function"){(function(){var timeoutMap={};var timeoutId=0;global.setTimeout=function(cb,time){timeoutMap[++timeoutId]=cb;setTimeoutNative(timeoutId.toString(),time)};global.setTimeoutCallback=function(id){if(typeof timeoutMap[id]==="function"){timeoutMap[id]();delete timeoutMap[id]}}})()}}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){(function(global){"use strict";var _global=global,WXEnvironment=_global.WXEnvironment;if(WXEnvironment&&WXEnvironment.platform==="iOS"){global.Promise=null}__webpack_require__(7);__webpack_require__(27);__webpack_require__(53);__webpack_require__(57)}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){"use strict";var classof=__webpack_require__(8),test={};test[__webpack_require__(10)("toStringTag")]="z";if(test+""!="[object z]"){__webpack_require__(14)(Object.prototype,"toString",function toString(){return"[object "+classof(this)+"]"},true)}},function(module,exports,__webpack_require__){"use strict";var cof=__webpack_require__(9),TAG=__webpack_require__(10)("toStringTag"),ARG=cof(function(){return arguments}())=="Arguments";var tryGet=function tryGet(it,key){try{return it[key]}catch(e){}};module.exports=function(it){var O,T,B;return it===undefined?"Undefined":it===null?"Null":typeof(T=tryGet(O=Object(it),TAG))=="string"?T:ARG?cof(O):(B=cof(O))=="Object"&&typeof O.callee=="function"?"Arguments":B}},function(module,exports){"use strict";var toString={}.toString;module.exports=function(it){return toString.call(it).slice(8,-1)}},function(module,exports,__webpack_require__){"use strict";var store=__webpack_require__(11)("wks"),uid=__webpack_require__(13),_Symbol=__webpack_require__(12).Symbol,USE_SYMBOL=typeof _Symbol=="function";var $exports=module.exports=function(name){return store[name]||(store[name]=USE_SYMBOL&&_Symbol[name]||(USE_SYMBOL?_Symbol:uid)("Symbol."+name))};$exports.store=store},function(module,exports,__webpack_require__){"use strict";var global=__webpack_require__(12),SHARED="__core-js_shared__",store=global[SHARED]||(global[SHARED]={});module.exports=function(key){return store[key]||(store[key]={})}},function(module,exports){"use strict";var global=module.exports=typeof window!="undefined"&&window.Math==Math?window:typeof self!="undefined"&&self.Math==Math?self:Function("return this")();if(typeof __g=="number")__g=global},function(module,exports){"use strict";var id=0,px=Math.random();module.exports=function(key){return"Symbol(".concat(key===undefined?"":key,")_",(++id+px).toString(36))}},function(module,exports,__webpack_require__){"use strict";var global=__webpack_require__(12),hide=__webpack_require__(15),has=__webpack_require__(25),SRC=__webpack_require__(13)("src"),TO_STRING="toString",$toString=Function[TO_STRING],TPL=(""+$toString).split(TO_STRING);__webpack_require__(26).inspectSource=function(it){return $toString.call(it)};(module.exports=function(O,key,val,safe){var isFunction=typeof val=="function";if(isFunction)has(val,"name")||hide(val,"name",key);if(O[key]===val)return;if(isFunction)has(val,SRC)||hide(val,SRC,O[key]?""+O[key]:TPL.join(String(key)));if(O===global){O[key]=val}else{if(!safe){delete O[key];hide(O,key,val)}else{if(O[key])O[key]=val;else hide(O,key,val)}}})(Function.prototype,TO_STRING,function toString(){return typeof this=="function"&&this[SRC]||$toString.call(this)})},function(module,exports,__webpack_require__){"use strict";var dP=__webpack_require__(16),createDesc=__webpack_require__(24);module.exports=__webpack_require__(20)?function(object,key,value){return dP.f(object,key,createDesc(1,value))}:function(object,key,value){object[key]=value;return object}},function(module,exports,__webpack_require__){"use strict";var anObject=__webpack_require__(17),IE8_DOM_DEFINE=__webpack_require__(19),toPrimitive=__webpack_require__(23),dP=Object.defineProperty;exports.f=__webpack_require__(20)?Object.defineProperty:function defineProperty(O,P,Attributes){anObject(O);P=toPrimitive(P,true);anObject(Attributes);if(IE8_DOM_DEFINE)try{return dP(O,P,Attributes)}catch(e){}if("get"in Attributes||"set"in Attributes)throw TypeError("Accessors not supported!");if("value"in Attributes)O[P]=Attributes.value;return O}},function(module,exports,__webpack_require__){"use strict";var isObject=__webpack_require__(18);module.exports=function(it){if(!isObject(it))throw TypeError(it+" is not an object!");return it}},function(module,exports){"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};module.exports=function(it){return(typeof it==="undefined"?"undefined":_typeof(it))==="object"?it!==null:typeof it==="function"}},function(module,exports,__webpack_require__){"use strict";module.exports=!__webpack_require__(20)&&!__webpack_require__(21)(function(){return Object.defineProperty(__webpack_require__(22)("div"),"a",{get:function get(){return 7}}).a!=7})},function(module,exports,__webpack_require__){"use strict";module.exports=!__webpack_require__(21)(function(){return Object.defineProperty({},"a",{get:function get(){return 7}}).a!=7})},function(module,exports){"use strict";module.exports=function(exec){try{return!!exec()}catch(e){return true}}},function(module,exports,__webpack_require__){"use strict";var isObject=__webpack_require__(18),document=__webpack_require__(12).document,is=isObject(document)&&isObject(document.createElement);module.exports=function(it){return is?document.createElement(it):{}}},function(module,exports,__webpack_require__){"use strict";var isObject=__webpack_require__(18);module.exports=function(it,S){if(!isObject(it))return it;var fn,val;if(S&&typeof(fn=it.toString)=="function"&&!isObject(val=fn.call(it)))return val;if(typeof(fn=it.valueOf)=="function"&&!isObject(val=fn.call(it)))return val;if(!S&&typeof(fn=it.toString)=="function"&&!isObject(val=fn.call(it)))return val;throw TypeError("Can't convert object to primitive value")}},function(module,exports){"use strict";module.exports=function(bitmap,value){return{enumerable:!(bitmap&1),configurable:!(bitmap&2),writable:!(bitmap&4),value:value}}},function(module,exports){"use strict";var hasOwnProperty={}.hasOwnProperty;module.exports=function(it,key){return hasOwnProperty.call(it,key)}},function(module,exports){"use strict";var core=module.exports={version:"2.4.0"};if(typeof __e=="number")__e=core},function(module,exports,__webpack_require__){"use strict";var $at=__webpack_require__(28)(true);__webpack_require__(31)(String,"String",function(iterated){this._t=String(iterated);this._i=0},function(){var O=this._t,index=this._i,point;if(index>=O.length)return{value:undefined,done:true};point=$at(O,index);this._i+=point.length;return{value:point,done:false}})},function(module,exports,__webpack_require__){"use strict";var toInteger=__webpack_require__(29),defined=__webpack_require__(30);module.exports=function(TO_STRING){return function(that,pos){var s=String(defined(that)),i=toInteger(pos),l=s.length,a,b;if(i<0||i>=l)return TO_STRING?"":undefined;a=s.charCodeAt(i);return a<55296||a>56319||i+1===l||(b=s.charCodeAt(i+1))<56320||b>57343?TO_STRING?s.charAt(i):a:TO_STRING?s.slice(i,i+2):(a-55296<<10)+(b-56320)+65536}}},function(module,exports){"use strict";var ceil=Math.ceil,floor=Math.floor;module.exports=function(it){return isNaN(it=+it)?0:(it>0?floor:ceil)(it)}},function(module,exports){"use strict";module.exports=function(it){if(it==undefined)throw TypeError("Can't call method on "+it);return it}},function(module,exports,__webpack_require__){"use strict";var LIBRARY=__webpack_require__(32),$export=__webpack_require__(33),redefine=__webpack_require__(14),hide=__webpack_require__(15),has=__webpack_require__(25),Iterators=__webpack_require__(36),$iterCreate=__webpack_require__(37),setToStringTag=__webpack_require__(50),getPrototypeOf=__webpack_require__(51),ITERATOR=__webpack_require__(10)("iterator"),BUGGY=!([].keys&&"next"in[].keys()),FF_ITERATOR="@@iterator",KEYS="keys",VALUES="values";var returnThis=function returnThis(){return this};module.exports=function(Base,NAME,Constructor,next,DEFAULT,IS_SET,FORCED){$iterCreate(Constructor,NAME,next);var getMethod=function getMethod(kind){if(!BUGGY&&kind in proto)return proto[kind];switch(kind){case KEYS:return function keys(){return new Constructor(this,kind)};case VALUES:return function values(){return new Constructor(this,kind)}}return function entries(){return new Constructor(this,kind)}};var TAG=NAME+" Iterator",DEF_VALUES=DEFAULT==VALUES,VALUES_BUG=false,proto=Base.prototype,$native=proto[ITERATOR]||proto[FF_ITERATOR]||DEFAULT&&proto[DEFAULT],$default=$native||getMethod(DEFAULT),$entries=DEFAULT?!DEF_VALUES?$default:getMethod("entries"):undefined,$anyNative=NAME=="Array"?proto.entries||$native:$native,methods,key,IteratorPrototype;if($anyNative){IteratorPrototype=getPrototypeOf($anyNative.call(new Base));if(IteratorPrototype!==Object.prototype){setToStringTag(IteratorPrototype,TAG,true);if(!LIBRARY&&!has(IteratorPrototype,ITERATOR))hide(IteratorPrototype,ITERATOR,returnThis)}}if(DEF_VALUES&&$native&&$native.name!==VALUES){VALUES_BUG=true;$default=function values(){return $native.call(this)}}if((!LIBRARY||FORCED)&&(BUGGY||VALUES_BUG||!proto[ITERATOR])){hide(proto,ITERATOR,$default)}Iterators[NAME]=$default;Iterators[TAG]=returnThis;if(DEFAULT){methods={values:DEF_VALUES?$default:getMethod(VALUES),keys:IS_SET?$default:getMethod(KEYS),entries:$entries};if(FORCED)for(key in methods){if(!(key in proto))redefine(proto,key,methods[key])}else $export($export.P+$export.F*(BUGGY||VALUES_BUG),NAME,methods)}return methods}},function(module,exports){"use strict";module.exports=false},function(module,exports,__webpack_require__){"use strict";var global=__webpack_require__(12),core=__webpack_require__(26),hide=__webpack_require__(15),redefine=__webpack_require__(14),ctx=__webpack_require__(34),PROTOTYPE="prototype";var $export=function $export(type,name,source){var IS_FORCED=type&$export.F,IS_GLOBAL=type&$export.G,IS_STATIC=type&$export.S,IS_PROTO=type&$export.P,IS_BIND=type&$export.B,target=IS_GLOBAL?global:IS_STATIC?global[name]||(global[name]={}):(global[name]||{})[PROTOTYPE],exports=IS_GLOBAL?core:core[name]||(core[name]={}),expProto=exports[PROTOTYPE]||(exports[PROTOTYPE]={}),key,own,out,exp;if(IS_GLOBAL)source=name;for(key in source){own=!IS_FORCED&&target&&target[key]!==undefined;out=(own?target:source)[key];exp=IS_BIND&&own?ctx(out,global):IS_PROTO&&typeof out=="function"?ctx(Function.call,out):out;if(target)redefine(target,key,out,type&$export.U);if(exports[key]!=out)hide(exports,key,exp);if(IS_PROTO&&expProto[key]!=out)expProto[key]=out}};global.core=core;$export.F=1;$export.G=2;$export.S=4;$export.P=8;$export.B=16;$export.W=32;$export.U=64;$export.R=128;module.exports=$export},function(module,exports,__webpack_require__){"use strict";var aFunction=__webpack_require__(35);module.exports=function(fn,that,length){aFunction(fn);if(that===undefined)return fn;switch(length){case 1:return function(a){return fn.call(that,a)};case 2:return function(a,b){return fn.call(that,a,b)};case 3:return function(a,b,c){return fn.call(that,a,b,c)}}return function(){return fn.apply(that,arguments)}}},function(module,exports){"use strict";module.exports=function(it){if(typeof it!="function")throw TypeError(it+" is not a function!");return it}},function(module,exports){"use strict";module.exports={}},function(module,exports,__webpack_require__){"use strict";var create=__webpack_require__(38),descriptor=__webpack_require__(24),setToStringTag=__webpack_require__(50),IteratorPrototype={};__webpack_require__(15)(IteratorPrototype,__webpack_require__(10)("iterator"),function(){return this});module.exports=function(Constructor,NAME,next){Constructor.prototype=create(IteratorPrototype,{next:descriptor(1,next)});setToStringTag(Constructor,NAME+" Iterator")}},function(module,exports,__webpack_require__){"use strict";var anObject=__webpack_require__(17),dPs=__webpack_require__(39),enumBugKeys=__webpack_require__(48),IE_PROTO=__webpack_require__(47)("IE_PROTO"),Empty=function Empty(){},PROTOTYPE="prototype";var _createDict=function createDict(){var iframe=__webpack_require__(22)("iframe"),i=enumBugKeys.length,lt="<",gt=">",iframeDocument;iframe.style.display="none";__webpack_require__(49).appendChild(iframe);iframe.src="javascript:";iframeDocument=iframe.contentWindow.document;iframeDocument.open();iframeDocument.write(lt+"script"+gt+"document.F=Object"+lt+"/script"+gt);iframeDocument.close();_createDict=iframeDocument.F;while(i--){delete _createDict[PROTOTYPE][enumBugKeys[i]]}return _createDict()};module.exports=Object.create||function create(O,Properties){var result;if(O!==null){Empty[PROTOTYPE]=anObject(O);result=new Empty;Empty[PROTOTYPE]=null;result[IE_PROTO]=O}else result=_createDict();return Properties===undefined?result:dPs(result,Properties)}},function(module,exports,__webpack_require__){"use strict";var dP=__webpack_require__(16),anObject=__webpack_require__(17),getKeys=__webpack_require__(40);module.exports=__webpack_require__(20)?Object.defineProperties:function defineProperties(O,Properties){anObject(O);var keys=getKeys(Properties),length=keys.length,i=0,P;while(length>i){dP.f(O,P=keys[i++],Properties[P])}return O}},function(module,exports,__webpack_require__){"use strict";var $keys=__webpack_require__(41),enumBugKeys=__webpack_require__(48);module.exports=Object.keys||function keys(O){return $keys(O,enumBugKeys)}},function(module,exports,__webpack_require__){"use strict";var has=__webpack_require__(25),toIObject=__webpack_require__(42),arrayIndexOf=__webpack_require__(44)(false),IE_PROTO=__webpack_require__(47)("IE_PROTO");module.exports=function(object,names){var O=toIObject(object),i=0,result=[],key;for(key in O){if(key!=IE_PROTO)has(O,key)&&result.push(key)}while(names.length>i){if(has(O,key=names[i++])){~arrayIndexOf(result,key)||result.push(key)}}return result}},function(module,exports,__webpack_require__){"use strict";var IObject=__webpack_require__(43),defined=__webpack_require__(30);module.exports=function(it){return IObject(defined(it))}},function(module,exports,__webpack_require__){"use strict";var cof=__webpack_require__(9);module.exports=Object("z").propertyIsEnumerable(0)?Object:function(it){return cof(it)=="String"?it.split(""):Object(it)}},function(module,exports,__webpack_require__){"use strict";var toIObject=__webpack_require__(42),toLength=__webpack_require__(45),toIndex=__webpack_require__(46);module.exports=function(IS_INCLUDES){return function($this,el,fromIndex){var O=toIObject($this),length=toLength(O.length),index=toIndex(fromIndex,length),value;if(IS_INCLUDES&&el!=el)while(length>index){value=O[index++];if(value!=value)return true}else for(;length>index;index++){if(IS_INCLUDES||index in O){if(O[index]===el)return IS_INCLUDES||index||0}}return!IS_INCLUDES&&-1}}},function(module,exports,__webpack_require__){"use strict";var toInteger=__webpack_require__(29),min=Math.min;module.exports=function(it){return it>0?min(toInteger(it),9007199254740991):0}},function(module,exports,__webpack_require__){"use strict";var toInteger=__webpack_require__(29),max=Math.max,min=Math.min;module.exports=function(index,length){index=toInteger(index);return index<0?max(index+length,0):min(index,length)}},function(module,exports,__webpack_require__){"use strict";var shared=__webpack_require__(11)("keys"),uid=__webpack_require__(13);module.exports=function(key){return shared[key]||(shared[key]=uid(key))}},function(module,exports){"use strict";module.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(module,exports,__webpack_require__){"use strict";module.exports=__webpack_require__(12).document&&document.documentElement},function(module,exports,__webpack_require__){"use strict";var def=__webpack_require__(16).f,has=__webpack_require__(25),TAG=__webpack_require__(10)("toStringTag");module.exports=function(it,tag,stat){if(it&&!has(it=stat?it:it.prototype,TAG))def(it,TAG,{configurable:true,value:tag})}},function(module,exports,__webpack_require__){"use strict";var has=__webpack_require__(25),toObject=__webpack_require__(52),IE_PROTO=__webpack_require__(47)("IE_PROTO"),ObjectProto=Object.prototype;module.exports=Object.getPrototypeOf||function(O){O=toObject(O);if(has(O,IE_PROTO))return O[IE_PROTO];if(typeof O.constructor=="function"&&O instanceof O.constructor){return O.constructor.prototype}return O instanceof Object?ObjectProto:null}},function(module,exports,__webpack_require__){"use strict";var defined=__webpack_require__(30);module.exports=function(it){return Object(defined(it))}},function(module,exports,__webpack_require__){"use strict";var $iterators=__webpack_require__(54),redefine=__webpack_require__(14),global=__webpack_require__(12),hide=__webpack_require__(15),Iterators=__webpack_require__(36),wks=__webpack_require__(10),ITERATOR=wks("iterator"),TO_STRING_TAG=wks("toStringTag"),ArrayValues=Iterators.Array;for(var collections=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],i=0;i<5;i++){var NAME=collections[i],Collection=global[NAME],proto=Collection&&Collection.prototype,key;if(proto){if(!proto[ITERATOR])hide(proto,ITERATOR,ArrayValues);if(!proto[TO_STRING_TAG])hide(proto,TO_STRING_TAG,NAME);Iterators[NAME]=ArrayValues;for(key in $iterators){if(!proto[key])redefine(proto,key,$iterators[key],true)}}}},function(module,exports,__webpack_require__){"use strict";var addToUnscopables=__webpack_require__(55),step=__webpack_require__(56),Iterators=__webpack_require__(36),toIObject=__webpack_require__(42);module.exports=__webpack_require__(31)(Array,"Array",function(iterated,kind){this._t=toIObject(iterated);this._i=0;this._k=kind},function(){var O=this._t,kind=this._k,index=this._i++;if(!O||index>=O.length){this._t=undefined;return step(1)}if(kind=="keys")return step(0,index);if(kind=="values")return step(0,O[index]);return step(0,[index,O[index]])},"values");Iterators.Arguments=Iterators.Array;addToUnscopables("keys");addToUnscopables("values");addToUnscopables("entries")},function(module,exports,__webpack_require__){"use strict";var UNSCOPABLES=__webpack_require__(10)("unscopables"),ArrayProto=Array.prototype;if(ArrayProto[UNSCOPABLES]==undefined)__webpack_require__(15)(ArrayProto,UNSCOPABLES,{});module.exports=function(key){ArrayProto[UNSCOPABLES][key]=true}},function(module,exports){"use strict";module.exports=function(done,value){return{value:value,done:!!done}}},function(module,exports,__webpack_require__){"use strict";var LIBRARY=__webpack_require__(32),global=__webpack_require__(12),ctx=__webpack_require__(34),classof=__webpack_require__(8),$export=__webpack_require__(33),isObject=__webpack_require__(18),aFunction=__webpack_require__(35),anInstance=__webpack_require__(58),forOf=__webpack_require__(59),speciesConstructor=__webpack_require__(63),task=__webpack_require__(64).set,microtask=__webpack_require__(66)(),PROMISE="Promise",TypeError=global.TypeError,process=global.process,$Promise=global[PROMISE],process=global.process,isNode=classof(process)=="process",empty=function empty(){},Internal,GenericPromiseCapability,Wrapper;var USE_NATIVE=!!function(){try{var promise=$Promise.resolve(1),FakePromise=(promise.constructor={})[__webpack_require__(10)("species")]=function(exec){exec(empty,empty)};return(isNode||typeof PromiseRejectionEvent=="function")&&promise.then(empty)instanceof FakePromise}catch(e){}}();var sameConstructor=function sameConstructor(a,b){return a===b||a===$Promise&&b===Wrapper};var isThenable=function isThenable(it){var then;return isObject(it)&&typeof(then=it.then)=="function"?then:false};var newPromiseCapability=function newPromiseCapability(C){return sameConstructor($Promise,C)?new PromiseCapability(C):new GenericPromiseCapability(C)};var PromiseCapability=GenericPromiseCapability=function GenericPromiseCapability(C){var resolve,reject;this.promise=new C(function($$resolve,$$reject){if(resolve!==undefined||reject!==undefined)throw TypeError("Bad Promise constructor");resolve=$$resolve;reject=$$reject});this.resolve=aFunction(resolve);this.reject=aFunction(reject)};var perform=function perform(exec){try{exec()}catch(e){return{error:e}}};var notify=function notify(promise,isReject){if(promise._n)return;promise._n=true;var chain=promise._c;microtask(function(){var value=promise._v,ok=promise._s==1,i=0;var run=function run(reaction){var handler=ok?reaction.ok:reaction.fail,resolve=reaction.resolve,reject=reaction.reject,domain=reaction.domain,result,then;try{if(handler){if(!ok){if(promise._h==2)onHandleUnhandled(promise);promise._h=1}if(handler===true)result=value;else{if(domain)domain.enter();result=handler(value);if(domain)domain.exit()}if(result===reaction.promise){reject(TypeError("Promise-chain cycle"))}else if(then=isThenable(result)){then.call(result,resolve,reject)}else resolve(result)}else reject(value)}catch(e){reject(e)}};while(chain.length>i){run(chain[i++])}promise._c=[];promise._n=false;if(isReject&&!promise._h)onUnhandled(promise)})};var onUnhandled=function onUnhandled(promise){task.call(global,function(){var value=promise._v,abrupt,handler,console;if(isUnhandled(promise)){abrupt=perform(function(){if(isNode){process.emit("unhandledRejection",value,promise)}else if(handler=global.onunhandledrejection){handler({promise:promise,reason:value})}else if((console=global.console)&&console.error){console.error("Unhandled promise rejection",value)}});promise._h=isNode||isUnhandled(promise)?2:1}promise._a=undefined;if(abrupt)throw abrupt.error})};var isUnhandled=function isUnhandled(promise){if(promise._h==1)return false;var chain=promise._a||promise._c,i=0,reaction;while(chain.length>i){reaction=chain[i++];if(reaction.fail||!isUnhandled(reaction.promise))return false}return true};var onHandleUnhandled=function onHandleUnhandled(promise){task.call(global,function(){var handler;if(isNode){process.emit("rejectionHandled",promise)}else if(handler=global.onrejectionhandled){handler({promise:promise,reason:promise._v})}})};var $reject=function $reject(value){var promise=this;if(promise._d)return;promise._d=true;promise=promise._w||promise;promise._v=value;promise._s=2;if(!promise._a)promise._a=promise._c.slice();notify(promise,true)};var $resolve=function $resolve(value){var promise=this,then;if(promise._d)return;promise._d=true;promise=promise._w||promise;try{if(promise===value)throw TypeError("Promise can't be resolved itself");if(then=isThenable(value)){microtask(function(){var wrapper={_w:promise,_d:false};try{then.call(value,ctx($resolve,wrapper,1),ctx($reject,wrapper,1))}catch(e){$reject.call(wrapper,e)}})}else{promise._v=value;promise._s=1;notify(promise,false)}}catch(e){$reject.call({_w:promise,_d:false},e)}};if(!USE_NATIVE){$Promise=function Promise(executor){anInstance(this,$Promise,PROMISE,"_h");aFunction(executor);Internal.call(this);try{executor(ctx($resolve,this,1),ctx($reject,this,1))}catch(err){$reject.call(this,err)}};Internal=function Promise(executor){this._c=[];this._a=undefined;this._s=0;this._d=false;this._v=undefined;this._h=0;this._n=false};Internal.prototype=__webpack_require__(67)($Promise.prototype,{then:function then(onFulfilled,onRejected){var reaction=newPromiseCapability(speciesConstructor(this,$Promise));reaction.ok=typeof onFulfilled=="function"?onFulfilled:true;reaction.fail=typeof onRejected=="function"&&onRejected;reaction.domain=isNode?process.domain:undefined;this._c.push(reaction);if(this._a)this._a.push(reaction);if(this._s)notify(this,false);return reaction.promise},catch:function _catch(onRejected){return this.then(undefined,onRejected)}});PromiseCapability=function PromiseCapability(){var promise=new Internal;this.promise=promise;this.resolve=ctx($resolve,promise,1);this.reject=ctx($reject,promise,1)}}$export($export.G+$export.W+$export.F*!USE_NATIVE,{Promise:$Promise});__webpack_require__(50)($Promise,PROMISE);__webpack_require__(68)(PROMISE);Wrapper=__webpack_require__(26)[PROMISE];$export($export.S+$export.F*!USE_NATIVE,PROMISE,{reject:function reject(r){var capability=newPromiseCapability(this),$$reject=capability.reject;$$reject(r);return capability.promise}});$export($export.S+$export.F*(LIBRARY||!USE_NATIVE),PROMISE,{resolve:function resolve(x){if(x instanceof $Promise&&sameConstructor(x.constructor,this))return x;var capability=newPromiseCapability(this),$$resolve=capability.resolve;$$resolve(x);return capability.promise}});$export($export.S+$export.F*!(USE_NATIVE&&__webpack_require__(69)(function(iter){$Promise.all(iter)["catch"](empty)})),PROMISE,{all:function all(iterable){var C=this,capability=newPromiseCapability(C),resolve=capability.resolve,reject=capability.reject;var abrupt=perform(function(){var values=[],index=0,remaining=1;forOf(iterable,false,function(promise){var $index=index++,alreadyCalled=false;values.push(undefined);remaining++;C.resolve(promise).then(function(value){if(alreadyCalled)return;alreadyCalled=true;values[$index]=value;--remaining||resolve(values)},reject)});--remaining||resolve(values)});if(abrupt)reject(abrupt.error);return capability.promise},race:function race(iterable){var C=this,capability=newPromiseCapability(C),reject=capability.reject;var abrupt=perform(function(){forOf(iterable,false,function(promise){C.resolve(promise).then(capability.resolve,reject)})});if(abrupt)reject(abrupt.error);return capability.promise}})},function(module,exports){"use strict";module.exports=function(it,Constructor,name,forbiddenField){if(!(it instanceof Constructor)||forbiddenField!==undefined&&forbiddenField in it){throw TypeError(name+": incorrect invocation!")}return it}},function(module,exports,__webpack_require__){"use strict";var ctx=__webpack_require__(34),call=__webpack_require__(60),isArrayIter=__webpack_require__(61),anObject=__webpack_require__(17),toLength=__webpack_require__(45),getIterFn=__webpack_require__(62),BREAK={},RETURN={};var _exports=module.exports=function(iterable,entries,fn,that,ITERATOR){var iterFn=ITERATOR?function(){return iterable}:getIterFn(iterable),f=ctx(fn,that,entries?2:1),index=0,length,step,iterator,result;if(typeof iterFn!="function")throw TypeError(iterable+" is not iterable!");if(isArrayIter(iterFn))for(length=toLength(iterable.length);length>index;index++){result=entries?f(anObject(step=iterable[index])[0],step[1]):f(iterable[index]);if(result===BREAK||result===RETURN)return result}else for(iterator=iterFn.call(iterable);!(step=iterator.next()).done;){result=call(iterator,f,step.value,entries);if(result===BREAK||result===RETURN)return result}};_exports.BREAK=BREAK;_exports.RETURN=RETURN},function(module,exports,__webpack_require__){ -"use strict";var anObject=__webpack_require__(17);module.exports=function(iterator,fn,value,entries){try{return entries?fn(anObject(value)[0],value[1]):fn(value)}catch(e){var ret=iterator["return"];if(ret!==undefined)anObject(ret.call(iterator));throw e}}},function(module,exports,__webpack_require__){"use strict";var Iterators=__webpack_require__(36),ITERATOR=__webpack_require__(10)("iterator"),ArrayProto=Array.prototype;module.exports=function(it){return it!==undefined&&(Iterators.Array===it||ArrayProto[ITERATOR]===it)}},function(module,exports,__webpack_require__){"use strict";var classof=__webpack_require__(8),ITERATOR=__webpack_require__(10)("iterator"),Iterators=__webpack_require__(36);module.exports=__webpack_require__(26).getIteratorMethod=function(it){if(it!=undefined)return it[ITERATOR]||it["@@iterator"]||Iterators[classof(it)]}},function(module,exports,__webpack_require__){"use strict";var anObject=__webpack_require__(17),aFunction=__webpack_require__(35),SPECIES=__webpack_require__(10)("species");module.exports=function(O,D){var C=anObject(O).constructor,S;return C===undefined||(S=anObject(C)[SPECIES])==undefined?D:aFunction(S)}},function(module,exports,__webpack_require__){"use strict";var ctx=__webpack_require__(34),invoke=__webpack_require__(65),html=__webpack_require__(49),cel=__webpack_require__(22),global=__webpack_require__(12),process=global.process,setTask=global.setImmediate,clearTask=global.clearImmediate,MessageChannel=global.MessageChannel,counter=0,queue={},ONREADYSTATECHANGE="onreadystatechange",defer,channel,port;var run=function run(){var id=+this;if(queue.hasOwnProperty(id)){var fn=queue[id];delete queue[id];fn()}};var listener=function listener(event){run.call(event.data)};if(!setTask||!clearTask){setTask=function setImmediate(fn){var args=[],i=1;while(arguments.length>i){args.push(arguments[i++])}queue[++counter]=function(){invoke(typeof fn=="function"?fn:Function(fn),args)};defer(counter);return counter};clearTask=function clearImmediate(id){delete queue[id]};if(__webpack_require__(9)(process)=="process"){defer=function defer(id){process.nextTick(ctx(run,id,1))}}else if(MessageChannel){channel=new MessageChannel;port=channel.port2;channel.port1.onmessage=listener;defer=ctx(port.postMessage,port,1)}else if(global.addEventListener&&typeof postMessage=="function"&&!global.importScripts){defer=function defer(id){global.postMessage(id+"","*")};global.addEventListener("message",listener,false)}else if(ONREADYSTATECHANGE in cel("script")){defer=function defer(id){html.appendChild(cel("script"))[ONREADYSTATECHANGE]=function(){html.removeChild(this);run.call(id)}}}else{defer=function defer(id){setTimeout(ctx(run,id,1),0)}}}module.exports={set:setTask,clear:clearTask}},function(module,exports){"use strict";module.exports=function(fn,args,that){var un=that===undefined;switch(args.length){case 0:return un?fn():fn.call(that);case 1:return un?fn(args[0]):fn.call(that,args[0]);case 2:return un?fn(args[0],args[1]):fn.call(that,args[0],args[1]);case 3:return un?fn(args[0],args[1],args[2]):fn.call(that,args[0],args[1],args[2]);case 4:return un?fn(args[0],args[1],args[2],args[3]):fn.call(that,args[0],args[1],args[2],args[3])}return fn.apply(that,args)}},function(module,exports,__webpack_require__){"use strict";var global=__webpack_require__(12),macrotask=__webpack_require__(64).set,Observer=global.MutationObserver||global.WebKitMutationObserver,process=global.process,Promise=global.Promise,isNode=__webpack_require__(9)(process)=="process";module.exports=function(){var head,last,notify;var flush=function flush(){var parent,fn;if(isNode&&(parent=process.domain))parent.exit();while(head){fn=head.fn;head=head.next;try{fn()}catch(e){if(head)notify();else last=undefined;throw e}}last=undefined;if(parent)parent.enter()};if(isNode){notify=function notify(){process.nextTick(flush)}}else if(Observer){var toggle=true,node=document.createTextNode("");new Observer(flush).observe(node,{characterData:true});notify=function notify(){node.data=toggle=!toggle}}else if(Promise&&Promise.resolve){var promise=Promise.resolve();notify=function notify(){promise.then(flush)}}else{notify=function notify(){macrotask.call(global,flush)}}return function(fn){var task={fn:fn,next:undefined};if(last)last.next=task;if(!head){head=task;notify()}last=task}}},function(module,exports,__webpack_require__){"use strict";var redefine=__webpack_require__(14);module.exports=function(target,src,safe){for(var key in src){redefine(target,key,src[key],safe)}return target}},function(module,exports,__webpack_require__){"use strict";var global=__webpack_require__(12),dP=__webpack_require__(16),DESCRIPTORS=__webpack_require__(20),SPECIES=__webpack_require__(10)("species");module.exports=function(KEY){var C=global[KEY];if(DESCRIPTORS&&C&&!C[SPECIES])dP.f(C,SPECIES,{configurable:true,get:function get(){return this}})}},function(module,exports,__webpack_require__){"use strict";var ITERATOR=__webpack_require__(10)("iterator"),SAFE_CLOSING=false;try{var riter=[7][ITERATOR]();riter["return"]=function(){SAFE_CLOSING=true};Array.from(riter,function(){throw 2})}catch(e){}module.exports=function(exec,skipClosing){if(!skipClosing&&!SAFE_CLOSING)return false;var safe=false;try{var arr=[7],iter=arr[ITERATOR]();iter.next=function(){return{done:safe=true}};arr[ITERATOR]=function(){return iter};exec(arr)}catch(e){}return safe}},function(module,exports){(function(global){"use strict";function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);iindex){var S=IObject(arguments[index++]),keys=getSymbols?getKeys(S).concat(getSymbols(S)):getKeys(S),length=keys.length,j=0,key;while(length>j){if(isEnum.call(S,key=keys[j++]))T[key]=S[key]}}return T}:$assign},function(module,exports){"use strict";exports.f=Object.getOwnPropertySymbols},function(module,exports){"use strict";exports.f={}.propertyIsEnumerable},function(module,exports){"use strict";if(!Object.setPrototypeOf){Object.setPrototypeOf=function(Object,magic){var set;function setPrototypeOf(O,proto){set.call(O,proto);return O}try{set=Object.getOwnPropertyDescriptor(Object.prototype,magic).set;set.call({},null)}catch(e){if(Object.prototype!=={}[magic]||{__proto__:null}.__proto__===void 0){return}set=function set(proto){this[magic]=proto};setPrototypeOf.polyfill=setPrototypeOf(setPrototypeOf({},null),Object.prototype)instanceof Object}return setPrototypeOf}(Object,"__proto__")}},function(module,exports){"use strict";if(!Array.from){console.log("make polyfill");Array.from=function(){var toStr=Object.prototype.toString;var isCallable=function isCallable(fn){return typeof fn==="function"||toStr.call(fn)==="[object Function]"};var toInteger=function toInteger(value){var number=Number(value);if(isNaN(number)){return 0}if(number===0||!isFinite(number)){return number}return(number>0?1:-1)*Math.floor(Math.abs(number))};var maxSafeInteger=Math.pow(2,53)-1;var toLength=function toLength(value){var len=toInteger(value);return Math.min(Math.max(len,0),maxSafeInteger)};return function from(arrayLike){var C=this;var items=Object(arrayLike);if(arrayLike==null){throw new TypeError("Array.from requires an array-like object - not null or undefined")}var mapFn=arguments.length>1?arguments[1]:void undefined;var T;if(typeof mapFn!=="undefined"){if(!isCallable(mapFn)){throw new TypeError("Array.from: when provided, the second argument must be a function")}if(arguments.length>2){T=arguments[2]}}var len=toLength(items.length);var A=isCallable(C)?Object(new C(len)):new Array(len);var k=0;var kValue;while(k0||node.parentNode){return}var children=documentElement.children;var beforeIndex=children.indexOf(before);if(beforeIndex<0){children.push(node)}else{children.splice(beforeIndex,0,node)}if(node.nodeType===1){if(node.role==="body"){node.docId=doc.id;node.ownerDocument=doc;node.parentNode=documentElement;linkParent(node,documentElement)}else{node.children.forEach(function(child){child.parentNode=node});setBody(doc,node);node.docId=doc.id;node.ownerDocument=doc;linkParent(node,documentElement);delete doc.nodeMap[node.nodeId]}documentElement.pureChildren.push(node);doc.listener.createBody(node)}else{node.parentNode=documentElement;doc.nodeMap[node.ref]=node}}function setBody(doc,el){el.role="body";el.depth=1;delete doc.nodeMap[el.nodeId];el.ref="_root";doc.nodeMap._root=el;doc.body=el}Document.prototype.createBody=function(type,props){if(!this.body){var el=new Element(type,props);setBody(this,el)}return this.body};Document.prototype.createElement=function(tagName,props){return new Element(tagName,props)};Document.prototype.createComment=function(text){return new Comment(text)};Document.prototype.fireEvent=function(el,type,e,domChanges){if(!el){return}e=e||{};e.type=type;e.target=el;e.timestamp=Date.now();if(domChanges){updateElement(el,domChanges)}return el.fireEvent(type,e)};Document.prototype.getRef=function(ref){return this.nodeMap[ref]};function updateElement(el,changes){var attrs=changes.attrs||{};for(var name in attrs){el.setAttr(name,attrs[name],true)}var style=changes.style||{};for(var _name in style){el.setStyle(_name,style[_name],true)}}function Node(){this.nodeId=(nextNodeRef++).toString();this.ref=this.nodeId;this.children=[];this.pureChildren=[];this.parentNode=null;this.nextSibling=null;this.previousSibling=null}Node.prototype.destroy=function(){var doc=instanceMap[this.docId];if(doc){delete this.docId;delete doc.nodeMap[this.nodeId]}this.children.forEach(function(child){child.destroy()})};function Element(){var type=arguments.length>0&&arguments[0]!==undefined?arguments[0]:DEFAULT_TAG_NAME;var props=arguments[1];props=props||{};this.nodeType=1;this.nodeId=(nextNodeRef++).toString();this.ref=this.nodeId;this.type=type;this.attr=props.attr||{};this.classStyle=props.classStyle||{};this.style=props.style||{};this.event={};this.children=[];this.pureChildren=[]}Element.prototype=new Node;Element.prototype.appendChild=function(node){if(node.parentNode&&node.parentNode!==this){return}if(!node.parentNode){linkParent(node,this);insertIndex(node,this.children,this.children.length,true);if(this.docId){registerNode(this.docId,node)}if(node.nodeType===1){insertIndex(node,this.pureChildren,this.pureChildren.length);if(this.docId){var listener=instanceMap[this.docId].listener;return listener.addElement(node,this.ref,-1)}}}else{moveIndex(node,this.children,this.children.length,true);if(node.nodeType===1){var index=moveIndex(node,this.pureChildren,this.pureChildren.length);if(this.docId&&index>=0){var _listener=instanceMap[this.docId].listener;return _listener.moveElement(node.ref,this.ref,index)}}}};Element.prototype.insertBefore=function(node,before){if(node.parentNode&&node.parentNode!==this){return}if(node===before||node.nextSibling===before){return}if(!node.parentNode){linkParent(node,this);insertIndex(node,this.children,this.children.indexOf(before),true);if(this.docId){registerNode(this.docId,node)}if(node.nodeType===1){var pureBefore=nextElement(before);var index=insertIndex(node,this.pureChildren,pureBefore?this.pureChildren.indexOf(pureBefore):this.pureChildren.length);if(this.docId){var listener=instanceMap[this.docId].listener;return listener.addElement(node,this.ref,index)}}}else{moveIndex(node,this.children,this.children.indexOf(before),true);if(node.nodeType===1){var _pureBefore=nextElement(before);var _index=moveIndex(node,this.pureChildren,_pureBefore?this.pureChildren.indexOf(_pureBefore):this.pureChildren.length);if(this.docId&&_index>=0){var _listener2=instanceMap[this.docId].listener;return _listener2.moveElement(node.ref,this.ref,_index)}}}};Element.prototype.insertAfter=function(node,after){if(node.parentNode&&node.parentNode!==this){return}if(node===after||node.previousSibling===after){return}if(!node.parentNode){linkParent(node,this);insertIndex(node,this.children,this.children.indexOf(after)+1,true);if(this.docId){registerNode(this.docId,node)}if(node.nodeType===1){var index=insertIndex(node,this.pureChildren,this.pureChildren.indexOf(previousElement(after))+1);if(this.docId){var listener=instanceMap[this.docId].listener;return listener.addElement(node,this.ref,index)}}}else{moveIndex(node,this.children,this.children.indexOf(after)+1,true);if(node.nodeType===1){var _index2=moveIndex(node,this.pureChildren,this.pureChildren.indexOf(previousElement(after))+1);if(this.docId&&_index2>=0){var _listener3=instanceMap[this.docId].listener;return _listener3.moveElement(node.ref,this.ref,_index2)}}}};Element.prototype.removeChild=function(node,preserved){if(node.parentNode){removeIndex(node,this.children,true);if(node.nodeType===1){removeIndex(node,this.pureChildren);if(this.docId){var listener=instanceMap[this.docId].listener;listener.removeElement(node.ref)}}}if(!preserved){node.destroy()}};Element.prototype.clear=function(){var _this2=this;if(this.docId){(function(){var listener=instanceMap[_this2.docId].listener;_this2.pureChildren.forEach(function(node){listener.removeElement(node.ref)})})()}this.children.forEach(function(node){node.destroy()});this.children.length=0;this.pureChildren.length=0};function nextElement(node){while(node){if(node.nodeType===1){return node}node=node.nextSibling}}function previousElement(node){while(node){if(node.nodeType===1){return node}node=node.previousSibling}}function linkParent(node,parent){node.parentNode=parent;if(parent.docId){node.docId=parent.docId;node.ownerDocument=parent.ownerDocument;node.ownerDocument.nodeMap[node.nodeId]=node;node.depth=parent.depth+1}node.children.forEach(function(child){linkParent(child,node)})}function registerNode(docId,node){var doc=instanceMap[docId];doc.nodeMap[node.nodeId]=node}function insertIndex(target,list,newIndex,changeSibling){if(newIndex<0){newIndex=0}var before=list[newIndex-1];var after=list[newIndex];list.splice(newIndex,0,target);if(changeSibling){before&&(before.nextSibling=target);target.previousSibling=before;target.nextSibling=after;after&&(after.previousSibling=target)}return newIndex}function moveIndex(target,list,newIndex,changeSibling){var index=list.indexOf(target);if(index<0){return-1}if(changeSibling){var before=list[index-1];var after=list[index+1];before&&(before.nextSibling=after);after&&(after.previousSibling=before)}list.splice(index,1);var newIndexAfter=newIndex;if(index<=newIndex){newIndexAfter=newIndex-1}var beforeNew=list[newIndexAfter-1];var afterNew=list[newIndexAfter];list.splice(newIndexAfter,0,target);if(changeSibling){beforeNew&&(beforeNew.nextSibling=target);target.previousSibling=beforeNew;target.nextSibling=afterNew;afterNew&&(afterNew.previousSibling=target)}if(index===newIndexAfter){return-1}return newIndex}function removeIndex(target,list,changeSibling){var index=list.indexOf(target);if(index<0){return}if(changeSibling){var before=list[index-1];var after=list[index+1];before&&(before.nextSibling=after);after&&(after.previousSibling=before)}list.splice(index,1)}Element.prototype.setAttr=function(key,value,silent){if(this.attr[key]===value&&silent!==false){return}this.attr[key]=value;if(!silent&&this.docId){var listener=instanceMap[this.docId].listener;listener.setAttr(this.ref,key,value)}};Element.prototype.setStyle=function(key,value,silent){if(this.style[key]===value&&silent!==false){return}this.style[key]=value;if(!silent&&this.docId){var listener=instanceMap[this.docId].listener;listener.setStyle(this.ref,key,value)}};Element.prototype.resetClassStyle=function(){for(var key in this.classStyle){this.classStyle[key]=""}};Element.prototype.setClassStyle=function(classStyle){this.resetClassStyle();(0,_utils.extend)(this.classStyle,classStyle);if(this.docId){var listener=instanceMap[this.docId].listener;listener.setStyles(this.ref,this.toStyle())}};Element.prototype.addEvent=function(type,handler){if(!this.event[type]){this.event[type]=handler;if(this.docId){var listener=instanceMap[this.docId].listener;listener.addEvent(this.ref,type)}}};Element.prototype.removeEvent=function(type){if(this.event[type]){delete this.event[type];if(this.docId){var listener=instanceMap[this.docId].listener;listener.removeEvent(this.ref,type)}}};Element.prototype.fireEvent=function(type,e){var handler=this.event[type];if(handler){return handler.call(this,e)}};Element.prototype.toStyle=function(){return(0,_utils.extend)({},this.classStyle,this.style)};Element.prototype.toJSON=function(){var result={ref:this.ref.toString(),type:this.type,attr:this.attr,style:this.toStyle()};var event=Object.keys(this.event);if(event.length){result.event=event}if(this.pureChildren.length){result.children=this.pureChildren.map(function(child){return child.toJSON()})}return result};Element.prototype.toString=function(){return"<"+this.type+" attr="+JSON.stringify(this.attr)+" style="+JSON.stringify(this.toStyle())+">"+this.pureChildren.map(function(child){return child.toString()}).join("")+""};function Comment(value){this.nodeType=8;this.nodeId=(nextNodeRef++).toString();this.ref=this.nodeId;this.type="comment";this.value=value;this.children=[];this.pureChildren=[]}Comment.prototype=new Node;Comment.prototype.toString=function(){return""}},function(module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=Listener;exports.createAction=createAction;function Listener(id,handler){this.id=id;this.batched=false;this.updates=[];if(typeof handler==="function"){this.handler=handler}}Listener.prototype.createFinish=function(callback){var handler=this.handler;return handler([createAction("createFinish",[])],callback)};Listener.prototype.updateFinish=function(callback){var handler=this.handler;return handler([createAction("updateFinish",[])],callback)};Listener.prototype.refreshFinish=function(callback){var handler=this.handler;return handler([createAction("refreshFinish",[])],callback)};Listener.prototype.createBody=function(element){var body=element.toJSON();var children=body.children;delete body.children;var actions=[createAction("createBody",[body])];if(children){actions.push.apply(actions,children.map(function(child){return createAction("addElement",[body.ref,child,-1])}))}return this.addActions(actions)};Listener.prototype.addElement=function(element,ref,index){if(!(index>=0)){index=-1}return this.addActions(createAction("addElement",[ref,element.toJSON(),index]))};Listener.prototype.removeElement=function(ref){if(Array.isArray(ref)){var actions=ref.map(function(r){return createAction("removeElement",[r])});return this.addActions(actions)}return this.addActions(createAction("removeElement",[ref]))};Listener.prototype.moveElement=function(targetRef,parentRef,index){return this.addActions(createAction("moveElement",[targetRef,parentRef,index]))};Listener.prototype.setAttr=function(ref,key,value){var result={};result[key]=value;return this.addActions(createAction("updateAttrs",[ref,result]))};Listener.prototype.setStyle=function(ref,key,value){var result={};result[key]=value;return this.addActions(createAction("updateStyle",[ref,result]))};Listener.prototype.setStyles=function(ref,style){return this.addActions(createAction("updateStyle",[ref,style]))};Listener.prototype.addEvent=function(ref,type){return this.addActions(createAction("addEvent",[ref,type]))};Listener.prototype.removeEvent=function(ref,type){return this.addActions(createAction("removeEvent",[ref,type]))};Listener.prototype.handler=function(actions,cb){return cb&&cb()};Listener.prototype.addActions=function(actions){var updates=this.updates;var handler=this.handler;if(!Array.isArray(actions)){actions=[actions]}if(this.batched){updates.push.apply(updates,actions)}else{return handler(actions)}};function createAction(name,args){return{module:"dom",method:name,args:args}}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _weexRxFramework=__webpack_require__(83);var Rx=_interopRequireWildcard(_weexRxFramework);var _vanilla=__webpack_require__(85);var Vanilla=_interopRequireWildcard(_vanilla);var _default=__webpack_require__(86);var Weex=_interopRequireWildcard(_default);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key]}}newObj.default=obj;return newObj}}exports.default={Rx:Rx,Vanilla:Vanilla,Weex:Weex}},function(module,exports,__webpack_require__){(function(global){"use strict";var _typeof2=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};Object.defineProperty(exports,"__esModule",{value:true});var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break}}catch(err){_d=true;_e=err}finally{try{if(!_n&&_i["return"])_i["return"]()}finally{if(_d)throw _e}}return _arr}return function(arr,i){if(Array.isArray(arr)){return arr}else if(Symbol.iterator in Object(arr)){return sliceIterator(arr,i)}else{throw new TypeError("Invalid attempt to destructure non-iterable instance")}}}();var _typeof=typeof Symbol==="function"&&_typeof2(Symbol.iterator)==="symbol"?function(obj){return typeof obj==="undefined"?"undefined":_typeof2(obj)}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol?"symbol":typeof obj==="undefined"?"undefined":_typeof2(obj)};exports.getInstance=getInstance;exports.init=init;exports.registerComponents=registerComponents;exports.registerMethods=registerMethods;exports.registerModules=registerModules;exports.createInstance=createInstance;exports.refreshInstance=refreshInstance;exports.destroyInstance=destroyInstance;exports.getRoot=getRoot;exports.receiveTasks=receiveTasks;var _builtinModulesCode=__webpack_require__(84);var _builtinModulesCode2=_interopRequireDefault(_builtinModulesCode);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i2?a-2:0),d=2;d2?f-2:0),c=2;c=c,e.isDesktop=r=!/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent)),e.isWeex=o,e.isWeb=t,e.isWidescreen=i,e.isDesktop=r,e}(),i=function(e){"use strict";return e=t}(),o.exports=i});\ndefine("kg/rx-promise/index",["kg/rx-env/index"],function(e,t,n){var o,r,i,u=e("kg/rx-env/index");o=function(e){function t(){}function n(e,t){return function(){e.apply(t,arguments)}}function o(e){if("object"!==d(this))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],l(e,this)}function r(e,t){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(t):(e._handled=!0,void a(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null===n)return void(1===e._state?i:u)(t.promise,e._value);var o;try{o=n(e._value)}catch(r){return void u(t.promise,r)}i(t.promise,o)}))}function i(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"===("undefined"==typeof t?"undefined":d(t))||"function"==typeof t)){var r=t.then;if(t instanceof o)return e._state=3,e._value=t,void f(e);if("function"==typeof r)return void l(n(r,t),e)}e._state=1,e._value=t,f(e)}catch(i){u(e,i)}}function u(e,t){e._state=2,e._value=t,f(e)}function f(e){2===e._state&&0===e._deferreds.length&&a(function(){e._handled||p(e._value)});for(var t=0,n=e._deferreds.length;t-1?e:t}function p(t,e){e=e||{};var r=e.body;if(p.prototype.isPrototypeOf(t)){if(t.bodyUsed)throw new TypeError("Already read");this.url=t.url,this.credentials=t.credentials,e.headers||(this.headers=new o(t.headers)),this.method=t.method,this.mode=t.mode,r||(r=t._bodyInit,t.bodyUsed=!0)}else this.url=t;if(this.credentials=e.credentials||this.credentials||"omit",!e.headers&&this.headers||(this.headers=new o(e.headers)),this.method=c(e.method||this.method||"GET"),this.mode=e.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&r)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(r,e)}function y(t){var e=new FormData;return t.trim().split("&").forEach(function(t){if(t){var r=t.split("="),n=r.shift().replace(/\\+/g," "),o=r.join("=").replace(/\\+/g," ");e.append(decodeURIComponent(n),decodeURIComponent(o))}}),e}function m(t){var e=new o,r=t.getAllResponseHeaders().trim().split("\\n");return r.forEach(function(t){var r=t.trim().split(":"),n=r.shift().trim(),o=r.join(":").trim();e.append(n,o)}),e}function b(t,e){e||(e={}),this._initBody(t,e),this.type="default",this.status=e.status,this.ok=this.status>=200&&this.status<300,this.statusText=e.statusText,this.headers=e.headers instanceof o?e.headers:new o(e.headers),this.url=e.url||""}t={},Object.defineProperty(t,"__esModule",{value:!0});var w=a,v=e(w),T=u,x="undefined"!=typeof x?x:"undefined"!=typeof global?global:"undefined"!=typeof window?window:{};o.prototype.append=function(t,e){t=r(t),e=n(e);var o=this.map[t];o||(o=[],this.map[t]=o),o.push(e)},o.prototype["delete"]=function(t){delete this.map[r(t)]},o.prototype.get=function(t){var e=this.map[r(t)];return e?e[0]:null},o.prototype.getAll=function(t){return this.map[r(t)]||[]},o.prototype.has=function(t){return this.map.hasOwnProperty(r(t))},o.prototype.set=function(t,e){this.map[r(t)]=[n(e)]},o.prototype.forEach=function(t,e){Object.getOwnPropertyNames(this.map).forEach(function(r){this.map[r].forEach(function(n){t.call(e,n,r,this)},this)},this)};var _={blob:"FileReader"in x&&"Blob"in x&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in x,arrayBuffer:"ArrayBuffer"in x},g=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];p.prototype.clone=function(){return new p(this)},h.call(p.prototype),h.call(b.prototype),b.prototype.clone=function(){return new b(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new o(this.headers),url:this.url})},b.error=function(){var t=new b(null,{status:0,statusText:""});return t.type="error",t};var E=[301,302,303,307,308];b.redirect=function(t,e){if(E.indexOf(e)===-1)throw new RangeError("Invalid status code");return new b(null,{status:e,headers:{location:t}})};var O=function(t,e){return new v["default"](function(r,n){var o;if(o=p.prototype.isPrototypeOf(t)&&!e?t:new p(t,e),T.isWeex){var s=d;if(s.fetch){var i={url:o.url,method:o.method,header:o.headers&&o.headers.originHeaders,body:o.body};i.type=e&&e.dataType?e.dataType:"json",s.fetch(i,function(t){try{"string"==typeof t&&(t=JSON.parse(t));var e="string"==typeof t.data?t.data:JSON.stringify(t.data),s=new b(e,{status:t.status,statusText:t.statusText,headers:t.headers,url:o.url});r(s)}catch(i){n(i)}},function(t){})}else s.sendHttp&&s.sendHttp({url:o.url,method:o.method,header:o.headers&&o.headers.originHeaders,body:o.body},function(t){r(new b(t,{status:200}))})}else{var a,u;!function(){var t=function(){return"responseURL"in a?a.responseURL:/^X-Request-URL:/m.test(a.getAllResponseHeaders())?a.getResponseHeader("X-Request-URL"):void 0},e=function(){if(4===a.readyState){var e=1223===a.status?204:a.status;if(e<100||e>599){if(u)return;return u=!0,void n(new TypeError("Network request failed"))}var o={status:e,statusText:a.statusText,headers:m(a),url:t()},s="response"in a?a.response:a.responseText;u||(u=!0,r(new b(s,o)))}};a=new XMLHttpRequest,u=!1,a.onreadystatechange=e,a.onload=e,a.onerror=function(){u||(u=!0,n(new TypeError("Network request failed")))},a.open(o.method,o.url,!0);try{"include"===o.credentials&&("withCredentials"in a?a.withCredentials=!0:console&&console.warn&&console.warn("withCredentials is not supported, you can ignore this warning"))}catch(s){console&&console.warn&&console.warn("set withCredentials error:"+s)}"responseType"in a&&_.blob&&(a.responseType="blob"),o.headers.forEach(function(t,e){a.setRequestHeader(e,t)}),a.send("undefined"==typeof o._bodyInit?null:o._bodyInit)}()}})};return t["default"]=O,t=t["default"]}(),o=function(t){function e(t){return t&&t.__esModule?t:{"default":t}}function r(){return"jsonp_"+Date.now()+"_"+Math.ceil(1e5*Math.random())}function n(t){try{delete window[t]}catch(e){window[t]=void 0}}function o(t){document.getElementsByTagName("head")[0].removeChild(t)}t={},Object.defineProperty(t,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},i=a,f=e(i),l=u,h={timeout:5e3,jsonpCallback:"callback"},c=function(t){var e=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(!l.isWeex)return new f["default"](function(s,i){var a=null!=e.timeout?e.timeout:h.timeout,u=null!=e.jsonpCallback?e.jsonpCallback:h.jsonpCallback,d=void 0,l=e.jsonpCallbackFunctionName||r(),c=document.createElement("script");window[l]=function(t){s({ok:!0,json:function(){return f["default"].resolve(t)}}),d&&clearTimeout(d),o(c),n(l)},t+=t.indexOf("?")===-1?"?":"&",c.setAttribute("src",t+u+"="+l),document.getElementsByTagName("head")[0].appendChild(c),d=setTimeout(function(){i(new Error("JSONP request to "+t+" timed out")),n(l),o(c)},a)});var i=function(){var e=d;return e.fetch?{v:new f["default"](function(r,n){var o={url:t,method:"GET",type:"jsonp"};e.fetch(o,function(t){try{if("string"==typeof t&&(t=JSON.parse(t),t.data&&"string"==typeof t.data&&t.ok))try{t.data=JSON.parse(t.data)}catch(e){throw"the response.data in not valid json"}r({ok:t.ok,status:t.status,statusText:t.statusText,data:t.data,json:function(){return f["default"].resolve(t.data)}})}catch(e){n(e)}},function(t){})})}:e.sendHttp?{v:new f["default"](function(r,n){e.sendHttp({url:t,method:"GET"},function(t){"string"==typeof t&&(t=JSON.parse(t)),r({status:200,json:function(){return f["default"].resolve(t)}})})})}:{v:f["default"].reject("No fetch or sendhttp service")}}();return"object"===("undefined"==typeof i?"undefined":s(i))?i.v:void 0};return t["default"]=c,t=t["default"]}(),s=function(t){function e(t){return t&&t.__esModule?t:{"default":t}}t={},Object.defineProperty(t,"__esModule",{value:!0});var r=n,s=e(r),i=o,a=e(i),d=u,f=function(t){var e=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],r=void 0;return 0===t.indexOf("//")&&console.error("Failed to parse URL from "+t+", URL scheme is must in Weex. "),r="jsonp"===e.mode?(0,a["default"])(t,e):d.isWeex?(0,s["default"])(t,e):"undefined"!=typeof fetch?fetch(t,e):(0,s["default"])(t,e)};return t["default"]=f,t=t["default"]}(),i=function(t){"use strict";return t=s}(),r.exports=i});\ndefine("kg/rx-downgrade/index",["@weex-module/instanceWrap"],function(e,r,n){var t,o,i,a=e("@weex-module/instanceWrap");t=function(e){e={},Object.defineProperty(e,"__esModule",{value:!0});var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};return e["default"]={satisfies:function(e,n){var t=/(\\W+)?([\\d|.]+)/;if(("undefined"==typeof e?"undefined":r(e))+("undefined"==typeof n?"undefined":r(n))!="stringstring")return!1;if("*"==n)return!0;for(var o=n.match(t),i=e.split("."),a=o[2].split("."),f=Math.max(i.length,a.length),u=0,d=0;d0||parseInt(i[d])>parseInt(a[d])){u=1;break}if(a[d]&&!i[d]&&parseInt(a[d])>0||parseInt(i[d])":if(1===u)return!0;break;case">=":if(u!==-1)return!0;break;default:if(0===u)return!0}return!1}},e=e["default"]}(),o=function(e){function r(e){return e&&e.__esModule?e:{"default":e}}function n(e){if("*"==e)return e;e="string"==typeof e?e:"";for(var r=e.split("."),n=0,t=[];n<3;){var o="string"==typeof r[n]&&r[n]?r[n]:"0";t.push(o),n++}return t.join(".")}function o(e,r,n){var t={isDowngrade:!0,errorType:1,code:1e3},o=function(e,r,n){return"Downgrade["+e+"] :: deviceInfo "+r+" matched criteria "+n},i=e.toLowerCase();return i.indexOf("osversion")>=0?t.code=1001:i.indexOf("appversion")>=0?t.code=1002:i.indexOf("weexversion")>=0?t.code=1003:i.indexOf("devicemodel")>=0&&(t.code=1004),t.errorMessage=o(e,r,n),t}function i(e){var r={isDowngrade:!1};if(!d)return r;var t=WXEnvironment,i=t.platform||"unknow",a=i.toLowerCase(),f=e[a]||{};for(var s in t){var c=s,l=c.toLowerCase(),p=t[s],v=l.indexOf("version")>=0,y=l.indexOf("devicemodel")>=0,b=f[s];if(b&&v){var g=n(b),m=n(t[s]);if(u["default"].satisfies(m,g)){r=o(c,p,b);break}}else if(y){var w="array"==typeof b?b:[b];if(w.indexOf(p)>=0){r=o(c,p,b);break}}}return r}e={},Object.defineProperty(e,"__esModule",{value:!0});var f=t,u=r(f),d="undefined"!=typeof callNative;return e["default"]={setting:function(e){if(d){var r=i(e.downgrade);if(r.isDowngrade){var n=a;return n.error(r.errorType,r.code,r.errorMessage),!0}}return!1}},e=e["default"]}(),i=function(e){function r(e){return e&&e.__esModule?e:{"default":e}}e={},Object.defineProperty(e,"__esModule",{value:!0});var n=o,t=r(n);return e["default"]=t["default"],e=e["default"]}(),n.exports=i});\ndefine("kg/rx-animated/index",["kg/rx/index","kg/rx-components/index"],function(t,e,n){var r,i,o,a,u,s,c,l,f,h,p,_,y,v,d,b,m,g,w,k,O,j,V,P,x,E,T,C,A,R,F,M,S,I,U,L,q=t("kg/rx/index"),D=t("kg/rx-components/index");r=function(t){"use strict";var e=function(t,e,n,r,i,o,a,u){if(!t){var s;if(void 0===e)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,i,o,a,u],l=0;s=new Error(e.replace(/%s/g,function(){return c[l++]})),s.name="Invariant Violation"}throw s.framesToPop=1,s}};return t=e}(),i=function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var n=function(){function t(t,e){for(var n=0;n>>0===t&&t>=0&&t<=4294967295?t:null:(e=f.hex6.exec(t))?parseInt(e[1]+"ff",16)>>>0:h.hasOwnProperty(t)?h[t]:(e=f.rgb.exec(t))?(o(e[1])<<24|o(e[2])<<16|o(e[3])<<8|255)>>>0:(e=f.rgba.exec(t))?(o(e[1])<<24|o(e[2])<<16|o(e[3])<<8|u(e[4]))>>>0:(e=f.hex3.exec(t))?parseInt(e[1]+e[1]+e[2]+e[2]+e[3]+e[3]+"ff",16)>>>0:(e=f.hex8.exec(t))?parseInt(e[1],16)>>>0:(e=f.hex4.exec(t))?parseInt(e[1]+e[1]+e[2]+e[2]+e[3]+e[3]+e[4]+e[4],16)>>>0:(e=f.hsl.exec(t))?(255|r(a(e[1]),s(e[2]),s(e[3])))>>>0:(e=f.hsla.exec(t))?(r(a(e[1]),s(e[2]),s(e[3]))|u(e[4]))>>>0:null}function n(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t}function r(t,e,r){var i=r<.5?r*(1+e):r+e-r*e,o=2*r-i,a=n(o,i,t+1/3),u=n(o,i,t),s=n(o,i,t-1/3);return Math.round(255*a)<<24|Math.round(255*u)<<16|Math.round(255*s)<<8}function i(){for(var t=arguments.length,e=Array(t),n=0;n255?255:e}function a(t){var e=parseFloat(t);return(e%360+360)%360/360}function u(t){var e=parseFloat(t);return e<0?0:e>1?255:Math.round(255*e)}function s(t){var e=parseFloat(t,10);return e<0?0:e>100?1:e/100}var c="[-+]?\\\\d*\\\\.?\\\\d+",l=c+"%",f={rgb:new RegExp("rgb"+i(c,c,c)),rgba:new RegExp("rgba"+i(c,c,c,c)),hsl:new RegExp("hsl"+i(c,l,l)),hsla:new RegExp("hsla"+i(c,l,l,c)),hex3:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex4:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#([0-9a-fA-F]{6})$/,hex8:/^#([0-9a-fA-F]{8})$/},h={transparent:0,aliceblue:4042850303,antiquewhite:4209760255,aqua:16777215,aquamarine:2147472639,azure:4043309055,beige:4126530815,bisque:4293182719,black:255,blanchedalmond:4293643775,blue:65535,blueviolet:2318131967,brown:2771004159,burlywood:3736635391,burntsienna:3934150143,cadetblue:1604231423,chartreuse:2147418367,chocolate:3530104575,coral:4286533887,cornflowerblue:1687547391,cornsilk:4294499583,crimson:3692313855,cyan:16777215,darkblue:35839,darkcyan:9145343,darkgoldenrod:3095792639,darkgray:2846468607,darkgreen:6553855,darkgrey:2846468607,darkkhaki:3182914559,darkmagenta:2332068863,darkolivegreen:1433087999,darkorange:4287365375,darkorchid:2570243327,darkred:2332033279,darksalmon:3918953215,darkseagreen:2411499519,darkslateblue:1211993087,darkslategray:793726975,darkslategrey:793726975,darkturquoise:13554175,darkviolet:2483082239,deeppink:4279538687,deepskyblue:12582911,dimgray:1768516095,dimgrey:1768516095,dodgerblue:512819199,firebrick:2988581631,floralwhite:4294635775,forestgreen:579543807,fuchsia:4278255615,gainsboro:3705462015,ghostwhite:4177068031,gold:4292280575,goldenrod:3668254975,gray:2155905279,green:8388863,greenyellow:2919182335,grey:2155905279,honeydew:4043305215,hotpink:4285117695,indianred:3445382399,indigo:1258324735,ivory:4294963455,khaki:4041641215,lavender:3873897215,lavenderblush:4293981695,lawngreen:2096890111,lemonchiffon:4294626815,lightblue:2916673279,lightcoral:4034953471,lightcyan:3774873599,lightgoldenrodyellow:4210742015,lightgray:3553874943,lightgreen:2431553791,lightgrey:3553874943,lightpink:4290167295,lightsalmon:4288707327,lightseagreen:548580095,lightskyblue:2278488831,lightslategray:2005441023,lightslategrey:2005441023,lightsteelblue:2965692159,lightyellow:4294959359,lime:16711935,limegreen:852308735,linen:4210091775,magenta:4278255615,maroon:2147483903,mediumaquamarine:1724754687,mediumblue:52735,mediumorchid:3126187007,mediumpurple:2473647103,mediumseagreen:1018393087,mediumslateblue:2070474495,mediumspringgreen:16423679,mediumturquoise:1221709055,mediumvioletred:3340076543,midnightblue:421097727,mintcream:4127193855,mistyrose:4293190143,moccasin:4293178879,navajowhite:4292783615,navy:33023,oldlace:4260751103,olive:2155872511,olivedrab:1804477439,orange:4289003775,orangered:4282712319,orchid:3664828159,palegoldenrod:4008225535,palegreen:2566625535,paleturquoise:2951671551,palevioletred:3681588223,papayawhip:4293907967,peachpuff:4292524543,peru:3448061951,pink:4290825215,plum:3718307327,powderblue:2967529215,purple:2147516671,rebeccapurple:1714657791,red:4278190335,rosybrown:3163525119,royalblue:1097458175,saddlebrown:2336560127,salmon:4202722047,sandybrown:4104413439,seagreen:780883967,seashell:4294307583,sienna:2689740287,silver:3233857791,skyblue:2278484991,slateblue:1784335871,slategray:1887473919,slategrey:1887473919,snow:4294638335,springgreen:16744447,steelblue:1182971135,tan:3535047935,teal:8421631,thistle:3636451583,tomato:4284696575,turquoise:1088475391,violet:4001558271,wheat:4125012991,white:4294967295,whitesmoke:4126537215,yellow:4294902015,yellowgreen:2597139199};return t=e}(),s=function(t){"use strict";var e=0;return t=function(){return String(e++)}}(),c=function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var n=function(){function t(t,e){for(var n=0;n0?n=u:e=u;while(Math.abs(a)>l&&++s=c?u(e,_,t,n):0===y?_:a(e,r,r+p,t,n)}if(!(0<=t&&t<=1&&0<=n&&n<=1))throw new Error("bezier x values must be in [0, 1] range");var l=_?new Float32Array(h):new Array(h);if(t!==e||n!==r)for(var f=0;f18&&t<=44?c(t):l(t)}var h=i(t/1.7,0,20);h=o(h,0,.8);var p=i(r/1.7,0,20),_=o(p,.5,200),y=u(h,f(_),.01);return{tension:e(_),friction:n(y)}}return t={fromOrigamiTensionAndFriction:r,fromBouncinessAndSpeed:i}}(),b=function(t){function e(t){var e=Object.keys(t)[0],n="";return 0===e.indexOf("translate")&&(n="rem"),e+"("+t[e]+n+")"}function n(t){return t&&t.transform&&"string"!=typeof t.transform&&(t.transform=t.transform.map(e).join(" ")),t}return t={},Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n,t=t["default"]}(),m=function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){if(!t)throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var a=function(){function t(t,e){for(var n=0;nn){if("identity"===u)return s;"clamp"===u&&(s=n)}return r===i?r:e===n?t<=e?r:i:(e===-(1/0)?s=-s:n===1/0?s-=e:s=(s-e)/(n-e),s=o(s),r===-(1/0)?s=-s:i===1/0?s+=r:s=s*(i-r)+r,s)}function i(t){var e=p(t);if(null===e)return t;e=e||0;var n=(4278190080&e)>>>24,r=(16711680&e)>>>16,i=(65280&e)>>>8,o=(255&e)/255;return"rgba("+n+", "+r+", "+i+", "+o+")"}function o(t){var e=t.outputRange;_(e.length>=2,"Bad output range"),e=e.map(i),a(e);var n=e[0].match(d).map(function(){return[]});e.forEach(function(t){t.match(d).forEach(function(t,e){n[e].push(+t)})});var r=e[0].match(d).map(function(e,r){return v.create(f({},t,{outputRange:n[r]}))}),o=/^rgb/.test(e[0]);return function(t){var n=0;return e[0].replace(d,function(){var e=r[n++](t);return String(o&&n<4?Math.round(e):e)})}}function a(t){for(var e=t[0].replace(d,""),n=1;n=t);++n);return n-1}function c(t){_(t.length>=2,"inputRange must have at least 2 elements");for(var e=1;e=t[e-1],"inputRange must be monotonically increasing "+t)}function l(t,e){_(e.length>=2,t+" must have at least 2 elements"),_(2!==e.length||e[0]!==-(1/0)||e[1]!==1/0,t+"cannot be ]-infinity;+infinity[ "+e)}var f=Object.assign||function(t){for(var e=1;e0?1:0}},{key:"step1",value:function(t){return t>=1?1:0}},{key:"linear",value:function(t){return t}},{key:"ease",value:function(t){return o(t)}},{key:"quad",value:function(t){return t*t}},{key:"cubic",value:function(t){return t*t*t}},{key:"poly",value:function(t){return function(e){return Math.pow(e,t)}}},{key:"sin",value:function(t){return 1-Math.cos(t*Math.PI/2)}},{key:"circle",value:function(t){return 1-Math.sqrt(1-t*t)}},{key:"exp",value:function(t){return Math.pow(2,10*(t-1))}},{key:"elastic",value:function(){var t=arguments.length<=0||void 0===arguments[0]?1:arguments[0],e=t*Math.PI;return function(t){return 1-Math.pow(Math.cos(t*Math.PI/2),3)*Math.cos(t*e)}}},{key:"back",value:function(t){return void 0===t&&(t=1.70158),function(e){return e*e*((t+1)*e-t)}}},{key:"bounce",value:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?(t-=1.5/2.75,7.5625*t*t+.75):t<2.5/2.75?(t-=2.25/2.75,7.5625*t*t+.9375):(t-=2.625/2.75,7.5625*t*t+.984375)}},{key:"bezier",value:function(t,e,n,i){return r(t,e,n,i)}},{key:"in",value:function(t){return t}},{key:"out",value:function(t){return function(e){return 1-t(1-e)}}},{key:"inOut",value:function(t){return function(e){return e<.5?t(2*e)/2:1-t(2*(1-e))/2}}}]),t}(),o=i.bezier(.42,0,1,1);return t=i}(),j=function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){if(!t)throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var a=Object.assign||function(t){for(var e=1;e=this._startTime+this._duration?(0===this._duration?this._onUpdate(this._toValue):this._onUpdate(this._fromValue+this._easing(1)*(this._toValue-this._fromValue)),void this.__debouncedOnEnd({finished:!0})):(this._onUpdate(this._fromValue+this._easing((t-this._startTime)/this._duration)*(this._toValue-this._fromValue)),void(this.__active&&(this._animationFrame=u.current(this.onUpdate.bind(this)))))}},{key:"stop",value:function(){this.__active=!1,clearTimeout(this._timeout),s.current(this._animationFrame),this.__debouncedOnEnd({finished:!1})}}]),o}(o);return t=f}(),M=function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){if(!t)throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function o(t,e){return void 0===t||null===t?e:t}var a=function(){function t(t,e){for(var n=0;nthis._lastTime+i&&(o=this._lastTime+i);for(var a=1,u=Math.floor((o-this._lastTime)/a),c=0;cthis._toValue:t1?e-1:0),r=1;rt&&(a+=r&&o?c.currentPageX:r&&!o?c.currentPageY:!r&&o?c.previousPageX:c.previousPageY,u=1);else for(var s in i){var p=i[s];if(null!==p&&void 0!==p&&p.touchActive&&p.currentTimeStamp>=t){var d;d=r&&o?p.currentPageX:r&&!o?p.currentPageY:!r&&o?p.previousPageX:p.previousPageY,a+=d,u++}}return u>0?a/u:n.noCentroid},currentCentroidXOfTouchesChangedAfter:function(e,t){return n.centroidDimension(e,t,!0,!0)},currentCentroidYOfTouchesChangedAfter:function(e,t){return n.centroidDimension(e,t,!1,!0)},previousCentroidXOfTouchesChangedAfter:function(e,t){return n.centroidDimension(e,t,!0,!1)},previousCentroidYOfTouchesChangedAfter:function(e,t){return n.centroidDimension(e,t,!1,!1)},currentCentroidX:function(e){return n.centroidDimension(e,0,!0,!0)},currentCentroidY:function(e){return n.centroidDimension(e,0,!1,!0)},noCentroid:-1};return e=n}(),r=function(e){"use strict";function n(e){return e&&Array.prototype.slice.call(e)||[]}function t(e,t){var o=t.timeStamp||t.timestamp;return n(e).map(function(e){return{clientX:e.clientX,clientY:e.clientY,force:e.force,pageX:e.pageX,pageY:e.pageY,radiusX:e.radiusX,radiusY:e.radiusY,rotationAngle:e.rotationAngle,screenX:e.screenX,screenY:e.screenY,target:e.target||t.target,timestamp:o,identifier:e.identifier||1}})}var o={touchBank:{},numberActiveTouches:0,indexOfSingleActiveTouch:-1,mostRecentTimeStamp:0},r=function(e){return{touchActive:!0,startTimeStamp:e.timestamp,startPageX:e.pageX,startPageY:e.pageY,currentPageX:e.pageX,currentPageY:e.pageY,currentTimeStamp:e.timestamp,previousPageX:e.pageX,previousPageY:e.pageY,previousTimeStamp:e.timestamp}},i=function(e,n){e.touchActive=!0,e.startTimeStamp=n.timestamp,e.startPageX=n.pageX,e.startPageY=n.pageY,e.currentPageX=n.pageX,e.currentPageY=n.pageY,e.currentTimeStamp=n.timestamp,e.previousPageX=n.pageX,e.previousPageY=n.pageY,e.previousTimeStamp=n.timestamp},a=function(e){var n=o.touchBank,t=e.identifier,a=n[t];a?i(a,e):n[e.identifier]=r(e),o.mostRecentTimeStamp=e.timestamp},u=function(e){var n=o.touchBank,t=n[e.identifier];t.touchActive=!0,t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=e.timestamp,o.mostRecentTimeStamp=e.timestamp},c=function(e){var n=o.touchBank,t=n[e.identifier];t.previousPageX=t.currentPageX,t.previousPageY=t.currentPageY,t.previousTimeStamp=t.currentTimeStamp,t.currentPageX=e.pageX,t.currentPageY=e.pageY,t.currentTimeStamp=e.timestamp,t.touchActive=!1,o.mostRecentTimeStamp=e.timestamp},s={recordTouchTrack:function(e,n){var r=o.touchBank,i=t(n.changedTouches||[n],n);if("move"===e)i.forEach(u);else if("start"===e)i.forEach(a),o.numberActiveTouches=i.length,1===o.numberActiveTouches&&(o.indexOfSingleActiveTouch=i[0].identifier);else if("end"===e&&(i.forEach(c),o.numberActiveTouches=i.length,1===o.numberActiveTouches))for(var s in r){var p=r[s];if(null!=p&&p.touchActive){o.indexOfSingleActiveTouch=s;break}}},touchHistory:o};return e=s}(),i=function(e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e},t=o,i=r,a=t.currentCentroidXOfTouchesChangedAfter,u=t.currentCentroidYOfTouchesChangedAfter,c=t.previousCentroidXOfTouchesChangedAfter,s=t.previousCentroidYOfTouchesChangedAfter,p=t.currentCentroidX,d=t.currentCentroidY,m={_initializeGestureState:function(e){e.moveX=0,e.moveY=0,e.x0=0,e.y0=0,e.dx=0,e.dy=0,e.vx=0,e.vy=0,e.numberActiveTouches=0,e._accountsForMovesUpTo=0},_updateGestureStateOnMove:function(e,n){e.numberActiveTouches=n.numberActiveTouches,e.moveX=a(n,e._accountsForMovesUpTo),e.moveY=u(n,e._accountsForMovesUpTo);var t=e._accountsForMovesUpTo,o=c(n,t),r=a(n,t),i=s(n,t),p=u(n,t),d=e.dx+(r-o),m=e.dy+(p-i),v=n.mostRecentTimeStamp-e._accountsForMovesUpTo;e.vx=(d-e.dx)/v,e.vy=(m-e.dy)/v,e.dx=d,e.dy=m,e._accountsForMovesUpTo=n.mostRecentTimeStamp},create:function(e){var t={stateID:Math.random()};m._initializeGestureState(t);var o={onStartShouldSetResponder:function(n){return void 0!==e.onStartShouldSetPanResponder&&e.onStartShouldSetPanResponder(n,t)},onMoveShouldSetResponder:function(n){return void 0!==e.onMoveShouldSetPanResponder&&e.onMoveShouldSetPanResponder(n,t)},onStartShouldSetResponderCapture:function(n){return 1===n.nativeEvent.touches.length&&m._initializeGestureState(t),t.numberActiveTouches=i.touchHistory.numberActiveTouches,void 0!==e.onStartShouldSetPanResponderCapture&&e.onStartShouldSetPanResponderCapture(n,t)},onMoveShouldSetResponderCapture:function(n){var o=i.touchHistory;return t._accountsForMovesUpTo!==o.mostRecentTimeStamp&&(m._updateGestureStateOnMove(t,o),!!e.onMoveShouldSetPanResponderCapture&&e.onMoveShouldSetPanResponderCapture(n,t))}},r={onResponderGrant:function(n){return t.x0=p(i.touchHistory),t.y0=d(i.touchHistory),t.dx=0,t.dy=0,e.onPanResponderGrant&&e.onPanResponderGrant(n,t),void 0===e.onShouldBlockNativeResponder||e.onShouldBlockNativeResponder()},onResponderReject:function(n){e.onPanResponderReject&&e.onPanResponderReject(n,t)},onResponderRelease:function(n){e.onPanResponderRelease&&e.onPanResponderRelease(n,t),m._initializeGestureState(t)},onResponderTerminate:function(n){e.onPanResponderTerminate&&e.onPanResponderTerminate(n,t),m._initializeGestureState(t)},onResponderTerminationRequest:function(n){return void 0===e.onPanResponderTerminationRequest||e.onPanResponderTerminationRequest(n,t)}},a=!1,u={onPanStart:function(n){if(a=!0,i.recordTouchTrack("start",n),!o.onStartShouldSetResponder(n))return r.onResponderReject(n);r.onResponderGrant(n);var u=i.touchHistory;t.numberActiveTouches=u.numberActiveTouches,e.onPanResponderStart&&e.onPanResponderStart(n,t)},onPanMove:function(n){if(a&&(i.recordTouchTrack("move",n),o.onMoveShouldSetResponder(n))){var r=i.touchHistory;t._accountsForMovesUpTo!==r.mostRecentTimeStamp&&(m._updateGestureStateOnMove(t,r),e.onPanResponderMove&&e.onPanResponderMove(n,t))}},onPanEnd:function(n){a=!1,i.recordTouchTrack("end",n);var o=i.touchHistory;t.numberActiveTouches=o.numberActiveTouches,e.onPanResponderEnd&&e.onPanResponderEnd(n,t),r.onResponderRelease(n)}};return"undefined"==typeof callNative&&"object"===("undefined"==typeof window?"undefined":n(window))&&(u="ontouchstart"in window?{onTouchStart:u.onPanStart,onTouchMove:u.onPanMove,onTouchEnd:u.onPanEnd}:{onMouseDown:u.onPanStart,onMouseMove:u.onPanMove,onMouseUp:u.onPanEnd}),{panHandlers:u}}};return e=m}(),a=function(e){"use strict";return e=i}(),t.exports=a});\ndefine("kg/rx-toast/index",["kg/rx-env/index","@weex-module/modal"],function(e,t,n){var o,i,r=e("kg/rx-env/index"),a=e("@weex-module/modal");o=function(e){function t(e){if(!f){f=document.createElement("div");for(var t in m.container)f.style[t]=m.container[t];document.body.appendChild(f)}f.style.transform="translateX(-50%)",f.style.webkitTransform="translateX(-50%)",f.innerHTML=e}function n(){f&&setTimeout(function(){f.style.transform="translateX(-50%) scale(0.8)",f.style.webkitTransform="translateX(-50%) scale(0.8)"},0)}e={},Object.defineProperty(e,"__esModule",{value:!0});var o=r,i=3500,s=2e3,l=[],u=!1,f=void 0,d={push:function(e,t){l.push({message:e,duration:t}),this.show()},show:function(){var e=this;if(!l.length)return f&&f.parentNode.removeChild(f),void(f=null);if(!u){u=!0;var o=l.shift();t(o.message),setTimeout(function(){n(),u=!1,setTimeout(function(){return e.show()},600)},o.duration)}}},c={SHORT:s,LONG:i,show:function(e){var t=arguments.length<=1||void 0===arguments[1]?s:arguments[1];if(o.isWeex){var n=a;n.toast&&n.toast({message:e,duration:Number(t)/1e3})}else d.push(e,t)}},m={container:{backgroundColor:"rgba(0, 0, 0, 0.6)",boxSizing:"border-box",maxWidth:"80%",color:"#ffffff",padding:"8px 16px",position:"fixed",left:"50%",bottom:"50%",fontSize:"16px",lineHeight:"32px",fontWeight:"600",borderRadius:"4px",textAlign:"center",transition:"all 0.4s ease-in-out",webkitTransition:"all 0.4s ease-in-out",transform:"translateX(-50%)",webkitTransform:"translateX(-50%)",zIndex:9999}};return e["default"]=c,e=e["default"]}(),i=function(e){"use strict";return e=o}(),n.exports=i});\ndefine("kg/rx-alert/index",["@weex-module/modal"],function(n,t,e){var o,r,i=n("@weex-module/modal");o=function(n){function t(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}n={},Object.defineProperty(n,"__esModule",{value:!0});var e=function(){function n(n,t){for(var e=0;e-1?t&&t(e):o&&o(e)})}else if("undefined"!=typeof lib&&lib.mtop)return lib.mtop.request(e,t,o)},config:function(e,i){n||"undefined"!=typeof lib&&lib.mtop&&("string"==typeof e?lib.mtop.config[e]=i:lib.mtop.config=t({},lib.mtop.config,conf))},RESPONSE_TYPE:i},e=e["default"]}(),o=function(e){"use strict";return e=i}(),n.exports=o});\ndefine("kg/rx-user/index",["@weex-module/user"],function(i,e,n){var o,l,t=i("@weex-module/user");o=function(i){i={},Object.defineProperty(i,"__esModule",{value:!0});var e="undefined"!=typeof callNative;return i["default"]={getUserInfo:function(i){if(e){var n=t;n.getUserInfo&&n.getUserInfo(function(e){"string"==typeof e&&(e=JSON.parse(e)),i(e)})}else"undefined"!=typeof lib&&lib.login&&lib.login.isLogin(function(e,n){var o=n?n.data||{}:{};i({isLogin:e,info:{userId:o.userNumId,nick:o.nick}})})},login:function(i){if(e){var n=t;n.login&&n.login(i)}else"undefined"!=typeof lib&&lib.login&&(lib.login.isLogin()?i&&i():lib.login.goLogin())},logout:function(i){if(e){var n=t;n.logout&&n.logout(i)}else"undefined"!=typeof lib&&lib.login&&(lib.login.isLogin()?lib.login.goLogout():i&&i())}},i=i["default"]}(),l=function(i){"use strict";return i=o}(),n.exports=l});\ndefine("kg/rx-windvane/index",["@weex-module/windvane"],function(e,n,a){var i,l,d=e("@weex-module/windvane");i=function(e){e={},Object.defineProperty(e,"__esModule",{value:!0});var n="undefined"!=typeof callNative,a="undefined"!=typeof WindVane,i={};return i.call=function(e,l,t,u,f){if(n){var r=d;r.call&&r.call({"class":e,method:l,data:t},u)}else a&&WindVane.isAvailable?(i.isAvailable=WindVane.isAvailable,WindVane.call(e,l,t,u,f)):f&&f({msg:"\\u6d4f\\u89c8\\u5668\\u4e0d\\u652f\\u6301 windvane",ret:["HY_NOT_SUPPORT_DEVICE"]})},e["default"]=i,e=e["default"]}(),l=function(e){"use strict";return e=i}(),a.exports=l});\ndefine("kg/rx-spm/index",["@weex-module/pageInfo"],function(e,n,t){var o,g,i=e("@weex-module/pageInfo");o=function(e){e={},Object.defineProperty(e,"__esModule",{value:!0});var n="undefined"!=typeof callNative,t=("undefined"!=typeof WindVane,"undefined"!=typeof window),o=["0","0"];return e["default"]={getPageSPM:function(){return n||t&&window.goldlog&&(o=goldlog.spm_ab||o),o},getSPM:function(e,n){return[].concat(this.getPageSPM(),e||0,n||0)},getSPMQueryString:function(e,n){return"spm="+this.getSPM(e,n).join(".")},setPageSPM:function(e,g){if(o[0]=e,o[1]=g,n){var d=i;d.setSpm&&d.setSpm(e,g)}else t&&window.goldlog&&goldlog.setPageSPM&&goldlog.setPageSPM(e,g)}},e=e["default"]}(),g=function(e){"use strict";return e=o}(),t.exports=g});\ndefine("kg/rx-goldlog/index",["kg/rx-env/index","kg/rx-spm/index","@weex-module/userTrack"],function(e,n,r){var t,o,i=e("kg/rx-env/index"),l=e("kg/rx-spm/index"),u=e("@weex-module/userTrack");t=function(e){function n(e){return e&&e.__esModule?e:{"default":e}}function r(e){e="string"==typeof e?e:"";for(var n={},r=e.split("&"),t=0;t=t?r():l=setTimeout(r,t-e)),i}}e={},Object.defineProperty(e,"__esModule",{value:!0});var a=Object.assign||function(e){for(var t=1;ti.lastScrollDistance,l=t!=i.lastScrollContentSize;n&&o&&l&&(i.lastScrollContentSize=t,i.props.onEndReached(e)),i.lastScrollDistance=r}},i.resetScroll=function(e){s.isWeb&&(i.lastScrollContentSize=0,i.lastScrollDistance=0)},i.scrollTo=function(e){var t=parseInt(e.x),r=parseInt(e.y);if(s.isWeex){var n=O,o=(0,c.findDOMNode)(i.refs.contentContainer);n.scrollToElement(o.ref,{offset:t||r||0})}else{var l=document.documentElement.clientWidth/b;t>=0&&((0,c.findDOMNode)(i.refs.scroller).scrollLeft=l*t),r>=0&&((0,c.findDOMNode)(i.refs.scroller).scrollTop=l*r)}},l=n,o(i,l)}return i(t,e),u(t,[{key:"render",value:function(){var e=this,t=this.props,r=t.id,n=(t.style,t.scrollEventThrottle),o=t.showsHorizontalScrollIndicator,i=t.showsVerticalScrollIndicator,u=t.onEndReached,f=t.onEndReachedThreshold;f=parseInt(f,10);var d=[this.props.horizontal&&v.contentContainerHorizontal,this.props.contentContainerStyle];if(s.isWeex||this.props.horizontal||d.push(v.containerWebStyle),this.props.style){var h=["alignItems","justifyContent"].filter(function(t){return void 0!==e.props.style[t]});0!==h.length&&console.warn("ScrollView child layout ("+JSON.stringify(h)+") must be applied through the contentContainerStyle prop.")}var b=(0,c.createElement)(p["default"],{ref:"contentContainer",style:d},this.props.children),y=this.props.horizontal?v.baseHorizontal:v.baseVertical,m=a({},y,this.props.style),w=this.props.horizontal?o:i;if(s.isWeex)return(0,c.createElement)("scroller",{id:r,style:m,showScrollbar:w,onLoadmore:u,loadmoreoffset:f,scrollDirection:this.props.horizontal?"horizontal":"vertical"},b);var O=this.handleScroll;if(n&&(O=l(O,n)),!w&&!document.getElementById("rx-scrollview-style")){var _=document.createElement("style");_.id="rx-scrollview-style",document.head.appendChild(_),_.innerHTML="."+this.props.className+"::-webkit-scrollbar{display: none;}"}return m.webkitOverflowScrolling="touch",m.overflow="scroll",(0,c.createElement)(p["default"],a({},this.props,{ref:"scroller",style:m,onScroll:O}),b)}}]),t}(c.Component);y.defaultProps={scrollEventThrottle:h,onEndReachedThreshold:d,showsHorizontalScrollIndicator:!0,showsVerticalScrollIndicator:!0,className:"rx-scrollview"};var v={baseVertical:{flex:1,flexDirection:"column"},baseHorizontal:{flex:1,flexDirection:"row"},contentContainerHorizontal:{flexDirection:"row"},containerWebStyle:{display:"block"}};return e["default"]=y,e=e["default"]}(),p=function(e){function t(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}e={},Object.defineProperty(e,"__esModule",{value:!0});var l=function(){function e(e,t){for(var r=0;r1){for(var i=1;i-1||!(0,_util.isReserved)(key)){Object.defineProperty(vm,key,{configurable:true,enumerable:true,get:function proxyGetter(){return vm._data[key]},set:function proxySetter(val){vm._data[key]=val}})}}function unproxy(vm,key){if(!(0,_util.isReserved)(key)){delete vm[key]}}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.arrayMethods=undefined;var _util=__webpack_require__(93);var arrayProto=Array.prototype;var arrayMethods=exports.arrayMethods=Object.create(arrayProto);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(method){var original=arrayProto[method];(0,_util.def)(arrayMethods,method,function mutator(){var i=arguments.length;var args=new Array(i);while(i--){args[i]=arguments[i]}var result=original.apply(this,args);var ob=this.__ob__;var inserted=void 0;switch(method){case"push":inserted=args;break;case"unshift":inserted=args;break;case"splice":inserted=args.slice(2);break}if(inserted)ob.observeArray(inserted);ob.dep.notify();return result})});(0,_util.def)(arrayProto,"$set",function $set(index,val){if(index>=this.length){this.length=index+1}return this.splice(index,1,val)[0]});(0,_util.def)(arrayProto,"$remove",function $remove(index){if(!this.length)return;if(typeof index!=="number"){index=this.indexOf(index)}if(index>-1){this.splice(index,1)}})},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.build=build;var _util=__webpack_require__(93);var _state=__webpack_require__(94);var _directive=__webpack_require__(101);var _domHelper=__webpack_require__(103);function build(vm){var opt=vm._options||{};var template=opt.template||{};if(opt.replace){if(template.children&&template.children.length===1){compile(vm,template.children[0],vm._parentEl)}else{compile(vm,template.children,vm._parentEl)}}else{compile(vm,template,vm._parentEl)}console.debug('[JS Framework] "ready" lifecycle in Vm('+vm._type+")");vm.$emit("hook:ready");vm._ready=true}function compile(vm,target,dest,meta){var app=vm._app||{};if(app.lastSignal===-1){return}if(target.attr&&target.attr.hasOwnProperty("static")){vm._static=true}if(targetIsFragment(target)){compileFragment(vm,target,dest,meta);return}meta=meta||{};if(targetIsContent(target)){console.debug('[JS Framework] compile "content" block by',target);vm._content=(0,_domHelper.createBlock)(vm,dest);return}if(targetNeedCheckRepeat(target,meta)){console.debug('[JS Framework] compile "repeat" logic by',target);if(dest.type==="document"){console.warn("[JS Framework] The root element does't support `repeat` directive!")}else{compileRepeat(vm,target,dest)}return}if(targetNeedCheckShown(target,meta)){console.debug('[JS Framework] compile "if" logic by',target);if(dest.type==="document"){console.warn("[JS Framework] The root element does't support `if` directive!")}else{compileShown(vm,target,dest,meta)}return}var typeGetter=meta.type||target.type;if(targetNeedCheckType(typeGetter,meta)){compileType(vm,target,dest,typeGetter,meta);return}var type=typeGetter;var component=targetIsComposed(vm,target,type);if(component){console.debug("[JS Framework] compile composed component by",target);compileCustomComponent(vm,component,target,dest,type,meta);return}console.debug("[JS Framework] compile native component by",target);compileNativeComponent(vm,target,dest,type)}function targetIsFragment(target){ -return Array.isArray(target)}function targetIsContent(target){return target.type==="content"||target.type==="slot"}function targetNeedCheckRepeat(target,meta){return!meta.hasOwnProperty("repeat")&&target.repeat}function targetNeedCheckShown(target,meta){return!meta.hasOwnProperty("shown")&&target.shown}function targetNeedCheckType(typeGetter,meta){return typeof typeGetter==="function"&&!meta.hasOwnProperty("type")}function targetIsComposed(vm,target,type){var component=void 0;if(vm._app&&vm._app.customComponentMap){component=vm._app.customComponentMap[type]}if(vm._options&&vm._options.components){component=vm._options.components[type]}if(target.component){component=component||{}}return component}function compileFragment(vm,target,dest,meta){var fragBlock=(0,_domHelper.createBlock)(vm,dest);target.forEach(function(child){compile(vm,child,fragBlock,meta)})}function compileRepeat(vm,target,dest){var repeat=target.repeat;var oldStyle=typeof repeat==="function";var getter=repeat.getter||repeat.expression||repeat;if(typeof getter!=="function"){getter=function getter(){return[]}}var key=repeat.key||"$index";var value=repeat.value||"$value";var trackBy=repeat.trackBy||target.trackBy||target.attr&&target.attr.trackBy;var fragBlock=(0,_domHelper.createBlock)(vm,dest);fragBlock.children=[];fragBlock.data=[];fragBlock.vms=[];bindRepeat(vm,target,fragBlock,{getter:getter,key:key,value:value,trackBy:trackBy,oldStyle:oldStyle})}function compileShown(vm,target,dest,meta){var newMeta={shown:true};var fragBlock=(0,_domHelper.createBlock)(vm,dest);if(dest.element&&dest.children){dest.children.push(fragBlock)}if(meta.repeat){newMeta.repeat=meta.repeat}bindShown(vm,target,fragBlock,newMeta)}function compileType(vm,target,dest,typeGetter,meta){var type=typeGetter.call(vm);var newMeta=(0,_util.extend)({type:type},meta);var fragBlock=(0,_domHelper.createBlock)(vm,dest);if(dest.element&&dest.children){dest.children.push(fragBlock)}(0,_directive.watch)(vm,typeGetter,function(value){var newMeta=(0,_util.extend)({type:value},meta);(0,_domHelper.removeTarget)(vm,fragBlock,true);compile(vm,target,fragBlock,newMeta)});compile(vm,target,fragBlock,newMeta)}function compileCustomComponent(vm,component,target,dest,type,meta){var Ctor=vm.constructor;var subVm=new Ctor(type,component,vm,dest,undefined,{"hook:init":function hookInit(){if(vm._static){this._static=vm._static}(0,_directive.setId)(vm,null,target.id,this);this._externalBinding={parent:vm,template:target}},"hook:created":function hookCreated(){(0,_directive.bindSubVm)(vm,this,target,meta.repeat)},"hook:ready":function hookReady(){if(this._content){compileChildren(vm,target,this._content)}}});(0,_directive.bindSubVmAfterInitialized)(vm,subVm,target,dest)}function compileNativeComponent(vm,template,dest,type){(0,_directive.applyNaitveComponentOptions)(template);var element=void 0;if(dest.ref==="_documentElement"){console.debug("[JS Framework] compile to create body for "+type);element=(0,_domHelper.createBody)(vm,type)}else{console.debug("[JS Framework] compile to create element for "+type);element=(0,_domHelper.createElement)(vm,type)}if(!vm._rootEl){vm._rootEl=element;var binding=vm._externalBinding||{};var target=binding.template;var parentVm=binding.parent;if(target&&target.events&&parentVm&&element){for(var _type in target.events){var handler=parentVm[target.events[_type]];if(handler){element.addEvent(_type,(0,_util.bind)(handler,parentVm))}}}}(0,_directive.bindElement)(vm,element,template);if(template.attr&&template.attr.append){template.append=template.attr.append}if(template.append){element.attr=element.attr||{};element.attr.append=template.append}var treeMode=template.append==="tree";var app=vm._app||{};if(app.lastSignal!==-1&&!treeMode){console.debug("[JS Framework] compile to append single node for",element);app.lastSignal=(0,_domHelper.attachTarget)(vm,element,dest)}if(app.lastSignal!==-1){compileChildren(vm,template,element)}if(app.lastSignal!==-1&&treeMode){console.debug("[JS Framework] compile to append whole tree for",element);app.lastSignal=(0,_domHelper.attachTarget)(vm,element,dest)}}function compileChildren(vm,template,dest){var app=vm._app||{};var children=template.children;if(children&&children.length){children.every(function(child){compile(vm,child,dest);return app.lastSignal!==-1})}}function bindRepeat(vm,target,fragBlock,info){var vms=fragBlock.vms;var children=fragBlock.children;var getter=info.getter,trackBy=info.trackBy,oldStyle=info.oldStyle;var keyName=info.key;var valueName=info.value;function compileItem(item,index,context){var mergedData=void 0;if(oldStyle){mergedData=item;if((0,_util.isObject)(item)){mergedData[keyName]=index;if(!mergedData.hasOwnProperty("INDEX")){Object.defineProperty(mergedData,"INDEX",{value:function value(){console.warn('[JS Framework] "INDEX" in repeat is deprecated, '+'please use "$index" instead')}})}}else{console.warn("[JS Framework] Each list item must be an object in old-style repeat, "+"please use `repeat={{v in list}}` instead.");mergedData={};mergedData[keyName]=index;mergedData[valueName]=item}}else{mergedData={};mergedData[keyName]=index;mergedData[valueName]=item}var newContext=mergeContext(context,mergedData);vms.push(newContext);compile(newContext,target,fragBlock,{repeat:item})}var list=watchBlock(vm,fragBlock,getter,"repeat",function(data){console.debug('[JS Framework] the "repeat" item has changed',data);if(!fragBlock||!data){return}var oldChildren=children.slice();var oldVms=vms.slice();var oldData=fragBlock.data.slice();var trackMap={};var reusedMap={};data.forEach(function(item,index){var key=trackBy?item[trackBy]:oldStyle?item[keyName]:index;if(key==null||key===""){return}trackMap[key]=item});var reusedList=[];oldData.forEach(function(item,index){var key=trackBy?item[trackBy]:oldStyle?item[keyName]:index;if(trackMap.hasOwnProperty(key)){reusedMap[key]={item:item,index:index,key:key,target:oldChildren[index],vm:oldVms[index]};reusedList.push(item)}else{(0,_domHelper.removeTarget)(vm,oldChildren[index])}});children.length=0;vms.length=0;fragBlock.data=data.slice();fragBlock.updateMark=fragBlock.start;data.forEach(function(item,index){var key=trackBy?item[trackBy]:oldStyle?item[keyName]:index;var reused=reusedMap[key];if(reused){if(reused.item===reusedList[0]){reusedList.shift()}else{reusedList.$remove(reused.item);(0,_domHelper.moveTarget)(vm,reused.target,fragBlock.updateMark,true)}children.push(reused.target);vms.push(reused.vm);if(oldStyle){reused.vm=item}else{reused.vm[valueName]=item}reused.vm[keyName]=index;fragBlock.updateMark=reused.target}else{compileItem(item,index,vm)}});delete fragBlock.updateMark});fragBlock.data=list.slice(0);list.forEach(function(item,index){compileItem(item,index,vm)})}function bindShown(vm,target,fragBlock,meta){var display=watchBlock(vm,fragBlock,target.shown,"shown",function(display){console.debug('[JS Framework] the "if" item was changed',display);if(!fragBlock||!!fragBlock.display===!!display){return}fragBlock.display=!!display;if(display){compile(vm,target,fragBlock,meta)}else{(0,_domHelper.removeTarget)(vm,fragBlock,true)}});fragBlock.display=!!display;if(display){compile(vm,target,fragBlock,meta)}}function watchBlock(vm,fragBlock,calc,type,handler){var differ=vm&&vm._app&&vm._app.differ;var config={};var depth=(fragBlock.element.depth||0)+1;return(0,_directive.watch)(vm,calc,function(value){config.latestValue=value;if(differ&&!config.recorded){differ.append(type,depth,fragBlock.blockId,function(){var latestValue=config.latestValue;handler(latestValue);config.recorded=false;config.latestValue=undefined})}config.recorded=true})}function mergeContext(context,mergedData){var newContext=Object.create(context);newContext._data=mergedData;(0,_state.initData)(newContext);(0,_state.initComputed)(newContext);newContext._realParent=context;if(context._static){newContext._static=context._static}return newContext}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};exports.applyNaitveComponentOptions=applyNaitveComponentOptions;exports.bindElement=bindElement;exports.bindSubVm=bindSubVm;exports.bindSubVmAfterInitialized=bindSubVmAfterInitialized;exports.setId=setId;exports.watch=watch;var _util=__webpack_require__(93);var _watcher=__webpack_require__(95);var _watcher2=_interopRequireDefault(_watcher);var _config=__webpack_require__(102);var _config2=_interopRequireDefault(_config);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var nativeComponentMap=_config2.default.nativeComponentMap;var SETTERS={attr:"setAttr",style:"setStyle",event:"addEvent"};function applyNaitveComponentOptions(template){var type=template.type;var options=nativeComponentMap[type];if((typeof options==="undefined"?"undefined":_typeof(options))==="object"){for(var key in options){if(template[key]==null){template[key]=options[key]}else if((0,_util.typof)(template[key])==="object"&&(0,_util.typof)(options[key])==="object"){for(var subkey in options[key]){if(template[key][subkey]==null){template[key][subkey]=options[key][subkey]}}}}}}function bindElement(vm,el,template){setId(vm,el,template.id,vm);setAttr(vm,el,template.attr);setClass(vm,el,template.classList);setStyle(vm,el,template.style);bindEvents(vm,el,template.events)}function bindSubVm(vm,subVm,template,repeatItem){subVm=subVm||{};template=template||{};var options=subVm._options||{};var props=options.props;if(Array.isArray(props)){props=props.reduce(function(result,value){result[value]=true;return result},{})}mergeProps(repeatItem,props,vm,subVm);mergeProps(template.attr,props,vm,subVm)}function bindSubVmAfterInitialized(vm,subVm,template){var target=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};mergeClassStyle(template.classList,vm,subVm);mergeStyle(template.style,vm,subVm);if(target.children){target.children[target.children.length-1]._vm=subVm}else{target._vm=subVm}}function mergeProps(target,props,vm,subVm){if(!target){return}var _loop=function _loop(key){if(!props||props[key]){var value=target[key];if(typeof value==="function"){var returnValue=watch(vm,value,function(v){subVm[key]=v});subVm[key]=returnValue}else{subVm[key]=value}}};for(var key in target){_loop(key)}}function mergeStyle(target,vm,subVm){var _loop2=function _loop2(key){var value=target[key];if(typeof value==="function"){var returnValue=watch(vm,value,function(v){if(subVm._rootEl){subVm._rootEl.setStyle(key,v)}});subVm._rootEl.setStyle(key,returnValue)}else{if(subVm._rootEl){subVm._rootEl.setStyle(key,value)}}};for(var key in target){_loop2(key)}}function mergeClassStyle(target,vm,subVm){var css=vm._options&&vm._options.style||{};if(!subVm._rootEl){return}var className="@originalRootEl";css[className]=subVm._rootEl.classStyle;function addClassName(list,name){if((0,_util.typof)(list)==="array"){list.unshift(name)}}if(typeof target==="function"){var _value=watch(vm,target,function(v){addClassName(v,className);setClassStyle(subVm._rootEl,css,v)});addClassName(_value,className);setClassStyle(subVm._rootEl,css,_value)}else if(target!=null){addClassName(target,className);setClassStyle(subVm._rootEl,css,target)}}function setId(vm,el,id,target){var map=Object.create(null);Object.defineProperties(map,{vm:{value:target,writable:false,configurable:false},el:{get:function get(){return el||target._rootEl},configurable:false}});if(typeof id==="function"){var handler=id;id=handler.call(vm);if(id){vm._ids[id]=map}watch(vm,handler,function(newId){if(newId){vm._ids[newId]=map}})}else if(id&&typeof id==="string"){vm._ids[id]=map}}function setAttr(vm,el,attr){bindDir(vm,el,"attr",attr)}function setClassStyle(el,css,classList){var classStyle={};var length=classList.length;for(var i=0;i2&&arguments[2]!==undefined?arguments[2]:false;if(target.element){removeBlock(target,preserveBlock)}else{removeElement(target)}if(target._vm){target._vm.$emit("hook:destroyed")}}function removeElement(target){var parent=target.parentNode;if(parent){parent.removeChild(target)}}function removeBlock(fragBlock){var preserveBlock=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var result=[];var el=fragBlock.start.nextSibling;while(el&&el!==fragBlock.end){result.push(el);el=el.nextSibling}if(!preserveBlock){removeElement(fragBlock.start)}result.forEach(function(el){removeElement(el)});if(!preserveBlock){removeElement(fragBlock.end)}}},function(module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.$emit=$emit;exports.$dispatch=$dispatch;exports.$broadcast=$broadcast;exports.$on=$on;exports.$off=$off;exports.initEvents=initEvents;exports.mixinEvents=mixinEvents;function Evt(type,detail){if(detail instanceof Evt){return detail}this.timestamp=Date.now();this.detail=detail;this.type=type;var shouldStop=false;this.stop=function(){shouldStop=true};this.hasStopped=function(){return shouldStop}}function $emit(type,detail){var _this=this;var events=this._vmEvents;var handlerList=events[type];if(handlerList){(function(){var evt=new Evt(type,detail);handlerList.forEach(function(handler){handler.call(_this,evt)})})()}}function $dispatch(type,detail){var evt=new Evt(type,detail);this.$emit(type,evt);if(!evt.hasStopped()&&this._parent&&this._parent.$dispatch){this._parent.$dispatch(type,evt)}}function $broadcast(type,detail){var evt=new Evt(type,detail);this.$emit(type,evt);if(!evt.hasStopped()&&this._childrenVms){this._childrenVms.forEach(function(subVm){subVm.$broadcast(type,evt)})}}function $on(type,handler){if(!type||typeof handler!=="function"){return}var events=this._vmEvents;var handlerList=events[type]||[];handlerList.push(handler);events[type]=handlerList;if(type==="hook:ready"&&this._ready){this.$emit("hook:ready")}}function $off(type,handler){if(!type){return}var events=this._vmEvents;if(!handler){delete events[type];return}var handlerList=events[type];if(!handlerList){return}handlerList.$remove(handler)}var LIFE_CYCLE_TYPES=["init","created","ready","destroyed"];function initEvents(vm,externalEvents){var options=vm._options||{};var events=options.events||{};for(var type1 in events){vm.$on(type1,events[type1])}for(var type2 in externalEvents){vm.$on(type2,externalEvents[type2])}LIFE_CYCLE_TYPES.forEach(function(type){vm.$on("hook:"+type,options[type])})}function mixinEvents(vm){vm.$emit=$emit;vm.$dispatch=$dispatch;vm.$broadcast=$broadcast;vm.$on=$on;vm.$off=$off}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _bootstrap=__webpack_require__(106);Object.defineProperty(exports,"bootstrap",{enumerable:true,get:function get(){return _bootstrap.bootstrap}});var _define=__webpack_require__(109);Object.defineProperty(exports,"defineFn",{enumerable:true,get:function get(){return _define.defineFn}});Object.defineProperty(exports,"register",{enumerable:true,get:function get(){return _define.register}})},function(module,exports,__webpack_require__){(function(global){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.bootstrap=bootstrap;var _semver=__webpack_require__(107);var _semver2=_interopRequireDefault(_semver);var _vm=__webpack_require__(92);var _vm2=_interopRequireDefault(_vm);var _downgrade=__webpack_require__(108);var downgrade=_interopRequireWildcard(_downgrade);var _register=__webpack_require__(89);var _util=__webpack_require__(93);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key]}}newObj.default=obj;return newObj}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function bootstrap(app,name,config,data){console.debug("[JS Framework] bootstrap for "+name);var cleanName=void 0;if((0,_util.isWeexComponent)(name)){cleanName=(0,_util.removeWeexPrefix)(name)}else if((0,_util.isNpmModule)(name)){cleanName=(0,_util.removeJSSurfix)(name);if(!(0,_register.requireCustomComponent)(app,cleanName)){return new Error("It's not a component: "+name)}}else{return new Error("Wrong component name: "+name)}config=(0,_util.isPlainObject)(config)?config:{};if(typeof config.transformerVersion==="string"&&typeof global.transformerVersion==="string"&&!_semver2.default.satisfies(config.transformerVersion,global.transformerVersion)){return new Error("JS Bundle version: "+config.transformerVersion+" "+("not compatible with "+global.transformerVersion))}var downgradeResult=downgrade.check(config.downgrade);if(downgradeResult.isDowngrade){app.callTasks([{module:"instanceWrap",method:"error",args:[downgradeResult.errorType,downgradeResult.code,downgradeResult.errorMessage]}]);return new Error("Downgrade["+downgradeResult.code+"]: "+downgradeResult.errorMessage)}app.vm=new _vm2.default(cleanName,null,{_app:app},null,data)}}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){(function(process){"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};exports=module.exports=SemVer;var debug;if((typeof process==="undefined"?"undefined":_typeof(process))==="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG))debug=function debug(){var args=Array.prototype.slice.call(arguments,0);args.unshift("SEMVER");console.log.apply(console,args)};else debug=function debug(){};exports.SEMVER_SPEC_VERSION="2.0.0";var MAX_LENGTH=256;var MAX_SAFE_INTEGER=Number.MAX_SAFE_INTEGER||9007199254740991;var re=exports.re=[];var src=exports.src=[];var R=0;var NUMERICIDENTIFIER=R++;src[NUMERICIDENTIFIER]="0|[1-9]\\d*";var NUMERICIDENTIFIERLOOSE=R++;src[NUMERICIDENTIFIERLOOSE]="[0-9]+";var NONNUMERICIDENTIFIER=R++;src[NONNUMERICIDENTIFIER]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var MAINVERSION=R++;src[MAINVERSION]="("+src[NUMERICIDENTIFIER]+")\\."+"("+src[NUMERICIDENTIFIER]+")\\."+"("+src[NUMERICIDENTIFIER]+")";var MAINVERSIONLOOSE=R++;src[MAINVERSIONLOOSE]="("+src[NUMERICIDENTIFIERLOOSE]+")\\."+"("+src[NUMERICIDENTIFIERLOOSE]+")\\."+"("+src[NUMERICIDENTIFIERLOOSE]+")";var PRERELEASEIDENTIFIER=R++;src[PRERELEASEIDENTIFIER]="(?:"+src[NUMERICIDENTIFIER]+"|"+src[NONNUMERICIDENTIFIER]+")";var PRERELEASEIDENTIFIERLOOSE=R++;src[PRERELEASEIDENTIFIERLOOSE]="(?:"+src[NUMERICIDENTIFIERLOOSE]+"|"+src[NONNUMERICIDENTIFIER]+")";var PRERELEASE=R++;src[PRERELEASE]="(?:-("+src[PRERELEASEIDENTIFIER]+"(?:\\."+src[PRERELEASEIDENTIFIER]+")*))";var PRERELEASELOOSE=R++;src[PRERELEASELOOSE]="(?:-?("+src[PRERELEASEIDENTIFIERLOOSE]+"(?:\\."+src[PRERELEASEIDENTIFIERLOOSE]+")*))";var BUILDIDENTIFIER=R++;src[BUILDIDENTIFIER]="[0-9A-Za-z-]+";var BUILD=R++;src[BUILD]="(?:\\+("+src[BUILDIDENTIFIER]+"(?:\\."+src[BUILDIDENTIFIER]+")*))";var FULL=R++;var FULLPLAIN="v?"+src[MAINVERSION]+src[PRERELEASE]+"?"+src[BUILD]+"?";src[FULL]="^"+FULLPLAIN+"$";var LOOSEPLAIN="[v=\\s]*"+src[MAINVERSIONLOOSE]+src[PRERELEASELOOSE]+"?"+src[BUILD]+"?";var LOOSE=R++;src[LOOSE]="^"+LOOSEPLAIN+"$";var GTLT=R++;src[GTLT]="((?:<|>)?=?)";var XRANGEIDENTIFIERLOOSE=R++;src[XRANGEIDENTIFIERLOOSE]=src[NUMERICIDENTIFIERLOOSE]+"|x|X|\\*";var XRANGEIDENTIFIER=R++;src[XRANGEIDENTIFIER]=src[NUMERICIDENTIFIER]+"|x|X|\\*";var XRANGEPLAIN=R++;src[XRANGEPLAIN]="[v=\\s]*("+src[XRANGEIDENTIFIER]+")"+"(?:\\.("+src[XRANGEIDENTIFIER]+")"+"(?:\\.("+src[XRANGEIDENTIFIER]+")"+"(?:"+src[PRERELEASE]+")?"+src[BUILD]+"?"+")?)?";var XRANGEPLAINLOOSE=R++;src[XRANGEPLAINLOOSE]="[v=\\s]*("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:\\.("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:\\.("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:"+src[PRERELEASELOOSE]+")?"+src[BUILD]+"?"+")?)?";var XRANGE=R++;src[XRANGE]="^"+src[GTLT]+"\\s*"+src[XRANGEPLAIN]+"$";var XRANGELOOSE=R++;src[XRANGELOOSE]="^"+src[GTLT]+"\\s*"+src[XRANGEPLAINLOOSE]+"$";var LONETILDE=R++;src[LONETILDE]="(?:~>?)";var TILDETRIM=R++;src[TILDETRIM]="(\\s*)"+src[LONETILDE]+"\\s+";re[TILDETRIM]=new RegExp(src[TILDETRIM],"g");var tildeTrimReplace="$1~";var TILDE=R++;src[TILDE]="^"+src[LONETILDE]+src[XRANGEPLAIN]+"$";var TILDELOOSE=R++;src[TILDELOOSE]="^"+src[LONETILDE]+src[XRANGEPLAINLOOSE]+"$";var LONECARET=R++;src[LONECARET]="(?:\\^)";var CARETTRIM=R++;src[CARETTRIM]="(\\s*)"+src[LONECARET]+"\\s+";re[CARETTRIM]=new RegExp(src[CARETTRIM],"g");var caretTrimReplace="$1^";var CARET=R++;src[CARET]="^"+src[LONECARET]+src[XRANGEPLAIN]+"$";var CARETLOOSE=R++;src[CARETLOOSE]="^"+src[LONECARET]+src[XRANGEPLAINLOOSE]+"$";var COMPARATORLOOSE=R++;src[COMPARATORLOOSE]="^"+src[GTLT]+"\\s*("+LOOSEPLAIN+")$|^$";var COMPARATOR=R++;src[COMPARATOR]="^"+src[GTLT]+"\\s*("+FULLPLAIN+")$|^$";var COMPARATORTRIM=R++;src[COMPARATORTRIM]="(\\s*)"+src[GTLT]+"\\s*("+LOOSEPLAIN+"|"+src[XRANGEPLAIN]+")";re[COMPARATORTRIM]=new RegExp(src[COMPARATORTRIM],"g");var comparatorTrimReplace="$1$2$3";var HYPHENRANGE=R++;src[HYPHENRANGE]="^\\s*("+src[XRANGEPLAIN]+")"+"\\s+-\\s+"+"("+src[XRANGEPLAIN]+")"+"\\s*$";var HYPHENRANGELOOSE=R++;src[HYPHENRANGELOOSE]="^\\s*("+src[XRANGEPLAINLOOSE]+")"+"\\s+-\\s+"+"("+src[XRANGEPLAINLOOSE]+")"+"\\s*$";var STAR=R++;src[STAR]="(<|>)?=?\\s*\\*";for(var i=0;iMAX_LENGTH)return null;var r=loose?re[LOOSE]:re[FULL];if(!r.test(version))return null;try{return new SemVer(version,loose)}catch(er){return null}}exports.valid=valid;function valid(version,loose){var v=parse(version,loose);return v?v.version:null}exports.clean=clean;function clean(version,loose){var s=parse(version.trim().replace(/^[=v]+/,""),loose);return s?s.version:null}exports.SemVer=SemVer;function SemVer(version,loose){if(version instanceof SemVer){if(version.loose===loose)return version;else version=version.version}else if(typeof version!=="string"){throw new TypeError("Invalid Version: "+version)}if(version.length>MAX_LENGTH)throw new TypeError("version is longer than "+MAX_LENGTH+" characters");if(!(this instanceof SemVer))return new SemVer(version,loose);debug("SemVer",version,loose);this.loose=loose;var m=version.trim().match(loose?re[LOOSE]:re[FULL]);if(!m)throw new TypeError("Invalid Version: "+version);this.raw=version;this.major=+m[1];this.minor=+m[2];this.patch=+m[3];if(this.major>MAX_SAFE_INTEGER||this.major<0)throw new TypeError("Invalid major version");if(this.minor>MAX_SAFE_INTEGER||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>MAX_SAFE_INTEGER||this.patch<0)throw new TypeError("Invalid patch version");if(!m[4])this.prerelease=[];else this.prerelease=m[4].split(".").map(function(id){if(/^[0-9]+$/.test(id)){var num=+id;if(num>=0&&num=0){if(typeof this.prerelease[i]==="number"){this.prerelease[i]++;i=-2}}if(i===-1)this.prerelease.push(0)}if(identifier){if(this.prerelease[0]===identifier){if(isNaN(this.prerelease[1]))this.prerelease=[identifier,0]}else this.prerelease=[identifier,0]}break;default:throw new Error("invalid increment argument: "+release)}this.format();this.raw=this.version;return this};exports.inc=inc;function inc(version,release,loose,identifier){if(typeof loose==="string"){identifier=loose;loose=undefined}try{return new SemVer(version,loose).inc(release,identifier).version}catch(er){return null}}exports.diff=diff;function diff(version1,version2){if(eq(version1,version2)){return null}else{var v1=parse(version1);var v2=parse(version2);if(v1.prerelease.length||v2.prerelease.length){for(var key in v1){if(key==="major"||key==="minor"||key==="patch"){if(v1[key]!==v2[key]){return"pre"+key}}}return"prerelease"}for(var key in v1){if(key==="major"||key==="minor"||key==="patch"){if(v1[key]!==v2[key]){return key}}}}}exports.compareIdentifiers=compareIdentifiers;var numeric=/^[0-9]+$/;function compareIdentifiers(a,b){var anum=numeric.test(a);var bnum=numeric.test(b);if(anum&&bnum){a=+a;b=+b}return anum&&!bnum?-1:bnum&&!anum?1:ab?1:0}exports.rcompareIdentifiers=rcompareIdentifiers;function rcompareIdentifiers(a,b){return compareIdentifiers(b,a)}exports.major=major;function major(a,loose){return new SemVer(a,loose).major}exports.minor=minor;function minor(a,loose){return new SemVer(a,loose).minor}exports.patch=patch;function patch(a,loose){return new SemVer(a,loose).patch}exports.compare=compare;function compare(a,b,loose){return new SemVer(a,loose).compare(b)}exports.compareLoose=compareLoose;function compareLoose(a,b){return compare(a,b,true)}exports.rcompare=rcompare;function rcompare(a,b,loose){return compare(b,a,loose); -}exports.sort=sort;function sort(list,loose){return list.sort(function(a,b){return exports.compare(a,b,loose)})}exports.rsort=rsort;function rsort(list,loose){return list.sort(function(a,b){return exports.rcompare(a,b,loose)})}exports.gt=gt;function gt(a,b,loose){return compare(a,b,loose)>0}exports.lt=lt;function lt(a,b,loose){return compare(a,b,loose)<0}exports.eq=eq;function eq(a,b,loose){return compare(a,b,loose)===0}exports.neq=neq;function neq(a,b,loose){return compare(a,b,loose)!==0}exports.gte=gte;function gte(a,b,loose){return compare(a,b,loose)>=0}exports.lte=lte;function lte(a,b,loose){return compare(a,b,loose)<=0}exports.cmp=cmp;function cmp(a,op,b,loose){var ret;switch(op){case"===":if((typeof a==="undefined"?"undefined":_typeof(a))==="object")a=a.version;if((typeof b==="undefined"?"undefined":_typeof(b))==="object")b=b.version;ret=a===b;break;case"!==":if((typeof a==="undefined"?"undefined":_typeof(a))==="object")a=a.version;if((typeof b==="undefined"?"undefined":_typeof(b))==="object")b=b.version;ret=a!==b;break;case"":case"=":case"==":ret=eq(a,b,loose);break;case"!=":ret=neq(a,b,loose);break;case">":ret=gt(a,b,loose);break;case">=":ret=gte(a,b,loose);break;case"<":ret=lt(a,b,loose);break;case"<=":ret=lte(a,b,loose);break;default:throw new TypeError("Invalid operator: "+op)}return ret}exports.Comparator=Comparator;function Comparator(comp,loose){if(comp instanceof Comparator){if(comp.loose===loose)return comp;else comp=comp.value}if(!(this instanceof Comparator))return new Comparator(comp,loose);debug("comparator",comp,loose);this.loose=loose;this.parse(comp);if(this.semver===ANY)this.value="";else this.value=this.operator+this.semver.version;debug("comp",this)}var ANY={};Comparator.prototype.parse=function(comp){var r=this.loose?re[COMPARATORLOOSE]:re[COMPARATOR];var m=comp.match(r);if(!m)throw new TypeError("Invalid comparator: "+comp);this.operator=m[1];if(this.operator==="=")this.operator="";if(!m[2])this.semver=ANY;else this.semver=new SemVer(m[2],this.loose)};Comparator.prototype.toString=function(){return this.value};Comparator.prototype.test=function(version){debug("Comparator.test",version,this.loose);if(this.semver===ANY)return true;if(typeof version==="string")version=new SemVer(version,this.loose);return cmp(version,this.operator,this.semver,this.loose)};exports.Range=Range;function Range(range,loose){if(range instanceof Range&&range.loose===loose)return range;if(!(this instanceof Range))return new Range(range,loose);this.loose=loose;this.raw=range;this.set=range.split(/\s*\|\|\s*/).map(function(range){return this.parseRange(range.trim())},this).filter(function(c){return c.length});if(!this.set.length){throw new TypeError("Invalid SemVer Range: "+range)}this.format()}Range.prototype.format=function(){this.range=this.set.map(function(comps){return comps.join(" ").trim()}).join("||").trim();return this.range};Range.prototype.toString=function(){return this.range};Range.prototype.parseRange=function(range){var loose=this.loose;range=range.trim();debug("range",range,loose);var hr=loose?re[HYPHENRANGELOOSE]:re[HYPHENRANGE];range=range.replace(hr,hyphenReplace);debug("hyphen replace",range);range=range.replace(re[COMPARATORTRIM],comparatorTrimReplace);debug("comparator trim",range,re[COMPARATORTRIM]);range=range.replace(re[TILDETRIM],tildeTrimReplace);range=range.replace(re[CARETTRIM],caretTrimReplace);range=range.split(/\s+/).join(" ");var compRe=loose?re[COMPARATORLOOSE]:re[COMPARATOR];var set=range.split(" ").map(function(comp){return parseComparator(comp,loose)}).join(" ").split(/\s+/);if(this.loose){set=set.filter(function(comp){return!!comp.match(compRe)})}set=set.map(function(comp){return new Comparator(comp,loose)});return set};exports.toComparators=toComparators;function toComparators(range,loose){return new Range(range,loose).set.map(function(comp){return comp.map(function(c){return c.value}).join(" ").trim().split(" ")})}function parseComparator(comp,loose){debug("comp",comp);comp=replaceCarets(comp,loose);debug("caret",comp);comp=replaceTildes(comp,loose);debug("tildes",comp);comp=replaceXRanges(comp,loose);debug("xrange",comp);comp=replaceStars(comp,loose);debug("stars",comp);return comp}function isX(id){return!id||id.toLowerCase()==="x"||id==="*"}function replaceTildes(comp,loose){return comp.trim().split(/\s+/).map(function(comp){return replaceTilde(comp,loose)}).join(" ")}function replaceTilde(comp,loose){var r=loose?re[TILDELOOSE]:re[TILDE];return comp.replace(r,function(_,M,m,p,pr){debug("tilde",comp,_,M,m,p,pr);var ret;if(isX(M))ret="";else if(isX(m))ret=">="+M+".0.0 <"+(+M+1)+".0.0";else if(isX(p))ret=">="+M+"."+m+".0 <"+M+"."+(+m+1)+".0";else if(pr){debug("replaceTilde pr",pr);if(pr.charAt(0)!=="-")pr="-"+pr;ret=">="+M+"."+m+"."+p+pr+" <"+M+"."+(+m+1)+".0"}else ret=">="+M+"."+m+"."+p+" <"+M+"."+(+m+1)+".0";debug("tilde return",ret);return ret})}function replaceCarets(comp,loose){return comp.trim().split(/\s+/).map(function(comp){return replaceCaret(comp,loose)}).join(" ")}function replaceCaret(comp,loose){debug("caret",comp,loose);var r=loose?re[CARETLOOSE]:re[CARET];return comp.replace(r,function(_,M,m,p,pr){debug("caret",comp,_,M,m,p,pr);var ret;if(isX(M))ret="";else if(isX(m))ret=">="+M+".0.0 <"+(+M+1)+".0.0";else if(isX(p)){if(M==="0")ret=">="+M+"."+m+".0 <"+M+"."+(+m+1)+".0";else ret=">="+M+"."+m+".0 <"+(+M+1)+".0.0"}else if(pr){debug("replaceCaret pr",pr);if(pr.charAt(0)!=="-")pr="-"+pr;if(M==="0"){if(m==="0")ret=">="+M+"."+m+"."+p+pr+" <"+M+"."+m+"."+(+p+1);else ret=">="+M+"."+m+"."+p+pr+" <"+M+"."+(+m+1)+".0"}else ret=">="+M+"."+m+"."+p+pr+" <"+(+M+1)+".0.0"}else{debug("no pr");if(M==="0"){if(m==="0")ret=">="+M+"."+m+"."+p+" <"+M+"."+m+"."+(+p+1);else ret=">="+M+"."+m+"."+p+" <"+M+"."+(+m+1)+".0"}else ret=">="+M+"."+m+"."+p+" <"+(+M+1)+".0.0"}debug("caret return",ret);return ret})}function replaceXRanges(comp,loose){debug("replaceXRanges",comp,loose);return comp.split(/\s+/).map(function(comp){return replaceXRange(comp,loose)}).join(" ")}function replaceXRange(comp,loose){comp=comp.trim();var r=loose?re[XRANGELOOSE]:re[XRANGE];return comp.replace(r,function(ret,gtlt,M,m,p,pr){debug("xRange",comp,ret,gtlt,M,m,p,pr);var xM=isX(M);var xm=xM||isX(m);var xp=xm||isX(p);var anyX=xp;if(gtlt==="="&&anyX)gtlt="";if(xM){if(gtlt===">"||gtlt==="<"){ret="<0.0.0"}else{ret="*"}}else if(gtlt&&anyX){if(xm)m=0;if(xp)p=0;if(gtlt===">"){gtlt=">=";if(xm){M=+M+1;m=0;p=0}else if(xp){m=+m+1;p=0}}else if(gtlt==="<="){gtlt="<";if(xm)M=+M+1;else m=+m+1}ret=gtlt+M+"."+m+"."+p}else if(xm){ret=">="+M+".0.0 <"+(+M+1)+".0.0"}else if(xp){ret=">="+M+"."+m+".0 <"+M+"."+(+m+1)+".0"}debug("xRange return",ret);return ret})}function replaceStars(comp,loose){debug("replaceStars",comp,loose);return comp.trim().replace(re[STAR],"")}function hyphenReplace($0,from,fM,fm,fp,fpr,fb,to,tM,tm,tp,tpr,tb){if(isX(fM))from="";else if(isX(fm))from=">="+fM+".0.0";else if(isX(fp))from=">="+fM+"."+fm+".0";else from=">="+from;if(isX(tM))to="";else if(isX(tm))to="<"+(+tM+1)+".0.0";else if(isX(tp))to="<"+tM+"."+(+tm+1)+".0";else if(tpr)to="<="+tM+"."+tm+"."+tp+"-"+tpr;else to="<="+to;return(from+" "+to).trim()}Range.prototype.test=function(version){if(!version)return false;if(typeof version==="string")version=new SemVer(version,this.loose);for(var i=0;i0){var allowed=set[i].semver;if(allowed.major===version.major&&allowed.minor===version.minor&&allowed.patch===version.patch)return true}}return false}return true}exports.satisfies=satisfies;function satisfies(version,range,loose){try{range=new Range(range,loose)}catch(er){return false}return range.test(version)}exports.maxSatisfying=maxSatisfying;function maxSatisfying(versions,range,loose){return versions.filter(function(version){return satisfies(version,range,loose)}).sort(function(a,b){return rcompare(a,b,loose)})[0]||null}exports.minSatisfying=minSatisfying;function minSatisfying(versions,range,loose){return versions.filter(function(version){return satisfies(version,range,loose)}).sort(function(a,b){return compare(a,b,loose)})[0]||null}exports.validRange=validRange;function validRange(range,loose){try{return new Range(range,loose).range||"*"}catch(er){return null}}exports.ltr=ltr;function ltr(version,range,loose){return outside(version,range,"<",loose)}exports.gtr=gtr;function gtr(version,range,loose){return outside(version,range,">",loose)}exports.outside=outside;function outside(version,range,hilo,loose){version=new SemVer(version,loose);range=new Range(range,loose);var gtfn,ltefn,ltfn,comp,ecomp;switch(hilo){case">":gtfn=gt;ltefn=lte;ltfn=lt;comp=">";ecomp=">=";break;case"<":gtfn=lt;ltefn=gte;ltfn=gt;comp="<";ecomp="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(satisfies(version,range,loose)){return false}for(var i=0;i=0.0.0")}high=high||comparator;low=low||comparator;if(gtfn(comparator.semver,high.semver,loose)){high=comparator}else if(ltfn(comparator.semver,low.semver,loose)){low=comparator}});if(high.operator===comp||high.operator===ecomp){return false}if((!low.operator||low.operator===comp)&<efn(version,low.semver)){return false}else if(low.operator===ecomp&<fn(version,low.semver)){return false}}return true}exports.prerelease=prerelease;function prerelease(version,loose){var parsed=parse(version,loose);return parsed&&parsed.prerelease.length?parsed.prerelease:null}}).call(exports,__webpack_require__(96))},function(module,exports,__webpack_require__){(function(global){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.normalizeVersion=normalizeVersion;exports.getError=getError;exports.check=check;var _semver=__webpack_require__(107);var _semver2=_interopRequireDefault(_semver);var _util=__webpack_require__(93);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function normalizeVersion(v){var isValid=_semver2.default.valid(v);if(isValid){return v}v=typeof v==="string"?v:"";var split=v.split(".");var i=0;var result=[];while(i<3){var s=typeof split[i]==="string"&&split[i]?split[i]:"0";result.push(s);i++}return result.join(".")}function getError(key,val,criteria){var result={isDowngrade:true,errorType:1,code:1e3};var getMsg=function getMsg(key,val,criteria){return"Downgrade["+key+"] :: deviceInfo "+val+" matched criteria "+criteria};var _key=key.toLowerCase();result.errorMessage=getMsg(key,val,criteria);if(_key.indexOf("osversion")>=0){result.code=1001}else if(_key.indexOf("appversion")>=0){result.code=1002}else if(_key.indexOf("weexversion")>=0){result.code=1003}else if(_key.indexOf("devicemodel")>=0){result.code=1004}return result}function check(config,deviceInfo){deviceInfo=deviceInfo||global.WXEnvironment;deviceInfo=(0,_util.isPlainObject)(deviceInfo)?deviceInfo:{};var result={isDowngrade:false};if((0,_util.typof)(config)==="function"){var customDowngrade=config.call(this,deviceInfo,{semver:_semver2.default,normalizeVersion:this.normalizeVersion});customDowngrade=!!customDowngrade;result=customDowngrade?this.getError("custom","","custom params"):result}else{config=(0,_util.isPlainObject)(config)?config:{};var platform=deviceInfo.platform||"unknow";var dPlatform=platform.toLowerCase();var cObj=config[dPlatform]||{};for(var i in deviceInfo){var key=i;var keyLower=key.toLowerCase();var val=deviceInfo[i];var isVersion=keyLower.indexOf("version")>=0;var isDeviceModel=keyLower.indexOf("devicemodel")>=0;var criteria=cObj[i];if(criteria&&isVersion){var c=this.normalizeVersion(criteria);var d=this.normalizeVersion(deviceInfo[i]);if(_semver2.default.satisfies(d,c)){result=this.getError(key,val,criteria);break}}else if(isDeviceModel){var _criteria=(0,_util.typof)(criteria)==="array"?criteria:[criteria];if(_criteria.indexOf(val)>=0){result=this.getError(key,val,criteria);break}}}}return result}}).call(exports,function(){return this}())},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.defineFn=undefined;exports.register=register;var _util=__webpack_require__(93);var _register=__webpack_require__(89);function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}var defineFn=exports.defineFn=function defineFn(app,name){console.debug("[JS Framework] define a component "+name);var factory=void 0,definition=void 0;if((arguments.length<=2?0:arguments.length-2)>1){definition=arguments.length<=3?undefined:arguments[3]}else{definition=arguments.length<=2?undefined:arguments[2]}if(typeof definition==="function"){factory=definition;definition=null}if(factory){var r=function r(name){if((0,_util.isWeexComponent)(name)){var cleanName=(0,_util.removeWeexPrefix)(name);return(0,_register.requireCustomComponent)(app,cleanName)}if((0,_util.isWeexModule)(name)){var _cleanName=(0,_util.removeWeexPrefix)(name);return app.requireModule(_cleanName)}if((0,_util.isNormalModule)(name)||(0,_util.isNpmModule)(name)){var _cleanName2=(0,_util.removeJSSurfix)(name);return app.commonModules[_cleanName2]}};var m={exports:{}};factory(r,m.exports,m);definition=m.exports}if((0,_util.isWeexComponent)(name)){var cleanName=(0,_util.removeWeexPrefix)(name);(0,_register.registerCustomComponent)(app,cleanName,definition)}else if((0,_util.isWeexModule)(name)){var _cleanName3=(0,_util.removeWeexPrefix)(name);(0,_register.initModules)(_defineProperty({},_cleanName3,definition))}else if((0,_util.isNormalModule)(name)){var _cleanName4=(0,_util.removeJSSurfix)(name);app.commonModules[_cleanName4]=definition}else if((0,_util.isNpmModule)(name)){var _cleanName5=(0,_util.removeJSSurfix)(name);if(definition.template||definition.style||definition.methods){(0,_register.registerCustomComponent)(app,_cleanName5,definition)}else{app.commonModules[_cleanName5]=definition}}};function register(app,type,options){console.warn("[JS Framework] Register is deprecated, please install lastest transformer.");(0,_register.registerCustomComponent)(app,type,options)}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.refresh=refresh;exports.destroy=destroy;exports.destroyVm=destroyVm;exports.getRootElement=getRootElement;exports.fireEvent=fireEvent;exports.callback=callback;exports.updateActions=updateActions;exports.callTasks=callTasks;var _util=__webpack_require__(93);var _config=__webpack_require__(102);var _config2=_interopRequireDefault(_config);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key]}return _ctrl.fireEvent.apply(undefined,[_map.instanceMap[id]].concat(args))},callback:function callback(id){for(var _len2=arguments.length,args=Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++){args[_key2-1]=arguments[_key2]}return _ctrl.callback.apply(undefined,[_map.instanceMap[id]].concat(args))}};function receiveTasks(id,tasks){var instance=_map.instanceMap[id];if(instance&&Array.isArray(tasks)){var _ret=function(){var results=[];tasks.forEach(function(task){var handler=jsHandlers[task.method];var args=[].concat(_toConsumableArray(task.args));if(typeof handler==="function"){args.unshift(id);results.push(handler.apply(undefined,_toConsumableArray(args)))}});return{v:results}}();if((typeof _ret==="undefined"?"undefined":_typeof(_ret))==="object")return _ret.v}return new Error('invalid instance id "'+id+'" or tasks')}},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getRoot=getRoot;var _map=__webpack_require__(113);var _ctrl=__webpack_require__(90);function getRoot(id){var instance=_map.instanceMap[id];var result=void 0;if(instance){result=(0,_ctrl.getRootElement)(instance)}else{result=new Error('invalid instance id "'+id+'"')}return result}},function(module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=init;var frameworks=void 0;var versionRegExp=/^\s*\/\/ *(\{[^\}]*\}) *\r?\n/;function checkVersion(code){var info=void 0;var result=versionRegExp.exec(code);if(result){try{info=JSON.parse(result[1])}catch(e){}}return info}var instanceMap={};function createInstance(id,code,config,data){var info=instanceMap[id];if(!info){info=checkVersion(code)||{};if(!frameworks[info.framework]){info.framework="Weex"}instanceMap[id]=info;config=config||{};config.bundleVersion=info.version;console.debug("[JS Framework] create an "+info.framework+"@"+config.bundleVersion+" instance from "+config.bundleVersion);return frameworks[info.framework].createInstance(id,code,config,data)}return new Error('invalid instance id "'+id+'"')}var methods={createInstance:createInstance};function genInit(methodName){methods[methodName]=function(){for(var name in frameworks){var framework=frameworks[name];if(framework&&framework[methodName]){framework[methodName].apply(framework,arguments)}}}}function genInstance(methodName){methods[methodName]=function(){var id=arguments.length<=0?undefined:arguments[0];var info=instanceMap[id];if(info&&frameworks[info.framework]){var _frameworks$info$fram;return(_frameworks$info$fram=frameworks[info.framework])[methodName].apply(_frameworks$info$fram,arguments)}return new Error('invalid instance id "'+id+'"')}}function adaptInstance(methodName,nativeMethodName){methods[nativeMethodName]=function(){var id=arguments.length<=0?undefined:arguments[0];var info=instanceMap[id];if(info&&frameworks[info.framework]){var _frameworks$info$fram2;return(_frameworks$info$fram2=frameworks[info.framework])[methodName].apply(_frameworks$info$fram2,arguments)}return new Error('invalid instance id "'+id+'"')}}function init(config){frameworks=config.frameworks||{};for(var name in frameworks){var framework=frameworks[name];framework.init(config)}["registerComponents","registerModules","registerMethods"].forEach(genInit);["destroyInstance","refreshInstance","receiveTasks","getRoot"].forEach(genInstance);adaptInstance("receiveTasks","callJS");return methods}},function(module,exports){module.exports={name:"weex-js-framework",version:"0.16.18",subversion:{framework:"0.16.18",transformer:">=0.1.5 <0.4"},description:"Weex JS Framework",keywords:["weex","mvvm","javascript","html5"],homepage:"https://alibaba.github.io/weex",bugs:{url:"https://github.com/alibaba/weex/issues"},license:"Apache-2.0",author:"Jinjiang ",maintainers:["terrykingcha ","IskenHuang ","yuanyan "],main:"index.js",repository:{type:"git",url:"git@github.com:alibaba/weex.git"},scripts:{test:'echo "Error: no test specified" && exit 1'},dependencies:{"core-js":"^2.4.0",semver:"^5.1.0","weex-rx-framework":"0.1.13"}}},function(module,exports,__webpack_require__){(function(global){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.$=$;exports.$el=$el;exports.$vm=$vm;exports.$renderThen=$renderThen;exports.$scrollTo=$scrollTo;exports.$transition=$transition;exports.$getConfig=$getConfig;exports.$sendHttp=$sendHttp;exports.$openURL=$openURL;exports.$setTitle=$setTitle;exports.$call=$call;var _util=__webpack_require__(93);var _config=__webpack_require__(102);var _config2=_interopRequireDefault(_config);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var nativeComponentMap=_config2.default.nativeComponentMap;function $(id){console.warn("[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead");var info=this._ids[id];if(info){return info.vm}}function addComponentMethods(app,el){if(el&&el.type){(function(){var component=nativeComponentMap[el.type];if(component&&component.methods){component.methods.forEach(function(method){el[method]=function(){for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}app.callTasks({component:component.type,ref:el.ref,method:method,args:args})}})}})()}return el}function $el(id){var info=this._ids[id];if(info){return addComponentMethods(info.vm._app||{},info.el)}}function $vm(id){var info=this._ids[id];if(info){return info.vm}}function $renderThen(fn){var app=this._app;var differ=app.differ;return differ.then(function(){fn()})}function $scrollTo(id,offset){console.warn("[JS Framework] Vm#$scrollTo is deprecated, "+"please use \"require('@weex-module/dom')"+'.scrollTo(el, options)" instead');var el=this.$el(id);if(el){var dom=this._app.requireModule("dom");dom.scrollToElement(el.ref,{offset:offset})}}function $transition(id,options,callback){var _this=this;var el=this.$el(id);if(el&&options&&options.styles){var animation=this._app.requireModule("animation");animation.transition(el.ref,options,function(){_this._setStyle(el,options.styles);callback&&callback.apply(undefined,arguments)})}}function $getConfig(callback){var config=(0,_util.extend)({env:global.WXEnvironment||{}},this._app.options);if((0,_util.typof)(callback)==="function"){console.warn("[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, "+"this api now can directly RETURN config info.");callback(config)}return config}function $sendHttp(params,callback){console.warn("[JS Framework] Vm#$sendHttp is deprecated, "+"please use \"require('@weex-module/stream')"+'.sendHttp(params, callback)" instead');var stream=this._app.requireModule("stream");stream.sendHttp(params,callback)}function $openURL(url){console.warn("[JS Framework] Vm#$openURL is deprecated, "+"please use \"require('@weex-module/event')"+'.openURL(url)" instead');var event=this._app.requireModule("event");event.openURL(url)}function $setTitle(title){console.warn("[JS Framework] Vm#$setTitle is deprecated, "+"please use \"require('@weex-module/pageInfo')"+'.setTitle(title)" instead');var pageInfo=this._app.requireModule("pageInfo");pageInfo.setTitle(title)}function $call(moduleName,methodName){console.warn("[JS Framework] Vm#$call is deprecated, "+"please use \"require('@weex-module/moduleName')\" instead");var module=this._app.requireModule(moduleName);if(module&&module[methodName]){for(var _len2=arguments.length,args=Array(_len2>2?_len2-2:0),_key2=2;_key2<_len2;_key2++){ -args[_key2-2]=arguments[_key2]}module[methodName].apply(module,args)}}}).call(exports,function(){return this}())},function(module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.$userTrack=$userTrack;exports.$sendMtop=$sendMtop;exports.$callWindvane=$callWindvane;exports.$setSpm=$setSpm;exports.$getUserInfo=$getUserInfo;exports.$login=$login;exports.$logout=$logout;function $userTrack(type,name,comName,param){console.warn("[JS Framework] Vm#$userTrack is deprecated, "+"please use \"require('@weex-module/userTrack')"+'.commit(type, name, comName, param)" instead');var userTrack=this._app.requireModule("userTrack");userTrack.commit(type,name,comName,param)}function $sendMtop(params,callback){console.warn("[JS Framework] Vm#$sendMtop is deprecated, "+"please use \"require('@weex-module/stream')"+'.sendMtop(params, callback)" instead');if(typeof window==="undefined"){var windvane=this._app.requireModule("windvane");windvane.call({class:"MtopWVPlugin",method:"send",data:params},callback)}else{var stream=this._app.requireModule("stream");stream.sendMtop(params,callback)}}function $callWindvane(params,callback){console.warn("[JS Framework] Vm#$callWindvane is deprecated, "+"please use \"require('@weex-module/windvane')"+'.call(params, callback)" instead');var windvane=this._app.requireModule("windvane");windvane.call(params,callback)}function $setSpm(a,b){console.warn("[JS Framework] Vm#$setSpm is deprecated, "+"please use \"require('@weex-module/pageInfo')"+'.setSpm(a, b)" instead');var pageInfo=this._app.requireModule("pageInfo");pageInfo.setSpm(a,b)}function $getUserInfo(callback){console.warn("[JS Framework] Vm#$getUserInfo is deprecated, "+"please use \"require('@weex-module/user')"+'.getUserInfo(callback)" instead');var user=this._app.requireModule("user");user.getUserInfo(callback)}function $login(callback){console.warn("[JS Framework] Vm#$login is deprecated, "+"please use \"require('@weex-module/user')"+'.login(callback)" instead');var user=this._app.requireModule("user");user.login(callback)}function $logout(callback){console.warn("[JS Framework] Vm#$logout is deprecated, "+"please use \"require('@weex-module/user')"+'.logout(callback)" instead');var user=this._app.requireModule("user");user.logout(callback)}}]); \ No newline at end of file +(this.nativeLog || function(s) {console.log(s)})('START JS FRAMEWORK: 0.19.0 Build 2016-12-23 02:32'); +(this.getJSFMVersion = function(){return "0.19.0"});var global = this, process = { env: {} };var setTimeout = global.setTimeout; + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + +var subversion = {"browser":"0.5.0","framework":"0.19.0","transformer":">=0.1.5 <0.4"}; + +/* eslint-disable */ + +// Production steps of ECMA-262, Edition 6, 22.1.2.1 +// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from + +/* istanbul ignore if */ +if (!Array.from) { + Array.from = (function() { + var toStr = Object.prototype.toString; + var isCallable = function(fn) { + return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; + }; + var toInteger = function(value) { + var number = Number(value); + if (isNaN(number)) { + return 0; + } + if (number === 0 || !isFinite(number)) { + return number; + } + return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); + }; + var maxSafeInteger = Math.pow(2, 53) - 1; + var toLength = function(value) { + var len = toInteger(value); + return Math.min(Math.max(len, 0), maxSafeInteger); + }; + + // The length property of the from method is 1. + return function from(arrayLike/*, mapFn, thisArg */) { + // 1. Let C be the this value. + var C = this; + + // 2. Let items be ToObject(arrayLike). + var items = Object(arrayLike); + + // 3. ReturnIfAbrupt(items). + if (arrayLike == null) { + throw new TypeError('Array.from requires an array-like object - not null or undefined'); + } + + // 4. If mapfn is undefined, then let mapping be false. + var mapFn = arguments.length > 1 ? arguments[1] : void undefined; + var T; + if (typeof mapFn !== 'undefined') { + // 5. else + // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. + if (!isCallable(mapFn)) { + throw new TypeError('Array.from: when provided, the second argument must be a function'); + } + + // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 2) { + T = arguments[2]; + } + } + + // 10. Let lenValue be Get(items, "length"). + // 11. Let len be ToLength(lenValue). + var len = toLength(items.length); + + // 13. If IsConstructor(C) is true, then + // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. + // 14. a. Else, Let A be ArrayCreate(len). + var A = isCallable(C) ? Object(new C(len)) : new Array(len); + + // 16. Let k be 0. + var k = 0; + // 17. Repeat, while k < len… (also steps a - h) + var kValue; + while (k < len) { + kValue = items[k]; + if (mapFn) { + A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); + } else { + A[k] = kValue; + } + k += 1; + } + // 18. Let putStatus be Put(A, "length", len, true). + A.length = len; + // 20. Return A. + return A; + }; + }()); +} + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + + +function unwrapExports (x) { + return x && x.__esModule ? x['default'] : x; +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var _global = createCommonjsModule(function (module) { +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number'){ __g = global; } // eslint-disable-line no-undef +}); + +var _core = createCommonjsModule(function (module) { +var core = module.exports = {version: '2.4.0'}; +if(typeof __e == 'number'){ __e = core; } // eslint-disable-line no-undef +}); + +var _isObject = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + +var isObject = _isObject; +var _anObject = function(it){ + if(!isObject(it)){ throw TypeError(it + ' is not an object!'); } + return it; +}; + +var _fails = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; + +// Thank's IE8 for his funny defineProperty +var _descriptors = !_fails(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); + +var isObject$1 = _isObject; +var document$1 = _global.document; +var is = isObject$1(document$1) && isObject$1(document$1.createElement); +var _domCreate = function(it){ + return is ? document$1.createElement(it) : {}; +}; + +var _ie8DomDefine = !_descriptors && !_fails(function(){ + return Object.defineProperty(_domCreate('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); + +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject$2 = _isObject; +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +var _toPrimitive = function(it, S){ + if(!isObject$2(it)){ return it; } + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject$2(val = fn.call(it))){ return val; } + if(typeof (fn = it.valueOf) == 'function' && !isObject$2(val = fn.call(it))){ return val; } + if(!S && typeof (fn = it.toString) == 'function' && !isObject$2(val = fn.call(it))){ return val; } + throw TypeError("Can't convert object to primitive value"); +}; + +var anObject = _anObject; +var IE8_DOM_DEFINE = _ie8DomDefine; +var toPrimitive = _toPrimitive; +var dP$1 = Object.defineProperty; + +var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE){ try { + return dP$1(O, P, Attributes); + } catch(e){ /* empty */ } } + if('get' in Attributes || 'set' in Attributes){ throw TypeError('Accessors not supported!'); } + if('value' in Attributes){ O[P] = Attributes.value; } + return O; +}; + +var _objectDp = { + f: f +}; + +var _propertyDesc = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; + +var dP = _objectDp; +var createDesc = _propertyDesc; +var _hide = _descriptors ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; + +var hasOwnProperty = {}.hasOwnProperty; +var _has = function(it, key){ + return hasOwnProperty.call(it, key); +}; + +var id = 0; +var px = Math.random(); +var _uid = function(key){ + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + +var _redefine = createCommonjsModule(function (module) { +var global = _global + , hide = _hide + , has = _has + , SRC = _uid('src') + , TO_STRING = 'toString' + , $toString = Function[TO_STRING] + , TPL = ('' + $toString).split(TO_STRING); + +_core.inspectSource = function(it){ + return $toString.call(it); +}; + +(module.exports = function(O, key, val, safe){ + var isFunction = typeof val == 'function'; + if(isFunction){ has(val, 'name') || hide(val, 'name', key); } + if(O[key] === val){ return; } + if(isFunction){ has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); } + if(O === global){ + O[key] = val; + } else { + if(!safe){ + delete O[key]; + hide(O, key, val); + } else { + if(O[key]){ O[key] = val; } + else { hide(O, key, val); } + } + } +// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative +})(Function.prototype, TO_STRING, function toString(){ + return typeof this == 'function' && this[SRC] || $toString.call(this); +}); +}); + +var _aFunction = function(it){ + if(typeof it != 'function'){ throw TypeError(it + ' is not a function!'); } + return it; +}; + +// optional / simple context binding +var aFunction = _aFunction; +var _ctx = function(fn, that, length){ + aFunction(fn); + if(that === undefined){ return fn; } + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; + +var global$1 = _global; +var core = _core; +var hide = _hide; +var redefine = _redefine; +var ctx = _ctx; +var PROTOTYPE = 'prototype'; + +var $export$1 = function(type, name, source){ + var IS_FORCED = type & $export$1.F + , IS_GLOBAL = type & $export$1.G + , IS_STATIC = type & $export$1.S + , IS_PROTO = type & $export$1.P + , IS_BIND = type & $export$1.B + , target = IS_GLOBAL ? global$1 : IS_STATIC ? global$1[name] || (global$1[name] = {}) : (global$1[name] || {})[PROTOTYPE] + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}) + , key, own, out, exp; + if(IS_GLOBAL){ source = name; } + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? ctx(out, global$1) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // extend global + if(target){ redefine(target, key, out, type & $export$1.U); } + // export + if(exports[key] != out){ hide(exports, key, exp); } + if(IS_PROTO && expProto[key] != out){ expProto[key] = out; } + } +}; +global$1.core = core; +// type bitmap +$export$1.F = 1; // forced +$export$1.G = 2; // global +$export$1.S = 4; // static +$export$1.P = 8; // proto +$export$1.B = 16; // bind +$export$1.W = 32; // wrap +$export$1.U = 64; // safe +$export$1.R = 128; // real proto method for `library` +var _export = $export$1; + +var toString$1 = {}.toString; + +var _cof = function(it){ + return toString$1.call(it).slice(8, -1); +}; + +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = _cof; +var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function(it){ + return cof(it) == 'String' ? it.split('') : Object(it); +}; + +// 7.2.1 RequireObjectCoercible(argument) +var _defined = function(it){ + if(it == undefined){ throw TypeError("Can't call method on " + it); } + return it; +}; + +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject$1 = _iobject; +var defined = _defined; +var _toIobject = function(it){ + return IObject$1(defined(it)); +}; + +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +var _toInteger = function(it){ + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + +// 7.1.15 ToLength +var toInteger = _toInteger; +var min = Math.min; +var _toLength = function(it){ + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + +var toInteger$1 = _toInteger; +var max = Math.max; +var min$1 = Math.min; +var _toIndex = function(index, length){ + index = toInteger$1(index); + return index < 0 ? max(index + length, 0) : min$1(index, length); +}; + +// false -> Array#indexOf +// true -> Array#includes +var toIObject$1 = _toIobject; +var toLength = _toLength; +var toIndex = _toIndex; +var _arrayIncludes = function(IS_INCLUDES){ + return function($this, el, fromIndex){ + var O = toIObject$1($this) + , length = toLength(O.length) + , index = toIndex(fromIndex, length) + , value; + // Array#includes uses SameValueZero equality algorithm + if(IS_INCLUDES && el != el){ while(length > index){ + value = O[index++]; + if(value != value){ return true; } + // Array#toIndex ignores holes, Array#includes - not + } } else { for(;length > index; index++){ if(IS_INCLUDES || index in O){ + if(O[index] === el){ return IS_INCLUDES || index || 0; } + } } } return !IS_INCLUDES && -1; + }; +}; + +var global$2 = _global; +var SHARED = '__core-js_shared__'; +var store = global$2[SHARED] || (global$2[SHARED] = {}); +var _shared = function(key){ + return store[key] || (store[key] = {}); +}; + +var shared = _shared('keys'); +var uid = _uid; +var _sharedKey = function(key){ + return shared[key] || (shared[key] = uid(key)); +}; + +var has$1 = _has; +var toIObject = _toIobject; +var arrayIndexOf = _arrayIncludes(false); +var IE_PROTO = _sharedKey('IE_PROTO'); + +var _objectKeysInternal = function(object, names){ + var O = toIObject(object) + , i = 0 + , result = [] + , key; + for(key in O){ if(key != IE_PROTO){ has$1(O, key) && result.push(key); } } + // Don't enum bug & hidden keys + while(names.length > i){ if(has$1(O, key = names[i++])){ + ~arrayIndexOf(result, key) || result.push(key); + } } + return result; +}; + +// IE 8- don't enum bug keys +var _enumBugKeys = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = _objectKeysInternal; +var enumBugKeys = _enumBugKeys; + +var _objectKeys = Object.keys || function keys(O){ + return $keys(O, enumBugKeys); +}; + +var f$1 = Object.getOwnPropertySymbols; + +var _objectGops = { + f: f$1 +}; + +var f$2 = {}.propertyIsEnumerable; + +var _objectPie = { + f: f$2 +}; + +// 7.1.13 ToObject(argument) +var defined$1 = _defined; +var _toObject = function(it){ + return Object(defined$1(it)); +}; + +// 19.1.2.1 Object.assign(target, source, ...) +var getKeys = _objectKeys; +var gOPS = _objectGops; +var pIE = _objectPie; +var toObject = _toObject; +var IObject = _iobject; +var $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +var _objectAssign = !$assign || _fails(function(){ + var A = {} + , B = {} + , S = Symbol() + , K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function(k){ B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source){ + var arguments$1 = arguments; + // eslint-disable-line no-unused-vars + var T = toObject(target) + , aLen = arguments.length + , index = 1 + , getSymbols = gOPS.f + , isEnum = pIE.f; + while(aLen > index){ + var S = IObject(arguments$1[index++]) + , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) + , length = keys.length + , j = 0 + , key; + while(length > j){ if(isEnum.call(S, key = keys[j++])){ T[key] = S[key]; } } + } return T; +} : $assign; + +// 19.1.3.1 Object.assign(target, source) +var $export = _export; + +$export($export.S + $export.F, 'Object', {assign: _objectAssign}); + +/* eslint-disable */ + +// https://gist.github.com/WebReflection/5593554 + +/* istanbul ignore if */ +if (!Object.setPrototypeOf) { + Object.setPrototypeOf = (function(Object, magic) { + var set; + function setPrototypeOf(O, proto) { + set.call(O, proto); + return O; + } + try { + // this works already in Firefox and Safari + set = Object.getOwnPropertyDescriptor(Object.prototype, magic).set; + set.call({}, null); + } catch (e) { + if ( + // IE < 11 cannot be shimmed + Object.prototype !== {}[magic] || + // neither can any browser that actually + // implemented __proto__ correctly + // (all but old V8 will return here) + {__proto__: null}.__proto__ === void 0 + // this case means null objects cannot be passed + // through setPrototypeOf in a reliable way + // which means here a **Sham** is needed instead + ) { + return; + } + // nodejs 0.8 and 0.10 are (buggy and..) fine here + // probably Chrome or some old Mobile stock browser + set = function(proto) { + this[magic] = proto; + }; + // please note that this will **not** work + // in those browsers that do not inherit + // __proto__ by mistake from Object.prototype + // in these cases we should probably throw an error + // or at least be informed about the issue + setPrototypeOf.polyfill = setPrototypeOf( + setPrototypeOf({}, null), + Object.prototype + ) instanceof Object; + // setPrototypeOf.polyfill === true means it works as meant + // setPrototypeOf.polyfill === false means it's not 100% reliable + // setPrototypeOf.polyfill === undefined + // or + // setPrototypeOf.polyfill == null means it's not a polyfill + // which means it works as expected + // we can even delete Object.prototype.__proto__; + } + return setPrototypeOf; + }(Object, '__proto__')); +} + +// fix Promise Problem on JSContext of iOS7~8 +// @see https://bugs.webkit.org/show_bug.cgi?id=135866 +var ref = commonjsGlobal; +var WXEnvironment = ref.WXEnvironment; + +/* istanbul ignore next */ +if (WXEnvironment && WXEnvironment.platform === 'iOS') { + commonjsGlobal.Promise = undefined; +} + +var _wks = createCommonjsModule(function (module) { +var store = _shared('wks') + , uid = _uid + , Symbol = _global.Symbol + , USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function(name){ + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; +}); + +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof$1 = _cof; +var TAG = _wks('toStringTag'); +var ARG = cof$1(function(){ return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function(it, key){ + try { + return it[key]; + } catch(e){ /* empty */ } +}; + +var _classof = function(it){ + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof$1(O) + // ES3 arguments fallback + : (B = cof$1(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; + +// 19.1.3.6 Object.prototype.toString() +var classof = _classof; +var test = {}; +test[_wks('toStringTag')] = 'z'; +if(test + '' != '[object z]'){ + _redefine(Object.prototype, 'toString', function toString(){ + return '[object ' + classof(this) + ']'; + }, true); +} + +var toInteger$2 = _toInteger; +var defined$2 = _defined; +// true -> String#at +// false -> String#codePointAt +var _stringAt = function(TO_STRING){ + return function(that, pos){ + var s = String(defined$2(that)) + , i = toInteger$2(pos) + , l = s.length + , a, b; + if(i < 0 || i >= l){ return TO_STRING ? '' : undefined; } + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; +}; + +var _library = false; + +var _iterators = {}; + +var dP$2 = _objectDp; +var anObject$2 = _anObject; +var getKeys$1 = _objectKeys; + +var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties){ + anObject$2(O); + var keys = getKeys$1(Properties) + , length = keys.length + , i = 0 + , P; + while(length > i){ dP$2.f(O, P = keys[i++], Properties[P]); } + return O; +}; + +var _html = _global.document && document.documentElement; + +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject$1 = _anObject; +var dPs = _objectDps; +var enumBugKeys$1 = _enumBugKeys; +var IE_PROTO$1 = _sharedKey('IE_PROTO'); +var Empty = function(){ /* empty */ }; +var PROTOTYPE$1 = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function(){ + // Thrash, waste and sodomy: IE GC bug + var iframe = _domCreate('iframe') + , i = enumBugKeys$1.length + , lt = '<' + , gt = '>' + , iframeDocument; + iframe.style.display = 'none'; + _html.appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while(i--){ delete createDict[PROTOTYPE$1][enumBugKeys$1[i]]; } + return createDict(); +}; + +var _objectCreate = Object.create || function create(O, Properties){ + var result; + if(O !== null){ + Empty[PROTOTYPE$1] = anObject$1(O); + result = new Empty; + Empty[PROTOTYPE$1] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO$1] = O; + } else { result = createDict(); } + return Properties === undefined ? result : dPs(result, Properties); +}; + +var def = _objectDp.f; +var has$3 = _has; +var TAG$1 = _wks('toStringTag'); + +var _setToStringTag = function(it, tag, stat){ + if(it && !has$3(it = stat ? it : it.prototype, TAG$1)){ def(it, TAG$1, {configurable: true, value: tag}); } +}; + +var create$1 = _objectCreate; +var descriptor = _propertyDesc; +var setToStringTag$1 = _setToStringTag; +var IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +_hide(IteratorPrototype, _wks('iterator'), function(){ return this; }); + +var _iterCreate = function(Constructor, NAME, next){ + Constructor.prototype = create$1(IteratorPrototype, {next: descriptor(1, next)}); + setToStringTag$1(Constructor, NAME + ' Iterator'); +}; + +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has$4 = _has; +var toObject$1 = _toObject; +var IE_PROTO$2 = _sharedKey('IE_PROTO'); +var ObjectProto = Object.prototype; + +var _objectGpo = Object.getPrototypeOf || function(O){ + O = toObject$1(O); + if(has$4(O, IE_PROTO$2)){ return O[IE_PROTO$2]; } + if(typeof O.constructor == 'function' && O instanceof O.constructor){ + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + +var LIBRARY = _library; +var $export$2 = _export; +var redefine$1 = _redefine; +var hide$1 = _hide; +var has$2 = _has; +var Iterators = _iterators; +var $iterCreate = _iterCreate; +var setToStringTag = _setToStringTag; +var getPrototypeOf = _objectGpo; +var ITERATOR = _wks('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; + +var returnThis = function(){ return this; }; + +var _iterDefine = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ + $iterCreate(Constructor, NAME, next); + var getMethod = function(kind){ + if(!BUGGY && kind in proto){ return proto[kind]; } + switch(kind){ + case KEYS: return function keys(){ return new Constructor(this, kind); }; + case VALUES: return function values(){ return new Constructor(this, kind); }; + } return function entries(){ return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator' + , DEF_VALUES = DEFAULT == VALUES + , VALUES_BUG = false + , proto = Base.prototype + , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] + , $default = $native || getMethod(DEFAULT) + , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined + , $anyNative = NAME == 'Array' ? proto.entries || $native : $native + , methods, key, IteratorPrototype; + // Fix native + if($anyNative){ + IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); + if(IteratorPrototype !== Object.prototype){ + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if(!LIBRARY && !has$2(IteratorPrototype, ITERATOR)){ hide$1(IteratorPrototype, ITERATOR, returnThis); } + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if(DEF_VALUES && $native && $native.name !== VALUES){ + VALUES_BUG = true; + $default = function values(){ return $native.call(this); }; + } + // Define iterator + if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ + hide$1(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if(DEFAULT){ + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if(FORCED){ for(key in methods){ + if(!(key in proto)){ redefine$1(proto, key, methods[key]); } + } } else { $export$2($export$2.P + $export$2.F * (BUGGY || VALUES_BUG), NAME, methods); } + } + return methods; +}; + +var $at = _stringAt(true); + +// 21.1.3.27 String.prototype[@@iterator]() +_iterDefine(String, 'String', function(iterated){ + this._t = String(iterated); // target + this._i = 0; // next index +// 21.1.5.2.1 %StringIteratorPrototype%.next() +}, function(){ + var O = this._t + , index = this._i + , point; + if(index >= O.length){ return {value: undefined, done: true}; } + point = $at(O, index); + this._i += point.length; + return {value: point, done: false}; +}); + +// 22.1.3.31 Array.prototype[@@unscopables] +var UNSCOPABLES = _wks('unscopables'); +var ArrayProto = Array.prototype; +if(ArrayProto[UNSCOPABLES] == undefined){ _hide(ArrayProto, UNSCOPABLES, {}); } +var _addToUnscopables = function(key){ + ArrayProto[UNSCOPABLES][key] = true; +}; + +var _iterStep = function(done, value){ + return {value: value, done: !!done}; +}; + +var addToUnscopables = _addToUnscopables; +var step = _iterStep; +var Iterators$2 = _iterators; +var toIObject$2 = _toIobject; + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +var es6_array_iterator = _iterDefine(Array, 'Array', function(iterated, kind){ + this._t = toIObject$2(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function(){ + var O = this._t + , kind = this._k + , index = this._i++; + if(!O || index >= O.length){ + this._t = undefined; + return step(1); + } + if(kind == 'keys' ){ return step(0, index); } + if(kind == 'values'){ return step(0, O[index]); } + return step(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators$2.Arguments = Iterators$2.Array; + +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); + +var $iterators = es6_array_iterator; +var redefine$2 = _redefine; +var global$3 = _global; +var hide$2 = _hide; +var Iterators$1 = _iterators; +var wks = _wks; +var ITERATOR$1 = wks('iterator'); +var TO_STRING_TAG = wks('toStringTag'); +var ArrayValues = Iterators$1.Array; + +for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){ + var NAME = collections[i] + , Collection = global$3[NAME] + , proto = Collection && Collection.prototype + , key; + if(proto){ + if(!proto[ITERATOR$1]){ hide$2(proto, ITERATOR$1, ArrayValues); } + if(!proto[TO_STRING_TAG]){ hide$2(proto, TO_STRING_TAG, NAME); } + Iterators$1[NAME] = ArrayValues; + for(key in $iterators){ if(!proto[key]){ redefine$2(proto, key, $iterators[key], true); } } + } +} + +var _anInstance = function(it, Constructor, name, forbiddenField){ + if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){ + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + +// call something on iterator step with safe closing on error +var anObject$3 = _anObject; +var _iterCall = function(iterator, fn, value, entries){ + try { + return entries ? fn(anObject$3(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch(e){ + var ret = iterator['return']; + if(ret !== undefined){ anObject$3(ret.call(iterator)); } + throw e; + } +}; + +// check on default Array iterator +var Iterators$3 = _iterators; +var ITERATOR$2 = _wks('iterator'); +var ArrayProto$1 = Array.prototype; + +var _isArrayIter = function(it){ + return it !== undefined && (Iterators$3.Array === it || ArrayProto$1[ITERATOR$2] === it); +}; + +var classof$2 = _classof; +var ITERATOR$3 = _wks('iterator'); +var Iterators$4 = _iterators; +var core_getIteratorMethod = _core.getIteratorMethod = function(it){ + if(it != undefined){ return it[ITERATOR$3] + || it['@@iterator'] + || Iterators$4[classof$2(it)]; } +}; + +var _forOf = createCommonjsModule(function (module) { +var ctx = _ctx + , call = _iterCall + , isArrayIter = _isArrayIter + , anObject = _anObject + , toLength = _toLength + , getIterFn = core_getIteratorMethod + , BREAK = {} + , RETURN = {}; +var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){ + var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable) + , f = ctx(fn, that, entries ? 2 : 1) + , index = 0 + , length, step, iterator, result; + if(typeof iterFn != 'function'){ throw TypeError(iterable + ' is not iterable!'); } + // fast case for arrays with default iterator + if(isArrayIter(iterFn)){ for(length = toLength(iterable.length); length > index; index++){ + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if(result === BREAK || result === RETURN){ return result; } + } } else { for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ + result = call(iterator, f, step.value, entries); + if(result === BREAK || result === RETURN){ return result; } + } } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; +}); + +// 7.3.20 SpeciesConstructor(O, defaultConstructor) +var anObject$4 = _anObject; +var aFunction$2 = _aFunction; +var SPECIES = _wks('species'); +var _speciesConstructor = function(O, D){ + var C = anObject$4(O).constructor, S; + return C === undefined || (S = anObject$4(C)[SPECIES]) == undefined ? D : aFunction$2(S); +}; + +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +var _invoke = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; + +var ctx$2 = _ctx; +var invoke = _invoke; +var html = _html; +var cel = _domCreate; +var global$5 = _global; +var process$2 = global$5.process; +var setTask = global$5.setImmediate; +var clearTask = global$5.clearImmediate; +var MessageChannel = global$5.MessageChannel; +var counter = 0; +var queue = {}; +var ONREADYSTATECHANGE = 'onreadystatechange'; +var defer; +var channel; +var port; +var run$1 = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run$1.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var arguments$1 = arguments; + + var args = [], i = 1; + while(arguments.length > i){ args.push(arguments$1[i++]); } + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(_cof(process$2) == 'process'){ + defer = function(id){ + process$2.nextTick(ctx$2(run$1, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx$2(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global$5.addEventListener && typeof postMessage == 'function' && !global$5.importScripts){ + defer = function(id){ + global$5.postMessage(id + '', '*'); + }; + global$5.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run$1.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx$2(run$1, id, 1), 0); + }; + } +} +var _task = { + set: setTask, + clear: clearTask +}; + +var global$6 = _global; +var macrotask = _task.set; +var Observer = global$6.MutationObserver || global$6.WebKitMutationObserver; +var process$3 = global$6.process; +var Promise$1 = global$6.Promise; +var isNode$1 = _cof(process$3) == 'process'; + +var _microtask = function(){ + var head, last, notify; + + var flush = function(){ + var parent, fn; + if(isNode$1 && (parent = process$3.domain)){ parent.exit(); } + while(head){ + fn = head.fn; + head = head.next; + try { + fn(); + } catch(e){ + if(head){ notify(); } + else { last = undefined; } + throw e; + } + } last = undefined; + if(parent){ parent.enter(); } + }; + + // Node.js + if(isNode$1){ + notify = function(){ + process$3.nextTick(flush); + }; + // browsers with MutationObserver + } else if(Observer){ + var toggle = true + , node = document.createTextNode(''); + new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new + notify = function(){ + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if(Promise$1 && Promise$1.resolve){ + var promise = Promise$1.resolve(); + notify = function(){ + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function(){ + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global$6, flush); + }; + } + + return function(fn){ + var task = {fn: fn, next: undefined}; + if(last){ last.next = task; } + if(!head){ + head = task; + notify(); + } last = task; + }; +}; + +var redefine$3 = _redefine; +var _redefineAll = function(target, src, safe){ + for(var key in src){ redefine$3(target, key, src[key], safe); } + return target; +}; + +var global$7 = _global; +var dP$3 = _objectDp; +var DESCRIPTORS = _descriptors; +var SPECIES$1 = _wks('species'); + +var _setSpecies = function(KEY){ + var C = global$7[KEY]; + if(DESCRIPTORS && C && !C[SPECIES$1]){ dP$3.f(C, SPECIES$1, { + configurable: true, + get: function(){ return this; } + }); } +}; + +var ITERATOR$4 = _wks('iterator'); +var SAFE_CLOSING = false; + +try { + var riter = [7][ITERATOR$4](); + riter['return'] = function(){ SAFE_CLOSING = true; }; + Array.from(riter, function(){ throw 2; }); +} catch(e){ /* empty */ } + +var _iterDetect = function(exec, skipClosing){ + if(!skipClosing && !SAFE_CLOSING){ return false; } + var safe = false; + try { + var arr = [7] + , iter = arr[ITERATOR$4](); + iter.next = function(){ return {done: safe = true}; }; + arr[ITERATOR$4] = function(){ return iter; }; + exec(arr); + } catch(e){ /* empty */ } + return safe; +}; + +var LIBRARY$1 = _library; +var global$4 = _global; +var ctx$1 = _ctx; +var classof$1 = _classof; +var $export$3 = _export; +var isObject$3 = _isObject; +var aFunction$1 = _aFunction; +var anInstance = _anInstance; +var forOf = _forOf; +var speciesConstructor = _speciesConstructor; +var task = _task.set; +var microtask = _microtask(); +var PROMISE = 'Promise'; +var TypeError$1 = global$4.TypeError; +var process$1 = global$4.process; +var $Promise = global$4[PROMISE]; +var process$1 = global$4.process; +var isNode = classof$1(process$1) == 'process'; +var empty = function(){ /* empty */ }; +var Internal; +var GenericPromiseCapability; +var Wrapper; + +var USE_NATIVE = !!function(){ + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1) + , FakePromise = (promise.constructor = {})[_wks('species')] = function(exec){ exec(empty, empty); }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + } catch(e){ /* empty */ } +}(); + +// helpers +var sameConstructor = function(a, b){ + // with library wrapper special case + return a === b || a === $Promise && b === Wrapper; +}; +var isThenable = function(it){ + var then; + return isObject$3(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var newPromiseCapability = function(C){ + return sameConstructor($Promise, C) + ? new PromiseCapability(C) + : new GenericPromiseCapability(C); +}; +var PromiseCapability = GenericPromiseCapability = function(C){ + var resolve, reject; + this.promise = new C(function($$resolve, $$reject){ + if(resolve !== undefined || reject !== undefined){ throw TypeError$1('Bad Promise constructor'); } + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction$1(resolve); + this.reject = aFunction$1(reject); +}; +var perform = function(exec){ + try { + exec(); + } catch(e){ + return {error: e}; + } +}; +var notify$1 = function(promise, isReject){ + if(promise._n){ return; } + promise._n = true; + var chain = promise._c; + microtask(function(){ + var value = promise._v + , ok = promise._s == 1 + , i = 0; + var run = function(reaction){ + var handler = ok ? reaction.ok : reaction.fail + , resolve = reaction.resolve + , reject = reaction.reject + , domain = reaction.domain + , result, then; + try { + if(handler){ + if(!ok){ + if(promise._h == 2){ onHandleUnhandled(promise); } + promise._h = 1; + } + if(handler === true){ result = value; } + else { + if(domain){ domain.enter(); } + result = handler(value); + if(domain){ domain.exit(); } + } + if(result === reaction.promise){ + reject(TypeError$1('Promise-chain cycle')); + } else if(then = isThenable(result)){ + then.call(result, resolve, reject); + } else { resolve(result); } + } else { reject(value); } + } catch(e){ + reject(e); + } + }; + while(chain.length > i){ run(chain[i++]); } // variable length - can't use forEach + promise._c = []; + promise._n = false; + if(isReject && !promise._h){ onUnhandled(promise); } + }); +}; +var onUnhandled = function(promise){ + task.call(global$4, function(){ + var value = promise._v + , abrupt, handler, console; + if(isUnhandled(promise)){ + abrupt = perform(function(){ + if(isNode){ + process$1.emit('unhandledRejection', value, promise); + } else if(handler = global$4.onunhandledrejection){ + handler({promise: promise, reason: value}); + } else if((console = global$4.console) && console.error){ + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if(abrupt){ throw abrupt.error; } + }); +}; +var isUnhandled = function(promise){ + if(promise._h == 1){ return false; } + var chain = promise._a || promise._c + , i = 0 + , reaction; + while(chain.length > i){ + reaction = chain[i++]; + if(reaction.fail || !isUnhandled(reaction.promise)){ return false; } + } return true; +}; +var onHandleUnhandled = function(promise){ + task.call(global$4, function(){ + var handler; + if(isNode){ + process$1.emit('rejectionHandled', promise); + } else if(handler = global$4.onrejectionhandled){ + handler({promise: promise, reason: promise._v}); + } + }); +}; +var $reject = function(value){ + var promise = this; + if(promise._d){ return; } + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if(!promise._a){ promise._a = promise._c.slice(); } + notify$1(promise, true); +}; +var $resolve = function(value){ + var promise = this + , then; + if(promise._d){ return; } + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if(promise === value){ throw TypeError$1("Promise can't be resolved itself"); } + if(then = isThenable(value)){ + microtask(function(){ + var wrapper = {_w: promise, _d: false}; // wrap + try { + then.call(value, ctx$1($resolve, wrapper, 1), ctx$1($reject, wrapper, 1)); + } catch(e){ + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify$1(promise, false); + } + } catch(e){ + $reject.call({_w: promise, _d: false}, e); // wrap + } +}; + +// constructor polyfill +if(!USE_NATIVE){ + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor){ + anInstance(this, $Promise, PROMISE, '_h'); + aFunction$1(executor); + Internal.call(this); + try { + executor(ctx$1($resolve, this, 1), ctx$1($reject, this, 1)); + } catch(err){ + $reject.call(this, err); + } + }; + Internal = function Promise(executor){ + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = _redefineAll($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected){ + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process$1.domain : undefined; + this._c.push(reaction); + if(this._a){ this._a.push(reaction); } + if(this._s){ notify$1(this, false); } + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function(onRejected){ + return this.then(undefined, onRejected); + } + }); + PromiseCapability = function(){ + var promise = new Internal; + this.promise = promise; + this.resolve = ctx$1($resolve, promise, 1); + this.reject = ctx$1($reject, promise, 1); + }; +} + +$export$3($export$3.G + $export$3.W + $export$3.F * !USE_NATIVE, {Promise: $Promise}); +_setToStringTag($Promise, PROMISE); +_setSpecies(PROMISE); +Wrapper = _core[PROMISE]; + +// statics +$export$3($export$3.S + $export$3.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r){ + var capability = newPromiseCapability(this) + , $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +$export$3($export$3.S + $export$3.F * (LIBRARY$1 || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x){ + // instanceof instead of internal slot check because we should fix it without replacement native Promise core + if(x instanceof $Promise && sameConstructor(x.constructor, this)){ return x; } + var capability = newPromiseCapability(this) + , $$resolve = capability.resolve; + $$resolve(x); + return capability.promise; + } +}); +$export$3($export$3.S + $export$3.F * !(USE_NATIVE && _iterDetect(function(iter){ + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable){ + var C = this + , capability = newPromiseCapability(C) + , resolve = capability.resolve + , reject = capability.reject; + var abrupt = perform(function(){ + var values = [] + , index = 0 + , remaining = 1; + forOf(iterable, false, function(promise){ + var $index = index++ + , alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function(value){ + if(alreadyCalled){ return; } + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if(abrupt){ reject(abrupt.error); } + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable){ + var C = this + , capability = newPromiseCapability(C) + , reject = capability.reject; + var abrupt = perform(function(){ + forOf(iterable, false, function(promise){ + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if(abrupt){ reject(abrupt.error); } + return capability.promise; + } +}); + +/** + * @fileOverview + * This file will hack `console` methods by `WXEnvironment.logLevel`. + * So we can control how many and which messages will be sent by change the log level. + * Additionally in native platform the message content must be primitive values and + * using `nativeLog(...args, logLevelMark)` so we create a new `console` object in + * global add a format process for its methods. + */ + +var LEVELS = ['off', 'error', 'warn', 'info', 'log', 'debug']; +var levelMap = {}; + +var originalConsole = global.console; + +/** + * Hack console for native environment. + */ +function setNativeConsole () { + generateLevelMap(); + + /* istanbul ignore next */ + if ( + typeof global.console === 'undefined' || // Android + (global.WXEnvironment && global.WXEnvironment.platform === 'iOS') // iOS + ) { + global.console = { + debug: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('debug')) { global.nativeLog.apply(global, format(args).concat( ['__DEBUG'] )); } + }, + log: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('log')) { global.nativeLog.apply(global, format(args).concat( ['__LOG'] )); } + }, + info: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('info')) { global.nativeLog.apply(global, format(args).concat( ['__INFO'] )); } + }, + warn: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('warn')) { global.nativeLog.apply(global, format(args).concat( ['__WARN'] )); } + }, + error: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('error')) { global.nativeLog.apply(global, format(args).concat( ['__ERROR'] )); } + } + }; + } + else { // HTML5 or Node + var debug = console.debug; + var log = console.log; + var info = console.info; + var warn = console.warn; + var error = console.error; + console.__ori__ = { debug: debug, log: log, info: info, warn: warn, error: error }; + console.debug = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('debug')) { console.__ori__.debug.apply(console, args); } + }; + console.log = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('log')) { console.__ori__.log.apply(console, args); } + }; + console.info = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('info')) { console.__ori__.info.apply(console, args); } + }; + console.warn = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('warn')) { console.__ori__.warn.apply(console, args); } + }; + console.error = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (checkLevel('error')) { console.__ori__.error.apply(console, args); } + }; + } +} + +/** + * Reset hacked console to original. + */ +/* istanbul ignore next */ +function resetNativeConsole () { + levelMap = {}; + global.console = originalConsole; +} + +/** + * Generate map for which types of message will be sent in a certain message level + * as the order of LEVELS. + */ +function generateLevelMap () { + LEVELS.forEach(function (level) { + var levelIndex = LEVELS.indexOf(level); + levelMap[level] = {}; + LEVELS.forEach(function (type) { + var typeIndex = LEVELS.indexOf(type); + if (typeIndex <= levelIndex) { + levelMap[level][type] = true; + } + }); + }); +} + +/** + * Check if a certain type of message will be sent in current log level of env. + * @param {string} type + * @return {boolean} + */ +function checkLevel (type) { + var logLevel = (global.WXEnvironment && global.WXEnvironment.logLevel) || 'log'; + return levelMap[logLevel] && levelMap[logLevel][type] +} + +/** + * Convert all log arguments into primitive values. + * @param {array} args + * @return {array} + */ +/* istanbul ignore next */ +function format (args) { + return args.map(function (v) { + var type = Object.prototype.toString.call(v); + if (type.toLowerCase() === '[object object]') { + v = JSON.stringify(v); + } + else { + v = String(v); + } + return v + }) +} + +/** + * @fileOverview + * Polyfill `setTimeout` on Android V8 using native method + * `setTimeoutNative(callbackId, time)` and JS method + * `setTimeoutCallback(callbackId)`. + * This polyfill is only used in virtual-DOM diff & flush agorithm. Not + * accessed by JS Bundle code (The timer APIs polyfill for JS Bundle is in + * `html5/default/app/ctrl.js`). + */ + +var originalSetTimeout = global.setTimeout; +var setTimeoutNative = global.setTimeoutNative; + +/** + * Set up native timer + */ +/* istanbul ignore next */ +function setNativeTimer () { + if (typeof setTimeout === 'undefined' && + typeof setTimeoutNative === 'function') { + var timeoutMap = {}; + var timeoutId = 0; + + global.setTimeout = function (cb, time) { + timeoutMap[++timeoutId] = cb; + setTimeoutNative(timeoutId.toString(), time); + }; + + global.setTimeoutCallback = function (id) { + if (typeof timeoutMap[id] === 'function') { + timeoutMap[id](); + delete timeoutMap[id]; + } + }; + } +} + +/* istanbul ignore next */ +function resetNativeTimer () { + global.setTimeout = originalSetTimeout; + global.setTimeoutCallback = null; +} + +/** + * Freeze the prototype of javascript build-in objects. + */ +/* istanbul ignore next */ +function freezePrototype$1 () { + Object.freeze(Object); + Object.freeze(Array); + + Object.freeze(Object.prototype); + Object.freeze(Array.prototype); + Object.freeze(String.prototype); + Object.freeze(Number.prototype); + Object.freeze(Boolean.prototype); + + Object.freeze(Error.prototype); + Object.freeze(Date.prototype); + Object.freeze(RegExp.prototype); +} + +// import promise hack and polyfills + +var fallback = function () {}; + +var TaskCenter = function TaskCenter (id, sendTasks) { + this.instanceId = id; + fallback = sendTasks || function () {}; +}; + +TaskCenter.prototype.send = function send (type, options, args) { + var action = options.action; + var component = options.component; + var ref = options.ref; + var module = options.module; + var method = options.method; + + switch (type) { + case 'dom': + return this[action](this.instanceId, args) + case 'component': + return this.componentHandler(this.instanceId, ref, method, args, { component: component }) + case 'module': + return this.moduleHandler(this.instanceId, module, method, args, {}) + } +}; + +function init$2 () { + var DOM_METHODS = { + createFinish: global.callCreateFinish, + updateFinish: global.callUpdateFinish, + refreshFinish: global.callRefreshFinish, + + createBody: global.callCreateBody, + + addElement: global.callAddElement, + removeElement: global.callRemoveElement, + moveElement: global.callMoveElement, + updateAttrs: global.callUpdateAttrs, + updateStyle: global.callUpdateStyle, + + addEvent: global.callAddEvent, + removeEvent: global.callRemoveEvent + }; + var proto = TaskCenter.prototype; + + var loop = function ( name ) { + var method = DOM_METHODS[name]; + proto[name] = method ? + function (id, args) { return method.apply(void 0, [ id ].concat( args )); } : + function (id, args) { return fallback(id, [{ module: 'dom', method: name, args: args }]); }; + }; + + for (var name in DOM_METHODS) loop( name ); + + proto.componentHandler = global.callNativeComponent || + (function (id, ref, method, args, options) { return fallback(id, [{ component: options.component, ref: ref, method: method, args: args }]); }); + + proto.moduleHandler = global.callNativeModule || + (function (id, module, method, args) { return fallback(id, [{ module: module, method: method, args: args }]); }); +} + +var docMap = {}; + +/** + * Add a document object into docMap. + * @param {string} id + * @param {object} document + */ +function addDoc (id, doc) { + if (id) { + docMap[id] = doc; + } +} + +/** + * Get the document object by id. + * @param {string} id + */ +function getDoc (id) { + return docMap[id] +} + +/** + * Remove the document from docMap by id. + * @param {string} id + */ +function removeDoc (id) { + delete docMap[id]; +} + +/** + * @deprecated + * Get listener by document id. + * @param {string} id + * @return {object} listener + */ + + +/** + * Get TaskCenter instance by id. + * @param {string} id + * @return {object} TaskCenter + */ +function getTaskCenter (id) { + var doc = docMap[id]; + if (doc && doc.taskCenter) { + return doc.taskCenter + } + return null +} + +/** + * Get a unique id. + */ +var nextNodeRef = 1; +function uniqueId () { + return (nextNodeRef++).toString() +} + +/** + * Append body node to documentElement. + * @param {object} document + * @param {object} node + * @param {object} before + */ +function appendBody (doc, node, before) { + var documentElement = doc.documentElement; + + if (documentElement.pureChildren.length > 0 || node.parentNode) { + return + } + var children = documentElement.children; + var beforeIndex = children.indexOf(before); + if (beforeIndex < 0) { + children.push(node); + } + else { + children.splice(beforeIndex, 0, node); + } + + if (node.nodeType === 1) { + if (node.role === 'body') { + node.docId = doc.id; + node.ownerDocument = doc; + node.parentNode = documentElement; + linkParent(node, documentElement); + } + else { + node.children.forEach(function (child) { + child.parentNode = node; + }); + setBody(doc, node); + node.docId = doc.id; + node.ownerDocument = doc; + linkParent(node, documentElement); + delete doc.nodeMap[node.nodeId]; + } + documentElement.pureChildren.push(node); + sendBody(doc, node); + } + else { + node.parentNode = documentElement; + doc.nodeMap[node.ref] = node; + } +} + +function sendBody (doc, node) { + var body = node.toJSON(); + var children = body.children; + delete body.children; + var result = doc.taskCenter.send('dom', { action: 'createBody' }, [body]); + if (children) { + children.forEach(function (child) { + result = doc.taskCenter.send('dom', { action: 'addElement' }, [body.ref, child, -1]); + }); + } + return result +} + +/** + * Set up body node. + * @param {object} document + * @param {object} element + */ +function setBody (doc, el) { + el.role = 'body'; + el.depth = 1; + delete doc.nodeMap[el.nodeId]; + el.ref = '_root'; + doc.nodeMap._root = el; + doc.body = el; +} + +/** + * Establish the connection between parent and child node. + * @param {object} child node + * @param {object} parent node + */ +function linkParent (node, parent) { + node.parentNode = parent; + if (parent.docId) { + node.docId = parent.docId; + node.ownerDocument = parent.ownerDocument; + node.ownerDocument.nodeMap[node.nodeId] = node; + node.depth = parent.depth + 1; + } + node.children.forEach(function (child) { + linkParent(child, node); + }); +} + +/** + * Get the next sibling element. + * @param {object} node + */ +function nextElement (node) { + while (node) { + if (node.nodeType === 1) { + return node + } + node = node.nextSibling; + } +} + +/** + * Get the previous sibling element. + * @param {object} node + */ +function previousElement (node) { + while (node) { + if (node.nodeType === 1) { + return node + } + node = node.previousSibling; + } +} + +/** + * Insert a node into list at the specified index. + * @param {object} target node + * @param {array} list + * @param {number} newIndex + * @param {boolean} changeSibling + * @return {number} newIndex + */ +function insertIndex (target, list, newIndex, changeSibling) { + /* istanbul ignore next */ + if (newIndex < 0) { + newIndex = 0; + } + var before = list[newIndex - 1]; + var after = list[newIndex]; + list.splice(newIndex, 0, target); + if (changeSibling) { + before && (before.nextSibling = target); + target.previousSibling = before; + target.nextSibling = after; + after && (after.previousSibling = target); + } + return newIndex +} + +/** + * Move the node to a new index in list. + * @param {object} target node + * @param {array} list + * @param {number} newIndex + * @param {boolean} changeSibling + * @return {number} newIndex + */ +function moveIndex (target, list, newIndex, changeSibling) { + var index = list.indexOf(target); + /* istanbul ignore next */ + if (index < 0) { + return -1 + } + if (changeSibling) { + var before = list[index - 1]; + var after = list[index + 1]; + before && (before.nextSibling = after); + after && (after.previousSibling = before); + } + list.splice(index, 1); + var newIndexAfter = newIndex; + if (index <= newIndex) { + newIndexAfter = newIndex - 1; + } + var beforeNew = list[newIndexAfter - 1]; + var afterNew = list[newIndexAfter]; + list.splice(newIndexAfter, 0, target); + if (changeSibling) { + beforeNew && (beforeNew.nextSibling = target); + target.previousSibling = beforeNew; + target.nextSibling = afterNew; + afterNew && (afterNew.previousSibling = target); + } + if (index === newIndexAfter) { + return -1 + } + return newIndex +} + +/** + * Remove the node from list. + * @param {object} target node + * @param {array} list + * @param {boolean} changeSibling + */ +function removeIndex (target, list, changeSibling) { + var index = list.indexOf(target); + /* istanbul ignore next */ + if (index < 0) { + return + } + if (changeSibling) { + var before = list[index - 1]; + var after = list[index + 1]; + before && (before.nextSibling = after); + after && (after.previousSibling = before); + } + list.splice(index, 1); +} + +var Element; + +function setElement (El) { + Element = El; +} + +/** + * A map which stores all type of elements. + * @type {Object} + */ +var elementTypes = {}; + +/** + * Register an extended element type with component methods. + * @param {string} type component type + * @param {array} methods a list of method names + */ +function registerElement (type, methods) { + // Skip when no special component methods. + if (!methods || !methods.length) { + return + } + + // Init constructor. + var XElement = function (props) { + Element.call(this, type, props, true); + }; + + // Init prototype. + XElement.prototype = Object.create(Element.prototype); + Object.defineProperty(XElement.prototype, 'constructor', { + configurable: false, + enumerable: false, + writable: false, + value: Element + }); + + // Add methods to prototype. + methods.forEach(function (methodName) { + XElement.prototype[methodName] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + taskCenter.send('component', { ref: this.ref, component: type, method: methodName }, args); + } + }; + }); + + // Add to element type map. + elementTypes[type] = XElement; +} + +/** + * Clear all element types. Only for testing. + */ + +// JS Services + +var services = []; + +/** + * Register a JavaScript service. + * A JavaScript service options could have a set of lifecycle methods + * for each Weex instance. For example: create, refresh, destroy. + * For the JS framework maintainer if you want to supply some features + * which need to work well in different Weex instances, even in different + * frameworks separately. You can make a JavaScript service to init + * its variables or classes for each Weex instance when it's created + * and recycle them when it's destroyed. + * @param {object} options Could have { create, refresh, destroy } + * lifecycle methods. In create method it should + * return an object of what variables or classes + * would be injected into the Weex instance. + */ +function register$1 (name, options) { + if (has$5(name)) { + console.warn(("Service \"" + name + "\" has been registered already!")); + } + else { + options = Object.assign({}, options); + services.push({ name: name, options: options }); + } +} + +/** + * Unregister a JavaScript service by name + * @param {string} name + */ +function unregister (name) { + services.some(function (service, index) { + if (service.name === name) { + services.splice(index, 1); + return true + } + }); +} + +/** + * Check if a JavaScript service with a certain name existed. + * @param {string} name + * @return {Boolean} + */ +function has$5 (name) { + return indexOf(name) >= 0 +} + +/** + * Find the index of a JavaScript service by name + * @param {string} name + * @return {number} + */ +function indexOf (name) { + return services.map(function (service) { return service.name; }).indexOf(name) +} + +var frameworks; +var runtimeConfig; + +var versionRegExp = /^\s*\/\/ *(\{[^}]*\}) *\r?\n/; + +/** + * Detect a JS Bundle code and make sure which framework it's based to. Each JS + * Bundle should make sure that it starts with a line of JSON comment and is + * more that one line. + * @param {string} code + * @return {object} + */ +function checkVersion (code) { + var info; + var result = versionRegExp.exec(code); + if (result) { + try { + info = JSON.parse(result[1]); + } + catch (e) {} + } + return info +} + +var instanceMap = {}; + +/** + * Check which framework a certain JS Bundle code based to. And create instance + * by this framework. + * @param {string} id + * @param {string} code + * @param {object} config + * @param {object} data + */ +function createInstance (id, code, config, data) { + var info = instanceMap[id]; + + if (!info) { + // Init instance info. + info = checkVersion(code) || {}; + if (!frameworks[info.framework]) { + info.framework = 'Weex'; + } + + // Init instance config. + config = JSON.parse(JSON.stringify(config || {})); + config.bundleVersion = info.version; + config.env = JSON.parse(JSON.stringify(global.WXEnvironment || {})); + console.debug(("[JS Framework] create an " + (info.framework) + "@" + (config.bundleVersion) + " instance from " + (config.bundleVersion))); + + // Init callback manager + var callbacks = new runtimeConfig.CallbackManager(id); + + var env = { + info: info, + config: config, + callbacks: callbacks + }; + env.framework = info.framework; + env.created = Date.now(); + env.services = {}; + instanceMap[id] = env; + + // Init JavaScript services for this instance. + var serviceObjects = Object.create(null); + services.forEach(function (service) { + var create = service.options.create; + if (create) { + var result = create(id, env, runtimeConfig); + Object.assign(serviceObjects, result); + } + }); + env.services = serviceObjects; + + return frameworks[info.framework].createInstance(id, code, config, data, env) + } + return new Error(("invalid instance id \"" + id + "\"")) +} + +var methods = { + createInstance: createInstance, + registerService: services.register, + unregisterService: services.unregister +}; + +/** + * Register methods which init each frameworks. + * @param {string} methodName + */ +function genInit (methodName) { + methods[methodName] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if (methodName === 'registerComponents') { + checkComponentMethods(args[0]); + } + for (var name in frameworks) { + var framework = frameworks[name]; + if (framework && framework[methodName]) { + framework[methodName].apply(framework, args); + } + } + }; +} + +function checkComponentMethods (components) { + if (Array.isArray(components)) { + components.forEach(function (name) { + if (name && name.type && name.methods) { + registerElement(name.type, name.methods); + } + }); + } +} + +/** + * Register methods which will be called for each instance. + * @param {string} methodName + */ +function genInstance (methodName) { + methods[methodName] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var id = args[0]; + var info = instanceMap[id]; + if (info && frameworks[info.framework]) { + var result = (ref = frameworks[info.framework])[methodName].apply(ref, args); + + // Lifecycle methods + if (methodName === 'refreshInstance') { + services.forEach(function (service) { + var refresh = service.options.refresh; + if (refresh) { + refresh(id, { info: info, runtime: runtimeConfig }); + } + }); + } + else if (methodName === 'destroyInstance') { + services.forEach(function (service) { + var destroy = service.options.destroy; + if (destroy) { + destroy(id, { info: info, runtime: runtimeConfig }); + } + }); + delete instanceMap[id]; + } + + return result + } + return new Error(("invalid instance id \"" + id + "\"")) + var ref; + }; +} + +/** + * Adapt some legacy method(s) which will be called for each instance. These + * methods should be deprecated and removed later. + * @param {string} methodName + * @param {string} nativeMethodName + */ +function adaptInstance (methodName, nativeMethodName) { + methods[nativeMethodName] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var id = args[0]; + var info = instanceMap[id]; + if (info && frameworks[info.framework]) { + return (ref = frameworks[info.framework])[methodName].apply(ref, args) + } + return new Error(("invalid instance id \"" + id + "\"")) + var ref; + }; +} + +function init$1 (config) { + runtimeConfig = config || {}; + frameworks = runtimeConfig.frameworks || {}; + init$2(); + + // Init each framework by `init` method and `config` which contains three + // virtual-DOM Class: `Document`, `Element` & `Comment`, and a JS bridge method: + // `sendTasks(...args)`. + for (var name in frameworks) { + var framework = frameworks[name]; + framework.init(config); + } + + // @todo: The method `registerMethods` will be re-designed or removed later. + ['registerComponents', 'registerModules', 'registerMethods'].forEach(genInit) + + ; ['destroyInstance', 'refreshInstance', 'receiveTasks', 'getRoot'].forEach(genInstance); + + adaptInstance('receiveTasks', 'callJS'); + + return methods +} + +/** + * @fileOverview + * Virtual-DOM Node. It's the supper class of Element and Comment. + */ + +function Node () { + this.nodeId = uniqueId(); + this.ref = this.nodeId; + this.children = []; + this.pureChildren = []; + this.parentNode = null; + this.nextSibling = null; + this.previousSibling = null; +} + +/** + * Destroy current node, and remove itself form nodeMap. + */ +Node.prototype.destroy = function () { + var doc = getDoc(this.docId); + if (doc) { + delete this.docId; + delete doc.nodeMap[this.nodeId]; + } + this.children.forEach(function (child) { + child.destroy(); + }); +}; + +/** + * @fileOverview + * Virtual-DOM Element. + */ + +var DEFAULT_TAG_NAME = 'div'; + +function Element$1 (type, props, isExtended) { + if ( type === void 0 ) type = DEFAULT_TAG_NAME; + + var XElement = elementTypes[type]; + if (XElement && !isExtended) { + return new XElement(props) + } + props = props || {}; + this.nodeType = 1; + this.nodeId = uniqueId(); + this.ref = this.nodeId; + this.type = type; + this.attr = props.attr || {}; + this.style = props.style || {}; + this.classStyle = props.classStyle || {}; + this.event = {}; + this.children = []; + this.pureChildren = []; +} + +Element$1.prototype = Object.create(Node.prototype); +Element$1.prototype.constructor = Element$1; + +function registerNode (docId, node) { + var doc = getDoc(docId); + doc.nodeMap[node.nodeId] = node; +} + +setElement(Element$1); + +Object.assign(Element$1.prototype, { + /** + * Append a child node. + * @param {object} node + * @return {undefined | number} the signal sent by native + */ + appendChild: function appendChild (node) { + if (node.parentNode && node.parentNode !== this) { + return + } + /* istanbul ignore else */ + if (!node.parentNode) { + linkParent(node, this); + insertIndex(node, this.children, this.children.length, true); + if (this.docId) { + registerNode(this.docId, node); + } + if (node.nodeType === 1) { + insertIndex(node, this.pureChildren, this.pureChildren.length); + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + return taskCenter.send( + 'dom', + { action: 'addElement' }, + [this.ref, node.toJSON(), -1] + ) + } + } + } + else { + moveIndex(node, this.children, this.children.length, true); + if (node.nodeType === 1) { + var index = moveIndex(node, this.pureChildren, this.pureChildren.length); + var taskCenter$1 = getTaskCenter(this.docId); + if (taskCenter$1 && index >= 0) { + return taskCenter$1.send( + 'dom', + { action: 'moveElement' }, + [node.ref, this.ref, index] + ) + } + } + } + }, + + /** + * Insert a node before specified node. + * @param {object} node + * @param {object} before + * @return {undefined | number} the signal sent by native + */ + insertBefore: function insertBefore (node, before) { + if (node.parentNode && node.parentNode !== this) { + return + } + if (node === before || (node.nextSibling && node.nextSibling === before)) { + return + } + if (!node.parentNode) { + linkParent(node, this); + insertIndex(node, this.children, this.children.indexOf(before), true); + if (this.docId) { + registerNode(this.docId, node); + } + if (node.nodeType === 1) { + var pureBefore = nextElement(before); + var index = insertIndex( + node, + this.pureChildren, + pureBefore + ? this.pureChildren.indexOf(pureBefore) + : this.pureChildren.length + ); + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + return taskCenter.send( + 'dom', + { action: 'addElement' }, + [this.ref, node.toJSON(), index] + ) + } + } + } + else { + moveIndex(node, this.children, this.children.indexOf(before), true); + if (node.nodeType === 1) { + var pureBefore$1 = nextElement(before); + /* istanbul ignore next */ + var index$1 = moveIndex( + node, + this.pureChildren, + pureBefore$1 + ? this.pureChildren.indexOf(pureBefore$1) + : this.pureChildren.length + ); + var taskCenter$1 = getTaskCenter(this.docId); + if (taskCenter$1 && index$1 >= 0) { + return taskCenter$1.send( + 'dom', + { action: 'moveElement' }, + [node.ref, this.ref, index$1] + ) + } + } + } + }, + + /** + * Insert a node after specified node. + * @param {object} node + * @param {object} after + * @return {undefined | number} the signal sent by native + */ + insertAfter: function insertAfter (node, after) { + if (node.parentNode && node.parentNode !== this) { + return + } + if (node === after || (node.previousSibling && node.previousSibling === after)) { + return + } + if (!node.parentNode) { + linkParent(node, this); + insertIndex(node, this.children, this.children.indexOf(after) + 1, true); + /* istanbul ignore else */ + if (this.docId) { + registerNode(this.docId, node); + } + if (node.nodeType === 1) { + var index = insertIndex( + node, + this.pureChildren, + this.pureChildren.indexOf(previousElement(after)) + 1 + ); + var taskCenter = getTaskCenter(this.docId); + /* istanbul ignore else */ + if (taskCenter) { + return taskCenter.send( + 'dom', + { action: 'addElement' }, + [this.ref, node.toJSON(), index] + ) + } + } + } + else { + moveIndex(node, this.children, this.children.indexOf(after) + 1, true); + if (node.nodeType === 1) { + var index$1 = moveIndex( + node, + this.pureChildren, + this.pureChildren.indexOf(previousElement(after)) + 1 + ); + var taskCenter$1 = getTaskCenter(this.docId); + if (taskCenter$1 && index$1 >= 0) { + return taskCenter$1.send( + 'dom', + { action: 'moveElement' }, + [node.ref, this.ref, index$1] + ) + } + } + } + }, + + /** + * Remove a child node, and decide whether it should be destroyed. + * @param {object} node + * @param {boolean} preserved + */ + removeChild: function removeChild (node, preserved) { + if (node.parentNode) { + removeIndex(node, this.children, true); + if (node.nodeType === 1) { + removeIndex(node, this.pureChildren); + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + taskCenter.send( + 'dom', + { action: 'removeElement' }, + [node.ref] + ); + } + } + } + if (!preserved) { + node.destroy(); + } + }, + + /** + * Clear all child nodes. + */ + clear: function clear () { + var taskCenter = getTaskCenter(this.docId); + /* istanbul ignore else */ + if (taskCenter) { + this.pureChildren.forEach(function (node) { + taskCenter.send( + 'dom', + { action: 'removeElement' }, + [node.ref] + ); + }); + } + this.children.forEach(function (node) { + node.destroy(); + }); + this.children.length = 0; + this.pureChildren.length = 0; + }, + + /** + * Set an attribute, and decide whether the task should be send to native. + * @param {string} key + * @param {string | number} value + * @param {boolean} silent + */ + setAttr: function setAttr (key, value, silent) { + if (this.attr[key] === value && silent !== false) { + return + } + this.attr[key] = value; + var taskCenter = getTaskCenter(this.docId); + if (!silent && taskCenter) { + var result = {}; + result[key] = value; + taskCenter.send( + 'dom', + { action: 'updateAttrs' }, + [this.ref, result] + ); + } + }, + + /** + * Set a style property, and decide whether the task should be send to native. + * @param {string} key + * @param {string | number} value + * @param {boolean} silent + */ + setStyle: function setStyle (key, value, silent) { + if (this.style[key] === value && silent !== false) { + return + } + this.style[key] = value; + var taskCenter = getTaskCenter(this.docId); + if (!silent && taskCenter) { + var result = {}; + result[key] = value; + taskCenter.send( + 'dom', + { action: 'updateStyle' }, + [this.ref, result] + ); + } + }, + + /** + * Set style properties from class. + * @param {object} classStyle + */ + setClassStyle: function setClassStyle (classStyle) { + var this$1 = this; + + // reset previous class style to empty string + for (var key in this.classStyle) { + this$1.classStyle[key] = ''; + } + + Object.assign(this.classStyle, classStyle); + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + taskCenter.send( + 'dom', + { action: 'updateStyle' }, + [this.ref, this.toStyle()] + ); + } + }, + + /** + * Add an event handler. + * @param {string} event type + * @param {function} event handler + */ + addEvent: function addEvent (type, handler) { + if (!this.event[type]) { + this.event[type] = handler; + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + taskCenter.send( + 'dom', + { action: 'addEvent' }, + [this.ref, type] + ); + } + } + }, + + /** + * Remove an event handler. + * @param {string} event type + */ + removeEvent: function removeEvent (type) { + if (this.event[type]) { + delete this.event[type]; + var taskCenter = getTaskCenter(this.docId); + if (taskCenter) { + taskCenter.send( + 'dom', + { action: 'removeEvent' }, + [this.ref, type] + ); + } + } + }, + + /** + * Fire an event manually. + * @param {string} event type + * @param {function} event handler + * @return {} anything returned by handler function + */ + fireEvent: function fireEvent (type, e) { + var handler = this.event[type]; + if (handler) { + return handler.call(this, e) + } + }, + + /** + * Get all styles of current element. + * @return {object} style + */ + toStyle: function toStyle () { + return Object.assign({}, this.classStyle, this.style) + }, + + /** + * Convert current element to JSON like object. + * @return {object} element + */ + toJSON: function toJSON () { + var result = { + ref: this.ref.toString(), + type: this.type, + attr: this.attr, + style: this.toStyle() + }; + var event = Object.keys(this.event); + if (event.length) { + result.event = event; + } + if (this.pureChildren.length) { + result.children = this.pureChildren.map(function (child) { return child.toJSON(); }); + } + return result + }, + + /** + * Convert to HTML element tag string. + * @return {stirng} html + */ + toString: function toString () { + return '<' + this.type + + ' attr=' + JSON.stringify(this.attr) + + ' style=' + JSON.stringify(this.toStyle()) + '>' + + this.pureChildren.map(function (child) { return child.toString(); }).join('') + + '' + } +}); + +/** + * @fileOverview + * Virtual-DOM Comment. + */ + +function Comment (value) { + this.nodeType = 8; + this.nodeId = uniqueId(); + this.ref = this.nodeId; + this.type = 'comment'; + this.value = value; + this.children = []; + this.pureChildren = []; +} + +Comment.prototype = Object.create(Node.prototype); +Comment.prototype.constructor = Comment; + +/** + * Convert to HTML comment string. + * @return {stirng} html + */ +Comment.prototype.toString = function () { + return '' +}; + +/** + * @fileOverview + * Listen virtual-dom operations and create corresponding actions. + */ + +function Listener (id, handler) { + this.id = id; + this.batched = false; + this.updates = []; + if (typeof handler === 'function') { + Object.defineProperty(this, 'handler', { + configurable: true, + enumerable: true, + writable: true, + value: handler + }); + } + else { + console.error('[JS Runtime] invalid parameter, handler must be a function'); + } +} + +/** + * Create the action object. + * @param {string} name + * @param {array} arguments + * @return {object} action + */ +function createAction (name, args) { + if ( args === void 0 ) args = []; + + return { module: 'dom', method: name, args: args } +} + +Object.assign(Listener.prototype, { + /** + * Send the "createFinish" signal. + * @param {function} callback + * @return {undefined | number} the signal sent by native + */ + createFinish: function createFinish (callback) { + var handler = this.handler; + return handler([createAction('createFinish')], callback) + }, + + /** + * Send the "updateFinish" signal. + * @param {function} callback + * @return {undefined | number} the signal sent by native + */ + updateFinish: function updateFinish (callback) { + var handler = this.handler; + return handler([createAction('updateFinish')], callback) + }, + + /** + * Send the "refreshFinish" signal. + * @param {function} callback + * @return {undefined | number} the signal sent by native + */ + refreshFinish: function refreshFinish (callback) { + var handler = this.handler; + return handler([createAction('refreshFinish')], callback) + }, + + /** + * Send the "createBody" signal. + * @param {object} element + * @return {undefined | number} the signal sent by native + */ + createBody: function createBody (element) { + var body = element.toJSON(); + var children = body.children; + delete body.children; + var actions = [createAction('createBody', [body])]; + if (children) { + actions.push.apply(actions, children.map(function (child) { + return createAction('addElement', [body.ref, child, -1]) + })); + } + return this.addActions(actions) + }, + + /** + * Send the "addElement" signal. + * @param {object} element + * @param {stirng} reference id + * @param {number} index + * @return {undefined | number} the signal sent by native + */ + addElement: function addElement (element, ref, index) { + if (!(index >= 0)) { + index = -1; + } + return this.addActions(createAction('addElement', [ref, element.toJSON(), index])) + }, + + /** + * Send the "removeElement" signal. + * @param {stirng} reference id + * @return {undefined | number} the signal sent by native + */ + removeElement: function removeElement (ref) { + if (Array.isArray(ref)) { + var actions = ref.map(function (r) { return createAction('removeElement', [r]); }); + return this.addActions(actions) + } + return this.addActions(createAction('removeElement', [ref])) + }, + + /** + * Send the "moveElement" signal. + * @param {stirng} target reference id + * @param {stirng} parent reference id + * @param {number} index + * @return {undefined | number} the signal sent by native + */ + moveElement: function moveElement (targetRef, parentRef, index) { + return this.addActions(createAction('moveElement', [targetRef, parentRef, index])) + }, + + /** + * Send the "updateAttrs" signal. + * @param {stirng} reference id + * @param {stirng} key + * @param {stirng} value + * @return {undefined | number} the signal sent by native + */ + setAttr: function setAttr (ref, key, value) { + var result = {}; + result[key] = value; + return this.addActions(createAction('updateAttrs', [ref, result])) + }, + + /** + * Send the "updateStyle" signal, update a sole style. + * @param {stirng} reference id + * @param {stirng} key + * @param {stirng} value + * @return {undefined | number} the signal sent by native + */ + setStyle: function setStyle (ref, key, value) { + var result = {}; + result[key] = value; + return this.addActions(createAction('updateStyle', [ref, result])) + }, + + /** + * Send the "updateStyle" signal. + * @param {stirng} reference id + * @param {object} style + * @return {undefined | number} the signal sent by native + */ + setStyles: function setStyles (ref, style) { + return this.addActions(createAction('updateStyle', [ref, style])) + }, + + /** + * Send the "addEvent" signal. + * @param {stirng} reference id + * @param {string} event type + * @return {undefined | number} the signal sent by native + */ + addEvent: function addEvent (ref, type) { + return this.addActions(createAction('addEvent', [ref, type])) + }, + + /** + * Send the "removeEvent" signal. + * @param {stirng} reference id + * @param {string} event type + * @return {undefined | number} the signal sent by native + */ + removeEvent: function removeEvent (ref, type) { + return this.addActions(createAction('removeEvent', [ref, type])) + }, + + /** + * Default handler. + * @param {object | array} actions + * @param {function} callback + * @return {} anything returned by callback function + */ + handler: function handler (actions, cb) { + return cb && cb() + }, + + /** + * Add actions into updates. + * @param {object | array} actions + * @return {undefined | number} the signal sent by native + */ + addActions: function addActions (actions) { + var updates = this.updates; + var handler = this.handler; + + if (!Array.isArray(actions)) { + actions = [actions]; + } + + if (this.batched) { + updates.push.apply(updates, actions); + } + else { + return handler(actions) + } + } +}); + +/** + * @fileOverview + * Task handler for communication between javascript and native. + */ + +var handlerMap = { + createBody: 'callCreateBody', + addElement: 'callAddElement', + removeElement: 'callRemoveElement', + moveElement: 'callMoveElement', + updateAttrs: 'callUpdateAttrs', + updateStyle: 'callUpdateStyle', + addEvent: 'callAddEvent', + removeEvent: 'callRemoveEvent' +}; + +/** + * Create a task handler. + * @param {string} id + * @param {function} handler + * @return {function} taskHandler + */ +function createHandler (id, handler) { + var defaultHandler = handler || global.callNative; + + /* istanbul ignore if */ + if (typeof defaultHandler !== 'function') { + console.error('[JS Runtime] no default handler'); + } + + return function taskHandler (tasks) { + /* istanbul ignore if */ + if (!Array.isArray(tasks)) { + tasks = [tasks]; + } + for (var i = 0; i < tasks.length; i++) { + var returnValue = dispatchTask(id, tasks[i], defaultHandler); + if (returnValue === -1) { + return returnValue + } + } + } +} + +/** + * Check if there is a corresponding available handler in the environment. + * @param {string} module + * @param {string} method + * @return {boolean} + */ +function hasAvailableHandler (module, method) { + return module === 'dom' + && handlerMap[method] + && typeof global[handlerMap[method]] === 'function' +} + +/** + * Dispatch the task to the specified handler. + * @param {string} id + * @param {object} task + * @param {function} defaultHandler + * @return {number} signal returned from native + */ +function dispatchTask (id, task, defaultHandler) { + var module = task.module; + var method = task.method; + var args = task.args; + + if (hasAvailableHandler(module, method)) { + return global[handlerMap[method]].apply(global, [ id ].concat( args, ['-1'] )) + } + + return defaultHandler(id, [task], '-1') +} + +/** + * @fileOverview + * Virtual-DOM Document. + */ + +function Document (id, url, handler) { + id = id ? id.toString() : ''; + this.id = id; + this.URL = url; + + addDoc(id, this); + this.nodeMap = {}; + var L = Document.Listener || Listener; + this.listener = new L(id, handler || createHandler(id, Document.handler)); // deprecated + this.taskCenter = new TaskCenter(id, handler ? function (id) { + var args = [], len = arguments.length - 1; + while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; + + return handler.apply(void 0, args); + } : Document.handler); + this.createDocumentElement(); +} + +// default task handler +Document.handler = null; + +/** + * Update all changes for an element. + * @param {object} element + * @param {object} changes + */ +function updateElement (el, changes) { + var attrs = changes.attrs || {}; + for (var name in attrs) { + el.setAttr(name, attrs[name], true); + } + var style = changes.style || {}; + for (var name$1 in style) { + el.setStyle(name$1, style[name$1], true); + } +} + +Object.assign(Document.prototype, { + /** + * Get the node from nodeMap. + * @param {string} reference id + * @return {object} node + */ + getRef: function getRef (ref) { + return this.nodeMap[ref] + }, + + /** + * Turn on batched updates. + */ + open: function open () { + this.listener.batched = false; + }, + + /** + * Turn off batched updates. + */ + close: function close () { + this.listener.batched = true; + }, + + /** + * Create the document element. + * @return {object} documentElement + */ + createDocumentElement: function createDocumentElement () { + var this$1 = this; + + if (!this.documentElement) { + var el = new Element$1('document'); + el.docId = this.id; + el.ownerDocument = this; + el.role = 'documentElement'; + el.depth = 0; + el.ref = '_documentElement'; + this.nodeMap._documentElement = el; + this.documentElement = el; + + Object.defineProperty(el, 'appendChild', { + configurable: true, + enumerable: true, + writable: true, + value: function (node) { + appendBody(this$1, node); + } + }); + + Object.defineProperty(el, 'insertBefore', { + configurable: true, + enumerable: true, + writable: true, + value: function (node, before) { + appendBody(this$1, node, before); + } + }); + } + + return this.documentElement + }, + + /** + * Create the body element. + * @param {string} type + * @param {objct} props + * @return {object} body element + */ + createBody: function createBody (type, props) { + if (!this.body) { + var el = new Element$1(type, props); + setBody(this, el); + } + + return this.body + }, + + /** + * Create an element. + * @param {string} tagName + * @param {objct} props + * @return {object} element + */ + createElement: function createElement (tagName, props) { + return new Element$1(tagName, props) + }, + + /** + * Create an comment. + * @param {string} text + * @return {object} comment + */ + createComment: function createComment (text) { + return new Comment(text) + }, + + /** + * Fire an event on specified element manually. + * @param {object} element + * @param {string} event type + * @param {object} event object + * @param {object} dom changes + * @return {} anything returned by handler function + */ + fireEvent: function fireEvent (el, type, e, domChanges) { + if (!el) { + return + } + e = e || {}; + e.type = type; + e.target = el; + e.timestamp = Date.now(); + if (domChanges) { + updateElement(el, domChanges); + } + return el.fireEvent(type, e) + }, + + /** + * Destroy current document, and remove itself form docMap. + */ + destroy: function destroy () { + delete this.listener; + delete this.nodeMap; + removeDoc(this.id); + } +}); + +/** + * For general callback management of a certain Weex instance. + * Because function can not passed into native, so we create callback + * callback id for each function and pass the callback id into native + * in fact. And when a callback called from native, we can find the real + * callback through the callback id we have passed before. + */ +var CallbackManager = function CallbackManager (instanceId) { + this.instanceId = instanceId; + this.lastCallbackId = 0; + this.callbacks = []; +}; +CallbackManager.prototype.add = function add (callback) { + this.lastCallbackId++; + this.callbacks[this.lastCallbackId] = callback; + return this.lastCallbackId +}; +CallbackManager.prototype.remove = function remove (callbackId) { + var callback = this.callbacks[callbackId]; + this.callbacks[callbackId] = undefined; + return callback +}; +CallbackManager.prototype.consume = function consume (callbackId, data, ifKeepAlive) { + var callback = this.callbacks[callbackId]; + if (typeof ifKeepAlive === 'undefined' || ifKeepAlive === false) { + this.callbacks[callbackId] = undefined; + } + if (typeof callback === 'function') { + return callback(data) + } + return new Error(("invalid callback id \"" + callbackId + "\"")) +}; +CallbackManager.prototype.close = function close () { + this.callbacks = this.callbacks.map(function (cb) { return undefined; }); +}; + +var config$1 = { + Document: Document, Element: Element$1, Comment: Comment, Listener: Listener, + TaskCenter: TaskCenter, + sendTasks: function sendTasks () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return global.callNative.apply(global, args) + }, + CallbackManager: CallbackManager +}; + +Document.handler = config$1.sendTasks; + +/** + * @fileOverview + * Register framework(s) in JS runtime. Weex supply two layers for 3rd-party + * framework(s): one is the instance management layer, another is the + * virtual-DOM layer. + */ + +/* istanbul ignore next */ +function freezePrototype$$1 () { + freezePrototype$1(); + + Object.freeze(config$1.Element); + Object.freeze(config$1.Comment); + Object.freeze(config$1.Listener); + Object.freeze(config$1.Document.prototype); + Object.freeze(config$1.Element.prototype); + Object.freeze(config$1.Comment.prototype); + Object.freeze(config$1.Listener.prototype); +} + +var runtime = { + setNativeConsole: setNativeConsole, + resetNativeConsole: resetNativeConsole, + setNativeTimer: setNativeTimer, + resetNativeTimer: resetNativeTimer, + service: { register: register$1, unregister: unregister, has: has$5 }, + freezePrototype: freezePrototype$$1, + init: init$1, + config: config$1 +}; + +var config$3 = {}; + +var instanceMap$1 = {}; + +function init$3 (cfg) { + config$3.Document = cfg.Document; + config$3.Element = cfg.Element; + config$3.Comment = cfg.Comment; + config$3.sendTasks = cfg.sendTasks; +} + +function registerComponents (components) {} + +function registerModules (modules) {} + +function registerMethods (apis) {} + +function prepareInstance (id, options, data) {} + +function createInstance$1 (id, code, options, data, serviceObjects) { + var document = new config$3.Document(id, options.bundleUrl); + var callbacks = {}; + + var lastCallbackId = 0; + document.addCallback = function (func) { + lastCallbackId++; + callbacks[lastCallbackId] = func; + return lastCallbackId + }; + document.handleCallback = function (funcId, data, ifLast) { + var callback = callbacks[funcId]; + if (ifLast) { + delete callbacks[funcId]; + } + return callback(data) + }; + instanceMap$1[id] = document; + + var globalObjects = Object.assign({ + Document: config$3.Document, + Element: config$3.Element, + Comment: config$3.Comment, + sendTasks: config$3.sendTasks, + id: id, options: options, data: data, document: document + }, serviceObjects); + + var globalKeys = []; + var globalValues = []; + for (var key in globalObjects) { + globalKeys.push(key); + globalValues.push(globalObjects[key]); + } + globalKeys.push(code); + + var result = new (Function.prototype.bind.apply( Function, [ null ].concat( globalKeys) )); + return result.apply(void 0, globalValues) +} + +function refreshInstance (id, data) {} + +function destroyInstance (id) { + delete instanceMap$1[id]; +} + +function getRoot (id) { + return instanceMap$1[id].body.toJSON() +} + +function receiveTasks (id, tasks) { + var jsHandlers = { + fireEvent: function (id, ref, type, data, domChanges) { + var document = instanceMap$1[id]; + var el = document.getRef(ref); + return document.fireEvent(el, type, data, domChanges) + }, + + callback: function (id, funcId, data, ifLast) { + var document = instanceMap$1[id]; + return document.handleCallback(funcId, data, ifLast) + } + }; + + var document = instanceMap$1[id]; + if (document && Array.isArray(tasks)) { + var results = []; + tasks.forEach(function (task) { + var handler = jsHandlers[task.method]; + var args = [].concat( task.args ); + if (typeof handler === 'function') { + args.unshift(id); + results.push(handler.apply(void 0, args)); + } + }); + return results + } +} + +var init_1 = init$3; +var registerComponents_1 = registerComponents; +var registerModules_1 = registerModules; +var registerMethods_1 = registerMethods; +var prepareInstance_1 = prepareInstance; +var createInstance_1 = createInstance$1; +var refreshInstance_1 = refreshInstance; +var destroyInstance_1 = destroyInstance; +var getRoot_1 = getRoot; +var receiveTasks_1 = receiveTasks; + +var index = { + init: init_1, + registerComponents: registerComponents_1, + registerModules: registerModules_1, + registerMethods: registerMethods_1, + prepareInstance: prepareInstance_1, + createInstance: createInstance_1, + refreshInstance: refreshInstance_1, + destroyInstance: destroyInstance_1, + getRoot: getRoot_1, + receiveTasks: receiveTasks_1 +}; + + + +var Vanilla = Object.freeze({ + default: index, + __moduleExports: index, + init: init_1, + registerComponents: registerComponents_1, + registerModules: registerModules_1, + registerMethods: registerMethods_1, + prepareInstance: prepareInstance_1, + createInstance: createInstance_1, + refreshInstance: refreshInstance_1, + destroyInstance: destroyInstance_1, + getRoot: getRoot_1, + receiveTasks: receiveTasks_1 +}); + +var index_1 = createCommonjsModule(function (module, exports) { +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +/* */ + +/** + * Convert a value to a string that is actually rendered. + */ +function _toString (val) { + return val == null + ? '' + : typeof val === 'object' + ? JSON.stringify(val, null, 2) + : String(val) +} + +/** + * Convert a input value to a number for persistence. + * If the conversion fails, return original string. + */ +function toNumber (val) { + var n = parseFloat(val, 10); + return (n || n === 0) ? n : val +} + +/** + * Make a map and return a function for checking if a key + * is in that map. + */ +function makeMap ( + str, + expectsLowerCase +) { + var map = Object.create(null); + var list = str.split(','); + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + return expectsLowerCase + ? function (val) { return map[val.toLowerCase()]; } + : function (val) { return map[val]; } +} + +/** + * Check if a tag is a built-in tag. + */ +var isBuiltInTag = makeMap('slot,component', true); + +/** + * Remove an item from an array + */ +function remove (arr, item) { + if (arr.length) { + var index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1) + } + } +} + +/** + * Check whether the object has the property. + */ +var hasOwnProperty = Object.prototype.hasOwnProperty; +function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) +} + +/** + * Check if value is primitive + */ +function isPrimitive (value) { + return typeof value === 'string' || typeof value === 'number' +} + +/** + * Create a cached version of a pure function. + */ +function cached (fn) { + var cache = Object.create(null); + return function cachedFn (str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)) + } +} + +/** + * Camelize a hyphen-delmited string. + */ +var camelizeRE = /-(\w)/g; +var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) +}); + +/** + * Capitalize a string. + */ +var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1) +}); + +/** + * Hyphenate a camelCase string. + */ +var hyphenateRE = /([^-])([A-Z])/g; +var hyphenate = cached(function (str) { + return str + .replace(hyphenateRE, '$1-$2') + .replace(hyphenateRE, '$1-$2') + .toLowerCase() +}); + +/** + * Simple bind, faster than native + */ +function bind (fn, ctx) { + function boundFn (a) { + var l = arguments.length; + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } + // record original fn length + boundFn._length = fn.length; + return boundFn +} + +/** + * Convert an Array-like object to a real Array. + */ +function toArray (list, start) { + start = start || 0; + var i = list.length - start; + var ret = new Array(i); + while (i--) { + ret[i] = list[i + start]; + } + return ret +} + +/** + * Mix properties into target object. + */ +function extend (to, _from) { + for (var key in _from) { + to[key] = _from[key]; + } + return to +} + +/** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ +function isObject (obj) { + return obj !== null && typeof obj === 'object' +} + +/** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ +var toString = Object.prototype.toString; +var OBJECT_STRING = '[object Object]'; +function isPlainObject (obj) { + return toString.call(obj) === OBJECT_STRING +} + +/** + * Merge an Array of Objects into a single Object. + */ +function toObject (arr) { + var res = {}; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } + } + return res +} + +/** + * Perform no operation. + */ +function noop () {} + +/** + * Always return false. + */ +var no = function () { return false; }; + +/** + * Return same value + */ +var identity = function (_) { return _; }; + +/** + * Generate a static keys string from compiler modules. + */ +function genStaticKeys (modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') +} + +/** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + */ +function looseEqual (a, b) { + /* eslint-disable eqeqeq */ + return a == b || ( + isObject(a) && isObject(b) + ? JSON.stringify(a) === JSON.stringify(b) + : false + ) + /* eslint-enable eqeqeq */ +} + +function looseIndexOf (arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { return i } + } + return -1 +} + +/* */ + +var config = { + /** + * Option merge strategies (used in core/util/options) + */ + optionMergeStrategies: Object.create(null), + + /** + * Whether to suppress warnings. + */ + silent: false, + + /** + * Whether to enable devtools + */ + devtools: "development" !== 'production', + + /** + * Error handler for watcher errors + */ + errorHandler: null, + + /** + * Ignore certain custom elements + */ + ignoredElements: [], + + /** + * Custom user key aliases for v-on + */ + keyCodes: Object.create(null), + + /** + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. + */ + isReservedTag: no, + + /** + * Check if a tag is an unknown element. + * Platform-dependent. + */ + isUnknownElement: no, + + /** + * Get the namespace of an element + */ + getTagNamespace: noop, + + /** + * Parse the real tag name for the specific platform. + */ + parsePlatformTagName: identity, + + /** + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. + */ + mustUseProp: no, + + /** + * List of asset types that a component can own. + */ + _assetTypes: [ + 'component', + 'directive', + 'filter' + ], + + /** + * List of lifecycle hooks. + */ + _lifecycleHooks: [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated' + ], + + /** + * Max circular updates allowed in a scheduler flush cycle. + */ + _maxUpdateCount: 100 +}; + +/* */ + +/** + * Check if a string starts with $ or _ + */ +function isReserved (str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F +} + +/** + * Define a property. + */ +function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); +} + +/** + * Parse simple path. + */ +var bailRE = /[^\w.$]/; +function parsePath (path) { + if (bailRE.test(path)) { + return + } else { + var segments = path.split('.'); + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { return } + obj = obj[segments[i]]; + } + return obj + } + } +} + +/* */ +/* globals MutationObserver */ + +// can we use __proto__? +var hasProto = '__proto__' in {}; + +// Browser environment sniffing +var inBrowser = typeof window !== 'undefined'; +var UA = inBrowser && window.navigator.userAgent.toLowerCase(); +var isIE = UA && /msie|trident/.test(UA); +var isIE9 = UA && UA.indexOf('msie 9.0') > 0; +var isEdge = UA && UA.indexOf('edge/') > 0; +var isAndroid = UA && UA.indexOf('android') > 0; +var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); + +// this needs to be lazy-evaled because vue may be required before +// vue-server-renderer can set VUE_ENV +var _isServer; +var isServerRendering = function () { + if (_isServer === undefined) { + /* istanbul ignore if */ + if (!inBrowser && typeof commonjsGlobal !== 'undefined') { + // detect presence of vue-server-renderer and avoid + // Webpack shimming the process + _isServer = commonjsGlobal['process'].env.VUE_ENV === 'server'; + } else { + _isServer = false; + } + } + return _isServer +}; + +// detect devtools +var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +/* istanbul ignore next */ +function isNative (Ctor) { + return /native code/.test(Ctor.toString()) +} + +/** + * Defer a task to execute it asynchronously. + */ +var nextTick = (function () { + var callbacks = []; + var pending = false; + var timerFunc; + + function nextTickHandler () { + pending = false; + var copies = callbacks.slice(0); + callbacks.length = 0; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + + // the nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore if */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + var logError = function (err) { console.error(err); }; + timerFunc = function () { + p.then(nextTickHandler).catch(logError); + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop); } + }; + } else if (typeof MutationObserver !== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // use MutationObserver where native Promise is not available, + // e.g. PhantomJS IE11, iOS7, Android 4.4 + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = String(counter); + }; + } else { + // fallback to setTimeout + /* istanbul ignore next */ + timerFunc = function () { + setTimeout(nextTickHandler, 0); + }; + } + + return function queueNextTick (cb, ctx) { + var _resolve; + callbacks.push(function () { + if (cb) { cb.call(ctx); } + if (_resolve) { _resolve(ctx); } + }); + if (!pending) { + pending = true; + timerFunc(); + } + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve) { + _resolve = resolve; + }) + } + } +})(); + +var _Set; +/* istanbul ignore if */ +if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; +} else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = (function () { + function Set () { + this.set = Object.create(null); + } + Set.prototype.has = function has (key) { + return this.set[key] === true + }; + Set.prototype.add = function add (key) { + this.set[key] = true; + }; + Set.prototype.clear = function clear () { + this.set = Object.create(null); + }; + + return Set; + }()); +} + +var warn = noop; +var formatComponentName; + +{ + var hasConsole = typeof console !== 'undefined'; + + warn = function (msg, vm) { + if (hasConsole && (!config.silent)) { + console.error("[Vue warn]: " + msg + " " + ( + vm ? formatLocation(formatComponentName(vm)) : '' + )); + } + }; + + formatComponentName = function (vm) { + if (vm.$root === vm) { + return 'root instance' + } + var name = vm._isVue + ? vm.$options.name || vm.$options._componentTag + : vm.name; + return ( + (name ? ("component <" + name + ">") : "anonymous component") + + (vm._isVue && vm.$options.__file ? (" at " + (vm.$options.__file)) : '') + ) + }; + + var formatLocation = function (str) { + if (str === 'anonymous component') { + str += " - use the \"name\" option for better debugging messages."; + } + return ("\n(found in " + str + ")") + }; +} + +/* */ + + +var uid$1 = 0; + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ +var Dep = function Dep () { + this.id = uid$1++; + this.subs = []; +}; + +Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); +}; + +Dep.prototype.removeSub = function removeSub (sub) { + remove(this.subs, sub); +}; + +Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); + } +}; + +Dep.prototype.notify = function notify () { + // stablize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } +}; + +// the current target watcher being evaluated. +// this is globally unique because there could be only one +// watcher being evaluated at any time. +Dep.target = null; +var targetStack = []; + +function pushTarget (_target) { + if (Dep.target) { targetStack.push(Dep.target); } + Dep.target = _target; +} + +function popTarget () { + Dep.target = targetStack.pop(); +} + +/* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype + */ + +var arrayProto = Array.prototype; +var arrayMethods = Object.create(arrayProto);[ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' +] +.forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator () { + var arguments$1 = arguments; + + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length; + var args = new Array(i); + while (i--) { + args[i] = arguments$1[i]; + } + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + inserted = args; + break + case 'unshift': + inserted = args; + break + case 'splice': + inserted = args.slice(2); + break + } + if (inserted) { ob.observeArray(inserted); } + // notify change + ob.dep.notify(); + return result + }); +}); + +/* */ + +var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + +/** + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However when passing down props, + * we don't want to force conversion because the value may be a nested value + * under a frozen data structure. Converting it would defeat the optimization. + */ +var observerState = { + shouldConvert: true, + isSettingProps: false +}; + +/** + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. + */ +var Observer = function Observer (value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + def(value, '__ob__', this); + if (Array.isArray(value)) { + var augment = hasProto + ? protoAugment + : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); + } else { + this.walk(value); + } +}; + +/** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + */ +Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i], obj[keys[i]]); + } +}; + +/** + * Observe a list of Array items. + */ +Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } +}; + +// helpers + +/** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + */ +function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ +} + +/** + * Augment an target Object or Array by defining + * hidden properties. + */ +/* istanbul ignore next */ +function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } +} + +/** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + */ +function observe (value, asRootData) { + if (!isObject(value)) { + return + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if ( + observerState.shouldConvert && + !isServerRendering() && + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value); + } + if (asRootData && ob) { + ob.vmCount++; + } + return ob +} + +/** + * Define a reactive property on an Object. + */ +function defineReactive$$1 ( + obj, + key, + val, + customSetter +) { + var dep = new Dep(); + + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return + } + + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; + + var childOb = observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter () { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + } + if (Array.isArray(value)) { + dependArray(value); + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val; + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } + /* eslint-enable no-self-compare */ + if ("development" !== 'production' && customSetter) { + customSetter(); + } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = observe(newVal); + dep.notify(); + } + }); +} + +/** + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. + */ +function set$1 (obj, key, val) { + if (Array.isArray(obj)) { + obj.length = Math.max(obj.length, key); + obj.splice(key, 1, val); + return val + } + if (hasOwn(obj, key)) { + obj[key] = val; + return + } + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + "development" !== 'production' && warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ); + return + } + if (!ob) { + obj[key] = val; + return + } + defineReactive$$1(ob.value, key, val); + ob.dep.notify(); + return val +} + +/** + * Delete a property and trigger change if necessary. + */ +function del (obj, key) { + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + "development" !== 'production' && warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ); + return + } + if (!hasOwn(obj, key)) { + return + } + delete obj[key]; + if (!ob) { + return + } + ob.dep.notify(); +} + +/** + * Collect dependencies on array elements when the array is touched, since + * we cannot intercept array element access like property getters. + */ +function dependArray (value) { + for (var e = (void 0), i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + if (Array.isArray(e)) { + dependArray(e); + } + } +} + +/* */ + +/** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + */ +var strats = config.optionMergeStrategies; + +/** + * Options with restrictions + */ +{ + strats.el = strats.propsData = function (parent, child, vm, key) { + if (!vm) { + warn( + "option \"" + key + "\" can only be used during instance " + + 'creation with the `new` keyword.' + ); + } + return defaultStrat(parent, child) + }; +} + +/** + * Helper that recursively merges two data objects together. + */ +function mergeData (to, from) { + if (!from) { return to } + var key, toVal, fromVal; + var keys = Object.keys(from); + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + toVal = to[key]; + fromVal = from[key]; + if (!hasOwn(to, key)) { + set$1(to, key, fromVal); + } else if (isPlainObject(toVal) && isPlainObject(fromVal)) { + mergeData(toVal, fromVal); + } + } + return to +} + +/** + * Data + */ +strats.data = function ( + parentVal, + childVal, + vm +) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal + } + if (typeof childVal !== 'function') { + "development" !== 'production' && warn( + 'The "data" option should be a function ' + + 'that returns a per-instance value in component ' + + 'definitions.', + vm + ); + return parentVal + } + if (!parentVal) { + return childVal + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn () { + return mergeData( + childVal.call(this), + parentVal.call(this) + ) + } + } else if (parentVal || childVal) { + return function mergedInstanceDataFn () { + // instance merge + var instanceData = typeof childVal === 'function' + ? childVal.call(vm) + : childVal; + var defaultData = typeof parentVal === 'function' + ? parentVal.call(vm) + : undefined; + if (instanceData) { + return mergeData(instanceData, defaultData) + } else { + return defaultData + } + } + } +}; + +/** + * Hooks and param attributes are merged as arrays. + */ +function mergeHook ( + parentVal, + childVal +) { + return childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal + : [childVal] + : parentVal +} + +config._lifecycleHooks.forEach(function (hook) { + strats[hook] = mergeHook; +}); + +/** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ +function mergeAssets (parentVal, childVal) { + var res = Object.create(parentVal || null); + return childVal + ? extend(res, childVal) + : res +} + +config._assetTypes.forEach(function (type) { + strats[type + 's'] = mergeAssets; +}); + +/** + * Watchers. + * + * Watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ +strats.watch = function (parentVal, childVal) { + /* istanbul ignore if */ + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = {}; + extend(ret, parentVal); + for (var key in childVal) { + var parent = ret[key]; + var child = childVal[key]; + if (parent && !Array.isArray(parent)) { + parent = [parent]; + } + ret[key] = parent + ? parent.concat(child) + : [child]; + } + return ret +}; + +/** + * Other object hashes. + */ +strats.props = +strats.methods = +strats.computed = function (parentVal, childVal) { + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = Object.create(null); + extend(ret, parentVal); + extend(ret, childVal); + return ret +}; + +/** + * Default strategy. + */ +var defaultStrat = function (parentVal, childVal) { + return childVal === undefined + ? parentVal + : childVal +}; + +/** + * Validate component names + */ +function checkComponents (options) { + for (var key in options.components) { + var lower = key.toLowerCase(); + if (isBuiltInTag(lower) || config.isReservedTag(lower)) { + warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + key + ); + } + } +} + +/** + * Ensure all props option syntax are normalized into the + * Object-based format. + */ +function normalizeProps (options) { + var props = options.props; + if (!props) { return } + var res = {}; + var i, val, name; + if (Array.isArray(props)) { + i = props.length; + while (i--) { + val = props[i]; + if (typeof val === 'string') { + name = camelize(val); + res[name] = { type: null }; + } else { + warn('props must be strings when using array syntax.'); + } + } + } else if (isPlainObject(props)) { + for (var key in props) { + val = props[key]; + name = camelize(key); + res[name] = isPlainObject(val) + ? val + : { type: val }; + } + } + options.props = res; +} + +/** + * Normalize raw function directives into object format. + */ +function normalizeDirectives (options) { + var dirs = options.directives; + if (dirs) { + for (var key in dirs) { + var def = dirs[key]; + if (typeof def === 'function') { + dirs[key] = { bind: def, update: def }; + } + } + } +} + +/** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + */ +function mergeOptions ( + parent, + child, + vm +) { + { + checkComponents(child); + } + normalizeProps(child); + normalizeDirectives(child); + var extendsFrom = child.extends; + if (extendsFrom) { + parent = typeof extendsFrom === 'function' + ? mergeOptions(parent, extendsFrom.options, vm) + : mergeOptions(parent, extendsFrom, vm); + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + var mixin = child.mixins[i]; + if (mixin.prototype instanceof Vue$2) { + mixin = mixin.options; + } + parent = mergeOptions(parent, mixin, vm); + } + } + var options = {}; + var key; + for (key in parent) { + mergeField(key); + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key); + } + } + function mergeField (key) { + var strat = strats[key] || defaultStrat; + options[key] = strat(parent[key], child[key], vm, key); + } + return options +} + +/** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + */ +function resolveAsset ( + options, + type, + id, + warnMissing +) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return + } + var assets = options[type]; + // check local registration variations first + if (hasOwn(assets, id)) { return assets[id] } + var camelizedId = camelize(id); + if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } + var PascalCaseId = capitalize(camelizedId); + if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } + // fallback to prototype chain + var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; + if ("development" !== 'production' && warnMissing && !res) { + warn( + 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, + options + ); + } + return res +} + +/* */ + +function validateProp ( + key, + propOptions, + propsData, + vm +) { + var prop = propOptions[key]; + var absent = !hasOwn(propsData, key); + var value = propsData[key]; + // handle boolean props + if (isBooleanType(prop.type)) { + if (absent && !hasOwn(prop, 'default')) { + value = false; + } else if (value === '' || value === hyphenate(key)) { + value = true; + } + } + // check default value + if (value === undefined) { + value = getPropDefaultValue(vm, prop, key); + // since the default value is a fresh copy, + // make sure to observe it. + var prevShouldConvert = observerState.shouldConvert; + observerState.shouldConvert = true; + observe(value); + observerState.shouldConvert = prevShouldConvert; + } + { + assertProp(prop, key, value, vm, absent); + } + return value +} + +/** + * Get the default value of a prop. + */ +function getPropDefaultValue (vm, prop, key) { + // no default, return undefined + if (!hasOwn(prop, 'default')) { + return undefined + } + var def = prop.default; + // warn against non-factory defaults for Object & Array + if (isObject(def)) { + "development" !== 'production' && warn( + 'Invalid default value for prop "' + key + '": ' + + 'Props with type Object/Array must use a factory function ' + + 'to return the default value.', + vm + ); + } + // the raw prop value was also undefined from previous render, + // return previous default value to avoid unnecessary watcher trigger + if (vm && vm.$options.propsData && + vm.$options.propsData[key] === undefined && + vm[key] !== undefined) { + return vm[key] + } + // call factory function for non-Function types + return typeof def === 'function' && prop.type !== Function + ? def.call(vm) + : def +} + +/** + * Assert whether a prop is valid. + */ +function assertProp ( + prop, + name, + value, + vm, + absent +) { + if (prop.required && absent) { + warn( + 'Missing required prop: "' + name + '"', + vm + ); + return + } + if (value == null && !prop.required) { + return + } + var type = prop.type; + var valid = !type || type === true; + var expectedTypes = []; + if (type) { + if (!Array.isArray(type)) { + type = [type]; + } + for (var i = 0; i < type.length && !valid; i++) { + var assertedType = assertType(value, type[i]); + expectedTypes.push(assertedType.expectedType); + valid = assertedType.valid; + } + } + if (!valid) { + warn( + 'Invalid prop: type check failed for prop "' + name + '".' + + ' Expected ' + expectedTypes.map(capitalize).join(', ') + + ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.', + vm + ); + return + } + var validator = prop.validator; + if (validator) { + if (!validator(value)) { + warn( + 'Invalid prop: custom validator check failed for prop "' + name + '".', + vm + ); + } + } +} + +/** + * Assert the type of a value + */ +function assertType (value, type) { + var valid; + var expectedType = getType(type); + if (expectedType === 'String') { + valid = typeof value === (expectedType = 'string'); + } else if (expectedType === 'Number') { + valid = typeof value === (expectedType = 'number'); + } else if (expectedType === 'Boolean') { + valid = typeof value === (expectedType = 'boolean'); + } else if (expectedType === 'Function') { + valid = typeof value === (expectedType = 'function'); + } else if (expectedType === 'Object') { + valid = isPlainObject(value); + } else if (expectedType === 'Array') { + valid = Array.isArray(value); + } else { + valid = value instanceof type; + } + return { + valid: valid, + expectedType: expectedType + } +} + +/** + * Use function string name to check built-in types, + * because a simple equality check will fail when running + * across different vms / iframes. + */ +function getType (fn) { + var match = fn && fn.toString().match(/^\s*function (\w+)/); + return match && match[1] +} + +function isBooleanType (fn) { + if (!Array.isArray(fn)) { + return getType(fn) === 'Boolean' + } + for (var i = 0, len = fn.length; i < len; i++) { + if (getType(fn[i]) === 'Boolean') { + return true + } + } + /* istanbul ignore next */ + return false +} + + + +var util = Object.freeze({ + defineReactive: defineReactive$$1, + _toString: _toString, + toNumber: toNumber, + makeMap: makeMap, + isBuiltInTag: isBuiltInTag, + remove: remove, + hasOwn: hasOwn, + isPrimitive: isPrimitive, + cached: cached, + camelize: camelize, + capitalize: capitalize, + hyphenate: hyphenate, + bind: bind, + toArray: toArray, + extend: extend, + isObject: isObject, + isPlainObject: isPlainObject, + toObject: toObject, + noop: noop, + no: no, + identity: identity, + genStaticKeys: genStaticKeys, + looseEqual: looseEqual, + looseIndexOf: looseIndexOf, + isReserved: isReserved, + def: def, + parsePath: parsePath, + hasProto: hasProto, + inBrowser: inBrowser, + UA: UA, + isIE: isIE, + isIE9: isIE9, + isEdge: isEdge, + isAndroid: isAndroid, + isIOS: isIOS, + isServerRendering: isServerRendering, + devtools: devtools, + nextTick: nextTick, + get _Set () { return _Set; }, + mergeOptions: mergeOptions, + resolveAsset: resolveAsset, + get warn () { return warn; }, + get formatComponentName () { return formatComponentName; }, + validateProp: validateProp +}); + +/* not type checking this file because flow doesn't play well with Proxy */ + +var initProxy; + +{ + var allowedGlobals = makeMap( + 'Infinity,undefined,NaN,isFinite,isNaN,' + + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + + 'require' // for Webpack/Browserify + ); + + var warnNonPresent = function (target, key) { + warn( + "Property or method \"" + key + "\" is not defined on the instance but " + + "referenced during render. Make sure to declare reactive data " + + "properties in the data option.", + target + ); + }; + + var hasProxy = + typeof Proxy !== 'undefined' && + Proxy.toString().match(/native code/); + + if (hasProxy) { + var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); + config.keyCodes = new Proxy(config.keyCodes, { + set: function set (target, key, value) { + if (isBuiltInModifier(key)) { + warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key)); + return false + } else { + target[key] = value; + return true + } + } + }); + } + + var hasHandler = { + has: function has (target, key) { + var has = key in target; + var isAllowed = allowedGlobals(key) || key.charAt(0) === '_'; + if (!has && !isAllowed) { + warnNonPresent(target, key); + } + return has || !isAllowed + } + }; + + var getHandler = { + get: function get (target, key) { + if (typeof key === 'string' && !(key in target)) { + warnNonPresent(target, key); + } + return target[key] + } + }; + + initProxy = function initProxy (vm) { + if (hasProxy) { + // determine which proxy handler to use + var options = vm.$options; + var handlers = options.render && options.render._withStripped + ? getHandler + : hasHandler; + vm._renderProxy = new Proxy(vm, handlers); + } else { + vm._renderProxy = vm; + } + }; +} + +/* */ + + +var queue = []; +var has$1 = {}; +var circular = {}; +var waiting = false; +var flushing = false; +var index = 0; + +/** + * Reset the scheduler's state. + */ +function resetSchedulerState () { + queue.length = 0; + has$1 = {}; + { + circular = {}; + } + waiting = flushing = false; +} + +/** + * Flush both queues and run the watchers. + */ +function flushSchedulerQueue () { + flushing = true; + + // Sort queue before flush. + // This ensures that: + // 1. Components are updated from parent to child. (because parent is always + // created before the child) + // 2. A component's user watchers are run before its render watcher (because + // user watchers are created before the render watcher) + // 3. If a component is destroyed during a parent component's watcher run, + // its watchers can be skipped. + queue.sort(function (a, b) { return a.id - b.id; }); + + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (index = 0; index < queue.length; index++) { + var watcher = queue[index]; + var id = watcher.id; + has$1[id] = null; + watcher.run(); + // in dev build, check and stop circular updates. + if ("development" !== 'production' && has$1[id] != null) { + circular[id] = (circular[id] || 0) + 1; + if (circular[id] > config._maxUpdateCount) { + warn( + 'You may have an infinite update loop ' + ( + watcher.user + ? ("in watcher with expression \"" + (watcher.expression) + "\"") + : "in a component render function." + ), + watcher.vm + ); + break + } + } + } + + // devtool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush'); + } + + resetSchedulerState(); +} + +/** + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. + */ +function queueWatcher (watcher) { + var id = watcher.id; + if (has$1[id] == null) { + has$1[id] = true; + if (!flushing) { + queue.push(watcher); + } else { + // if already flushing, splice the watcher based on its id + // if already past its id, it will be run next immediately. + var i = queue.length - 1; + while (i >= 0 && queue[i].id > watcher.id) { + i--; + } + queue.splice(Math.max(i, index) + 1, 0, watcher); + } + // queue the flush + if (!waiting) { + waiting = true; + nextTick(flushSchedulerQueue); + } + } +} + +/* */ + +var uid$2 = 0; + +/** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + */ +var Watcher = function Watcher ( + vm, + expOrFn, + cb, + options +) { + this.vm = vm; + vm._watchers.push(this); + // options + if (options) { + this.deep = !!options.deep; + this.user = !!options.user; + this.lazy = !!options.lazy; + this.sync = !!options.sync; + } else { + this.deep = this.user = this.lazy = this.sync = false; + } + this.cb = cb; + this.id = ++uid$2; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = new _Set(); + this.newDepIds = new _Set(); + this.expression = expOrFn.toString(); + // parse expression for getter + if (typeof expOrFn === 'function') { + this.getter = expOrFn; + } else { + this.getter = parsePath(expOrFn); + if (!this.getter) { + this.getter = function () {}; + "development" !== 'production' && warn( + "Failed watching path: \"" + expOrFn + "\" " + + 'Watcher only accepts simple dot-delimited paths. ' + + 'For full control, use a function instead.', + vm + ); + } + } + this.value = this.lazy + ? undefined + : this.get(); +}; + +/** + * Evaluate the getter, and re-collect dependencies. + */ +Watcher.prototype.get = function get () { + pushTarget(this); + var value = this.getter.call(this.vm, this.vm); + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); + } + popTarget(); + this.cleanupDeps(); + return value +}; + +/** + * Add a dependency to this directive. + */ +Watcher.prototype.addDep = function addDep (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); + } + } +}; + +/** + * Clean up for dependency collection. + */ +Watcher.prototype.cleanupDeps = function cleanupDeps () { + var this$1 = this; + + var i = this.deps.length; + while (i--) { + var dep = this$1.deps[i]; + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1); + } + } + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; +}; + +/** + * Subscriber interface. + * Will be called when a dependency changes. + */ +Watcher.prototype.update = function update () { + /* istanbul ignore else */ + if (this.lazy) { + this.dirty = true; + } else if (this.sync) { + this.run(); + } else { + queueWatcher(this); + } +}; + +/** + * Scheduler job interface. + * Will be called by the scheduler. + */ +Watcher.prototype.run = function run () { + if (this.active) { + var value = this.get(); + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + isObject(value) || + this.deep + ) { + // set new value + var oldValue = this.value; + this.value = value; + if (this.user) { + try { + this.cb.call(this.vm, value, oldValue); + } catch (e) { + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, this.vm); + } else { + "development" !== 'production' && warn( + ("Error in watcher \"" + (this.expression) + "\""), + this.vm + ); + throw e + } + } + } else { + this.cb.call(this.vm, value, oldValue); + } + } + } +}; + +/** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ +Watcher.prototype.evaluate = function evaluate () { + this.value = this.get(); + this.dirty = false; +}; + +/** + * Depend on all deps collected by this watcher. + */ +Watcher.prototype.depend = function depend () { + var this$1 = this; + + var i = this.deps.length; + while (i--) { + this$1.deps[i].depend(); + } +}; + +/** + * Remove self from all dependencies' subscriber list. + */ +Watcher.prototype.teardown = function teardown () { + var this$1 = this; + + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + remove(this.vm._watchers, this); + } + var i = this.deps.length; + while (i--) { + this$1.deps[i].removeSub(this$1); + } + this.active = false; + } +}; + +/** + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + */ +var seenObjects = new _Set(); +function traverse (val) { + seenObjects.clear(); + _traverse(val, seenObjects); +} + +function _traverse (val, seen) { + var i, keys; + var isA = Array.isArray(val); + if ((!isA && !isObject(val)) || !Object.isExtensible(val)) { + return + } + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return + } + seen.add(depId); + } + if (isA) { + i = val.length; + while (i--) { _traverse(val[i], seen); } + } else { + keys = Object.keys(val); + i = keys.length; + while (i--) { _traverse(val[keys[i]], seen); } + } +} + +/* */ + +function initState (vm) { + vm._watchers = []; + var opts = vm.$options; + if (opts.props) { initProps(vm, opts.props); } + if (opts.methods) { initMethods(vm, opts.methods); } + if (opts.data) { + initData(vm); + } else { + observe(vm._data = {}, true /* asRootData */); + } + if (opts.computed) { initComputed(vm, opts.computed); } + if (opts.watch) { initWatch(vm, opts.watch); } +} + +var isReservedProp = { key: 1, ref: 1, slot: 1 }; + +function initProps (vm, props) { + var propsData = vm.$options.propsData || {}; + var keys = vm.$options._propKeys = Object.keys(props); + var isRoot = !vm.$parent; + // root instance props should be converted + observerState.shouldConvert = isRoot; + var loop = function ( i ) { + var key = keys[i]; + /* istanbul ignore else */ + { + if (isReservedProp[key]) { + warn( + ("\"" + key + "\" is a reserved attribute and cannot be used as component prop."), + vm + ); + } + defineReactive$$1(vm, key, validateProp(key, props, propsData, vm), function () { + if (vm.$parent && !observerState.isSettingProps) { + warn( + "Avoid mutating a prop directly since the value will be " + + "overwritten whenever the parent component re-renders. " + + "Instead, use a data or computed property based on the prop's " + + "value. Prop being mutated: \"" + key + "\"", + vm + ); + } + }); + } + }; + + for (var i = 0; i < keys.length; i++) { loop( i ); } + observerState.shouldConvert = true; +} + +function initData (vm) { + var data = vm.$options.data; + data = vm._data = typeof data === 'function' + ? data.call(vm) + : data || {}; + if (!isPlainObject(data)) { + data = {}; + "development" !== 'production' && warn( + 'data functions should return an object:\n' + + 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', + vm + ); + } + // proxy data on instance + var keys = Object.keys(data); + var props = vm.$options.props; + var i = keys.length; + while (i--) { + if (props && hasOwn(props, keys[i])) { + "development" !== 'production' && warn( + "The data property \"" + (keys[i]) + "\" is already declared as a prop. " + + "Use prop default value instead.", + vm + ); + } else { + proxy(vm, keys[i]); + } + } + // observe data + observe(data, true /* asRootData */); +} + +var computedSharedDefinition = { + enumerable: true, + configurable: true, + get: noop, + set: noop +}; + +function initComputed (vm, computed) { + for (var key in computed) { + var userDef = computed[key]; + if (typeof userDef === 'function') { + computedSharedDefinition.get = makeComputedGetter(userDef, vm); + computedSharedDefinition.set = noop; + } else { + computedSharedDefinition.get = userDef.get + ? userDef.cache !== false + ? makeComputedGetter(userDef.get, vm) + : bind(userDef.get, vm) + : noop; + computedSharedDefinition.set = userDef.set + ? bind(userDef.set, vm) + : noop; + } + Object.defineProperty(vm, key, computedSharedDefinition); + } +} + +function makeComputedGetter (getter, owner) { + var watcher = new Watcher(owner, getter, noop, { + lazy: true + }); + return function computedGetter () { + if (watcher.dirty) { + watcher.evaluate(); + } + if (Dep.target) { + watcher.depend(); + } + return watcher.value + } +} + +function initMethods (vm, methods) { + for (var key in methods) { + vm[key] = methods[key] == null ? noop : bind(methods[key], vm); + if ("development" !== 'production' && methods[key] == null) { + warn( + "method \"" + key + "\" has an undefined value in the component definition. " + + "Did you reference the function correctly?", + vm + ); + } + } +} + +function initWatch (vm, watch) { + for (var key in watch) { + var handler = watch[key]; + if (Array.isArray(handler)) { + for (var i = 0; i < handler.length; i++) { + createWatcher(vm, key, handler[i]); + } + } else { + createWatcher(vm, key, handler); + } + } +} + +function createWatcher (vm, key, handler) { + var options; + if (isPlainObject(handler)) { + options = handler; + handler = handler.handler; + } + if (typeof handler === 'string') { + handler = vm[handler]; + } + vm.$watch(key, handler, options); +} + +function stateMixin (Vue) { + // flow somehow has problems with directly declared definition object + // when using Object.defineProperty, so we have to procedurally build up + // the object here. + var dataDef = {}; + dataDef.get = function () { + return this._data + }; + { + dataDef.set = function (newData) { + warn( + 'Avoid replacing instance root $data. ' + + 'Use nested data properties instead.', + this + ); + }; + } + Object.defineProperty(Vue.prototype, '$data', dataDef); + + Vue.prototype.$set = set$1; + Vue.prototype.$delete = del; + + Vue.prototype.$watch = function ( + expOrFn, + cb, + options + ) { + var vm = this; + options = options || {}; + options.user = true; + var watcher = new Watcher(vm, expOrFn, cb, options); + if (options.immediate) { + cb.call(vm, watcher.value); + } + return function unwatchFn () { + watcher.teardown(); + } + }; +} + +function proxy (vm, key) { + if (!isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val; + } + }); + } +} + +/* */ + +var VNode = function VNode ( + tag, + data, + children, + text, + elm, + context, + componentOptions +) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = undefined; + this.context = context; + this.functionalContext = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.child = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; +}; + +var createEmptyVNode = function () { + var node = new VNode(); + node.text = ''; + node.isComment = true; + return node +}; + +function createTextVNode (val) { + return new VNode(undefined, undefined, undefined, String(val)) +} + +// optimized shallow clone +// used for static nodes and slot nodes because they may be reused across +// multiple renders, cloning them avoids errors when DOM manipulations rely +// on their elm reference. +function cloneVNode (vnode) { + var cloned = new VNode( + vnode.tag, + vnode.data, + vnode.children, + vnode.text, + vnode.elm, + vnode.context, + vnode.componentOptions + ); + cloned.ns = vnode.ns; + cloned.isStatic = vnode.isStatic; + cloned.key = vnode.key; + cloned.isCloned = true; + return cloned +} + +function cloneVNodes (vnodes) { + var res = new Array(vnodes.length); + for (var i = 0; i < vnodes.length; i++) { + res[i] = cloneVNode(vnodes[i]); + } + return res +} + +/* */ + +function mergeVNodeHook (def, hookKey, hook, key) { + key = key + hookKey; + var injectedHash = def.__injected || (def.__injected = {}); + if (!injectedHash[key]) { + injectedHash[key] = true; + var oldHook = def[hookKey]; + if (oldHook) { + def[hookKey] = function () { + oldHook.apply(this, arguments); + hook.apply(this, arguments); + }; + } else { + def[hookKey] = hook; + } + } +} + +/* */ + +function updateListeners ( + on, + oldOn, + add, + remove$$1, + vm +) { + var name, cur, old, fn, event, capture, once; + for (name in on) { + cur = on[name]; + old = oldOn[name]; + if (!cur) { + "development" !== 'production' && warn( + "Invalid handler for event \"" + name + "\": got " + String(cur), + vm + ); + } else if (!old) { + once = name.charAt(0) === '~'; // Prefixed last, checked first + event = once ? name.slice(1) : name; + capture = event.charAt(0) === '!'; + event = capture ? event.slice(1) : event; + if (Array.isArray(cur)) { + add(event, (cur.invoker = arrInvoker(cur)), once, capture); + } else { + if (!cur.invoker) { + fn = cur; + cur = on[name] = {}; + cur.fn = fn; + cur.invoker = fnInvoker(cur); + } + add(event, cur.invoker, once, capture); + } + } else if (cur !== old) { + if (Array.isArray(old)) { + old.length = cur.length; + for (var i = 0; i < old.length; i++) { old[i] = cur[i]; } + on[name] = old; + } else { + old.fn = cur; + on[name] = old; + } + } + } + for (name in oldOn) { + if (!on[name]) { + once = name.charAt(0) === '~'; // Prefixed last, checked first + event = once ? name.slice(1) : name; + capture = event.charAt(0) === '!'; + event = capture ? event.slice(1) : event; + remove$$1(event, oldOn[name].invoker, capture); + } + } +} + +function arrInvoker (arr) { + return function (ev) { + var arguments$1 = arguments; + + var single = arguments.length === 1; + for (var i = 0; i < arr.length; i++) { + single ? arr[i](ev) : arr[i].apply(null, arguments$1); + } + } +} + +function fnInvoker (o) { + return function (ev) { + var single = arguments.length === 1; + single ? o.fn(ev) : o.fn.apply(null, arguments); + } +} + +/* */ + +// The template compiler attempts to minimize the need for normalization by +// statically analyzing the template at compile time. +// +// For plain HTML markup, normalization can be completely skipped because the +// generated render function is guaranteed to return Array. There are +// two cases where extra normalization is needed: + +// 1. When the children contains components - because a functional component +// may return an Array instead of a single root. In this case, just a simple +// nomralization is needed - if any child is an Array, we flatten the whole +// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep +// because functional components already normalize their own children. +function simpleNormalizeChildren (children) { + for (var i = 0; i < children.length; i++) { + if (Array.isArray(children[i])) { + return Array.prototype.concat.apply([], children) + } + } + return children +} + +// 2. When the children contains constrcuts that always generated nested Arrays, +// e.g.