You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ac...@apache.org on 2017/09/21 13:44:24 UTC

[01/17] incubator-weex git commit: * [ios] finish 70% of new recycle-list

Repository: incubator-weex
Updated Branches:
  refs/heads/0.16-dev af2923026 -> 5b99cc6b0


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
new file mode 100644
index 0000000..49ed216
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListDataManager.h"
+#import "NSArray+Weex.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@implementation WXRecycleListDataManager
+{
+    NSArray *_data;
+}
+
+- (instancetype)initWithData:(NSArray *)data
+{
+    if (self = [super init]) {
+        if (![data isKindOfClass:[NSArray class]]) {
+            WXLogError(@"list data must be an array!");
+        } else {
+            _data = data;
+        }
+    }
+    
+    return self;
+}
+
+- (void)updateData:(NSArray *)data
+{
+    WXAssertMainThread();
+    
+    _data = data;
+}
+
+- (NSDictionary *)dataAtIndex:(NSInteger)index
+{
+    WXAssertMainThread();
+    
+    return [_data wx_safeObjectAtIndex:index];
+}
+
+- (NSInteger)numberOfItems
+{
+    WXAssertMainThread();
+    
+    return [_data count];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
new file mode 100644
index 0000000..389dbb8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXCellSlotComponent.h"
+
+@interface WXRecycleListTemplateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+
+- (void)addTemplate:(WXCellSlotComponent *)component;
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type forIndexPath:(NSIndexPath *)indexPath;
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
new file mode 100644
index 0000000..0ac528e
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListTemplateManager.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@interface WXReusableCollectionViewCell : UICollectionViewCell
+
+@end
+
+@implementation WXReusableCollectionViewCell
+
+@end
+
+@implementation WXRecycleListTemplateManager
+{
+    NSMapTable<NSString *, WXCellSlotComponent *> *_templateTypeMap;
+}
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _templateTypeMap = [NSMapTable strongToWeakObjectsMapTable];
+    }
+    
+    return self;
+}
+
+- (void)setCollectionView:(UICollectionView *)collectionView
+{
+    WXAssertMainThread();
+    
+    if (_collectionView == collectionView) {
+        return;
+    }
+    
+    _collectionView = collectionView;
+    
+    for (NSString *templateType in [_templateTypeMap.keyEnumerator.allObjects copy]) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (void)addTemplate:(WXCellSlotComponent *)component
+{
+    WXAssertMainThread();
+    
+    NSString *templateType = component.templateType;
+    WXAssert(templateType != nil, @"cell-slot:%@ must have a template id!", component);
+    
+    [_templateTypeMap setObject:component forKey:templateType];
+    if (_collectionView) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type forIndexPath:(NSIndexPath *)indexPath
+{
+    WXAssertMainThread();
+    
+    WXCellSlotComponent *cellSlot = [_templateTypeMap objectForKey:type];
+    return [cellSlot copy];
+}
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type
+{
+    return [_templateTypeMap objectForKey:type];;
+}
+
+- (void)_registerCellClassForReuseID:(NSString *)templateID
+{
+    WXLogDebug(@"register cell class for template id:%@", templateID);
+    //TODO: register class updateTemplateId
+    [_collectionView registerClass:[WXReusableCollectionViewCell class] forCellWithReuseIdentifier:templateID];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
new file mode 100644
index 0000000..c96bbcd
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXRecycleListUpdateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+
+- (void)reload;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
new file mode 100644
index 0000000..1395607
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListUpdateManager.h"
+
+@implementation WXRecycleListUpdateManager
+
+- (void)reload
+{
+    [_collectionView reloadData];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
index e579139..0902eab 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -100,7 +100,7 @@
 
 - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index
 {
-    if (self.delegate == newSupercomponent) {
+    if (self.delegate == (id<WXCellRenderDelegate>)newSupercomponent) {
         [self.delegate cell:self didMoveToIndex:index];
         [super _removeFromSupercomponent];
         [newSupercomponent _insertSubcomponent:self atIndex:index];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 1452118..1b0f784 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -25,6 +25,7 @@
 @class WXTouchGestureRecognizer;
 @class WXThreadSafeCounter;
 
+typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 /**
  * The following variables and methods are used in Weex INTERNAL logic.
@@ -131,6 +132,21 @@
     BOOL _lazyCreateView;
     
     WXTransform *_transform;
+    
+    /**
+     * Data Binding
+     */
+    BOOL _isTemplate;
+    WXComponent *_templateComponent;
+    WXDataBindingBlock _bindingMatch;
+    WXDataBindingBlock _bindingRepeat;
+    NSString *_repeatIndexIdentify;
+    NSString *_repeatLabelIdentify;
+    BOOL _isRepeating;
+    BOOL _isSkipUpdate;
+    
+    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingAttributes;
+    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingStyles;
 }
 
 ///--------------------------------------
@@ -226,6 +242,10 @@
 
 - (void)setGradientLayer;
 
+- (void)_storeBindingsWithStyles:(NSDictionary *)styles attributes:(NSDictionary *)attributes;
+
+- (void)_didInserted;
+
 @end
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index c2db44a..ef1c73d 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -109,6 +109,10 @@
     [self registerComponent:@"textarea" withClass:NSClassFromString(@"WXTextAreaComponent")];
 	[self registerComponent:@"canvas" withClass:NSClassFromString(@"WXCanvasComponent")];
     [self registerComponent:@"slider-neighbor" withClass:NSClassFromString(@"WXSliderNeighborComponent")];
+    
+    [self registerComponent:@"recycle-list" withClass:NSClassFromString(@"WXRecycleListComponent")];
+    [self registerComponent:@"cell-slot" withClass:NSClassFromString(@"WXCellSlotComponent") withProperties: @{@"append":@"tree", @"isTemplate":@YES}];
+    
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
index f2d2f6a..73b08e1 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
@@ -18,6 +18,16 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXInvocationConfig.h"
+
+@interface WXComponentConfig : WXInvocationConfig
+
+@property (nonatomic, strong) NSDictionary *properties;
+
+- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros;
+
+@end
+
 
 @interface WXComponentFactory : NSObject
 
@@ -53,6 +63,8 @@
  */
 + (Class)classWithComponentName:(NSString *)name;
 
++ (WXComponentConfig *)configWithComponentName:(NSString *)name;
+
 /**
  * @abstract Returns the registered components.
  */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
index 6970376..0101d7a 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
@@ -20,17 +20,9 @@
 #import "WXComponentFactory.h"
 #import "WXAssert.h"
 #import "WXLog.h"
-#import "WXInvocationConfig.h"
 
 #import <objc/runtime.h>
 
-@interface WXComponentConfig : WXInvocationConfig
-@property (nonatomic, strong) NSDictionary *properties;
-
-- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros;
-
-@end
-
 @implementation WXComponentConfig
 
 - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros
@@ -82,7 +74,17 @@
 
 + (Class)classWithComponentName:(NSString *)name
 {
-    return [[self sharedInstance] classWithComponentName:name];
+    WXComponentConfig *config = [self configWithComponentName:name];
+    if(!config || !config.clazz) {
+        return nil;
+    }
+    
+    return NSClassFromString(config.clazz);
+}
+
++ (WXComponentConfig *)configWithComponentName:(NSString *)name
+{
+    return [[self sharedInstance] configWithComponentName:name];
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros
@@ -195,9 +197,9 @@
     return componentDic;
 }
 
-- (Class)classWithComponentName:(NSString *)name
+- (WXComponentConfig *)configWithComponentName:(NSString *)name
 {
-    WXAssert(name, @"Can not find class for a nil component name");
+    WXAssert(name, @"Can not find config for a nil component name");
     
     WXComponentConfig *config = nil;
     
@@ -209,11 +211,7 @@
     }
     [_configLock unlock];
     
-    if(!config || !config.clazz) {
-        return nil;
-    }
-    
-    return NSClassFromString(config.clazz);
+    return config;
 }
 
 - (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
index 729e6d7..387e3d0 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -24,8 +24,15 @@
 @class WXSDKInstance;
 @class WXComponent;
 
-extern void WXPerformBlockOnComponentThread(void (^block)());
-
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+void WXPerformBlockOnComponentThread(void (^block)());
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXComponentManager : NSObject
 
@@ -91,6 +98,7 @@ extern void WXPerformBlockOnComponentThread(void (^block)());
  */
 - (NSUInteger)numberOfComponents;
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref;
 
 ///--------------------------------------
 /// @name Updating

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
index 86ec447..bfd96eb 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@ -20,6 +20,7 @@
 #import "WXComponentManager.h"
 #import "WXComponent.h"
 #import "WXComponent_internal.h"
+#import "WXComponent+DataBinding.h"
 #import "WXComponentFactory.h"
 #import "WXDefine.h"
 #import "NSArray+Weex.h"
@@ -204,6 +205,15 @@ static NSThread *WXComponentThread;
     _rootComponent = [self _buildComponentForData:data supercomponent:nil];
     
     [self _initRootCSSNode];
+    
+    NSArray *subcomponentsData = [data valueForKey:@"children"];
+    if (subcomponentsData) {
+        BOOL appendTree = [_rootComponent.attributes[@"append"] isEqualToString:@"tree"];
+        for(NSDictionary *subcomponentData in subcomponentsData){
+            [self _recursivelyAddComponent:subcomponentData toSupercomponent:_rootComponent atIndex:-1 appendingInTree:appendTree];
+        }
+    }
+    
     __weak typeof(self) weakSelf = self;
     [self _addUITask:^{
         [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] className:nil name:data[@"type"] phase:WXTracingBegin functionName:@"createBody" options:@{@"threadName":WXTUIThread}];
@@ -212,6 +222,8 @@ static NSThread *WXComponentThread;
         [strongSelf.weexInstance.rootView addSubview:strongSelf->_rootComponent.view];
         [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] className:nil name:data[@"type"] phase:WXTracingEnd functionName:@"createBody" options:@{@"threadName":WXTUIThread}];
     }];
+    
+    
 }
 
 static bool rootNodeIsDirty(void *context)
@@ -258,14 +270,16 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     if(supercomponent && component && supercomponent->_lazyCreateView) {
         component->_lazyCreateView = YES;
     }
-
-    __weak typeof(self) weakSelf = self;
-    [self _addUITask:^{
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingBegin functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-        [supercomponent insertSubview:component atIndex:index];
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-    }];
-
+    
+    if (!component->_isTemplate) {
+        __weak typeof(self) weakSelf = self;
+        [self _addUITask:^{
+            [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingBegin functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
+            [supercomponent insertSubview:component atIndex:index];
+            [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
+        }];
+    }
+    
     NSArray *subcomponentsData = [componentData valueForKey:@"children"];
     
     BOOL appendTree = !appendingInTree && [component.attributes[@"append"] isEqualToString:@"tree"];
@@ -273,6 +287,9 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     for(NSDictionary *subcomponentData in subcomponentsData){
         [self _recursivelyAddComponent:subcomponentData toSupercomponent:component atIndex:-1 appendingInTree:appendTree || appendingInTree];
     }
+    
+    [component _didInserted];
+    
     if (appendTree) {
         // If appending treeļ¼Œforce layout in case of too much tasks piling up in syncQueue
         [self _layoutAndSyncUI];
@@ -383,9 +400,26 @@ static css_node_t * rootNodeGetChild(void *context, int i)
             }
         }
     }
-
-    Class clazz = [WXComponentFactory classWithComponentName:type];
+    
+    WXComponentConfig *config = [WXComponentFactory configWithComponentName:type];
+    BOOL isTemplate = [config.properties[@"isTemplate"] boolValue] || (supercomponent && supercomponent->_isTemplate);
+    NSDictionary *bindingStyles;
+    NSDictionary *bindingAttibutes;
+    NSDictionary *bindingEvents;
+    if (isTemplate) {
+        bindingStyles = [self _extractBindings:&styles];
+        bindingAttibutes = [self _extractBindings:&attributes];
+        bindingEvents = [self _extractBindingEvents:&events];
+    }
+    
+    Class clazz = NSClassFromString(config.clazz);;
     WXComponent *component = [[clazz alloc] initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:self.weexInstance];
+    
+    if (isTemplate) {
+        component->_isTemplate = YES;
+        [component _storeBindingsWithStyles:bindingStyles attributes:bindingAttibutes];
+    }
+
     WXAssert(component, @"Component build failed for data:%@", data);
     
     [_indexDict setObject:component forKey:component.ref];
@@ -393,6 +427,67 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     return component;
 }
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref
+{
+    [_indexDict setObject:component forKey:ref];
+}
+
+- (NSDictionary *)_extractBindings:(NSDictionary **)attributesOrStylesPoint
+{
+    NSDictionary *attributesOrStyles = *attributesOrStylesPoint;
+    if (!attributesOrStyles) {
+        return nil;
+    }
+    
+    NSMutableDictionary *newAttributesOrStyles = [attributesOrStyles mutableCopy];
+    NSMutableDictionary *bindingAttributesOrStyles = [NSMutableDictionary dictionary];
+    
+    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
+        if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName] // match
+            ||  [WXBindingRepeatIdentify isEqualToString:attributeOrStyleName] // repeat
+            || ([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify])) {  // {"attributeOrStyleName": {"@binding":"bindingExpression"}
+            bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
+            [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
+        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
+            // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
+            __block BOOL isBinding = NO;
+            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([obj isKindOfClass:[NSDictionary class]] && obj[WXBindingIdentify]) {
+                    isBinding = YES;
+                    *stop = YES;
+                }
+            }];
+            
+            if (isBinding) {
+                bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
+                [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
+            }
+        }
+    }];
+    
+    *attributesOrStylesPoint = newAttributesOrStyles;
+    
+    return bindingAttributesOrStyles;
+}
+
+- (NSDictionary *)_extractBindingEvents:(NSArray **)eventsPoint
+{
+    NSArray *events = *eventsPoint;
+    NSMutableArray *newEvents = [events mutableCopy];
+    NSMutableDictionary *bindingEvents = [NSMutableDictionary dictionary];
+    [events enumerateObjectsUsingBlock:^(id  _Nonnull event, NSUInteger idx, BOOL * _Nonnull stop) {
+        if ([event isKindOfClass:[NSDictionary class]] && event[@"type"] && event[@"params"]) {
+            NSString *eventName = event[@"type"];
+            NSString *bindingParams = event[@"params"];
+            bindingEvents[eventName] = bindingParams;
+            [newEvents removeObject:event];
+        }
+    }];
+    
+    *eventsPoint = newEvents;
+    return bindingEvents;
+}
+
 #pragma mark Reset
 -(BOOL)isShouldReset:(id )value
 {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
index 39385ef..ac1b13a 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
@@ -23,6 +23,11 @@
 
 @class WXSDKInstance;
 
+typedef enum : NSUInteger {
+    WXDisplayTypeNone,
+    WXDisplayTypeBlock
+} WXDisplayType;
+
 /**
  * @abstract the component callback , result can be string or dictionary.
  * @discussion callback data to js, the id of callback function will be removed to save memory.
@@ -37,7 +42,7 @@ typedef void (^WXKeepAliveCallback)(_Nonnull id result, BOOL keepAlive);
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface WXComponent : NSObject
+@interface WXComponent : NSObject <NSCopying>
 
 ///--------------------------------------
 /// @name Component Hierarchy Management
@@ -346,6 +351,8 @@ NS_ASSUME_NONNULL_BEGIN
 /// @name Display
 ///--------------------------------------
 
+@property (nonatomic, assign) WXDisplayType displayType;
+
 /**
  * @abstract Marks the view as needing display. The method should be called on the main thread.
  * @discussion You can use this method to notify the system that your component's contents need to be redrawn. This method makes a note of the request and returns immediately. The component is not actually redrawn until the next drawing cycle, at which point all invalidated components are updated.
@@ -399,6 +406,16 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (UIImage *)endDrawContext:(CGContextRef)context;
 
+///--------------------------------------
+/// @name Data Binding
+///--------------------------------------
+
+/**
+ * @abstract Update binding data for the component
+ * @parameter binding data to update
+ */
+- (void)updateBindingData:(NSDictionary *)data;
+
 @end
 
 @interface WXComponent (Deprecated)

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 81f8178..76fb446 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -88,6 +88,7 @@
         
         _absolutePosition = CGPointMake(NAN, NAN);
         
+        _displayType = WXDisplayTypeBlock;
         _isNeedJoinLayoutSystem = YES;
         _isLayoutDirty = YES;
         _isViewFrameSyncWithCalculated = YES;
@@ -136,6 +137,41 @@
     return self;
 }
 
+- (id)copyWithZone:(NSZone *)zone
+{
+    NSInteger copyId = 0;
+    @synchronized(self){
+        static NSInteger __copy = 0;
+        copyId = __copy % (1024*1024);
+        __copy++;
+    }
+    NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", copyId, _isTemplate ? self.ref : self->_templateComponent.ref];
+    WXComponent *component = [[[self class] allocWithZone:zone] initWithRef:copyRef type:self.type styles:self.styles attributes:self.attributes events:self.events weexInstance:self.weexInstance];
+    if (_isTemplate) {
+        component->_templateComponent = self;
+    } else {
+        component->_templateComponent = self->_templateComponent;
+    }
+    memcpy(component->_cssNode, self.cssNode, sizeof(css_node_t));
+    component->_cssNode->context = (__bridge void *)component;
+    component->_calculatedFrame = self.calculatedFrame;
+    
+    NSMutableArray *subcomponentsCopy = [NSMutableArray array];
+    for (WXComponent *subcomponent in self.subcomponents) {
+        WXComponent *subcomponentCopy = [subcomponent copy];
+        subcomponentCopy->_supercomponent = component;
+        [subcomponentsCopy addObject:subcomponentCopy];
+    }
+    
+    component->_subcomponents = subcomponentsCopy;
+    
+    WXPerformBlockOnComponentThread(^{
+        [self.weexInstance.componentManager addComponent:component toIndexDictForRef:copyRef];
+    });
+    
+    return component;
+}
+
 - (void)dealloc
 {
     free_css_node(_cssNode);
@@ -195,6 +231,28 @@
     return events;
 }
 
+- (void)setDisplayType:(WXDisplayType)displayType
+{
+    if (_displayType != displayType) {
+        _displayType = displayType;
+        if (displayType == WXDisplayTypeNone) {
+            _isNeedJoinLayoutSystem = NO;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self removeFromSuperview];
+            });
+        } else {
+            _isNeedJoinLayoutSystem = YES;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self _buildViewHierarchyLazily];
+                // TODO: insert into the correct index
+                [self.supercomponent insertSubview:self atIndex:0];
+            });
+        }
+    }
+}
+
 - (WXSDKInstance *)weexInstance
 {
     return _weexInstance;
@@ -423,6 +481,11 @@
     [newSupercomponent _insertSubcomponent:self atIndex:index];
 }
 
+- (void)_didInserted
+{
+    
+}
+
 - (id<WXScrollerProtocol>)ancestorScroller
 {
     if(!_ancestorScroller) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
index 9396243..4b05df3 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
@@ -107,7 +107,9 @@ typedef enum : NSUInteger {
         }
     }
     
+#if DEBUG
     [self _printMatrix:matrix rowSize:oldSize columnSize:newSize];
+#endif
     
     NSMutableArray *updates = [NSMutableArray array];
     NSMutableIndexSet *inserts = [NSMutableIndexSet indexSet];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 5d96757..538dc77 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -81,33 +81,41 @@ do {\
     }\
 }while(0)
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
 /**
  * @abstract execute asynchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute synchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute action block on the specific thread.
  *
  */
-extern void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread *_Nonnull thread);
+void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread *_Nonnull thread);
 
 /**
  * @abstract swizzling methods.
  *
  */
-extern void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL original, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL original, _Nonnull SEL replaced);
 
-extern void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, _Nonnull SEL original, _Nonnull id block, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, _Nonnull SEL original, _Nonnull id block, _Nonnull SEL replaced);
 
-extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+_Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXUtility : NSObject
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
index ef00f9a..be27ae7 100644
--- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
+++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
@@ -94,6 +94,10 @@ do {\
 {
     WXAssertMainThread();
     
+    if (subcomponent.displayType == WXDisplayTypeNone) {
+        return;
+    }
+    
     WX_CHECK_COMPONENT_TYPE(self.componentType)
     if (subcomponent->_positionType == WXPositionTypeFixed) {
         [self.weexInstance.rootView addSubview:subcomponent.view];


[06/17] incubator-weex git commit: * [ios] update JSFM to 0.22.2

Posted by ac...@apache.org.
* [ios] update JSFM to 0.22.2


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

Branch: refs/heads/0.16-dev
Commit: 6a272abc81b4c3952420e06c0114d29e662cd1ea
Parents: dc112fc
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:24:22 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:24:22 2017 +0800

----------------------------------------------------------------------
 pre-build/native-bundle-main.js | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------



[02/17] incubator-weex git commit: * [ios] finish 70% of new recycle-list

Posted by ac...@apache.org.
* [ios] finish 70% of new recycle-list


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

Branch: refs/heads/0.16-dev
Commit: 877487a6e31e48ae4684626deb71993579d5e575
Parents: 5f5d674
Author: yinfeng <cx...@apache.org>
Authored: Fri Sep 8 12:24:09 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Fri Sep 8 12:24:09 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj       |  64 ++
 .../Component/RecycleList/WXCellSlotComponent.h |  32 +
 .../Component/RecycleList/WXCellSlotComponent.m |  93 ++
 .../RecycleList/WXComponent+DataBinding.h       |  31 +
 .../RecycleList/WXComponent+DataBinding.mm      | 374 ++++++++
 .../Component/RecycleList/WXJSASTParser.h       |  95 ++
 .../Component/RecycleList/WXJSASTParser.mm      | 873 +++++++++++++++++++
 .../RecycleList/WXRecycleListComponent.h        |  25 +
 .../RecycleList/WXRecycleListComponent.m        | 225 +++++
 .../RecycleList/WXRecycleListDataManager.h      |  32 +
 .../RecycleList/WXRecycleListDataManager.m      |  64 ++
 .../RecycleList/WXRecycleListTemplateManager.h  |  33 +
 .../RecycleList/WXRecycleListTemplateManager.m  |  94 ++
 .../RecycleList/WXRecycleListUpdateManager.h    |  28 +
 .../RecycleList/WXRecycleListUpdateManager.m    |  29 +
 .../WeexSDK/Sources/Component/WXCellComponent.m |   2 +-
 .../Sources/Component/WXComponent_internal.h    |  20 +
 ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m    |   4 +
 .../Sources/Manager/WXComponentFactory.h        |  12 +
 .../Sources/Manager/WXComponentFactory.m        |  30 +-
 .../Sources/Manager/WXComponentManager.h        |  12 +-
 .../Sources/Manager/WXComponentManager.m        | 115 ++-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.h     |  19 +-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |  63 ++
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m    |   2 +
 ios/sdk/WeexSDK/Sources/Utility/WXUtility.h     |  20 +-
 .../Sources/View/WXComponent+ViewManagement.m   |   4 +
 27 files changed, 2359 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index d43ec0e..d597bf0 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -105,6 +105,8 @@
 		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, ); }; };
+		7423EB511F4ADE30001662D1 /* WXComponent+DataBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */; };
+		7423EB521F4ADE30001662D1 /* WXComponent+DataBinding.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */; };
 		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 */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -150,6 +152,8 @@
 		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 */; };
+		746B923B1F46BE36009AE86B /* WXCellSlotComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 746B92391F46BE36009AE86B /* WXCellSlotComponent.h */; };
+		746B923C1F46BE36009AE86B /* WXCellSlotComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 746B923A1F46BE36009AE86B /* WXCellSlotComponent.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 */; };
 		747DF6821E31AEE4005C53A8 /* WXLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 747DF6801E31AEE4005C53A8 /* WXLength.h */; };
@@ -186,12 +190,22 @@
 		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 */; };
+		74BF19F81F5139BB00AEE3D7 /* WXJSASTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */; };
+		74BF19F91F5139BB00AEE3D7 /* WXJSASTParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */; };
 		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 */; };
 		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 */; };
+		74CFDD391F45939C007A1A66 /* WXRecycleListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */; };
+		74CFDD3A1F45939C007A1A66 /* WXRecycleListComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */; };
+		74CFDD3D1F459400007A1A66 /* WXRecycleListDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */; };
+		74CFDD3E1F459400007A1A66 /* WXRecycleListDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */; };
+		74CFDD411F45941E007A1A66 /* WXRecycleListTemplateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */; };
+		74CFDD421F45941E007A1A66 /* WXRecycleListTemplateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */; };
+		74CFDD451F459443007A1A66 /* WXRecycleListUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */; };
+		74CFDD461F459443007A1A66 /* WXRecycleListUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.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, ); }; };
@@ -680,6 +694,8 @@
 		742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXWeakObjectWrapper.h; sourceTree = "<group>"; };
 		7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXWeakObjectWrapper.m; sourceTree = "<group>"; };
 		7423899D1C32733800D748CA /* WXType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXType.h; sourceTree = "<group>"; };
+		7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WXComponent+DataBinding.h"; sourceTree = "<group>"; };
+		7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "WXComponent+DataBinding.mm"; sourceTree = "<group>"; };
 		742AD7251DF98C45007DC46C /* WXResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequest.h; path = Network/WXResourceRequest.h; sourceTree = "<group>"; };
 		742AD7261DF98C45007DC46C /* WXResourceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceRequest.m; path = Network/WXResourceRequest.m; sourceTree = "<group>"; };
 		742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequestHandler.h; path = Network/WXResourceRequestHandler.h; sourceTree = "<group>"; };
@@ -726,6 +742,8 @@
 		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 = "<group>"; };
 		7469869E1C4E2C000054A57E /* NSArray+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Weex.m"; sourceTree = "<group>"; };
+		746B92391F46BE36009AE86B /* WXCellSlotComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXCellSlotComponent.h; sourceTree = "<group>"; };
+		746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXCellSlotComponent.m; sourceTree = "<group>"; };
 		747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+ViewManagement.h"; sourceTree = "<group>"; };
 		747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+ViewManagement.m"; sourceTree = "<group>"; };
 		747DF6801E31AEE4005C53A8 /* WXLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLength.h; sourceTree = "<group>"; };
@@ -762,6 +780,8 @@
 		74B8BF001DC49AFE004A6027 /* WXRootViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootViewTests.m; sourceTree = "<group>"; };
 		74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXMetaModule.h; sourceTree = "<group>"; };
 		74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXMetaModule.m; sourceTree = "<group>"; };
+		74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXJSASTParser.h; sourceTree = "<group>"; };
+		74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WXJSASTParser.mm; sourceTree = "<group>"; };
 		74C27A011CEC441D004E488E /* WeexSDK-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WeexSDK-Prefix.pch"; sourceTree = "<group>"; };
 		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 = "<group>"; };
@@ -770,6 +790,14 @@
 		74CC7A1B1C2BC5F800829368 /* WXCellComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCellComponent.m; sourceTree = "<group>"; };
 		74CC7A1E1C2BF9DC00829368 /* WXListComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXListComponent.h; sourceTree = "<group>"; };
 		74CC7A1F1C2BF9DC00829368 /* WXListComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXListComponent.m; sourceTree = "<group>"; };
+		74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListComponent.h; sourceTree = "<group>"; };
+		74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListComponent.m; sourceTree = "<group>"; };
+		74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListDataManager.h; sourceTree = "<group>"; };
+		74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListDataManager.m; sourceTree = "<group>"; };
+		74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListTemplateManager.h; sourceTree = "<group>"; };
+		74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListTemplateManager.m; sourceTree = "<group>"; };
+		74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListUpdateManager.h; sourceTree = "<group>"; };
+		74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListUpdateManager.m; sourceTree = "<group>"; };
 		74D2051E1E091B8000128F44 /* WXCallJSMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXCallJSMethod.h; sourceTree = "<group>"; };
 		74D2051F1E091B8000128F44 /* WXCallJSMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCallJSMethod.m; sourceTree = "<group>"; };
 		74EF31A91DE58AE600667A07 /* WXURLRewriteProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXURLRewriteProtocol.h; sourceTree = "<group>"; };
@@ -1104,6 +1132,27 @@
 			path = WeexSDKTests;
 			sourceTree = "<group>";
 		};
+		74CFDD361F45937D007A1A66 /* RecycleList */ = {
+			isa = PBXGroup;
+			children = (
+				74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */,
+				74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */,
+				74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */,
+				74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */,
+				74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */,
+				74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */,
+				74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */,
+				74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */,
+				746B92391F46BE36009AE86B /* WXCellSlotComponent.h */,
+				746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */,
+				7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */,
+				7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */,
+				74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */,
+				74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */,
+			);
+			path = RecycleList;
+			sourceTree = "<group>";
+		};
 		74D8DB401E4825920078B667 /* Recycler */ = {
 			isa = PBXGroup;
 			children = (
@@ -1400,6 +1449,7 @@
 			children = (
 				C4B3D6D21E6954300013F38D /* WXEditComponent.h */,
 				C4B3D6D31E6954300013F38D /* WXEditComponent.m */,
+				74CFDD361F45937D007A1A66 /* RecycleList */,
 				74D8DB401E4825920078B667 /* Recycler */,
 				2A837AAC1CD9DE9200AEDF03 /* WXLoadingComponent.h */,
 				2A837AAD1CD9DE9200AEDF03 /* WXLoadingComponent.m */,
@@ -1515,7 +1565,9 @@
 				775BEE711C1BD977008D1629 /* WXModuleProtocol.h in Headers */,
 				7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */,
 				74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */,
+				7423EB511F4ADE30001662D1 /* WXComponent+DataBinding.h in Headers */,
 				74FD6E041C7C0E9600DBEB6D /* WXScrollerProtocol.h in Headers */,
+				74CFDD3D1F459400007A1A66 /* WXRecycleListDataManager.h in Headers */,
 				77D161201C02DDB40010B15B /* WXSDKEngine.h in Headers */,
 				745ED2DA1C5F2C7E002DB5A8 /* WXView.h in Headers */,
 				59D3CA411CF9ED57008835DC /* Layout.h in Headers */,
@@ -1528,6 +1580,7 @@
 				59A5961C1CB630F10012CD52 /* WXComponent+Navigation.h in Headers */,
 				775BEE6E1C1BD8F4008D1629 /* WXImgLoaderProtocol.h in Headers */,
 				7410811F1CED585A001BC6E5 /* WXComponentManager.h in Headers */,
+				74CFDD411F45941E007A1A66 /* WXRecycleListTemplateManager.h in Headers */,
 				1D3000F11D40B9AC004F3B4F /* WXClipboardModule.h in Headers */,
 				59A583081CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h in Headers */,
 				775BEE4E1C16F993008D1629 /* WXDefine.h in Headers */,
@@ -1571,15 +1624,18 @@
 				749DC27B1D40827B009E1C91 /* WXMonitor.h in Headers */,
 				77E659DA1C07F594008B8775 /* WXDomModule.h in Headers */,
 				74EF31AD1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h in Headers */,
+				746B923B1F46BE36009AE86B /* WXCellSlotComponent.h in Headers */,
 				744D61101E49979000B624B3 /* WXFooterComponent.h in Headers */,
 				744D61141E4AF23E00B624B3 /* WXDiffUtil.h in Headers */,
 				74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */,
 				2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */,
 				C4F012791E1502A6003378D0 /* SRWebSocket+Weex.h in Headers */,
+				74CFDD451F459443007A1A66 /* WXRecycleListUpdateManager.h in Headers */,
 				74A4BA9A1CB3BAA100195969 /* WXThreadSafeMutableDictionary.h in Headers */,
 				74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h in Headers */,
 				741DFE021DDD7D18009B020F /* WXRoundedRect.h in Headers */,
 				7423899B1C3174EB00D748CA /* WXWeakObjectWrapper.h in Headers */,
+				74BF19F81F5139BB00AEE3D7 /* WXJSASTParser.h in Headers */,
 				59A596191CB630E50012CD52 /* WXNavigationProtocol.h in Headers */,
 				59A5962F1CB632050012CD52 /* WXBaseViewController.h in Headers */,
 				74AD99841D5B0E59008F0336 /* WXPolyfillSet.h in Headers */,
@@ -1651,6 +1707,7 @@
 				741081231CED6756001BC6E5 /* WXComponentFactory.h in Headers */,
 				59D3CA4A1CFC3CE1008835DC /* NSTimer+Weex.h in Headers */,
 				C4424E5B1F24DA3D009F52E2 /* WXExtendCallNativeProtocol.h in Headers */,
+				74CFDD391F45939C007A1A66 /* WXRecycleListComponent.h in Headers */,
 				D334510C1D3E19B80083598A /* WXCanvasModule.h in Headers */,
 				742AD73A1DF98C8B007DC46C /* WXResourceLoader.h in Headers */,
 				746319291C71B92600EFEBD4 /* WXModalUIModule.h in Headers */,
@@ -2042,6 +2099,7 @@
 				746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */,
 				74B8BEFF1DC47B72004A6027 /* WXRootView.m in Sources */,
 				742AD7321DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m in Sources */,
+				74CFDD421F45941E007A1A66 /* WXRecycleListTemplateManager.m in Sources */,
 				747DF6831E31AEE4005C53A8 /* WXLength.m in Sources */,
 				C4F0127C1E1502A6003378D0 /* WXWebSocketDefaultImpl.m in Sources */,
 				77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */,
@@ -2061,6 +2119,7 @@
 				DCF087621DCAE161005CD6EB /* WXInvocationConfig.m in Sources */,
 				C47B78CF1F2998EE001D3B0C /* WXExtendCallNativeManager.m in Sources */,
 				77D161311C02DE4E0010B15B /* WXComponent.m in Sources */,
+				74CFDD461F459443007A1A66 /* WXRecycleListUpdateManager.m in Sources */,
 				74862F7A1E02B88D00B7A041 /* JSValue+Weex.m in Sources */,
 				740451EB1E14BB26004157CB /* WXServiceFactory.m in Sources */,
 				77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */,
@@ -2099,6 +2158,7 @@
 				59CE27E91CC387DB000BE37A /* WXEmbedComponent.m in Sources */,
 				DCA0EF651D6EED6F00CB18B9 /* WXGlobalEventModule.m in Sources */,
 				2A919DA71E321F1F006EB6B5 /* WXBridgeMethod.m in Sources */,
+				7423EB521F4ADE30001662D1 /* WXComponent+DataBinding.mm in Sources */,
 				DCAB35FF1D658EB700C0EA70 /* WXRuleManager.m in Sources */,
 				77D161251C02DDD10010B15B /* WXSDKInstance.m in Sources */,
 				DC7764931F3C2CA300B5727E /* WXRecyclerDragController.m in Sources */,
@@ -2120,9 +2180,11 @@
 				74CC7A1D1C2BC5F800829368 /* WXCellComponent.m in Sources */,
 				74862F821E03A24500B7A041 /* WXComponentMethod.m in Sources */,
 				77E65A121C155EA8008B8775 /* WXImageComponent.m in Sources */,
+				74CFDD3E1F459400007A1A66 /* WXRecycleListDataManager.m in Sources */,
 				2A837AB31CD9DE9200AEDF03 /* WXLoadingComponent.m in Sources */,
 				2AE5B7531CAB7DBD0082FDDB /* WXAComponent.m in Sources */,
 				333D9A291F41507A007CED39 /* WXTransition.m in Sources */,
+				74CFDD3A1F45939C007A1A66 /* WXRecycleListComponent.m in Sources */,
 				741DFE031DDD7D18009B020F /* WXRoundedRect.mm in Sources */,
 				59A596301CB632050012CD52 /* WXBaseViewController.m in Sources */,
 				74CC7A211C2BF9DC00829368 /* WXListComponent.m in Sources */,
@@ -2139,6 +2201,7 @@
 				D33451091D3E19480083598A /* WXCanvasComponent.m in Sources */,
 				74A4BA971CB365D100195969 /* WXAppConfiguration.m in Sources */,
 				59A583091CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m in Sources */,
+				746B923C1F46BE36009AE86B /* WXCellSlotComponent.m in Sources */,
 				7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */,
 				77D161501C02E3880010B15B /* WXUtility.m in Sources */,
 				74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */,
@@ -2155,6 +2218,7 @@
 				C4F0127A1E1502A6003378D0 /* SRWebSocket+Weex.m in Sources */,
 				745B2D691E5A8E1E0092D38A /* WXMultiColumnLayout.m in Sources */,
 				77D161391C02DE940010B15B /* WXBridgeManager.m in Sources */,
+				74BF19F91F5139BB00AEE3D7 /* WXJSASTParser.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
new file mode 100644
index 0000000..4e62676
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXComponent.h"
+
+@interface WXCellSlotComponent : WXComponent
+
+@property (nonatomic, strong) NSString *templateType;
+
+- (void)updateCellData:(NSDictionary *)data;
+
+- (void)triggerLayout;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
new file mode 100644
index 0000000..2561d86
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXCellSlotComponent.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+#import "WXConvert.h"
+#import "WXAssert.h"
+#import "WXScrollerComponent.h"
+
+static const NSString *WXDefaultRecycleTemplateType = @"WXDefaultRecycleTemplateType";
+
+@implementation WXCellSlotComponent
+
+- (instancetype)initWithRef:(NSString *)ref
+                       type:(NSString *)type
+                     styles:(NSDictionary *)styles
+                 attributes:(NSDictionary *)attributes
+                     events:(NSArray *)events
+               weexInstance:(WXSDKInstance *)weexInstance
+{
+    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
+    if (self) {
+        // TODO: isRecycle / insertAnimation / deleteAnimation / keepScrollPosition
+        _templateType = attributes[@"templateType"] ? [WXConvert NSString:attributes[@"templateType"]] : WXDefaultRecycleTemplateType;
+        _lazyCreateView = YES;
+        _isNeedJoinLayoutSystem = NO;
+    }
+    
+    return self;
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    
+}
+
+- (void)updateCellData:(NSDictionary *)data
+{
+    WXAssertComponentThread();    
+    
+    [self updateBindingData:data];
+    [self triggerLayout];
+}
+
+- (void)_didInserted
+{
+    [self triggerLayout];
+}
+
+- (void)triggerLayout
+{
+    WXAssertComponentThread();
+    
+    //TODO: _isUseContainerWidth?
+    if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH])) {
+        self.cssNode->style.dimensions[CSS_WIDTH] = ((WXScrollerComponent *)(self.supercomponent)).scrollerCSSNode->style.dimensions[CSS_WIDTH];
+    }
+    
+    if ([self needsLayout]) {
+        layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
+//        if ([WXLog logLevel] >= WXLogLevelDebug) {
+            print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN);
+//        }
+    }
+    
+    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
+    [self _calculateFrameWithSuperAbsolutePosition:CGPointZero gatherDirtyComponents:dirtyComponents];
+    for (WXComponent *dirtyComponent in dirtyComponents) {
+        [self.weexInstance.componentManager _addUITask:^{
+            [dirtyComponent _layoutDidFinish];
+        }];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
new file mode 100644
index 0000000..ce3ab15
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <WeexSDK/WeexSDK.h>
+
+static const NSString *WXBindingIdentify = @"@binding";
+static const NSString *WXBindingMatchIdentify = @"[[match]]";
+static const NSString *WXBindingRepeatIdentify = @"[[repeat]]";
+static const NSString *WXBindingRepeatExprIdentify = @"@expression";
+static const NSString *WXBindingRepeatIndexIdentify = @"@index";
+static const NSString *WXBindingRepeatLabelIdentify = @"@label";
+
+@interface WXComponent (DataBinding)
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
new file mode 100644
index 0000000..51f5724
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
@@ -0,0 +1,374 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXComponent+DataBinding.h"
+#import "WXComponent_internal.h"
+#import "WXSDKInstance_private.h"
+#import "WXComponentManager.h"
+#import "WXAssert.h"
+#import "WXJSASTParser.h"
+
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+typedef enum : NSUInteger {
+    WXDataBindingTypeStyle = 0,
+    WXDataBindingTypeAttributes,
+    WXDataBindingTypeCount,
+} WXDataBindingType;
+
+static JSContext *jsContext;
+
+@implementation WXComponent (DataBinding)
+
+- (void)updateBindingData:(NSDictionary *)data
+{
+    WXAssertComponentThread();
+    
+    if (_isSkipUpdate) {
+        _isSkipUpdate = NO;
+        return;
+    }
+    
+    WXLogDebug(@"Update binding data:%@, for component:%@", data, self.ref);
+    if (!data) {
+        WXLogWarning(@"No data for updateBindingData");
+        return;
+    }
+    
+    WXComponent *templateComponent = _templateComponent;
+    if (!templateComponent) {
+        WXLogError(@"No template fount for component:%@", templateComponent);
+        return;
+    }
+    
+    if (!_isRepeating) {
+        WXDataBindingBlock repeatBlock = templateComponent->_bindingRepeat;
+        if (repeatBlock) {
+            BOOL needUpdate = NO;
+            NSArray *repeatData = repeatBlock(data, &needUpdate);
+            [self _repeat:repeatData inData:data];
+            return;
+        }
+    }
+    
+    WXDataBindingBlock matchBlock = templateComponent->_bindingMatch;
+    if (matchBlock) {
+        BOOL needUpdate = NO;
+        BOOL needDisplay = [matchBlock(data, &needUpdate) boolValue];
+        if (!needDisplay) {
+            self.displayType = WXDisplayTypeNone;
+            return;
+        } else if (needDisplay && !_isNeedJoinLayoutSystem) {
+            self.displayType = WXDisplayTypeBlock;
+        }
+    }
+    
+    for (int i = WXDataBindingTypeStyle; i < WXDataBindingTypeCount; i++) {
+        NSDictionary *bindingMap = i == WXDataBindingTypeStyle ? templateComponent->_bindingStyles : templateComponent->_bindingAttributes;
+        if (!bindingMap || bindingMap.count == 0) {
+            continue;
+        }
+        NSMutableDictionary *newAttributesOrStyles = [NSMutableDictionary dictionary];
+        
+        [bindingMap enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, WXDataBindingBlock  _Nonnull bindingBlock, BOOL * _Nonnull stop) {
+            BOOL needUpdate = NO;
+            id newValue = bindingBlock(data, &needUpdate);
+            if (needUpdate) {
+                newAttributesOrStyles[attributeOrStyleName] = newValue;
+            }
+        }];
+        
+        if (newAttributesOrStyles.count > 0) {
+            [self.weexInstance.componentManager startComponentTasks];
+            if (i == WXDataBindingTypeStyle) {
+                [self.weexInstance.componentManager updateStyles:newAttributesOrStyles forComponent:self.ref];
+            } else {
+                [self.weexInstance.componentManager updateAttributes:newAttributesOrStyles forComponent:self.ref];
+            }
+        }
+    }
+    
+    NSArray *subcomponents = self.subcomponents;
+    for (WXComponent *subcomponent in subcomponents) {
+        [subcomponent updateBindingData:data];
+    }
+}
+
+- (void)_repeat:(NSArray *)repeatData inData:(NSDictionary *)data
+{
+    NSMutableDictionary *dataCopy = [data mutableCopy];
+    WXComponent *templateComponent = _templateComponent;
+    NSArray *subcomponents = self.supercomponent.subcomponents;
+    NSUInteger startIndex = [subcomponents indexOfObject:self];
+    [repeatData enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        if (templateComponent->_repeatIndexIdentify) {
+            dataCopy[templateComponent->_repeatIndexIdentify] = @(idx);
+        }
+        if (templateComponent->_repeatLabelIdentify) {
+            dataCopy[templateComponent->_repeatLabelIdentify] = obj;
+        }
+        
+        WXComponent *exsitingComponent;
+        if (startIndex + idx < subcomponents.count) {
+            if (subcomponents[startIndex + idx]
+                && ((WXComponent *)(subcomponents[startIndex + idx]))->_templateComponent == templateComponent) {
+                exsitingComponent = subcomponents[startIndex + idx];
+                exsitingComponent.displayType = WXDisplayTypeBlock;
+            }
+        }
+        
+        WXComponent *component = exsitingComponent ? : [templateComponent copy];
+        component->_isRepeating = YES;
+        [component updateBindingData:dataCopy];
+        component->_isRepeating = NO;
+        
+        if (idx > 0 && exsitingComponent) {
+            component->_isSkipUpdate = YES;
+        }
+        
+        if (!exsitingComponent) {
+            [self.weexInstance.componentManager startComponentTasks];
+            [self.supercomponent _insertSubcomponent:component atIndex:startIndex + idx];
+            [self.weexInstance.componentManager _addUITask:^{
+                [self.supercomponent insertSubview:component atIndex:startIndex + idx];
+            }];
+        }
+    }];
+    
+    // set displaty:none to the redundant components;
+    NSUInteger i = startIndex + repeatData.count;
+    while (i < self.supercomponent.subcomponents.count) {
+        WXComponent *component = self.supercomponent.subcomponents[i];
+        if (component->_templateComponent == templateComponent) {
+            component->_isSkipUpdate = YES;
+            component.displayType = WXDisplayTypeNone;
+        }
+        i++;
+    }
+}
+
+- (void)_storeBindingsWithStyles:(NSDictionary *)styles attributes:(NSDictionary *)attributes
+{
+    if (!_bindingAttributes) {
+        _bindingAttributes = [NSMutableDictionary new];
+    }
+    if (!_bindingStyles) {
+        _bindingStyles = [NSMutableDictionary new];
+    }
+    [self _storeBindings:styles type:WXDataBindingTypeStyle];
+    [self _storeBindings:attributes type:WXDataBindingTypeAttributes];
+}
+
+- (void)_storeBindings:(NSDictionary *)attributesOrStyles type:(WXDataBindingType)type
+{
+    WXAssertComponentThread();
+    
+    NSMutableDictionary *bindingMap = type == WXDataBindingTypeStyle ? _bindingStyles : _bindingAttributes;
+    
+    // many-to-many relationship between attibuteName and bindingKey
+    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
+        if ([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify]) {
+            // {"attributeOrStyleName":{"@binding":"bindingExpression"}
+            NSString *bindingExpression = attributeOrStyle[WXBindingIdentify];
+            WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
+            WXJSExpression *expression = [parser parseExpression];
+            WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
+            bindingMap[attributeOrStyleName] = block;
+        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
+            // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
+            NSMutableDictionary *bindingBlocksForIndex = [NSMutableDictionary dictionary];
+            __block BOOL isBinding = NO;
+            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([obj isKindOfClass:[NSDictionary class]] && obj[WXBindingIdentify]) {
+                    isBinding = YES;
+                    NSString *bindingExpression = obj[WXBindingIdentify];
+                    WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
+                    WXJSExpression *expression = [parser parseExpression];
+                    WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
+                    bindingBlocksForIndex[@(idx)] = block;
+                }
+            }];
+            
+            bindingMap[attributeOrStyleName] = ^NSString *(NSDictionary *data, BOOL *needUpdate) {
+                NSMutableArray *newArray = [attributeOrStyle mutableCopy];
+                [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    BOOL _needUpdate = NO;
+                    WXDataBindingBlock block = bindingBlocksForIndex[@(idx)];
+                    if (block) {
+                        id newValue = block(data, &_needUpdate);
+                        if (newValue) {
+                             newArray[idx] = newValue;
+                        }  
+                        if (_needUpdate) {
+                            *needUpdate = YES;
+                        }
+                    }
+                }];
+                
+                return [newArray componentsJoinedByString:@""];
+            };
+        }
+        
+        if (type == WXDataBindingTypeAttributes) {
+            if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:attributeOrStyle];
+                WXJSExpression *expression = [parser parseExpression];
+                _bindingMatch = [self bindingBlockWithExpression:expression];
+            } else if ([WXBindingRepeatIdentify isEqualToString:attributeOrStyleName]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:attributeOrStyle[WXBindingRepeatExprIdentify]];
+                WXJSExpression *expression = [parser parseExpression];
+                _bindingRepeat = [self bindingBlockWithExpression:expression];
+                _repeatIndexIdentify = attributeOrStyle[WXBindingRepeatIndexIdentify];
+                _repeatLabelIdentify = attributeOrStyle[WXBindingRepeatLabelIdentify];
+            }
+        }
+    }];
+}
+
+- (WXDataBindingBlock)bindingBlockWithExpression:(WXJSExpression *)expression
+{
+    if (!expression) {
+        return nil;
+    }
+    WXDataBindingBlock block = ^id(NSDictionary *data, BOOL *needUpdate) {
+        if (expression->is<WXJSStringLiteral>()) {
+            *needUpdate = NO;
+            return [NSString stringWithCString:(((WXJSStringLiteral *)expression)->value).c_str() encoding:[NSString defaultCStringEncoding]];
+        } else if (expression->is<WXJSNumericLiteral>()) {
+            *needUpdate = NO;
+            return @(((WXJSNumericLiteral *)expression)->value);
+        } else if (expression->is<WXJSBooleanLiteral>()) {
+            *needUpdate = NO;
+            return @(((WXJSBooleanLiteral *)expression)->value);
+        } else if (expression->is<WXJSNullLiteral>()) {
+            *needUpdate = NO;
+            return nil;
+        } else if (expression->is<WXJSIdentifier>()) {
+            NSString *identiferName = [NSString stringWithCString:(((WXJSIdentifier *)expression)->name).c_str() encoding:[NSString defaultCStringEncoding]];
+            if (data[identiferName]) {
+                *needUpdate = YES;
+                return data[identiferName];
+            } else {
+                WXLogError(@"identifer:%@ not found", identiferName);
+                return nil;
+            }
+        } else if (expression->is<WXJSMemberExpression>()) {
+            WXJSMemberExpression *member = (WXJSMemberExpression *)expression;
+            BOOL objectNeedUpdate = NO, propertyNeedUpdate = NO;
+            id object = [self bindingBlockWithExpression:member->object](data, &objectNeedUpdate);
+            if (member->computed) {
+                id propertyName = [self bindingBlockWithExpression:member->property](data, &propertyNeedUpdate);
+                if ([object isKindOfClass:[NSDictionary class]] && [propertyName isKindOfClass:[NSString class]]) {
+                    return object[propertyName];
+                } else if ([object isKindOfClass:[NSArray class]] && [propertyName isKindOfClass:[NSNumber class]]) {
+                    return [object objectAtIndex:[propertyName unsignedIntegerValue]];
+                }
+            } else {
+                NSString *propertyName = [NSString stringWithCString:(((WXJSStringLiteral *)member->property)->value).c_str() encoding:[NSString defaultCStringEncoding]];
+                return object[propertyName];
+            }
+            
+            return nil;
+        } else if (expression->is<WXJSUnaryExpression>()) {
+            WXJSUnaryExpression *expr = (WXJSUnaryExpression *)expression;
+            std::string operator_ = expr->operator_;
+            id argument = [self bindingBlockWithExpression:expr->argument](data, needUpdate);
+            if (operator_ == "+") {
+                return @([argument doubleValue]);
+            } else if (operator_ == "-") {
+                return @(-[argument doubleValue]);
+            } else if (operator_ == "!") {
+                return @(![argument boolValue]);
+            } else {
+                WXLogError(@"Not supported unary operator:%s", operator_.c_str());
+                return nil;
+            }
+        } else if (expression->is<WXJSBinaryExpression>()) {
+            WXJSBinaryExpression *expr = (WXJSBinaryExpression *)expression;
+            std::string operator_ = expr->operator_;
+            BOOL leftNeedUpdate = NO, rightNeedUpdate = NO;
+            id left = [self bindingBlockWithExpression:expr->left](data, &leftNeedUpdate);
+            id right = [self bindingBlockWithExpression:expr->right](data, &rightNeedUpdate);
+            *needUpdate = leftNeedUpdate || rightNeedUpdate;
+            if (operator_ == "+") {
+                return @([left doubleValue] + [right doubleValue]);
+            } else if (operator_ == "-") {
+                return @([left doubleValue] - [right doubleValue]);
+            } else if (operator_ == "*") {
+                return @([left doubleValue] * [right doubleValue]);
+            } else if (operator_ == "/") {
+                return @([left doubleValue] / [right doubleValue]);
+            } else if (operator_ == "%") {
+                return @([left integerValue] % [right integerValue]);
+            } else if (operator_ == ">") {
+                return @([left doubleValue] > [right doubleValue]);
+            } else if (operator_ == ">=") {
+                return @([left doubleValue] >= [right doubleValue]);
+            } else if (operator_ == "<") {
+                return @([left doubleValue] < [right doubleValue]);
+            } else if (operator_ == "<=") {
+                return @([left doubleValue] <= [right doubleValue]);
+            } else if (operator_ == "===" || operator_ == "==") {
+                if ([left isKindOfClass:[NSString class]]) {
+                    return @([left isEqualToString:right]);
+                } else if ([left isKindOfClass:[NSNumber class]]) {
+                    return  @([left doubleValue] == [right doubleValue]);
+                } else {
+                    WXLogError(@"Wrong type %@ at left of '===' or '=='", NSStringFromClass([left class]));
+                    return nil;
+                }
+            } else if (operator_ == "!==" || operator_ == "!=") {
+                if ([left isKindOfClass:[NSString class]]) {
+                    return @(![left isEqualToString:right]);
+                } else if ([left isKindOfClass:[NSNumber class]]) {
+                    return  @([left doubleValue] != [right doubleValue]);
+                } else {
+                    WXLogError(@"Wrong type %@ at left of '!==' or '!='", NSStringFromClass([left class]));
+                    return nil;
+                }
+            } else if (operator_ == "||") {
+                return @([left boolValue] || [right boolValue]);
+            } else if (operator_ == "&&") {
+                return @([left boolValue] && [right boolValue]);
+            } else {
+                WXLogError(@"Not supported binary operator:%s", operator_.c_str());
+                return nil;
+            }
+        } else if (expression->is<WXJSConditionalExpression>()) {
+            WXJSConditionalExpression *conditional = (WXJSConditionalExpression *)expression;
+            BOOL testNeedUpdate = NO, conditionalNeedUpdate = NO, alternateNeedUpdate = NO;
+            id testResult = [self bindingBlockWithExpression:conditional->test](data, &testNeedUpdate);
+            id result;
+            if ([testResult boolValue]) {
+                result = [self bindingBlockWithExpression:conditional->consequent](data, &conditionalNeedUpdate);
+            } else {
+                result = [self bindingBlockWithExpression:conditional->alternate](data, &alternateNeedUpdate);
+            }
+            *needUpdate = testNeedUpdate || conditionalNeedUpdate || alternateNeedUpdate;
+            return result;
+        } else {
+            WXAssert(NO, @"expression type error");
+            return nil;
+        }
+    };
+    
+    return block;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
new file mode 100644
index 0000000..597aa99
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#include <string>
+
+typedef enum : NSUInteger {
+    WXJSExpressionTypeUnary,
+    WXJSExpressionTypeBinary,
+    WXJSExpressionTypeBinaryConditional,
+} WXJSExpressionType;
+
+struct WXJSExpression {
+    virtual ~WXJSExpression() {}
+    template <class T> bool is() {
+        return dynamic_cast<T *>(this) != NULL;
+    }
+};
+
+struct WXJSLiteral :WXJSExpression {
+};
+
+struct WXJSNullLiteral : WXJSLiteral {
+};
+
+struct WXJSStringLiteral : WXJSLiteral {
+    std::string value;
+};
+
+struct WXJSNumericLiteral : WXJSLiteral {
+    double value;
+};
+
+struct WXJSBooleanLiteral : WXJSLiteral {
+    bool value;
+};
+
+struct WXJSIdentifier : WXJSExpression {
+    std::string name;
+};
+
+struct WXJSMemberExpression : WXJSExpression {
+    WXJSExpression *object;
+    WXJSExpression *property;
+    bool computed;
+};
+
+struct WXJSUnaryExpression : WXJSExpression {
+    std::string operator_;
+    bool prefix;
+    WXJSExpression *argument;
+};
+
+struct WXJSBinaryExpression : WXJSExpression {
+    std::string operator_;
+    WXJSExpression *left;
+    WXJSExpression *right;
+};
+
+struct WXJSLogicalExpression : WXJSExpression {
+    std::string operator_;
+    WXJSExpression *left;
+    WXJSExpression *right;
+};
+
+struct WXJSConditionalExpression : WXJSExpression {
+    WXJSExpression *test;
+    WXJSExpression *alternate;
+    WXJSExpression *consequent;
+};
+
+
+@interface WXJSASTParser : NSObject
+
++ (instancetype)parserWithScript:(NSString *)script;
+
+- (WXJSExpression *)parseExpression;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
new file mode 100644
index 0000000..eaa8394
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
@@ -0,0 +1,873 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXJSASTParser.h"
+#import "WXLog.h"
+#include <vector>
+#include <sstream>
+
+
+typedef enum : NSUInteger {
+    WXJSTokenTypeBooleanLiteral = 1,
+    WXJSTokenTypeEOF,
+    WXJSTokenTypeIdentifier,
+    WXJSTokenTypeKeyword,
+    WXJSTokenTypeNullLiteral,
+    WXJSTokenTypeNumericLiteral,
+    WXJSTokenTypePunctuator,
+    WXJSTokenTypeStringLiteral,
+    WXJSTokenTypeRegularExpression,
+    WXJSTokenTypeTemplate
+} WXJSTokenType;
+
+struct WXJSToken {
+    WXJSTokenType type;
+    std::string value;
+    double doubleValue;
+    bool octal;
+    int start;
+    int end;
+};
+
+struct WXJSMarker {
+    int index;
+};
+
+static bool isWhiteSpace(int ch) {
+    return (ch == 32) ||  // space
+    (ch == 9) ||      // tab
+    (ch == 0xB) ||
+    (ch == 0xC) ||
+    (ch == 0xA0);
+}
+
+static bool isIdentifierStart(int ch)
+{
+    return (ch == 36) || (ch == 95) ||  // $ or _
+        (ch >= 65 && ch <= 90) ||         // A..Z
+        (ch >= 97 && ch <= 122) ||        // a..z
+        (ch == 92);                      // \ (backslash)
+}
+
+static bool isIdentifierPart(int ch) {
+    return (ch == 36) || (ch == 95) ||  // $ or _
+    (ch >= 65 && ch <= 90) ||         // A..Z
+    (ch >= 97 && ch <= 122) ||        // a..z
+    (ch >= 48 && ch <= 57) ||         // 0..9
+    (ch == 92);                      // \ (backslash)
+}
+
+static bool isDecimalDigit(int ch) {
+    return (ch >= 48 && ch <= 57);   // 0..9
+}
+
+static bool isHexDigit(int ch) {
+    return std::string("0123456789abcdefABCDEF").find(ch) != std::string::npos;
+}
+
+static bool isOctalDigit(int ch) {
+    return std::string("01234567").find(ch) != std::string::npos;
+}
+
+static int binaryPrecedence(WXJSToken *token)
+{
+    int prec = 0;
+    
+    if (token->type != WXJSTokenTypePunctuator) {
+        return prec;
+    }
+    
+    const std::string &value = token->value;
+    
+    if (value == "||") {
+        prec = 1;
+    }
+    
+    else if (value == "&&") {
+        prec = 2;
+    }
+    
+    else if (value == "|") {
+        prec = 3;
+    }
+    
+    else if (value == "^") {
+        prec = 4;
+    }
+    
+    else if (value == "&") {
+        prec = 5;
+    }
+    
+    else if (value == "==" || value == "!=" || value == "===" || value == "!==") {
+        prec = 6;
+    }
+    
+    else if (value == "<" || value == ">" || value == "<=" || value == ">=") {
+        prec = 7;
+    }
+    
+    else if (value == "<<" || value == ">>" || value == ">>>") {
+        prec = 8;
+    }
+    
+    else if (value == "+" || value == "-") {
+        prec = 9;
+    }
+    
+    else if (value == "*" || value == "/" || value == "%") {
+        prec = 11;
+    }
+    
+    return prec;
+}
+
+@implementation WXJSASTParser
+{
+    std::string _source;
+    
+    int _length;
+    int _index;
+    
+    WXJSToken *_lookahead;
+    
+    std::vector<WXJSToken *> _tokens;
+}
+
++ (instancetype)parserWithScript:(NSString *)script
+{
+    if (!script) {
+        WXLogError(@"can not init parser with nil script");
+        return nil;
+    }
+    return [[self alloc] initWithScript:script];
+}
+
+- (instancetype)initWithScript:(NSString *)script
+{
+    if (self = [super init]) {
+        _source = std::string([script UTF8String]);;
+        _length = (int)(_source.length());
+        _index = 0;
+        
+        _lookahead = NULL;
+        
+        [self nextToken];
+    }
+    
+    return self;
+}
+
+- (WXJSToken *)nextToken
+{
+    WXJSToken *token = _lookahead;
+    
+    WXJSToken *next = [self lex];
+    
+    _lookahead = next;
+    
+    if (next->type != WXJSTokenTypeEOF) {
+        _tokens.push_back(token);
+    }
+    
+    return token;
+}
+
+- (WXJSToken *)lex
+{
+    [self skipSpaces];
+    
+    if (_index >= _length) {
+        WXJSToken *token = new WXJSToken();
+        token->type = WXJSTokenTypeEOF;
+        token->value = "";
+        token->start = _index;
+        token->end = _index;
+        
+        return token;
+    }
+    
+    int ch = _source[_index];
+    
+    if (isIdentifierStart(ch)) {
+        return [self scanIdentifier];
+    }
+    
+    // ( or ) or ;
+    if (ch == 40 || ch == 41 || ch == 59) {
+        return [self scanPunctuator];
+    }
+    
+    // string starting with ' or " .
+    if (ch == 39 || ch == 34 ) {
+        return [self scanStringLiteral];
+    }
+    
+    // Dot (.) U+002E can also start a floating-point number, hence the need
+    // to check the next
+    if (ch == 0x2E) {
+        if (isDecimalDigit(_source[_index + 1])) {
+            return [self scanNumericLiteral];
+        }
+        return [self scanPunctuator];
+    }
+    
+    if (isDecimalDigit(ch)) {
+        return [self scanNumericLiteral];
+    }
+    
+    // Possible `identifier
+    if (ch >= 0xD800 && ch < 0xDFFF) {
+        if (isIdentifierStart(ch)) {
+            return [self scanIdentifier];
+        }
+    }
+    
+    return [self scanPunctuator];
+}
+
+- (WXJSToken *)scanIdentifier
+{
+    int start = _index;
+    // Backslash (U+005C) starts an escaped
+    std::string identifier = [self getIdentifier];
+    WXJSTokenType type;
+    if (identifier == "null") {
+        type = WXJSTokenTypeNullLiteral;
+    } else if (identifier == "true" || identifier == "false") {
+        type = WXJSTokenTypeBooleanLiteral;
+    } else {
+        type = WXJSTokenTypeIdentifier;
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = type;
+    token->value = identifier;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (std::string)getIdentifier
+{
+    int start = _index++;
+    while (_index < _length) {
+        int ch = _source[_index];
+        if (isIdentifierPart(ch)) {
+            ++_index;
+        } else {
+            break;
+        }
+    }
+    
+    return _source.substr(start, _index - start);
+}
+
+- (WXJSToken *)scanPunctuator
+{
+    int start = _index;
+    
+    // Check for most common single-character punctuators.
+    int ch = _source[_index];
+    std::string str = "";
+    switch (ch) {
+        // single-character punctuators
+        case 46:   // .
+        case 40:   // (
+        case 41:   // )
+        case 59:   // ;
+        case 44:   // ,
+        case 123:  // {
+        case 125:  // }
+        case 91:   // [
+        case 93:   // ]
+        case 58:   // :
+        case 63:   // ?
+        case 126:  // ~
+            ++_index;
+            str = std::string(1, ch);
+            break;
+        default:
+            str =  _source.substr(_index, 3);
+            if (str == "===" || str == "!==" || str == "**=") {
+                _index += 3;
+            } else {
+                str = str.substr(0, 2);
+                if (str == "&&" || str == "||" || str == "==" || str == "!=" ||
+                    str == "+=" || str == "-=" || str == "*=" || str == "/=" ||
+                    str == "++" || str == "--" || str == "&=" || str == "|=" ||
+                    str == "^=" || str == "%=" || str == "<=" || str == ">=" ||
+                    str == "=>" || str == "**") {
+                    _index += 2;
+                }  else {
+                    str = _source[_index];
+                    // parse 2-character punctuators first
+                    if (std::string("<>=!+-*%&|^/").find(ch) != std::string::npos) {
+                        ++_index;
+                    }
+                }
+            }
+    }
+    
+    if (_index == start) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypePunctuator;
+    token->value = str;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanStringLiteral
+{
+    int start = _index;
+    int quote = _source[start];
+    bool octal = false;
+    
+    ++_index;
+    std::string str = "";
+    
+    while (_index < _length) {
+        int ch = _source[_index++];
+        
+        if (ch == quote) {
+            quote = -1;
+            break;
+        } else if (ch == 92) { // \ (backslash)
+            ch = _source[_index++];
+            switch (ch) {
+                case 'u': {
+                    if (_source[_index] == '{') { // {
+                        ++_index;
+                        str += [self scanUnicodeCodePointEscape];
+                    } else {
+                        int unescaped = [self scanHexEscape:ch];
+                        if (unescaped == -1) {
+                            [self _throwError:@"Invalid hexadecimal escape"];
+                        } else {
+                            str += unescaped;
+                        }
+                    }
+                    break;
+                }
+                case 'x': {
+                    int unescaped = [self scanHexEscape:ch];
+                    if (unescaped == -1) {
+                        [self _throwError:@"Invalid hexadecimal escape"];
+                    } else {
+                        str += unescaped;
+                    }
+                    
+                    break;
+                }
+                case 'n': {
+                    str += '\n';
+                    break;
+                }
+                case 'r': {
+                    str += '\r';
+                    break;
+                }
+                case 't': {
+                    str += '\t';
+                    break;
+                }
+                case 'b': {
+                    str += '\b';
+                    break;
+                }
+                case 'f': {
+                    str += '\f';
+                    break;
+                }
+                case 'v': {
+                    str += '\x0B';
+                    break;
+                }
+                case '8':
+                case '9': {
+                    str += ch;
+                    [self _throwUnexpectedTokenError];
+                    break;
+                }
+                    
+                default:
+                    if (isOctalDigit(ch)) {
+                        int code = ch - '0';
+                        
+                        // \0 is not octal escape sequence
+                        if (code != 0) {
+                            octal = true;
+                        }
+                        
+                        if (_index < _length && isOctalDigit(_source[_index])) {
+                            octal = true;
+                            code = code * 8 + _source[_index++] - '0';
+                            
+                            // 3 digits are only allowed when string starts
+                            // with 0, 1, 2, 3
+                            if (std::string(1, '0123').find(ch) != std::string::npos &&
+                                _index < _length &&
+                                isOctalDigit(_source[_index])) {
+                                code = code * 8 + _source[_index++] - '0';
+                            }
+                        }
+                        str += std::string(1, code);
+                    } else {
+                        str += ch;
+                    }
+                    break;
+            }
+        } else {
+            str += ch;
+        }
+    }
+    
+    if (quote != -1) {
+        _index = start;
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeStringLiteral;
+    token->value = str;
+    token->octal = octal;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (int)scanUnicodeCodePointEscape {
+    int ch = _source[_index];
+    int code = 0;
+    
+    if (ch == '}') { // '}'
+        [self _throwError:@"At least one hex digit is required in Unicode"];
+    }
+    
+    while (_index < _length) {
+        ch = _source[_index++];
+        if (!isHexDigit(ch)) {
+            break;
+        }
+        code = (int)(code * 16 + std::string("0123456789abcdef").find(tolower(ch)));
+    }
+    
+    if (code > 0x10FFFF || ch != '}') {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    return code;
+}
+
+- (WXJSToken *)scanNumericLiteral
+{
+    int start = _index;
+    int ch = _source[start];
+    std::string num;
+    if (ch != '.') {
+        num = _source[_index++];
+        ch = _source[_index];
+        
+        if (num == "0") {
+            if (ch == 'x' || ch == 'X') {
+                ++_index;
+                return [self scanHexLiteral:start];
+            }
+            if (ch == 'b' || ch == 'B') {
+                ++_index;
+                return [self scanBinaryLiteral:start];
+            }
+            if (ch == 'o' || ch == 'O') {
+                return [self scanOctalLiteral:ch start:start];
+            }
+        }
+        
+        while (isDecimalDigit(_source[_index])) {
+            num += _source[_index++];
+        }
+        ch = _source[_index];
+    }
+    
+    if (ch == '.') {
+        num += _source[_index++];
+        while (isDecimalDigit(_source[_index])) {
+            num += _source[_index++];
+        }
+        ch = _source[_index];
+    }
+    
+    if (ch == 'e' || ch == 'E') {
+        num += _source[_index++];
+        
+        ch = _source[_index];
+        if (ch == '+' || ch == '-') {
+            num += _source[_index++];
+        }
+        if (isDecimalDigit(_source[_index])) {
+            while (isDecimalDigit(_source[_index])) {
+                num += _source[_index++];
+            }
+        } else {
+            [self _throwUnexpectedTokenError];
+        }
+    }
+    
+    if (isIdentifierStart(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = atof(num.c_str());
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanHexLiteral:(int)start
+{
+    std::string num = "";
+    while (_index < _length) {
+        if (!isHexDigit(_source[_index])) {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (num.length() == 0) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (isIdentifierStart(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 16));
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanBinaryLiteral: (int)start
+{
+    std::string num = "";
+    int ch;
+    
+    while (_index < _length) {
+        ch = _source[_index];
+        if (ch != '0' && ch != '1') {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (num.length() == 0) {
+        // only 0b or 0B
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (_index < _length) {
+        ch = _source[_index];
+        /* istanbul ignore else */
+        if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+            [self _throwUnexpectedTokenError];
+        }
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 2));
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+- (WXJSToken *)scanOctalLiteral:(int)prefix start:(int)start
+{
+    std::string num = "";
+    bool octal = false;
+    
+    if (isOctalDigit(prefix)) {
+        octal = true;
+        num = '0' + _source[_index++];
+    } else {
+        ++_index;
+    }
+    
+    while (_index < _length) {
+        if (!isOctalDigit(_source[_index])) {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (!octal && num.length() == 0) {
+        // only 0o or 0O
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (isIdentifierStart(_source[_index]) || isDecimalDigit(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 8));
+    token->octal = octal;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (int)scanHexEscape:(int)prefix
+{
+    int i, len, ch, code = 0;
+    
+    len = (prefix == 'u') ? 4 : 2;
+    for (i = 0; i < len; ++i) {
+        if (_index < _length && isHexDigit(_source[_index])) {
+            ch = _source[_index++];
+            code = (int)(code * 16 + std::string("0123456789abcdef").find(tolower(ch)));
+        } else {
+            return -1;
+        }
+    }
+    return code;
+}
+
+- (WXJSExpression *)parseExpression
+{
+    return [self parseConditionalExpression];
+}
+
+- (WXJSExpression *)parseConditionalExpression
+{
+    WXJSExpression *expr = [self parseBinaryExpression];
+    
+    if ([self match:"?"]) {
+        [self nextToken];
+        WXJSExpression *consequent = [self parseConditionalExpression];
+        [self expect:":"];
+        WXJSExpression *alternate = [self parseConditionalExpression];
+        
+        WXJSConditionalExpression *conditionalExpr = new WXJSConditionalExpression();
+        conditionalExpr->test = expr;
+        conditionalExpr->consequent = consequent;
+        conditionalExpr->alternate = alternate;
+        
+        return conditionalExpr;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)parseBinaryExpression
+{
+    WXJSExpression *expr = [self parseUnaryExpression];
+    
+    std::vector<int> precedenceStack;
+    std::vector<WXJSToken *> operatorStack;
+    std::vector<WXJSExpression *> expressionStack;
+    
+    WXJSToken *token = _lookahead;
+    int prec = binaryPrecedence(token);
+    if (prec == 0) {
+        return expr;
+    }
+    
+    [self nextToken];
+    
+    expressionStack.push_back(expr);
+    precedenceStack.push_back(prec);
+    operatorStack.push_back(token);
+    expressionStack.push_back([self parseUnaryExpression]);
+    
+    WXJSExpression *right;
+    std::string operator_;
+    WXJSExpression *left;
+    while ((prec = binaryPrecedence(_lookahead)) > 0) {
+        while ((expressionStack.size() > 1) && (prec <= precedenceStack[precedenceStack.size() - 1])) {
+            right = expressionStack[expressionStack.size() - 1];
+            expressionStack.pop_back();
+            operator_ = operatorStack[operatorStack.size() - 1]->value;
+            operatorStack.pop_back(); precedenceStack.pop_back();
+            left = expressionStack[expressionStack.size() - 1]; expressionStack.pop_back();
+            expressionStack.push_back([self createBinaryExpression:operator_ left:left right:right]);
+        }
+        
+        // Shift.
+        token = [self nextToken];
+        precedenceStack.push_back(prec);
+        operatorStack.push_back(token);
+        expressionStack.push_back([self parseUnaryExpression]);
+    }
+    
+    // Final reduce to clean-up the stack.
+    int i = (int)(expressionStack.size() - 1);
+    expr = expressionStack[i];
+    while (i > 0) {
+        expr = [self createBinaryExpression:operatorStack[i - 1]->value left:expressionStack[i - 1] right:expr];
+        i--;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)parseUnaryExpression
+{
+    WXJSToken *token;
+    
+    if ([self match:"++"] || [self match:"--"] || [self match:"+"] || [self match:"-"] || [self match:"~"] || [self match:"!"]) {
+        token = [self nextToken];
+        WXJSExpression *argument = [self parseUnaryExpression];
+        WXJSUnaryExpression *expr = new WXJSUnaryExpression();
+        expr->operator_ = token->value;
+        expr->prefix = ([self match:"++"] || [self match:"--"]) ? true : false;
+        expr->argument = argument;
+        return expr;
+    }
+    
+    return [self parseMemberExpression];
+}
+
+- (WXJSExpression *)parsePrimaryExpression
+{
+    int type = _lookahead->type;
+    
+    if (type == WXJSTokenTypeIdentifier) {
+        WXJSIdentifier *identifier = new WXJSIdentifier();
+        identifier->name = [self nextToken]->value;
+        return identifier;
+    }
+    
+    if (type == WXJSTokenTypeStringLiteral || type == WXJSTokenTypeNumericLiteral || type == WXJSTokenTypeBooleanLiteral || type == WXJSTokenTypeNullLiteral) {
+        return [self createLiteral:[self nextToken]];
+    } else {
+        [self _throwUnexpectedTokenError];
+        return new WXJSIdentifier();
+    }
+}
+
+
+- (WXJSExpression *)parseMemberExpression
+{
+    WXJSExpression *expr = [self parsePrimaryExpression];
+    
+    if ([self match:"."]) {
+        [self expect:"."];
+        WXJSExpression *property = [self parsePrimaryExpression];
+        WXJSMemberExpression *memberExpr = new WXJSMemberExpression();
+        memberExpr->object = expr;
+        memberExpr->property = property;
+        memberExpr->computed = false;
+        return memberExpr;
+    } else if ([self match:"["]) {
+        [self expect:"["];
+        WXJSExpression *property = [self parseConditionalExpression];
+        [self expect:"]"];
+        WXJSMemberExpression *memberExpr = new WXJSMemberExpression();
+        memberExpr->object = expr;
+        memberExpr->property = property;
+        memberExpr->computed = true;
+        return memberExpr;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)createBinaryExpression:(const std::string &)operator_ left:(WXJSExpression *)left right:(WXJSExpression *)right
+{
+    WXJSBinaryExpression *node = new WXJSBinaryExpression();
+    node->operator_ = operator_;
+    node->left = left;
+    node->right = right;
+    return node;
+}
+
+- (WXJSLiteral *)createLiteral:(WXJSToken *)token
+{
+    if (token->type == WXJSTokenTypeNumericLiteral) {
+        WXJSNumericLiteral *node = new WXJSNumericLiteral();
+        node->value = token->doubleValue;
+        return node;
+    } else if (token->type == WXJSTokenTypeNullLiteral) {
+        WXJSNullLiteral *node = new WXJSNullLiteral();
+        return node;
+    } else if (token->type == WXJSTokenTypeStringLiteral) {
+        WXJSStringLiteral *node = new WXJSStringLiteral();
+        node->value = token->value;
+        return node;
+    } else if (token->type == WXJSTokenTypeBooleanLiteral) {
+        WXJSBooleanLiteral *node = new WXJSBooleanLiteral();
+        node->value = token->value == "true";
+        return node;
+    } else {
+        assert(false);
+    }
+}
+
+- (void)skipSpaces
+{
+    int ch;
+    while (_index < _length) {
+        ch = _source[_index];
+        if (isWhiteSpace(ch)) {
+            ++_index;
+        } else {
+            break;
+        }
+    }
+}
+
+- (bool)match:(std::string)value
+{
+    return _lookahead->type == WXJSTokenTypePunctuator && _lookahead->value == value;
+}
+
+- (void)expect:(std::string)value
+{
+    WXJSToken *token = [self nextToken];
+    if (token->type != WXJSTokenTypePunctuator || token->value != value) {
+        [self _throwUnexpectedTokenError];
+    }
+}
+
+- (void)_throwUnexpectedTokenError
+{
+    [self _throwError:@"Unexpected Token"];
+}
+
+- (void)_throwError:(NSString *)errorMessage
+{
+    WXLogError(@"%@, index:%d, script:%s", errorMessage, _index, _source.c_str());
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
new file mode 100644
index 0000000..0e038a7
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXComponent.h"
+
+@interface WXRecycleListComponent : WXComponent <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
new file mode 100644
index 0000000..4d119c2
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXLog.h"
+#import "WXUtility.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+
+#import "WXCellSlotComponent.h"
+#import "WXRecycleListComponent.h"
+#import "WXRecycleListDataManager.h"
+#import "WXRecycleListTemplateManager.h"
+#import "WXRecycleListUpdateManager.h"
+
+@interface WXRecycleListComponent ()
+
+@end
+
+@implementation WXRecycleListComponent
+{
+    WXRecycleListDataManager *_dataManager;
+    WXRecycleListTemplateManager *_templateManager;
+    WXRecycleListUpdateManager *_updateManager;
+    
+    NSString *_templateKey;
+    __weak UICollectionView *_collectionView;
+    
+    NSMutableDictionary *_sizeCache;
+}
+
+- (instancetype)initWithRef:(NSString *)ref
+                       type:(NSString *)type
+                     styles:(NSDictionary *)styles
+                 attributes:(NSDictionary *)attributes
+                     events:(NSArray *)events
+               weexInstance:(WXSDKInstance *)weexInstance
+{
+    if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
+        _dataManager = [[WXRecycleListDataManager alloc] initWithData:attributes[@"listData"]];
+        _templateManager = [WXRecycleListTemplateManager new];
+        _updateManager = [WXRecycleListUpdateManager new];
+        _templateKey = [WXConvert NSString:attributes[@"templateKey"]] ? : @"templateType";
+        _sizeCache = [NSMutableDictionary dictionary];
+    }
+    
+    return self;
+}
+
+#pragma mark - WXComponent Methods
+
+- (UIView *)loadView
+{
+    UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
+    return [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    
+    _collectionView = (UICollectionView *)self.view;
+    _collectionView.allowsSelection = NO;
+    _collectionView.allowsMultipleSelection = NO;
+    _collectionView.dataSource = self;
+    _collectionView.delegate = self;
+    
+    _templateManager.collectionView = _collectionView;
+    _updateManager.collectionView = _collectionView;
+//    [_updateManager reload];
+}
+
+- (void)viewWillUnload
+{
+    [super viewWillUnload];
+    
+    _collectionView.dataSource = nil;
+    _collectionView.delegate = nil;
+}
+
+- (void)setContentSize:(CGSize)contentSize
+{
+    // Do Nothing
+}
+
+- (void)adjustSticky
+{
+    // Do Nothing, sticky is adjusted by layout
+}
+
+#pragma mark - WXComonent Internal Methods
+
+- (void)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index
+{
+   [super _insertSubcomponent:subcomponent atIndex:index];
+    
+    if ([subcomponent isKindOfClass:[WXCellSlotComponent class]]) {
+        WXCellSlotComponent *cell = (WXCellSlotComponent*)subcomponent;
+        [self.weexInstance.componentManager _addUITask:^{
+            [_templateManager addTemplate:cell];
+        }];
+        
+        //TODO: update collection view if adding template
+    }
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
+{
+    return 1;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
+    return [_dataManager numberOfItems];
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    // 1. get the data relating to the cell
+    NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
+    if (!data || ![data isKindOfClass:[NSDictionary class]]) {
+        WXLogError(@"No data or wrong data format for index:%zd, data:%@", indexPath.row, data);
+        return nil;
+    }
+    
+    // 2. get the template type specified by data
+    NSString *templateType = data[_templateKey];
+    if (!templateType) {
+        WXLogError(@"Each data should have a value for %@ to indicate template type", _templateKey);
+        return nil;
+    }
+    
+    // 3. dequeue a cell component by template type
+    UICollectionViewCell *cellView = [_collectionView dequeueReusableCellWithReuseIdentifier:templateType forIndexPath:indexPath];
+    WXCellSlotComponent *cellComponent = (WXCellSlotComponent *)cellView.wx_component;
+    if (!cellComponent) {
+        cellComponent = [_templateManager dequeueCellSlotWithType:templateType forIndexPath:indexPath];
+        cellView.wx_component = cellComponent;
+        WXPerformBlockOnComponentThread(^{
+            //TODO: How can we avoid this?
+            [super _insertSubcomponent:cellComponent atIndex:self.subcomponents.count];
+        });
+    }
+    
+    
+    // 4. binding the data to the cell component
+    WXPerformBlockOnComponentThread(^{
+        [cellComponent updateCellData:data];
+        WXPerformBlockOnMainThread(^{
+            NSValue *cacheSize = _sizeCache[indexPath];
+            if (!cacheSize || !CGSizeEqualToSize([cacheSize CGSizeValue] , cellComponent.calculatedFrame.size)) {
+                _sizeCache[indexPath] = [NSValue valueWithCGSize:cellComponent.calculatedFrame.size];
+                [UIView performWithoutAnimation:^{
+                    [_collectionView reloadItemsAtIndexPaths:@[indexPath]];
+                }];
+            }
+        });
+    });
+    
+    // 5. Add cell component's view to content view.
+    UIView *contentView = cellComponent.view;
+    if (contentView.superview == cellView.contentView) {
+        return cellView;
+    }
+    
+    for (UIView *view in cellView.contentView.subviews) {
+        [view removeFromSuperview];
+    }
+    [cellView.contentView addSubview:contentView];
+    [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
+    
+    return cellView;
+}
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
+{
+    return nil;
+}
+
+#pragma mark - UICollectionViewDelegate
+
+- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    WXLogDebug(@"will display cell:%@, at index path:%@", cell, indexPath);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    WXLogDebug(@"Did end displaying cell:%@, at index path:%@", cell, indexPath);
+}
+
+#pragma mark - UICollectionViewDelegateFlowLayout
+- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    NSValue *size = _sizeCache[indexPath];
+    if (size) {
+        return [size CGSizeValue];
+    } else {
+        NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
+        WXCellSlotComponent *cell = [_templateManager templateWithType:data[_templateKey]];
+        CGSize size = cell.calculatedFrame.size;
+        _sizeCache[indexPath] = [NSValue valueWithCGSize:size];
+        return size;
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
new file mode 100644
index 0000000..c340f9d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXRecycleListDataManager : NSObject
+
+- (instancetype)initWithData:(NSArray *)data;
+
+- (void)updateData:(NSArray *)data;
+
+- (NSDictionary *)dataAtIndex:(NSInteger)index;
+
+- (NSInteger)numberOfItems;
+
+@end



[09/17] incubator-weex git commit: * [ios] Add new files to dynamic target

Posted by ac...@apache.org.
* [ios] Add new files to dynamic target


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

Branch: refs/heads/0.16-dev
Commit: 523843adb06a0562bdbc15fa40b2d87081462897
Parents: 81c7816
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:57:48 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:57:48 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 33 ++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/523843ad/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index a7329a7..37aa33c 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -182,6 +182,22 @@
 		74AD99841D5B0E59008F0336 /* WXPolyfillSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 74AD99821D5B0E59008F0336 /* WXPolyfillSet.h */; };
 		74AD99851D5B0E59008F0336 /* WXPolyfillSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 74AD99831D5B0E59008F0336 /* WXPolyfillSet.m */; };
 		74B232D21D2A2BA4006322EA /* WXLayoutDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 74B232D11D2A2BA4006322EA /* WXLayoutDefine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		74B81AE31F73C3E300D3A61D /* WXRecycleListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */; };
+		74B81AE41F73C3E500D3A61D /* WXRecycleListComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */; };
+		74B81AE51F73C3E900D3A61D /* WXRecycleListDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */; };
+		74B81AE61F73C3E900D3A61D /* WXRecycleListDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */; };
+		74B81AE71F73C3E900D3A61D /* WXRecycleListTemplateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */; };
+		74B81AE81F73C3E900D3A61D /* WXRecycleListTemplateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */; };
+		74B81AE91F73C3E900D3A61D /* WXRecycleListUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */; };
+		74B81AEA1F73C3E900D3A61D /* WXRecycleListUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */; };
+		74B81AEB1F73C3E900D3A61D /* WXRecycleListLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */; };
+		74B81AEC1F73C3E900D3A61D /* WXRecycleListLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */; };
+		74B81AED1F73C3E900D3A61D /* WXCellSlotComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 746B92391F46BE36009AE86B /* WXCellSlotComponent.h */; };
+		74B81AEE1F73C3E900D3A61D /* WXCellSlotComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */; };
+		74B81AEF1F73C3E900D3A61D /* WXComponent+DataBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */; };
+		74B81AF01F73C3E900D3A61D /* WXComponent+DataBinding.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */; };
+		74B81AF11F73C3E900D3A61D /* WXJSASTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */; };
+		74B81AF21F73C3E900D3A61D /* WXJSASTParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */; };
 		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 */; };
@@ -1706,11 +1722,14 @@
 				DCA445A61EFA571E00D0CFA8 /* WXSDKEngine.h in Headers */,
 				DCA445AA1EFA573900D0CFA8 /* WXResourceRequest.h in Headers */,
 				DCA445C61EFA57EE00D0CFA8 /* NSObject+WXSwizzle.h in Headers */,
+				74B81AEB1F73C3E900D3A61D /* WXRecycleListLayout.h in Headers */,
 				DCA445B41EFA577F00D0CFA8 /* WXJSExceptionProtocol.h in Headers */,
+				74B81AEF1F73C3E900D3A61D /* WXComponent+DataBinding.h in Headers */,
 				DCA445B51EFA578400D0CFA8 /* WXJSExceptionInfo.h in Headers */,
 				DCA445B61EFA578B00D0CFA8 /* WXIndicatorComponent.h in Headers */,
 				DCA445BF1EFA57C300D0CFA8 /* WXComponent.h in Headers */,
 				DCA445A71EFA572300D0CFA8 /* WXRootViewController.h in Headers */,
+				74B81AE91F73C3E900D3A61D /* WXRecycleListUpdateManager.h in Headers */,
 				DCA445C01EFA57C900D0CFA8 /* WXBridgeProtocol.h in Headers */,
 				DCA445AC1EFA574A00D0CFA8 /* WXNetworkProtocol.h in Headers */,
 				DCA445C31EFA57DC00D0CFA8 /* WXAppMonitorProtocol.h in Headers */,
@@ -1736,11 +1755,13 @@
 				DCA445A11EFA56FA00D0CFA8 /* WXScrollerProtocol.h in Headers */,
 				DCA445DE1EFA59B800D0CFA8 /* WXSectionDataController.h in Headers */,
 				DCA445F01EFA5A1D00D0CFA8 /* WXComponent_internal.h in Headers */,
+				74B81AE71F73C3E900D3A61D /* WXRecycleListTemplateManager.h in Headers */,
 				DCA445ED1EFA5A1200D0CFA8 /* WXTransform.h in Headers */,
 				DCA445CD1EFA592E00D0CFA8 /* WXComponent+Events.h in Headers */,
 				DCA445EC1EFA5A0E00D0CFA8 /* WXTextAreaComponent.h in Headers */,
 				DCA445D81EFA599400D0CFA8 /* WXRootView.h in Headers */,
 				DCA446131EFA5A8C00D0CFA8 /* WXCallJSMethod.h in Headers */,
+				74B81AED1F73C3E900D3A61D /* WXCellSlotComponent.h in Headers */,
 				DCA445E41EFA59DC00D0CFA8 /* WXVideoComponent.h in Headers */,
 				DCA4460B1EFA5A7200D0CFA8 /* WXAssert.h in Headers */,
 				DCA445F71EFA5A3100D0CFA8 /* WXPickerModule.h in Headers */,
@@ -1772,6 +1793,7 @@
 				DCA4460E1EFA5A7E00D0CFA8 /* WXLength.h in Headers */,
 				DCA445FA1EFA5A3A00D0CFA8 /* WXNavigatorModule.h in Headers */,
 				DCA446081EFA5A6A00D0CFA8 /* NSArray+Weex.h in Headers */,
+				74B81AE51F73C3E900D3A61D /* WXRecycleListDataManager.h in Headers */,
 				DCA445F21EFA5A2300D0CFA8 /* WXHeaderComponent.h in Headers */,
 				DCA445DD1EFA59B300D0CFA8 /* WXRecyclerUpdateController.h in Headers */,
 				DCA4461E1EFA5AAF00D0CFA8 /* WXComponentFactory.h in Headers */,
@@ -1781,6 +1803,7 @@
 				DCA4461D1EFA5AAA00D0CFA8 /* WXHandlerFactory.h in Headers */,
 				DCA445EE1EFA5A1500D0CFA8 /* WXWebComponent.h in Headers */,
 				DCA4460D1EFA5A7900D0CFA8 /* WXThreadSafeMutableArray.h in Headers */,
+				74B81AE31F73C3E300D3A61D /* WXRecycleListComponent.h in Headers */,
 				DCA445DA1EFA59A600D0CFA8 /* WXMultiColumnLayout.h in Headers */,
 				DCA445E01EFA59CD00D0CFA8 /* WXLoadingIndicator.h in Headers */,
 				DCA445E61EFA59E500D0CFA8 /* WXImageComponent.h in Headers */,
@@ -1816,6 +1839,7 @@
 				DCA445EB1EFA5A0B00D0CFA8 /* WXTextInputComponent.h in Headers */,
 				DCA4460C1EFA5A7600D0CFA8 /* WXThreadSafeMutableDictionary.h in Headers */,
 				DCA445CE1EFA593500D0CFA8 /* WXComponent+BoxShadow.h in Headers */,
+				74B81AF11F73C3E900D3A61D /* WXJSASTParser.h in Headers */,
 				DCA4461C1EFA5AA600D0CFA8 /* WXModuleFactory.h in Headers */,
 				DCA445D91EFA59A100D0CFA8 /* WXEditComponent.h in Headers */,
 				DCA445FB1EFA5A3C00D0CFA8 /* WXStorageModule.h in Headers */,
@@ -1928,6 +1952,7 @@
 					};
 					DCA445241EFA555400D0CFA8 = {
 						CreatedOnToolsVersion = 8.3.3;
+						DevelopmentTeam = "Xing Zhang";
 						ProvisioningStyle = Automatic;
 					};
 				};
@@ -2207,7 +2232,9 @@
 				DCA445391EFA55B300D0CFA8 /* WXComponent+PseudoClassManagement.m in Sources */,
 				DCA4453A1EFA55B300D0CFA8 /* WXView.m in Sources */,
 				DCA4453B1EFA55B300D0CFA8 /* WXErrorView.m in Sources */,
+				74B81AEC1F73C3E900D3A61D /* WXRecycleListLayout.m in Sources */,
 				DCA4453C1EFA55B300D0CFA8 /* WXComponent+ViewManagement.m in Sources */,
+				74B81AE41F73C3E500D3A61D /* WXRecycleListComponent.m in Sources */,
 				DC7764951F3C685200B5727E /* WXRecyclerDragController.m in Sources */,
 				DCA4453D1EFA55B300D0CFA8 /* WXRootView.m in Sources */,
 				DCA4453E1EFA55B300D0CFA8 /* WXBaseViewController.m in Sources */,
@@ -2223,7 +2250,9 @@
 				DCA445481EFA55B300D0CFA8 /* WXLoadingIndicator.m in Sources */,
 				DCA445491EFA55B300D0CFA8 /* WXRefreshComponent.m in Sources */,
 				DCA4454A1EFA55B300D0CFA8 /* WXEmbedComponent.m in Sources */,
+				74B81AE81F73C3E900D3A61D /* WXRecycleListTemplateManager.m in Sources */,
 				DCA4454B1EFA55B300D0CFA8 /* WXVideoComponent.m in Sources */,
+				74B81AE61F73C3E900D3A61D /* WXRecycleListDataManager.m in Sources */,
 				DCA4454C1EFA55B300D0CFA8 /* WXComponent.m in Sources */,
 				DCA4454D1EFA55B300D0CFA8 /* WXDivComponent.m in Sources */,
 				DCA4454E1EFA55B300D0CFA8 /* WXImageComponent.m in Sources */,
@@ -2246,6 +2275,7 @@
 				DCA4455D1EFA55B300D0CFA8 /* WXHeaderComponent.m in Sources */,
 				DCA4455E1EFA55B300D0CFA8 /* WXFooterComponent.m in Sources */,
 				DCA4455F1EFA55B300D0CFA8 /* WXNavigationDefaultImpl.m in Sources */,
+				74B81AF21F73C3E900D3A61D /* WXJSASTParser.mm in Sources */,
 				DCA445601EFA55B300D0CFA8 /* WXURLRewriteDefaultImpl.m in Sources */,
 				DCA445611EFA55B300D0CFA8 /* WXPrerenderManager.m in Sources */,
 				DCA445631EFA55B300D0CFA8 /* WXPickerModule.m in Sources */,
@@ -2265,8 +2295,11 @@
 				DCA445711EFA55B300D0CFA8 /* WXMetaModule.m in Sources */,
 				DCA445721EFA55B300D0CFA8 /* WXBoxShadow.m in Sources */,
 				DCA445731EFA55B300D0CFA8 /* NSTimer+Weex.m in Sources */,
+				74B81AEE1F73C3E900D3A61D /* WXCellSlotComponent.m in Sources */,
 				DCA445741EFA55B300D0CFA8 /* WXConvert.m in Sources */,
 				DCA445751EFA55B300D0CFA8 /* WXUtility.m in Sources */,
+				74B81AEA1F73C3E900D3A61D /* WXRecycleListUpdateManager.m in Sources */,
+				74B81AF01F73C3E900D3A61D /* WXComponent+DataBinding.mm in Sources */,
 				DCA445761EFA55B300D0CFA8 /* WXLog.m in Sources */,
 				DCA445771EFA55B300D0CFA8 /* WXWeakObjectWrapper.m in Sources */,
 				DCA445781EFA55B300D0CFA8 /* NSArray+Weex.m in Sources */,


[14/17] incubator-weex git commit: * [ios] merge pull request

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/pre-build/native-bundle-main.js
----------------------------------------------------------------------
diff --git a/pre-build/native-bundle-main.js b/pre-build/native-bundle-main.js
index 70f4b57..c737167 100644
--- a/pre-build/native-bundle-main.js
+++ b/pre-build/native-bundle-main.js
@@ -1,8 +1,8 @@
-(this.nativeLog||function(e){console.log(e)})("START JS FRAMEWORK 0.22.3, Build 2017-09-21 19:05."),this.getJSFMVersion=function(){return"0.22.3"};var global=this,process={env:{}},setTimeout=global.setTimeout;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(0,function(){"use strict";function e(e){Hn.Document=e.Document,Hn.Element=e.Element,Hn.Comment=e.Comment,Hn.sendTasks=e.sendTasks}function t(e,t,n,r,o){void 0===n&&(n={}),void 0===r&&(r={}),void 0===o&&(o={});var i=new Hn.Document(e,n.bundleUrl),a={},s={id:e,data:r,document:i,callbacks:a},u=0;i.addCallback=function(e){return u++,a[u]=e,u},i.handleCallback=function(e,t,n){var r=a[e];return n&&delete a[e],r(t)},Gn[e]=s;var c=Object.assign({Document:Hn.Document,Element:Hn.Element,Comment:Hn.Comment,sendTasks:function(t){return Hn.sendTasks(e,t,-1)},options:n,document:i},o),l=[],f=[];for(var p in c)l.push(p),f.push(c[p]);return l.push(t),(new(Function.prototy
 pe.bind.apply(Function,[null].concat(l)))).apply(void 0,f),Hn.sendTasks(e,[{module:"dom",method:"createFinish",args:[]}],-1),s}function n(e){delete Gn[e]}function r(e){return Gn[e].document.body.toJSON()}function o(e,t){var n={fireEvent:function(e,t,n,r,o){var i=Gn[e],a=i.document,s=a.getRef(t);return a.fireEvent(s,n,r,o)},callback:function(e,t,n,r){return Gn[e].document.handleCallback(t,n,r)}};if((Gn[e]||{}).document&&Array.isArray(t)){var r=[];return t.forEach(function(t){var o=n[t.method],i=[].concat(t.args);"function"==typeof o&&(i.unshift(e),r.push(o.apply(void 0,i)))}),r}}function i(e){return e&&e.__esModule?e.default:e}function a(e,t){return t={exports:{}},e(t,t.exports),t.exports}function s(e){console.warn("[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead");var t=this._ids[e];if(t)return t.vm}function u(e){var t=this._ids[e];if(t)return t.el}function c(e){var t=this._ids[e];if(t)return t.vm}function l(e){return this._app.differ.then(function(){e()})}function f(e,
 t){console.warn("[JS Framework] Vm#$scrollTo is deprecated, please use \"require('@weex-module/dom').scrollTo(el, options)\" instead");var n=this.$el(e);if(n){this._app.requireModule("dom").scrollToElement(n.ref,{offset:t})}}function p(e,t,n){var r=this,o=this.$el(e);if(o&&t&&t.styles){this._app.requireModule("animation").transition(o.ref,t,function(){for(var e=[],i=arguments.length;i--;)e[i]=arguments[i];r._setStyle(o,t.styles),n&&n.apply(void 0,e)})}}function d(e){var t=this._app.options;return"function"==typeof e&&(console.warn("[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, this api now can directly RETURN config info."),e(t)),t}function h(e,t){console.warn("[JS Framework] Vm#$sendHttp is deprecated, please use \"require('@weex-module/stream').sendHttp(params, callback)\" instead"),this._app.requireModule("stream").sendHttp(e,t)}function v(e){console.warn("[JS Framework] Vm#$openURL is deprecated, please use \"require('@weex-module/event').openURL(url)\" i
 nstead"),this._app.requireModule("event").openURL(e)}function y(e){console.warn("[JS Framework] Vm#$setTitle is deprecated, please use \"require('@weex-module/pageInfo').setTitle(title)\" instead"),this._app.requireModule("pageInfo").setTitle(e)}function m(e,t){for(var n=[],r=arguments.length-2;r-- >0;)n[r]=arguments[r+2];console.warn("[JS Framework] Vm#$call is deprecated, please use \"require('@weex-module/moduleName')\" instead");var o=this._app.requireModule(e);o&&o[t]&&o[t].apply(o,n)}function _(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];if("function"==typeof Object.assign)Object.assign.apply(Object,[e].concat(t));else{var r=t.shift();for(var o in r)e[o]=r[o];t.length&&_.apply(void 0,[e].concat(t))}return e}function g(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function b(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function w(e,t){return hr.call(e,t)}function x(e,t){return function(n){var 
 r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}}function E(e){return null!==e&&"object"==typeof e}function O(e){return vr.call(e)===yr}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function C(){return"object"==typeof nativeSet?nativeSet.create():new Jn}function k(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1).toLowerCase()}function j(e){return e.replace(_r,"").replace(gr,"")}function A(e){return e.replace(wr,"")}function I(){this.id=Cr++,this.subs=[]}function T(e){I.target&&kr.push(I.target),I.target=e}function N(){I.target=kr.pop()}function P(){I.target=null,kr=[]}function M(e,t,n,r){r&&_(this,r);var o="function"==typeof t;this.vm=e,e._watchers.push(this),this.expression=t,this.cb=n,this.id=++jr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=C(),this.newDepIds=C(),o&&(this.getter=t),this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function $(e,t){var n,r,o,i;if(
 t||(t=Ar,t.clear()),o=Array.isArray(e),i=E(e),o||i){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.length;n--;)$(e[n],t);else if(i)for(r=Object.keys(e),n=r.length;n--;)$(e[r[n]],t)}}function R(e){if(this.value=e,this.dep=new I,g(e,"__ob__",this),Array.isArray(e)){(mr?D:F)(e,Tr,Nr),this.observeArray(e)}else this.walk(e)}function D(e,t){e.__proto__=t}function F(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];g(e,i,t[i])}}function L(e,t){if(E(e)){var n;return w(e,"__ob__")&&e.__ob__ instanceof R?n=e.__ob__:(Array.isArray(e)||O(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new R(e)),n&&t&&n.addVm(t),n}}function W(e,t,n){var r=new I,o=Object.getOwnPropertyDescriptor(e,t);if(!o||!1!==o.configurable){var i=o&&o.get,a=o&&o.set,s=L(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=i?i.call(e):n;if(I.target&&(r.depend(),s&&s.dep.depend(),Array.isArray(t)))for(var o=void 0,a=0,u=t.length;a<u;a++)(o=t[a])&&o.__ob__&&o.__ob__.dep.depend(
 );return t},set:function(t){t!==(i?i.call(e):n)&&(a?a.call(e,t):n=t,s=L(t),r.notify())}})}}function U(e,t,n){if(Array.isArray(e))return e.splice(t,1,n);if(w(e,t))return void(e[t]=n);if(e._isVue)return void U(e._data,t,n);var r=e.__ob__;if(!r)return void(e[t]=n);if(r.convert(t,n),r.dep.notify(),r.vms)for(var o=r.vms.length;o--;){var i=r.vms[o];B(i,t)}return n}function V(e,t){if(w(e,t)){delete e[t];var n=e.__ob__;if(!n)return void(e._isVue&&delete e._data[t]);if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var o=n.vms[r];q(o,t)}}}function B(e,t){(Pr.indexOf(t)>-1||!S(t))&&Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return e._data[t]},set:function(n){e._data[t]=n}})}function q(e,t){S(t)||delete e[t]}function z(e){e._watchers=[],J(e),G(e),K(e)}function J(e){var t=e._data;O(t)||(t={});for(var n=Object.keys(t),r=n.length;r--;)B(e,n[r]);L(t,e)}function H(){}function G(e){var t=e._computed;if(t)for(var n in t){var r=t[n],o={enumerable:!0,configurable:!0};"fu
 nction"==typeof r?(o.get=X(r,e),o.set=H):(o.get=r.get?!1!==r.cache?X(r.get,e):x(r.get,e):H,o.set=r.set?x(r.set,e):H),Object.defineProperty(e,n,o)}}function X(e,t){var n=new M(t,e,null,{lazy:!0});return function(){return n.dirty&&n.evaluate(),I.target&&n.depend(),n.value}}function K(e){var t=e._methods;if(t)for(var n in t)e[n]=t[n]}function Z(e){var t=e.type,n=$r[t];if("object"==typeof n)for(var r in n)if(null==e[r])e[r]=n[r];else if("object"===k(e[r])&&"object"===k(n[r]))for(var o in n[r])null==e[r][o]&&(e[r][o]=n[r][o])}function Q(e,t,n){oe(e,t,n.id,e),ie(e,t,n.attr),se(e,t,n.classList),ue(e,t,n.style),le(e,t,n.events)}function Y(e,t,n,r){t=t||{},n=n||{};var o=t._options||{},i=o.props;Array.isArray(i)&&(i=i.reduce(function(e,t){return e[t]=!0,e},{})),te(r,i,e,t),te(n.attr,i,e,t)}function ee(e,t,n,r){void 0===r&&(r={}),re(n.classList,e,t),ne(n.style,e,t),r.children?r.children[r.children.length-1]._vm=t:r._vm=t}function te(e,t,n,r){if(e){for(var o in e)!function(o){if(!t||t[o]){var i
 =e[o];if("function"==typeof i){var a=de(n,i,function(e){r[o]=e});r[o]=a}else r[o]=i}}(o)}}function ne(e,t,n){for(var r in e)!function(r){var o=e[r];if("function"==typeof o){var i=de(t,o,function(e){n._rootEl&&n._rootEl.setStyle(r,e)});n._rootEl.setStyle(r,i)}else n._rootEl&&n._rootEl.setStyle(r,o)}(r)}function re(e,t,n){function r(e,t){"array"===k(e)&&e.unshift(t)}var o=t._options&&t._options.style||{};if(n._rootEl){var i="@originalRootEl";if(o[i]=n._rootEl.classStyle,"function"==typeof e){var a=de(t,e,function(e){r(e,i),ae(n._rootEl,o,e)});r(a,i),ae(n._rootEl,o,a)}else null!=e&&(r(e,i),ae(n._rootEl,o,e))}}function oe(e,t,n,r){var o=Object.create(null);if(Object.defineProperties(o,{vm:{value:r,writable:!1,configurable:!1},el:{get:function(){return t||r._rootEl},configurable:!1}}),"function"==typeof n){var i=n;n=i.call(e),(n||0===n)&&(e._ids[n]=o),de(e,i,function(t){t&&(e._ids[t]=o)})}else n&&"string"==typeof n&&(e._ids[n]=o)}function ie(e,t,n){fe(e,t,"attr",n)}function ae(e,t,n){"st
 ring"==typeof n&&(n=n.split(/\s+/)),n.forEach(function(e,t){n.splice.apply(n,[t,1].concat(e.split(/\s+/)))});for(var r={},o=n.length,i=0;i<o;i++)!function(e){var o=t[n[e]];o&&Object.keys(o).forEach(function(e){r[e]=o[e]})}(i);e.setClassStyle(r)}function se(e,t,n){if("function"==typeof n||Array.isArray(n)){if(Array.isArray(n)&&!n.length)return void t.setClassStyle({});var r=e._options&&e._options.style||{};if("function"==typeof n){var o=de(e,n,function(e){ae(t,r,e)});ae(t,r,o)}else ae(t,r,n)}}function ue(e,t,n){fe(e,t,"style",n)}function ce(e,t,n,r){t.addEvent(n,x(r,e))}function le(e,t,n){if(n)for(var r=Object.keys(n),o=r.length;o--;){var i=r[o],a=n[i];"string"==typeof a&&((a=e[a])||console.warn('[JS Framework] The event handler "'+a+'" is not defined.')),ce(e,t,i,a)}}function fe(e,t,n,r){if(r)for(var o=Object.keys(r),i=o.length;i--;){var a=o[i],s=r[a];"function"==typeof s?pe(e,t,n,a,s):t[Rr[n]](a,s)}}function pe(e,t,n,r,o){var i=Rr[n],a=de(e,o,function(n){function o(){t[i](r,n)}var 
 a=e&&e._app&&e._app.differ;a?a.append("element",t.depth||0,t.ref,o):o()});t[i](r,a)}function de(e,t,n){return e._static?t.call(e,e):new M(e,t,function(e,t){"object"!=typeof e&&e===t||n(e)}).value}function he(e,t){return e._app.doc.createBody(t)}function ve(e,t){return e._app.doc.createElement(t)}function ye(e,t){var n=me(e),r=_e(e),o=Dr++;if(t.element){var i=t.updateMark;i?(i.element&&(i=i.end),t.element.insertAfter(r,i),t.element.insertAfter(n,i),t.updateMark=r):(t.element.insertBefore(n,t.end),t.element.insertBefore(r,t.end)),t=t.element}else t.appendChild(n),t.appendChild(r);return{start:n,end:r,element:t,blockId:o}}function me(e){return e._app.doc.createComment("start")}function _e(e){return e._app.doc.createComment("end")}function ge(e,t,n){if(n.element){var r=n.end,o=n.updateMark;if(n.children&&n.children.push(t),o){var i=be(e,t,o);return n.updateMark=t.element?t.end:t,i}if(!t.element)return n.element.insertBefore(t,r);n.element.insertBefore(t.start,r),n.element.insertBefore(t
 .end,r)}else{if(!t.element)return n.appendChild(t);n.appendChild(t.start),n.appendChild(t.end)}}function be(e,t,n){return t.element?xe(t,n):we(t,n)}function we(e,t){var n=t.parentNode;if(n)return n.insertAfter(e,t)}function xe(e,t){var n=t.parentNode;if(n){for(var r,o=e.start,i=[o];o&&o!==e.end;)o=o.nextSibling,i.push(o);var a=t;return i.every(function(e){return r=n.insertAfter(e,a),a=e,-1!==r}),r}}function Ee(e,t,n){void 0===n&&(n=!1),t.element?Se(t,n):Oe(t),t._vm&&t._vm.$emit("hook:destroyed")}function Oe(e){var t=e.parentNode;t&&t.removeChild(e)}function Se(e,t){void 0===t&&(t=!1);for(var n=[],r=e.start.nextSibling;r&&r!==e.end;)n.push(r),r=r.nextSibling;t||Oe(e.start),n.forEach(function(e){Oe(e)}),t||Oe(e.end)}function Ce(e){var t=e._options||{},n=t.template||{};t.replace?n.children&&1===n.children.length?ke(e,n.children[0],e._parentEl):ke(e,n.children,e._parentEl):ke(e,n,e._parentEl),console.debug('[JS Framework] "ready" lifecycle in Vm('+e._type+")"),e.$emit("hook:ready"),e._r
 eady=!0}function ke(e,t,n,r){if(-1!==(e._app||{}).lastSignal){if(t.attr&&t.attr.hasOwnProperty("static")&&(e._static=!0),je(t))return void Me(e,t,n,r);if(r=r||{},Ae(t))return console.debug('[JS Framework] compile "content" block by',t),void(e._content=ye(e,n));if(Ie(t,r))return console.debug('[JS Framework] compile "repeat" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `repeat` directive!"):$e(e,t,n));if(Te(t,r))return console.debug('[JS Framework] compile "if" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `if` directive!"):Re(e,t,n,r));var o=r.type||t.type;if(Ne(o,r))return void De(e,t,n,o,r);var i=o,a=Pe(e,t,i);if(a)return console.debug("[JS Framework] compile composed component by",t),void Fe(e,a,t,n,i,r);console.debug("[JS Framework] compile native component by",t),Le(e,t,n,i)}}function je(e){return Array.isArray(e)}function Ae(e){return"content"===e.type||"slot"===e.type}fu
 nction Ie(e,t){return!t.hasOwnProperty("repeat")&&e.repeat}function Te(e,t){return!t.hasOwnProperty("shown")&&e.shown}function Ne(e,t){return"function"==typeof e&&!t.hasOwnProperty("type")}function Pe(e,t,n){var r;return e._app&&e._app.customComponentMap&&(r=e._app.customComponentMap[n]),e._options&&e._options.components&&(r=e._options.components[n]),t.component&&(r=r||{}),r}function Me(e,t,n,r){var o=ye(e,n);t.forEach(function(t){ke(e,t,o,r)})}function $e(e,t,n){var r=t.repeat,o="function"==typeof r,i=r.getter||r.expression||r;"function"!=typeof i&&(i=function(){return[]});var a=r.key||"$index",s=r.value||"$value",u=r.trackBy||t.trackBy||t.attr&&t.attr.trackBy,c=ye(e,n);c.children=[],c.data=[],c.vms=[],Ue(e,t,c,{getter:i,key:a,value:s,trackBy:u,oldStyle:o})}function Re(e,t,n,r){var o={shown:!0},i=ye(e,n);n.element&&n.children&&n.children.push(i),r.repeat&&(o.repeat=r.repeat),Ve(e,t,i,o)}function De(e,t,n,r,o){var i=r.call(e),a=_({type:i},o),s=ye(e,n);n.element&&n.children&&n.childr
 en.push(s),de(e,r,function(n){var r=_({type:n},o);Ee(e,s,!0),ke(e,t,s,r)}),ke(e,t,s,a)}function Fe(e,t,n,r,o,i){var a=e.constructor,s=new a(o,t,e,r,void 0,{"hook:init":function(){e._static&&(this._static=e._static),oe(e,null,n.id,this),this._externalBinding={parent:e,template:n}},"hook:created":function(){Y(e,this,n,i.repeat)},"hook:ready":function(){this._content&&We(e,n,this._content)}});ee(e,s,n,r)}function Le(e,t,n,r){Z(t);var o;if("_documentElement"===n.ref?(console.debug("[JS Framework] compile to create body for "+r),o=he(e,r)):(console.debug("[JS Framework] compile to create element for "+r),o=ve(e,r)),!e._rootEl){e._rootEl=o;var i=e._externalBinding||{},a=i.template,s=i.parent;if(a&&a.events&&s&&o)for(var u in a.events){var c=s[a.events[u]];c&&o.addEvent(u,x(c,s))}}Q(e,o,t),t.attr&&t.attr.append&&(t.append=t.attr.append),t.append&&(o.attr=o.attr||{},o.attr.append=t.append);var l="tree"===t.append,f=e._app||{};-1===f.lastSignal||l||(console.debug("[JS Framework] compile to a
 ppend single node for",o),f.lastSignal=ge(e,o,n)),-1!==f.lastSignal&&We(e,t,o),-1!==f.lastSignal&&l&&(console.debug("[JS Framework] compile to append whole tree for",o),f.lastSignal=ge(e,o,n))}function We(e,t,n){var r=e._app||{},o=t.children;o&&o.length&&o.every(function(t){return ke(e,t,n),-1!==r.lastSignal})}function Ue(e,t,n,r){function o(e,r,o){var a;c?(a=e,E(e)?(a[l]=r,a.hasOwnProperty("INDEX")||Object.defineProperty(a,"INDEX",{value:function(){console.warn('[JS Framework] "INDEX" in repeat is deprecated, please use "$index" instead')}})):(console.warn("[JS Framework] Each list item must be an object in old-style repeat, please use `repeat={{v in list}}` instead."),a={},a[l]=r,a[f]=e)):(a={},a[l]=r,a[f]=e);var s=qe(o,a);i.push(s),ke(s,t,n,{repeat:e})}var i=n.vms,a=n.children,s=r.getter,u=r.trackBy,c=r.oldStyle,l=r.key,f=r.value,p=Be(e,n,s,"repeat",function(t){if(console.debug('[JS Framework] the "repeat" item has changed',t),n&&t){var r=a.slice(),s=i.slice(),p=n.data.slice(),d=
 {},h={};t.forEach(function(e,t){var n=u?e[u]:c?e[l]:t;null!=n&&""!==n&&(d[n]=e)});var v=[];p.forEach(function(t,n){var o=u?t[u]:c?t[l]:n;d.hasOwnProperty(o)?(h[o]={item:t,index:n,key:o,target:r[n],vm:s[n]},v.push(t)):Ee(e,r[n])}),a.length=0,i.length=0,n.data=t.slice(),n.updateMark=n.start,t.forEach(function(t,r){var s=u?t[u]:c?t[l]:r,p=h[s];p?(p.item===v[0]?v.shift():(v.$remove(p.item),be(e,p.target,n.updateMark,!0)),a.push(p.target),i.push(p.vm),c?p.vm=t:p.vm[f]=t,p.vm[l]=r,n.updateMark=p.target):o(t,r,e)}),delete n.updateMark}});n.data=p.slice(0),p.forEach(function(t,n){o(t,n,e)})}function Ve(e,t,n,r){var o=Be(e,n,t.shown,"shown",function(o){console.debug('[JS Framework] the "if" item was changed',o),n&&!!n.display!=!!o&&(n.display=!!o,o?ke(e,t,n,r):Ee(e,n,!0))});n.display=!!o,o&&ke(e,t,n,r)}function Be(e,t,n,r,o){var i=e&&e._app&&e._app.differ,a={},s=(t.element.depth||0)+1;return de(e,n,function(e){a.latestValue=e,i&&!a.recorded&&i.append(r,s,t.blockId,function(){var e=a.latestVa
 lue;o(e),a.recorded=!1,a.latestValue=void 0}),a.recorded=!0})}function qe(e,t){var n=Object.create(e);return n._data=t,J(n),G(n),n._realParent=e,e._static&&(n._static=e._static),n}function ze(e,t){if(t instanceof ze)return t;this.timestamp=Date.now(),this.detail=t,this.type=e;var n=!1;this.stop=function(){n=!0},this.hasStopped=function(){return n}}function Je(e,t){var n=this,r=this._vmEvents,o=r[e];if(o){var i=new ze(e,t);o.forEach(function(e){e.call(n,i)})}}function He(e,t){var n=new ze(e,t);this.$emit(e,n),!n.hasStopped()&&this._parent&&this._parent.$dispatch&&this._parent.$dispatch(e,n)}function Ge(e,t){var n=new ze(e,t);this.$emit(e,n),!n.hasStopped()&&this._childrenVms&&this._childrenVms.forEach(function(t){t.$broadcast(e,n)})}function Xe(e,t){if(e&&"function"==typeof t){var n=this._vmEvents,r=n[e]||[];r.push(t),n[e]=r,"hook:ready"===e&&this._ready&&this.$emit("hook:ready")}}function Ke(e,t){if(e){var n=this._vmEvents;if(!t)return void delete n[e];var r=n[e];r&&r.$remove(t)}}fu
 nction Ze(e,t){var n=e._options||{},r=n.events||{};for(var o in r)e.$on(o,r[o]);for(var i in t)e.$on(i,t[i]);Fr.forEach(function(t){e.$on("hook:"+t,n[t])})}function Qe(e,t,n,r,o,i){n=n||{},this._parent=n._realParent?n._realParent:n,this._app=n._app||{},n._childrenVms&&n._childrenVms.push(this),!t&&this._app.customComponentMap&&(t=this._app.customComponentMap[e]),t=t||{};var a=t.data||{};this._options=t,this._methods=t.methods||{},this._computed=t.computed||{},this._css=t.style||{},this._ids={},this._vmEvents={},this._childrenVms=[],this._type=e,Ze(this,i),console.debug('[JS Framework] "init" lifecycle in Vm('+this._type+")"),this.$emit("hook:init"),this._inited=!0,this._data="function"==typeof a?a():a,o&&_(this._data,o),z(this),console.debug('[JS Framework] "created" lifecycle in Vm('+this._type+")"),this.$emit("hook:created"),this._created=!0,t.methods&&t.methods.ready&&(console.warn('"exports.methods.ready" is deprecated, please use "exports.created" instead'),t.methods.ready.call
 (this)),this._app.doc&&(this._parentEl=r||this._app.doc.documentElement,Ce(this))}function Ye(e,t){for(var n in e)!function(n){var r=Lr[n];r||(r={},Lr[n]=r),e[n].forEach(function(e){"string"==typeof e&&(e={name:e}),r[e.name]&&!t||(r[e.name]=e)})}(n)}function et(e,t){var n=e.prototype;for(var r in t)n.hasOwnProperty(r)||(n[r]=t[r])}function tt(e,t){var n=Lr[t],r={};for(var o in n)!function(n){Object.defineProperty(r,n,{configurable:!0,enumerable:!0,get:function(){return function(){for(var r=[],o=arguments.length;o--;)r[o]=arguments[o];return e.callTasks({module:t,method:n,args:r})}},set:function(r){if("function"==typeof r)return e.callTasks({module:t,method:n,args:[r]})}})}(o);return r}function nt(e,t){return e.customComponentMap[t]}function rt(e,t,n){var r=e.customComponentMap;if(r[t])return void console.error("[JS Framework] define a component("+t+") that already exists");r[t]=n}function ot(e){if(Wr.valid(e))return e;e="string"==typeof e?e:"";for(var t=e.split("."),n=0,r=[];n<3;){v
 ar o="string"==typeof t[n]&&t[n]?t[n]:"0";r.push(o),n++}return r.join(".")}function it(e,t,n){var r={isDowngrade:!0,errorType:1,code:1e3},o=e.toLowerCase();return r.errorMessage=function(e,t,n){return"Downgrade["+e+"] :: deviceInfo "+t+" matched criteria "+n}(e,t,n),o.indexOf("osversion")>=0?r.code=1001:o.indexOf("appversion")>=0?r.code=1002:o.indexOf("weexversion")>=0?r.code=1003:o.indexOf("devicemodel")>=0&&(r.code=1004),r}function at(e,t){t=t||global.WXEnvironment,t=O(t)?t:{};var n={isDowngrade:!1};if("function"===k(e)){var r=e.call(this,t,{semver:Wr,normalizeVersion:ot});r=!!r,n=r?it("custom","","custom params"):n}else{e=O(e)?e:{};var o=t.platform||"unknow",i=o.toLowerCase(),a=e[i]||{};for(var s in t){var u=s,c=u.toLowerCase(),l=t[s],f=c.indexOf("version")>=0,p=c.indexOf("devicemodel")>=0,d=a[s];if(d&&f){var h=ot(d),v=ot(t[s]);if(Wr.satisfies(v,h)){n=it(u,l,d);break}}else if(p){var y="array"===k(d)?d:[d];if(y.indexOf(l)>=0){n=it(u,l,d);break}}}}return n}function st(e,t){if(void 
 0===t&&(t={}),e&&e.callTasks)return e.callTasks([{module:"meta",method:"setViewport",args:[t]}])}function ut(e,t,n,r){console.debug("[JS Framework] bootstrap for "+t);var o;if(xr(t))o=j(t);else{if(!Sr(t))return new Error("Wrong component name: "+t);if(o=A(t),!nt(e,o))return new Error("It's not a component: "+t)}if(n=O(n)?n:{},"string"==typeof n.transformerVersion&&"string"==typeof global.transformerVersion&&!Wr.satisfies(n.transformerVersion,global.transformerVersion))return new Error("JS Bundle version: "+n.transformerVersion+" not compatible with "+global.transformerVersion);var i=at(n.downgrade);if(i.isDowngrade)return e.callTasks([{module:"instanceWrap",method:"error",args:[i.errorType,i.code,i.errorMessage]}]),new Error("Downgrade["+i.code+"]: "+i.errorMessage);n.viewport&&st(e,n.viewport),e.vm=new Qe(o,null,{_app:e},null,r)}function ct(e,t,n){console.warn("[JS Framework] Register is deprecated, please install lastest transformer."),rt(e,t,n)}function lt(e,t){console.debug("[JS
  Framework] Refresh with",t,"in instance["+e.id+"]");var n=e.vm;return n&&t?("function"==typeof n.refreshData?n.refreshData(t):_(n,t),e.differ.flush(),void e.doc.taskCenter.send("dom",{action:"refreshFinish"},[])):new Error('invalid data "'+t+'"')}function ft(e){console.debug("[JS Framework] Destory an instance("+e.id+")"),e.vm&&pt(e.vm),e.id="",e.options=null,e.blocks=null,e.vm=null,e.doc.taskCenter.destroyCallback(),e.doc.destroy(),e.doc=null,e.customComponentMap=null,e.commonModules=null}function pt(e){if(delete e._app,delete e._computed,delete e._css,delete e._data,delete e._ids,delete e._methods,delete e._options,delete e._parent,delete e._parentEl,delete e._rootEl,e._watchers){for(var t=e._watchers.length;t--;)e._watchers[t].teardown();delete e._watchers}if(e._childrenVms){for(var n=e._childrenVms.length;n--;)pt(e._childrenVms[n]);delete e._childrenVms}console.debug('[JS Framework] "destroyed" lifecycle in Vm('+e._type+")"),e.$emit("hook:destroyed"),delete e._type,delete e._vm
 Events}function dt(e){var t=e.doc||{},n=t.body||{};return n.toJSON?n.toJSON():{}}function ht(e,t,n,r,o){if(console.debug('[JS Framework] Fire a "'+n+'" event on an element('+t+") in instance("+e.id+")"),Array.isArray(t))return void t.some(function(t){return!1!==ht(e,t,n,r)});var i=e.doc.getRef(t);if(i){var a=e.doc.fireEvent(i,n,r,o);return e.differ.flush(),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),a}return new Error('invalid element reference "'+t+'"')}function vt(e,t,n,r){console.debug("[JS Framework] Invoke a callback("+t+") with",n,"in instance("+e.id+")");var o=e.doc.taskCenter.callback(t,n,r);return yt(e),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),o}function yt(e){e.differ.flush()}function mt(e,t){var n;return"array"!==k(t)&&(t=[t]),t.forEach(function(t){n=e.doc.taskCenter.send("module",{module:t.module,method:t.method},t.args)}),n}function _t(e,t,n,r){console.debug("[JS Framework] Intialize an instance with:\n",n);var o,i=function(){for(var t=[],n=ar
 guments.length;n--;)t[n]=arguments[n];return Ur.apply(void 0,[e].concat(t))},a=function(t,r,i){o=ut(e,t,r,i||n),yt(e),e.doc.listener.createFinish(),console.debug("[JS Framework] After intialized an instance("+e.id+")")},s=Qe,u=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return ct.apply(void 0,[e].concat(t))},c=function(t,n){o=ut(e,t,{},n)},l=function(t){return function(n){o=ut(e,t,{},n)}},f=e.doc,p=function(t){return e.requireModule(j(t))},d={config:e.options,define:i,bootstrap:a,requireModule:p,document:f,Vm:s};Object.freeze(d);var h;"function"==typeof t?h=t.toString().substr(12):t&&(h=t.toString()),h='(function(global){\n\n"use strict";\n\n '+h+" \n\n})(Object.create(this))";var v=global.WXEnvironment,y={};if(v&&"Web"!==v.platform){var m=e.requireModule("timer");Object.assign(y,{setTimeout:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setTimeout(r,t[1]),e.doc.taskCenter.callbackManager.la
 stCallbackId.toString()},setInterval:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setInterval(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},clearTimeout:function(e){m.clearTimeout(e)},clearInterval:function(e){m.clearInterval(e)}})}var _=Object.assign({define:i,require:l,bootstrap:a,register:u,render:c,__weex_define__:i,__weex_bootstrap__:a,__weex_document__:f,__weex_require__:p,__weex_viewmodel__:s,weex:d},y,r);return bt(_,h)||gt(_,h),o}function gt(e,t){var n=[],r=[];for(var o in e)n.push(o),r.push(e[o]);return n.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(n)))).apply(void 0,r)}function bt(e,t){if("function"!=typeof compileAndRunBundle)return!1;var n=void 0,r=!1,o="(function (",i=[],a=[];for(var s in e)i.push(s),a.push(e[s]);for(var u=0;u<i.length-1;++u)o+=i[u],o+=",";o+=i[i.length-1],o+=") {",o+=t,o+="} )";try{var c=e.weex||{},l=c.config||{};n=compileAndRunBundle(o,
 l.bundleUrl,l.bundleDigest,l.codeCachePath),n&&"function"==typeof n&&(n.apply(void 0,a),r=!0)}catch(e){console.error(e)}return r}function wt(e,t){var n=e[t];for(var r in n)n[r]()}function xt(e,t){var n=e[t];for(var r in n){n[r].forEach(function(e){e()})}}function Et(e,t){this.id=e,this.options=t||{},this.vm=null,this.customComponentMap={},this.commonModules={},this.doc=new Mr.Document(e,this.options.bundleUrl,null,Mr.Listener),this.differ=new Vr(e)}function Ot(e,t,n,r,o){var i=o||{},a=i.services;P();var s=Br[e];n=n||{};var u;return s?u=new Error('invalid instance id "'+e+'"'):(s=new Et(e,n),Br[e]=s,u=_t(s,t,r,a)),u instanceof Error?u:s}function St(e){Mr.Document=e.Document,Mr.Element=e.Element,Mr.Comment=e.Comment,Mr.sendTasks=e.sendTasks,Mr.Listener=e.Listener}function Ct(e,t){var n=Br[e];return n?lt(n,t):new Error('invalid instance id "'+e+'"')}function kt(e){"function"==typeof markupState&&markupState(),P();var t=Br[e];if(!t)return new Error('invalid instance id "'+e+'"');ft(t),d
 elete Br[e];var n=Math.round(e);if(n>0){n%18||"function"!=typeof notifyTrimMemory||notifyTrimMemory()}return Br}function jt(e){Array.isArray(e)&&e.forEach(function(e){e&&("string"==typeof e?qr[e]=!0:"object"==typeof e&&"string"==typeof e.type&&(qr[e.type]=e))})}function At(e){"object"==typeof e&&Ye(e)}function It(e){"object"==typeof e&&et(Qe,e)}function Tt(e,t){if(Br[e]&&Array.isArray(t)){var n=[];return t.forEach(function(t){var r=zr[t.method],o=[].concat(t.args);"function"==typeof r&&(o.unshift(e),n.push(r.apply(void 0,o)))}),n}return new Error('invalid instance id "'+e+'" or tasks')}function Nt(e){var t=Br[e];return t?dt(t):new Error('invalid instance id "'+e+'"')}function Pt(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=Hs(t),this.reject=Hs(n)}function Mt(){if(Rt(),global.WXEnvironment&&"Web"!==global.WXEnvironment.platform)global.console={debug:function(){for(var e=[],t=arguments.length;t-
 -;)e[t]=arguments[t];Dt("debug")&&global.nativeLog.apply(global,Ft(e).concat(["__DEBUG"]))},log:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("log")&&global.nativeLog.apply(global,Ft(e).concat(["__LOG"]))},info:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("info")&&global.nativeLog.apply(global,Ft(e).concat(["__INFO"]))},warn:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("warn")&&global.nativeLog.apply(global,Ft(e).concat(["__WARN"]))},error:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("error")&&global.nativeLog.apply(global,Ft(e).concat(["__ERROR"]))}};else{var e=console.debug,t=console.log,n=console.info,r=console.warn,o=console.error;console.__ori__={debug:e,log:t,info:n,warn:r,error:o},console.debug=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("debug")&&console.__ori__.debug.apply(console,e)},console.log=function(){for(var e=[],t=arguments.length;t--;)e[t]=argumen
 ts[t];Dt("log")&&console.__ori__.log.apply(console,e)},console.info=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("info")&&console.__ori__.info.apply(console,e)},console.warn=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("warn")&&console.__ori__.warn.apply(console,e)},console.error=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("error")&&console.__ori__.error.apply(console,e)}}}function $t(){Vu={},global.console=Bu}function Rt(){Uu.forEach(function(e){var t=Uu.indexOf(e);Vu[e]={},Uu.forEach(function(n){Uu.indexOf(n)<=t&&(Vu[e][n]=!0)})})}function Dt(e){var t=global.WXEnvironment&&global.WXEnvironment.logLevel||"log";return Vu[t]&&Vu[t][e]}function Ft(e){return e.map(function(e){return e="[object object]"===Object.prototype.toString.call(e).toLowerCase()?JSON.stringify(e):String(e)})}function Lt(){if(void 0===setTimeout&&"function"==typeof zu){var e={},t=0;global.setTimeout=function(n,r){e[++t]=n,zu(t.toString(),r)},
 global.setTimeoutCallback=function(t){"function"==typeof e[t]&&(e[t](),delete e[t])}}}function Wt(){global.setTimeout=qu,global.setTimeoutCallback=null}function Ut(){Object.freeze(Object),Object.freeze(Array),Vt(),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Bt(),Object.freeze(Date.prototype),Object.freeze(RegExp.prototype)}function Vt(){var e=Object.prototype,t="Object.prototype";qt(e,"__defineGetter__",t),qt(e,"__defineSetter__",t),qt(e,"__lookupGetter__",t),qt(e,"__lookupSetter__",t),qt(e,"constructor",t),qt(e,"hasOwnProperty",t),qt(e,"isPrototypeOf",t),qt(e,"propertyIsEnumerable",t),qt(e,"toLocaleString",t),qt(e,"toString",t),qt(e,"valueOf",t),Object.seal(e)}function Bt(){var e=Error.prototype,t="Error.prototype";qt(e,"name",t),qt(e,"message",t),qt(e,"toString",t),qt(e,"constructor",t),Object.seal(e)}function qt(e,t,n){if(e.hasOwnProperty(t)){var r=e[t];Object.defineProperty(e,t,{get:function(){re
 turn r},set:function(r){if(this===e)throw Error("Cannot assign to read only property "+t+" of "+n);return Object.defineProperty(this,t,{value:r,writable:!0}),r}})}}function zt(){return(Ju++).toString()}function Jt(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1)}function Ht(e){if("function"!=typeof btoa)return"";var t=Array.prototype.map.call(new Uint8Array(e),function(e){return String.fromCharCode(e)}).join("");return btoa(t)}function Gt(e){if("function"!=typeof atob)return new ArrayBuffer(0);var t=atob(e),n=new Uint8Array(t.length);return Array.prototype.forEach.call(t,function(e,t){n[t]=e.charCodeAt(0)}),n.buffer}function Xt(e){var t=Jt(e);switch(t){case"Undefined":case"Null":return"";case"RegExp":return e.toString();case"Date":return e.toISOString();case"Number":case"String":case"Boolean":case"Array":case"Object":return e;case"ArrayBuffer":return{"@type":"binary",dataType:t,base64:Ht(e)};case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int
 16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":
+(this.nativeLog||function(e){console.log(e)})("START JS FRAMEWORK 0.22.2, Build 2017-09-21 15:46."),this.getJSFMVersion=function(){return"0.22.2"};var global=this,process={env:{}},setTimeout=global.setTimeout;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(0,function(){"use strict";function e(e){Hn.Document=e.Document,Hn.Element=e.Element,Hn.Comment=e.Comment,Hn.sendTasks=e.sendTasks}function t(e,t,n,r,o){void 0===n&&(n={}),void 0===r&&(r={}),void 0===o&&(o={});var i=new Hn.Document(e,n.bundleUrl),a={},s={id:e,data:r,document:i,callbacks:a},u=0;i.addCallback=function(e){return u++,a[u]=e,u},i.handleCallback=function(e,t,n){var r=a[e];return n&&delete a[e],r(t)},Gn[e]=s;var c=Object.assign({Document:Hn.Document,Element:Hn.Element,Comment:Hn.Comment,sendTasks:function(t){return Hn.sendTasks(e,t,-1)},options:n,document:i},o),l=[],f=[];for(var p in c)l.push(p),f.push(c[p]);return l.push(t),(new(Function.prototy
 pe.bind.apply(Function,[null].concat(l)))).apply(void 0,f),Hn.sendTasks(e,[{module:"dom",method:"createFinish",args:[]}],-1),s}function n(e){delete Gn[e]}function r(e){return Gn[e].document.body.toJSON()}function o(e,t){var n={fireEvent:function(e,t,n,r,o){var i=Gn[e],a=i.document,s=a.getRef(t);return a.fireEvent(s,n,r,o)},callback:function(e,t,n,r){return Gn[e].document.handleCallback(t,n,r)}};if((Gn[e]||{}).document&&Array.isArray(t)){var r=[];return t.forEach(function(t){var o=n[t.method],i=[].concat(t.args);"function"==typeof o&&(i.unshift(e),r.push(o.apply(void 0,i)))}),r}}function i(e){return e&&e.__esModule?e.default:e}function a(e,t){return t={exports:{}},e(t,t.exports),t.exports}function s(e){console.warn("[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead");var t=this._ids[e];if(t)return t.vm}function u(e){var t=this._ids[e];if(t)return t.el}function c(e){var t=this._ids[e];if(t)return t.vm}function l(e){return this._app.differ.then(function(){e()})}function f(e,
 t){console.warn("[JS Framework] Vm#$scrollTo is deprecated, please use \"require('@weex-module/dom').scrollTo(el, options)\" instead");var n=this.$el(e);if(n){this._app.requireModule("dom").scrollToElement(n.ref,{offset:t})}}function p(e,t,n){var r=this,o=this.$el(e);if(o&&t&&t.styles){this._app.requireModule("animation").transition(o.ref,t,function(){for(var e=[],i=arguments.length;i--;)e[i]=arguments[i];r._setStyle(o,t.styles),n&&n.apply(void 0,e)})}}function d(e){var t=this._app.options;return"function"==typeof e&&(console.warn("[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, this api now can directly RETURN config info."),e(t)),t}function h(e,t){console.warn("[JS Framework] Vm#$sendHttp is deprecated, please use \"require('@weex-module/stream').sendHttp(params, callback)\" instead"),this._app.requireModule("stream").sendHttp(e,t)}function v(e){console.warn("[JS Framework] Vm#$openURL is deprecated, please use \"require('@weex-module/event').openURL(url)\" i
 nstead"),this._app.requireModule("event").openURL(e)}function y(e){console.warn("[JS Framework] Vm#$setTitle is deprecated, please use \"require('@weex-module/pageInfo').setTitle(title)\" instead"),this._app.requireModule("pageInfo").setTitle(e)}function m(e,t){for(var n=[],r=arguments.length-2;r-- >0;)n[r]=arguments[r+2];console.warn("[JS Framework] Vm#$call is deprecated, please use \"require('@weex-module/moduleName')\" instead");var o=this._app.requireModule(e);o&&o[t]&&o[t].apply(o,n)}function _(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];if("function"==typeof Object.assign)Object.assign.apply(Object,[e].concat(t));else{var r=t.shift();for(var o in r)e[o]=r[o];t.length&&_.apply(void 0,[e].concat(t))}return e}function g(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function b(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function w(e,t){return hr.call(e,t)}function x(e,t){return function(n){var 
 r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}}function E(e){return null!==e&&"object"==typeof e}function O(e){return vr.call(e)===yr}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function C(){return"object"==typeof nativeSet?nativeSet.create():new Jn}function k(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1).toLowerCase()}function j(e){return e.replace(_r,"").replace(gr,"")}function A(e){return e.replace(wr,"")}function I(){this.id=Cr++,this.subs=[]}function T(e){I.target&&kr.push(I.target),I.target=e}function N(){I.target=kr.pop()}function P(){I.target=null,kr=[]}function M(e,t,n,r){r&&_(this,r);var o="function"==typeof t;this.vm=e,e._watchers.push(this),this.expression=t,this.cb=n,this.id=++jr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=C(),this.newDepIds=C(),o&&(this.getter=t),this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function $(e,t){var n,r,o,i;if(
 t||(t=Ar,t.clear()),o=Array.isArray(e),i=E(e),o||i){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.length;n--;)$(e[n],t);else if(i)for(r=Object.keys(e),n=r.length;n--;)$(e[r[n]],t)}}function R(e){if(this.value=e,this.dep=new I,g(e,"__ob__",this),Array.isArray(e)){(mr?D:F)(e,Tr,Nr),this.observeArray(e)}else this.walk(e)}function D(e,t){e.__proto__=t}function F(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];g(e,i,t[i])}}function L(e,t){if(E(e)){var n;return w(e,"__ob__")&&e.__ob__ instanceof R?n=e.__ob__:(Array.isArray(e)||O(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new R(e)),n&&t&&n.addVm(t),n}}function W(e,t,n){var r=new I,o=Object.getOwnPropertyDescriptor(e,t);if(!o||!1!==o.configurable){var i=o&&o.get,a=o&&o.set,s=L(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=i?i.call(e):n;if(I.target&&(r.depend(),s&&s.dep.depend(),Array.isArray(t)))for(var o=void 0,a=0,u=t.length;a<u;a++)(o=t[a])&&o.__ob__&&o.__ob__.dep.depend(
 );return t},set:function(t){t!==(i?i.call(e):n)&&(a?a.call(e,t):n=t,s=L(t),r.notify())}})}}function U(e,t,n){if(Array.isArray(e))return e.splice(t,1,n);if(w(e,t))return void(e[t]=n);if(e._isVue)return void U(e._data,t,n);var r=e.__ob__;if(!r)return void(e[t]=n);if(r.convert(t,n),r.dep.notify(),r.vms)for(var o=r.vms.length;o--;){var i=r.vms[o];B(i,t)}return n}function V(e,t){if(w(e,t)){delete e[t];var n=e.__ob__;if(!n)return void(e._isVue&&delete e._data[t]);if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var o=n.vms[r];q(o,t)}}}function B(e,t){(Pr.indexOf(t)>-1||!S(t))&&Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return e._data[t]},set:function(n){e._data[t]=n}})}function q(e,t){S(t)||delete e[t]}function z(e){e._watchers=[],J(e),G(e),K(e)}function J(e){var t=e._data;O(t)||(t={});for(var n=Object.keys(t),r=n.length;r--;)B(e,n[r]);L(t,e)}function H(){}function G(e){var t=e._computed;if(t)for(var n in t){var r=t[n],o={enumerable:!0,configurable:!0};"fu
 nction"==typeof r?(o.get=X(r,e),o.set=H):(o.get=r.get?!1!==r.cache?X(r.get,e):x(r.get,e):H,o.set=r.set?x(r.set,e):H),Object.defineProperty(e,n,o)}}function X(e,t){var n=new M(t,e,null,{lazy:!0});return function(){return n.dirty&&n.evaluate(),I.target&&n.depend(),n.value}}function K(e){var t=e._methods;if(t)for(var n in t)e[n]=t[n]}function Z(e){var t=e.type,n=$r[t];if("object"==typeof n)for(var r in n)if(null==e[r])e[r]=n[r];else if("object"===k(e[r])&&"object"===k(n[r]))for(var o in n[r])null==e[r][o]&&(e[r][o]=n[r][o])}function Q(e,t,n){oe(e,t,n.id,e),ie(e,t,n.attr),se(e,t,n.classList),ue(e,t,n.style),le(e,t,n.events)}function Y(e,t,n,r){t=t||{},n=n||{};var o=t._options||{},i=o.props;Array.isArray(i)&&(i=i.reduce(function(e,t){return e[t]=!0,e},{})),te(r,i,e,t),te(n.attr,i,e,t)}function ee(e,t,n,r){void 0===r&&(r={}),re(n.classList,e,t),ne(n.style,e,t),r.children?r.children[r.children.length-1]._vm=t:r._vm=t}function te(e,t,n,r){if(e){for(var o in e)!function(o){if(!t||t[o]){var i
 =e[o];if("function"==typeof i){var a=de(n,i,function(e){r[o]=e});r[o]=a}else r[o]=i}}(o)}}function ne(e,t,n){for(var r in e)!function(r){var o=e[r];if("function"==typeof o){var i=de(t,o,function(e){n._rootEl&&n._rootEl.setStyle(r,e)});n._rootEl.setStyle(r,i)}else n._rootEl&&n._rootEl.setStyle(r,o)}(r)}function re(e,t,n){function r(e,t){"array"===k(e)&&e.unshift(t)}var o=t._options&&t._options.style||{};if(n._rootEl){var i="@originalRootEl";if(o[i]=n._rootEl.classStyle,"function"==typeof e){var a=de(t,e,function(e){r(e,i),ae(n._rootEl,o,e)});r(a,i),ae(n._rootEl,o,a)}else null!=e&&(r(e,i),ae(n._rootEl,o,e))}}function oe(e,t,n,r){var o=Object.create(null);if(Object.defineProperties(o,{vm:{value:r,writable:!1,configurable:!1},el:{get:function(){return t||r._rootEl},configurable:!1}}),"function"==typeof n){var i=n;n=i.call(e),(n||0===n)&&(e._ids[n]=o),de(e,i,function(t){t&&(e._ids[t]=o)})}else n&&"string"==typeof n&&(e._ids[n]=o)}function ie(e,t,n){fe(e,t,"attr",n)}function ae(e,t,n){"st
 ring"==typeof n&&(n=n.split(/\s+/)),n.forEach(function(e,t){n.splice.apply(n,[t,1].concat(e.split(/\s+/)))});for(var r={},o=n.length,i=0;i<o;i++)!function(e){var o=t[n[e]];o&&Object.keys(o).forEach(function(e){r[e]=o[e]})}(i);e.setClassStyle(r)}function se(e,t,n){if("function"==typeof n||Array.isArray(n)){if(Array.isArray(n)&&!n.length)return void t.setClassStyle({});var r=e._options&&e._options.style||{};if("function"==typeof n){var o=de(e,n,function(e){ae(t,r,e)});ae(t,r,o)}else ae(t,r,n)}}function ue(e,t,n){fe(e,t,"style",n)}function ce(e,t,n,r){t.addEvent(n,x(r,e))}function le(e,t,n){if(n)for(var r=Object.keys(n),o=r.length;o--;){var i=r[o],a=n[i];"string"==typeof a&&((a=e[a])||console.warn('[JS Framework] The event handler "'+a+'" is not defined.')),ce(e,t,i,a)}}function fe(e,t,n,r){if(r)for(var o=Object.keys(r),i=o.length;i--;){var a=o[i],s=r[a];"function"==typeof s?pe(e,t,n,a,s):t[Rr[n]](a,s)}}function pe(e,t,n,r,o){var i=Rr[n],a=de(e,o,function(n){function o(){t[i](r,n)}var 
 a=e&&e._app&&e._app.differ;a?a.append("element",t.depth||0,t.ref,o):o()});t[i](r,a)}function de(e,t,n){return e._static?t.call(e,e):new M(e,t,function(e,t){"object"!=typeof e&&e===t||n(e)}).value}function he(e,t){return e._app.doc.createBody(t)}function ve(e,t){return e._app.doc.createElement(t)}function ye(e,t){var n=me(e),r=_e(e),o=Dr++;if(t.element){var i=t.updateMark;i?(i.element&&(i=i.end),t.element.insertAfter(r,i),t.element.insertAfter(n,i),t.updateMark=r):(t.element.insertBefore(n,t.end),t.element.insertBefore(r,t.end)),t=t.element}else t.appendChild(n),t.appendChild(r);return{start:n,end:r,element:t,blockId:o}}function me(e){return e._app.doc.createComment("start")}function _e(e){return e._app.doc.createComment("end")}function ge(e,t,n){if(n.element){var r=n.end,o=n.updateMark;if(n.children&&n.children.push(t),o){var i=be(e,t,o);return n.updateMark=t.element?t.end:t,i}if(!t.element)return n.element.insertBefore(t,r);n.element.insertBefore(t.start,r),n.element.insertBefore(t
 .end,r)}else{if(!t.element)return n.appendChild(t);n.appendChild(t.start),n.appendChild(t.end)}}function be(e,t,n){return t.element?xe(t,n):we(t,n)}function we(e,t){var n=t.parentNode;if(n)return n.insertAfter(e,t)}function xe(e,t){var n=t.parentNode;if(n){for(var r,o=e.start,i=[o];o&&o!==e.end;)o=o.nextSibling,i.push(o);var a=t;return i.every(function(e){return r=n.insertAfter(e,a),a=e,-1!==r}),r}}function Ee(e,t,n){void 0===n&&(n=!1),t.element?Se(t,n):Oe(t),t._vm&&t._vm.$emit("hook:destroyed")}function Oe(e){var t=e.parentNode;t&&t.removeChild(e)}function Se(e,t){void 0===t&&(t=!1);for(var n=[],r=e.start.nextSibling;r&&r!==e.end;)n.push(r),r=r.nextSibling;t||Oe(e.start),n.forEach(function(e){Oe(e)}),t||Oe(e.end)}function Ce(e){var t=e._options||{},n=t.template||{};t.replace?n.children&&1===n.children.length?ke(e,n.children[0],e._parentEl):ke(e,n.children,e._parentEl):ke(e,n,e._parentEl),console.debug('[JS Framework] "ready" lifecycle in Vm('+e._type+")"),e.$emit("hook:ready"),e._r
 eady=!0}function ke(e,t,n,r){if(-1!==(e._app||{}).lastSignal){if(t.attr&&t.attr.hasOwnProperty("static")&&(e._static=!0),je(t))return void Me(e,t,n,r);if(r=r||{},Ae(t))return console.debug('[JS Framework] compile "content" block by',t),void(e._content=ye(e,n));if(Ie(t,r))return console.debug('[JS Framework] compile "repeat" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `repeat` directive!"):$e(e,t,n));if(Te(t,r))return console.debug('[JS Framework] compile "if" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `if` directive!"):Re(e,t,n,r));var o=r.type||t.type;if(Ne(o,r))return void De(e,t,n,o,r);var i=o,a=Pe(e,t,i);if(a)return console.debug("[JS Framework] compile composed component by",t),void Fe(e,a,t,n,i,r);console.debug("[JS Framework] compile native component by",t),Le(e,t,n,i)}}function je(e){return Array.isArray(e)}function Ae(e){return"content"===e.type||"slot"===e.type}fu
 nction Ie(e,t){return!t.hasOwnProperty("repeat")&&e.repeat}function Te(e,t){return!t.hasOwnProperty("shown")&&e.shown}function Ne(e,t){return"function"==typeof e&&!t.hasOwnProperty("type")}function Pe(e,t,n){var r;return e._app&&e._app.customComponentMap&&(r=e._app.customComponentMap[n]),e._options&&e._options.components&&(r=e._options.components[n]),t.component&&(r=r||{}),r}function Me(e,t,n,r){var o=ye(e,n);t.forEach(function(t){ke(e,t,o,r)})}function $e(e,t,n){var r=t.repeat,o="function"==typeof r,i=r.getter||r.expression||r;"function"!=typeof i&&(i=function(){return[]});var a=r.key||"$index",s=r.value||"$value",u=r.trackBy||t.trackBy||t.attr&&t.attr.trackBy,c=ye(e,n);c.children=[],c.data=[],c.vms=[],Ue(e,t,c,{getter:i,key:a,value:s,trackBy:u,oldStyle:o})}function Re(e,t,n,r){var o={shown:!0},i=ye(e,n);n.element&&n.children&&n.children.push(i),r.repeat&&(o.repeat=r.repeat),Ve(e,t,i,o)}function De(e,t,n,r,o){var i=r.call(e),a=_({type:i},o),s=ye(e,n);n.element&&n.children&&n.childr
 en.push(s),de(e,r,function(n){var r=_({type:n},o);Ee(e,s,!0),ke(e,t,s,r)}),ke(e,t,s,a)}function Fe(e,t,n,r,o,i){var a=e.constructor,s=new a(o,t,e,r,void 0,{"hook:init":function(){e._static&&(this._static=e._static),oe(e,null,n.id,this),this._externalBinding={parent:e,template:n}},"hook:created":function(){Y(e,this,n,i.repeat)},"hook:ready":function(){this._content&&We(e,n,this._content)}});ee(e,s,n,r)}function Le(e,t,n,r){Z(t);var o;if("_documentElement"===n.ref?(console.debug("[JS Framework] compile to create body for "+r),o=he(e,r)):(console.debug("[JS Framework] compile to create element for "+r),o=ve(e,r)),!e._rootEl){e._rootEl=o;var i=e._externalBinding||{},a=i.template,s=i.parent;if(a&&a.events&&s&&o)for(var u in a.events){var c=s[a.events[u]];c&&o.addEvent(u,x(c,s))}}Q(e,o,t),t.attr&&t.attr.append&&(t.append=t.attr.append),t.append&&(o.attr=o.attr||{},o.attr.append=t.append);var l="tree"===t.append,f=e._app||{};-1===f.lastSignal||l||(console.debug("[JS Framework] compile to a
 ppend single node for",o),f.lastSignal=ge(e,o,n)),-1!==f.lastSignal&&We(e,t,o),-1!==f.lastSignal&&l&&(console.debug("[JS Framework] compile to append whole tree for",o),f.lastSignal=ge(e,o,n))}function We(e,t,n){var r=e._app||{},o=t.children;o&&o.length&&o.every(function(t){return ke(e,t,n),-1!==r.lastSignal})}function Ue(e,t,n,r){function o(e,r,o){var a;c?(a=e,E(e)?(a[l]=r,a.hasOwnProperty("INDEX")||Object.defineProperty(a,"INDEX",{value:function(){console.warn('[JS Framework] "INDEX" in repeat is deprecated, please use "$index" instead')}})):(console.warn("[JS Framework] Each list item must be an object in old-style repeat, please use `repeat={{v in list}}` instead."),a={},a[l]=r,a[f]=e)):(a={},a[l]=r,a[f]=e);var s=qe(o,a);i.push(s),ke(s,t,n,{repeat:e})}var i=n.vms,a=n.children,s=r.getter,u=r.trackBy,c=r.oldStyle,l=r.key,f=r.value,p=Be(e,n,s,"repeat",function(t){if(console.debug('[JS Framework] the "repeat" item has changed',t),n&&t){var r=a.slice(),s=i.slice(),p=n.data.slice(),d=
 {},h={};t.forEach(function(e,t){var n=u?e[u]:c?e[l]:t;null!=n&&""!==n&&(d[n]=e)});var v=[];p.forEach(function(t,n){var o=u?t[u]:c?t[l]:n;d.hasOwnProperty(o)?(h[o]={item:t,index:n,key:o,target:r[n],vm:s[n]},v.push(t)):Ee(e,r[n])}),a.length=0,i.length=0,n.data=t.slice(),n.updateMark=n.start,t.forEach(function(t,r){var s=u?t[u]:c?t[l]:r,p=h[s];p?(p.item===v[0]?v.shift():(v.$remove(p.item),be(e,p.target,n.updateMark,!0)),a.push(p.target),i.push(p.vm),c?p.vm=t:p.vm[f]=t,p.vm[l]=r,n.updateMark=p.target):o(t,r,e)}),delete n.updateMark}});n.data=p.slice(0),p.forEach(function(t,n){o(t,n,e)})}function Ve(e,t,n,r){var o=Be(e,n,t.shown,"shown",function(o){console.debug('[JS Framework] the "if" item was changed',o),n&&!!n.display!=!!o&&(n.display=!!o,o?ke(e,t,n,r):Ee(e,n,!0))});n.display=!!o,o&&ke(e,t,n,r)}function Be(e,t,n,r,o){var i=e&&e._app&&e._app.differ,a={},s=(t.element.depth||0)+1;return de(e,n,function(e){a.latestValue=e,i&&!a.recorded&&i.append(r,s,t.blockId,function(){var e=a.latestVa
 lue;o(e),a.recorded=!1,a.latestValue=void 0}),a.recorded=!0})}function qe(e,t){var n=Object.create(e);return n._data=t,J(n),G(n),n._realParent=e,e._static&&(n._static=e._static),n}function ze(e,t){if(t instanceof ze)return t;this.timestamp=Date.now(),this.detail=t,this.type=e;var n=!1;this.stop=function(){n=!0},this.hasStopped=function(){return n}}function Je(e,t){var n=this,r=this._vmEvents,o=r[e];if(o){var i=new ze(e,t);o.forEach(function(e){e.call(n,i)})}}function He(e,t){var n=new ze(e,t);this.$emit(e,n),!n.hasStopped()&&this._parent&&this._parent.$dispatch&&this._parent.$dispatch(e,n)}function Ge(e,t){var n=new ze(e,t);this.$emit(e,n),!n.hasStopped()&&this._childrenVms&&this._childrenVms.forEach(function(t){t.$broadcast(e,n)})}function Xe(e,t){if(e&&"function"==typeof t){var n=this._vmEvents,r=n[e]||[];r.push(t),n[e]=r,"hook:ready"===e&&this._ready&&this.$emit("hook:ready")}}function Ke(e,t){if(e){var n=this._vmEvents;if(!t)return void delete n[e];var r=n[e];r&&r.$remove(t)}}fu
 nction Ze(e,t){var n=e._options||{},r=n.events||{};for(var o in r)e.$on(o,r[o]);for(var i in t)e.$on(i,t[i]);Fr.forEach(function(t){e.$on("hook:"+t,n[t])})}function Qe(e,t,n,r,o,i){n=n||{},this._parent=n._realParent?n._realParent:n,this._app=n._app||{},n._childrenVms&&n._childrenVms.push(this),!t&&this._app.customComponentMap&&(t=this._app.customComponentMap[e]),t=t||{};var a=t.data||{};this._options=t,this._methods=t.methods||{},this._computed=t.computed||{},this._css=t.style||{},this._ids={},this._vmEvents={},this._childrenVms=[],this._type=e,Ze(this,i),console.debug('[JS Framework] "init" lifecycle in Vm('+this._type+")"),this.$emit("hook:init"),this._inited=!0,this._data="function"==typeof a?a():a,o&&_(this._data,o),z(this),console.debug('[JS Framework] "created" lifecycle in Vm('+this._type+")"),this.$emit("hook:created"),this._created=!0,t.methods&&t.methods.ready&&(console.warn('"exports.methods.ready" is deprecated, please use "exports.created" instead'),t.methods.ready.call
 (this)),this._app.doc&&(this._parentEl=r||this._app.doc.documentElement,Ce(this))}function Ye(e,t){for(var n in e)!function(n){var r=Lr[n];r||(r={},Lr[n]=r),e[n].forEach(function(e){"string"==typeof e&&(e={name:e}),r[e.name]&&!t||(r[e.name]=e)})}(n)}function et(e,t){var n=e.prototype;for(var r in t)n.hasOwnProperty(r)||(n[r]=t[r])}function tt(e,t){var n=Lr[t],r={};for(var o in n)!function(n){Object.defineProperty(r,n,{configurable:!0,enumerable:!0,get:function(){return function(){for(var r=[],o=arguments.length;o--;)r[o]=arguments[o];return e.callTasks({module:t,method:n,args:r})}},set:function(r){if("function"==typeof r)return e.callTasks({module:t,method:n,args:[r]})}})}(o);return r}function nt(e,t){return e.customComponentMap[t]}function rt(e,t,n){var r=e.customComponentMap;if(r[t])return void console.error("[JS Framework] define a component("+t+") that already exists");r[t]=n}function ot(e){if(Wr.valid(e))return e;e="string"==typeof e?e:"";for(var t=e.split("."),n=0,r=[];n<3;){v
 ar o="string"==typeof t[n]&&t[n]?t[n]:"0";r.push(o),n++}return r.join(".")}function it(e,t,n){var r={isDowngrade:!0,errorType:1,code:1e3},o=e.toLowerCase();return r.errorMessage=function(e,t,n){return"Downgrade["+e+"] :: deviceInfo "+t+" matched criteria "+n}(e,t,n),o.indexOf("osversion")>=0?r.code=1001:o.indexOf("appversion")>=0?r.code=1002:o.indexOf("weexversion")>=0?r.code=1003:o.indexOf("devicemodel")>=0&&(r.code=1004),r}function at(e,t){t=t||global.WXEnvironment,t=O(t)?t:{};var n={isDowngrade:!1};if("function"===k(e)){var r=e.call(this,t,{semver:Wr,normalizeVersion:ot});r=!!r,n=r?it("custom","","custom params"):n}else{e=O(e)?e:{};var o=t.platform||"unknow",i=o.toLowerCase(),a=e[i]||{};for(var s in t){var u=s,c=u.toLowerCase(),l=t[s],f=c.indexOf("version")>=0,p=c.indexOf("devicemodel")>=0,d=a[s];if(d&&f){var h=ot(d),v=ot(t[s]);if(Wr.satisfies(v,h)){n=it(u,l,d);break}}else if(p){var y="array"===k(d)?d:[d];if(y.indexOf(l)>=0){n=it(u,l,d);break}}}}return n}function st(e,t){if(void 
 0===t&&(t={}),e&&e.callTasks)return e.callTasks([{module:"meta",method:"setViewport",args:[t]}])}function ut(e,t,n,r){console.debug("[JS Framework] bootstrap for "+t);var o;if(xr(t))o=j(t);else{if(!Sr(t))return new Error("Wrong component name: "+t);if(o=A(t),!nt(e,o))return new Error("It's not a component: "+t)}if(n=O(n)?n:{},"string"==typeof n.transformerVersion&&"string"==typeof global.transformerVersion&&!Wr.satisfies(n.transformerVersion,global.transformerVersion))return new Error("JS Bundle version: "+n.transformerVersion+" not compatible with "+global.transformerVersion);var i=at(n.downgrade);if(i.isDowngrade)return e.callTasks([{module:"instanceWrap",method:"error",args:[i.errorType,i.code,i.errorMessage]}]),new Error("Downgrade["+i.code+"]: "+i.errorMessage);n.viewport&&st(e,n.viewport),e.vm=new Qe(o,null,{_app:e},null,r)}function ct(e,t,n){console.warn("[JS Framework] Register is deprecated, please install lastest transformer."),rt(e,t,n)}function lt(e,t){console.debug("[JS
  Framework] Refresh with",t,"in instance["+e.id+"]");var n=e.vm;return n&&t?("function"==typeof n.refreshData?n.refreshData(t):_(n,t),e.differ.flush(),void e.doc.taskCenter.send("dom",{action:"refreshFinish"},[])):new Error('invalid data "'+t+'"')}function ft(e){console.debug("[JS Framework] Destory an instance("+e.id+")"),e.vm&&pt(e.vm),e.id="",e.options=null,e.blocks=null,e.vm=null,e.doc.taskCenter.destroyCallback(),e.doc.destroy(),e.doc=null,e.customComponentMap=null,e.commonModules=null}function pt(e){if(delete e._app,delete e._computed,delete e._css,delete e._data,delete e._ids,delete e._methods,delete e._options,delete e._parent,delete e._parentEl,delete e._rootEl,e._watchers){for(var t=e._watchers.length;t--;)e._watchers[t].teardown();delete e._watchers}if(e._childrenVms){for(var n=e._childrenVms.length;n--;)pt(e._childrenVms[n]);delete e._childrenVms}console.debug('[JS Framework] "destroyed" lifecycle in Vm('+e._type+")"),e.$emit("hook:destroyed"),delete e._type,delete e._vm
 Events}function dt(e){var t=e.doc||{},n=t.body||{};return n.toJSON?n.toJSON():{}}function ht(e,t,n,r,o){if(console.debug('[JS Framework] Fire a "'+n+'" event on an element('+t+") in instance("+e.id+")"),Array.isArray(t))return void t.some(function(t){return!1!==ht(e,t,n,r)});var i=e.doc.getRef(t);if(i){var a=e.doc.fireEvent(i,n,r,o);return e.differ.flush(),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),a}return new Error('invalid element reference "'+t+'"')}function vt(e,t,n,r){console.debug("[JS Framework] Invoke a callback("+t+") with",n,"in instance("+e.id+")");var o=e.doc.taskCenter.callback(t,n,r);return yt(e),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),o}function yt(e){e.differ.flush()}function mt(e,t){var n;return"array"!==k(t)&&(t=[t]),t.forEach(function(t){n=e.doc.taskCenter.send("module",{module:t.module,method:t.method},t.args)}),n}function _t(e,t,n,r){console.debug("[JS Framework] Intialize an instance with:\n",n);var o,i=function(){for(var t=[],n=ar
 guments.length;n--;)t[n]=arguments[n];return Ur.apply(void 0,[e].concat(t))},a=function(t,r,i){o=ut(e,t,r,i||n),yt(e),e.doc.listener.createFinish(),console.debug("[JS Framework] After intialized an instance("+e.id+")")},s=Qe,u=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return ct.apply(void 0,[e].concat(t))},c=function(t,n){o=ut(e,t,{},n)},l=function(t){return function(n){o=ut(e,t,{},n)}},f=e.doc,p=function(t){return e.requireModule(j(t))},d={config:e.options,define:i,bootstrap:a,requireModule:p,document:f,Vm:s};Object.freeze(d);var h;"function"==typeof t?h=t.toString().substr(12):t&&(h=t.toString()),h='(function(global){\n\n"use strict";\n\n '+h+" \n\n})(Object.create(this))";var v=global.WXEnvironment,y={};if(v&&"Web"!==v.platform){var m=e.requireModule("timer");Object.assign(y,{setTimeout:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setTimeout(r,t[1]),e.doc.taskCenter.callbackManager.la
 stCallbackId.toString()},setInterval:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setInterval(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},clearTimeout:function(e){m.clearTimeout(e)},clearInterval:function(e){m.clearInterval(e)}})}var _=Object.assign({define:i,require:l,bootstrap:a,register:u,render:c,__weex_define__:i,__weex_bootstrap__:a,__weex_document__:f,__weex_require__:p,__weex_viewmodel__:s,weex:d},y,r);return bt(_,h)||gt(_,h),o}function gt(e,t){var n=[],r=[];for(var o in e)n.push(o),r.push(e[o]);return n.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(n)))).apply(void 0,r)}function bt(e,t){if("function"!=typeof compileAndRunBundle)return!1;var n=void 0,r=!1,o="(function (",i=[],a=[];for(var s in e)i.push(s),a.push(e[s]);for(var u=0;u<i.length-1;++u)o+=i[u],o+=",";o+=i[i.length-1],o+=") {",o+=t,o+="} )";try{var c=e.weex||{},l=c.config||{};n=compileAndRunBundle(o,
 l.bundleUrl,l.bundleDigest,l.codeCachePath),n&&"function"==typeof n&&(n.apply(void 0,a),r=!0)}catch(e){console.error(e)}return r}function wt(e,t){var n=e[t];for(var r in n)n[r]()}function xt(e,t){var n=e[t];for(var r in n){n[r].forEach(function(e){e()})}}function Et(e,t){this.id=e,this.options=t||{},this.vm=null,this.customComponentMap={},this.commonModules={},this.doc=new Mr.Document(e,this.options.bundleUrl,null,Mr.Listener),this.differ=new Vr(e)}function Ot(e,t,n,r,o){var i=o||{},a=i.services;P();var s=Br[e];n=n||{};var u;return s?u=new Error('invalid instance id "'+e+'"'):(s=new Et(e,n),Br[e]=s,u=_t(s,t,r,a)),u instanceof Error?u:s}function St(e){Mr.Document=e.Document,Mr.Element=e.Element,Mr.Comment=e.Comment,Mr.sendTasks=e.sendTasks,Mr.Listener=e.Listener}function Ct(e,t){var n=Br[e];return n?lt(n,t):new Error('invalid instance id "'+e+'"')}function kt(e){"function"==typeof markupState&&markupState(),P();var t=Br[e];if(!t)return new Error('invalid instance id "'+e+'"');ft(t),d
 elete Br[e];var n=Math.round(e);if(n>0){n%18||"function"!=typeof notifyTrimMemory||notifyTrimMemory()}return Br}function jt(e){Array.isArray(e)&&e.forEach(function(e){e&&("string"==typeof e?qr[e]=!0:"object"==typeof e&&"string"==typeof e.type&&(qr[e.type]=e))})}function At(e){"object"==typeof e&&Ye(e)}function It(e){"object"==typeof e&&et(Qe,e)}function Tt(e,t){if(Br[e]&&Array.isArray(t)){var n=[];return t.forEach(function(t){var r=zr[t.method],o=[].concat(t.args);"function"==typeof r&&(o.unshift(e),n.push(r.apply(void 0,o)))}),n}return new Error('invalid instance id "'+e+'" or tasks')}function Nt(e){var t=Br[e];return t?dt(t):new Error('invalid instance id "'+e+'"')}function Pt(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=Hs(t),this.reject=Hs(n)}function Mt(){if(Rt(),global.WXEnvironment&&"Web"!==global.WXEnvironment.platform)global.console={debug:function(){for(var e=[],t=arguments.length;t-
 -;)e[t]=arguments[t];Dt("debug")&&global.nativeLog.apply(global,Ft(e).concat(["__DEBUG"]))},log:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("log")&&global.nativeLog.apply(global,Ft(e).concat(["__LOG"]))},info:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("info")&&global.nativeLog.apply(global,Ft(e).concat(["__INFO"]))},warn:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("warn")&&global.nativeLog.apply(global,Ft(e).concat(["__WARN"]))},error:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("error")&&global.nativeLog.apply(global,Ft(e).concat(["__ERROR"]))}};else{var e=console.debug,t=console.log,n=console.info,r=console.warn,o=console.error;console.__ori__={debug:e,log:t,info:n,warn:r,error:o},console.debug=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("debug")&&console.__ori__.debug.apply(console,e)},console.log=function(){for(var e=[],t=arguments.length;t--;)e[t]=argumen
 ts[t];Dt("log")&&console.__ori__.log.apply(console,e)},console.info=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("info")&&console.__ori__.info.apply(console,e)},console.warn=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("warn")&&console.__ori__.warn.apply(console,e)},console.error=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Dt("error")&&console.__ori__.error.apply(console,e)}}}function $t(){Vu={},global.console=Bu}function Rt(){Uu.forEach(function(e){var t=Uu.indexOf(e);Vu[e]={},Uu.forEach(function(n){Uu.indexOf(n)<=t&&(Vu[e][n]=!0)})})}function Dt(e){var t=global.WXEnvironment&&global.WXEnvironment.logLevel||"log";return Vu[t]&&Vu[t][e]}function Ft(e){return e.map(function(e){return e="[object object]"===Object.prototype.toString.call(e).toLowerCase()?JSON.stringify(e):String(e)})}function Lt(){if(void 0===setTimeout&&"function"==typeof zu){var e={},t=0;global.setTimeout=function(n,r){e[++t]=n,zu(t.toString(),r)},
 global.setTimeoutCallback=function(t){"function"==typeof e[t]&&(e[t](),delete e[t])}}}function Wt(){global.setTimeout=qu,global.setTimeoutCallback=null}function Ut(){Object.freeze(Object),Object.freeze(Array),Vt(),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Bt(),Object.freeze(Date.prototype),Object.freeze(RegExp.prototype)}function Vt(){var e=Object.prototype,t="Object.prototype";qt(e,"__defineGetter__",t),qt(e,"__defineSetter__",t),qt(e,"__lookupGetter__",t),qt(e,"__lookupSetter__",t),qt(e,"constructor",t),qt(e,"hasOwnProperty",t),qt(e,"isPrototypeOf",t),qt(e,"propertyIsEnumerable",t),qt(e,"toLocaleString",t),qt(e,"toString",t),qt(e,"valueOf",t),Object.seal(e)}function Bt(){var e=Error.prototype,t="Error.prototype";qt(e,"name",t),qt(e,"message",t),qt(e,"toString",t),qt(e,"constructor",t),Object.seal(e)}function qt(e,t,n){if(e.hasOwnProperty(t)){var r=e[t];Object.defineProperty(e,t,{get:function(){re
 turn r},set:function(r){if(this===e)throw Error("Cannot assign to read only property "+t+" of "+n);return Object.defineProperty(this,t,{value:r,writable:!0}),r}})}}function zt(){return(Ju++).toString()}function Jt(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1)}function Ht(e){if("function"!=typeof btoa)return"";var t=Array.prototype.map.call(new Uint8Array(e),function(e){return String.fromCharCode(e)}).join("");return btoa(t)}function Gt(e){if("function"!=typeof atob)return new ArrayBuffer(0);var t=atob(e),n=new Uint8Array(t.length);return Array.prototype.forEach.call(t,function(e,t){n[t]=e.charCodeAt(0)}),n.buffer}function Xt(e){var t=Jt(e);switch(t){case"Undefined":case"Null":return"";case"RegExp":return e.toString();case"Date":return e.toISOString();case"Number":case"String":case"Boolean":case"Array":case"Object":return e;case"ArrayBuffer":return{"@type":"binary",dataType:t,base64:Ht(e)};case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int
 16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":
 case"Float64Array":return{"@type":"binary",dataType:t,base64:Ht(e.buffer)};default:return JSON.stringify(e)}}function Kt(e){if("Object"===Jt(e)){if(e["@type"]&&"binary"===e["@type"])return Gt(e.base64||"");var t={};for(var n in e)t[n]=Kt(e[n]);return t}return"Array"===Jt(e)?e.map(Kt):e}function Zt(e,t){e&&(Gu[e]=t)}function Qt(e){return Gu[e]}function Yt(e){delete Gu[e]}function en(e){var t=Gu[e];return t&&t.taskCenter?t.taskCenter:null}function tn(e,t,n){var r=e.documentElement;if(!(r.pureChildren.length>0||t.parentNode)){var o=r.children,i=o.indexOf(n);i<0?o.push(t):o.splice(i,0,t),1===t.nodeType?("body"===t.role?(t.docId=e.id,t.ownerDocument=e,t.parentNode=r,on(t,r)):(t.children.forEach(function(e){e.parentNode=t}),rn(e,t),t.docId=e.id,t.ownerDocument=e,on(t,r),delete e.nodeMap[t.nodeId]),r.pureChildren.push(t),nn(e,t)):(t.parentNode=r,e.nodeMap[t.ref]=t)}}function nn(e,t){var n=t.toJSON(),r=n.children;delete n.children;var o=e.taskCenter.send("dom",{action:"createBody"},[n]);ret
 urn r&&r.forEach(function(t){o=e.taskCenter.send("dom",{action:"addElement"},[n.ref,t,-1])}),o}function rn(e,t){t.role="body",t.depth=1,delete e.nodeMap[t.nodeId],t.ref="_root",e.nodeMap._root=t,e.body=t}function on(e,t){e.parentNode=t,t.docId&&(e.docId=t.docId,e.ownerDocument=t.ownerDocument,e.ownerDocument.nodeMap[e.nodeId]=e,e.depth=t.depth+1),e.children.forEach(function(t){on(t,e)})}function an(e){for(;e;){if(1===e.nodeType)return e;e=e.nextSibling}}function sn(e){for(;e;){if(1===e.nodeType)return e;e=e.previousSibling}}function un(e,t,n,r){n<0&&(n=0);var o=t[n-1],i=t[n];return t.splice(n,0,e),r&&(o&&(o.nextSibling=e),e.previousSibling=o,e.nextSibling=i,i&&(i.previousSibling=e)),n}function cn(e,t,n,r){var o=t.indexOf(e);if(o<0)return-1;if(r){var i=t[o-1],a=t[o+1];i&&(i.nextSibling=a),a&&(a.previousSibling=i)}t.splice(o,1);var s=n;o<=n&&(s=n-1);var u=t[s-1],c=t[s];return t.splice(s,0,e),r&&(u&&(u.nextSibling=e),e.previousSibling=u,e.nextSibling=c,c&&(c.previousSibling=e)),o===s?-
 1:n}function ln(e,t,n){var r=t.indexOf(e);if(!(r<0)){if(n){var o=t[r-1],i=t[r+1];o&&(o.nextSibling=i),i&&(i.previousSibling=o)}t.splice(r,1)}}function fn(e,t){if(t&&t.length){var n=function(e){function t(){e.apply(this,arguments)}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t}(Ku);t.forEach(function(t){n.prototype[t]=function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var o=en(this.docId);if(o)return o.send("component",{ref:this.ref,component:e,method:t},n)}}),Zu[e]=n}}function pn(e){return Zu[e]}function dn(e){return"String"===Jt(e)?{"@binding":e}:e}function hn(e){for(var t,n,r=[],o=Qu.lastIndex=0;t=Qu.exec(e);){n=t.index,n>o&&r.push(e.slice(o,n));var i=dn(t[1].trim());r.push(i),o=n+t[0].length}return o<e.length&&r.push(e.slice(o)),1===r.length?r[0]:r}function vn(e){if("String"===Jt(e)&&Qu.test(e))return hn(e);if("Object"===Jt(e)){var t={};for(var n in e)t[n]=vn(e[n]);return t}return"Array"===Jt(e)?e.map(vn):e}function 
 yn(e,t){Qt(e).nodeMap[t.nodeId]=t}function mn(){var e={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},t=rc.prototype;for(var n in e)!function(n){var r=e[n];t[n]=r?function(e,t){return r.apply(void 0,[e].concat(t))}:function(e,t){return nc(e,[{module:"dom",method:n,args:t}],"-1")}}(n);t.componentHandler=global.callNativeComponent||function(e,t,n,r,o){return nc(e,[{component:o.component,ref:t,method:n,args:r}])},t.moduleHandler=global.callNativeModule||function(e,t,n,r){return nc(e,[{module:t,method:n,args:r}])}}function _n(e,t){bn(e)?console.warn('Service "'+e+'" has been registered already!'):(t=Object.assign({},t),ac.push({name:e,options:t}))}func
 tion gn(e){ac.some(function(t,n){if(t.name===e)return ac.splice(n,1),!0})}function bn(e){return wn(e)>=0}function wn(e){return ac.map(function(e){return e.name}).indexOf(e)}function xn(e){var t=sc.exec(e);if(t)try{return JSON.parse(t[1]).framework}catch(e){}return"Weex"}function En(e,t,n){var r=Object.create(null);return r.service=Object.create(null),ac.forEach(function(o){var i=(o.name,o.options),a=i.create;if(a){var s=a(e,t,n);Object.assign(r.service,s),Object.assign(r,s.instance)}}),delete r.service.instance,Object.freeze(r.service),r}function On(e){if(uc[e])return uc[e].framework}function Sn(e,t,n,r){if(uc[e])return new Error('invalid instance id "'+e+'"');var o=xn(t);n=JSON.parse(JSON.stringify(n||{})),n.env=JSON.parse(JSON.stringify(global.WXEnvironment||{}));var i={config:n,created:Date.now(),framework:o};i.services=En(e,i,ic),uc[e]=i;var a=oc[o];return a?a.createInstance(e,t,n,r,i):new Error('invalid bundle type "'+o+'".')}function Cn(e){cc[e]=function(){for(var t=[],n=argum
 ents.length;n--;)t[n]=arguments[n];"registerComponents"===e&&kn(t[0]);for(var r in oc){var o=oc[r];o&&o[e]&&o[e].apply(o,t)}}}function kn(e){Array.isArray(e)&&e.forEach(function(e){e&&e.type&&e.methods&&fn(e.type,e.methods)})}function jn(e){cc[e]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=On(r);if(o&&oc[o]){var i=(s=oc[o])[e].apply(s,t),a={framework:o};return"refreshInstance"===e?ac.forEach(function(e){var t=e.options.refresh;t&&t(r,{info:a,runtime:ic})}):"destroyInstance"===e&&(ac.forEach(function(e){var t=e.options.destroy;t&&t(r,{info:a,runtime:ic})}),delete uc[r]),i}return new Error('invalid instance id "'+r+'"');var s}}function An(e,t){cc[t]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=On(r);return o&&oc[o]?(i=oc[o])[e].apply(i,t):new Error('invalid instance id "'+r+'"');var i}}function In(e){ic=e||{},oc=ic.frameworks||{},mn();for(var t in oc){oc[t].init(e)}return["registerComponents","registerModules","regis
 terMethods"].forEach(Cn),["destroyInstance","refreshInstance","receiveTasks","getRoot"].forEach(jn),An("receiveTasks","callJS"),cc}function Tn(e,t){return void 0===t&&(t=[]),{module:"dom",method:e,args:t}}function Nn(e,t){var n=t||global.callNative;return"function"!=typeof n&&console.error("[JS Runtime] no default handler"),function(t){Array.isArray(t)||(t=[t]);for(var r=0;r<t.length;r++){var o=Mn(e,t[r],n);if(-1===o)return o}}}function Pn(e,t){return"dom"===e&&pc[t]&&"function"==typeof global[pc[t]]}function Mn(e,t,n){var r=t.module,o=t.method,i=t.args;return Pn(r,o)?global[pc[o]].apply(global,[e].concat(i,["-1"])):n(e,[t],"-1")}function $n(e,t){var n=t.attrs||{};for(var r in n)e.setAttr(r,n[r],!0);var o=t.style||{};for(var i in o)e.setStyle(i,o[i],!0)}function Rn(){Ut(),Object.freeze(hc.Comment),Object.freeze(hc.Listener),Object.freeze(hc.Document.prototype),Object.freeze(hc.Comment.prototype),Object.freeze(hc.Listener.prototype)}function Dn(e,t){void 0===t&&(t={}),this.type=e||"m
 essage",this.data=t.data||null,this.origin=t.origin||"",this.source=t.source||null,this.ports=t.ports||[],this.target=null,this.timeStamp=Date.now()}function Fn(){}function Ln(e,t,n,r){console.warn("[Upgrade Warning] $userTrack will be removed in the next version!"),console.warn("[JS Framework] Vm#$userTrack is deprecated, please use \"require('@weex-module/userTrack').commit(type, name, comName, param)\" instead"),this._app.requireModule("userTrack").commit(e,t,n,r)}function Wn(e,t){if(console.warn("[Upgrade Warning] $sendMtop will be removed in the next version!"),console.warn("[JS Framework] Vm#$sendMtop is deprecated, please use \"require('@weex-module/stream').sendMtop(params, callback)\" instead"),"undefined"==typeof window){this._app.requireModule("windvane").call({class:"MtopWVPlugin",method:"send",data:e},t)}else{this._app.requireModule("stream").sendMtop(e,t)}}function Un(e,t){console.warn("[Upgrade Warning] $callWindvane will be removed in the next version!"),console.warn
 ("[JS Framework] Vm#$callWindvane is deprecated, please use \"require('@weex-module/windvane').call(params, callback)\" instead"),this._app.requireModule("windvane").call(e,t)}function Vn(e,t){console.warn("[Upgrade Warning] $setSpm will be removed in the next version!"),console.warn("[JS Framework] Vm#$setSpm is deprecated, please use \"require('@weex-module/pageInfo').setSpm(a, b)\" instead"),this._app.requireModule("pageInfo").setSpm(e,t)}function Bn(e){console.warn("[Upgrade Warning] $getUserInfo will be removed in the next version!"),console.warn("[JS Framework] Vm#$getUserInfo is deprecated, please use \"require('@weex-module/user').getUserInfo(callback)\" instead"),this._app.requireModule("user").getUserInfo(e)}function qn(e){console.warn("[Upgrade Warning] $login will be removed in the next version!"),console.warn("[JS Framework] Vm#$login is deprecated, please use \"require('@weex-module/user').login(callback)\" instead"),this._app.requireModule("user").login(e)}function zn
 (e){console.warn("[Upgrade Warning] $logout will be removed in the next version!"),console.warn("[JS Framework] Vm#$logout is deprecated, please use \"require('@weex-module/user').logout(callback)\" instead"),this._app.requireModule("user").logout(e)}var Jn,Hn={},Gn={},Xn=Object.freeze({init:e,createInstance:t,destroyInstance:n,getRoot:r,receiveTasks:o}),Kn="undefined"!=typeof window?window:void 0!==global?global:"undefined"!=typeof self?self:{},Zn=a(function(e){e.exports=function(e,t){function n(e){return void 0===e||null===e}function r(e){return void 0!==e&&null!==e}function o(e){return!0===e}function i(e){return!1===e}function a(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e}function s(e){return null!==e&&"object"==typeof e}function u(e){return"[object Object]"===kn.call(e)}function c(e){return"[object RegExp]"===kn.call(e)}function l(e){var t=parseFloat(e);return t>=0&&Math.floor(t)===t&&isFinite(e)}function f(e){return null==e?"":"object"==typeof e?JSON.st
 ringify(e,null,2):String(e)}function p(e){var t=parseFloat(e);return isNaN(t)?e:t}function d(e,t){for(var n=Object.create(null),r=e.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function v(e,t){return An.call(e,t)}function y(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function m(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function _(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function g(e,t){for(var n in t)e[n]=t[n];return e}function b(e){for(var t={},n=0;n<e.length;n++)e[n]&&g(t,e[n]);return t}function w(e,t,n){}function x(e,t){if(e===t)return!0;var n=s(e),r=s(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var o=Array.isArray(e),i=Array.isArray(t);if(o&&i)return e.length===t.length&&e.every(fu
 nction(e,n){return x(e,t[n])});if(o||i)return!1;var a=Object.keys(e),u=Object.keys(t);return a.length===u.length&&a.every(function(n){return x(e[n],t[n])})}catch(e){return!1}}function E(e,t){for(var n=0;n<e.length;n++)if(x(e[n],t))return n;return-1}function O(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function C(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function k(e){if(!Vn.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function j(e,t,n){if(Wn.errorHandler)Wn.errorHandler.call(null,e,t,n);else{if(!zn||"undefined"==typeof console)throw e;console.error(e)}}function A(e){return"function"==typeof e&&/native code/.test(e.toString())}function I(e){ar.target&&sr.push(ar.target),ar.target=e}function T(){ar.target=sr.pop()}function N(e,t,n){e.__proto__=t}function P(e,t,n){for(var r=0,o=n.length;r<o;r+
 +){var i=n[r];C(e,i,t[i])}}function M(e,t){if(s(e)){var n;return v(e,"__ob__")&&e.__ob__ instanceof pr?n=e.__ob__:fr.shouldConvert&&!tr()&&(Array.isArray(e)||u(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new pr(e)),t&&n&&n.vmCount++,n}}function $(e,t,n,r,o){var i=new ar,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,u=a&&a.set,c=!o&&M(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ar.target&&(i.depend(),c&&c.dep.depend(),Array.isArray(t)&&F(t)),t},set:function(t){var r=s?s.call(e):n;t===r||t!==t&&r!==r||(u?u.call(e,t):n=t,c=!o&&M(t),i.notify())}})}}function R(e,t,n){if(Array.isArray(e)&&l(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(v(e,t))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?($(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function D(e,t){if(Array.isArray(e)&&l(t))return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||v(e,t)&&(delete e[t],n&&n.d
 ep.notify())}function F(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Array.isArray(t)&&F(t)}function L(e,t){if(!t)return e;for(var n,r,o,i=Object.keys(t),a=0;a<i.length;a++)n=i[a],r=e[n],o=t[n],v(e,n)?u(r)&&u(o)&&L(r,o):R(e,n,o);return e}function W(e,t,n){return n?e||t?function(){var r="function"==typeof t?t.call(n):t,o="function"==typeof e?e.call(n):e;return r?L(r,o):o}:void 0:t?e?function(){return L("function"==typeof t?t.call(this):t,"function"==typeof e?e.call(this):e)}:t:e}function U(e,t){return t?e?e.concat(t):Array.isArray(t)?t:[t]:e}function V(e,t){var n=Object.create(e||null);return t?g(n,t):n}function B(e){var t=e.props;if(t){var n,r,o,i={};if(Array.isArray(t))for(n=t.length;n--;)"string"==typeof(r=t[n])&&(o=Tn(r),i[o]={type:null});else if(u(t))for(var a in t)r=t[a],o=Tn(a),i[o]=u(r)?r:{type:r};e.props=i}}function q(e){var t=e.inject;if(Array.isArray(t))for(var n=e.inject={},r=0;r<t.length;r++)n[t[r]]=t[r]}function z(e){var t=e.direc
 tives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function J(e,t,n){function r(r){var o=dr[r]||hr;u[r]=o(e[r],t[r],n,r)}"function"==typeof t&&(t=t.options),B(t),q(t),z(t);var o=t.extends;if(o&&(e=J(e,o,n)),t.mixins)for(var i=0,a=t.mixins.length;i<a;i++)e=J(e,t.mixins[i],n);var s,u={};for(s in e)r(s);for(s in t)v(e,s)||r(s);return u}function H(e,t,n,r){if("string"==typeof n){var o=e[t];if(v(o,n))return o[n];var i=Tn(n);if(v(o,i))return o[i];var a=Nn(i);if(v(o,a))return o[a];var s=o[n]||o[i]||o[a];return s}}function G(e,t,n,r){var o=t[e],i=!v(n,e),a=n[e];if(Z(Boolean,o.type)&&(i&&!v(o,"default")?a=!1:Z(String,o.type)||""!==a&&a!==Mn(e)||(a=!0)),void 0===a){a=X(r,o,e);var s=fr.shouldConvert;fr.shouldConvert=!0,M(a),fr.shouldConvert=s}return a}function X(e,t,n){if(v(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==K(t.type)?r.call(e):r}}f
 unction K(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function Z(e,t){if(!Array.isArray(t))return K(t)===K(e);for(var n=0,r=t.length;n<r;n++)if(K(t[n])===K(e))return!0;return!1}function Q(e){return new vr(void 0,void 0,void 0,String(e))}function Y(e,t){var n=new vr(e.tag,e.data,e.children,e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return n.ns=e.ns,n.isStatic=e.isStatic,n.key=e.key,n.isComment=e.isComment,n.isCloned=!0,t&&e.children&&(n.children=ee(e.children)),n}function ee(e,t){for(var n=e.length,r=new Array(n),o=0;o<n;o++)r[o]=Y(e[o],t);return r}function te(e){function t(){var e=arguments,n=t.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=n.slice(),o=0;o<r.length;o++)r[o].apply(null,e)}return t.fns=e,t}function ne(e,t,r,o,i){var a,s,c,l,f;for(a in e)s=c=e[a],l=t[a],f=gr(a),u(s)&&(c=s.handler,f.params=s.params),n(c)||(n(l)?(n(c.fns)&&(c=e[a]=te(c)),r(f.name,c,f.once,f.capture,f.passive,f.params)):c!==l&&(l.fns=c,e[a]=l));f
 or(a in t)n(e[a])&&(f=gr(a),o(f.name,t[a],f.capture))}function re(e,t,i){function a(){i.apply(this,arguments),h(s.fns,a)}var s,u=e[t];n(u)?s=te([a]):r(u.fns)&&o(u.merged)?(s=u,s.fns.push(a)):s=te([u,a]),s.merged=!0,e[t]=s}function oe(e,t,o){var i=t.options.props;if(!n(i)){var a={},s=e.attrs,u=e.props;if(r(s)||r(u))for(var c in i){var l=Mn(c);ie(a,u,c,l,!0)||ie(a,s,c,l,!1)}return a}}function ie(e,t,n,o,i){if(r(t)){if(v(t,n))return e[n]=t[n],i||delete t[n],!0;if(v(t,o))return e[n]=t[o],i||delete t[o],!0}return!1}function ae(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function se(e){return a(e)?[Q(e)]:Array.isArray(e)?ce(e):void 0}function ue(e){return r(e)&&r(e.text)&&i(e.isComment)}function ce(e,t){var i,s,u,c=[];for(i=0;i<e.length;i++)s=e[i],n(s)||"boolean"==typeof s||(u=c[c.length-1],Array.isArray(s)?c.push.apply(c,ce(s,(t||"")+"_"+i)):a(s)?ue(u)?u.text+=String(s):""!==s&&c.push(Q(s)):ue(s)&&ue(u)?c[c.length-1]=Q(u.text+s.
 text):(o(e._isVList)&&r(s.tag)&&n(s.key)&&r(t)&&(s.key="__vlist"+t+"_"+i+"__"),c.push(s)));return c}function le(e,t){return e.__esModule&&e.default&&(e=e.default),s(e)?t.extend(e):e}function fe(e,t,n,r,o){var i=_r();return i.asyncFactory=e,i.asyncMeta={data:t,context:n,children:r,tag:o},i}function pe(e,t,i){if(o(e.error)&&r(e.errorComp))return e.errorComp;if(r(e.resolved))return e.resolved;if(o(e.loading)&&r(e.loadingComp))return e.loadingComp;if(!r(e.contexts)){var a=e.contexts=[i],u=!0,c=function(){for(var e=0,t=a.length;e<t;e++)a[e].$forceUpdate()},l=O(function(n){e.resolved=le(n,t),u||c()}),f=O(function(t){r(e.errorComp)&&(e.error=!0,c())}),p=e(l,f);return s(p)&&("function"==typeof p.then?n(e.resolved)&&p.then(l,f):r(p.component)&&"function"==typeof p.component.then&&(p.component.then(l,f),r(p.error)&&(e.errorComp=le(p.error,t)),r(p.loading)&&(e.loadingComp=le(p.loading,t),0===p.delay?e.loading=!0:setTimeout(function(){n(e.resolved)&&n(e.error)&&(e.loading=!0,c())},p.delay||200)
 ),r(p.timeout)&&setTimeout(function(){n(e.resolved)&&f(null)},p.timeout))),u=!1,e.loading?e.loadingComp:e.resolved}e.contexts.push(i)}function de(e){return e.isComment&&e.asyncFactory}function he(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var n=e[t];if(r(n)&&(r(n.componentOptions)||de(n)))return n}}function ve(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&_e(e,t)}function ye(e,t,n){n?mr.$once(e,t):mr.$on(e,t)}function me(e,t){mr.$off(e,t)}function _e(e,t,n){mr=e,ne(t,n||{},ye,me,e)}function ge(e,t){var n={};if(!e)return n;for(var r=[],o=0,i=e.length;o<i;o++){var a=e[o];if(a.context!==t&&a.functionalContext!==t||!a.data||null==a.data.slot)r.push(a);else{var s=a.data.slot,u=n[s]||(n[s]=[]);"template"===a.tag?u.push.apply(u,a.children):u.push(a)}}return r.every(be)||(n.default=r),n}function be(e){return e.isComment||" "===e.text}function we(e,t){t=t||{};for(var n=0;n<e.length;n++)Array.isArray(e[n])?we(e[n],t):t[e[n].key]=e[n].fn;retur
 n t}function xe(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}function Ee(e,t,n){e.$el=t,e.$options.render||(e.$options.render=_r),je(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},e._watcher=new jr(e,r,w),n=!1,null==e.$vnode&&(e._isMounted=!0,je(e,"mounted")),e}function Oe(e,t,n,r,o){var i=!!(o||e.$options._renderChildren||r.data.scopedSlots||e.$scopedSlots!==Un);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=o,e.$attrs=r.data&&r.data.attrs||Un,e.$listeners=n||Un,t&&e.$options.props){fr.shouldConvert=!1;for(var a=e._props,s=e.$options._propKeys||[],u=0;u<s.length;u++){var c=s[u];a[c]=G(c,e.$options.props,t,e)}fr.shouldConvert=!0,e.$options.propsData=t}if(n){var l=e.$options
 ._parentListeners;e.$options._parentListeners=n,_e(e,n,l)}i&&(e.$slots=ge(o,r.context),e.$forceUpdate())}function Se(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Ce(e,t){if(t){if(e._directInactive=!1,Se(e))return}else if(e._directInactive)return;if(e._inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Ce(e.$children[n]);je(e,"activated")}}function ke(e,t){if(!(t&&(e._directInactive=!0,Se(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)ke(e.$children[n]);je(e,"deactivated")}}function je(e,t){var n=e.$options[t];if(n)for(var r=0,o=n.length;r<o;r++)try{n[r].call(e)}catch(n){j(n,e,t+" hook")}e._hasHookEvent&&e.$emit("hook:"+t)}function Ae(){Cr=wr.length=xr.length=0,Er={},Or=Sr=!1}function Ie(){Sr=!0;var e,t;for(wr.sort(function(e,t){return e.id-t.id}),Cr=0;Cr<wr.length;Cr++)e=wr[Cr],t=e.id,Er[t]=null,e.run();var n=xr.slice(),r=wr.slice();Ae(),Pe(n),Te(r),nr&&Wn.devtools&&nr.emit("flush")}function Te(e){for(var 
 t=e.length;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&je(r,"updated")}}function Ne(e){e._inactive=!1,xr.push(e)}function Pe(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Ce(e[t],!0)}function Me(e){var t=e.id;if(null==Er[t]){if(Er[t]=!0,Sr){for(var n=wr.length-1;n>Cr&&wr[n].id>e.id;)n--;wr.splice(n+1,0,e)}else wr.push(e);Or||(Or=!0,or(Ie))}}function $e(e){Ar.clear(),Re(e,Ar)}function Re(e,t){var n,r,o=Array.isArray(e);if((o||s(e))&&Object.isExtensible(e)){if(e.__ob__){var i=e.__ob__.dep.id;if(t.has(i))return;t.add(i)}if(o)for(n=e.length;n--;)Re(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)Re(e[r[n]],t)}}function De(e,t,n){Ir.get=function(){return this[t][n]},Ir.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Ir)}function Fe(e){e._watchers=[];var t=e.$options;t.props&&Le(e,t.props),t.methods&&ze(e,t.methods),t.data?We(e):M(e._data={},!0),t.computed&&Ve(e,t.computed),t.watch&&t.watch!==Xn&&Je(e,t.watch)}function Le(e,t){var n=e.$options.propsData||{},r=e._prop
 s={},o=e.$options._propKeys=[],i=!e.$parent;fr.shouldConvert=i;for(var a in t)!function(i){o.push(i);var a=G(i,t,n,e);$(r,i,a),i in e||De(e,"_props",i)}(a);fr.shouldConvert=!0}function We(e){var t=e.$options.data;t=e._data="function"==typeof t?Ue(t,e):t||{},u(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,o=(e.$options.methods,n.length);o--;){var i=n[o];r&&v(r,i)||S(i)||De(e,"_data",i)}M(t,!0)}function Ue(e,t){try{return e.call(t)}catch(e){return j(e,t,"data()"),{}}}function Ve(e,t){var n=e._computedWatchers=Object.create(null),r=tr();for(var o in t){var i=t[o],a="function"==typeof i?i:i.get;r||(n[o]=new jr(e,a||w,w,Tr)),o in e||Be(e,o,i)}}function Be(e,t,n){var r=!tr();"function"==typeof n?(Ir.get=r?qe(t):n,Ir.set=w):(Ir.get=n.get?r&&!1!==n.cache?qe(t):n.get:w,Ir.set=n.set?n.set:w),Object.defineProperty(e,t,Ir)}function qe(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ar.target&&t.depend(),t.value}}function ze
 (e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?w:m(t[n],e)}function Je(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)He(e,n,r[o]);else He(e,n,r)}}function He(e,t,n,r){return u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function Ge(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function Xe(e){var t=Ke(e.$options.inject,e);t&&(fr.shouldConvert=!1,Object.keys(t).forEach(function(n){$(e,n,t[n])}),fr.shouldConvert=!0)}function Ke(e,t){if(e){for(var n=Object.create(null),r=rr?Reflect.ownKeys(e):Object.keys(e),o=0;o<r.length;o++)for(var i=r[o],a=e[i],s=t;s;){if(s._provided&&a in s._provided){n[i]=s._provided[a];break}s=s.$parent}return n}}function Ze(e,t,n,o,i){var a={},s=e.options.props;if(r(s))for(var u in s)a[u]=G(u,s,t||Un);else r(n.attrs)&&Qe(a,n.attrs),r(n.props)&&Qe(a,n.props);var c=Object.create(o),l=function(e,t,n,r){return ot(c,e,t,n,r,!0)},f=e.options.render.call(null,l,{data:n,props:a
 ,children:i,parent:o,listeners:n.on||Un,injections:Ke(e.options.inject,o),slots:function(){return ge(i,o)}});return f instanceof vr&&(f.functionalContext=o,f.functionalOptions=e.options,n.slot&&((f.data||(f.data={})).slot=n.slot)),f}function Qe(e,t){for(var n in t)e[Tn(n)]=t[n]}function Ye(e,t,i,a,u){if(!n(e)){var c=i.$options._base;if(s(e)&&(e=c.extend(e)),"function"==typeof e){var l;if(n(e.cid)&&(l=e,void 0===(e=pe(l,c,i))))return fe(l,t,i,a,u);t=t||{},gt(e),r(t.model)&&rt(e.options,t);var f=oe(t,e,u);if(o(e.options.functional))return Ze(e,f,t,i,a);var p=t.on;if(t.on=t.nativeOn,o(e.options.abstract)){var d=t.slot;t={},d&&(t.slot=d)}tt(t);var h=e.options.name||u;return new vr("vue-component-"+e.cid+(h?"-"+h:""),t,void 0,void 0,void 0,i,{Ctor:e,propsData:f,listeners:p,tag:u,children:a},l)}}}function et(e,t,n,o){var i=e.componentOptions,a={_isComponent:!0,parent:t,propsData:i.propsData,_componentTag:i.tag,_parentVnode:e,_parentListeners:i.listeners,_renderChildren:i.children,_parentE
 lm:n||null,_refElm:o||null},s=e.data.inlineTemplate;return r(s)&&(a.render=s.render,a.staticRenderFns=s.staticRenderFns),new i.Ctor(a)}function tt(e){e.hook||(e.hook={});for(var t=0;t<Pr.length;t++){var n=Pr[t],r=e.h

<TRUNCATED>


[04/17] incubator-weex git commit: Merge remote-tracking branch 'upstream/0.16-dev' into 0.17-dev-feature-recycle-list

Posted by ac...@apache.org.
Merge remote-tracking branch 'upstream/0.16-dev' into 0.17-dev-feature-recycle-list

# Conflicts:
#	ios/sdk/WeexSDK.xcodeproj/project.pbxproj
#	ios/sdk/WeexSDK/Sources/Model/WXComponent.m


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

Branch: refs/heads/0.16-dev
Commit: dc112fc2d8efc5a32597dc6ecead70fbe53b88ed
Parents: 74cc3b3 8325077
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:16:24 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:16:24 2017 +0800

----------------------------------------------------------------------
 .travis.yml                                     |   47 +-
 POSSIBLE-NOTICES-FOR-BIN-DIST                   |    5 +-
 WeexSDK.podspec                                 |    2 -
 android/build.gradle                            |   13 +-
 android/gradle.properties                       |    5 +-
 .../gradle/wrapper/gradle-wrapper.properties    |    2 +-
 android/jacoco.gradle                           |   43 +
 .../alibaba/weex/benchmark/BenchmarkTest.java   |   29 +-
 .../playground/app/src/main/AndroidManifest.xml |    8 +
 .../alibaba/weex/util/CoverageDataDumper.java   |   36 +
 .../alibaba/weex/util/JacocoCodeCoverage.java   |   93 +
 android/sdk/libs/armeabi/libweexjsb.so          |  Bin 0 -> 22556 bytes
 android/sdk/libs/armeabi/libweexjsc.so          |  Bin 7570392 -> 325660 bytes
 android/sdk/libs/armeabi/libweexjss.so          |  Bin 0 -> 6754016 bytes
 .../java/com/taobao/weex/WXEnvironment.java     |   16 +
 .../java/com/taobao/weex/WXSDKInstance.java     |  110 +-
 .../weex/appfram/pickers/DatePickerImpl.java    |    3 +-
 .../appfram/websocket/WebSocketCloseCodes.java  |    2 +-
 .../com/taobao/weex/bridge/WXBridgeManager.java |   48 +-
 .../java/com/taobao/weex/bridge/WXParams.java   |    9 +
 .../java/com/taobao/weex/common/Constants.java  |    2 +
 .../java/com/taobao/weex/common/WXConfig.java   |    1 +
 .../com/taobao/weex/dom/ImmutableDomObject.java |   21 +-
 .../main/java/com/taobao/weex/dom/WXStyle.java  |   17 -
 .../com/taobao/weex/dom/WXTextDomObject.java    |   11 +-
 .../com/taobao/weex/dom/action/Actions.java     |    4 +-
 .../weex/dom/action/CreateBodyAction.java       |   12 +-
 .../weex/dom/action/ReloadPageAction.java       |    6 +-
 .../taobao/weex/ui/component/WXComponent.java   |  143 +-
 .../com/taobao/weex/ui/component/WXDiv.java     |   74 +-
 .../com/taobao/weex/ui/component/WXSlider.java  |    4 +-
 .../com/taobao/weex/ui/component/WXText.java    |   65 +-
 .../taobao/weex/ui/component/WXVContainer.java  |   44 +-
 .../taobao/weex/ui/component/list/WXCell.java   |   63 +-
 .../weex/ui/component/list/WXListComponent.java |   90 +-
 .../com/taobao/weex/ui/flat/FlatComponent.java  |   33 +
 .../com/taobao/weex/ui/flat/FlatGUIContext.java |  146 ++
 .../taobao/weex/ui/flat/WidgetContainer.java    |   93 +
 .../weex/ui/flat/widget/AndroidViewWidget.java  |   76 +
 .../taobao/weex/ui/flat/widget/BaseWidget.java  |  130 ++
 .../taobao/weex/ui/flat/widget/TextWidget.java  |   49 +
 .../com/taobao/weex/ui/flat/widget/Widget.java  |   51 +
 .../taobao/weex/ui/flat/widget/WidgetGroup.java |   54 +
 .../taobao/weex/ui/module/WXTimerModule.java    |    9 +-
 .../weex/ui/view/WXBaseCircleIndicator.java     |  131 +-
 .../com/taobao/weex/ui/view/WXFrameLayout.java  |   53 +-
 .../weex/ui/view/border/BorderCorner.java       |   37 +-
 .../taobao/weex/ui/view/border/BorderUtil.java  |   26 -
 .../weex/ui/view/border/BottomLeftCorner.java   |    7 +-
 .../weex/ui/view/border/BottomRightCorner.java  |    7 +-
 .../weex/ui/view/border/TopLeftCorner.java      |    7 +-
 .../weex/ui/view/border/TopRightCorner.java     |    7 +-
 .../com/taobao/weex/utils/FunctionParser.java   |    6 -
 .../java/com/taobao/weex/utils/LogLevel.java    |    4 +-
 .../java/com/taobao/weex/utils/OsVersion.java   |    2 +-
 .../main/java/com/taobao/weex/utils/Trace.java  |    4 +-
 .../java/com/taobao/weex/utils/WXLogUtils.java  |   14 +
 .../java/com/taobao/weex/utils/WXViewUtils.java |   31 +
 .../com/taobao/weex/ui/component/WXDivTest.java |   12 +-
 .../taobao/weex/ui/component/WXTextTest.java    |   18 +-
 .../weex/ui/module/WXTimerModuleTest.java       |   45 +-
 dangerfile-android.js                           |  108 ++
 dangerfile-ios.js                               |  107 ++
 dangerfile-jsfm.js                              |  105 +
 dangerfile.js                                   |    4 +-
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj       |   42 -
 .../WeexSDK/Sources/Bridge/WXBridgeContext.m    |    4 +-
 .../Sources/Bridge/WXDebugLoggerBridge.h        |   26 -
 .../Sources/Bridge/WXDebugLoggerBridge.m        |  213 ---
 ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m |   89 +-
 .../Component/Recycler/WXMultiColumnLayout.m    |   32 +-
 .../Sources/Component/WXComponent_internal.h    |    3 +-
 .../WeexSDK/Sources/Component/WXEditComponent.m |    4 +-
 .../Sources/Component/WXImageComponent.m        |   34 +-
 .../WeexSDK/Sources/Component/WXListComponent.m |    4 +
 .../WeexSDK/Sources/Component/WXTextComponent.m |    6 +-
 ios/sdk/WeexSDK/Sources/Component/WXTransform.m |    2 +-
 .../Sources/Display/WXComponent+Display.m       |    2 +-
 ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m    |    4 -
 .../WeexSDK/Sources/Events/WXComponent+Events.m |   35 +-
 .../WeexSDK/Sources/Layout/WXComponent+Layout.m |    4 +-
 .../Sources/Manager/WXComponentManager.m        |    6 +-
 .../WeexSDK/Sources/Manager/WXTracingManager.h  |    5 +
 .../WeexSDK/Sources/Manager/WXTracingManager.m  |   11 +
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |   39 +-
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m   |    4 +
 .../WeexSDK/Sources/Module/WXAnimationModule.m  |   26 +-
 .../WeexSDK/Sources/Module/WXModalUIModule.m    |    4 +-
 .../WeexSDK/Sources/Module/WXPrerenderManager.m |   50 +-
 .../WeexSDK/Sources/Module/WXWebSocketModule.m  |    1 -
 ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h     |    1 +
 ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m     |    1 +
 .../Sources/Protocol/WXAppMonitorProtocol.h     |    1 +
 ios/sdk/WeexSDK/Sources/Utility/WXConvert.m     |   24 +-
 ios/sdk/WeexSDK/Sources/Utility/WXLog.m         |   15 +-
 ios/sdk/WeexSDK/Sources/Utility/WXUtility.m     |    4 +
 .../Sources/WebSocket/SRWebSocket+Weex.h        |   29 -
 .../Sources/WebSocket/SRWebSocket+Weex.m        |   47 -
 .../Sources/WebSocket/WXWebSocketDefaultImpl.h  |   25 -
 .../Sources/WebSocket/WXWebSocketDefaultImpl.m  |  121 --
 ios/sdk/WeexSDK/dependency/SRWebSocket.h        |  135 --
 ios/sdk/WeexSDK/dependency/SRWebSocket.m        | 1806 ------------------
 package.json                                    |    5 +-
 scripts/build_from_source.sh                    |    2 +-
 scripts/generate_apache_release.sh              |    2 +-
 test/pages/components/iconfont.vue              |    6 +-
 test/pages/components/textarea-placeholder.vue  |   62 +
 test/pages/include/navbar.vue                   |  121 ++
 test/pages/include/navpage.vue                  |   62 +
 test/pages/modules/modal-event.vue              |    2 +-
 test/pages/modules/navigator-event.vue          |  101 +
 test/pages/modules/picker-event.vue             |    6 +-
 test/pages/modules/viewport-basic.vue           |   62 +
 test/pages/modules/vue_timer.vue                |   14 +-
 test/pages/modules/we_timer.we                  |   14 +-
 test/run.sh                                     |   25 +-
 test/screenshot/border-android.png              |  Bin 158634 -> 162929 bytes
 test/screenshot/border-ios.png                  |  Bin 126185 -> 128088 bytes
 test/screenshot/compositing-ios.png             |  Bin 228306 -> 229534 bytes
 test/screenshot/image-resize-android.png        |  Bin 214440 -> 218804 bytes
 test/screenshot/image-resize-ios.png            |  Bin 138033 -> 138103 bytes
 test/scripts/components/scroll-event.test.js    |    2 +-
 .../components/textarea-placeholder.test.js     |   69 +
 test/scripts/modules/navigator-event.test.js    |   51 +
 test/scripts/modules/picker-event.test.js       |    4 +-
 test/scripts/modules/viewport-basic.test.js     |   45 +
 test/scripts/util.js                            |   37 +
 127 files changed, 2860 insertions(+), 3095 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --cc ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 5911fec,3802d0e..a7329a7
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@@ -1635,8 -1541,6 +1601,7 @@@
  				744D61141E4AF23E00B624B3 /* WXDiffUtil.h in Headers */,
  				74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */,
  				2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */,
- 				C4F012791E1502A6003378D0 /* SRWebSocket+Weex.h in Headers */,
 +				74CFDD451F459443007A1A66 /* WXRecycleListUpdateManager.h in Headers */,
  				74A4BA9A1CB3BAA100195969 /* WXThreadSafeMutableDictionary.h in Headers */,
  				74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h in Headers */,
  				741DFE021DDD7D18009B020F /* WXRoundedRect.h in Headers */,
@@@ -2106,9 -2004,7 +2068,8 @@@
  				746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */,
  				74B8BEFF1DC47B72004A6027 /* WXRootView.m in Sources */,
  				742AD7321DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m in Sources */,
 +				74CFDD421F45941E007A1A66 /* WXRecycleListTemplateManager.m in Sources */,
  				747DF6831E31AEE4005C53A8 /* WXLength.m in Sources */,
- 				C4F0127C1E1502A6003378D0 /* WXWebSocketDefaultImpl.m in Sources */,
  				77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */,
  				2A60CE9D1C91733E00857B9F /* WXSwitchComponent.m in Sources */,
  				744D61111E49979000B624B3 /* WXFooterComponent.m in Sources */,
@@@ -2223,10 -2112,8 +2183,9 @@@
  				77D1614C1C02E3790010B15B /* WXConvert.m in Sources */,
  				749DC27C1D40827B009E1C91 /* WXMonitor.m in Sources */,
  				C4B834271DE69B09007AD27E /* WXPickerModule.m in Sources */,
- 				C4F0127A1E1502A6003378D0 /* SRWebSocket+Weex.m in Sources */,
  				745B2D691E5A8E1E0092D38A /* WXMultiColumnLayout.m in Sources */,
  				77D161391C02DE940010B15B /* WXBridgeManager.m in Sources */,
 +				74BF19F91F5139BB00AEE3D7 /* WXJSASTParser.mm in Sources */,
  			);
  			runOnlyForDeploymentPostprocessing = 0;
  		};

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
----------------------------------------------------------------------
diff --cc ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
index fa42445,c53d5f1..db26c93
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@@ -217,16 -204,8 +217,17 @@@ static NSThread *WXComponentThread
      _rootComponent = [self _buildComponentForData:data supercomponent:nil];
      
      [self _initRootCSSNode];
 +    
 +    NSArray *subcomponentsData = [data valueForKey:@"children"];
 +    if (subcomponentsData) {
 +        BOOL appendTree = [_rootComponent.attributes[@"append"] isEqualToString:@"tree"];
 +        for(NSDictionary *subcomponentData in subcomponentsData){
 +            [self _recursivelyAddComponent:subcomponentData toSupercomponent:_rootComponent atIndex:-1 appendingInTree:appendTree];
 +        }
 +    }
 +    
      __weak typeof(self) weakSelf = self;
+     WX_MONITOR_INSTANCE_PERF_END(WXFirstScreenJSFExecuteTime, self.weexInstance);
      [self _addUITask:^{
          [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] className:nil name:data[@"type"] phase:WXTracingBegin functionName:@"createBody" options:@{@"threadName":WXTUIThread}];
          __strong typeof(self) strongSelf = weakSelf;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/dc112fc2/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --cc ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 491e272,0992b49..5bdc7f3
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@@ -137,39 -140,14 +141,48 @@@
      return self;
  }
  
 +- (id)copyWithZone:(NSZone *)zone
 +{
 +    NSInteger copyId = 0;
 +    @synchronized(self){
 +        static NSInteger __copy = 0;
 +        copyId = __copy % (1024*1024);
 +        __copy++;
 +    }
 +    NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", copyId, _isTemplate ? self.ref : self->_templateComponent.ref];
 +    WXComponent *component = [[[self class] allocWithZone:zone] initWithRef:copyRef type:self.type styles:self.styles attributes:self.attributes events:self.events weexInstance:self.weexInstance];
 +    if (_isTemplate) {
 +        component->_templateComponent = self;
 +    } else {
 +        component->_templateComponent = self->_templateComponent;
 +    }
 +    memcpy(component->_cssNode, self.cssNode, sizeof(css_node_t));
 +    component->_cssNode->context = (__bridge void *)component;
 +    component->_calculatedFrame = self.calculatedFrame;
 +    
 +    NSMutableArray *subcomponentsCopy = [NSMutableArray array];
 +    for (WXComponent *subcomponent in self.subcomponents) {
 +        WXComponent *subcomponentCopy = [subcomponent copy];
 +        subcomponentCopy->_supercomponent = component;
 +        [subcomponentsCopy addObject:subcomponentCopy];
 +    }
 +    
 +    component->_subcomponents = subcomponentsCopy;
 +    
 +    WXPerformBlockOnComponentThread(^{
 +        [self.weexInstance.componentManager addComponent:component toIndexDictForRef:copyRef];
 +    });
 +    
 +    return component;
++
+ - (UIAccessibilityTraits)_parseAccessibilityTraitsWithTraits:(UIAccessibilityTraits)trait roles:(NSString*)roleStr
+ {
+     UIAccessibilityTraits newTrait = trait;
+     for (NSString * role in [roleStr componentsSeparatedByString:@" "]) {
+         newTrait |= [WXConvert WXUIAccessibilityTraits: role];
+     }
+     
+     return newTrait;
  }
  
  - (void)dealloc


[03/17] incubator-weex git commit: * [ios] Supporting events and data updating for recycle-list component.

Posted by ac...@apache.org.
* [ios] Supporting events and data updating for recycle-list component.


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

Branch: refs/heads/0.16-dev
Commit: 74cc3b331d00b5f333e215dba8f6200ccf1bf668
Parents: 877487a
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:11:10 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:11:10 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj       |   8 +
 .../Component/RecycleList/WXCellSlotComponent.m |   4 +-
 .../RecycleList/WXComponent+DataBinding.h       |   2 +-
 .../RecycleList/WXComponent+DataBinding.mm      | 139 +++++++---
 .../Component/RecycleList/WXJSASTParser.h       |   5 +
 .../Component/RecycleList/WXJSASTParser.mm      |  46 ++++
 .../RecycleList/WXRecycleListComponent.h        |   4 +-
 .../RecycleList/WXRecycleListComponent.m        | 272 +++++++++++++++++--
 .../RecycleList/WXRecycleListDataManager.h      |   2 +
 .../RecycleList/WXRecycleListDataManager.m      |   7 +
 .../Component/RecycleList/WXRecycleListLayout.h |  21 ++
 .../Component/RecycleList/WXRecycleListLayout.m | 102 +++++++
 .../RecycleList/WXRecycleListTemplateManager.m  |   2 +-
 .../RecycleList/WXRecycleListUpdateManager.h    |  22 ++
 .../RecycleList/WXRecycleListUpdateManager.m    | 233 ++++++++++++++++
 .../Recycler/WXSectionDataController.m          |   2 +-
 .../WeexSDK/Sources/Component/WXCellComponent.m |   2 +-
 .../Sources/Component/WXComponent_internal.h    |  14 +-
 .../Sources/Component/WXScrollerComponent.h     |   2 +
 .../Sources/Component/WXScrollerComponent.m     |  13 +-
 .../WeexSDK/Sources/Events/WXComponent+Events.m |   5 +-
 .../WeexSDK/Sources/Manager/WXBridgeManager.h   |  13 +-
 .../WeexSDK/Sources/Manager/WXBridgeManager.m   |  10 +
 .../Sources/Manager/WXComponentManager.h        |   1 +
 .../Sources/Manager/WXComponentManager.m        |  36 ++-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |  20 ++
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h    |  23 +-
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m    |  84 +++++-
 28 files changed, 1024 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index d597bf0..5911fec 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -188,6 +188,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 */; };
+		74BA4AB31F70F4B600AC29BF /* WXRecycleListLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */; };
+		74BA4AB41F70F4B600AC29BF /* WXRecycleListLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */; };
 		74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */; };
 		74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */; };
 		74BF19F81F5139BB00AEE3D7 /* WXJSASTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */; };
@@ -778,6 +780,8 @@
 		74B8BEFC1DC47B72004A6027 /* WXRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXRootView.h; sourceTree = "<group>"; };
 		74B8BEFD1DC47B72004A6027 /* WXRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootView.m; sourceTree = "<group>"; };
 		74B8BF001DC49AFE004A6027 /* WXRootViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootViewTests.m; sourceTree = "<group>"; };
+		74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListLayout.h; sourceTree = "<group>"; };
+		74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListLayout.m; sourceTree = "<group>"; };
 		74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXMetaModule.h; sourceTree = "<group>"; };
 		74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXMetaModule.m; sourceTree = "<group>"; };
 		74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXJSASTParser.h; sourceTree = "<group>"; };
@@ -1143,6 +1147,8 @@
 				74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */,
 				74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */,
 				74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */,
+				74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */,
+				74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */,
 				746B92391F46BE36009AE86B /* WXCellSlotComponent.h */,
 				746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */,
 				7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */,
@@ -1649,6 +1655,7 @@
 				741081261CEDB4EC001BC6E5 /* WXComponent_internal.h in Headers */,
 				77E65A191C155F25008B8775 /* WXScrollerComponent.h in Headers */,
 				C4E375381E5FCBD3009B2D9C /* WXComponent+BoxShadow.h in Headers */,
+				74BA4AB31F70F4B600AC29BF /* WXRecycleListLayout.h in Headers */,
 				742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */,
 				C4F0127D1E1502A6003378D0 /* WXWebSocketHandler.h in Headers */,
 				DC03ADBA1D508719003F76E7 /* WXTextAreaComponent.h in Headers */,
@@ -2193,6 +2200,7 @@
 				7408C48F1CFB345D000BCCD0 /* WXComponent+Events.m in Sources */,
 				C4F012871E150307003378D0 /* WXWebSocketLoader.m in Sources */,
 				C4D872211E5DDEDA00E39BC1 /* WXInnerLayer.m in Sources */,
+				74BA4AB41F70F4B600AC29BF /* WXRecycleListLayout.m in Sources */,
 				745ED2DB1C5F2C7E002DB5A8 /* WXView.m in Sources */,
 				DC03ADB91D508719003F76E7 /* WXTextAreaComponent.m in Sources */,
 				59A596231CB6311F0012CD52 /* WXNavigatorModule.m in Sources */,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
index 2561d86..0cbd97b 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
@@ -76,9 +76,9 @@ static const NSString *WXDefaultRecycleTemplateType = @"WXDefaultRecycleTemplate
     
     if ([self needsLayout]) {
         layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
-//        if ([WXLog logLevel] >= WXLogLevelDebug) {
+        if ([WXLog logLevel] >= WXLogLevelDebug) {
             print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN);
-//        }
+        }
     }
     
     NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
index ce3ab15..610f82f 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
@@ -24,7 +24,7 @@ static const NSString *WXBindingMatchIdentify = @"[[match]]";
 static const NSString *WXBindingRepeatIdentify = @"[[repeat]]";
 static const NSString *WXBindingRepeatExprIdentify = @"@expression";
 static const NSString *WXBindingRepeatIndexIdentify = @"@index";
-static const NSString *WXBindingRepeatLabelIdentify = @"@label";
+static const NSString *WXBindingRepeatLabelIdentify = @"@alias";
 
 @interface WXComponent (DataBinding)
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
index 51f5724..b15ebd8 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
@@ -27,8 +27,10 @@
 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
 
 typedef enum : NSUInteger {
-    WXDataBindingTypeStyle = 0,
+    WXDataBindingTypeProp = 0,
+    WXDataBindingTypeStyle,
     WXDataBindingTypeAttributes,
+    WXDataBindingTypeEvents,
     WXDataBindingTypeCount,
 } WXDataBindingType;
 
@@ -57,6 +59,19 @@ static JSContext *jsContext;
         return;
     }
     
+    if (templateComponent->_bindingProps) {
+        NSMutableDictionary *newData = [NSMutableDictionary dictionary];
+        [templateComponent->_bindingProps enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, WXDataBindingBlock  _Nonnull block, BOOL * _Nonnull stop) {
+            BOOL needUpdate;
+            id value = block(data, &needUpdate);
+            if (value) {
+                newData[key] = value;
+            }
+        }];
+        
+        data = newData;
+    }
+    
     if (!_isRepeating) {
         WXDataBindingBlock repeatBlock = templateComponent->_bindingRepeat;
         if (repeatBlock) {
@@ -80,7 +95,7 @@ static JSContext *jsContext;
     }
     
     for (int i = WXDataBindingTypeStyle; i < WXDataBindingTypeCount; i++) {
-        NSDictionary *bindingMap = i == WXDataBindingTypeStyle ? templateComponent->_bindingStyles : templateComponent->_bindingAttributes;
+        NSDictionary *bindingMap = i == WXDataBindingTypeStyle ? templateComponent->_bindingStyles : (i == WXDataBindingTypeAttributes ? templateComponent->_bindingAttributes : templateComponent->_bindingEvents);
         if (!bindingMap || bindingMap.count == 0) {
             continue;
         }
@@ -98,8 +113,10 @@ static JSContext *jsContext;
             [self.weexInstance.componentManager startComponentTasks];
             if (i == WXDataBindingTypeStyle) {
                 [self.weexInstance.componentManager updateStyles:newAttributesOrStyles forComponent:self.ref];
-            } else {
+            } else if (i == WXDataBindingTypeAttributes) {
                 [self.weexInstance.componentManager updateAttributes:newAttributesOrStyles forComponent:self.ref];
+            } else if (i == WXDataBindingTypeEvents) {
+                [self _addEventParams:newAttributesOrStyles];
             }
         }
     }
@@ -163,41 +180,78 @@ static JSContext *jsContext;
     }
 }
 
-- (void)_storeBindingsWithStyles:(NSDictionary *)styles attributes:(NSDictionary *)attributes
+- (void)_storeBindingsWithProps:(NSDictionary *)props styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSDictionary *)events
 {
-    if (!_bindingAttributes) {
-        _bindingAttributes = [NSMutableDictionary new];
+    WXAssertComponentThread();
+    
+    if (props.count > 0) {
+        if (!_bindingProps) {
+            _bindingProps = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:props type:WXDataBindingTypeProp];
     }
-    if (!_bindingStyles) {
-        _bindingStyles = [NSMutableDictionary new];
+    
+    if (styles.count > 0) {
+        if (!_bindingStyles) {
+            _bindingStyles = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:styles type:WXDataBindingTypeStyle];
+    }
+    
+    if (attributes.count > 0) {
+        if (!_bindingAttributes) {
+            _bindingAttributes = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:attributes type:WXDataBindingTypeAttributes];
+    }
+    
+    if (events.count > 0) {
+        if (!_bindingEvents) {
+            _bindingEvents = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:events type:WXDataBindingTypeEvents];
     }
-    [self _storeBindings:styles type:WXDataBindingTypeStyle];
-    [self _storeBindings:attributes type:WXDataBindingTypeAttributes];
 }
 
-- (void)_storeBindings:(NSDictionary *)attributesOrStyles type:(WXDataBindingType)type
+- (void)_storeBindings:(NSDictionary *)stylesOrAttributesOrEvents type:(WXDataBindingType)type
 {
     WXAssertComponentThread();
     
-    NSMutableDictionary *bindingMap = type == WXDataBindingTypeStyle ? _bindingStyles : _bindingAttributes;
+    NSMutableDictionary *bindingMap;
+    switch (type) {
+        case WXDataBindingTypeProp:
+            bindingMap = _bindingProps;
+            break;
+        case WXDataBindingTypeStyle:
+            bindingMap = _bindingStyles;
+            break;
+        case WXDataBindingTypeAttributes:
+            bindingMap = _bindingAttributes;
+            break;
+        case WXDataBindingTypeEvents:
+            bindingMap = _bindingEvents;
+            break;
+        default:
+            WXAssert(NO, @"error binding type:%z", type);
+            break;
+    }
     
-    // many-to-many relationship between attibuteName and bindingKey
-    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
-        if ([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify]) {
+    [stylesOrAttributesOrEvents enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull name, id  _Nonnull binding, BOOL * _Nonnull stop) {
+        if ([binding isKindOfClass:[NSDictionary class]] && binding[WXBindingIdentify]) {
             // {"attributeOrStyleName":{"@binding":"bindingExpression"}
-            NSString *bindingExpression = attributeOrStyle[WXBindingIdentify];
+            NSString *bindingExpression = binding[WXBindingIdentify];
             WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
             WXJSExpression *expression = [parser parseExpression];
             WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
-            bindingMap[attributeOrStyleName] = block;
-        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
+            bindingMap[name] = block;
+        } else if ([binding isKindOfClass:[NSArray class]]) {
             // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
             NSMutableDictionary *bindingBlocksForIndex = [NSMutableDictionary dictionary];
             __block BOOL isBinding = NO;
-            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-                if ([obj isKindOfClass:[NSDictionary class]] && obj[WXBindingIdentify]) {
+            [binding enumerateObjectsUsingBlock:^(id  _Nonnull bindingInArray, NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([bindingInArray isKindOfClass:[NSDictionary class]] && bindingInArray[WXBindingIdentify]) {
                     isBinding = YES;
-                    NSString *bindingExpression = obj[WXBindingIdentify];
+                    NSString *bindingExpression = bindingInArray[WXBindingIdentify];
                     WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
                     WXJSExpression *expression = [parser parseExpression];
                     WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
@@ -205,9 +259,9 @@ static JSContext *jsContext;
                 }
             }];
             
-            bindingMap[attributeOrStyleName] = ^NSString *(NSDictionary *data, BOOL *needUpdate) {
-                NSMutableArray *newArray = [attributeOrStyle mutableCopy];
-                [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+            bindingMap[name] = ^id(NSDictionary *data, BOOL *needUpdate) {
+                NSMutableArray *newArray = [binding mutableCopy];
+                [binding enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                     BOOL _needUpdate = NO;
                     WXDataBindingBlock block = bindingBlocksForIndex[@(idx)];
                     if (block) {
@@ -221,21 +275,21 @@ static JSContext *jsContext;
                     }
                 }];
                 
-                return [newArray componentsJoinedByString:@""];
+                return type == WXDataBindingTypeEvents ? newArray : [newArray componentsJoinedByString:@""];
             };
         }
         
         if (type == WXDataBindingTypeAttributes) {
-            if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName]) {
-                WXJSASTParser *parser = [WXJSASTParser parserWithScript:attributeOrStyle];
+            if ([WXBindingMatchIdentify isEqualToString:name]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:binding];
                 WXJSExpression *expression = [parser parseExpression];
                 _bindingMatch = [self bindingBlockWithExpression:expression];
-            } else if ([WXBindingRepeatIdentify isEqualToString:attributeOrStyleName]) {
-                WXJSASTParser *parser = [WXJSASTParser parserWithScript:attributeOrStyle[WXBindingRepeatExprIdentify]];
+            } else if ([WXBindingRepeatIdentify isEqualToString:name]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:binding[WXBindingRepeatExprIdentify]];
                 WXJSExpression *expression = [parser parseExpression];
                 _bindingRepeat = [self bindingBlockWithExpression:expression];
-                _repeatIndexIdentify = attributeOrStyle[WXBindingRepeatIndexIdentify];
-                _repeatLabelIdentify = attributeOrStyle[WXBindingRepeatLabelIdentify];
+                _repeatIndexIdentify = binding[WXBindingRepeatIndexIdentify];
+                _repeatLabelIdentify = binding[WXBindingRepeatLabelIdentify];
             }
         }
     }];
@@ -274,6 +328,7 @@ static JSContext *jsContext;
             id object = [self bindingBlockWithExpression:member->object](data, &objectNeedUpdate);
             if (member->computed) {
                 id propertyName = [self bindingBlockWithExpression:member->property](data, &propertyNeedUpdate);
+                *needUpdate = objectNeedUpdate || propertyNeedUpdate;
                 if ([object isKindOfClass:[NSDictionary class]] && [propertyName isKindOfClass:[NSString class]]) {
                     return object[propertyName];
                 } else if ([object isKindOfClass:[NSArray class]] && [propertyName isKindOfClass:[NSNumber class]]) {
@@ -281,10 +336,32 @@ static JSContext *jsContext;
                 }
             } else {
                 NSString *propertyName = [NSString stringWithCString:(((WXJSStringLiteral *)member->property)->value).c_str() encoding:[NSString defaultCStringEncoding]];
+                *needUpdate = objectNeedUpdate;
                 return object[propertyName];
             }
             
             return nil;
+        } else if (expression->is<WXJSArrayExpression>()) {
+            WXJSArrayExpression *expr = (WXJSArrayExpression *)expression;
+            std::vector<WXJSExpression *> expressions = expr->expressions;
+            NSMutableArray *array = [NSMutableArray array];
+            for(WXJSExpression *expr : expressions) {
+                if (expr == NULL) {
+                    continue;
+                }
+                WXDataBindingBlock block = [self bindingBlockWithExpression:expr];
+                *needUpdate = NO;
+                if (block) {
+                    BOOL elementNeedUpdate;
+                    id object = block(data, &elementNeedUpdate);
+                    if (object) {
+                        *needUpdate = *needUpdate || elementNeedUpdate;
+                        [array addObject:object];
+                    }
+                }
+            }
+            
+            return array;
         } else if (expression->is<WXJSUnaryExpression>()) {
             WXJSUnaryExpression *expr = (WXJSUnaryExpression *)expression;
             std::string operator_ = expr->operator_;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
index 597aa99..76ebff3 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
@@ -19,6 +19,7 @@
 
 #import <Foundation/Foundation.h>
 #include <string>
+#include <vector>
 
 typedef enum : NSUInteger {
     WXJSExpressionTypeUnary,
@@ -61,6 +62,10 @@ struct WXJSMemberExpression : WXJSExpression {
     bool computed;
 };
 
+struct WXJSArrayExpression : WXJSExpression {
+    std::vector<WXJSExpression *> expressions;
+};
+
 struct WXJSUnaryExpression : WXJSExpression {
     std::string operator_;
     bool prefix;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
index eaa8394..7e7a565 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
@@ -762,6 +762,13 @@ static int binaryPrecedence(WXJSToken *token)
 {
     int type = _lookahead->type;
     
+    if (type == WXJSTokenTypePunctuator) {
+        if (_lookahead->value == "[") {
+            return [self parseArrayExpression];
+        } else if (_lookahead->value == "(") {
+            return [self parseGroupExpression];
+        }
+    }
     if (type == WXJSTokenTypeIdentifier) {
         WXJSIdentifier *identifier = new WXJSIdentifier();
         identifier->name = [self nextToken]->value;
@@ -776,6 +783,45 @@ static int binaryPrecedence(WXJSToken *token)
     }
 }
 
+- (WXJSArrayExpression *)parseArrayExpression
+{
+    std::vector<WXJSExpression *> expressions;
+    
+    [self expect:"["];
+    
+    while (![self match:"]"]) {
+        if ([self match:","]) {
+            [self nextToken];
+            expressions.push_back(NULL);
+        } else {
+            expressions.push_back([self parseConditionalExpression]);
+            
+            if (![self match:"]"]) {
+                [self expect:","];
+            }
+        }
+    }
+    
+    [self expect:"]"];
+    
+    WXJSArrayExpression *array = new WXJSArrayExpression();
+    array->expressions = expressions;
+    
+    return array;
+}
+
+- (WXJSExpression *)parseGroupExpression
+{
+    WXJSExpression *expr;
+    [self expect:"("];
+    
+    expr = [self parseConditionalExpression];
+    
+    [self expect:")"];
+    
+    return expr;
+}
+
 
 - (WXJSExpression *)parseMemberExpression
 {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
index 0e038a7..a072752 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
@@ -18,8 +18,8 @@
  */
 
 #import <Foundation/Foundation.h>
-#import "WXComponent.h"
+#import "WXScrollerComponent.h"
 
-@interface WXRecycleListComponent : WXComponent <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
+@interface WXRecycleListComponent : WXScrollerComponent 
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
index 4d119c2..71a52f5 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
@@ -24,12 +24,13 @@
 #import "WXSDKInstance_private.h"
 
 #import "WXCellSlotComponent.h"
+#import "WXRecycleListLayout.h"
 #import "WXRecycleListComponent.h"
 #import "WXRecycleListDataManager.h"
 #import "WXRecycleListTemplateManager.h"
 #import "WXRecycleListUpdateManager.h"
 
-@interface WXRecycleListComponent ()
+@interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
 
 @end
 
@@ -40,11 +41,23 @@
     WXRecycleListUpdateManager *_updateManager;
     
     NSString *_templateKey;
+    NSString *_aliasKey;
+    NSString *_indexKey;
     __weak UICollectionView *_collectionView;
     
     NSMutableDictionary *_sizeCache;
+    NSMutableDictionary *_stickyCache;
+    
+    NSUInteger _previousLoadMoreCellNumber;
 }
 
+WX_EXPORT_METHOD(@selector(appendData:))
+WX_EXPORT_METHOD(@selector(insertData:atIndex:))
+WX_EXPORT_METHOD(@selector(updateData:atIndex:))
+WX_EXPORT_METHOD(@selector(removeData:))
+WX_EXPORT_METHOD(@selector(moveData:toIndex:))
+WX_EXPORT_METHOD(@selector(scrollTo:options:))
+
 - (instancetype)initWithRef:(NSString *)ref
                        type:(NSString *)type
                      styles:(NSDictionary *)styles
@@ -56,8 +69,12 @@
         _dataManager = [[WXRecycleListDataManager alloc] initWithData:attributes[@"listData"]];
         _templateManager = [WXRecycleListTemplateManager new];
         _updateManager = [WXRecycleListUpdateManager new];
+        _updateManager.delegate = self;
         _templateKey = [WXConvert NSString:attributes[@"templateKey"]] ? : @"templateType";
+        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
+        _indexKey = [WXConvert NSString:attributes[@"index"]];
         _sizeCache = [NSMutableDictionary dictionary];
+        _stickyCache = [NSMutableDictionary dictionary];
     }
     
     return self;
@@ -67,7 +84,11 @@
 
 - (UIView *)loadView
 {
-    UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
+    WXRecycleListLayout *layout = [WXRecycleListLayout new];
+    layout.delegate = self;
+    // to show cells that original width / height is zero, otherwise cellForItemAtIndexPath will not be called
+    layout.minimumLineSpacing = 0.01;
+    layout.minimumInteritemSpacing = 0.01;
     return [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
 }
 
@@ -83,7 +104,6 @@
     
     _templateManager.collectionView = _collectionView;
     _updateManager.collectionView = _collectionView;
-//    [_updateManager reload];
 }
 
 - (void)viewWillUnload
@@ -94,6 +114,38 @@
     _collectionView.delegate = nil;
 }
 
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    if (attributes[@"listData"]) {
+        NSArray *listData = attributes[@"listData"];
+        [self _updateListData:listData withCompletion:nil animation:NO];
+    }
+}
+
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component
+{
+    CGPoint position = CGPointZero;
+    UIView *view = component->_view;
+    while (view) {
+        if ([view isKindOfClass:[UICollectionViewCell class]]) {
+            NSIndexPath *indexPath = [_collectionView indexPathForCell:(UICollectionViewCell *)view];
+            if (!indexPath) {
+                return CGPointMake(NAN, NAN);
+            }
+            UICollectionViewLayoutAttributes *attributes = [_collectionView layoutAttributesForItemAtIndexPath:indexPath];
+            CGPoint cellOrigin = attributes.frame.origin;
+            position = CGPointMake(position.x + cellOrigin.x,
+                                   position.y + cellOrigin.y);
+            break;
+        }
+        position = CGPointMake(position.x + view.frame.origin.x,
+                               position.y + view.frame.origin.y);
+        view = view.superview;
+    }
+    
+    return position;
+}
+
 - (void)setContentSize:(CGSize)contentSize
 {
     // Do Nothing
@@ -104,6 +156,119 @@
     // Do Nothing, sticky is adjusted by layout
 }
 
+#pragma mark - Load More Event
+
+- (void)loadMore
+{
+    [super loadMore];
+    
+    _previousLoadMoreCellNumber = [_collectionView numberOfItemsInSection:0];
+}
+
+- (BOOL)isNeedLoadMore
+{
+    BOOL superNeedLoadMore = [super isNeedLoadMore];
+    return superNeedLoadMore && _previousLoadMoreCellNumber != [_collectionView numberOfItemsInSection:0];
+}
+
+- (void)resetLoadmore
+{
+    [super resetLoadmore];
+    _previousLoadMoreCellNumber = 0;
+}
+
+#pragma mark - Exported Component Methods
+
+- (void)appendData:(NSArray *)appendingData
+{
+    if (![appendingData isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of appending data:%@", appendingData);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithAppendingData:appendingData oldData:oldData completion:nil animation:NO];
+}
+
+- (void)insertData:(id)data atIndex:(NSUInteger)index
+{
+    // TODO: bring the update logic to UpdateManager
+    // TODO: update cell because index has changed
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index <= newListData.count) {
+        [newListData insertObject:data atIndex:index];
+        [_dataManager updateData:newListData];
+        
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        
+        [UIView performWithoutAnimation:^{
+            [_collectionView insertItemsAtIndexPaths:@[indexPath]];
+        }];
+    }
+}
+
+- (void)updateData:(id)data atIndex:(NSUInteger)index
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index < newListData.count) {
+        newListData[index] = data;
+        [_dataManager updateData:newListData];
+        
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        UICollectionViewCell *cellView = [_collectionView cellForItemAtIndexPath:indexPath];
+        WXCellSlotComponent *cellComponent = (WXCellSlotComponent *)cellView.wx_component;
+        if (cellComponent) {
+            [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
+        }
+    }
+}
+
+- (void)removeData:(NSArray *)indexes
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    NSMutableIndexSet *indexSet = [NSMutableIndexSet new];
+    NSMutableArray *indexPaths = [NSMutableArray array];
+    for (NSNumber *index in indexes) {
+        if ([index unsignedIntegerValue] >= newListData.count) {
+            WXLogError(@"invalid remove index:%@", index);
+            continue;
+        }
+        [indexSet addIndex:[index unsignedIntegerValue]];
+        [indexPaths addObject:[NSIndexPath indexPathForItem:[index unsignedIntegerValue] inSection:0]];
+    }
+    
+    [newListData removeObjectsAtIndexes:indexSet];
+    [_dataManager updateData:newListData];
+    [UIView performWithoutAnimation:^{
+        [_collectionView deleteItemsAtIndexPaths:indexPaths];
+    }];
+}
+
+- (void)moveData:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    id data = newListData[fromIndex];
+    [newListData removeObjectAtIndex:fromIndex];
+    [newListData insertObject:data atIndex:toIndex];
+    [_dataManager updateData:newListData];
+    
+    NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:fromIndex inSection:0];
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:toIndex inSection:0];
+    [UIView performWithoutAnimation:^{
+        [_collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
+    }];
+}
+
+- (void)scrollTo:(NSUInteger)index options:(NSDictionary *)options
+{
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:index inSection:0];
+    BOOL animated = options[@"animated"] ? [WXConvert BOOL:options[@"animated"]] : NO;
+    [_collectionView scrollToItemAtIndexPath:toIndexPath atScrollPosition:UICollectionViewScrollPositionTop animated:animated];
+}
+
 #pragma mark - WXComonent Internal Methods
 
 - (void)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index
@@ -120,6 +285,56 @@
     }
 }
 
+#pragma mark - Private
+
+- (void)_updateBindingData:(NSDictionary *)data forCell:(WXCellSlotComponent *)cellComponent atIndexPath:(NSIndexPath *)indexPath
+{
+    if (_aliasKey) {
+        data = @{_aliasKey:data};
+    }
+    if (_indexKey) {
+        NSMutableDictionary *dataNew = [data mutableCopy];
+        dataNew[_indexKey] = @(indexPath.item);
+        data = dataNew;
+    }
+    
+#ifdef DEBUG
+    NSDate *startTime = [NSDate date];
+#endif
+    WXPerformBlockSyncOnComponentThread(^{
+        [cellComponent updateCellData:data];
+    });
+#ifdef DEBUG
+    double duration = -[startTime timeIntervalSinceNow] * 1000;
+    WXLogDebug(@"cell:%zi update data time:%f", indexPath.item, duration);
+#endif
+    
+    NSValue *cachedSize = _sizeCache[indexPath];
+    if (!cachedSize || !CGSizeEqualToSize([cachedSize CGSizeValue] , cellComponent.calculatedFrame.size)) {
+        _sizeCache[indexPath] = [NSValue valueWithCGSize:cellComponent.calculatedFrame.size];
+        [_collectionView.collectionViewLayout invalidateLayout];
+    }
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    BOOL isSticky = cellComponent->_positionType == WXPositionTypeSticky;
+    if (!cachedSticky || [cachedSticky boolValue] != isSticky) {
+        _stickyCache[indexPath] = @(isSticky);
+    }
+}
+
+- (void)_updateListData:(NSArray *)newData
+        withCompletion:(WXRecycleListUpdateCompletion)completion
+             animation:(BOOL)animation
+{
+    if (![newData isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of list data:%@", newData);
+        completion(NO);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithNewData:newData oldData:oldData completion:completion animation:animation];
+}
+
 #pragma mark - UICollectionViewDataSource
 
 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
@@ -137,7 +352,7 @@
     // 1. get the data relating to the cell
     NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
     if (!data || ![data isKindOfClass:[NSDictionary class]]) {
-        WXLogError(@"No data or wrong data format for index:%zd, data:%@", indexPath.row, data);
+        WXLogError(@"No data or wrong data format for index:%zd, data:%@", indexPath.item, data);
         return nil;
     }
     
@@ -160,21 +375,9 @@
         });
     }
     
-    
     // 4. binding the data to the cell component
-    WXPerformBlockOnComponentThread(^{
-        [cellComponent updateCellData:data];
-        WXPerformBlockOnMainThread(^{
-            NSValue *cacheSize = _sizeCache[indexPath];
-            if (!cacheSize || !CGSizeEqualToSize([cacheSize CGSizeValue] , cellComponent.calculatedFrame.size)) {
-                _sizeCache[indexPath] = [NSValue valueWithCGSize:cellComponent.calculatedFrame.size];
-                [UIView performWithoutAnimation:^{
-                    [_collectionView reloadItemsAtIndexPaths:@[indexPath]];
-                }];
-            }
-        });
-    });
-    
+    [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
+
     // 5. Add cell component's view to content view.
     UIView *contentView = cellComponent.view;
     if (contentView.superview == cellView.contentView) {
@@ -187,6 +390,12 @@
     [cellView.contentView addSubview:contentView];
     [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
     
+    WXLogDebug(@"Return cell view:%@, indexPath:%@", cellView, indexPath);
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [self handleAppear];
+    });
+    
     return cellView;
 }
 
@@ -208,6 +417,7 @@
 }
 
 #pragma mark - UICollectionViewDelegateFlowLayout
+
 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
 {
     NSValue *size = _sizeCache[indexPath];
@@ -218,8 +428,32 @@
         WXCellSlotComponent *cell = [_templateManager templateWithType:data[_templateKey]];
         CGSize size = cell.calculatedFrame.size;
         _sizeCache[indexPath] = [NSValue valueWithCGSize:size];
-        return size;
+        return CGSizeMake(_collectionView.frame.size.width, size.height);
     }
 }
 
+#pragma mark - WXRecycleListLayoutDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout isNeedStickyForIndexPath:(NSIndexPath *)indexPath
+{
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    if (cachedSticky) {
+        return [cachedSticky boolValue];
+    } else {
+        return NO;
+    }
+}
+
+#pragma mark - WXRecycleListUpdateDelegate
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager willUpdateData:(id)newData
+{
+    [_dataManager updateData:newData];
+}
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager didUpdateData:(id)newData withSuccess:(BOOL)finished
+{
+    
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
index c340f9d..fc053c5 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
@@ -25,6 +25,8 @@
 
 - (void)updateData:(NSArray *)data;
 
+- (NSArray *)data;
+
 - (NSDictionary *)dataAtIndex:(NSInteger)index;
 
 - (NSInteger)numberOfItems;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
index 49ed216..8d27171 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
@@ -47,6 +47,13 @@
     _data = data;
 }
 
+- (NSArray *)data
+{
+    WXAssertMainThread();
+    
+    return _data;
+}
+
 - (NSDictionary *)dataAtIndex:(NSInteger)index
 {
     WXAssertMainThread();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
new file mode 100644
index 0000000..04e65ea
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
@@ -0,0 +1,21 @@
+//
+//  WXRecycleListLinearLayout.h
+//  WeexSDK
+//
+//  Created by yinfeng on 2017/9/19.
+//  Copyright Ā© 2017幓 taobao. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@protocol WXRecycleListLayoutDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout isNeedStickyForIndexPath:(NSIndexPath *)indexPath;
+
+@end
+
+@interface WXRecycleListLayout : UICollectionViewFlowLayout
+
+@property (nonatomic, weak) id<WXRecycleListLayoutDelegate> delegate;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
new file mode 100644
index 0000000..e5bc8c3
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
@@ -0,0 +1,102 @@
+//
+//  WXRecycleListLinearLayout.m
+//  WeexSDK
+//
+//  Created by yinfeng on 2017/9/19.
+//  Copyright Ā© 2017幓 taobao. All rights reserved.
+//
+
+#import "WXRecycleListLayout.h"
+
+@implementation WXRecycleListLayout
+{
+    NSMutableDictionary<NSNumber *, UICollectionViewLayoutAttributes *> *_stickyCellsAttributes;
+}
+
+- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
+{
+    NSArray *cellAttributes = [super layoutAttributesForElementsInRect:rect];
+    NSMutableDictionary *lastCellsAttributes = [NSMutableDictionary dictionary];
+    
+    __block NSInteger currentStickyIndex = -1;
+    [cellAttributes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        UICollectionViewLayoutAttributes *attributes = obj;
+        NSIndexPath *indexPath = attributes.indexPath;
+        if ([self.delegate collectionView:self.collectionView layout:self isNeedStickyForIndexPath:indexPath]) {
+            if (!_stickyCellsAttributes) {
+                _stickyCellsAttributes = [NSMutableDictionary dictionary];
+            }
+            
+            currentStickyIndex = indexPath.item;
+            [_stickyCellsAttributes setObject:attributes forKey:@(indexPath.item)];
+        } else {
+            [_stickyCellsAttributes removeObjectForKey:@(indexPath.item)];
+            
+            // bottom cell above sticky cell
+            UICollectionViewLayoutAttributes *currentLastCell = [lastCellsAttributes objectForKey:@(currentStickyIndex)];
+            if (!currentLastCell || indexPath.item > currentLastCell.indexPath.item) {
+                [lastCellsAttributes setObject:obj forKey:@(currentStickyIndex)];
+            }
+        }
+        
+        attributes.zIndex = 1;
+    }];
+    
+    NSMutableArray *newCellAttributes = [cellAttributes mutableCopy];
+    [lastCellsAttributes enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
+        UICollectionViewLayoutAttributes *attributes = obj;
+        
+        UICollectionViewLayoutAttributes *stickyCell = _stickyCellsAttributes[key];
+        if (!stickyCell) {
+            NSInteger item = attributes.indexPath.item;
+            while (item >= 0) {
+                if (_stickyCellsAttributes[@(item)]) {
+                    stickyCell = [self.collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:item inSection:0]];
+                    break;
+                } else {
+                    item --;
+                }
+            }
+        }
+        
+        if (stickyCell) {
+            [newCellAttributes addObject:stickyCell];
+            [self _adjustStickyForCellAttributes:stickyCell lastCellAttributes:attributes];
+        }
+    }];
+    
+    return newCellAttributes;
+}
+
+- (void)_adjustStickyForCellAttributes:(UICollectionViewLayoutAttributes *)cell
+                    lastCellAttributes:(UICollectionViewLayoutAttributes *)lastCell
+{
+    cell.zIndex = 99;
+    cell.hidden = NO;
+    
+    CGFloat maxY = CGRectGetMaxY(lastCell.frame) - cell.frame.size.height;
+    CGFloat minY = CGRectGetMinY(self.collectionView.bounds) + self.collectionView.contentInset.top;
+    CGFloat y = MIN(MAX(minY, cell.frame.origin.y), maxY);
+
+//    NSLog(@"%zi : %zi, %.1f, %.1f, %.1f, %.1f", cell.indexPath.item, lastCell.indexPath.item, maxY, minY, cell.frame.origin.y, y);
+    
+    CGPoint origin = cell.frame.origin;
+    origin.y = y;
+    
+    cell.frame = (CGRect){
+        origin,
+        cell.frame.size
+    };
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
+{
+    if (_stickyCellsAttributes.count > 0) {
+        // always return yes to trigger resetting sticky header's frame.
+        return YES;
+    }
+    
+    return [super shouldInvalidateLayoutForBoundsChange:newBounds];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
index 0ac528e..87ecd90 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
@@ -87,7 +87,7 @@
 - (void)_registerCellClassForReuseID:(NSString *)templateID
 {
     WXLogDebug(@"register cell class for template id:%@", templateID);
-    //TODO: register class updateTemplateId
+    //TODO: register class update TemplateId
     [_collectionView registerClass:[WXReusableCollectionViewCell class] forCellWithReuseIdentifier:templateID];
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
index c96bbcd..1753b2b 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
@@ -19,10 +19,32 @@
 
 #import <Foundation/Foundation.h>
 
+typedef void(^WXRecycleListUpdateCompletion)(BOOL isFinished);
+@class WXRecycleListUpdateManager;
+
+@protocol WXRecycleListUpdateDelegate
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager willUpdateData:(id)newData;
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager didUpdateData:(id)newData withSuccess:(BOOL)finished;
+
+@end
+
 @interface WXRecycleListUpdateManager : NSObject
 
 @property (nonatomic, weak) UICollectionView *collectionView;
+@property (nonatomic, weak) id<WXRecycleListUpdateDelegate> delegate;
 
 - (void)reload;
 
+- (void)updateWithNewData:(NSArray *)newData
+                  oldData:(NSArray *)oldData
+               completion:(WXRecycleListUpdateCompletion)completion
+                animation:(BOOL)isAnimated;
+
+- (void)updateWithAppendingData:(NSArray *)appendingData
+                        oldData:(NSArray *)oldData
+                     completion:(WXRecycleListUpdateCompletion)completion
+                      animation:(BOOL)isAnimated;
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
index 1395607..7ad4caa 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
@@ -18,12 +18,245 @@
  */
 
 #import "WXRecycleListUpdateManager.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+#import "WXDiffUtil.h"
+
+@interface WXRecycleListDiffResult : NSObject
+
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *deleteIndexPaths;
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *insertIndexPaths;
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *reloadIndexPaths;
+
+- (BOOL)hasChanges;
+
+@end
+
+@implementation WXRecycleListDiffResult
+
+- (instancetype)initWithInsertIndexPaths:(NSMutableSet<NSIndexPath *> *)insertIndexPaths
+                        deleteIndexPaths:(NSMutableSet<NSIndexPath *> *)deleteIndexPaths
+                        reloadIndexPaths:(NSMutableSet<NSIndexPath *> *)reloadIndexPaths
+{
+    if (self = [super init]) {
+        _insertIndexPaths = [insertIndexPaths copy];
+        _deleteIndexPaths = [deleteIndexPaths copy];
+        _reloadIndexPaths = [reloadIndexPaths copy];
+    }
+    
+    return self;
+}
+
+- (BOOL)hasChanges
+{
+    return _insertIndexPaths.count > 0 || _deleteIndexPaths.count > 0 || _reloadIndexPaths.count > 0;
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@: %p; insert index paths: %@; delete index paths: %@; reload index paths: %@", NSStringFromClass([self class]), self, _insertIndexPaths, _deleteIndexPaths, _reloadIndexPaths];
+}
+
+@end
+
+@interface WXRecycleListUpdateManager ()
+
+@property (nonatomic, copy) NSArray *newerData;
+@property (nonatomic, copy) NSArray *appendingData;
+@property (nonatomic, copy) NSArray *olderData;
+@property (nonatomic, assign) BOOL isUpdating;
+@property (nonatomic, strong) NSMutableArray *completions;
+
+@property (nonatomic, strong) NSMutableSet<NSIndexPath *> *reloadIndexPaths;
+
+@end
 
 @implementation WXRecycleListUpdateManager
 
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _completions = [NSMutableArray array];
+    }
+    
+    return self;
+}
+
 - (void)reload
 {
     [_collectionView reloadData];
 }
 
+- (void)updateWithNewData:(NSArray *)newData
+                  oldData:(NSArray *)oldData
+               completion:(WXRecycleListUpdateCompletion)completion
+                animation:(BOOL)isAnimated
+{
+    WXAssertMainThread();
+    
+    if (!_collectionView) {
+        WXLogError(@"Update list with no collection view");
+        completion(NO);
+        return;
+    }
+    
+    self.newerData = newData;
+    self.appendingData = nil;
+    self.olderData = oldData;
+    
+    if (completion) {
+        [_completions addObject:completion];
+    }
+    
+    [self checkUpdates];
+}
+
+- (void)updateWithAppendingData:(NSArray *)appendingData
+                        oldData:(NSArray *)oldData
+                     completion:(WXRecycleListUpdateCompletion)completion
+                      animation:(BOOL)isAnimated
+{
+    if (!_collectionView) {
+        WXLogError(@"Update list with no collection view");
+        completion(NO);
+        return;
+    }
+    
+    self.appendingData = appendingData;
+    self.olderData = oldData;
+    
+    if (completion) {
+        [_completions addObject:completion];
+    }
+    
+    [self checkUpdates];
+}
+
+
+- (void)checkUpdates
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (self.isUpdating) {
+            return ;
+        }
+        
+        [self performBatchUpdates];
+    });
+}
+
+- (void)performBatchUpdates
+{
+    WXAssertMainThread();
+    WXAssert(!self.isUpdating, @"Can not perform updates while an updating is being performed");
+    
+    UICollectionView *collectionView = self.collectionView;
+    if (!collectionView) {
+        return;
+    }
+    
+    NSArray *newData = [self.newerData copy];
+    NSArray *oldData = [self.olderData copy];
+    NSArray *appendingData = [self.appendingData copy];
+    //TODO use completionBlocks
+//    NSArray *completionBlocks = [self.completions copy];
+    
+    [self cleanup];
+    
+    WXDiffResult *diffResult;
+    if (appendingData) {
+        newData = [oldData arrayByAddingObjectsFromArray:appendingData];
+        NSIndexSet *inserts = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(oldData.count, appendingData.count)];
+        diffResult = [[WXDiffResult alloc] initWithInserts:inserts deletes:nil updates:nil];
+    } else if (newData){
+        diffResult = [WXDiffUtil diffWithMinimumDistance:newData oldArray:oldData];
+    }
+    
+    WXRecycleListDiffResult *recycleListDiffResult = [self recycleListUpdatesByDiffResult:diffResult];
+    
+    if (![diffResult hasChanges] && self.reloadIndexPaths.count == 0) {
+        return;
+    }
+    
+    void (^updates)() = [^{
+        [self.delegate updateManager:self willUpdateData:newData];
+        [UIView setAnimationsEnabled:NO];
+        NSLog(@"UICollectionView update:%@", recycleListDiffResult);
+        [self applyUpdateWithDiffResult:recycleListDiffResult];
+    } copy];
+    
+    void (^completion)(BOOL) = [^(BOOL finished) {
+        [UIView setAnimationsEnabled:YES];
+        self.isUpdating = NO;
+        [self.delegate updateManager:self didUpdateData:newData withSuccess:finished];
+        
+        [self.reloadIndexPaths removeAllObjects];
+        [self checkUpdates];
+    } copy];
+    
+    self.isUpdating = YES;
+    
+    if (!self.delegate || !collectionView.dataSource) {
+        return;
+    }
+    
+    [collectionView performBatchUpdates:updates completion:completion];
+}
+
+- (WXRecycleListDiffResult *)recycleListUpdatesByDiffResult:(WXDiffResult *)diffResult
+{
+    NSMutableSet<NSIndexPath *> *reloadIndexPaths = [NSMutableSet set];
+    NSMutableSet<NSIndexPath *> *deleteIndexPaths = [NSMutableSet set];
+    NSMutableSet<NSIndexPath *> *insertIndexPaths = [NSMutableSet set];
+    
+    for (WXDiffUpdateIndex *update in diffResult.updates) {
+        NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0];
+        [reloadIndexPaths addObject:reloadIndexPath];
+    }
+    
+    [diffResult.updates enumerateObjectsUsingBlock:^(WXDiffUpdateIndex * _Nonnull update, NSUInteger idx, BOOL * _Nonnull stop) {
+        NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0];
+        [reloadIndexPaths addObject:reloadIndexPath];
+    }];
+    
+    [diffResult.inserts enumerateIndexesUsingBlock:^(NSUInteger insertIndex, BOOL * _Nonnull stop) {
+        NSIndexPath *insertIndexPath = [NSIndexPath indexPathForItem:insertIndex inSection:0];
+        [insertIndexPaths addObject:insertIndexPath];
+    }];
+    
+    [diffResult.deletes enumerateIndexesUsingBlock:^(NSUInteger deleteIndex, BOOL * _Nonnull stop) {
+        NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForItem:deleteIndex inSection:0];
+        [deleteIndexPaths addObject:deleteIndexPath];
+    }];
+    
+    WXRecycleListDiffResult *result = [[WXRecycleListDiffResult alloc] initWithInsertIndexPaths:insertIndexPaths deleteIndexPaths:deleteIndexPaths reloadIndexPaths:reloadIndexPaths];
+    
+    return result;
+}
+
+
+- (void)applyUpdateWithDiffResult:(WXRecycleListDiffResult *)diffResult
+{
+    if (!_collectionView) {
+        return;
+    }
+    
+    // reload index paths should not inculde delete index paths, otherwise it will cause crash:
+    // Assertion failure in
+    // -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:]
+    NSMutableSet *reloadIndexPaths = self.reloadIndexPaths ? [[diffResult.reloadIndexPaths setByAddingObjectsFromSet:self.reloadIndexPaths] mutableCopy]: [diffResult.reloadIndexPaths mutableCopy];
+    [reloadIndexPaths minusSet:diffResult.deleteIndexPaths];
+    
+    [_collectionView deleteItemsAtIndexPaths:[diffResult.deleteIndexPaths allObjects]];
+    [_collectionView insertItemsAtIndexPaths:[diffResult.insertIndexPaths allObjects]];
+    [_collectionView reloadItemsAtIndexPaths:[reloadIndexPaths allObjects]];
+}
+
+- (void)cleanup
+{
+    self.newerData = nil;
+    self.appendingData = nil;
+    self.olderData = nil;
+    [self.completions removeAllObjects];
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
index af1f760..1bc7d23 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
@@ -65,7 +65,7 @@
     return [super hash];
 }
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
 {
     if ([object isKindOfClass:[WXSectionDataController class]]) {
         WXSectionDataController *controller = (WXSectionDataController *)object;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
index 0902eab..07621c7 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -56,7 +56,7 @@
     
 }
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
 {
     return self == object;
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 1b0f784..98c100d 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -145,8 +145,12 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
     BOOL _isRepeating;
     BOOL _isSkipUpdate;
     
-    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingAttributes;
-    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingStyles;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingProps;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingAttributes;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingStyles;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingEvents;
+    
+    NSMutableDictionary<NSString *, NSArray *> *_eventParameters;
 }
 
 ///--------------------------------------
@@ -222,6 +226,10 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 - (void)_removeAllEvents;
 
+- (void)_addEventParams:(NSDictionary *)params;
+
+- (NSArray *)_paramsForEvent:(NSString *)eventName;
+
 - (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles attributes:(NSMutableDictionary *)attributes;
 
 - (void)_initCompositingAttribute:(NSDictionary *)attributes;
@@ -242,7 +250,7 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 - (void)setGradientLayer;
 
-- (void)_storeBindingsWithStyles:(NSDictionary *)styles attributes:(NSDictionary *)attributes;
+- (void)_storeBindingsWithProps:(NSDictionary *)props styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSDictionary *)events;
 
 - (void)_didInserted;
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
index 39bf0d7..db0c155 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
@@ -34,5 +34,7 @@
 
 - (void)handleAppear;
 
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component;
+
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
index a960cc6..306631b 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
@@ -566,25 +566,30 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     }
 }
 
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component
+{
+    return [component->_view.superview convertPoint:component->_view.frame.origin toView:_view];
+}
+
 #pragma mark  Private Methods
 
 - (void)scrollToTarget:(WXScrollToTarget *)target scrollRect:(CGRect)rect
 {
     WXComponent *component = target.target;
-    if (![component isViewLoaded]) {
+    if (![component isViewLoaded]) { 
         return;
     }
     
     CGFloat ctop;
     if (component && component->_view && component->_view.superview) {
-        ctop = [component->_view.superview convertPoint:component->_view.frame.origin toView:_view].y;
+        ctop = [self absolutePositionForComponent:component].y;
     } else {
         ctop = 0.0;
     }
     CGFloat cbottom = ctop + CGRectGetHeight(component.calculatedFrame);
     CGFloat cleft;
     if (component && component->_view && component->_view.superview) {
-        cleft = [component->_view.superview convertPoint:component->_view.frame.origin toView:_view].x;
+        cleft = [self absolutePositionForComponent:component].x;
     } else {
         cleft = 0.0;
     }
@@ -595,6 +600,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         if(!target.hasAppear && component){
             target.hasAppear = YES;
             if (component->_appearEvent) {
+//                NSLog(@"appear:%@, %.2f", component, ctop);
                 [component fireEvent:@"appear" params:_direction ? @{@"direction":_direction} : nil];
             }
         }
@@ -602,6 +608,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         if(target.hasAppear && component){
             target.hasAppear = NO;
             if(component->_disappearEvent){
+//                NSLog(@"disappear:%@", component);
                 [component fireEvent:@"disappear" params:_direction ? @{@"direction":_direction} : nil];
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
index d3dceb0..51e3fd6 100644
--- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
@@ -109,7 +109,10 @@
         [dict addEntriesFromDictionary:params];
     }
     
-    [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:self.ref type:eventName params:dict domChanges:domChanges];
+    NSArray *handlerArguments = [self _paramsForEvent:eventName];
+    NSString *ref = _templateComponent ? _templateComponent.ref  : self.ref;
+    
+    [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:ref type:eventName params:dict domChanges:domChanges handlerArguments:handlerArguments];
 }
 
 - (void)addEvent:(NSString *)addEventName

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
index fee0be7..7ff2e01 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -125,12 +125,23 @@ extern void WXPerformBlockOnBridgeThread(void (^block)());
  *  @param instanceId   instance id
  *  @param ref       :   node reference
  *  @param type      :   event type
- *  @param params    :   parameters
+ *  @param params    :   parameters in event object
  *  @param domChanges   dom value changes, used for two-way data binding
  **/
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges;
 
 /**
+ *  FireEvent
+ *  @param instanceId   instance id
+ *  @param ref       :   node reference
+ *  @param type      :   event type
+ *  @param params    :   parameters in event object
+ *  @param domChanges:   dom value changes, used for two-way data binding
+ *  @param eventArguments : arguments passed to event handler
+ **/
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments;
+
+/**
  *  callBack
  *
  *  @param instanceId instanceId

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index 0bf5aca..791aceb 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -304,12 +304,22 @@ void WXPerformBlockOnBridgeThread(void (^block)())
 
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges
 {
+    [self fireEvent:instanceId ref:ref type:type params:params domChanges:domChanges handlerArguments:nil];
+}
+
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments
+{
     if (!type || !ref) {
         WXLogError(@"Event type and component ref should not be nil");
         return;
     }
     
     NSArray *args = @[ref, type, params?:@{}, domChanges?:@{}];
+    if (handlerArguments) {
+        NSMutableArray *newArgs = [args mutableCopy];
+        [newArgs addObject:@{@"params":handlerArguments}];
+        args = newArgs;
+    }
     WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
     
     WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
index 387e3d0..ff5182c 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -29,6 +29,7 @@ extern "C" {
 #endif
     
 void WXPerformBlockOnComponentThread(void (^block)());
+void WXPerformBlockSyncOnComponentThread(void (^block)());
     
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
index bfd96eb..fa42445 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@ -136,6 +136,18 @@ static NSThread *WXComponentThread;
     }
 }
 
++ (void)_performBlockSyncOnComponentThread:(void (^)())block
+{
+    if([NSThread currentThread] == [self componentThread]){
+        block();
+    } else {
+        [self performSelector:@selector(_performBlockOnComponentThread:)
+                     onThread:WXComponentThread
+                   withObject:[block copy]
+                waitUntilDone:YES];
+    }
+}
+
 - (void)startComponentTasks
 {
     [self _awakeDisplayLink];
@@ -406,7 +418,9 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     NSDictionary *bindingStyles;
     NSDictionary *bindingAttibutes;
     NSDictionary *bindingEvents;
+    NSDictionary *bindingProps;
     if (isTemplate) {
+        bindingProps = [self _extractBindingProps:&attributes];
         bindingStyles = [self _extractBindings:&styles];
         bindingAttibutes = [self _extractBindings:&attributes];
         bindingEvents = [self _extractBindingEvents:&events];
@@ -417,7 +431,7 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     
     if (isTemplate) {
         component->_isTemplate = YES;
-        [component _storeBindingsWithStyles:bindingStyles attributes:bindingAttibutes];
+        [component _storeBindingsWithProps:bindingProps styles:bindingStyles attributes:bindingAttibutes events:bindingEvents];
     }
 
     WXAssert(component, @"Component build failed for data:%@", data);
@@ -480,7 +494,7 @@ static css_node_t * rootNodeGetChild(void *context, int i)
             NSString *eventName = event[@"type"];
             NSString *bindingParams = event[@"params"];
             bindingEvents[eventName] = bindingParams;
-            [newEvents removeObject:event];
+            newEvents[idx] = eventName;
         }
     }];
     
@@ -488,6 +502,19 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     return bindingEvents;
 }
 
+- (NSDictionary *)_extractBindingProps:(NSDictionary **)attributesPoint
+{
+    NSDictionary *attributes = *attributesPoint;
+    if (attributes[@"@componentProps"]) {
+        NSMutableDictionary *newAttributes = [attributes mutableCopy];
+        [newAttributes removeObjectForKey:@"@componentProps"];
+        *attributesPoint = newAttributes;
+        return attributes[@"@componentProps"];
+    }
+    
+    return nil;
+}
+
 #pragma mark Reset
 -(BOOL)isShouldReset:(id )value
 {
@@ -878,3 +905,8 @@ void WXPerformBlockOnComponentThread(void (^block)())
 {
     [WXComponentManager _performBlockOnComponentThread:block];
 }
+
+void WXPerformBlockSyncOnComponentThread(void (^block)())
+{
+    [WXComponentManager _performBlockSyncOnComponentThread:block];
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 76fb446..491e272 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -412,6 +412,26 @@
     return _cssNode;
 }
 
+- (void)_addEventParams:(NSDictionary *)params
+{
+    pthread_mutex_lock(&_propertyMutex);
+    if (!_eventParameters) {
+        _eventParameters = [NSMutableDictionary dictionary];
+    }
+    [_eventParameters addEntriesFromDictionary:params];
+    pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (NSArray *)_paramsForEvent:(NSString *)eventName
+{
+    NSArray *params;
+    pthread_mutex_lock(&_propertyMutex);
+    params = _eventParameters[eventName];
+    pthread_mutex_unlock(&_propertyMutex);
+    
+    return params;
+}
+
 #pragma mark Component Hierarchy 
 
 - (NSArray<WXComponent *> *)subcomponents

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
index f494247..8c7aee3 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
@@ -21,7 +21,7 @@
 
 @protocol WXDiffable <NSObject>
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object;
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object;
 
 @end
 
@@ -40,6 +40,10 @@
 
 - (BOOL)hasChanges;
 
+- (instancetype)initWithInserts:(NSIndexSet *)inserts
+                        deletes:(NSIndexSet *)deletes
+                        updates:(NSArray<WXDiffUpdateIndex *> *)updates;
+
 @end
 
 @interface WXDiffUtil : NSObject
@@ -47,3 +51,20 @@
 + (WXDiffResult *)diffWithMinimumDistance:(NSArray<id<WXDiffable>> *)newArray oldArray:(NSArray<id<WXDiffable>> *)oldArray;
 
 @end
+
+@interface NSNumber (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSString (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSArray (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSDictionary (WXDiffable) <WXDiffable>
+
+@end
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/74cc3b33/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
index 4b05df3..fabdbd1 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
@@ -96,7 +96,7 @@ typedef enum : NSUInteger {
     
     for (int oldIndex = 1; oldIndex < oldSize; oldIndex ++) {
         for (int newIndex = 1; newIndex < newSize; newIndex ++) {
-            if ([oldArray[oldIndex - 1] isEqualToWXObject:newArray[newIndex - 1]]) {
+            if ([oldArray[oldIndex - 1] weex_isEqualTo:newArray[newIndex - 1]]) {
                 matrix[oldIndex][newIndex] = matrix[oldIndex - 1][newIndex - 1];
             } else {
                 int updateCost = matrix[oldIndex - 1][newIndex - 1] + 1;
@@ -197,3 +197,85 @@ typedef enum : NSUInteger {
 }
 
 @end
+
+@implementation NSNumber (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    return [self isEqual:object];
+}
+
+@end
+
+@implementation NSString (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    return [self isEqual:object];
+}
+
+@end
+
+@implementation NSArray (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    if (![object isKindOfClass:[NSArray class]]) {
+        return NO;
+    }
+    
+    NSArray *array = (NSArray *)object;
+    if (self.count != array.count) {
+        return NO;
+    }
+    
+    __block BOOL isEqual = YES;
+    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        id obj2 = [self objectAtIndex:idx];
+        if ([obj conformsToProtocol:@protocol(WXDiffable)] && [obj2 conformsToProtocol:@protocol(WXDiffable)]) {
+            if (![obj weex_isEqualTo:obj2]) {
+                isEqual = NO;
+                *stop = YES;
+            }
+        } else {
+            isEqual = NO;
+            *stop = YES;
+        }
+    }];
+    
+    return isEqual;
+}
+
+@end
+
+@implementation NSDictionary (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    if (![object isKindOfClass:[NSDictionary class]]) {
+        return NO;
+    }
+    
+    NSDictionary *dictionary = (NSDictionary *)object;
+    if (self.count != dictionary.count) {
+        return NO;
+    }
+    
+    __block BOOL isEqual = YES;
+    [dictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
+        id obj2 = [self objectForKey:key];
+        if (obj2 && [obj2 conformsToProtocol:@protocol(WXDiffable)] && [obj conformsToProtocol:@protocol(WXDiffable)]) {
+            if (![obj weex_isEqualTo:obj2]) {
+                isEqual = NO;
+                *stop = YES;
+            }
+        } else {
+            isEqual = NO;
+            *stop = YES;
+        }
+    }];
+    
+    return isEqual;
+}
+
+@end


[15/17] incubator-weex git commit: * [ios] merge pull request

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
index c53d5f1..db26c93 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@ -20,6 +20,7 @@
 #import "WXComponentManager.h"
 #import "WXComponent.h"
 #import "WXComponent_internal.h"
+#import "WXComponent+DataBinding.h"
 #import "WXComponentFactory.h"
 #import "WXDefine.h"
 #import "NSArray+Weex.h"
@@ -135,6 +136,18 @@ static NSThread *WXComponentThread;
     }
 }
 
++ (void)_performBlockSyncOnComponentThread:(void (^)())block
+{
+    if([NSThread currentThread] == [self componentThread]){
+        block();
+    } else {
+        [self performSelector:@selector(_performBlockOnComponentThread:)
+                     onThread:WXComponentThread
+                   withObject:[block copy]
+                waitUntilDone:YES];
+    }
+}
+
 - (void)startComponentTasks
 {
     [self _awakeDisplayLink];
@@ -204,6 +217,15 @@ static NSThread *WXComponentThread;
     _rootComponent = [self _buildComponentForData:data supercomponent:nil];
     
     [self _initRootCSSNode];
+    
+    NSArray *subcomponentsData = [data valueForKey:@"children"];
+    if (subcomponentsData) {
+        BOOL appendTree = [_rootComponent.attributes[@"append"] isEqualToString:@"tree"];
+        for(NSDictionary *subcomponentData in subcomponentsData){
+            [self _recursivelyAddComponent:subcomponentData toSupercomponent:_rootComponent atIndex:-1 appendingInTree:appendTree];
+        }
+    }
+    
     __weak typeof(self) weakSelf = self;
     WX_MONITOR_INSTANCE_PERF_END(WXFirstScreenJSFExecuteTime, self.weexInstance);
     [self _addUITask:^{
@@ -213,6 +235,8 @@ static NSThread *WXComponentThread;
         [strongSelf.weexInstance.rootView addSubview:strongSelf->_rootComponent.view];
         [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] className:nil name:data[@"type"] phase:WXTracingEnd functionName:@"createBody" options:@{@"threadName":WXTUIThread}];
     }];
+    
+    
 }
 
 static bool rootNodeIsDirty(void *context)
@@ -259,14 +283,16 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     if(supercomponent && component && supercomponent->_lazyCreateView) {
         component->_lazyCreateView = YES;
     }
-
-    __weak typeof(self) weakSelf = self;
-    [self _addUITask:^{
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingBegin functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-        [supercomponent insertSubview:component atIndex:index];
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-    }];
-
+    
+    if (!component->_isTemplate) {
+        __weak typeof(self) weakSelf = self;
+        [self _addUITask:^{
+            [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingBegin functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
+            [supercomponent insertSubview:component atIndex:index];
+            [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:componentData[@"ref"] className:nil name:componentData[@"type"] phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
+        }];
+    }
+    
     NSArray *subcomponentsData = [componentData valueForKey:@"children"];
     
     BOOL appendTree = !appendingInTree && [component.attributes[@"append"] isEqualToString:@"tree"];
@@ -274,6 +300,9 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     for(NSDictionary *subcomponentData in subcomponentsData){
         [self _recursivelyAddComponent:subcomponentData toSupercomponent:component atIndex:-1 appendingInTree:appendTree || appendingInTree];
     }
+    
+    [component _didInserted];
+    
     if (appendTree) {
         // If appending treeļ¼Œforce layout in case of too much tasks piling up in syncQueue
         [self _layoutAndSyncUI];
@@ -384,9 +413,28 @@ static css_node_t * rootNodeGetChild(void *context, int i)
             }
         }
     }
-
-    Class clazz = [WXComponentFactory classWithComponentName:type];
+    
+    WXComponentConfig *config = [WXComponentFactory configWithComponentName:type];
+    BOOL isTemplate = [config.properties[@"isTemplate"] boolValue] || (supercomponent && supercomponent->_isTemplate);
+    NSDictionary *bindingStyles;
+    NSDictionary *bindingAttibutes;
+    NSDictionary *bindingEvents;
+    NSDictionary *bindingProps;
+    if (isTemplate) {
+        bindingProps = [self _extractBindingProps:&attributes];
+        bindingStyles = [self _extractBindings:&styles];
+        bindingAttibutes = [self _extractBindings:&attributes];
+        bindingEvents = [self _extractBindingEvents:&events];
+    }
+    
+    Class clazz = NSClassFromString(config.clazz);;
     WXComponent *component = [[clazz alloc] initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:self.weexInstance];
+    
+    if (isTemplate) {
+        component->_isTemplate = YES;
+        [component _storeBindingsWithProps:bindingProps styles:bindingStyles attributes:bindingAttibutes events:bindingEvents];
+    }
+
     WXAssert(component, @"Component build failed for data:%@", data);
     
     [_indexDict setObject:component forKey:component.ref];
@@ -394,6 +442,80 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     return component;
 }
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref
+{
+    [_indexDict setObject:component forKey:ref];
+}
+
+- (NSDictionary *)_extractBindings:(NSDictionary **)attributesOrStylesPoint
+{
+    NSDictionary *attributesOrStyles = *attributesOrStylesPoint;
+    if (!attributesOrStyles) {
+        return nil;
+    }
+    
+    NSMutableDictionary *newAttributesOrStyles = [attributesOrStyles mutableCopy];
+    NSMutableDictionary *bindingAttributesOrStyles = [NSMutableDictionary dictionary];
+    
+    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
+        if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName] // match
+            ||  [WXBindingRepeatIdentify isEqualToString:attributeOrStyleName] // repeat
+            || ([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify])) {  // {"attributeOrStyleName": {"@binding":"bindingExpression"}
+            bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
+            [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
+        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
+            // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
+            __block BOOL isBinding = NO;
+            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([obj isKindOfClass:[NSDictionary class]] && obj[WXBindingIdentify]) {
+                    isBinding = YES;
+                    *stop = YES;
+                }
+            }];
+            
+            if (isBinding) {
+                bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
+                [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
+            }
+        }
+    }];
+    
+    *attributesOrStylesPoint = newAttributesOrStyles;
+    
+    return bindingAttributesOrStyles;
+}
+
+- (NSDictionary *)_extractBindingEvents:(NSArray **)eventsPoint
+{
+    NSArray *events = *eventsPoint;
+    NSMutableArray *newEvents = [events mutableCopy];
+    NSMutableDictionary *bindingEvents = [NSMutableDictionary dictionary];
+    [events enumerateObjectsUsingBlock:^(id  _Nonnull event, NSUInteger idx, BOOL * _Nonnull stop) {
+        if ([event isKindOfClass:[NSDictionary class]] && event[@"type"] && event[@"params"]) {
+            NSString *eventName = event[@"type"];
+            NSString *bindingParams = event[@"params"];
+            bindingEvents[eventName] = bindingParams;
+            newEvents[idx] = eventName;
+        }
+    }];
+    
+    *eventsPoint = newEvents;
+    return bindingEvents;
+}
+
+- (NSDictionary *)_extractBindingProps:(NSDictionary **)attributesPoint
+{
+    NSDictionary *attributes = *attributesPoint;
+    if (attributes[@"@componentProps"]) {
+        NSMutableDictionary *newAttributes = [attributes mutableCopy];
+        [newAttributes removeObjectForKey:@"@componentProps"];
+        *attributesPoint = newAttributes;
+        return attributes[@"@componentProps"];
+    }
+    
+    return nil;
+}
+
 #pragma mark Reset
 -(BOOL)isShouldReset:(id )value
 {
@@ -783,3 +905,8 @@ void WXPerformBlockOnComponentThread(void (^block)())
 {
     [WXComponentManager _performBlockOnComponentThread:block];
 }
+
+void WXPerformBlockSyncOnComponentThread(void (^block)())
+{
+    [WXComponentManager _performBlockSyncOnComponentThread:block];
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
index 39385ef..ac1b13a 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
@@ -23,6 +23,11 @@
 
 @class WXSDKInstance;
 
+typedef enum : NSUInteger {
+    WXDisplayTypeNone,
+    WXDisplayTypeBlock
+} WXDisplayType;
+
 /**
  * @abstract the component callback , result can be string or dictionary.
  * @discussion callback data to js, the id of callback function will be removed to save memory.
@@ -37,7 +42,7 @@ typedef void (^WXKeepAliveCallback)(_Nonnull id result, BOOL keepAlive);
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface WXComponent : NSObject
+@interface WXComponent : NSObject <NSCopying>
 
 ///--------------------------------------
 /// @name Component Hierarchy Management
@@ -346,6 +351,8 @@ NS_ASSUME_NONNULL_BEGIN
 /// @name Display
 ///--------------------------------------
 
+@property (nonatomic, assign) WXDisplayType displayType;
+
 /**
  * @abstract Marks the view as needing display. The method should be called on the main thread.
  * @discussion You can use this method to notify the system that your component's contents need to be redrawn. This method makes a note of the request and returns immediately. The component is not actually redrawn until the next drawing cycle, at which point all invalidated components are updated.
@@ -399,6 +406,16 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (UIImage *)endDrawContext:(CGContextRef)context;
 
+///--------------------------------------
+/// @name Data Binding
+///--------------------------------------
+
+/**
+ * @abstract Update binding data for the component
+ * @parameter binding data to update
+ */
+- (void)updateBindingData:(NSDictionary *)data;
+
 @end
 
 @interface WXComponent (Deprecated)

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 0992b49..2bad1c2 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -88,6 +88,7 @@
         
         _absolutePosition = CGPointMake(NAN, NAN);
         
+        _displayType = WXDisplayTypeBlock;
         _isNeedJoinLayoutSystem = YES;
         _isLayoutDirty = YES;
         _isViewFrameSyncWithCalculated = YES;
@@ -140,6 +141,41 @@
     return self;
 }
 
+- (id)copyWithZone:(NSZone *)zone
+{
+    NSInteger copyId = 0;
+    @synchronized(self){
+        static NSInteger __copy = 0;
+        copyId = __copy % (1024*1024);
+        __copy++;
+    }
+    NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", copyId, _isTemplate ? self.ref : self->_templateComponent.ref];
+    WXComponent *component = [[[self class] allocWithZone:zone] initWithRef:copyRef type:self.type styles:self.styles attributes:self.attributes events:self.events weexInstance:self.weexInstance];
+    if (_isTemplate) {
+        component->_templateComponent = self;
+    } else {
+        component->_templateComponent = self->_templateComponent;
+    }
+    memcpy(component->_cssNode, self.cssNode, sizeof(css_node_t));
+    component->_cssNode->context = (__bridge void *)component;
+    component->_calculatedFrame = self.calculatedFrame;
+    
+    NSMutableArray *subcomponentsCopy = [NSMutableArray array];
+    for (WXComponent *subcomponent in self.subcomponents) {
+        WXComponent *subcomponentCopy = [subcomponent copy];
+        subcomponentCopy->_supercomponent = component;
+        [subcomponentsCopy addObject:subcomponentCopy];
+    }
+    
+    component->_subcomponents = subcomponentsCopy;
+    
+    WXPerformBlockOnComponentThread(^{
+        [self.weexInstance.componentManager addComponent:component toIndexDictForRef:copyRef];
+    });
+    
+    return component;
+}
+
 - (UIAccessibilityTraits)_parseAccessibilityTraitsWithTraits:(UIAccessibilityTraits)trait roles:(NSString*)roleStr
 {
     UIAccessibilityTraits newTrait = trait;
@@ -208,6 +244,28 @@
     return events;
 }
 
+- (void)setDisplayType:(WXDisplayType)displayType
+{
+    if (_displayType != displayType) {
+        _displayType = displayType;
+        if (displayType == WXDisplayTypeNone) {
+            _isNeedJoinLayoutSystem = NO;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self removeFromSuperview];
+            });
+        } else {
+            _isNeedJoinLayoutSystem = YES;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self _buildViewHierarchyLazily];
+                // TODO: insert into the correct index
+                [self.supercomponent insertSubview:self atIndex:0];
+            });
+        }
+    }
+}
+
 - (WXSDKInstance *)weexInstance
 {
     return _weexInstance;
@@ -371,6 +429,26 @@
     return _cssNode;
 }
 
+- (void)_addEventParams:(NSDictionary *)params
+{
+    pthread_mutex_lock(&_propertyMutex);
+    if (!_eventParameters) {
+        _eventParameters = [NSMutableDictionary dictionary];
+    }
+    [_eventParameters addEntriesFromDictionary:params];
+    pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (NSArray *)_paramsForEvent:(NSString *)eventName
+{
+    NSArray *params;
+    pthread_mutex_lock(&_propertyMutex);
+    params = _eventParameters[eventName];
+    pthread_mutex_unlock(&_propertyMutex);
+    
+    return params;
+}
+
 #pragma mark Component Hierarchy 
 
 - (NSArray<WXComponent *> *)subcomponents
@@ -440,6 +518,11 @@
     [newSupercomponent _insertSubcomponent:self atIndex:index];
 }
 
+- (void)_didInserted
+{
+    
+}
+
 - (id<WXScrollerProtocol>)ancestorScroller
 {
     if(!_ancestorScroller) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
index f494247..8c7aee3 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
@@ -21,7 +21,7 @@
 
 @protocol WXDiffable <NSObject>
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object;
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object;
 
 @end
 
@@ -40,6 +40,10 @@
 
 - (BOOL)hasChanges;
 
+- (instancetype)initWithInserts:(NSIndexSet *)inserts
+                        deletes:(NSIndexSet *)deletes
+                        updates:(NSArray<WXDiffUpdateIndex *> *)updates;
+
 @end
 
 @interface WXDiffUtil : NSObject
@@ -47,3 +51,20 @@
 + (WXDiffResult *)diffWithMinimumDistance:(NSArray<id<WXDiffable>> *)newArray oldArray:(NSArray<id<WXDiffable>> *)oldArray;
 
 @end
+
+@interface NSNumber (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSString (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSArray (WXDiffable) <WXDiffable>
+
+@end
+
+@interface NSDictionary (WXDiffable) <WXDiffable>
+
+@end
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
index 9396243..fabdbd1 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
@@ -96,7 +96,7 @@ typedef enum : NSUInteger {
     
     for (int oldIndex = 1; oldIndex < oldSize; oldIndex ++) {
         for (int newIndex = 1; newIndex < newSize; newIndex ++) {
-            if ([oldArray[oldIndex - 1] isEqualToWXObject:newArray[newIndex - 1]]) {
+            if ([oldArray[oldIndex - 1] weex_isEqualTo:newArray[newIndex - 1]]) {
                 matrix[oldIndex][newIndex] = matrix[oldIndex - 1][newIndex - 1];
             } else {
                 int updateCost = matrix[oldIndex - 1][newIndex - 1] + 1;
@@ -107,7 +107,9 @@ typedef enum : NSUInteger {
         }
     }
     
+#if DEBUG
     [self _printMatrix:matrix rowSize:oldSize columnSize:newSize];
+#endif
     
     NSMutableArray *updates = [NSMutableArray array];
     NSMutableIndexSet *inserts = [NSMutableIndexSet indexSet];
@@ -195,3 +197,85 @@ typedef enum : NSUInteger {
 }
 
 @end
+
+@implementation NSNumber (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    return [self isEqual:object];
+}
+
+@end
+
+@implementation NSString (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    return [self isEqual:object];
+}
+
+@end
+
+@implementation NSArray (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    if (![object isKindOfClass:[NSArray class]]) {
+        return NO;
+    }
+    
+    NSArray *array = (NSArray *)object;
+    if (self.count != array.count) {
+        return NO;
+    }
+    
+    __block BOOL isEqual = YES;
+    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        id obj2 = [self objectAtIndex:idx];
+        if ([obj conformsToProtocol:@protocol(WXDiffable)] && [obj2 conformsToProtocol:@protocol(WXDiffable)]) {
+            if (![obj weex_isEqualTo:obj2]) {
+                isEqual = NO;
+                *stop = YES;
+            }
+        } else {
+            isEqual = NO;
+            *stop = YES;
+        }
+    }];
+    
+    return isEqual;
+}
+
+@end
+
+@implementation NSDictionary (WXDiffable)
+
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
+{
+    if (![object isKindOfClass:[NSDictionary class]]) {
+        return NO;
+    }
+    
+    NSDictionary *dictionary = (NSDictionary *)object;
+    if (self.count != dictionary.count) {
+        return NO;
+    }
+    
+    __block BOOL isEqual = YES;
+    [dictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
+        id obj2 = [self objectForKey:key];
+        if (obj2 && [obj2 conformsToProtocol:@protocol(WXDiffable)] && [obj conformsToProtocol:@protocol(WXDiffable)]) {
+            if (![obj weex_isEqualTo:obj2]) {
+                isEqual = NO;
+                *stop = YES;
+            }
+        } else {
+            isEqual = NO;
+            *stop = YES;
+        }
+    }];
+    
+    return isEqual;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 5d96757..538dc77 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -81,33 +81,41 @@ do {\
     }\
 }while(0)
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
 /**
  * @abstract execute asynchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute synchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute action block on the specific thread.
  *
  */
-extern void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread *_Nonnull thread);
+void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread *_Nonnull thread);
 
 /**
  * @abstract swizzling methods.
  *
  */
-extern void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL original, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL original, _Nonnull SEL replaced);
 
-extern void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, _Nonnull SEL original, _Nonnull id block, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, _Nonnull SEL original, _Nonnull id block, _Nonnull SEL replaced);
 
-extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+_Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXUtility : NSObject
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
index ef00f9a..be27ae7 100644
--- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
+++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
@@ -94,6 +94,10 @@ do {\
 {
     WXAssertMainThread();
     
+    if (subcomponent.displayType == WXDisplayTypeNone) {
+        return;
+    }
+    
     WX_CHECK_COMPONENT_TYPE(self.componentType)
     if (subcomponent->_positionType == WXPositionTypeFixed) {
         [self.weexInstance.rootView addSubview:subcomponent.view];


[05/17] incubator-weex git commit: * [ios] update JSFM to 0.22.2

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6a272abc/pre-build/native-bundle-main.js
----------------------------------------------------------------------
diff --git a/pre-build/native-bundle-main.js b/pre-build/native-bundle-main.js
index 462e4fc..c737167 100644
--- a/pre-build/native-bundle-main.js
+++ b/pre-build/native-bundle-main.js
@@ -1,8 +1,8 @@
-(this.nativeLog||function(e){console.log(e)})("START JS FRAMEWORK 0.21.11, Build 2017-08-23 15:52."),this.getJSFMVersion=function(){return"0.21.11"};var global=this,process={env:{}},setTimeout=global.setTimeout;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(0,function(){"use strict";function e(e){Qn.Document=e.Document,Qn.Element=e.Element,Qn.Comment=e.Comment,Qn.sendTasks=e.sendTasks}function t(e){}function n(e){}function r(e){}function o(e,t,n){}function i(e,t,n,r,o){var i=new Qn.Document(e,n.bundleUrl),a={},s=0;i.addCallback=function(e){return s++,a[s]=e,s},i.handleCallback=function(e,t,n){var r=a[e];return n&&delete a[e],r(t)},Yn[e]=i;var u=Object.assign({Document:Qn.Document,Element:Qn.Element,Comment:Qn.Comment,sendTasks:Qn.sendTasks,id:e,options:n,data:r,document:i},o),c=[],l=[];for(var f in u)c.push(f),l.push(u[f]);return c.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(c)))).app
 ly(void 0,l),{document:i}}function a(e,t){}function s(e){delete Yn[e]}function u(e){return Yn[e].body.toJSON()}function c(e,t){var n={fireEvent:function(e,t,n,r,o){var i=Yn[e],a=i.getRef(t);return i.fireEvent(a,n,r,o)},callback:function(e,t,n,r){return Yn[e].handleCallback(t,n,r)}};if(Yn[e]&&Array.isArray(t)){var r=[];return t.forEach(function(t){var o=n[t.method],i=[].concat(t.args);"function"==typeof o&&(i.unshift(e),r.push(o.apply(void 0,i)))}),r}}function l(e){return e&&e.__esModule?e.default:e}function f(e,t){return t={exports:{}},e(t,t.exports),t.exports}function d(e){console.warn("[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead");var t=this._ids[e];if(t)return t.vm}function p(e){var t=this._ids[e];if(t)return t.el}function h(e){var t=this._ids[e];if(t)return t.vm}function v(e){return this._app.differ.then(function(){e()})}function y(e,t){console.warn("[JS Framework] Vm#$scrollTo is deprecated, please use \"require('@weex-module/dom').scrollTo(el, options)\" inste
 ad");var n=this.$el(e);if(n){this._app.requireModule("dom").scrollToElement(n.ref,{offset:t})}}function m(e,t,n){var r=this,o=this.$el(e);if(o&&t&&t.styles){this._app.requireModule("animation").transition(o.ref,t,function(){for(var e=[],i=arguments.length;i--;)e[i]=arguments[i];r._setStyle(o,t.styles),n&&n.apply(void 0,e)})}}function _(e){var t=this._app.options;return"function"==typeof e&&(console.warn("[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, this api now can directly RETURN config info."),e(t)),t}function g(e,t){console.warn("[JS Framework] Vm#$sendHttp is deprecated, please use \"require('@weex-module/stream').sendHttp(params, callback)\" instead"),this._app.requireModule("stream").sendHttp(e,t)}function b(e){console.warn("[JS Framework] Vm#$openURL is deprecated, please use \"require('@weex-module/event').openURL(url)\" instead"),this._app.requireModule("event").openURL(e)}function w(e){console.warn("[JS Framework] Vm#$setTitle is deprecated, please
  use \"require('@weex-module/pageInfo').setTitle(title)\" instead"),this._app.requireModule("pageInfo").setTitle(e)}function O(e,t){for(var n=[],r=arguments.length-2;r-- >0;)n[r]=arguments[r+2];console.warn("[JS Framework] Vm#$call is deprecated, please use \"require('@weex-module/moduleName')\" instead");var o=this._app.requireModule(e);o&&o[t]&&o[t].apply(o,n)}function E(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];if("function"==typeof Object.assign)Object.assign.apply(Object,[e].concat(t));else{var r=t.shift();for(var o in r)e[o]=r[o];t.length&&E.apply(void 0,[e].concat(t))}return e}function x(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function S(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function C(e,t){return gr.call(e,t)}function k(e,t){return function(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}}function j(e){return null!==e&&"object"==typeof e}func
 tion A(e){return br.call(e)===wr}function I(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function T(){return"object"==typeof nativeSet?nativeSet.create():new Zn}function N(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1).toLowerCase()}function P(e){return e.replace(Er,"").replace(xr,"")}function M(e){return e.replace(Cr,"")}function $(){this.id=Tr++,this.subs=[]}function R(e){$.target&&Nr.push($.target),$.target=e}function D(){$.target=Nr.pop()}function F(){$.target=null,Nr=[]}function L(e,t,n,r){r&&E(this,r);var o="function"==typeof t;this.vm=e,e._watchers.push(this),this.expression=t,this.cb=n,this.id=++Pr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=T(),this.newDepIds=T(),o&&(this.getter=t),this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function V(e,t){var n,r,o,i;if(t||(t=Mr,t.clear()),o=Array.isArray(e),i=j(e),o||i){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.le
 ngth;n--;)V(e[n],t);else if(i)for(r=Object.keys(e),n=r.length;n--;)V(e[r[n]],t)}}function U(e){if(this.value=e,this.dep=new $,x(e,"__ob__",this),Array.isArray(e)){(Or?W:B)(e,Rr,Dr),this.observeArray(e)}else this.walk(e)}function W(e,t){e.__proto__=t}function B(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];x(e,i,t[i])}}function q(e,t){if(j(e)){var n;return C(e,"__ob__")&&e.__ob__ instanceof U?n=e.__ob__:(Array.isArray(e)||A(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new U(e)),n&&t&&n.addVm(t),n}}function z(e,t,n){var r=new $,o=Object.getOwnPropertyDescriptor(e,t);if(!o||!1!==o.configurable){var i=o&&o.get,a=o&&o.set,s=q(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=i?i.call(e):n;if($.target&&(r.depend(),s&&s.dep.depend(),Array.isArray(t)))for(var o=void 0,a=0,u=t.length;a<u;a++)(o=t[a])&&o.__ob__&&o.__ob__.dep.depend();return t},set:function(t){t!==(i?i.call(e):n)&&(a?a.call(e,t):n=t,s=q(t),r.notify())}})}}function J(e,t,n){if(Array.isArray(e))r
 eturn e.splice(t,1,n);if(C(e,t))return void(e[t]=n);if(e._isVue)return void J(e._data,t,n);var r=e.__ob__;if(!r)return void(e[t]=n);if(r.convert(t,n),r.dep.notify(),r.vms)for(var o=r.vms.length;o--;){var i=r.vms[o];G(i,t)}return n}function H(e,t){if(C(e,t)){delete e[t];var n=e.__ob__;if(!n)return void(e._isVue&&delete e._data[t]);if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var o=n.vms[r];X(o,t)}}}function G(e,t){(Fr.indexOf(t)>-1||!I(t))&&Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return e._data[t]},set:function(n){e._data[t]=n}})}function X(e,t){I(t)||delete e[t]}function K(e){e._watchers=[],Z(e),Y(e),te(e)}function Z(e){var t=e._data;A(t)||(t={});for(var n=Object.keys(t),r=n.length;r--;)G(e,n[r]);q(t,e)}function Q(){}function Y(e){var t=e._computed;if(t)for(var n in t){var r=t[n],o={enumerable:!0,configurable:!0};"function"==typeof r?(o.get=ee(r,e),o.set=Q):(o.get=r.get?!1!==r.cache?ee(r.get,e):k(r.get,e):Q,o.set=r.set?k(r.set,e):Q),Object.def
 ineProperty(e,n,o)}}function ee(e,t){var n=new L(t,e,null,{lazy:!0});return function(){return n.dirty&&n.evaluate(),$.target&&n.depend(),n.value}}function te(e){var t=e._methods;if(t)for(var n in t)e[n]=t[n]}function ne(e){var t=e.type,n=Vr[t];if("object"==typeof n)for(var r in n)if(null==e[r])e[r]=n[r];else if("object"===N(e[r])&&"object"===N(n[r]))for(var o in n[r])null==e[r][o]&&(e[r][o]=n[r][o])}function re(e,t,n){ce(e,t,n.id,e),le(e,t,n.attr),de(e,t,n.classList),pe(e,t,n.style),ve(e,t,n.events)}function oe(e,t,n,r){t=t||{},n=n||{};var o=t._options||{},i=o.props;Array.isArray(i)&&(i=i.reduce(function(e,t){return e[t]=!0,e},{})),ae(r,i,e,t),ae(n.attr,i,e,t)}function ie(e,t,n,r){void 0===r&&(r={}),ue(n.classList,e,t),se(n.style,e,t),r.children?r.children[r.children.length-1]._vm=t:r._vm=t}function ae(e,t,n,r){if(e){for(var o in e)!function(o){if(!t||t[o]){var i=e[o];if("function"==typeof i){var a=_e(n,i,function(e){r[o]=e});r[o]=a}else r[o]=i}}(o)}}function se(e,t,n){for(var r in 
 e)!function(r){var o=e[r];if("function"==typeof o){var i=_e(t,o,function(e){n._rootEl&&n._rootEl.setStyle(r,e)});n._rootEl.setStyle(r,i)}else n._rootEl&&n._rootEl.setStyle(r,o)}(r)}function ue(e,t,n){function r(e,t){"array"===N(e)&&e.unshift(t)}var o=t._options&&t._options.style||{};if(n._rootEl){var i="@originalRootEl";if(o[i]=n._rootEl.classStyle,"function"==typeof e){var a=_e(t,e,function(e){r(e,i),fe(n._rootEl,o,e)});r(a,i),fe(n._rootEl,o,a)}else null!=e&&(r(e,i),fe(n._rootEl,o,e))}}function ce(e,t,n,r){var o=Object.create(null);if(Object.defineProperties(o,{vm:{value:r,writable:!1,configurable:!1},el:{get:function(){return t||r._rootEl},configurable:!1}}),"function"==typeof n){var i=n;n=i.call(e),(n||0===n)&&(e._ids[n]=o),_e(e,i,function(t){t&&(e._ids[t]=o)})}else n&&"string"==typeof n&&(e._ids[n]=o)}function le(e,t,n){ye(e,t,"attr",n)}function fe(e,t,n){"string"==typeof n&&(n=n.split(/\s+/)),n.forEach(function(e,t){n.splice.apply(n,[t,1].concat(e.split(/\s+/)))});for(var r={},
 o=n.length,i=0;i<o;i++)!function(e){var o=t[n[e]];o&&Object.keys(o).forEach(function(e){r[e]=o[e]})}(i);e.setClassStyle(r)}function de(e,t,n){if("function"==typeof n||Array.isArray(n)){if(Array.isArray(n)&&!n.length)return void t.setClassStyle({});var r=e._options&&e._options.style||{};if("function"==typeof n){var o=_e(e,n,function(e){fe(t,r,e)});fe(t,r,o)}else fe(t,r,n)}}function pe(e,t,n){ye(e,t,"style",n)}function he(e,t,n,r){t.addEvent(n,k(r,e))}function ve(e,t,n){if(n)for(var r=Object.keys(n),o=r.length;o--;){var i=r[o],a=n[i];"string"==typeof a&&((a=e[a])||console.warn('[JS Framework] The event handler "'+a+'" is not defined.')),he(e,t,i,a)}}function ye(e,t,n,r){if(r)for(var o=Object.keys(r),i=o.length;i--;){var a=o[i],s=r[a];"function"==typeof s?me(e,t,n,a,s):t[Ur[n]](a,s)}}function me(e,t,n,r,o){var i=Ur[n],a=_e(e,o,function(n){function o(){t[i](r,n)}var a=e&&e._app&&e._app.differ;a?a.append("element",t.depth||0,t.ref,o):o()});t[i](r,a)}function _e(e,t,n){return e._static?t.
 call(e,e):new L(e,t,function(e,t){"object"!=typeof e&&e===t||n(e)}).value}function ge(e,t){return e._app.doc.createBody(t)}function be(e,t){return e._app.doc.createElement(t)}function we(e,t){var n=Oe(e),r=Ee(e),o=Wr++;if(t.element){var i=t.updateMark;i?(i.element&&(i=i.end),t.element.insertAfter(r,i),t.element.insertAfter(n,i),t.updateMark=r):(t.element.insertBefore(n,t.end),t.element.insertBefore(r,t.end)),t=t.element}else t.appendChild(n),t.appendChild(r);return{start:n,end:r,element:t,blockId:o}}function Oe(e){return e._app.doc.createComment("start")}function Ee(e){return e._app.doc.createComment("end")}function xe(e,t,n){if(n.element){var r=n.end,o=n.updateMark;if(n.children&&n.children.push(t),o){var i=Se(e,t,o);return n.updateMark=t.element?t.end:t,i}if(!t.element)return n.element.insertBefore(t,r);n.element.insertBefore(t.start,r),n.element.insertBefore(t.end,r)}else{if(!t.element)return n.appendChild(t);n.appendChild(t.start),n.appendChild(t.end)}}function Se(e,t,n){return 
 t.element?ke(t,n):Ce(t,n)}function Ce(e,t){var n=t.parentNode;if(n)return n.insertAfter(e,t)}function ke(e,t){var n=t.parentNode;if(n){for(var r,o=e.start,i=[o];o&&o!==e.end;)o=o.nextSibling,i.push(o);var a=t;return i.every(function(e){return r=n.insertAfter(e,a),a=e,-1!==r}),r}}function je(e,t,n){void 0===n&&(n=!1),t.element?Ie(t,n):Ae(t),t._vm&&t._vm.$emit("hook:destroyed")}function Ae(e){var t=e.parentNode;t&&t.removeChild(e)}function Ie(e,t){void 0===t&&(t=!1);for(var n=[],r=e.start.nextSibling;r&&r!==e.end;)n.push(r),r=r.nextSibling;t||Ae(e.start),n.forEach(function(e){Ae(e)}),t||Ae(e.end)}function Te(e){var t=e._options||{},n=t.template||{};t.replace?n.children&&1===n.children.length?Ne(e,n.children[0],e._parentEl):Ne(e,n.children,e._parentEl):Ne(e,n,e._parentEl),console.debug('[JS Framework] "ready" lifecycle in Vm('+e._type+")"),e.$emit("hook:ready"),e._ready=!0}function Ne(e,t,n,r){if(-1!==(e._app||{}).lastSignal){if(t.attr&&t.attr.hasOwnProperty("static")&&(e._static=!0),P
 e(t))return void Le(e,t,n,r);if(r=r||{},Me(t))return console.debug('[JS Framework] compile "content" block by',t),void(e._content=we(e,n));if($e(t,r))return console.debug('[JS Framework] compile "repeat" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `repeat` directive!"):Ve(e,t,n));if(Re(t,r))return console.debug('[JS Framework] compile "if" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `if` directive!"):Ue(e,t,n,r));var o=r.type||t.type;if(De(o,r))return void We(e,t,n,o,r);var i=o,a=Fe(e,t,i);if(a)return console.debug("[JS Framework] compile composed component by",t),void Be(e,a,t,n,i,r);console.debug("[JS Framework] compile native component by",t),qe(e,t,n,i)}}function Pe(e){return Array.isArray(e)}function Me(e){return"content"===e.type||"slot"===e.type}function $e(e,t){return!t.hasOwnProperty("repeat")&&e.repeat}function Re(e,t){return!t.hasOwnProperty("shown")&&e.shown}func
 tion De(e,t){return"function"==typeof e&&!t.hasOwnProperty("type")}function Fe(e,t,n){var r;return e._app&&e._app.customComponentMap&&(r=e._app.customComponentMap[n]),e._options&&e._options.components&&(r=e._options.components[n]),t.component&&(r=r||{}),r}function Le(e,t,n,r){var o=we(e,n);t.forEach(function(t){Ne(e,t,o,r)})}function Ve(e,t,n){var r=t.repeat,o="function"==typeof r,i=r.getter||r.expression||r;"function"!=typeof i&&(i=function(){return[]});var a=r.key||"$index",s=r.value||"$value",u=r.trackBy||t.trackBy||t.attr&&t.attr.trackBy,c=we(e,n);c.children=[],c.data=[],c.vms=[],Je(e,t,c,{getter:i,key:a,value:s,trackBy:u,oldStyle:o})}function Ue(e,t,n,r){var o={shown:!0},i=we(e,n);n.element&&n.children&&n.children.push(i),r.repeat&&(o.repeat=r.repeat),He(e,t,i,o)}function We(e,t,n,r,o){var i=r.call(e),a=E({type:i},o),s=we(e,n);n.element&&n.children&&n.children.push(s),_e(e,r,function(n){var r=E({type:n},o);je(e,s,!0),Ne(e,t,s,r)}),Ne(e,t,s,a)}function Be(e,t,n,r,o,i){var a=e.co
 nstructor,s=new a(o,t,e,r,void 0,{"hook:init":function(){e._static&&(this._static=e._static),ce(e,null,n.id,this),this._externalBinding={parent:e,template:n}},"hook:created":function(){oe(e,this,n,i.repeat)},"hook:ready":function(){this._content&&ze(e,n,this._content)}});ie(e,s,n,r)}function qe(e,t,n,r){ne(t);var o;if("_documentElement"===n.ref?(console.debug("[JS Framework] compile to create body for "+r),o=ge(e,r)):(console.debug("[JS Framework] compile to create element for "+r),o=be(e,r)),!e._rootEl){e._rootEl=o;var i=e._externalBinding||{},a=i.template,s=i.parent;if(a&&a.events&&s&&o)for(var u in a.events){var c=s[a.events[u]];c&&o.addEvent(u,k(c,s))}}re(e,o,t),t.attr&&t.attr.append&&(t.append=t.attr.append),t.append&&(o.attr=o.attr||{},o.attr.append=t.append);var l="tree"===t.append,f=e._app||{};-1===f.lastSignal||l||(console.debug("[JS Framework] compile to append single node for",o),f.lastSignal=xe(e,o,n)),-1!==f.lastSignal&&ze(e,t,o),-1!==f.lastSignal&&l&&(console.debug("[J
 S Framework] compile to append whole tree for",o),f.lastSignal=xe(e,o,n))}function ze(e,t,n){var r=e._app||{},o=t.children;o&&o.length&&o.every(function(t){return Ne(e,t,n),-1!==r.lastSignal})}function Je(e,t,n,r){function o(e,r,o){var a;c?(a=e,j(e)?(a[l]=r,a.hasOwnProperty("INDEX")||Object.defineProperty(a,"INDEX",{value:function(){console.warn('[JS Framework] "INDEX" in repeat is deprecated, please use "$index" instead')}})):(console.warn("[JS Framework] Each list item must be an object in old-style repeat, please use `repeat={{v in list}}` instead."),a={},a[l]=r,a[f]=e)):(a={},a[l]=r,a[f]=e);var s=Xe(o,a);i.push(s),Ne(s,t,n,{repeat:e})}var i=n.vms,a=n.children,s=r.getter,u=r.trackBy,c=r.oldStyle,l=r.key,f=r.value,d=Ge(e,n,s,"repeat",function(t){if(console.debug('[JS Framework] the "repeat" item has changed',t),n&&t){var r=a.slice(),s=i.slice(),d=n.data.slice(),p={},h={};t.forEach(function(e,t){var n=u?e[u]:c?e[l]:t;null!=n&&""!==n&&(p[n]=e)});var v=[];d.forEach(function(t,n){var 
 o=u?t[u]:c?t[l]:n;p.hasOwnProperty(o)?(h[o]={item:t,index:n,key:o,target:r[n],vm:s[n]},v.push(t)):je(e,r[n])}),a.length=0,i.length=0,n.data=t.slice(),n.updateMark=n.start,t.forEach(function(t,r){var s=u?t[u]:c?t[l]:r,d=h[s];d?(d.item===v[0]?v.shift():(v.$remove(d.item),Se(e,d.target,n.updateMark,!0)),a.push(d.target),i.push(d.vm),c?d.vm=t:d.vm[f]=t,d.vm[l]=r,n.updateMark=d.target):o(t,r,e)}),delete n.updateMark}});n.data=d.slice(0),d.forEach(function(t,n){o(t,n,e)})}function He(e,t,n,r){var o=Ge(e,n,t.shown,"shown",function(o){console.debug('[JS Framework] the "if" item was changed',o),n&&!!n.display!=!!o&&(n.display=!!o,o?Ne(e,t,n,r):je(e,n,!0))});n.display=!!o,o&&Ne(e,t,n,r)}function Ge(e,t,n,r,o){var i=e&&e._app&&e._app.differ,a={},s=(t.element.depth||0)+1;return _e(e,n,function(e){a.latestValue=e,i&&!a.recorded&&i.append(r,s,t.blockId,function(){var e=a.latestValue;o(e),a.recorded=!1,a.latestValue=void 0}),a.recorded=!0})}function Xe(e,t){var n=Object.create(e);return n._data=t,
 Z(n),Y(n),n._realParent=e,e._static&&(n._static=e._static),n}function Ke(e,t){if(t instanceof Ke)return t;this.timestamp=Date.now(),this.detail=t,this.type=e;var n=!1;this.stop=function(){n=!0},this.hasStopped=function(){return n}}function Ze(e,t){var n=this,r=this._vmEvents,o=r[e];if(o){var i=new Ke(e,t);o.forEach(function(e){e.call(n,i)})}}function Qe(e,t){var n=new Ke(e,t);this.$emit(e,n),!n.hasStopped()&&this._parent&&this._parent.$dispatch&&this._parent.$dispatch(e,n)}function Ye(e,t){var n=new Ke(e,t);this.$emit(e,n),!n.hasStopped()&&this._childrenVms&&this._childrenVms.forEach(function(t){t.$broadcast(e,n)})}function et(e,t){if(e&&"function"==typeof t){var n=this._vmEvents,r=n[e]||[];r.push(t),n[e]=r,"hook:ready"===e&&this._ready&&this.$emit("hook:ready")}}function tt(e,t){if(e){var n=this._vmEvents;if(!t)return void delete n[e];var r=n[e];r&&r.$remove(t)}}function nt(e,t){var n=e._options||{},r=n.events||{};for(var o in r)e.$on(o,r[o]);for(var i in t)e.$on(i,t[i]);Br.forEach
 (function(t){e.$on("hook:"+t,n[t])})}function rt(e,t,n,r,o,i){n=n||{},this._parent=n._realParent?n._realParent:n,this._app=n._app||{},n._childrenVms&&n._childrenVms.push(this),!t&&this._app.customComponentMap&&(t=this._app.customComponentMap[e]),t=t||{};var a=t.data||{};this._options=t,this._methods=t.methods||{},this._computed=t.computed||{},this._css=t.style||{},this._ids={},this._vmEvents={},this._childrenVms=[],this._type=e,nt(this,i),console.debug('[JS Framework] "init" lifecycle in Vm('+this._type+")"),this.$emit("hook:init"),this._inited=!0,this._data="function"==typeof a?a():a,o&&E(this._data,o),K(this),console.debug('[JS Framework] "created" lifecycle in Vm('+this._type+")"),this.$emit("hook:created"),this._created=!0,t.methods&&t.methods.ready&&(console.warn('"exports.methods.ready" is deprecated, please use "exports.created" instead'),t.methods.ready.call(this)),this._app.doc&&(this._parentEl=r||this._app.doc.documentElement,Te(this))}function ot(e,t){for(var n in e)!func
 tion(n){var r=qr[n];r||(r={},qr[n]=r),e[n].forEach(function(e){"string"==typeof e&&(e={name:e}),r[e.name]&&!t||(r[e.name]=e)})}(n)}function it(e,t){var n=e.prototype;for(var r in t)n.hasOwnProperty(r)||(n[r]=t[r])}function at(e,t){var n=qr[t],r={};for(var o in n)!function(n){Object.defineProperty(r,n,{configurable:!0,enumerable:!0,get:function(){return function(){for(var r=[],o=arguments.length;o--;)r[o]=arguments[o];return e.callTasks({module:t,method:n,args:r})}},set:function(r){if("function"==typeof r)return e.callTasks({module:t,method:n,args:[r]})}})}(o);return r}function st(e,t){return e.customComponentMap[t]}function ut(e,t,n){var r=e.customComponentMap;if(r[t])return void console.error("[JS Framework] define a component("+t+") that already exists");r[t]=n}function ct(e){if(zr.valid(e))return e;e="string"==typeof e?e:"";for(var t=e.split("."),n=0,r=[];n<3;){var o="string"==typeof t[n]&&t[n]?t[n]:"0";r.push(o),n++}return r.join(".")}function lt(e,t,n){var r={isDowngrade:!0,err
 orType:1,code:1e3},o=e.toLowerCase();return r.errorMessage=function(e,t,n){return"Downgrade["+e+"] :: deviceInfo "+t+" matched criteria "+n}(e,t,n),o.indexOf("osversion")>=0?r.code=1001:o.indexOf("appversion")>=0?r.code=1002:o.indexOf("weexversion")>=0?r.code=1003:o.indexOf("devicemodel")>=0&&(r.code=1004),r}function ft(e,t){t=t||global.WXEnvironment,t=A(t)?t:{};var n={isDowngrade:!1};if("function"===N(e)){var r=e.call(this,t,{semver:zr,normalizeVersion:ct});r=!!r,n=r?lt("custom","","custom params"):n}else{e=A(e)?e:{};var o=t.platform||"unknow",i=o.toLowerCase(),a=e[i]||{};for(var s in t){var u=s,c=u.toLowerCase(),l=t[s],f=c.indexOf("version")>=0,d=c.indexOf("devicemodel")>=0,p=a[s];if(p&&f){var h=ct(p),v=ct(t[s]);if(zr.satisfies(v,h)){n=lt(u,l,p);break}}else if(d){var y="array"===N(p)?p:[p];if(y.indexOf(l)>=0){n=lt(u,l,p);break}}}}return n}function dt(e,t){if(void 0===t&&(t={}),e&&e.callTasks)return e.callTasks([{module:"meta",method:"setViewport",args:[t]}])}function pt(e,t,n,r){c
 onsole.debug("[JS Framework] bootstrap for "+t);var o;if(kr(t))o=P(t);else{if(!Ir(t))return new Error("Wrong component name: "+t);if(o=M(t),!st(e,o))return new Error("It's not a component: "+t)}if(n=A(n)?n:{},"string"==typeof n.transformerVersion&&"string"==typeof global.transformerVersion&&!zr.satisfies(n.transformerVersion,global.transformerVersion))return new Error("JS Bundle version: "+n.transformerVersion+" not compatible with "+global.transformerVersion);var i=ft(n.downgrade);if(i.isDowngrade)return e.callTasks([{module:"instanceWrap",method:"error",args:[i.errorType,i.code,i.errorMessage]}]),new Error("Downgrade["+i.code+"]: "+i.errorMessage);n.viewport&&dt(e,n.viewport),e.vm=new rt(o,null,{_app:e},null,r)}function ht(e,t,n){console.warn("[JS Framework] Register is deprecated, please install lastest transformer."),ut(e,t,n)}function vt(e,t){console.debug("[JS Framework] Refresh with",t,"in instance["+e.id+"]");var n=e.vm;return n&&t?("function"==typeof n.refreshData?n.refresh
 Data(t):E(n,t),e.differ.flush(),void e.doc.taskCenter.send("dom",{action:"refreshFinish"},[])):new Error('invalid data "'+t+'"')}function yt(e){console.debug("[JS Framework] Destory an instance("+e.id+")"),e.vm&&mt(e.vm),e.id="",e.options=null,e.blocks=null,e.vm=null,e.doc.taskCenter.destroyCallback(),e.doc.destroy(),e.doc=null,e.customComponentMap=null,e.commonModules=null}function mt(e){if(delete e._app,delete e._computed,delete e._css,delete e._data,delete e._ids,delete e._methods,delete e._options,delete e._parent,delete e._parentEl,delete e._rootEl,e._watchers){for(var t=e._watchers.length;t--;)e._watchers[t].teardown();delete e._watchers}if(e._childrenVms){for(var n=e._childrenVms.length;n--;)mt(e._childrenVms[n]);delete e._childrenVms}console.debug('[JS Framework] "destroyed" lifecycle in Vm('+e._type+")"),e.$emit("hook:destroyed"),delete e._type,delete e._vmEvents}function _t(e){var t=e.doc||{},n=t.body||{};return n.toJSON?n.toJSON():{}}function gt(e,t,n,r,o){if(console.debu
 g('[JS Framework] Fire a "'+n+'" event on an element('+t+") in instance("+e.id+")"),Array.isArray(t))return void t.some(function(t){return!1!==gt(e,t,n,r)});var i=e.doc.getRef(t);if(i){var a=e.doc.fireEvent(i,n,r,o);return e.differ.flush(),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),a}return new Error('invalid element reference "'+t+'"')}function bt(e,t,n,r){console.debug("[JS Framework] Invoke a callback("+t+") with",n,"in instance("+e.id+")");var o=e.doc.taskCenter.callback(t,n,r);return wt(e),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),o}function wt(e){e.differ.flush()}function Ot(e,t){var n;return"array"!==N(t)&&(t=[t]),t.forEach(function(t){n=e.doc.taskCenter.send("module",{module:t.module,method:t.method},t.args)}),n}function Et(e,t,n,r){console.debug("[JS Framework] Intialize an instance with:\n",n);var o,i=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return Jr.apply(void 0,[e].concat(t))},a=function(t,r,i){o=pt(e,t,r,i||n),wt(e),e
 .doc.listener.createFinish(),console.debug("[JS Framework] After intialized an instance("+e.id+")")},s=rt,u=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return ht.apply(void 0,[e].concat(t))},c=function(t,n){o=pt(e,t,{},n)},l=function(t){return function(n){o=pt(e,t,{},n)}},f=e.doc,d=function(t){return e.requireModule(P(t))},p={config:e.options,define:i,bootstrap:a,requireModule:d,document:f,Vm:s};Object.freeze(p);var h;"function"==typeof t?h=t.toString().substr(12):t&&(h=t.toString()),h='(function(global){\n\n"use strict";\n\n '+h+" \n\n})(Object.create(this))";var v=global.WXEnvironment,y={};if(v&&"Web"!==v.platform){var m=e.requireModule("timer");Object.assign(y,{setTimeout:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setTimeout(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},setInterval:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function()
 {t[0].apply(t,t.slice(2))};return m.setInterval(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},clearTimeout:function(e){m.clearTimeout(e)},clearInterval:function(e){m.clearInterval(e)}})}var _=Object.assign({define:i,require:l,bootstrap:a,register:u,render:c,__weex_define__:i,__weex_bootstrap__:a,__weex_document__:f,__weex_require__:d,__weex_viewmodel__:s,weex:p},y,r);return St(_,h)||xt(_,h),o}function xt(e,t){var n=[],r=[];for(var o in e)n.push(o),r.push(e[o]);return n.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(n)))).apply(void 0,r)}function St(e,t){if("function"!=typeof compileAndRunBundle)return!1;var n=void 0,r=!1,o="(function (",i=[],a=[];for(var s in e)i.push(s),a.push(e[s]);for(var u=0;u<i.length-1;++u)o+=i[u],o+=",";o+=i[i.length-1],o+=") {",o+=t,o+="} )";try{var c=e.weex||{},l=c.config||{};n=compileAndRunBundle(o,l.bundleUrl,l.bundleDigest,l.codeCachePath),n&&"function"==typeof n&&(n.apply(void 0,a),r=!0)}catch(e){console.error(e)
 }return r}function Ct(e,t){var n=e[t];for(var r in n)n[r]()}function kt(e,t){var n=e[t];for(var r in n){n[r].forEach(function(e){e()})}}function jt(e,t){this.id=e,this.options=t||{},this.vm=null,this.customComponentMap={},this.commonModules={},this.doc=new Lr.Document(e,this.options.bundleUrl,null,Lr.Listener),this.differ=new Hr(e)}function At(e,t,n,r,o){var i=o||{},a=i.services;F();var s=Gr[e];n=n||{};var u;return s?u=new Error('invalid instance id "'+e+'"'):(s=new jt(e,n),Gr[e]=s,u=Et(s,t,r,a)),u instanceof Error?u:s}function It(e){Lr.Document=e.Document,Lr.Element=e.Element,Lr.Comment=e.Comment,Lr.sendTasks=e.sendTasks,Lr.Listener=e.Listener}function Tt(e,t){var n=Gr[e];return n?vt(n,t):new Error('invalid instance id "'+e+'"')}function Nt(e){"function"==typeof markupState&&markupState(),F();var t=Gr[e];if(!t)return new Error('invalid instance id "'+e+'"');yt(t),delete Gr[e];var n=Math.round(e);if(n>0){n%18||"function"!=typeof notifyTrimMemory||notifyTrimMemory()}return Gr}functio
 n Pt(e){Array.isArray(e)&&e.forEach(function(e){e&&("string"==typeof e?Xr[e]=!0:"object"==typeof e&&"string"==typeof e.type&&(Xr[e.type]=e))})}function Mt(e){"object"==typeof e&&ot(e)}function $t(e){"object"==typeof e&&it(rt,e)}function Rt(e,t){if(Gr[e]&&Array.isArray(t)){var n=[];return t.forEach(function(t){var r=Kr[t.method],o=[].concat(t.args);"function"==typeof r&&(o.unshift(e),n.push(r.apply(void 0,o)))}),n}return new Error('invalid instance id "'+e+'" or tasks')}function Dt(e){var t=Gr[e];return t?_t(t):new Error('invalid instance id "'+e+'"')}function Ft(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=Qs(t),this.reject=Qs(n)}function Lt(){if(Ut(),global.WXEnvironment&&"Web"!==global.WXEnvironment.platform)global.console={debug:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("debug")&&global.nativeLog.apply(global,Bt(e).concat(["__DEBUG"]))},log:function(){for(var e=[]
 ,t=arguments.length;t--;)e[t]=arguments[t];Wt("log")&&global.nativeLog.apply(global,Bt(e).concat(["__LOG"]))},info:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("info")&&global.nativeLog.apply(global,Bt(e).concat(["__INFO"]))},warn:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("warn")&&global.nativeLog.apply(global,Bt(e).concat(["__WARN"]))},error:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("error")&&global.nativeLog.apply(global,Bt(e).concat(["__ERROR"]))}};else{var e=console.debug,t=console.log,n=console.info,r=console.warn,o=console.error;console.__ori__={debug:e,log:t,info:n,warn:r,error:o},console.debug=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("debug")&&console.__ori__.debug.apply(console,e)},console.log=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("log")&&console.__ori__.log.apply(console,e)},console.info=function(){for(var e=[],t=arguments.length;t--;)e[t
 ]=arguments[t];Wt("info")&&console.__ori__.info.apply(console,e)},console.warn=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("warn")&&console.__ori__.warn.apply(console,e)},console.error=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("error")&&console.__ori__.error.apply(console,e)}}}function Vt(){zu={},global.console=Ju}function Ut(){qu.forEach(function(e){var t=qu.indexOf(e);zu[e]={},qu.forEach(function(n){qu.indexOf(n)<=t&&(zu[e][n]=!0)})})}function Wt(e){var t=global.WXEnvironment&&global.WXEnvironment.logLevel||"log";return zu[t]&&zu[t][e]}function Bt(e){return e.map(function(e){return e="[object object]"===Object.prototype.toString.call(e).toLowerCase()?JSON.stringify(e):String(e)})}function qt(){if(void 0===setTimeout&&"function"==typeof Gu){var e={},t=0;global.setTimeout=function(n,r){e[++t]=n,Gu(t.toString(),r)},global.setTimeoutCallback=function(t){"function"==typeof e[t]&&(e[t](),delete e[t])}}}function zt(){global.setTimeout=H
 u,global.setTimeoutCallback=null}function Jt(){Object.freeze(Object),Object.freeze(Array),Ht(),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Gt(),Object.freeze(Date.prototype),Object.freeze(RegExp.prototype)}function Ht(){var e=Object.prototype,t="Object.prototype";Xt(e,"__defineGetter__",t),Xt(e,"__defineSetter__",t),Xt(e,"__lookupGetter__",t),Xt(e,"__lookupSetter__",t),Xt(e,"constructor",t),Xt(e,"hasOwnProperty",t),Xt(e,"isPrototypeOf",t),Xt(e,"propertyIsEnumerable",t),Xt(e,"toLocaleString",t),Xt(e,"toString",t),Xt(e,"valueOf",t),Object.seal(e)}function Gt(){var e=Error.prototype,t="Error.prototype";Xt(e,"name",t),Xt(e,"message",t),Xt(e,"toString",t),Xt(e,"constructor",t),Object.seal(e)}function Xt(e,t,n){if(e.hasOwnProperty(t)){var r=e[t];Object.defineProperty(e,t,{get:function(){return r},set:function(r){if(this===e)throw Error("Cannot assign to read only property "+t+" of "+n);return Object.define
 Property(this,t,{value:r,writable:!0}),r}})}}function Kt(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1)}function Zt(e){if("function"!=typeof btoa)return"";var t=Array.prototype.map.call(new Uint8Array(e),function(e){return String.fromCharCode(e)}).join("");return btoa(t)}function Qt(e){if("function"!=typeof atob)return new ArrayBuffer(0);var t=atob(e),n=new Uint8Array(t.length);return Array.prototype.forEach.call(t,function(e,t){n[t]=e.charCodeAt(0)}),n.buffer}function Yt(e){var t=Kt(e);switch(t){case"Undefined":case"Null":return"";case"RegExp":return e.toString();case"Date":return e.toISOString();case"Number":case"String":case"Boolean":case"Array":case"Object":return e;case"ArrayBuffer":return{"@type":"binary",dataType:t,base64:Zt(e)};case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":return{"@type":"binary",dataType:t,base64:Zt(e.buffer)};d
 efault:return JSON.stringify(e)}}function en(e){if("Object"===Kt(e)){
-if(e["@type"]&&"binary"===e["@type"])return Qt(e.base64||"");var t={};for(var n in e)t[n]=en(e[n]);return t}return"Array"===Kt(e)?e.map(en):e}function tn(e,t){e&&(Ku[e]=t)}function nn(e){return Ku[e]}function rn(e){delete Ku[e]}function on(e){var t=Ku[e];return t&&t.taskCenter?t.taskCenter:null}function an(){return(Zu++).toString()}function sn(e,t,n){var r=e.documentElement;if(!(r.pureChildren.length>0||t.parentNode)){var o=r.children,i=o.indexOf(n);i<0?o.push(t):o.splice(i,0,t),1===t.nodeType?("body"===t.role?(t.docId=e.id,t.ownerDocument=e,t.parentNode=r,ln(t,r)):(t.children.forEach(function(e){e.parentNode=t}),cn(e,t),t.docId=e.id,t.ownerDocument=e,ln(t,r),delete e.nodeMap[t.nodeId]),r.pureChildren.push(t),un(e,t)):(t.parentNode=r,e.nodeMap[t.ref]=t)}}function un(e,t){var n=t.toJSON(),r=n.children;delete n.children;var o=e.taskCenter.send("dom",{action:"createBody"},[n]);return r&&r.forEach(function(t){o=e.taskCenter.send("dom",{action:"addElement"},[n.ref,t,-1])}),o}function cn(
 e,t){t.role="body",t.depth=1,delete e.nodeMap[t.nodeId],t.ref="_root",e.nodeMap._root=t,e.body=t}function ln(e,t){e.parentNode=t,t.docId&&(e.docId=t.docId,e.ownerDocument=t.ownerDocument,e.ownerDocument.nodeMap[e.nodeId]=e,e.depth=t.depth+1),e.children.forEach(function(t){ln(t,e)})}function fn(e){for(;e;){if(1===e.nodeType)return e;e=e.nextSibling}}function dn(e){for(;e;){if(1===e.nodeType)return e;e=e.previousSibling}}function pn(e,t,n,r){n<0&&(n=0);var o=t[n-1],i=t[n];return t.splice(n,0,e),r&&(o&&(o.nextSibling=e),e.previousSibling=o,e.nextSibling=i,i&&(i.previousSibling=e)),n}function hn(e,t,n,r){var o=t.indexOf(e);if(o<0)return-1;if(r){var i=t[o-1],a=t[o+1];i&&(i.nextSibling=a),a&&(a.previousSibling=i)}t.splice(o,1);var s=n;o<=n&&(s=n-1);var u=t[s-1],c=t[s];return t.splice(s,0,e),r&&(u&&(u.nextSibling=e),e.previousSibling=u,e.nextSibling=c,c&&(c.previousSibling=e)),o===s?-1:n}function vn(e,t,n){var r=t.indexOf(e);if(!(r<0)){if(n){var o=t[r-1],i=t[r+1];o&&(o.nextSibling=i),i&&(i
 .previousSibling=o)}t.splice(r,1)}}function yn(){this.nodeId=an(),this.ref=this.nodeId,this.children=[],this.pureChildren=[],this.parentNode=null,this.nextSibling=null,this.previousSibling=null}function mn(e,t){if(t&&t.length){var n=function(t){Qu.call(this,e,t,!0)};n.prototype=Object.create(Qu.prototype),Object.defineProperty(n.prototype,"constructor",{configurable:!1,enumerable:!1,writable:!1,value:Qu}),t.forEach(function(t){n.prototype[t]=function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var o=on(this.docId);if(o)return o.send("component",{ref:this.ref,component:e,method:t},n)}}),Yu[e]=n}}function _n(e,t,n){void 0===e&&(e=ec);var r=Yu[e];if(r&&!n)return new r(t);t=t||{},this.nodeType=1,this.nodeId=an(),this.ref=this.nodeId,this.type=e,this.attr=t.attr||{},this.style=t.style||{},this.classStyle=t.classStyle||{},this.event={},this.children=[],this.pureChildren=[]}function gn(e,t){nn(e).nodeMap[t.nodeId]=t}function bn(){var e={createFinish:global.callCreateFinish,upd
 ateFinish: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},t=rc.prototype;for(var n in e)!function(n){var r=e[n];t[n]=r?function(e,t){return r.apply(void 0,[e].concat(t))}:function(e,t){return nc(e,[{module:"dom",method:n,args:t}],"-1")}}(n);t.componentHandler=global.callNativeComponent||function(e,t,n,r,o){return nc(e,[{component:o.component,ref:t,method:n,args:r}])},t.moduleHandler=global.callNativeModule||function(e,t,n,r){return nc(e,[{module:t,method:n,args:r}])}}function wn(e,t){En(e)?console.warn('Service "'+e+'" has been registered already!'):(t=Object.assign({},t),ac.push({name:e,options:t}))}function On(e){ac.some(function(t,n){if(t.name===e)return ac.splice(n,1),!0})}function En(e){return
  xn(e)>=0}function xn(e){return ac.map(function(e){return e.name}).indexOf(e)}function Sn(e){var t,n=sc.exec(e);if(n)try{t=JSON.parse(n[1])}catch(e){}return t}function Cn(e,t,n){var r=Object.create(null);return r.service=Object.create(null),ac.forEach(function(o){var i=(o.name,o.options),a=i.create;if(a){var s=a(e,t,n);Object.assign(r.service,s),Object.assign(r,s.instance)}}),delete r.service.instance,Object.freeze(r.service),r}function kn(e,t,n,r){var o=uc[e];if(!o){o=Sn(t)||{},oc[o.framework]||(o.framework="Weex"),n=JSON.parse(JSON.stringify(n||{})),n.bundleVersion=o.version,n.env=JSON.parse(JSON.stringify(global.WXEnvironment||{})),console.debug("[JS Framework] create an "+o.framework+"@"+n.bundleVersion+" instance from "+n.bundleVersion);var i={info:o,config:n,created:Date.now(),framework:o.framework};return i.services=Cn(e,i,ic),uc[e]=i,oc[o.framework].createInstance(e,t,n,r,i)}return new Error('invalid instance id "'+e+'"')}function jn(e){cc[e]=function(){for(var t=[],n=argume
 nts.length;n--;)t[n]=arguments[n];"registerComponents"===e&&An(t[0]);for(var r in oc){var o=oc[r];o&&o[e]&&o[e].apply(o,t)}}}function An(e){Array.isArray(e)&&e.forEach(function(e){e&&e.type&&e.methods&&mn(e.type,e.methods)})}function In(e){cc[e]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=uc[r];if(o&&oc[o.framework]){var i=(a=oc[o.framework])[e].apply(a,t);return"refreshInstance"===e?ac.forEach(function(e){var t=e.options.refresh;t&&t(r,{info:o,runtime:ic})}):"destroyInstance"===e&&(ac.forEach(function(e){var t=e.options.destroy;t&&t(r,{info:o,runtime:ic})}),delete uc[r]),i}return new Error('invalid instance id "'+r+'"');var a}}function Tn(e,t){cc[t]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=uc[r];return o&&oc[o.framework]?(i=oc[o.framework])[e].apply(i,t):new Error('invalid instance id "'+r+'"');var i}}function Nn(e){ic=e||{},oc=ic.frameworks||{},bn();for(var t in oc){oc[t].init(e)}return["registerComponents","
 registerModules","registerMethods"].forEach(jn),["destroyInstance","refreshInstance","receiveTasks","getRoot"].forEach(In),Tn("receiveTasks","callJS"),cc}function Pn(e){this.nodeType=8,this.nodeId=an(),this.ref=this.nodeId,this.type="comment",this.value=e,this.children=[],this.pureChildren=[]}function Mn(e,t){this.id=e,this.batched=!1,this.updates=[],"function"==typeof t?Object.defineProperty(this,"handler",{configurable:!0,enumerable:!0,writable:!0,value:t}):console.error("[JS Runtime] invalid parameter, handler must be a function")}function $n(e,t){return void 0===t&&(t=[]),{module:"dom",method:e,args:t}}function Rn(e,t){var n=t||global.callNative;return"function"!=typeof n&&console.error("[JS Runtime] no default handler"),function(t){Array.isArray(t)||(t=[t]);for(var r=0;r<t.length;r++){var o=Fn(e,t[r],n);if(-1===o)return o}}}function Dn(e,t){return"dom"===e&&lc[t]&&"function"==typeof global[lc[t]]}function Fn(e,t,n){var r=t.module,o=t.method,i=t.args;return Dn(r,o)?global[lc[o]]
 .apply(global,[e].concat(i,["-1"])):n(e,[t],"-1")}function Ln(e,t,n){e=e?e.toString():"",this.id=e,this.URL=t,tn(e,this),this.nodeMap={};var r=Ln.Listener||Mn;this.listener=new r(e,n||Rn(e,Ln.handler)),this.taskCenter=new rc(e,n?function(e){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];return n.apply(void 0,t)}:Ln.handler),this.createDocumentElement()}function Vn(e,t){var n=t.attrs||{};for(var r in n)e.setAttr(r,n[r],!0);var o=t.style||{};for(var i in o)e.setStyle(i,o[i],!0)}function Un(){Jt(),Object.freeze(fc.Element),Object.freeze(fc.Comment),Object.freeze(fc.Listener),Object.freeze(fc.Document.prototype),Object.freeze(fc.Element.prototype),Object.freeze(fc.Comment.prototype),Object.freeze(fc.Listener.prototype)}function Wn(e,t){void 0===t&&(t={}),this.type=e||"message",this.data=t.data||null,this.origin=t.origin||"",this.source=t.source||null,this.ports=t.ports||[],this.target=null,this.timeStamp=Date.now()}function Bn(){}function qn(e,t,n,r){console.warn("[Upgrad
 e Warning] $userTrack will be removed in the next version!"),console.warn("[JS Framework] Vm#$userTrack is deprecated, please use \"require('@weex-module/userTrack').commit(type, name, comName, param)\" instead"),this._app.requireModule("userTrack").commit(e,t,n,r)}function zn(e,t){if(console.warn("[Upgrade Warning] $sendMtop will be removed in the next version!"),console.warn("[JS Framework] Vm#$sendMtop is deprecated, please use \"require('@weex-module/stream').sendMtop(params, callback)\" instead"),"undefined"==typeof window){this._app.requireModule("windvane").call({class:"MtopWVPlugin",method:"send",data:e},t)}else{this._app.requireModule("stream").sendMtop(e,t)}}function Jn(e,t){console.warn("[Upgrade Warning] $callWindvane will be removed in the next version!"),console.warn("[JS Framework] Vm#$callWindvane is deprecated, please use \"require('@weex-module/windvane').call(params, callback)\" instead"),this._app.requireModule("windvane").call(e,t)}function Hn(e,t){console.warn(
 "[Upgrade Warning] $setSpm will be removed in the next version!"),console.warn("[JS Framework] Vm#$setSpm is deprecated, please use \"require('@weex-module/pageInfo').setSpm(a, b)\" instead"),this._app.requireModule("pageInfo").setSpm(e,t)}function Gn(e){console.warn("[Upgrade Warning] $getUserInfo will be removed in the next version!"),console.warn("[JS Framework] Vm#$getUserInfo is deprecated, please use \"require('@weex-module/user').getUserInfo(callback)\" instead"),this._app.requireModule("user").getUserInfo(e)}function Xn(e){console.warn("[Upgrade Warning] $login will be removed in the next version!"),console.warn("[JS Framework] Vm#$login is deprecated, please use \"require('@weex-module/user').login(callback)\" instead"),this._app.requireModule("user").login(e)}function Kn(e){console.warn("[Upgrade Warning] $logout will be removed in the next version!"),console.warn("[JS Framework] Vm#$logout is deprecated, please use \"require('@weex-module/user').logout(callback)\" instead
 "),this._app.requireModule("user").logout(e)}var Zn,Qn={},Yn={},er=Object.freeze({init:e,registerComponents:t,registerModules:n,registerMethods:r,prepareInstance:o,createInstance:i,refreshInstance:a,destroyInstance:s,getRoot:u,receiveTasks:c}),tr="undefined"!=typeof window?window:void 0!==global?global:"undefined"!=typeof self?self:{},nr=f(function(e){e.exports=function(e,t){function n(e){return void 0===e||null===e}function r(e){return void 0!==e&&null!==e}function o(e){return!0===e}function i(e){return!1===e}function a(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e}function s(e){return null!==e&&"object"==typeof e}function u(e){return"[object Object]"===kn.call(e)}function c(e){return"[object RegExp]"===kn.call(e)}function l(e){var t=parseFloat(e);return t>=0&&Math.floor(t)===t&&isFinite(e)}function f(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function d(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Objec
 t.create(null),r=e.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function v(e,t){return An.call(e,t)}function y(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function m(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function _(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function g(e,t){for(var n in t)e[n]=t[n];return e}function b(e){for(var t={},n=0;n<e.length;n++)e[n]&&g(t,e[n]);return t}function w(e,t,n){}function O(e,t){if(e===t)return!0;var n=s(e),r=s(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var o=Array.isArray(e),i=Array.isArray(t);if(o&&i)return e.length===t.length&&e.every(function(e,n){return O(e,t[n])});if(o||i)return!1;var a=Object.keys(e),u=Object.keys(t);return a.length===u.length&
 &a.every(function(n){return O(e[n],t[n])})}catch(e){return!1}}function E(e,t){for(var n=0;n<e.length;n++)if(O(e[n],t))return n;return-1}function x(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function C(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function k(e){if(!Wn.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function j(e,t,n){if(Vn.errorHandler)Vn.errorHandler.call(null,e,t,n);else{if(!zn||"undefined"==typeof console)throw e;console.error(e)}}function A(e){return"function"==typeof e&&/native code/.test(e.toString())}function I(e){ar.target&&sr.push(ar.target),ar.target=e}function T(){ar.target=sr.pop()}function N(e,t,n){e.__proto__=t}function P(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];C(e,i,t[i])}}function M(e,t){if(s(e)){var n;return v(e,"__ob__")&&e.__ob__ instanceof dr?n=e.__ob__
 :fr.shouldConvert&&!er()&&(Array.isArray(e)||u(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new dr(e)),t&&n&&n.vmCount++,n}}function $(e,t,n,r,o){var i=new ar,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,u=a&&a.set,c=!o&&M(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ar.target&&(i.depend(),c&&c.dep.depend(),Array.isArray(t)&&F(t)),t},set:function(t){var r=s?s.call(e):n;t===r||t!==t&&r!==r||(u?u.call(e,t):n=t,c=!o&&M(t),i.notify())}})}}function R(e,t,n){if(Array.isArray(e)&&l(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(v(e,t))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?($(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function D(e,t){if(Array.isArray(e)&&l(t))return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||v(e,t)&&(delete e[t],n&&n.dep.notify())}function F(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Arra
 y.isArray(t)&&F(t)}function L(e,t){if(!t)return e;for(var n,r,o,i=Object.keys(t),a=0;a<i.length;a++)n=i[a],r=e[n],o=t[n],v(e,n)?u(r)&&u(o)&&L(r,o):R(e,n,o);return e}function V(e,t,n){return n?e||t?function(){var r="function"==typeof t?t.call(n):t,o="function"==typeof e?e.call(n):void 0;return r?L(r,o):o}:void 0:t?e?function(){return L("function"==typeof t?t.call(this):t,"function"==typeof e?e.call(this):e)}:t:e}function U(e,t){return t?e?e.concat(t):Array.isArray(t)?t:[t]:e}function W(e,t){var n=Object.create(e||null);return t?g(n,t):n}function B(e){var t=e.props;if(t){var n,r,o,i={};if(Array.isArray(t))for(n=t.length;n--;)"string"==typeof(r=t[n])&&(o=Tn(r),i[o]={type:null});else if(u(t))for(var a in t)r=t[a],o=Tn(a),i[o]=u(r)?r:{type:r};e.props=i}}function q(e){var t=e.inject;if(Array.isArray(t))for(var n=e.inject={},r=0;r<t.length;r++)n[t[r]]=t[r]}function z(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function J(e,t,n){func
 tion r(r){var o=pr[r]||hr;u[r]=o(e[r],t[r],n,r)}"function"==typeof t&&(t=t.options),B(t),q(t),z(t);var o=t.extends;if(o&&(e=J(e,o,n)),t.mixins)for(var i=0,a=t.mixins.length;i<a;i++)e=J(e,t.mixins[i],n);var s,u={};for(s in e)r(s);for(s in t)v(e,s)||r(s);return u}function H(e,t,n,r){if("string"==typeof n){var o=e[t];if(v(o,n))return o[n];var i=Tn(n);if(v(o,i))return o[i];var a=Nn(i);if(v(o,a))return o[a];var s=o[n]||o[i]||o[a];return s}}function G(e,t,n,r){var o=t[e],i=!v(n,e),a=n[e];if(Z(Boolean,o.type)&&(i&&!v(o,"default")?a=!1:Z(String,o.type)||""!==a&&a!==Mn(e)||(a=!0)),void 0===a){a=X(r,o,e);var s=fr.shouldConvert;fr.shouldConvert=!0,M(a),fr.shouldConvert=s}return a}function X(e,t,n){if(v(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==K(t.type)?r.call(e):r}}function K(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function Z(e,t){if(!Array.is
 Array(t))return K(t)===K(e);for(var n=0,r=t.length;n<r;n++)if(K(t[n])===K(e))return!0;return!1}function Q(e){return new vr(void 0,void 0,void 0,String(e))}function Y(e){var t=new vr(e.tag,e.data,e.children,e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.isCloned=!0,t}function ee(e){for(var t=e.length,n=new Array(t),r=0;r<t;r++)n[r]=Y(e[r]);return n}function te(e){function t(){var e=arguments,n=t.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=n.slice(),o=0;o<r.length;o++)r[o].apply(null,e)}return t.fns=e,t}function ne(e,t,r,o,i){var a,s,u,c;for(a in e)s=e[a],u=t[a],c=gr(a),n(s)||(n(u)?(n(s.fns)&&(s=e[a]=te(s)),r(c.name,s,c.once,c.capture,c.passive)):s!==u&&(u.fns=s,e[a]=u));for(a in t)n(e[a])&&(c=gr(a),o(c.name,t[a],c.capture))}function re(e,t,i){function a(){i.apply(this,arguments),h(s.fns,a)}var s,u=e[t];n(u)?s=te([a]):r(u.fns)&&o(u.merged)?(s=u,s.fns.push(a)):s=te([u,a]),s.mer
 ged=!0,e[t]=s}function oe(e,t,o){var i=t.options.props;if(!n(i)){var a={},s=e.attrs,u=e.props;if(r(s)||r(u))for(var c in i){var l=Mn(c);ie(a,u,c,l,!0)||ie(a,s,c,l,!1)}return a}}function ie(e,t,n,o,i){if(r(t)){if(v(t,n))return e[n]=t[n],i||delete t[n],!0;if(v(t,o))return e[n]=t[o],i||delete t[o],!0}return!1}function ae(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function se(e){return a(e)?[Q(e)]:Array.isArray(e)?ce(e):void 0}function ue(e){return r(e)&&r(e.text)&&i(e.isComment)}function ce(e,t){var i,s,u,c=[];for(i=0;i<e.length;i++)s=e[i],n(s)||"boolean"==typeof s||(u=c[c.length-1],Array.isArray(s)?c.push.apply(c,ce(s,(t||"")+"_"+i)):a(s)?ue(u)?u.text+=String(s):""!==s&&c.push(Q(s)):ue(s)&&ue(u)?c[c.length-1]=Q(u.text+s.text):(o(e._isVList)&&r(s.tag)&&n(s.key)&&r(t)&&(s.key="__vlist"+t+"_"+i+"__"),c.push(s)));return c}function le(e,t){return e.__esModule&&e.default&&(e=e.default),s(e)?t.extend(e):e}function fe(e,t,n,r,o){var
  i=_r();return i.asyncFactory=e,i.asyncMeta={data:t,context:n,children:r,tag:o},i}function de(e,t,i){if(o(e.error)&&r(e.errorComp))return e.errorComp;if(r(e.resolved))return e.resolved;if(o(e.loading)&&r(e.loadingComp))return e.loadingComp;if(!r(e.contexts)){var a=e.contexts=[i],u=!0,c=function(){for(var e=0,t=a.length;e<t;e++)a[e].$forceUpdate()},l=x(function(n){e.resolved=le(n,t),u||c()}),f=x(function(t){r(e.errorComp)&&(e.error=!0,c())}),d=e(l,f);return s(d)&&("function"==typeof d.then?n(e.resolved)&&d.then(l,f):r(d.component)&&"function"==typeof d.component.then&&(d.component.then(l,f),r(d.error)&&(e.errorComp=le(d.error,t)),r(d.loading)&&(e.loadingComp=le(d.loading,t),0===d.delay?e.loading=!0:setTimeout(function(){n(e.resolved)&&n(e.error)&&(e.loading=!0,c())},d.delay||200)),r(d.timeout)&&setTimeout(function(){n(e.resolved)&&f(null)},d.timeout))),u=!1,e.loading?e.loadingComp:e.resolved}e.contexts.push(i)}function pe(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var n=e[t];
 if(r(n)&&r(n.componentOptions))return n}}function he(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&me(e,t)}function ve(e,t,n){n?mr.$once(e,t):mr.$on(e,t)}function ye(e,t){mr.$off(e,t)}function me(e,t,n){mr=e,ne(t,n||{},ve,ye,e)}function _e(e,t){var n={};if(!e)return n;for(var r=[],o=0,i=e.length;o<i;o++){var a=e[o];if(a.context!==t&&a.functionalContext!==t||!a.data||null==a.data.slot)r.push(a);else{var s=a.data.slot,u=n[s]||(n[s]=[]);"template"===a.tag?u.push.apply(u,a.children):u.push(a)}}return r.every(ge)||(n.default=r),n}function ge(e){return e.isComment||" "===e.text}function be(e,t){t=t||{};for(var n=0;n<e.length;n++)Array.isArray(e[n])?be(e[n],t):t[e[n].key]=e[n].fn;return t}function we(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._i
 sDestroyed=!1,e._isBeingDestroyed=!1}function Oe(e,t,n){e.$el=t,e.$options.render||(e.$options.render=_r),ke(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},e._watcher=new jr(e,r,w),n=!1,null==e.$vnode&&(e._isMounted=!0,ke(e,"mounted")),e}function Ee(e,t,n,r,o){var i=!!(o||e.$options._renderChildren||r.data.scopedSlots||e.$scopedSlots!==Un);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=o,e.$attrs=r.data&&r.data.attrs,e.$listeners=n,t&&e.$options.props){fr.shouldConvert=!1;for(var a=e._props,s=e.$options._propKeys||[],u=0;u<s.length;u++){var c=s[u];a[c]=G(c,e.$options.props,t,e)}fr.shouldConvert=!0,e.$options.propsData=t}if(n){var l=e.$options._parentListeners;e.$options._parentListeners=n,me(e,n,l)}i&&(e.$slots=_e(o,r.context),e.$forceUpdate())}function xe(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Se(e,t){if(t){if(e._directInactive=!1,xe(e))return}else if(e._directInactive)return;if(e._
 inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Se(e.$children[n]);ke(e,"activated")}}function Ce(e,t){if(!(t&&(e._directInactive=!0,xe(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)Ce(e.$children[n]);ke(e,"deactivated")}}function ke(e,t){var n=e.$options[t];if(n)for(var r=0,o=n.length;r<o;r++)try{n[r].call(e)}catch(n){j(n,e,t+" hook")}e._hasHookEvent&&e.$emit("hook:"+t)}function je(){Cr=wr.length=Or.length=0,Er={},xr=Sr=!1}function Ae(){Sr=!0;var e,t;for(wr.sort(function(e,t){return e.id-t.id}),Cr=0;Cr<wr.length;Cr++)e=wr[Cr],t=e.id,Er[t]=null,e.run();var n=Or.slice(),r=wr.slice();je(),Ne(n),Ie(r),nr&&Vn.devtools&&nr.emit("flush")}function Ie(e){for(var t=e.length;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&ke(r,"updated")}}function Te(e){e._inactive=!1,Or.push(e)}function Ne(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Se(e[t],!0)}function Pe(e){var t=e.id;if(null==Er[t]){if(Er[t]=!0,Sr){for(var n=wr.length-1;
 n>Cr&&wr[n].id>e.id;)n--;wr.splice(n+1,0,e)}else wr.push(e);xr||(xr=!0,or(Ae))}}function Me(e){Ar.clear(),$e(e,Ar)}function $e(e,t){var n,r,o=Array.isArray(e);if((o||s(e))&&Object.isExtensible(e)){if(e.__ob__){var i=e.__ob__.dep.id;if(t.has(i))return;t.add(i)}if(o)for(n=e.length;n--;)$e(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)$e(e[r[n]],t)}}function Re(e,t,n){Ir.get=function(){return this[t][n]},Ir.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Ir)}function De(e){e._watchers=[];var t=e.$options;t.props&&Fe(e,t.props),t.methods&&qe(e,t.methods),t.data?Le(e):M(e._data={},!0),t.computed&&Ue(e,t.computed),t.watch&&t.watch!==Xn&&ze(e,t.watch)}function Fe(e,t){var n=e.$options.propsData||{},r=e._props={},o=e.$options._propKeys=[],i=!e.$parent;fr.shouldConvert=i;for(var a in t)!function(i){o.push(i);var a=G(i,t,n,e);$(r,i,a),i in e||Re(e,"_props",i)}(a);fr.shouldConvert=!0}function Le(e){var t=e.$options.data;t=e._data="function"==typeof t?Ve(t,e):t||{},u(t)||(t={});for(
 var n=Object.keys(t),r=e.$options.props,o=(e.$options.methods,n.length);o--;){var i=n[o];r&&v(r,i)||S(i)||Re(e,"_data",i)}M(t,!0)}function Ve(e,t){try{return e.call(t)}catch(e){return j(e,t,"data()"),{}}}function Ue(e,t){var n=e._computedWatchers=Object.create(null);for(var r in t){var o=t[r],i="function"==typeof o?o:o.get;n[r]=new jr(e,i||w,w,Tr),r in e||We(e,r,o)}}function We(e,t,n){"function"==typeof n?(Ir.get=Be(t),Ir.set=w):(Ir.get=n.get?!1!==n.cache?Be(t):n.get:w,Ir.set=n.set?n.set:w),Object.defineProperty(e,t,Ir)}function Be(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ar.target&&t.depend(),t.value}}function qe(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?w:m(t[n],e)}function ze(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)Je(e,n,r[o]);else Je(e,n,r)}}function Je(e,t,n,r){return u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function He(e){var t=e.
 $options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function Ge(e){var t=Xe(e.$options.inject,e);t&&(fr.shouldConvert=!1,Object.keys(t).forEach(function(n){$(e,n,t[n])}),fr.shouldConvert=!0)}function Xe(e,t){if(e){for(var n=Object.create(null),r=rr?Reflect.ownKeys(e):Object.keys(e),o=0;o<r.length;o++)for(var i=r[o],a=e[i],s=t;s;){if(s._provided&&a in s._provided){n[i]=s._provided[a];break}s=s.$parent}return n}}function Ke(e,t,n,o,i){var a={},s=e.options.props;if(r(s))for(var u in s)a[u]=G(u,s,t||{});else r(n.attrs)&&Ze(a,n.attrs),r(n.props)&&Ze(a,n.props);var c=Object.create(o),l=function(e,t,n,r){return rt(c,e,t,n,r,!0)},f=e.options.render.call(null,l,{data:n,props:a,children:i,parent:o,listeners:n.on||{},injections:Xe(e.options.inject,o),slots:function(){return _e(i,o)}});return f instanceof vr&&(f.functionalContext=o,f.functionalOptions=e.options,n.slot&&((f.data||(f.data={})).slot=n.slot)),f}function Ze(e,t){for(var n in t)e[Tn(n)]=t[n]}function Qe(e,t,i,a,u){if(!
 n(e)){var c=i.$options._base;if(s(e)&&(e=c.extend(e)),"function"==typeof e){var l;if(n(e.cid)&&(l=e,void 0===(e=de(l,c,i))))return fe(l,t,i,a,u);t=t||{},_t(e),r(t.model)&&nt(e.options,t);var f=oe(t,e,u);if(o(e.options.functional))return Ke(e,f,t,i,a);var d=t.on;if(t.on=t.nativeOn,o(e.options.abstract)){var p=t.slot;t={},p&&(t.slot=p)}et(t);var h=e.options.name||u;return new vr("vue-component-"+e.cid+(h?"-"+h:""),t,void 0,void 0,void 0,i,{Ctor:e,propsData:f,listeners:d,tag:u,children:a},l)}}}function Ye(e,t,n,o){var i=e.componentOptions,a={_isComponent:!0,parent:t,propsData:i.propsData,_componentTag:i.tag,_parentVnode:e,_parentListeners:i.listeners,_renderChildren:i.children,_parentElm:n||null,_refElm:o||null},s=e.data.inlineTemplate;return r(s)&&(a.render=s.render,a.staticRenderFns=s.staticRenderFns),new i.Ctor(a)}function et(e){e.hook||(e.hook={});for(var t=0;t<Pr.length;t++){var n=Pr[t],r=e.hook[n],o=Nr[n];e.hook[n]=r?tt(o,r):o}}function tt(e,t){return function(n,r,o,i){e(n,r,o,i)
 ,t(n,r,o,i)}}function nt(e,t){var n=e.model&&e.model.prop||"value",o=e.model&&e.model.event||"input";(t.props||(t.props={}))[n]=t.model.value;var i=t.on||(t.on={});r(i[o])?i[o]=[t.model.callback].concat(i[o]):i[o]=t.model.callback}function rt(e,t,n,r,i,s){return(Array.isArray(n)||a(n))&&(i=r,r=n,n=void 0),o(s)&&(i=$r),ot(e,t,n,r,i)}function ot(e,t,n,o,i){if(r(n)&&r(n.__ob__))return _r();if(r(n)&&r(n.is)&&(t=n.is),!t)return _r();Array.isArray(o)&&"function"==typeof o[0]&&(n=n||{},n.scopedSlots={default:o[0]},o.length=0),i===$r?o=se(o):i===Mr&&(o=ae(o));var a,s;if("string"==typeof t){var u;s=Vn.getTagNamespace(t),a=Vn.isReservedTag(t)?new vr(Vn.parsePlatformTagName(t),n,o,void 0,void 0,e):r(u=H(e.$options,"components",t))?Qe(u,n,e,o,t):new vr(t,n,o,void 0,void 0,e)}else a=Qe(t,n,e,o);return r(a)?(s&&it(a,s),a):_r()}function it(e,t){if(e.ns=t,"foreignObject"!==e.tag&&r(e.children))for(var o=0,i=e.children.length;o<i;o++){var a=e.children[o];r(a.tag)&&n(a.ns)&&it(a,t)}}function at(e,t){
 var n,o,i,a,u;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),o=0,i=e.length;o<i;o++)n[o]=t(e[o],o);else if("number"==typeof e)for(n=new Array(e),o=0;o<e;o++)n[o]=t(o+1,o);else if(s(e))for(a=Object.keys(e),n=new Array(a.length),o=0,i=a.length;o<i;o++)u=a[o],n[o]=t(e[u],u,o);return r(n)&&(n._isVList=!0),n}function st(e,t,n,r){var o=this.$scopedSlots[e];if(o)return n=n||{},r&&(n=g(g({},r),n)),o(n)||t;var i=this.$slots[e];return i||t}function ut(e){return H(this.$options,"filters",e,!0)||Rn}function ct(e,t,n){var r=Vn.keyCodes[t]||n;return Array.isArray(r)?-1===r.indexOf(e):r!==e}function lt(e,t,n,r,o){if(n)if(s(n)){Array.isArray(n)&&(n=b(n));var i;for(var a in n)!function(a){if("class"===a||"style"===a||jn(a))i=e;else{var s=e.attrs&&e.attrs.type;i=r||Vn.mustUseProp(t,s,a)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}if(!(a in i)&&(i[a]=n[a],o)){(e.on||(e.on={}))["update:"+a]=function(e){n[a]=e}}}(a)}else;return e}function ft(e,t){var n=this._staticTrees[e];retur
 n n&&!t?Array.isArray(n)?ee(n):Y(n):(n=this._staticTrees[e]=this.$options.staticRenderFns[e].call(this._renderProxy),pt(n,"__static__"+e,!1),n)}function dt(e,t,n){return pt(e,"__once__"+t+(n?"_"+n:""),!0),e}function pt(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&ht(e[r],t+"_"+r,n);else ht(e,t,n)}function ht(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function vt(e,t){if(t)if(u(t)){var n=e.on=e.on?g({},e.on):{};for(var r in t){var o=n[r],i=t[r];n[r]=o?[].concat(i,o):i}}else;return e}function yt(e){e._vnode=null,e._staticTrees=null;var t=e.$vnode=e.$options._parentVnode,n=t&&t.context;e.$slots=_e(e.$options._renderChildren,n),e.$scopedSlots=Un,e._c=function(t,n,r,o){return rt(e,t,n,r,o,!1)},e.$createElement=function(t,n,r,o){return rt(e,t,n,r,o,!0)};var r=t&&t.data;$(e,"$attrs",r&&r.attrs,null,!0),$(e,"$listeners",e.$options._parentListeners,null,!0)}function mt(e,t){var n=e.$options=Object.create(e.constructor.options);n.parent=t.parent,n.propsData=
 t.propsData,n._parentVnode=t._parentVnode,n._parentListeners=t._parentListeners,n._renderChildren=t._renderChildren,n._componentTag=t._componentTag,n._parentElm=t._parentElm,n._refElm=t._refElm,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}function _t(e){var t=e.options;if(e.super){var n=_t(e.super);if(n!==e.superOptions){e.superOptions=n;var r=gt(e);r&&g(e.extendOptions,r),t=e.options=J(n,e.extendOptions),t.name&&(t.components[t.name]=e)}}return t}function gt(e){var t,n=e.options,r=e.extendOptions,o=e.sealedOptions;for(var i in n)n[i]!==o[i]&&(t||(t={}),t[i]=bt(n[i],r[i],o[i]));return t}function bt(e,t,n){if(Array.isArray(e)){var r=[];n=Array.isArray(n)?n:[n],t=Array.isArray(t)?t:[t];for(var o=0;o<e.length;o++)(t.indexOf(e[o])>=0||n.indexOf(e[o])<0)&&r.push(e[o]);return r}return e}function wt(e){this._init(e)}function Ot(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=_(arguments,1);return n.uns
 hift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}function Et(e){e.mixin=function(e){return this.options=J(this.options,e),this}}function xt(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,o=e._Ctor||(e._Ctor={});if(o[r])return o[r];var i=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=J(n.options,e),a.super=n,a.options.props&&St(a),a.options.computed&&Ct(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Fn.forEach(function(e){a[e]=n[e]}),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=g({},a.options),o[r]=a,a}}function St(e){var t=e.options.props;for(var n in t)Re(e.prototype,"_props",n)}function Ct(e){var t=e.options.computed;for(var n in t)We(e.prototype,n,t[n])}function kt(e){Fn.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&u(n)&&(n.name=n.na
 me||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function jt(e){return e&&(e.Ctor.options.name||e.tag)}function At(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!c(e)&&e.test(t)}function It(e,t,n){for(var r in e){var o=e[r];if(o){var i=jt(o.componentOptions);i&&!n(i)&&(o!==t&&Tt(o),e[r]=null)}}}function Tt(e){e&&e.componentInstance.$destroy()}function Nt(e){return new t.Element(e)}function Pt(e,n){return new t.Element(e+":"+n)}function Mt(e){return new t.TextNode(e)}function $t(e){return new t.Comment(e)}function Rt(e,t,n){if(3!==t.nodeType)e.insertBefore(t,n);else if("text"===e.type)e.setAttr("value",t.text),t.parentNode=e;else{var r=Nt("text");r.setAttr("value",t.text),e.insertBefore(r,n)}}function Dt(e,t){if(3===t.nodeType)return void e.setAttr("value","");e.removeChild(t)}function Ft(e,t){if(3!==t.nodeType)e.appendChild(t);else if(
 "text"===e.type)e.setAttr("value",t.text),t.parentNode=e;else{var n=Nt("text")
-;n.setAttr("value",t.text),e.appendChild(n)}}function Lt(e){return e.parentNode}function Vt(e){return e.nextSibling}function Ut(e){return e.type}function Wt(e,t){e.parentNode.setAttr("value",t)}function Bt(e,t,n){e.setAttr(t,n)}function qt(e,t){var n=e.data.ref;if(n){var r=e.context,o=e.componentInstance||e.elm,i=r.$refs;t?Array.isArray(i[n])?h(i[n],o):i[n]===o&&(i[n]=void 0):e.data.refInFor?Array.isArray(i[n])?i[n].indexOf(o)<0&&i[n].push(o):i[n]=[o]:i[n]=o}}function zt(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&r(e.data)===r(t.data)&&Jt(e,t)||o(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&n(t.asyncFactory.error))}function Jt(e,t){if("input"!==e.tag)return!0;var n;return(r(n=e.data)&&r(n=n.attrs)&&n.type)===(r(n=t.data)&&r(n=n.attrs)&&n.type)}function Ht(e,t,n){var o,i,a={};for(o=t;o<=n;++o)i=e[o].key,r(i)&&(a[i]=o);return a}function Gt(e,t){(e.data.directives||t.data.directives)&&Xt(e,t)}function Xt(e,t){var n,r,o,i=e===qr,a=t===qr,s=Kt(e.data
 .directives,e.context),u=Kt(t.data.directives,t.context),c=[],l=[];for(n in u)r=s[n],o=u[n],r?(o.oldValue=r.value,Qt(o,"update",t,e),o.def&&o.def.componentUpdated&&l.push(o)):(Qt(o,"bind",t,e),o.def&&o.def.inserted&&c.push(o));if(c.length){var f=function(){for(var n=0;n<c.length;n++)Qt(c[n],"inserted",t,e)};i?re(t.data.hook||(t.data.hook={}),"insert",f):f()}if(l.length&&re(t.data.hook||(t.data.hook={}),"postpatch",function(){for(var n=0;n<l.length;n++)Qt(l[n],"componentUpdated",t,e)}),!i)for(n in s)u[n]||Qt(s[n],"unbind",e,e,a)}function Kt(e,t){var n=Object.create(null);if(!e)return n;var r,o;for(r=0;r<e.length;r++)o=e[r],o.modifiers||(o.modifiers=Hr),n[Zt(o)]=o,o.def=H(t.$options,"directives",o.name,!0);return n}function Zt(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function Qt(e,t,n,r,o){var i=e.def&&e.def[t];if(i)try{i(n.elm,e,n,r,o)}catch(r){j(r,n.context,"directive "+e.name+" "+t+" hook")}}function Yt(e,t){if(e.data.attrs||t.data.attrs){var n,r,o=t.e
 lm,i=e.data.attrs||{},a=t.data.attrs||{};a.__ob__&&(a=t.data.attrs=g({},a));for(n in a)r=a[n],i[n]!==r&&o.setAttr(n,r);for(n in i)null==a[n]&&o.setAttr(n)}}function en(e,t){var n=t.elm,r=t.context,o=t.data,i=e.data;if(o.staticClass||o.class||i&&(i.staticClass||i.class)){var a=[],s=i.staticClass;s&&a.push.apply(a,s),i.class&&a.push.apply(a,i.class);var u=[],c=o.staticClass;c&&u.push.apply(u,c),o.class&&u.push.apply(u,o.class);var l=tn(a,u,r);for(var f in l)n.setStyle(f,l[f])}}function tn(e,t,n){var r=n.$options.style||{},o={};return t.forEach(function(e){g(o,r[e])}),e.forEach(function(e){var t=r[e];for(var n in t)o.hasOwnProperty(n)||(o[n]="")}),o}function nn(e,t,n,r){if(r)return void console.log("Weex do not support event in bubble phase.");if(n){var o=t,i=Vr;t=function(t){null!==(1===arguments.length?o(t):o.apply(null,arguments))&&rn(e,null,null,i)}}Vr.addEvent(e,t)}function rn(e,t,n,r){(r||Vr).removeEvent(e)}function on(e,t){if(e.data.on||t.data.on){var n=t.data.on||{},r=e.data.on
 ||{};Vr=t.elm,ne(n,r,nn,rn,t.context)}}function an(e,t){if(!t.data.staticStyle)return void sn(e,t);var n=t.elm,r=t.data.staticStyle;for(var o in r)r[o]&&n.setStyle(Qr(o),r[o]);sn(e,t)}function sn(e,t){if(e.data.style||t.data.style){var n,r,o=t.elm,i=e.data.style||{},a=t.data.style||{},s=a.__ob__;Array.isArray(a)&&(a=t.data.style=un(a)),s&&(a=t.data.style=g({},a));for(r in i)a[r]||o.setStyle(Qr(r),"");for(r in a)n=a[r],o.setStyle(Qr(r),n)}}function un(e){for(var t={},n=0;n<e.length;n++)e[n]&&g(t,e[n]);return t}function cn(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&g(t,eo(e.name||"v")),g(t,e),t}return"string"==typeof e?eo(e):void 0}}function ln(e,t){var n=t.elm;n._leaveCb&&(n._leaveCb.cancelled=!0,n._leaveCb());var r=cn(t.data.transition);if(r&&!n._enterCb){for(var o=r.enterClass,i=r.enterToClass,a=r.enterActiveClass,s=r.appearClass,u=r.appearToClass,c=r.appearActiveClass,l=r.beforeEnter,f=r.enter,d=r.afterEnter,p=r.enterCancelled,h=r.beforeAppear,v=r.appear,y=r.afterA
 ppear,m=r.appearCancelled,_=br,g=br.$vnode;g&&g.parent;)g=g.parent,_=g.context;var b=!_._isMounted||!t.isRootInsert;if(!b||v||""===v){var O=b?s:o,E=b?u:i,S=b?c:a,C=b?h||l:l,k=b&&"function"==typeof v?v:f,j=b?y||d:d,A=b?m||p:p,I=k&&(k._length||k.length)>1,T=t.context.$options.style||{},N=T[O],P=T["@TRANSITION"]&&T["@TRANSITION"][S]||{},M=dn(n,T,O,E,S,t.context),$=Object.keys(M).length>0,R=n._enterCb=x(function(){R.cancelled?A&&A(n):j&&j(n),n._enterCb=null});if(setTimeout(function(){var e=n.parentNode,r=e&&e._pending&&e._pending[t.key];if(r&&r.context===t.context&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),k&&k(n,R),$){t.context.$requireWeexModule("animation").transition(n.ref,{styles:M,duration:P.duration||0,delay:P.delay||0,timingFunction:P.timingFunction||"linear"},I?w:R)}else I||R()},16),C&&C(n),N)for(var D in N)n.setStyle(D,N[D]);$||I||R()}}}function fn(e,t){function n(){function t(){n.transition(r.ref,{styles:y,duration:m.duration||0,delay:m.delay||0,timingFunction:m.timingF
 unction||"linear"},p?w:_)}var n=e.context.$requireWeexModule("animation");_.cancelled||(e.data.show||((r.parentNode._pending||(r.parentNode._pending={}))[e.key]=e),u&&u(r),v?n.transition(r.ref,{styles:v},t):t(),c&&c(r,_),y||p||_())}var r=e.elm;r._enterCb&&(r._enterCb.cancelled=!0,r._enterCb());var o=cn(e.data.transition);if(!o)return t();if(!r._leaveCb){var i=o.leaveClass,a=o.leaveToClass,s=o.leaveActiveClass,u=o.beforeLeave,c=o.leave,l=o.afterLeave,f=o.leaveCancelled,d=o.delayLeave,p=c&&(c._length||c.length)>1,h=e.context.$options.style||{},v=h[i],y=h[a]||h[s],m=h["@TRANSITION"]&&h["@TRANSITION"][s]||{},_=r._leaveCb=x(function(){r.parentNode&&r.parentNode._pending&&(r.parentNode._pending[e.key]=null),_.cancelled?f&&f(r):(t(),l&&l(r)),r._leaveCb=null});d?d(n):n()}}function dn(e,t,n,r,o,i){var a={},s=t[n],u=t[r],c=t[o];if(s)for(var l in s)a[l]=e.style[l];if(c)for(var f in c)0!==f.indexOf("transition")&&(a[f]=c[f]);return u&&g(a,u),a}function pn(e){return e.tag?e.tag.replace(/vue\-com
 ponent\-(\d+\-)?/,""):""}function hn(e){return e.children&&1===e.children.length&&!e.children[0].tag}function vn(e){var t=String(e).match(ao);return t?Number(t[1]):e}function yn(e){if(e&&e.data){var t=e.data,n=t.staticStyle,r=t.staticClass;if(e.data.style||e.data.class||n||r){var o=Object.assign({},n,e.data.style),i=e.context.$options.style||{};[].concat(r,e.data.class).forEach(function(e){e&&i[e]&&Object.assign(o,i[e])});for(var a in o)o[a]=vn(o[a]);return o}}}function mn(e){if(e.length)return e.map(function(e){var t=pn(e),n={type:t};if(t){if(n.style=yn(e),e.data&&(n.attr=e.data.attrs,e.data.on&&(n.events=e.data.on)),"span"===t&&hn(e))return n.attr=n.attr||{},n.attr.value=e.children[0].text.trim(),n}else n.type="span",n.attr={value:(e.text||"").trim()};return e.children&&e.children.length&&(n.children=mn(e.children)),n})}function _n(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?_n(pe(t.children)):e}function gn(e){var t={},n=e.$options;for(var r in n.propsData)t[r
 ]=e[r];var o=n._parentListeners;for(var i in o)t[Tn(i)]=o[i];return t}function bn(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}function wn(e){for(;e=e.parent;)if(e.data.transition)return!0}function On(e,t){return t.key===e.key&&t.tag===e.tag}function En(e){return e.isComment&&e.asyncFactory}function xn(){}function Sn(){}function Cn(e,n){var r=new t.Comment("root");return r.hasAttribute=r.removeAttribute=function(){},n.documentElement.appendChild(r),r}var kn=Object.prototype.toString,jn=(p("slot,component",!0),p("key,ref,slot,is")),An=Object.prototype.hasOwnProperty,In=/-(\w)/g,Tn=y(function(e){return e.replace(In,function(e,t){return t?t.toUpperCase():""})}),Nn=y(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),Pn=/([^-])([A-Z])/g,Mn=y(function(e){return e.replace(Pn,"$1-$2").replace(Pn,"$1-$2").toLowerCase()}),$n=function(e,t,n){return!1},Rn=function(e){return e},Dn="data-server-rendered",Fn=["component","directive","filt
 er"],Ln=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated"],Vn={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:$n,isReservedAttr:$n,isUnknownElement:$n,getTagNamespace:w,parsePlatformTagName:Rn,mustUseProp:$n,_lifecycleHooks:Ln},Un=Object.freeze({}),Wn=/[^\w.$]/,Bn=w,qn="__proto__"in{},zn="undefined"!=typeof window,Jn=zn&&window.navigator.userAgent.toLowerCase(),Hn=(Jn&&/msie|trident/.test(Jn),Jn&&Jn.indexOf("msie 9.0"),Jn&&Jn.indexOf("edge/")>0),Gn=(Jn&&Jn.indexOf("android"),Jn&&/iphone|ipad|ipod|ios/.test(Jn)),Xn=(Jn&&/chrome\/\d+/.test(Jn),{}.watch),Kn=!1;if(zn)try{var Zn={};Object.defineProperty(Zn,"passive",{get:function(){Kn=!0}}),window.addEventListener("test-passive",null,Zn)}catch(e){}var Qn,Yn,er=function(){return void 0===Qn&&(Qn=!zn&&void 0!==tr&&"ser
 ver"===tr.process.env.VUE_ENV),Qn},nr=zn&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,rr="undefined"!=typeof Symbol&&A(Symbol)&&"undefined"!=typeof Reflect&&A(Reflect.ownKeys),or=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t<e.length;t++)e[t]()}var t,n=[],r=!1;if("undefined"!=typeof Promise&&A(Promise)){var o=Promise.resolve(),i=function(e){console.error(e)};t=function(){o.then(e).catch(i),Gn&&setTimeout(w)}}else if("undefined"==typeof MutationObserver||!A(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())t=function(){setTimeout(e,0)};else{var a=1,s=new MutationObserver(e),u=document.createTextNode(String(a));s.observe(u,{characterData:!0}),t=function(){a=(a+1)%2,u.data=String(a)}}return function(e,o){var i;if(n.push(function(){if(e)try{e.call(o)}catch(e){j(e,o,"nextTick")}else i&&i(o)}),r||(r=!0,t()),!e&&"undefined"!=typeof Promise)return new Promise(function(e,t){i=e})}}();Yn="undefined"!=typeof Set&&A(Set)?Set:function(){func
 tion e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ir=0,ar=function(){this.id=ir++,this.subs=[]};ar.prototype.addSub=function(e){this.subs.push(e)},ar.prototype.removeSub=function(e){h(this.subs,e)},ar.prototype.depend=function(){ar.target&&ar.target.addDep(this)},ar.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},ar.target=null;var sr=[],ur=Array.prototype,cr=Object.create(ur);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=ur[e];C(cr,e,function(){for(var n=arguments,r=[],o=arguments.length;o--;)r[o]=n[o];var i,a=t.apply(this,r),s=this.__ob__;switch(e){case"push":case"unshift":i=r;break;case"splice":i=r.slice(2)}return i&&s.observeArray(i),s.dep.notify(),a})});var lr=Object.getOwnPropertyNames(cr),fr={shouldConvert:!0},dr=function(e){if(this.val
 ue=e,this.dep=new ar,this.vmCount=0,C(e,"__ob__",this),Array.isArray(e)){(qn?N:P)(e,cr,lr),this.observeArray(e)}else this.walk(e)};dr.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)$(e,t[n],e[t[n]])},dr.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)M(e[t])};var pr=Vn.optionMergeStrategies;pr.data=function(e,t,n){return n?V(e,t,n):t&&"function"!=typeof t?e:V.call(this,e,t)},Ln.forEach(function(e){pr[e]=U}),Fn.forEach(function(e){pr[e+"s"]=W}),pr.watch=function(e,t){if(e===Xn&&(e=void 0),t===Xn&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var n={};g(n,e);for(var r in t){var o=n[r],i=t[r];o&&!Array.isArray(o)&&(o=[o]),n[r]=o?o.concat(i):Array.isArray(i)?i:[i]}return n},pr.props=pr.methods=pr.inject=pr.computed=function(e,t){if(!e)return t;var n=Object.create(null);return g(n,e),t&&g(n,t),n},pr.provide=V;var hr=function(e,t){return void 0===t?e:t},vr=function(e,t,n,r,o,i,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,th
 is.elm=o,this.ns=void 0,this.context=i,this.functionalContext=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},yr={child:{}};yr.child.get=function(){return this.componentInstance},Object.defineProperties(vr.prototype,yr);var mr,_r=function(e){void 0===e&&(e="");var t=new vr;return t.text=e,t.isComment=!0,t},gr=y(function(e){var t="&"===e.charAt(0);e=t?e.slice(1):e;var n="~"===e.charAt(0);e=n?e.slice(1):e;var r="!"===e.charAt(0);return e=r?e.slice(1):e,{name:e,once:n,capture:r,passive:t}}),br=null,wr=[],Or=[],Er={},xr=!1,Sr=!1,Cr=0,kr=0,jr=function(e,t,n,r){this.vm=e,e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++kr,this.active=!0,this.dirty=this.lazy,
 this.deps=[],this.newDeps=[],this.depIds=new Yn,this.newDepIds=new Yn,this.expression="","function"==typeof t?this.getter=t:(this.getter=k(t),this.getter||(this.getter=function(){})),this.value=this.lazy?void 0:this.get()};jr.prototype.get=function(){I(this);var e,t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;j(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&Me(e),T(),this.cleanupDeps()}return e},jr.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},jr.prototype.cleanupDeps=function(){for(var e=this,t=this.deps.length;t--;){var n=e.deps[t];e.newDepIds.has(n.id)||n.removeSub(e)}var r=this.depIds;this.depIds=this.newDepIds,this.newDepIds=r,this.newDepIds.clear(),r=this.deps,this.deps=this.newDeps,this.newDeps=r,this.newDeps.length=0},jr.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():Pe(this)},jr.prototype.run=function(){if(thi
 s.active){var e=this.get();if(e!==this.value||s(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){j(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},jr.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},jr.prototype.depend=function(){for(var e=this,t=this.deps.length;t--;)e.deps[t].depend()},jr.prototype.teardown=function(){var e=this;if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var t=this.deps.length;t--;)e.deps[t].removeSub(e);this.active=!1}};var Ar=new Yn,Ir={enumerable:!0,configurable:!0,get:w,set:w},Tr={lazy:!0},Nr={init:function(e,t,n,r){if(!e.componentInstance||e.componentInstance._isDestroyed){(e.componentInstance=Ye(e,br,n,r)).$mount(t?e.elm:void 0,t)}else if(e.data.keepAlive){var o=e;Nr.prepatch(o,o)}},prepatch:function(e,t){var n=t.componentOptions;Ee(t.componentInstance=e.componentInstance,n.propsData,n.listeners,t,n.children)},insert:funct
 ion(e){var t=e.context,n=e.componentInstance;n._isMounted||(n._isMounted=!0,ke(n,"mounted")),e.data.keepAlive&&(t._isMounted?Te(n):Se(n,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?Ce(t,!0):t.$destroy())}},Pr=Object.keys(Nr),Mr=1,$r=2,Rr=0;!function(e){e.prototype._init=function(e){var t=this;t._uid=Rr++,t._isVue=!0,e&&e._isComponent?mt(t,e):t.$options=J(_t(t.constructor),e||{},t),t._renderProxy=t,t._self=t,we(t),he(t),yt(t),ke(t,"beforeCreate"),Ge(t),De(t),He(t),ke(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(wt),function(e){var t={};t.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=R,e.prototype.$delete=D,e.prototype.$watch=function(e,t,n){var r=this;if(u(t))return Je(r,e,t,n);n=n||{},n.user=!0;var o=new jr(r,e,t,n);return n.immediate&&t.call(r,o.value),function(){o.teardown()}}}(wt),function(e
 ){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this,o=this;if(Array.isArray(e))for(var i=0,a=e.length;i<a;i++)r.$on(e[i],n);else(o._events[e]||(o._events[e]=[])).push(n),t.test(e)&&(o._hasHookEvent=!0);return o},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(r,arguments)}var r=this;return n.fn=t,r.$on(e,n),r},e.prototype.$off=function(e,t){var n=this,r=this;if(!arguments.length)return r._events=Object.create(null),r;if(Array.isArray(e)){for(var o=0,i=e.length;o<i;o++)n.$off(e[o],t);return r}var a=r._events[e];if(!a)return r;if(1===arguments.length)return r._events[e]=null,r;for(var s,u=a.length;u--;)if((s=a[u])===t||s.fn===t){a.splice(u,1);break}return r},e.prototype.$emit=function(e){var t=this,n=t._events[e];if(n){n=n.length>1?_(n):n;for(var r=_(arguments,1),o=0,i=n.length;o<i;o++)try{n[o].apply(t,r)}catch(n){j(n,t,'event handler for "'+e+'"')}}return t}}(wt),function(e){e.prototype._update=function(e,t){var n=this;n._isMounted&&ke(n,"beforeUpdate");var r=n
 .$el,o=n._vnode,i=br;br=n,n._vnode=e,o?n.$el=n.__patch__(o,e):(n.$el=n.__patch__(n.$el,e,t,!1,n.$options._parentElm,n.$options._refElm),n.$options._parentElm=n.$options._refElm=null),br=i,r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){var e=this;e._watcher&&e._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){ke(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||h(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),ke(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null)}}}(wt),function(e){e.prototype.$nextTick=function(e){return or(e,this)},e.prototype._render=function(){var e=this,t=e.$options,n=t.render,r=t.staticRenderFns,o=t._parentVnode;if(e._isM
 ounted)for(var i in e.$slots)e.$slots[i]=ee(e.$slots[i]);e.$scopedSlots=o&&o.data.scopedSlots||Un,r&&!e._staticTrees&&(e._staticTrees=[]),e.$vnode=o;var a;try{a=n.call(e._renderProxy,e.$createElement)}catch(t){j(t,e,"render function"),a=e._vnode}return a instanceof vr||(a=_r()),a.parent=o,a},e.prototype._o=dt,e.prototype._n=d,e.prototype._s=f,e.prototype._l=at,e.prototype._t=st,e.prototype._q=O,e.prototype._i=E,e.prototype._m=ft,e.prototype._f=ut,e.prototype._k=ct,e.prototype._b=lt,e.prototype._v=Q,e.prototype._e=_r,e.prototype._u=be,e.prototype._g=vt}(wt);var Dr=[String,RegExp,Array],Fr={name:"keep-alive",abstract:!0,props:{include:Dr,exclude:Dr},created:function(){this.cache=Object.create(null)},destroyed:function(){var e=this;for(var t in e.cache)Tt(e.cache[t])},watch:{include:function(e){It(this.cache,this._vnode,function(t){return At(e,t)})},exclude:function(e){It(this.cache,this._vnode,function(t){return!At(e,t)})}},render:function(){var e=pe(this.$slots.default),t=e&&e.compon
 entOptions;if(t){var n=jt(t);if(n&&(this.include&&!At(this.include,n)||this.exclude&&At(this.exclude,n)))return e;var r=null==e.key?t.Ctor.cid+(t.tag?"::"+t.tag:""):e.key;this.cache[r]?e.componentInstance=this.cache[r].componentInstance:this.cache[r]=e,e.data.keepAlive=!0}return e}},Lr={KeepAlive:Fr};!function(e){var t={};t.get=function(){return Vn},Object.defineProperty(e,"config",t),e.util={warn:Bn,extend:g,mergeOptions:J,defineReactive:$},e.set=R,e.delete=D,e.nextTick=or,e.options=Object.create(null),Fn.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,g(e.options.components,Lr),Ot(e),Et(e),xt(e),kt(e)}(wt),Object.defineProperty(wt.prototype,"$isServer",{get:er}),Object.defineProperty(wt.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),wt.version="2.4.2";var Vr,Ur={},Wr=Object.freeze({namespaceMap:Ur,createElement:Nt,createElementNS:Pt,createTextNode:Mt,createComment:$t,insertBefore:Rt,removeChild:Dt,appendChild:Ft,p
 arentNode:Lt,nextSibling:Vt,tagName:Ut,setTextContent:Wt,setAttribute:Bt}),Br={create:function(e,t){qt(t)},update:function(e,t){e.data.ref!==t.data.ref&&(qt(e,!0),qt(t))},destroy:function(e){qt(e,!0)}},qr=new vr("",{},[]),zr=["create","activate","update","remove","destroy"],Jr={create:Gt,update:Gt,destroy:function(e){Gt(e,qr)}},Hr=Object.create(null),Gr=[Br,Jr],Xr={create:Yt,update:Yt},Kr={create:en,update:en},Zr={create:on,update:on},Qr=y(Tn),Yr={create:an,update:sn},eo=y(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),to=(zn&&window.requestAnimationFrame&&window.requestAnimationFrame.bind(window),{create:ln,activate:ln,remove:fn}),no=[Xr,Kr,Zr,Yr,to],ro=no.concat(Gr),oo=function(e){function t(e){return new vr(I.tagName(e).toLowerCase(),{},[],void 0,e)}function i(e,t){function n(){0==--n.listeners&&s(e)}return n.listeners=t,n}function s(e){va
 r t=I.parentNode(e);r(t)&&I.removeChild(t,e)}function u(e,t,n,i,a){if(e.isRootInsert=!a,!c(e,t,n,i)){var s=e.data,u=e.children,l=e.tag;if(r(l)){e.elm=e.ns?I.createElementNS(e.ns,l):I.createElement(l,e),m(e);var f=r(s)&&o(s.appendAsTree);f||(r(s)&&y(e,t),d(n,e.elm,i)),h(e,u,t),f&&(r(s)&&y(e,t),d(n,e.elm,i))}else o(e.isComment)?(e.elm=I.createComment(e.text),d(n,e.elm,i)):(e.elm=I.createTextNode(e.text),d(n,e.elm,i))}}function c(e,t,n,i){var a=e.data;if(r(a)){var s=r(e.componentInstance)&&a.keepAlive;if(r(a=a.hook)&&r(a=a.init)&&a(e,!1,n,i),r(e.componentInstance))return l(e,t),o(s)&&f(e,t,n,i),!0}}function l(e,t){r(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,v(e)?(y(e,t),m(e)):(qt(e),t.push(e))}function f(e,t,n,o){for(var i,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,r(i=a.data)&&r(i=i.transition)){for(i=0;i<j.activate.length;++i)j.activate[i](qr,a);t.push(a);break}d(n,e.elm,o)}function d(e,t,n){r(e
 )&&(r(n)?n.parentNode===e&&I.insertBefore(e,t,n):I.appendChild(e,t))}function h(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)u(t[r],n,e.elm,null,!0);else a(e.text)&&I.appendChild(e.elm,I.createTextNode(e.text))}function v(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return r(e.tag)}function y(e,t){for(var n=0;n<j.create.length;++n)j.create[n](qr,e);C=e.data.hook,r(C)&&(r(C.create)&&C.create(qr,e),r(C.insert)&&t.push(e))}function m(e){for(var t,n=e;n;)r(t=n.context)&&r(t=t.$options._scopeId)&&I.setAttribute(e.elm,t,""),n=n.parent;r(t=br)&&t!==e.context&&r(t=t.$options._scopeId)&&I.setAttribute(e.elm,t,"")}function _(e,t,n,r,o,i){for(;r<=o;++r)u(n[r],i,e,t)}function g(e){var t,n,o=e.data;if(r(o))for(r(t=o.hook)&&r(t=t.destroy)&&t(e),t=0;t<j.destroy.length;++t)j.destroy[t](e);if(r(t=e.children))for(n=0;n<e.children.length;++n)g(e.children[n])}function b(e,t,n,o){for(;n<=o;++n){var i=t[n];r(i)&&(r(i.tag)?(w(i),g(i)):s(i.elm))}}function w(e,t){if(r(t)||r(e.data)){va
 r n,o=j.remove.length+1;for(r(t)?t.listeners+=o:t=i(e.elm,o),r(n=e.componentInstance)&&r(n=n._vnode)&&r(n.data)&&w(n,t),n=0;n<j.remove.length;++n)j.remove[n](e,t);r(n=e.data.hook)&&r(n=n.remove)?n(e,t):t()}else s(e.elm)}function O(e,t,o,i,a){for(var s,c,l,f,d=0,p=0,h=t.length-1,v=t[0],y=t[h],m=o.length-1,g=o[0],w=o[m],O=!a;d<=h&&p<=m;)n(v)?v=t[++d]:n(y)?y=t[--h]:zt(v,g)?(E(v,g,i),v=t[++d],g=o[++p]):zt(y,w)?(E(y,w,i),y=t[--h],w=o[--m]):zt(v,w)?(E(v,w,i),O&&I.insertBefore(e,v.elm,I.nextSibling(y.elm)),v=t[++d],w=o[--m]):zt(y,g)?(E(y,g,i),O&&I.insertBefore(e,y.elm,v.elm),y=t[--h],g=o[++p]):(n(s)&&(s=Ht(t,d,h)),c=r(g.key)?s[g.key]:null,n(c)?(u(g,i,e,v.elm),g=o[++p]):(l=t[c],zt(l,g)?(E(l,g,i),t[c]=void 0,O&&I.insertBefore(e,l.elm,v.elm),g=o[++p]):(u(g,i,e,v.elm),g=o[++p])));d>h?(f=n(o[m+1])?null:o[m+1].elm,_(e,f,o,p,m,i)):p>m&&b(e,t,d,h)}function E(e,t,i,a){if(e!==t){var s=t.elm=e.elm;if(o(e.isAsyncPlaceholder))return void(r(t.asyncFactory.resolved)?S(e.elm,t,i):t.isAsyncPlaceholder=!0);
 if(o(t.isStatic)&&o(e.isStatic)&&t.key===e.key&&(o(t.isCloned)||o(t.isOnce)))return void(t.componentInstance=e.componentInstance);var u,c=t.data;r(c)&&r(u=c.hook)&&r(u=u.prepatch)&&u(e,t);var l=e.children,f=t.children;if(r(c)&&v(t)){for(u=0;u<j.update.length;++u)j.update[u](e,t);r(u=c.hook)&&r(u=u.update)&&u(e,t)}n(t.text)?r(l)&&r(f)?l!==f&&O(s,l,f,i,a):r(f)?(r(e.text)&&I.setTextContent(s,""),_(s,null,f,0,f.length-1,i)):r(l)?b(s,l,0,l.length-1):r(e.text)&&I.setTextContent(s,""):e.text!==t.text&&I.setTextContent(s,t.text),r(c)&&r(u=c.hook)&&r(u=u.postpatch)&&u(e,t)}}function x(e,t,n){if(o(n)&&r(e.parent))e.parent.data.pendingInsert=t;else for(var i=0;i<t.length;++i)t[i].data.hook.insert(t[i])}function S(e,t,n){if(o(t.isComment)&&r(t.asyncFactory))return t.elm=e,t.isAsyncPlaceholder=!0,!0;t.elm=e;var i=t.tag,a=t.data,s=t.children;if(r(a)&&(r(C=a.hook)&&r(C=C.init)&&C(t,!0),r(C=t.componentInstance)))return l(t,n),!0;if(r(i)){if(r(s))if(e.hasChildNodes()){for(var u=!0,c=e.firstChild,f=0
 ;f<s.length;f++){if(!c||!S(c,s[f],n)){u=!1;break}c=c.nextSibling}if(!u||c)return!1}else h(t,s,n);if(r(a))for(var d in a)if(!T(d)){y(t,n);break}}else e.data!==t.text&&(e.data=t.text);return!0}var C,k,j={},A=e.modules,I=e.nodeOps;for

<TRUNCATED>


[17/17] incubator-weex git commit: * [ios] merge pull request

Posted by ac...@apache.org.
* [ios] merge pull request


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

Branch: refs/heads/0.16-dev
Commit: 5b99cc6b0c721eeceb14491efb3dd6fd1a41bce0
Parents: 8725289
Author: acton393 <zh...@gmail.com>
Authored: Thu Sep 21 21:43:53 2017 +0800
Committer: acton393 <zh...@gmail.com>
Committed: Thu Sep 21 21:43:53 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj       | 105 +++
 .../Component/RecycleList/WXCellSlotComponent.h |  32 +
 .../Component/RecycleList/WXCellSlotComponent.m |  93 ++
 .../RecycleList/WXComponent+DataBinding.h       |  31 +
 .../RecycleList/WXComponent+DataBinding.mm      | 451 +++++++++
 .../Component/RecycleList/WXJSASTParser.h       | 100 ++
 .../Component/RecycleList/WXJSASTParser.mm      | 919 +++++++++++++++++++
 .../RecycleList/WXRecycleListComponent.h        |  25 +
 .../RecycleList/WXRecycleListComponent.m        | 459 +++++++++
 .../RecycleList/WXRecycleListDataManager.h      |  34 +
 .../RecycleList/WXRecycleListDataManager.m      |  71 ++
 .../Component/RecycleList/WXRecycleListLayout.h |  32 +
 .../Component/RecycleList/WXRecycleListLayout.m | 113 +++
 .../RecycleList/WXRecycleListTemplateManager.h  |  33 +
 .../RecycleList/WXRecycleListTemplateManager.m  |  94 ++
 .../RecycleList/WXRecycleListUpdateManager.h    |  50 +
 .../RecycleList/WXRecycleListUpdateManager.m    | 262 ++++++
 .../Recycler/WXSectionDataController.m          |   2 +-
 .../WeexSDK/Sources/Component/WXCellComponent.m |   4 +-
 .../Sources/Component/WXComponent_internal.h    |  28 +
 .../Sources/Component/WXScrollerComponent.h     |   2 +
 .../Sources/Component/WXScrollerComponent.m     |  13 +-
 ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m    |   4 +
 .../WeexSDK/Sources/Events/WXComponent+Events.m |   5 +-
 .../WeexSDK/Sources/Manager/WXBridgeManager.h   |  13 +-
 .../WeexSDK/Sources/Manager/WXBridgeManager.m   |  10 +
 .../Sources/Manager/WXComponentFactory.h        |  12 +
 .../Sources/Manager/WXComponentFactory.m        |  30 +-
 .../Sources/Manager/WXComponentManager.h        |  13 +-
 .../Sources/Manager/WXComponentManager.m        | 147 ++-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.h     |  19 +-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |  83 ++
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h    |  23 +-
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m    |  86 +-
 ios/sdk/WeexSDK/Sources/Utility/WXUtility.h     |  20 +-
 .../Sources/View/WXComponent+ViewManagement.m   |   4 +
 pre-build/native-bundle-main.js                 |  12 +-
 37 files changed, 3383 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 765a26a..8addaca 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -102,6 +102,8 @@
 		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, ); }; };
+		7423EB511F4ADE30001662D1 /* WXComponent+DataBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */; };
+		7423EB521F4ADE30001662D1 /* WXComponent+DataBinding.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */; };
 		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 */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -147,6 +149,8 @@
 		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 */; };
+		746B923B1F46BE36009AE86B /* WXCellSlotComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 746B92391F46BE36009AE86B /* WXCellSlotComponent.h */; };
+		746B923C1F46BE36009AE86B /* WXCellSlotComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 746B923A1F46BE36009AE86B /* WXCellSlotComponent.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 */; };
 		747DF6821E31AEE4005C53A8 /* WXLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 747DF6801E31AEE4005C53A8 /* WXLength.h */; };
@@ -178,17 +182,45 @@
 		74AD99841D5B0E59008F0336 /* WXPolyfillSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 74AD99821D5B0E59008F0336 /* WXPolyfillSet.h */; };
 		74AD99851D5B0E59008F0336 /* WXPolyfillSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 74AD99831D5B0E59008F0336 /* WXPolyfillSet.m */; };
 		74B232D21D2A2BA4006322EA /* WXLayoutDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 74B232D11D2A2BA4006322EA /* WXLayoutDefine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		74B81AE31F73C3E300D3A61D /* WXRecycleListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */; };
+		74B81AE41F73C3E500D3A61D /* WXRecycleListComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */; };
+		74B81AE51F73C3E900D3A61D /* WXRecycleListDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */; };
+		74B81AE61F73C3E900D3A61D /* WXRecycleListDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */; };
+		74B81AE71F73C3E900D3A61D /* WXRecycleListTemplateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */; };
+		74B81AE81F73C3E900D3A61D /* WXRecycleListTemplateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */; };
+		74B81AE91F73C3E900D3A61D /* WXRecycleListUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */; };
+		74B81AEA1F73C3E900D3A61D /* WXRecycleListUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */; };
+		74B81AEB1F73C3E900D3A61D /* WXRecycleListLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */; };
+		74B81AEC1F73C3E900D3A61D /* WXRecycleListLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */; };
+		74B81AED1F73C3E900D3A61D /* WXCellSlotComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 746B92391F46BE36009AE86B /* WXCellSlotComponent.h */; };
+		74B81AEE1F73C3E900D3A61D /* WXCellSlotComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */; };
+		74B81AEF1F73C3E900D3A61D /* WXComponent+DataBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */; };
+		74B81AF01F73C3E900D3A61D /* WXComponent+DataBinding.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */; };
+		74B81AF11F73C3E900D3A61D /* WXJSASTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */; };
+		74B81AF21F73C3E900D3A61D /* WXJSASTParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */; };
 		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 */; };
+		74BA4AB31F70F4B600AC29BF /* WXRecycleListLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */; };
+		74BA4AB41F70F4B600AC29BF /* WXRecycleListLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */; };
 		74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */; };
 		74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */; };
+		74BF19F81F5139BB00AEE3D7 /* WXJSASTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */; };
+		74BF19F91F5139BB00AEE3D7 /* WXJSASTParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */; };
 		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 */; };
 		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 */; };
+		74CFDD391F45939C007A1A66 /* WXRecycleListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */; };
+		74CFDD3A1F45939C007A1A66 /* WXRecycleListComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */; };
+		74CFDD3D1F459400007A1A66 /* WXRecycleListDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */; };
+		74CFDD3E1F459400007A1A66 /* WXRecycleListDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */; };
+		74CFDD411F45941E007A1A66 /* WXRecycleListTemplateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */; };
+		74CFDD421F45941E007A1A66 /* WXRecycleListTemplateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */; };
+		74CFDD451F459443007A1A66 /* WXRecycleListUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */; };
+		74CFDD461F459443007A1A66 /* WXRecycleListUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.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, ); }; };
@@ -668,6 +700,8 @@
 		742389991C3174EB00D748CA /* WXWeakObjectWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXWeakObjectWrapper.h; sourceTree = "<group>"; };
 		7423899A1C3174EB00D748CA /* WXWeakObjectWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXWeakObjectWrapper.m; sourceTree = "<group>"; };
 		7423899D1C32733800D748CA /* WXType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXType.h; sourceTree = "<group>"; };
+		7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WXComponent+DataBinding.h"; sourceTree = "<group>"; };
+		7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "WXComponent+DataBinding.mm"; sourceTree = "<group>"; };
 		742AD7251DF98C45007DC46C /* WXResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequest.h; path = Network/WXResourceRequest.h; sourceTree = "<group>"; };
 		742AD7261DF98C45007DC46C /* WXResourceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WXResourceRequest.m; path = Network/WXResourceRequest.m; sourceTree = "<group>"; };
 		742AD7271DF98C45007DC46C /* WXResourceRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXResourceRequestHandler.h; path = Network/WXResourceRequestHandler.h; sourceTree = "<group>"; };
@@ -714,6 +748,8 @@
 		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 = "<group>"; };
 		7469869E1C4E2C000054A57E /* NSArray+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Weex.m"; sourceTree = "<group>"; };
+		746B92391F46BE36009AE86B /* WXCellSlotComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXCellSlotComponent.h; sourceTree = "<group>"; };
+		746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXCellSlotComponent.m; sourceTree = "<group>"; };
 		747A787A1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+ViewManagement.h"; sourceTree = "<group>"; };
 		747A787B1D1BAAC900DED9D0 /* WXComponent+ViewManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+ViewManagement.m"; sourceTree = "<group>"; };
 		747DF6801E31AEE4005C53A8 /* WXLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLength.h; sourceTree = "<group>"; };
@@ -748,8 +784,12 @@
 		74B8BEFC1DC47B72004A6027 /* WXRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXRootView.h; sourceTree = "<group>"; };
 		74B8BEFD1DC47B72004A6027 /* WXRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootView.m; sourceTree = "<group>"; };
 		74B8BF001DC49AFE004A6027 /* WXRootViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRootViewTests.m; sourceTree = "<group>"; };
+		74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListLayout.h; sourceTree = "<group>"; };
+		74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListLayout.m; sourceTree = "<group>"; };
 		74BB5FB71DFEE81A004FC3DF /* WXMetaModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXMetaModule.h; sourceTree = "<group>"; };
 		74BB5FB81DFEE81A004FC3DF /* WXMetaModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXMetaModule.m; sourceTree = "<group>"; };
+		74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXJSASTParser.h; sourceTree = "<group>"; };
+		74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WXJSASTParser.mm; sourceTree = "<group>"; };
 		74C27A011CEC441D004E488E /* WeexSDK-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WeexSDK-Prefix.pch"; sourceTree = "<group>"; };
 		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 = "<group>"; };
@@ -758,6 +798,14 @@
 		74CC7A1B1C2BC5F800829368 /* WXCellComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCellComponent.m; sourceTree = "<group>"; };
 		74CC7A1E1C2BF9DC00829368 /* WXListComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXListComponent.h; sourceTree = "<group>"; };
 		74CC7A1F1C2BF9DC00829368 /* WXListComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXListComponent.m; sourceTree = "<group>"; };
+		74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListComponent.h; sourceTree = "<group>"; };
+		74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListComponent.m; sourceTree = "<group>"; };
+		74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListDataManager.h; sourceTree = "<group>"; };
+		74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListDataManager.m; sourceTree = "<group>"; };
+		74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListTemplateManager.h; sourceTree = "<group>"; };
+		74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListTemplateManager.m; sourceTree = "<group>"; };
+		74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXRecycleListUpdateManager.h; sourceTree = "<group>"; };
+		74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXRecycleListUpdateManager.m; sourceTree = "<group>"; };
 		74D2051E1E091B8000128F44 /* WXCallJSMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXCallJSMethod.h; sourceTree = "<group>"; };
 		74D2051F1E091B8000128F44 /* WXCallJSMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCallJSMethod.m; sourceTree = "<group>"; };
 		74EF31A91DE58AE600667A07 /* WXURLRewriteProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXURLRewriteProtocol.h; sourceTree = "<group>"; };
@@ -1079,6 +1127,29 @@
 			path = WeexSDKTests;
 			sourceTree = "<group>";
 		};
+		74CFDD361F45937D007A1A66 /* RecycleList */ = {
+			isa = PBXGroup;
+			children = (
+				74CFDD371F45939C007A1A66 /* WXRecycleListComponent.h */,
+				74CFDD381F45939C007A1A66 /* WXRecycleListComponent.m */,
+				74CFDD3B1F459400007A1A66 /* WXRecycleListDataManager.h */,
+				74CFDD3C1F459400007A1A66 /* WXRecycleListDataManager.m */,
+				74CFDD3F1F45941E007A1A66 /* WXRecycleListTemplateManager.h */,
+				74CFDD401F45941E007A1A66 /* WXRecycleListTemplateManager.m */,
+				74CFDD431F459443007A1A66 /* WXRecycleListUpdateManager.h */,
+				74CFDD441F459443007A1A66 /* WXRecycleListUpdateManager.m */,
+				74BA4AB11F70F4B600AC29BF /* WXRecycleListLayout.h */,
+				74BA4AB21F70F4B600AC29BF /* WXRecycleListLayout.m */,
+				746B92391F46BE36009AE86B /* WXCellSlotComponent.h */,
+				746B923A1F46BE36009AE86B /* WXCellSlotComponent.m */,
+				7423EB4F1F4ADE30001662D1 /* WXComponent+DataBinding.h */,
+				7423EB501F4ADE30001662D1 /* WXComponent+DataBinding.mm */,
+				74BF19F61F5139BB00AEE3D7 /* WXJSASTParser.h */,
+				74BF19F71F5139BB00AEE3D7 /* WXJSASTParser.mm */,
+			);
+			path = RecycleList;
+			sourceTree = "<group>";
+		};
 		74D8DB401E4825920078B667 /* Recycler */ = {
 			isa = PBXGroup;
 			children = (
@@ -1372,6 +1443,7 @@
 			children = (
 				C4B3D6D21E6954300013F38D /* WXEditComponent.h */,
 				C4B3D6D31E6954300013F38D /* WXEditComponent.m */,
+				74CFDD361F45937D007A1A66 /* RecycleList */,
 				74D8DB401E4825920078B667 /* Recycler */,
 				2A837AAC1CD9DE9200AEDF03 /* WXLoadingComponent.h */,
 				2A837AAD1CD9DE9200AEDF03 /* WXLoadingComponent.m */,
@@ -1483,7 +1555,9 @@
 				775BEE711C1BD977008D1629 /* WXModuleProtocol.h in Headers */,
 				7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */,
 				74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */,
+				7423EB511F4ADE30001662D1 /* WXComponent+DataBinding.h in Headers */,
 				74FD6E041C7C0E9600DBEB6D /* WXScrollerProtocol.h in Headers */,
+				74CFDD3D1F459400007A1A66 /* WXRecycleListDataManager.h in Headers */,
 				77D161201C02DDB40010B15B /* WXSDKEngine.h in Headers */,
 				745ED2DA1C5F2C7E002DB5A8 /* WXView.h in Headers */,
 				59D3CA411CF9ED57008835DC /* Layout.h in Headers */,
@@ -1496,6 +1570,7 @@
 				59A5961C1CB630F10012CD52 /* WXComponent+Navigation.h in Headers */,
 				775BEE6E1C1BD8F4008D1629 /* WXImgLoaderProtocol.h in Headers */,
 				7410811F1CED585A001BC6E5 /* WXComponentManager.h in Headers */,
+				74CFDD411F45941E007A1A66 /* WXRecycleListTemplateManager.h in Headers */,
 				1D3000F11D40B9AC004F3B4F /* WXClipboardModule.h in Headers */,
 				59A583081CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h in Headers */,
 				775BEE4E1C16F993008D1629 /* WXDefine.h in Headers */,
@@ -1538,14 +1613,17 @@
 				749DC27B1D40827B009E1C91 /* WXMonitor.h in Headers */,
 				77E659DA1C07F594008B8775 /* WXDomModule.h in Headers */,
 				74EF31AD1DE58BE200667A07 /* WXURLRewriteDefaultImpl.h in Headers */,
+				746B923B1F46BE36009AE86B /* WXCellSlotComponent.h in Headers */,
 				744D61101E49979000B624B3 /* WXFooterComponent.h in Headers */,
 				744D61141E4AF23E00B624B3 /* WXDiffUtil.h in Headers */,
 				74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */,
 				2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */,
+				74CFDD451F459443007A1A66 /* WXRecycleListUpdateManager.h in Headers */,
 				74A4BA9A1CB3BAA100195969 /* WXThreadSafeMutableDictionary.h in Headers */,
 				74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h in Headers */,
 				741DFE021DDD7D18009B020F /* WXRoundedRect.h in Headers */,
 				7423899B1C3174EB00D748CA /* WXWeakObjectWrapper.h in Headers */,
+				74BF19F81F5139BB00AEE3D7 /* WXJSASTParser.h in Headers */,
 				59A596191CB630E50012CD52 /* WXNavigationProtocol.h in Headers */,
 				59A5962F1CB632050012CD52 /* WXBaseViewController.h in Headers */,
 				74AD99841D5B0E59008F0336 /* WXPolyfillSet.h in Headers */,
@@ -1559,6 +1637,7 @@
 				741081261CEDB4EC001BC6E5 /* WXComponent_internal.h in Headers */,
 				77E65A191C155F25008B8775 /* WXScrollerComponent.h in Headers */,
 				C4E375381E5FCBD3009B2D9C /* WXComponent+BoxShadow.h in Headers */,
+				74BA4AB31F70F4B600AC29BF /* WXRecycleListLayout.h in Headers */,
 				742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */,
 				C4F0127D1E1502A6003378D0 /* WXWebSocketHandler.h in Headers */,
 				DC03ADBA1D508719003F76E7 /* WXTextAreaComponent.h in Headers */,
@@ -1616,6 +1695,7 @@
 				741081231CED6756001BC6E5 /* WXComponentFactory.h in Headers */,
 				59D3CA4A1CFC3CE1008835DC /* NSTimer+Weex.h in Headers */,
 				C4424E5B1F24DA3D009F52E2 /* WXExtendCallNativeProtocol.h in Headers */,
+				74CFDD391F45939C007A1A66 /* WXRecycleListComponent.h in Headers */,
 				D334510C1D3E19B80083598A /* WXCanvasModule.h in Headers */,
 				742AD73A1DF98C8B007DC46C /* WXResourceLoader.h in Headers */,
 				746319291C71B92600EFEBD4 /* WXModalUIModule.h in Headers */,
@@ -1643,11 +1723,14 @@
 				DCA445A61EFA571E00D0CFA8 /* WXSDKEngine.h in Headers */,
 				DCA445AA1EFA573900D0CFA8 /* WXResourceRequest.h in Headers */,
 				DCA445C61EFA57EE00D0CFA8 /* NSObject+WXSwizzle.h in Headers */,
+				74B81AEB1F73C3E900D3A61D /* WXRecycleListLayout.h in Headers */,
 				DCA445B41EFA577F00D0CFA8 /* WXJSExceptionProtocol.h in Headers */,
+				74B81AEF1F73C3E900D3A61D /* WXComponent+DataBinding.h in Headers */,
 				DCA445B51EFA578400D0CFA8 /* WXJSExceptionInfo.h in Headers */,
 				DCA445B61EFA578B00D0CFA8 /* WXIndicatorComponent.h in Headers */,
 				DCA445BF1EFA57C300D0CFA8 /* WXComponent.h in Headers */,
 				DCA445A71EFA572300D0CFA8 /* WXRootViewController.h in Headers */,
+				74B81AE91F73C3E900D3A61D /* WXRecycleListUpdateManager.h in Headers */,
 				DCA445C01EFA57C900D0CFA8 /* WXBridgeProtocol.h in Headers */,
 				DCA445AC1EFA574A00D0CFA8 /* WXNetworkProtocol.h in Headers */,
 				DCA445C31EFA57DC00D0CFA8 /* WXAppMonitorProtocol.h in Headers */,
@@ -1673,11 +1756,13 @@
 				DCA445A11EFA56FA00D0CFA8 /* WXScrollerProtocol.h in Headers */,
 				DCA445DE1EFA59B800D0CFA8 /* WXSectionDataController.h in Headers */,
 				DCA445F01EFA5A1D00D0CFA8 /* WXComponent_internal.h in Headers */,
+				74B81AE71F73C3E900D3A61D /* WXRecycleListTemplateManager.h in Headers */,
 				DCA445ED1EFA5A1200D0CFA8 /* WXTransform.h in Headers */,
 				DCA445CD1EFA592E00D0CFA8 /* WXComponent+Events.h in Headers */,
 				DCA445EC1EFA5A0E00D0CFA8 /* WXTextAreaComponent.h in Headers */,
 				DCA445D81EFA599400D0CFA8 /* WXRootView.h in Headers */,
 				DCA446131EFA5A8C00D0CFA8 /* WXCallJSMethod.h in Headers */,
+				74B81AED1F73C3E900D3A61D /* WXCellSlotComponent.h in Headers */,
 				DCA445E41EFA59DC00D0CFA8 /* WXVideoComponent.h in Headers */,
 				DCA4460B1EFA5A7200D0CFA8 /* WXAssert.h in Headers */,
 				DCA445F71EFA5A3100D0CFA8 /* WXPickerModule.h in Headers */,
@@ -1709,6 +1794,7 @@
 				DCA4460E1EFA5A7E00D0CFA8 /* WXLength.h in Headers */,
 				DCA445FA1EFA5A3A00D0CFA8 /* WXNavigatorModule.h in Headers */,
 				DCA446081EFA5A6A00D0CFA8 /* NSArray+Weex.h in Headers */,
+				74B81AE51F73C3E900D3A61D /* WXRecycleListDataManager.h in Headers */,
 				DCA445F21EFA5A2300D0CFA8 /* WXHeaderComponent.h in Headers */,
 				DCA445DD1EFA59B300D0CFA8 /* WXRecyclerUpdateController.h in Headers */,
 				DCA4461E1EFA5AAF00D0CFA8 /* WXComponentFactory.h in Headers */,
@@ -1718,6 +1804,7 @@
 				DCA4461D1EFA5AAA00D0CFA8 /* WXHandlerFactory.h in Headers */,
 				DCA445EE1EFA5A1500D0CFA8 /* WXWebComponent.h in Headers */,
 				DCA4460D1EFA5A7900D0CFA8 /* WXThreadSafeMutableArray.h in Headers */,
+				74B81AE31F73C3E300D3A61D /* WXRecycleListComponent.h in Headers */,
 				DCA445DA1EFA59A600D0CFA8 /* WXMultiColumnLayout.h in Headers */,
 				DCA445E01EFA59CD00D0CFA8 /* WXLoadingIndicator.h in Headers */,
 				DCA445E61EFA59E500D0CFA8 /* WXImageComponent.h in Headers */,
@@ -1754,6 +1841,7 @@
 				DCA445EB1EFA5A0B00D0CFA8 /* WXTextInputComponent.h in Headers */,
 				DCA4460C1EFA5A7600D0CFA8 /* WXThreadSafeMutableDictionary.h in Headers */,
 				DCA445CE1EFA593500D0CFA8 /* WXComponent+BoxShadow.h in Headers */,
+				74B81AF11F73C3E900D3A61D /* WXJSASTParser.h in Headers */,
 				DCA4461C1EFA5AA600D0CFA8 /* WXModuleFactory.h in Headers */,
 				DCA445D91EFA59A100D0CFA8 /* WXEditComponent.h in Headers */,
 				DCA445FB1EFA5A3C00D0CFA8 /* WXStorageModule.h in Headers */,
@@ -1866,6 +1954,7 @@
 					};
 					DCA445241EFA555400D0CFA8 = {
 						CreatedOnToolsVersion = 8.3.3;
+						DevelopmentTeam = "Xing Zhang";
 						ProvisioningStyle = Automatic;
 					};
 				};
@@ -2006,6 +2095,7 @@
 				746986A01C4E2C010054A57E /* NSArray+Weex.m in Sources */,
 				74B8BEFF1DC47B72004A6027 /* WXRootView.m in Sources */,
 				742AD7321DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.m in Sources */,
+				74CFDD421F45941E007A1A66 /* WXRecycleListTemplateManager.m in Sources */,
 				747DF6831E31AEE4005C53A8 /* WXLength.m in Sources */,
 				77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */,
 				2A60CE9D1C91733E00857B9F /* WXSwitchComponent.m in Sources */,
@@ -2024,6 +2114,7 @@
 				DCF087621DCAE161005CD6EB /* WXInvocationConfig.m in Sources */,
 				C47B78CF1F2998EE001D3B0C /* WXExtendCallNativeManager.m in Sources */,
 				77D161311C02DE4E0010B15B /* WXComponent.m in Sources */,
+				74CFDD461F459443007A1A66 /* WXRecycleListUpdateManager.m in Sources */,
 				74862F7A1E02B88D00B7A041 /* JSValue+Weex.m in Sources */,
 				740451EB1E14BB26004157CB /* WXServiceFactory.m in Sources */,
 				77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */,
@@ -2061,6 +2152,7 @@
 				59CE27E91CC387DB000BE37A /* WXEmbedComponent.m in Sources */,
 				DCA0EF651D6EED6F00CB18B9 /* WXGlobalEventModule.m in Sources */,
 				2A919DA71E321F1F006EB6B5 /* WXBridgeMethod.m in Sources */,
+				7423EB521F4ADE30001662D1 /* WXComponent+DataBinding.mm in Sources */,
 				DCAB35FF1D658EB700C0EA70 /* WXRuleManager.m in Sources */,
 				77D161251C02DDD10010B15B /* WXSDKInstance.m in Sources */,
 				DC7764931F3C2CA300B5727E /* WXRecyclerDragController.m in Sources */,
@@ -2082,9 +2174,11 @@
 				74CC7A1D1C2BC5F800829368 /* WXCellComponent.m in Sources */,
 				74862F821E03A24500B7A041 /* WXComponentMethod.m in Sources */,
 				77E65A121C155EA8008B8775 /* WXImageComponent.m in Sources */,
+				74CFDD3E1F459400007A1A66 /* WXRecycleListDataManager.m in Sources */,
 				2A837AB31CD9DE9200AEDF03 /* WXLoadingComponent.m in Sources */,
 				2AE5B7531CAB7DBD0082FDDB /* WXAComponent.m in Sources */,
 				333D9A291F41507A007CED39 /* WXTransition.m in Sources */,
+				74CFDD3A1F45939C007A1A66 /* WXRecycleListComponent.m in Sources */,
 				741DFE031DDD7D18009B020F /* WXRoundedRect.mm in Sources */,
 				59A596301CB632050012CD52 /* WXBaseViewController.m in Sources */,
 				74CC7A211C2BF9DC00829368 /* WXListComponent.m in Sources */,
@@ -2093,6 +2187,7 @@
 				7408C48F1CFB345D000BCCD0 /* WXComponent+Events.m in Sources */,
 				C4F012871E150307003378D0 /* WXWebSocketLoader.m in Sources */,
 				C4D872211E5DDEDA00E39BC1 /* WXInnerLayer.m in Sources */,
+				74BA4AB41F70F4B600AC29BF /* WXRecycleListLayout.m in Sources */,
 				745ED2DB1C5F2C7E002DB5A8 /* WXView.m in Sources */,
 				DC03ADB91D508719003F76E7 /* WXTextAreaComponent.m in Sources */,
 				59A596231CB6311F0012CD52 /* WXNavigatorModule.m in Sources */,
@@ -2101,6 +2196,7 @@
 				D33451091D3E19480083598A /* WXCanvasComponent.m in Sources */,
 				74A4BA971CB365D100195969 /* WXAppConfiguration.m in Sources */,
 				59A583091CF5B2FD0081FD3E /* WXNavigationDefaultImpl.m in Sources */,
+				746B923C1F46BE36009AE86B /* WXCellSlotComponent.m in Sources */,
 				7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */,
 				77D161501C02E3880010B15B /* WXUtility.m in Sources */,
 				74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */,
@@ -2116,6 +2212,7 @@
 				C4B834271DE69B09007AD27E /* WXPickerModule.m in Sources */,
 				745B2D691E5A8E1E0092D38A /* WXMultiColumnLayout.m in Sources */,
 				77D161391C02DE940010B15B /* WXBridgeManager.m in Sources */,
+				74BF19F91F5139BB00AEE3D7 /* WXJSASTParser.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2137,7 +2234,9 @@
 				DCA445391EFA55B300D0CFA8 /* WXComponent+PseudoClassManagement.m in Sources */,
 				DCA4453A1EFA55B300D0CFA8 /* WXView.m in Sources */,
 				DCA4453B1EFA55B300D0CFA8 /* WXErrorView.m in Sources */,
+				74B81AEC1F73C3E900D3A61D /* WXRecycleListLayout.m in Sources */,
 				DCA4453C1EFA55B300D0CFA8 /* WXComponent+ViewManagement.m in Sources */,
+				74B81AE41F73C3E500D3A61D /* WXRecycleListComponent.m in Sources */,
 				DC7764951F3C685200B5727E /* WXRecyclerDragController.m in Sources */,
 				DCA4453D1EFA55B300D0CFA8 /* WXRootView.m in Sources */,
 				DCA4453E1EFA55B300D0CFA8 /* WXBaseViewController.m in Sources */,
@@ -2153,7 +2252,9 @@
 				DCA445481EFA55B300D0CFA8 /* WXLoadingIndicator.m in Sources */,
 				DCA445491EFA55B300D0CFA8 /* WXRefreshComponent.m in Sources */,
 				DCA4454A1EFA55B300D0CFA8 /* WXEmbedComponent.m in Sources */,
+				74B81AE81F73C3E900D3A61D /* WXRecycleListTemplateManager.m in Sources */,
 				DCA4454B1EFA55B300D0CFA8 /* WXVideoComponent.m in Sources */,
+				74B81AE61F73C3E900D3A61D /* WXRecycleListDataManager.m in Sources */,
 				DCA4454C1EFA55B300D0CFA8 /* WXComponent.m in Sources */,
 				DCA4454D1EFA55B300D0CFA8 /* WXDivComponent.m in Sources */,
 				DCA4454E1EFA55B300D0CFA8 /* WXImageComponent.m in Sources */,
@@ -2176,6 +2277,7 @@
 				DCA4455D1EFA55B300D0CFA8 /* WXHeaderComponent.m in Sources */,
 				DCA4455E1EFA55B300D0CFA8 /* WXFooterComponent.m in Sources */,
 				DCA4455F1EFA55B300D0CFA8 /* WXNavigationDefaultImpl.m in Sources */,
+				74B81AF21F73C3E900D3A61D /* WXJSASTParser.mm in Sources */,
 				DCA445601EFA55B300D0CFA8 /* WXURLRewriteDefaultImpl.m in Sources */,
 				DCA445611EFA55B300D0CFA8 /* WXPrerenderManager.m in Sources */,
 				DCA445631EFA55B300D0CFA8 /* WXPickerModule.m in Sources */,
@@ -2195,8 +2297,11 @@
 				DCA445711EFA55B300D0CFA8 /* WXMetaModule.m in Sources */,
 				DCA445721EFA55B300D0CFA8 /* WXBoxShadow.m in Sources */,
 				DCA445731EFA55B300D0CFA8 /* NSTimer+Weex.m in Sources */,
+				74B81AEE1F73C3E900D3A61D /* WXCellSlotComponent.m in Sources */,
 				DCA445741EFA55B300D0CFA8 /* WXConvert.m in Sources */,
 				DCA445751EFA55B300D0CFA8 /* WXUtility.m in Sources */,
+				74B81AEA1F73C3E900D3A61D /* WXRecycleListUpdateManager.m in Sources */,
+				74B81AF01F73C3E900D3A61D /* WXComponent+DataBinding.mm in Sources */,
 				DCA445761EFA55B300D0CFA8 /* WXLog.m in Sources */,
 				DCA445771EFA55B300D0CFA8 /* WXWeakObjectWrapper.m in Sources */,
 				DCA445781EFA55B300D0CFA8 /* NSArray+Weex.m in Sources */,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
new file mode 100644
index 0000000..4e62676
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXComponent.h"
+
+@interface WXCellSlotComponent : WXComponent
+
+@property (nonatomic, strong) NSString *templateType;
+
+- (void)updateCellData:(NSDictionary *)data;
+
+- (void)triggerLayout;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
new file mode 100644
index 0000000..0cbd97b
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXCellSlotComponent.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+#import "WXConvert.h"
+#import "WXAssert.h"
+#import "WXScrollerComponent.h"
+
+static const NSString *WXDefaultRecycleTemplateType = @"WXDefaultRecycleTemplateType";
+
+@implementation WXCellSlotComponent
+
+- (instancetype)initWithRef:(NSString *)ref
+                       type:(NSString *)type
+                     styles:(NSDictionary *)styles
+                 attributes:(NSDictionary *)attributes
+                     events:(NSArray *)events
+               weexInstance:(WXSDKInstance *)weexInstance
+{
+    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
+    if (self) {
+        // TODO: isRecycle / insertAnimation / deleteAnimation / keepScrollPosition
+        _templateType = attributes[@"templateType"] ? [WXConvert NSString:attributes[@"templateType"]] : WXDefaultRecycleTemplateType;
+        _lazyCreateView = YES;
+        _isNeedJoinLayoutSystem = NO;
+    }
+    
+    return self;
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    
+}
+
+- (void)updateCellData:(NSDictionary *)data
+{
+    WXAssertComponentThread();    
+    
+    [self updateBindingData:data];
+    [self triggerLayout];
+}
+
+- (void)_didInserted
+{
+    [self triggerLayout];
+}
+
+- (void)triggerLayout
+{
+    WXAssertComponentThread();
+    
+    //TODO: _isUseContainerWidth?
+    if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH])) {
+        self.cssNode->style.dimensions[CSS_WIDTH] = ((WXScrollerComponent *)(self.supercomponent)).scrollerCSSNode->style.dimensions[CSS_WIDTH];
+    }
+    
+    if ([self needsLayout]) {
+        layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
+        if ([WXLog logLevel] >= WXLogLevelDebug) {
+            print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN);
+        }
+    }
+    
+    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
+    [self _calculateFrameWithSuperAbsolutePosition:CGPointZero gatherDirtyComponents:dirtyComponents];
+    for (WXComponent *dirtyComponent in dirtyComponents) {
+        [self.weexInstance.componentManager _addUITask:^{
+            [dirtyComponent _layoutDidFinish];
+        }];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
new file mode 100644
index 0000000..610f82f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <WeexSDK/WeexSDK.h>
+
+static const NSString *WXBindingIdentify = @"@binding";
+static const NSString *WXBindingMatchIdentify = @"[[match]]";
+static const NSString *WXBindingRepeatIdentify = @"[[repeat]]";
+static const NSString *WXBindingRepeatExprIdentify = @"@expression";
+static const NSString *WXBindingRepeatIndexIdentify = @"@index";
+static const NSString *WXBindingRepeatLabelIdentify = @"@alias";
+
+@interface WXComponent (DataBinding)
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
new file mode 100644
index 0000000..b15ebd8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm
@@ -0,0 +1,451 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXComponent+DataBinding.h"
+#import "WXComponent_internal.h"
+#import "WXSDKInstance_private.h"
+#import "WXComponentManager.h"
+#import "WXAssert.h"
+#import "WXJSASTParser.h"
+
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+typedef enum : NSUInteger {
+    WXDataBindingTypeProp = 0,
+    WXDataBindingTypeStyle,
+    WXDataBindingTypeAttributes,
+    WXDataBindingTypeEvents,
+    WXDataBindingTypeCount,
+} WXDataBindingType;
+
+static JSContext *jsContext;
+
+@implementation WXComponent (DataBinding)
+
+- (void)updateBindingData:(NSDictionary *)data
+{
+    WXAssertComponentThread();
+    
+    if (_isSkipUpdate) {
+        _isSkipUpdate = NO;
+        return;
+    }
+    
+    WXLogDebug(@"Update binding data:%@, for component:%@", data, self.ref);
+    if (!data) {
+        WXLogWarning(@"No data for updateBindingData");
+        return;
+    }
+    
+    WXComponent *templateComponent = _templateComponent;
+    if (!templateComponent) {
+        WXLogError(@"No template fount for component:%@", templateComponent);
+        return;
+    }
+    
+    if (templateComponent->_bindingProps) {
+        NSMutableDictionary *newData = [NSMutableDictionary dictionary];
+        [templateComponent->_bindingProps enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, WXDataBindingBlock  _Nonnull block, BOOL * _Nonnull stop) {
+            BOOL needUpdate;
+            id value = block(data, &needUpdate);
+            if (value) {
+                newData[key] = value;
+            }
+        }];
+        
+        data = newData;
+    }
+    
+    if (!_isRepeating) {
+        WXDataBindingBlock repeatBlock = templateComponent->_bindingRepeat;
+        if (repeatBlock) {
+            BOOL needUpdate = NO;
+            NSArray *repeatData = repeatBlock(data, &needUpdate);
+            [self _repeat:repeatData inData:data];
+            return;
+        }
+    }
+    
+    WXDataBindingBlock matchBlock = templateComponent->_bindingMatch;
+    if (matchBlock) {
+        BOOL needUpdate = NO;
+        BOOL needDisplay = [matchBlock(data, &needUpdate) boolValue];
+        if (!needDisplay) {
+            self.displayType = WXDisplayTypeNone;
+            return;
+        } else if (needDisplay && !_isNeedJoinLayoutSystem) {
+            self.displayType = WXDisplayTypeBlock;
+        }
+    }
+    
+    for (int i = WXDataBindingTypeStyle; i < WXDataBindingTypeCount; i++) {
+        NSDictionary *bindingMap = i == WXDataBindingTypeStyle ? templateComponent->_bindingStyles : (i == WXDataBindingTypeAttributes ? templateComponent->_bindingAttributes : templateComponent->_bindingEvents);
+        if (!bindingMap || bindingMap.count == 0) {
+            continue;
+        }
+        NSMutableDictionary *newAttributesOrStyles = [NSMutableDictionary dictionary];
+        
+        [bindingMap enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, WXDataBindingBlock  _Nonnull bindingBlock, BOOL * _Nonnull stop) {
+            BOOL needUpdate = NO;
+            id newValue = bindingBlock(data, &needUpdate);
+            if (needUpdate) {
+                newAttributesOrStyles[attributeOrStyleName] = newValue;
+            }
+        }];
+        
+        if (newAttributesOrStyles.count > 0) {
+            [self.weexInstance.componentManager startComponentTasks];
+            if (i == WXDataBindingTypeStyle) {
+                [self.weexInstance.componentManager updateStyles:newAttributesOrStyles forComponent:self.ref];
+            } else if (i == WXDataBindingTypeAttributes) {
+                [self.weexInstance.componentManager updateAttributes:newAttributesOrStyles forComponent:self.ref];
+            } else if (i == WXDataBindingTypeEvents) {
+                [self _addEventParams:newAttributesOrStyles];
+            }
+        }
+    }
+    
+    NSArray *subcomponents = self.subcomponents;
+    for (WXComponent *subcomponent in subcomponents) {
+        [subcomponent updateBindingData:data];
+    }
+}
+
+- (void)_repeat:(NSArray *)repeatData inData:(NSDictionary *)data
+{
+    NSMutableDictionary *dataCopy = [data mutableCopy];
+    WXComponent *templateComponent = _templateComponent;
+    NSArray *subcomponents = self.supercomponent.subcomponents;
+    NSUInteger startIndex = [subcomponents indexOfObject:self];
+    [repeatData enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        if (templateComponent->_repeatIndexIdentify) {
+            dataCopy[templateComponent->_repeatIndexIdentify] = @(idx);
+        }
+        if (templateComponent->_repeatLabelIdentify) {
+            dataCopy[templateComponent->_repeatLabelIdentify] = obj;
+        }
+        
+        WXComponent *exsitingComponent;
+        if (startIndex + idx < subcomponents.count) {
+            if (subcomponents[startIndex + idx]
+                && ((WXComponent *)(subcomponents[startIndex + idx]))->_templateComponent == templateComponent) {
+                exsitingComponent = subcomponents[startIndex + idx];
+                exsitingComponent.displayType = WXDisplayTypeBlock;
+            }
+        }
+        
+        WXComponent *component = exsitingComponent ? : [templateComponent copy];
+        component->_isRepeating = YES;
+        [component updateBindingData:dataCopy];
+        component->_isRepeating = NO;
+        
+        if (idx > 0 && exsitingComponent) {
+            component->_isSkipUpdate = YES;
+        }
+        
+        if (!exsitingComponent) {
+            [self.weexInstance.componentManager startComponentTasks];
+            [self.supercomponent _insertSubcomponent:component atIndex:startIndex + idx];
+            [self.weexInstance.componentManager _addUITask:^{
+                [self.supercomponent insertSubview:component atIndex:startIndex + idx];
+            }];
+        }
+    }];
+    
+    // set displaty:none to the redundant components;
+    NSUInteger i = startIndex + repeatData.count;
+    while (i < self.supercomponent.subcomponents.count) {
+        WXComponent *component = self.supercomponent.subcomponents[i];
+        if (component->_templateComponent == templateComponent) {
+            component->_isSkipUpdate = YES;
+            component.displayType = WXDisplayTypeNone;
+        }
+        i++;
+    }
+}
+
+- (void)_storeBindingsWithProps:(NSDictionary *)props styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSDictionary *)events
+{
+    WXAssertComponentThread();
+    
+    if (props.count > 0) {
+        if (!_bindingProps) {
+            _bindingProps = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:props type:WXDataBindingTypeProp];
+    }
+    
+    if (styles.count > 0) {
+        if (!_bindingStyles) {
+            _bindingStyles = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:styles type:WXDataBindingTypeStyle];
+    }
+    
+    if (attributes.count > 0) {
+        if (!_bindingAttributes) {
+            _bindingAttributes = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:attributes type:WXDataBindingTypeAttributes];
+    }
+    
+    if (events.count > 0) {
+        if (!_bindingEvents) {
+            _bindingEvents = [NSMutableDictionary dictionary];
+        }
+        [self _storeBindings:events type:WXDataBindingTypeEvents];
+    }
+}
+
+- (void)_storeBindings:(NSDictionary *)stylesOrAttributesOrEvents type:(WXDataBindingType)type
+{
+    WXAssertComponentThread();
+    
+    NSMutableDictionary *bindingMap;
+    switch (type) {
+        case WXDataBindingTypeProp:
+            bindingMap = _bindingProps;
+            break;
+        case WXDataBindingTypeStyle:
+            bindingMap = _bindingStyles;
+            break;
+        case WXDataBindingTypeAttributes:
+            bindingMap = _bindingAttributes;
+            break;
+        case WXDataBindingTypeEvents:
+            bindingMap = _bindingEvents;
+            break;
+        default:
+            WXAssert(NO, @"error binding type:%z", type);
+            break;
+    }
+    
+    [stylesOrAttributesOrEvents enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull name, id  _Nonnull binding, BOOL * _Nonnull stop) {
+        if ([binding isKindOfClass:[NSDictionary class]] && binding[WXBindingIdentify]) {
+            // {"attributeOrStyleName":{"@binding":"bindingExpression"}
+            NSString *bindingExpression = binding[WXBindingIdentify];
+            WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
+            WXJSExpression *expression = [parser parseExpression];
+            WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
+            bindingMap[name] = block;
+        } else if ([binding isKindOfClass:[NSArray class]]) {
+            // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
+            NSMutableDictionary *bindingBlocksForIndex = [NSMutableDictionary dictionary];
+            __block BOOL isBinding = NO;
+            [binding enumerateObjectsUsingBlock:^(id  _Nonnull bindingInArray, NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([bindingInArray isKindOfClass:[NSDictionary class]] && bindingInArray[WXBindingIdentify]) {
+                    isBinding = YES;
+                    NSString *bindingExpression = bindingInArray[WXBindingIdentify];
+                    WXJSASTParser *parser = [WXJSASTParser parserWithScript:bindingExpression];
+                    WXJSExpression *expression = [parser parseExpression];
+                    WXDataBindingBlock block = [self bindingBlockWithExpression:expression];
+                    bindingBlocksForIndex[@(idx)] = block;
+                }
+            }];
+            
+            bindingMap[name] = ^id(NSDictionary *data, BOOL *needUpdate) {
+                NSMutableArray *newArray = [binding mutableCopy];
+                [binding enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    BOOL _needUpdate = NO;
+                    WXDataBindingBlock block = bindingBlocksForIndex[@(idx)];
+                    if (block) {
+                        id newValue = block(data, &_needUpdate);
+                        if (newValue) {
+                             newArray[idx] = newValue;
+                        }  
+                        if (_needUpdate) {
+                            *needUpdate = YES;
+                        }
+                    }
+                }];
+                
+                return type == WXDataBindingTypeEvents ? newArray : [newArray componentsJoinedByString:@""];
+            };
+        }
+        
+        if (type == WXDataBindingTypeAttributes) {
+            if ([WXBindingMatchIdentify isEqualToString:name]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:binding];
+                WXJSExpression *expression = [parser parseExpression];
+                _bindingMatch = [self bindingBlockWithExpression:expression];
+            } else if ([WXBindingRepeatIdentify isEqualToString:name]) {
+                WXJSASTParser *parser = [WXJSASTParser parserWithScript:binding[WXBindingRepeatExprIdentify]];
+                WXJSExpression *expression = [parser parseExpression];
+                _bindingRepeat = [self bindingBlockWithExpression:expression];
+                _repeatIndexIdentify = binding[WXBindingRepeatIndexIdentify];
+                _repeatLabelIdentify = binding[WXBindingRepeatLabelIdentify];
+            }
+        }
+    }];
+}
+
+- (WXDataBindingBlock)bindingBlockWithExpression:(WXJSExpression *)expression
+{
+    if (!expression) {
+        return nil;
+    }
+    WXDataBindingBlock block = ^id(NSDictionary *data, BOOL *needUpdate) {
+        if (expression->is<WXJSStringLiteral>()) {
+            *needUpdate = NO;
+            return [NSString stringWithCString:(((WXJSStringLiteral *)expression)->value).c_str() encoding:[NSString defaultCStringEncoding]];
+        } else if (expression->is<WXJSNumericLiteral>()) {
+            *needUpdate = NO;
+            return @(((WXJSNumericLiteral *)expression)->value);
+        } else if (expression->is<WXJSBooleanLiteral>()) {
+            *needUpdate = NO;
+            return @(((WXJSBooleanLiteral *)expression)->value);
+        } else if (expression->is<WXJSNullLiteral>()) {
+            *needUpdate = NO;
+            return nil;
+        } else if (expression->is<WXJSIdentifier>()) {
+            NSString *identiferName = [NSString stringWithCString:(((WXJSIdentifier *)expression)->name).c_str() encoding:[NSString defaultCStringEncoding]];
+            if (data[identiferName]) {
+                *needUpdate = YES;
+                return data[identiferName];
+            } else {
+                WXLogError(@"identifer:%@ not found", identiferName);
+                return nil;
+            }
+        } else if (expression->is<WXJSMemberExpression>()) {
+            WXJSMemberExpression *member = (WXJSMemberExpression *)expression;
+            BOOL objectNeedUpdate = NO, propertyNeedUpdate = NO;
+            id object = [self bindingBlockWithExpression:member->object](data, &objectNeedUpdate);
+            if (member->computed) {
+                id propertyName = [self bindingBlockWithExpression:member->property](data, &propertyNeedUpdate);
+                *needUpdate = objectNeedUpdate || propertyNeedUpdate;
+                if ([object isKindOfClass:[NSDictionary class]] && [propertyName isKindOfClass:[NSString class]]) {
+                    return object[propertyName];
+                } else if ([object isKindOfClass:[NSArray class]] && [propertyName isKindOfClass:[NSNumber class]]) {
+                    return [object objectAtIndex:[propertyName unsignedIntegerValue]];
+                }
+            } else {
+                NSString *propertyName = [NSString stringWithCString:(((WXJSStringLiteral *)member->property)->value).c_str() encoding:[NSString defaultCStringEncoding]];
+                *needUpdate = objectNeedUpdate;
+                return object[propertyName];
+            }
+            
+            return nil;
+        } else if (expression->is<WXJSArrayExpression>()) {
+            WXJSArrayExpression *expr = (WXJSArrayExpression *)expression;
+            std::vector<WXJSExpression *> expressions = expr->expressions;
+            NSMutableArray *array = [NSMutableArray array];
+            for(WXJSExpression *expr : expressions) {
+                if (expr == NULL) {
+                    continue;
+                }
+                WXDataBindingBlock block = [self bindingBlockWithExpression:expr];
+                *needUpdate = NO;
+                if (block) {
+                    BOOL elementNeedUpdate;
+                    id object = block(data, &elementNeedUpdate);
+                    if (object) {
+                        *needUpdate = *needUpdate || elementNeedUpdate;
+                        [array addObject:object];
+                    }
+                }
+            }
+            
+            return array;
+        } else if (expression->is<WXJSUnaryExpression>()) {
+            WXJSUnaryExpression *expr = (WXJSUnaryExpression *)expression;
+            std::string operator_ = expr->operator_;
+            id argument = [self bindingBlockWithExpression:expr->argument](data, needUpdate);
+            if (operator_ == "+") {
+                return @([argument doubleValue]);
+            } else if (operator_ == "-") {
+                return @(-[argument doubleValue]);
+            } else if (operator_ == "!") {
+                return @(![argument boolValue]);
+            } else {
+                WXLogError(@"Not supported unary operator:%s", operator_.c_str());
+                return nil;
+            }
+        } else if (expression->is<WXJSBinaryExpression>()) {
+            WXJSBinaryExpression *expr = (WXJSBinaryExpression *)expression;
+            std::string operator_ = expr->operator_;
+            BOOL leftNeedUpdate = NO, rightNeedUpdate = NO;
+            id left = [self bindingBlockWithExpression:expr->left](data, &leftNeedUpdate);
+            id right = [self bindingBlockWithExpression:expr->right](data, &rightNeedUpdate);
+            *needUpdate = leftNeedUpdate || rightNeedUpdate;
+            if (operator_ == "+") {
+                return @([left doubleValue] + [right doubleValue]);
+            } else if (operator_ == "-") {
+                return @([left doubleValue] - [right doubleValue]);
+            } else if (operator_ == "*") {
+                return @([left doubleValue] * [right doubleValue]);
+            } else if (operator_ == "/") {
+                return @([left doubleValue] / [right doubleValue]);
+            } else if (operator_ == "%") {
+                return @([left integerValue] % [right integerValue]);
+            } else if (operator_ == ">") {
+                return @([left doubleValue] > [right doubleValue]);
+            } else if (operator_ == ">=") {
+                return @([left doubleValue] >= [right doubleValue]);
+            } else if (operator_ == "<") {
+                return @([left doubleValue] < [right doubleValue]);
+            } else if (operator_ == "<=") {
+                return @([left doubleValue] <= [right doubleValue]);
+            } else if (operator_ == "===" || operator_ == "==") {
+                if ([left isKindOfClass:[NSString class]]) {
+                    return @([left isEqualToString:right]);
+                } else if ([left isKindOfClass:[NSNumber class]]) {
+                    return  @([left doubleValue] == [right doubleValue]);
+                } else {
+                    WXLogError(@"Wrong type %@ at left of '===' or '=='", NSStringFromClass([left class]));
+                    return nil;
+                }
+            } else if (operator_ == "!==" || operator_ == "!=") {
+                if ([left isKindOfClass:[NSString class]]) {
+                    return @(![left isEqualToString:right]);
+                } else if ([left isKindOfClass:[NSNumber class]]) {
+                    return  @([left doubleValue] != [right doubleValue]);
+                } else {
+                    WXLogError(@"Wrong type %@ at left of '!==' or '!='", NSStringFromClass([left class]));
+                    return nil;
+                }
+            } else if (operator_ == "||") {
+                return @([left boolValue] || [right boolValue]);
+            } else if (operator_ == "&&") {
+                return @([left boolValue] && [right boolValue]);
+            } else {
+                WXLogError(@"Not supported binary operator:%s", operator_.c_str());
+                return nil;
+            }
+        } else if (expression->is<WXJSConditionalExpression>()) {
+            WXJSConditionalExpression *conditional = (WXJSConditionalExpression *)expression;
+            BOOL testNeedUpdate = NO, conditionalNeedUpdate = NO, alternateNeedUpdate = NO;
+            id testResult = [self bindingBlockWithExpression:conditional->test](data, &testNeedUpdate);
+            id result;
+            if ([testResult boolValue]) {
+                result = [self bindingBlockWithExpression:conditional->consequent](data, &conditionalNeedUpdate);
+            } else {
+                result = [self bindingBlockWithExpression:conditional->alternate](data, &alternateNeedUpdate);
+            }
+            *needUpdate = testNeedUpdate || conditionalNeedUpdate || alternateNeedUpdate;
+            return result;
+        } else {
+            WXAssert(NO, @"expression type error");
+            return nil;
+        }
+    };
+    
+    return block;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
new file mode 100644
index 0000000..76ebff3
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#include <string>
+#include <vector>
+
+typedef enum : NSUInteger {
+    WXJSExpressionTypeUnary,
+    WXJSExpressionTypeBinary,
+    WXJSExpressionTypeBinaryConditional,
+} WXJSExpressionType;
+
+struct WXJSExpression {
+    virtual ~WXJSExpression() {}
+    template <class T> bool is() {
+        return dynamic_cast<T *>(this) != NULL;
+    }
+};
+
+struct WXJSLiteral :WXJSExpression {
+};
+
+struct WXJSNullLiteral : WXJSLiteral {
+};
+
+struct WXJSStringLiteral : WXJSLiteral {
+    std::string value;
+};
+
+struct WXJSNumericLiteral : WXJSLiteral {
+    double value;
+};
+
+struct WXJSBooleanLiteral : WXJSLiteral {
+    bool value;
+};
+
+struct WXJSIdentifier : WXJSExpression {
+    std::string name;
+};
+
+struct WXJSMemberExpression : WXJSExpression {
+    WXJSExpression *object;
+    WXJSExpression *property;
+    bool computed;
+};
+
+struct WXJSArrayExpression : WXJSExpression {
+    std::vector<WXJSExpression *> expressions;
+};
+
+struct WXJSUnaryExpression : WXJSExpression {
+    std::string operator_;
+    bool prefix;
+    WXJSExpression *argument;
+};
+
+struct WXJSBinaryExpression : WXJSExpression {
+    std::string operator_;
+    WXJSExpression *left;
+    WXJSExpression *right;
+};
+
+struct WXJSLogicalExpression : WXJSExpression {
+    std::string operator_;
+    WXJSExpression *left;
+    WXJSExpression *right;
+};
+
+struct WXJSConditionalExpression : WXJSExpression {
+    WXJSExpression *test;
+    WXJSExpression *alternate;
+    WXJSExpression *consequent;
+};
+
+
+@interface WXJSASTParser : NSObject
+
++ (instancetype)parserWithScript:(NSString *)script;
+
+- (WXJSExpression *)parseExpression;
+
+@end


[16/17] incubator-weex git commit: * [ios] merge pull request

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
new file mode 100644
index 0000000..7e7a565
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm
@@ -0,0 +1,919 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXJSASTParser.h"
+#import "WXLog.h"
+#include <vector>
+#include <sstream>
+
+
+typedef enum : NSUInteger {
+    WXJSTokenTypeBooleanLiteral = 1,
+    WXJSTokenTypeEOF,
+    WXJSTokenTypeIdentifier,
+    WXJSTokenTypeKeyword,
+    WXJSTokenTypeNullLiteral,
+    WXJSTokenTypeNumericLiteral,
+    WXJSTokenTypePunctuator,
+    WXJSTokenTypeStringLiteral,
+    WXJSTokenTypeRegularExpression,
+    WXJSTokenTypeTemplate
+} WXJSTokenType;
+
+struct WXJSToken {
+    WXJSTokenType type;
+    std::string value;
+    double doubleValue;
+    bool octal;
+    int start;
+    int end;
+};
+
+struct WXJSMarker {
+    int index;
+};
+
+static bool isWhiteSpace(int ch) {
+    return (ch == 32) ||  // space
+    (ch == 9) ||      // tab
+    (ch == 0xB) ||
+    (ch == 0xC) ||
+    (ch == 0xA0);
+}
+
+static bool isIdentifierStart(int ch)
+{
+    return (ch == 36) || (ch == 95) ||  // $ or _
+        (ch >= 65 && ch <= 90) ||         // A..Z
+        (ch >= 97 && ch <= 122) ||        // a..z
+        (ch == 92);                      // \ (backslash)
+}
+
+static bool isIdentifierPart(int ch) {
+    return (ch == 36) || (ch == 95) ||  // $ or _
+    (ch >= 65 && ch <= 90) ||         // A..Z
+    (ch >= 97 && ch <= 122) ||        // a..z
+    (ch >= 48 && ch <= 57) ||         // 0..9
+    (ch == 92);                      // \ (backslash)
+}
+
+static bool isDecimalDigit(int ch) {
+    return (ch >= 48 && ch <= 57);   // 0..9
+}
+
+static bool isHexDigit(int ch) {
+    return std::string("0123456789abcdefABCDEF").find(ch) != std::string::npos;
+}
+
+static bool isOctalDigit(int ch) {
+    return std::string("01234567").find(ch) != std::string::npos;
+}
+
+static int binaryPrecedence(WXJSToken *token)
+{
+    int prec = 0;
+    
+    if (token->type != WXJSTokenTypePunctuator) {
+        return prec;
+    }
+    
+    const std::string &value = token->value;
+    
+    if (value == "||") {
+        prec = 1;
+    }
+    
+    else if (value == "&&") {
+        prec = 2;
+    }
+    
+    else if (value == "|") {
+        prec = 3;
+    }
+    
+    else if (value == "^") {
+        prec = 4;
+    }
+    
+    else if (value == "&") {
+        prec = 5;
+    }
+    
+    else if (value == "==" || value == "!=" || value == "===" || value == "!==") {
+        prec = 6;
+    }
+    
+    else if (value == "<" || value == ">" || value == "<=" || value == ">=") {
+        prec = 7;
+    }
+    
+    else if (value == "<<" || value == ">>" || value == ">>>") {
+        prec = 8;
+    }
+    
+    else if (value == "+" || value == "-") {
+        prec = 9;
+    }
+    
+    else if (value == "*" || value == "/" || value == "%") {
+        prec = 11;
+    }
+    
+    return prec;
+}
+
+@implementation WXJSASTParser
+{
+    std::string _source;
+    
+    int _length;
+    int _index;
+    
+    WXJSToken *_lookahead;
+    
+    std::vector<WXJSToken *> _tokens;
+}
+
++ (instancetype)parserWithScript:(NSString *)script
+{
+    if (!script) {
+        WXLogError(@"can not init parser with nil script");
+        return nil;
+    }
+    return [[self alloc] initWithScript:script];
+}
+
+- (instancetype)initWithScript:(NSString *)script
+{
+    if (self = [super init]) {
+        _source = std::string([script UTF8String]);;
+        _length = (int)(_source.length());
+        _index = 0;
+        
+        _lookahead = NULL;
+        
+        [self nextToken];
+    }
+    
+    return self;
+}
+
+- (WXJSToken *)nextToken
+{
+    WXJSToken *token = _lookahead;
+    
+    WXJSToken *next = [self lex];
+    
+    _lookahead = next;
+    
+    if (next->type != WXJSTokenTypeEOF) {
+        _tokens.push_back(token);
+    }
+    
+    return token;
+}
+
+- (WXJSToken *)lex
+{
+    [self skipSpaces];
+    
+    if (_index >= _length) {
+        WXJSToken *token = new WXJSToken();
+        token->type = WXJSTokenTypeEOF;
+        token->value = "";
+        token->start = _index;
+        token->end = _index;
+        
+        return token;
+    }
+    
+    int ch = _source[_index];
+    
+    if (isIdentifierStart(ch)) {
+        return [self scanIdentifier];
+    }
+    
+    // ( or ) or ;
+    if (ch == 40 || ch == 41 || ch == 59) {
+        return [self scanPunctuator];
+    }
+    
+    // string starting with ' or " .
+    if (ch == 39 || ch == 34 ) {
+        return [self scanStringLiteral];
+    }
+    
+    // Dot (.) U+002E can also start a floating-point number, hence the need
+    // to check the next
+    if (ch == 0x2E) {
+        if (isDecimalDigit(_source[_index + 1])) {
+            return [self scanNumericLiteral];
+        }
+        return [self scanPunctuator];
+    }
+    
+    if (isDecimalDigit(ch)) {
+        return [self scanNumericLiteral];
+    }
+    
+    // Possible `identifier
+    if (ch >= 0xD800 && ch < 0xDFFF) {
+        if (isIdentifierStart(ch)) {
+            return [self scanIdentifier];
+        }
+    }
+    
+    return [self scanPunctuator];
+}
+
+- (WXJSToken *)scanIdentifier
+{
+    int start = _index;
+    // Backslash (U+005C) starts an escaped
+    std::string identifier = [self getIdentifier];
+    WXJSTokenType type;
+    if (identifier == "null") {
+        type = WXJSTokenTypeNullLiteral;
+    } else if (identifier == "true" || identifier == "false") {
+        type = WXJSTokenTypeBooleanLiteral;
+    } else {
+        type = WXJSTokenTypeIdentifier;
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = type;
+    token->value = identifier;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (std::string)getIdentifier
+{
+    int start = _index++;
+    while (_index < _length) {
+        int ch = _source[_index];
+        if (isIdentifierPart(ch)) {
+            ++_index;
+        } else {
+            break;
+        }
+    }
+    
+    return _source.substr(start, _index - start);
+}
+
+- (WXJSToken *)scanPunctuator
+{
+    int start = _index;
+    
+    // Check for most common single-character punctuators.
+    int ch = _source[_index];
+    std::string str = "";
+    switch (ch) {
+        // single-character punctuators
+        case 46:   // .
+        case 40:   // (
+        case 41:   // )
+        case 59:   // ;
+        case 44:   // ,
+        case 123:  // {
+        case 125:  // }
+        case 91:   // [
+        case 93:   // ]
+        case 58:   // :
+        case 63:   // ?
+        case 126:  // ~
+            ++_index;
+            str = std::string(1, ch);
+            break;
+        default:
+            str =  _source.substr(_index, 3);
+            if (str == "===" || str == "!==" || str == "**=") {
+                _index += 3;
+            } else {
+                str = str.substr(0, 2);
+                if (str == "&&" || str == "||" || str == "==" || str == "!=" ||
+                    str == "+=" || str == "-=" || str == "*=" || str == "/=" ||
+                    str == "++" || str == "--" || str == "&=" || str == "|=" ||
+                    str == "^=" || str == "%=" || str == "<=" || str == ">=" ||
+                    str == "=>" || str == "**") {
+                    _index += 2;
+                }  else {
+                    str = _source[_index];
+                    // parse 2-character punctuators first
+                    if (std::string("<>=!+-*%&|^/").find(ch) != std::string::npos) {
+                        ++_index;
+                    }
+                }
+            }
+    }
+    
+    if (_index == start) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypePunctuator;
+    token->value = str;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanStringLiteral
+{
+    int start = _index;
+    int quote = _source[start];
+    bool octal = false;
+    
+    ++_index;
+    std::string str = "";
+    
+    while (_index < _length) {
+        int ch = _source[_index++];
+        
+        if (ch == quote) {
+            quote = -1;
+            break;
+        } else if (ch == 92) { // \ (backslash)
+            ch = _source[_index++];
+            switch (ch) {
+                case 'u': {
+                    if (_source[_index] == '{') { // {
+                        ++_index;
+                        str += [self scanUnicodeCodePointEscape];
+                    } else {
+                        int unescaped = [self scanHexEscape:ch];
+                        if (unescaped == -1) {
+                            [self _throwError:@"Invalid hexadecimal escape"];
+                        } else {
+                            str += unescaped;
+                        }
+                    }
+                    break;
+                }
+                case 'x': {
+                    int unescaped = [self scanHexEscape:ch];
+                    if (unescaped == -1) {
+                        [self _throwError:@"Invalid hexadecimal escape"];
+                    } else {
+                        str += unescaped;
+                    }
+                    
+                    break;
+                }
+                case 'n': {
+                    str += '\n';
+                    break;
+                }
+                case 'r': {
+                    str += '\r';
+                    break;
+                }
+                case 't': {
+                    str += '\t';
+                    break;
+                }
+                case 'b': {
+                    str += '\b';
+                    break;
+                }
+                case 'f': {
+                    str += '\f';
+                    break;
+                }
+                case 'v': {
+                    str += '\x0B';
+                    break;
+                }
+                case '8':
+                case '9': {
+                    str += ch;
+                    [self _throwUnexpectedTokenError];
+                    break;
+                }
+                    
+                default:
+                    if (isOctalDigit(ch)) {
+                        int code = ch - '0';
+                        
+                        // \0 is not octal escape sequence
+                        if (code != 0) {
+                            octal = true;
+                        }
+                        
+                        if (_index < _length && isOctalDigit(_source[_index])) {
+                            octal = true;
+                            code = code * 8 + _source[_index++] - '0';
+                            
+                            // 3 digits are only allowed when string starts
+                            // with 0, 1, 2, 3
+                            if (std::string(1, '0123').find(ch) != std::string::npos &&
+                                _index < _length &&
+                                isOctalDigit(_source[_index])) {
+                                code = code * 8 + _source[_index++] - '0';
+                            }
+                        }
+                        str += std::string(1, code);
+                    } else {
+                        str += ch;
+                    }
+                    break;
+            }
+        } else {
+            str += ch;
+        }
+    }
+    
+    if (quote != -1) {
+        _index = start;
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeStringLiteral;
+    token->value = str;
+    token->octal = octal;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (int)scanUnicodeCodePointEscape {
+    int ch = _source[_index];
+    int code = 0;
+    
+    if (ch == '}') { // '}'
+        [self _throwError:@"At least one hex digit is required in Unicode"];
+    }
+    
+    while (_index < _length) {
+        ch = _source[_index++];
+        if (!isHexDigit(ch)) {
+            break;
+        }
+        code = (int)(code * 16 + std::string("0123456789abcdef").find(tolower(ch)));
+    }
+    
+    if (code > 0x10FFFF || ch != '}') {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    return code;
+}
+
+- (WXJSToken *)scanNumericLiteral
+{
+    int start = _index;
+    int ch = _source[start];
+    std::string num;
+    if (ch != '.') {
+        num = _source[_index++];
+        ch = _source[_index];
+        
+        if (num == "0") {
+            if (ch == 'x' || ch == 'X') {
+                ++_index;
+                return [self scanHexLiteral:start];
+            }
+            if (ch == 'b' || ch == 'B') {
+                ++_index;
+                return [self scanBinaryLiteral:start];
+            }
+            if (ch == 'o' || ch == 'O') {
+                return [self scanOctalLiteral:ch start:start];
+            }
+        }
+        
+        while (isDecimalDigit(_source[_index])) {
+            num += _source[_index++];
+        }
+        ch = _source[_index];
+    }
+    
+    if (ch == '.') {
+        num += _source[_index++];
+        while (isDecimalDigit(_source[_index])) {
+            num += _source[_index++];
+        }
+        ch = _source[_index];
+    }
+    
+    if (ch == 'e' || ch == 'E') {
+        num += _source[_index++];
+        
+        ch = _source[_index];
+        if (ch == '+' || ch == '-') {
+            num += _source[_index++];
+        }
+        if (isDecimalDigit(_source[_index])) {
+            while (isDecimalDigit(_source[_index])) {
+                num += _source[_index++];
+            }
+        } else {
+            [self _throwUnexpectedTokenError];
+        }
+    }
+    
+    if (isIdentifierStart(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = atof(num.c_str());
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanHexLiteral:(int)start
+{
+    std::string num = "";
+    while (_index < _length) {
+        if (!isHexDigit(_source[_index])) {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (num.length() == 0) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (isIdentifierStart(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 16));
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (WXJSToken *)scanBinaryLiteral: (int)start
+{
+    std::string num = "";
+    int ch;
+    
+    while (_index < _length) {
+        ch = _source[_index];
+        if (ch != '0' && ch != '1') {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (num.length() == 0) {
+        // only 0b or 0B
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (_index < _length) {
+        ch = _source[_index];
+        /* istanbul ignore else */
+        if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+            [self _throwUnexpectedTokenError];
+        }
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 2));
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+- (WXJSToken *)scanOctalLiteral:(int)prefix start:(int)start
+{
+    std::string num = "";
+    bool octal = false;
+    
+    if (isOctalDigit(prefix)) {
+        octal = true;
+        num = '0' + _source[_index++];
+    } else {
+        ++_index;
+    }
+    
+    while (_index < _length) {
+        if (!isOctalDigit(_source[_index])) {
+            break;
+        }
+        num += _source[_index++];
+    }
+    
+    if (!octal && num.length() == 0) {
+        // only 0o or 0O
+        [self _throwUnexpectedTokenError];
+    }
+    
+    if (isIdentifierStart(_source[_index]) || isDecimalDigit(_source[_index])) {
+        [self _throwUnexpectedTokenError];
+    }
+    
+    WXJSToken *token = new WXJSToken();
+    token->type = WXJSTokenTypeNumericLiteral;
+    token->doubleValue = static_cast<double>(std::stoi(num, nullptr, 8));
+    token->octal = octal;
+    token->start = start;
+    token->end = _index;
+    
+    return token;
+}
+
+- (int)scanHexEscape:(int)prefix
+{
+    int i, len, ch, code = 0;
+    
+    len = (prefix == 'u') ? 4 : 2;
+    for (i = 0; i < len; ++i) {
+        if (_index < _length && isHexDigit(_source[_index])) {
+            ch = _source[_index++];
+            code = (int)(code * 16 + std::string("0123456789abcdef").find(tolower(ch)));
+        } else {
+            return -1;
+        }
+    }
+    return code;
+}
+
+- (WXJSExpression *)parseExpression
+{
+    return [self parseConditionalExpression];
+}
+
+- (WXJSExpression *)parseConditionalExpression
+{
+    WXJSExpression *expr = [self parseBinaryExpression];
+    
+    if ([self match:"?"]) {
+        [self nextToken];
+        WXJSExpression *consequent = [self parseConditionalExpression];
+        [self expect:":"];
+        WXJSExpression *alternate = [self parseConditionalExpression];
+        
+        WXJSConditionalExpression *conditionalExpr = new WXJSConditionalExpression();
+        conditionalExpr->test = expr;
+        conditionalExpr->consequent = consequent;
+        conditionalExpr->alternate = alternate;
+        
+        return conditionalExpr;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)parseBinaryExpression
+{
+    WXJSExpression *expr = [self parseUnaryExpression];
+    
+    std::vector<int> precedenceStack;
+    std::vector<WXJSToken *> operatorStack;
+    std::vector<WXJSExpression *> expressionStack;
+    
+    WXJSToken *token = _lookahead;
+    int prec = binaryPrecedence(token);
+    if (prec == 0) {
+        return expr;
+    }
+    
+    [self nextToken];
+    
+    expressionStack.push_back(expr);
+    precedenceStack.push_back(prec);
+    operatorStack.push_back(token);
+    expressionStack.push_back([self parseUnaryExpression]);
+    
+    WXJSExpression *right;
+    std::string operator_;
+    WXJSExpression *left;
+    while ((prec = binaryPrecedence(_lookahead)) > 0) {
+        while ((expressionStack.size() > 1) && (prec <= precedenceStack[precedenceStack.size() - 1])) {
+            right = expressionStack[expressionStack.size() - 1];
+            expressionStack.pop_back();
+            operator_ = operatorStack[operatorStack.size() - 1]->value;
+            operatorStack.pop_back(); precedenceStack.pop_back();
+            left = expressionStack[expressionStack.size() - 1]; expressionStack.pop_back();
+            expressionStack.push_back([self createBinaryExpression:operator_ left:left right:right]);
+        }
+        
+        // Shift.
+        token = [self nextToken];
+        precedenceStack.push_back(prec);
+        operatorStack.push_back(token);
+        expressionStack.push_back([self parseUnaryExpression]);
+    }
+    
+    // Final reduce to clean-up the stack.
+    int i = (int)(expressionStack.size() - 1);
+    expr = expressionStack[i];
+    while (i > 0) {
+        expr = [self createBinaryExpression:operatorStack[i - 1]->value left:expressionStack[i - 1] right:expr];
+        i--;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)parseUnaryExpression
+{
+    WXJSToken *token;
+    
+    if ([self match:"++"] || [self match:"--"] || [self match:"+"] || [self match:"-"] || [self match:"~"] || [self match:"!"]) {
+        token = [self nextToken];
+        WXJSExpression *argument = [self parseUnaryExpression];
+        WXJSUnaryExpression *expr = new WXJSUnaryExpression();
+        expr->operator_ = token->value;
+        expr->prefix = ([self match:"++"] || [self match:"--"]) ? true : false;
+        expr->argument = argument;
+        return expr;
+    }
+    
+    return [self parseMemberExpression];
+}
+
+- (WXJSExpression *)parsePrimaryExpression
+{
+    int type = _lookahead->type;
+    
+    if (type == WXJSTokenTypePunctuator) {
+        if (_lookahead->value == "[") {
+            return [self parseArrayExpression];
+        } else if (_lookahead->value == "(") {
+            return [self parseGroupExpression];
+        }
+    }
+    if (type == WXJSTokenTypeIdentifier) {
+        WXJSIdentifier *identifier = new WXJSIdentifier();
+        identifier->name = [self nextToken]->value;
+        return identifier;
+    }
+    
+    if (type == WXJSTokenTypeStringLiteral || type == WXJSTokenTypeNumericLiteral || type == WXJSTokenTypeBooleanLiteral || type == WXJSTokenTypeNullLiteral) {
+        return [self createLiteral:[self nextToken]];
+    } else {
+        [self _throwUnexpectedTokenError];
+        return new WXJSIdentifier();
+    }
+}
+
+- (WXJSArrayExpression *)parseArrayExpression
+{
+    std::vector<WXJSExpression *> expressions;
+    
+    [self expect:"["];
+    
+    while (![self match:"]"]) {
+        if ([self match:","]) {
+            [self nextToken];
+            expressions.push_back(NULL);
+        } else {
+            expressions.push_back([self parseConditionalExpression]);
+            
+            if (![self match:"]"]) {
+                [self expect:","];
+            }
+        }
+    }
+    
+    [self expect:"]"];
+    
+    WXJSArrayExpression *array = new WXJSArrayExpression();
+    array->expressions = expressions;
+    
+    return array;
+}
+
+- (WXJSExpression *)parseGroupExpression
+{
+    WXJSExpression *expr;
+    [self expect:"("];
+    
+    expr = [self parseConditionalExpression];
+    
+    [self expect:")"];
+    
+    return expr;
+}
+
+
+- (WXJSExpression *)parseMemberExpression
+{
+    WXJSExpression *expr = [self parsePrimaryExpression];
+    
+    if ([self match:"."]) {
+        [self expect:"."];
+        WXJSExpression *property = [self parsePrimaryExpression];
+        WXJSMemberExpression *memberExpr = new WXJSMemberExpression();
+        memberExpr->object = expr;
+        memberExpr->property = property;
+        memberExpr->computed = false;
+        return memberExpr;
+    } else if ([self match:"["]) {
+        [self expect:"["];
+        WXJSExpression *property = [self parseConditionalExpression];
+        [self expect:"]"];
+        WXJSMemberExpression *memberExpr = new WXJSMemberExpression();
+        memberExpr->object = expr;
+        memberExpr->property = property;
+        memberExpr->computed = true;
+        return memberExpr;
+    }
+    
+    return expr;
+}
+
+- (WXJSExpression *)createBinaryExpression:(const std::string &)operator_ left:(WXJSExpression *)left right:(WXJSExpression *)right
+{
+    WXJSBinaryExpression *node = new WXJSBinaryExpression();
+    node->operator_ = operator_;
+    node->left = left;
+    node->right = right;
+    return node;
+}
+
+- (WXJSLiteral *)createLiteral:(WXJSToken *)token
+{
+    if (token->type == WXJSTokenTypeNumericLiteral) {
+        WXJSNumericLiteral *node = new WXJSNumericLiteral();
+        node->value = token->doubleValue;
+        return node;
+    } else if (token->type == WXJSTokenTypeNullLiteral) {
+        WXJSNullLiteral *node = new WXJSNullLiteral();
+        return node;
+    } else if (token->type == WXJSTokenTypeStringLiteral) {
+        WXJSStringLiteral *node = new WXJSStringLiteral();
+        node->value = token->value;
+        return node;
+    } else if (token->type == WXJSTokenTypeBooleanLiteral) {
+        WXJSBooleanLiteral *node = new WXJSBooleanLiteral();
+        node->value = token->value == "true";
+        return node;
+    } else {
+        assert(false);
+    }
+}
+
+- (void)skipSpaces
+{
+    int ch;
+    while (_index < _length) {
+        ch = _source[_index];
+        if (isWhiteSpace(ch)) {
+            ++_index;
+        } else {
+            break;
+        }
+    }
+}
+
+- (bool)match:(std::string)value
+{
+    return _lookahead->type == WXJSTokenTypePunctuator && _lookahead->value == value;
+}
+
+- (void)expect:(std::string)value
+{
+    WXJSToken *token = [self nextToken];
+    if (token->type != WXJSTokenTypePunctuator || token->value != value) {
+        [self _throwUnexpectedTokenError];
+    }
+}
+
+- (void)_throwUnexpectedTokenError
+{
+    [self _throwError:@"Unexpected Token"];
+}
+
+- (void)_throwError:(NSString *)errorMessage
+{
+    WXLogError(@"%@, index:%d, script:%s", errorMessage, _index, _source.c_str());
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
new file mode 100644
index 0000000..a072752
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXScrollerComponent.h"
+
+@interface WXRecycleListComponent : WXScrollerComponent 
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
new file mode 100644
index 0000000..71a52f5
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXLog.h"
+#import "WXUtility.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+
+#import "WXCellSlotComponent.h"
+#import "WXRecycleListLayout.h"
+#import "WXRecycleListComponent.h"
+#import "WXRecycleListDataManager.h"
+#import "WXRecycleListTemplateManager.h"
+#import "WXRecycleListUpdateManager.h"
+
+@interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
+
+@end
+
+@implementation WXRecycleListComponent
+{
+    WXRecycleListDataManager *_dataManager;
+    WXRecycleListTemplateManager *_templateManager;
+    WXRecycleListUpdateManager *_updateManager;
+    
+    NSString *_templateKey;
+    NSString *_aliasKey;
+    NSString *_indexKey;
+    __weak UICollectionView *_collectionView;
+    
+    NSMutableDictionary *_sizeCache;
+    NSMutableDictionary *_stickyCache;
+    
+    NSUInteger _previousLoadMoreCellNumber;
+}
+
+WX_EXPORT_METHOD(@selector(appendData:))
+WX_EXPORT_METHOD(@selector(insertData:atIndex:))
+WX_EXPORT_METHOD(@selector(updateData:atIndex:))
+WX_EXPORT_METHOD(@selector(removeData:))
+WX_EXPORT_METHOD(@selector(moveData:toIndex:))
+WX_EXPORT_METHOD(@selector(scrollTo:options:))
+
+- (instancetype)initWithRef:(NSString *)ref
+                       type:(NSString *)type
+                     styles:(NSDictionary *)styles
+                 attributes:(NSDictionary *)attributes
+                     events:(NSArray *)events
+               weexInstance:(WXSDKInstance *)weexInstance
+{
+    if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
+        _dataManager = [[WXRecycleListDataManager alloc] initWithData:attributes[@"listData"]];
+        _templateManager = [WXRecycleListTemplateManager new];
+        _updateManager = [WXRecycleListUpdateManager new];
+        _updateManager.delegate = self;
+        _templateKey = [WXConvert NSString:attributes[@"templateKey"]] ? : @"templateType";
+        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
+        _indexKey = [WXConvert NSString:attributes[@"index"]];
+        _sizeCache = [NSMutableDictionary dictionary];
+        _stickyCache = [NSMutableDictionary dictionary];
+    }
+    
+    return self;
+}
+
+#pragma mark - WXComponent Methods
+
+- (UIView *)loadView
+{
+    WXRecycleListLayout *layout = [WXRecycleListLayout new];
+    layout.delegate = self;
+    // to show cells that original width / height is zero, otherwise cellForItemAtIndexPath will not be called
+    layout.minimumLineSpacing = 0.01;
+    layout.minimumInteritemSpacing = 0.01;
+    return [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    
+    _collectionView = (UICollectionView *)self.view;
+    _collectionView.allowsSelection = NO;
+    _collectionView.allowsMultipleSelection = NO;
+    _collectionView.dataSource = self;
+    _collectionView.delegate = self;
+    
+    _templateManager.collectionView = _collectionView;
+    _updateManager.collectionView = _collectionView;
+}
+
+- (void)viewWillUnload
+{
+    [super viewWillUnload];
+    
+    _collectionView.dataSource = nil;
+    _collectionView.delegate = nil;
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    if (attributes[@"listData"]) {
+        NSArray *listData = attributes[@"listData"];
+        [self _updateListData:listData withCompletion:nil animation:NO];
+    }
+}
+
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component
+{
+    CGPoint position = CGPointZero;
+    UIView *view = component->_view;
+    while (view) {
+        if ([view isKindOfClass:[UICollectionViewCell class]]) {
+            NSIndexPath *indexPath = [_collectionView indexPathForCell:(UICollectionViewCell *)view];
+            if (!indexPath) {
+                return CGPointMake(NAN, NAN);
+            }
+            UICollectionViewLayoutAttributes *attributes = [_collectionView layoutAttributesForItemAtIndexPath:indexPath];
+            CGPoint cellOrigin = attributes.frame.origin;
+            position = CGPointMake(position.x + cellOrigin.x,
+                                   position.y + cellOrigin.y);
+            break;
+        }
+        position = CGPointMake(position.x + view.frame.origin.x,
+                               position.y + view.frame.origin.y);
+        view = view.superview;
+    }
+    
+    return position;
+}
+
+- (void)setContentSize:(CGSize)contentSize
+{
+    // Do Nothing
+}
+
+- (void)adjustSticky
+{
+    // Do Nothing, sticky is adjusted by layout
+}
+
+#pragma mark - Load More Event
+
+- (void)loadMore
+{
+    [super loadMore];
+    
+    _previousLoadMoreCellNumber = [_collectionView numberOfItemsInSection:0];
+}
+
+- (BOOL)isNeedLoadMore
+{
+    BOOL superNeedLoadMore = [super isNeedLoadMore];
+    return superNeedLoadMore && _previousLoadMoreCellNumber != [_collectionView numberOfItemsInSection:0];
+}
+
+- (void)resetLoadmore
+{
+    [super resetLoadmore];
+    _previousLoadMoreCellNumber = 0;
+}
+
+#pragma mark - Exported Component Methods
+
+- (void)appendData:(NSArray *)appendingData
+{
+    if (![appendingData isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of appending data:%@", appendingData);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithAppendingData:appendingData oldData:oldData completion:nil animation:NO];
+}
+
+- (void)insertData:(id)data atIndex:(NSUInteger)index
+{
+    // TODO: bring the update logic to UpdateManager
+    // TODO: update cell because index has changed
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index <= newListData.count) {
+        [newListData insertObject:data atIndex:index];
+        [_dataManager updateData:newListData];
+        
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        
+        [UIView performWithoutAnimation:^{
+            [_collectionView insertItemsAtIndexPaths:@[indexPath]];
+        }];
+    }
+}
+
+- (void)updateData:(id)data atIndex:(NSUInteger)index
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index < newListData.count) {
+        newListData[index] = data;
+        [_dataManager updateData:newListData];
+        
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
+        UICollectionViewCell *cellView = [_collectionView cellForItemAtIndexPath:indexPath];
+        WXCellSlotComponent *cellComponent = (WXCellSlotComponent *)cellView.wx_component;
+        if (cellComponent) {
+            [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
+        }
+    }
+}
+
+- (void)removeData:(NSArray *)indexes
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    NSMutableIndexSet *indexSet = [NSMutableIndexSet new];
+    NSMutableArray *indexPaths = [NSMutableArray array];
+    for (NSNumber *index in indexes) {
+        if ([index unsignedIntegerValue] >= newListData.count) {
+            WXLogError(@"invalid remove index:%@", index);
+            continue;
+        }
+        [indexSet addIndex:[index unsignedIntegerValue]];
+        [indexPaths addObject:[NSIndexPath indexPathForItem:[index unsignedIntegerValue] inSection:0]];
+    }
+    
+    [newListData removeObjectsAtIndexes:indexSet];
+    [_dataManager updateData:newListData];
+    [UIView performWithoutAnimation:^{
+        [_collectionView deleteItemsAtIndexPaths:indexPaths];
+    }];
+}
+
+- (void)moveData:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    id data = newListData[fromIndex];
+    [newListData removeObjectAtIndex:fromIndex];
+    [newListData insertObject:data atIndex:toIndex];
+    [_dataManager updateData:newListData];
+    
+    NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:fromIndex inSection:0];
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:toIndex inSection:0];
+    [UIView performWithoutAnimation:^{
+        [_collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
+    }];
+}
+
+- (void)scrollTo:(NSUInteger)index options:(NSDictionary *)options
+{
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:index inSection:0];
+    BOOL animated = options[@"animated"] ? [WXConvert BOOL:options[@"animated"]] : NO;
+    [_collectionView scrollToItemAtIndexPath:toIndexPath atScrollPosition:UICollectionViewScrollPositionTop animated:animated];
+}
+
+#pragma mark - WXComonent Internal Methods
+
+- (void)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index
+{
+   [super _insertSubcomponent:subcomponent atIndex:index];
+    
+    if ([subcomponent isKindOfClass:[WXCellSlotComponent class]]) {
+        WXCellSlotComponent *cell = (WXCellSlotComponent*)subcomponent;
+        [self.weexInstance.componentManager _addUITask:^{
+            [_templateManager addTemplate:cell];
+        }];
+        
+        //TODO: update collection view if adding template
+    }
+}
+
+#pragma mark - Private
+
+- (void)_updateBindingData:(NSDictionary *)data forCell:(WXCellSlotComponent *)cellComponent atIndexPath:(NSIndexPath *)indexPath
+{
+    if (_aliasKey) {
+        data = @{_aliasKey:data};
+    }
+    if (_indexKey) {
+        NSMutableDictionary *dataNew = [data mutableCopy];
+        dataNew[_indexKey] = @(indexPath.item);
+        data = dataNew;
+    }
+    
+#ifdef DEBUG
+    NSDate *startTime = [NSDate date];
+#endif
+    WXPerformBlockSyncOnComponentThread(^{
+        [cellComponent updateCellData:data];
+    });
+#ifdef DEBUG
+    double duration = -[startTime timeIntervalSinceNow] * 1000;
+    WXLogDebug(@"cell:%zi update data time:%f", indexPath.item, duration);
+#endif
+    
+    NSValue *cachedSize = _sizeCache[indexPath];
+    if (!cachedSize || !CGSizeEqualToSize([cachedSize CGSizeValue] , cellComponent.calculatedFrame.size)) {
+        _sizeCache[indexPath] = [NSValue valueWithCGSize:cellComponent.calculatedFrame.size];
+        [_collectionView.collectionViewLayout invalidateLayout];
+    }
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    BOOL isSticky = cellComponent->_positionType == WXPositionTypeSticky;
+    if (!cachedSticky || [cachedSticky boolValue] != isSticky) {
+        _stickyCache[indexPath] = @(isSticky);
+    }
+}
+
+- (void)_updateListData:(NSArray *)newData
+        withCompletion:(WXRecycleListUpdateCompletion)completion
+             animation:(BOOL)animation
+{
+    if (![newData isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of list data:%@", newData);
+        completion(NO);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithNewData:newData oldData:oldData completion:completion animation:animation];
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
+{
+    return 1;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
+    return [_dataManager numberOfItems];
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    // 1. get the data relating to the cell
+    NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
+    if (!data || ![data isKindOfClass:[NSDictionary class]]) {
+        WXLogError(@"No data or wrong data format for index:%zd, data:%@", indexPath.item, data);
+        return nil;
+    }
+    
+    // 2. get the template type specified by data
+    NSString *templateType = data[_templateKey];
+    if (!templateType) {
+        WXLogError(@"Each data should have a value for %@ to indicate template type", _templateKey);
+        return nil;
+    }
+    
+    // 3. dequeue a cell component by template type
+    UICollectionViewCell *cellView = [_collectionView dequeueReusableCellWithReuseIdentifier:templateType forIndexPath:indexPath];
+    WXCellSlotComponent *cellComponent = (WXCellSlotComponent *)cellView.wx_component;
+    if (!cellComponent) {
+        cellComponent = [_templateManager dequeueCellSlotWithType:templateType forIndexPath:indexPath];
+        cellView.wx_component = cellComponent;
+        WXPerformBlockOnComponentThread(^{
+            //TODO: How can we avoid this?
+            [super _insertSubcomponent:cellComponent atIndex:self.subcomponents.count];
+        });
+    }
+    
+    // 4. binding the data to the cell component
+    [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
+
+    // 5. Add cell component's view to content view.
+    UIView *contentView = cellComponent.view;
+    if (contentView.superview == cellView.contentView) {
+        return cellView;
+    }
+    
+    for (UIView *view in cellView.contentView.subviews) {
+        [view removeFromSuperview];
+    }
+    [cellView.contentView addSubview:contentView];
+    [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
+    
+    WXLogDebug(@"Return cell view:%@, indexPath:%@", cellView, indexPath);
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [self handleAppear];
+    });
+    
+    return cellView;
+}
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
+{
+    return nil;
+}
+
+#pragma mark - UICollectionViewDelegate
+
+- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    WXLogDebug(@"will display cell:%@, at index path:%@", cell, indexPath);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    WXLogDebug(@"Did end displaying cell:%@, at index path:%@", cell, indexPath);
+}
+
+#pragma mark - UICollectionViewDelegateFlowLayout
+
+- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    NSValue *size = _sizeCache[indexPath];
+    if (size) {
+        return [size CGSizeValue];
+    } else {
+        NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
+        WXCellSlotComponent *cell = [_templateManager templateWithType:data[_templateKey]];
+        CGSize size = cell.calculatedFrame.size;
+        _sizeCache[indexPath] = [NSValue valueWithCGSize:size];
+        return CGSizeMake(_collectionView.frame.size.width, size.height);
+    }
+}
+
+#pragma mark - WXRecycleListLayoutDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout isNeedStickyForIndexPath:(NSIndexPath *)indexPath
+{
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    if (cachedSticky) {
+        return [cachedSticky boolValue];
+    } else {
+        return NO;
+    }
+}
+
+#pragma mark - WXRecycleListUpdateDelegate
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager willUpdateData:(id)newData
+{
+    [_dataManager updateData:newData];
+}
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager didUpdateData:(id)newData withSuccess:(BOOL)finished
+{
+    
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
new file mode 100644
index 0000000..fc053c5
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXRecycleListDataManager : NSObject
+
+- (instancetype)initWithData:(NSArray *)data;
+
+- (void)updateData:(NSArray *)data;
+
+- (NSArray *)data;
+
+- (NSDictionary *)dataAtIndex:(NSInteger)index;
+
+- (NSInteger)numberOfItems;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
new file mode 100644
index 0000000..8d27171
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListDataManager.h"
+#import "NSArray+Weex.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@implementation WXRecycleListDataManager
+{
+    NSArray *_data;
+}
+
+- (instancetype)initWithData:(NSArray *)data
+{
+    if (self = [super init]) {
+        if (![data isKindOfClass:[NSArray class]]) {
+            WXLogError(@"list data must be an array!");
+        } else {
+            _data = data;
+        }
+    }
+    
+    return self;
+}
+
+- (void)updateData:(NSArray *)data
+{
+    WXAssertMainThread();
+    
+    _data = data;
+}
+
+- (NSArray *)data
+{
+    WXAssertMainThread();
+    
+    return _data;
+}
+
+- (NSDictionary *)dataAtIndex:(NSInteger)index
+{
+    WXAssertMainThread();
+    
+    return [_data wx_safeObjectAtIndex:index];
+}
+
+- (NSInteger)numberOfItems
+{
+    WXAssertMainThread();
+    
+    return [_data count];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
new file mode 100644
index 0000000..6e08b94
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol WXRecycleListLayoutDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout isNeedStickyForIndexPath:(NSIndexPath *)indexPath;
+
+@end
+
+@interface WXRecycleListLayout : UICollectionViewFlowLayout
+
+@property (nonatomic, weak) id<WXRecycleListLayoutDelegate> delegate;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
new file mode 100644
index 0000000..73851de
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListLayout.h"
+
+@implementation WXRecycleListLayout
+{
+    NSMutableDictionary<NSNumber *, UICollectionViewLayoutAttributes *> *_stickyCellsAttributes;
+}
+
+- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
+{
+    NSArray *cellAttributes = [super layoutAttributesForElementsInRect:rect];
+    NSMutableDictionary *lastCellsAttributes = [NSMutableDictionary dictionary];
+    
+    __block NSInteger currentStickyIndex = -1;
+    [cellAttributes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        UICollectionViewLayoutAttributes *attributes = obj;
+        NSIndexPath *indexPath = attributes.indexPath;
+        if ([self.delegate collectionView:self.collectionView layout:self isNeedStickyForIndexPath:indexPath]) {
+            if (!_stickyCellsAttributes) {
+                _stickyCellsAttributes = [NSMutableDictionary dictionary];
+            }
+            
+            currentStickyIndex = indexPath.item;
+            [_stickyCellsAttributes setObject:attributes forKey:@(indexPath.item)];
+        } else {
+            [_stickyCellsAttributes removeObjectForKey:@(indexPath.item)];
+            
+            // bottom cell above sticky cell
+            UICollectionViewLayoutAttributes *currentLastCell = [lastCellsAttributes objectForKey:@(currentStickyIndex)];
+            if (!currentLastCell || indexPath.item > currentLastCell.indexPath.item) {
+                [lastCellsAttributes setObject:obj forKey:@(currentStickyIndex)];
+            }
+        }
+        
+        attributes.zIndex = 1;
+    }];
+    
+    NSMutableArray *newCellAttributes = [cellAttributes mutableCopy];
+    [lastCellsAttributes enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
+        UICollectionViewLayoutAttributes *attributes = obj;
+        
+        UICollectionViewLayoutAttributes *stickyCell = _stickyCellsAttributes[key];
+        if (!stickyCell) {
+            NSInteger item = attributes.indexPath.item;
+            while (item >= 0) {
+                if (_stickyCellsAttributes[@(item)]) {
+                    stickyCell = [self.collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:item inSection:0]];
+                    break;
+                } else {
+                    item --;
+                }
+            }
+        }
+        
+        if (stickyCell) {
+            [newCellAttributes addObject:stickyCell];
+            [self _adjustStickyForCellAttributes:stickyCell lastCellAttributes:attributes];
+        }
+    }];
+    
+    return newCellAttributes;
+}
+
+- (void)_adjustStickyForCellAttributes:(UICollectionViewLayoutAttributes *)cell
+                    lastCellAttributes:(UICollectionViewLayoutAttributes *)lastCell
+{
+    cell.zIndex = 99;
+    cell.hidden = NO;
+    
+    CGFloat maxY = CGRectGetMaxY(lastCell.frame) - cell.frame.size.height;
+    CGFloat minY = CGRectGetMinY(self.collectionView.bounds) + self.collectionView.contentInset.top;
+    CGFloat y = MIN(MAX(minY, cell.frame.origin.y), maxY);
+
+//    NSLog(@"%zi : %zi, %.1f, %.1f, %.1f, %.1f", cell.indexPath.item, lastCell.indexPath.item, maxY, minY, cell.frame.origin.y, y);
+    
+    CGPoint origin = cell.frame.origin;
+    origin.y = y;
+    
+    cell.frame = (CGRect){
+        origin,
+        cell.frame.size
+    };
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
+{
+    if (_stickyCellsAttributes.count > 0) {
+        // always return yes to trigger resetting sticky header's frame.
+        return YES;
+    }
+    
+    return [super shouldInvalidateLayoutForBoundsChange:newBounds];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
new file mode 100644
index 0000000..389dbb8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXCellSlotComponent.h"
+
+@interface WXRecycleListTemplateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+
+- (void)addTemplate:(WXCellSlotComponent *)component;
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type forIndexPath:(NSIndexPath *)indexPath;
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
new file mode 100644
index 0000000..87ecd90
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListTemplateManager.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@interface WXReusableCollectionViewCell : UICollectionViewCell
+
+@end
+
+@implementation WXReusableCollectionViewCell
+
+@end
+
+@implementation WXRecycleListTemplateManager
+{
+    NSMapTable<NSString *, WXCellSlotComponent *> *_templateTypeMap;
+}
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _templateTypeMap = [NSMapTable strongToWeakObjectsMapTable];
+    }
+    
+    return self;
+}
+
+- (void)setCollectionView:(UICollectionView *)collectionView
+{
+    WXAssertMainThread();
+    
+    if (_collectionView == collectionView) {
+        return;
+    }
+    
+    _collectionView = collectionView;
+    
+    for (NSString *templateType in [_templateTypeMap.keyEnumerator.allObjects copy]) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (void)addTemplate:(WXCellSlotComponent *)component
+{
+    WXAssertMainThread();
+    
+    NSString *templateType = component.templateType;
+    WXAssert(templateType != nil, @"cell-slot:%@ must have a template id!", component);
+    
+    [_templateTypeMap setObject:component forKey:templateType];
+    if (_collectionView) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type forIndexPath:(NSIndexPath *)indexPath
+{
+    WXAssertMainThread();
+    
+    WXCellSlotComponent *cellSlot = [_templateTypeMap objectForKey:type];
+    return [cellSlot copy];
+}
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type
+{
+    return [_templateTypeMap objectForKey:type];;
+}
+
+- (void)_registerCellClassForReuseID:(NSString *)templateID
+{
+    WXLogDebug(@"register cell class for template id:%@", templateID);
+    //TODO: register class update TemplateId
+    [_collectionView registerClass:[WXReusableCollectionViewCell class] forCellWithReuseIdentifier:templateID];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
new file mode 100644
index 0000000..1753b2b
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef void(^WXRecycleListUpdateCompletion)(BOOL isFinished);
+@class WXRecycleListUpdateManager;
+
+@protocol WXRecycleListUpdateDelegate
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager willUpdateData:(id)newData;
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager didUpdateData:(id)newData withSuccess:(BOOL)finished;
+
+@end
+
+@interface WXRecycleListUpdateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+@property (nonatomic, weak) id<WXRecycleListUpdateDelegate> delegate;
+
+- (void)reload;
+
+- (void)updateWithNewData:(NSArray *)newData
+                  oldData:(NSArray *)oldData
+               completion:(WXRecycleListUpdateCompletion)completion
+                animation:(BOOL)isAnimated;
+
+- (void)updateWithAppendingData:(NSArray *)appendingData
+                        oldData:(NSArray *)oldData
+                     completion:(WXRecycleListUpdateCompletion)completion
+                      animation:(BOOL)isAnimated;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
new file mode 100644
index 0000000..7ad4caa
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXRecycleListUpdateManager.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+#import "WXDiffUtil.h"
+
+@interface WXRecycleListDiffResult : NSObject
+
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *deleteIndexPaths;
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *insertIndexPaths;
+@property (nonatomic, strong, readonly) NSMutableSet<NSIndexPath *> *reloadIndexPaths;
+
+- (BOOL)hasChanges;
+
+@end
+
+@implementation WXRecycleListDiffResult
+
+- (instancetype)initWithInsertIndexPaths:(NSMutableSet<NSIndexPath *> *)insertIndexPaths
+                        deleteIndexPaths:(NSMutableSet<NSIndexPath *> *)deleteIndexPaths
+                        reloadIndexPaths:(NSMutableSet<NSIndexPath *> *)reloadIndexPaths
+{
+    if (self = [super init]) {
+        _insertIndexPaths = [insertIndexPaths copy];
+        _deleteIndexPaths = [deleteIndexPaths copy];
+        _reloadIndexPaths = [reloadIndexPaths copy];
+    }
+    
+    return self;
+}
+
+- (BOOL)hasChanges
+{
+    return _insertIndexPaths.count > 0 || _deleteIndexPaths.count > 0 || _reloadIndexPaths.count > 0;
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@: %p; insert index paths: %@; delete index paths: %@; reload index paths: %@", NSStringFromClass([self class]), self, _insertIndexPaths, _deleteIndexPaths, _reloadIndexPaths];
+}
+
+@end
+
+@interface WXRecycleListUpdateManager ()
+
+@property (nonatomic, copy) NSArray *newerData;
+@property (nonatomic, copy) NSArray *appendingData;
+@property (nonatomic, copy) NSArray *olderData;
+@property (nonatomic, assign) BOOL isUpdating;
+@property (nonatomic, strong) NSMutableArray *completions;
+
+@property (nonatomic, strong) NSMutableSet<NSIndexPath *> *reloadIndexPaths;
+
+@end
+
+@implementation WXRecycleListUpdateManager
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _completions = [NSMutableArray array];
+    }
+    
+    return self;
+}
+
+- (void)reload
+{
+    [_collectionView reloadData];
+}
+
+- (void)updateWithNewData:(NSArray *)newData
+                  oldData:(NSArray *)oldData
+               completion:(WXRecycleListUpdateCompletion)completion
+                animation:(BOOL)isAnimated
+{
+    WXAssertMainThread();
+    
+    if (!_collectionView) {
+        WXLogError(@"Update list with no collection view");
+        completion(NO);
+        return;
+    }
+    
+    self.newerData = newData;
+    self.appendingData = nil;
+    self.olderData = oldData;
+    
+    if (completion) {
+        [_completions addObject:completion];
+    }
+    
+    [self checkUpdates];
+}
+
+- (void)updateWithAppendingData:(NSArray *)appendingData
+                        oldData:(NSArray *)oldData
+                     completion:(WXRecycleListUpdateCompletion)completion
+                      animation:(BOOL)isAnimated
+{
+    if (!_collectionView) {
+        WXLogError(@"Update list with no collection view");
+        completion(NO);
+        return;
+    }
+    
+    self.appendingData = appendingData;
+    self.olderData = oldData;
+    
+    if (completion) {
+        [_completions addObject:completion];
+    }
+    
+    [self checkUpdates];
+}
+
+
+- (void)checkUpdates
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (self.isUpdating) {
+            return ;
+        }
+        
+        [self performBatchUpdates];
+    });
+}
+
+- (void)performBatchUpdates
+{
+    WXAssertMainThread();
+    WXAssert(!self.isUpdating, @"Can not perform updates while an updating is being performed");
+    
+    UICollectionView *collectionView = self.collectionView;
+    if (!collectionView) {
+        return;
+    }
+    
+    NSArray *newData = [self.newerData copy];
+    NSArray *oldData = [self.olderData copy];
+    NSArray *appendingData = [self.appendingData copy];
+    //TODO use completionBlocks
+//    NSArray *completionBlocks = [self.completions copy];
+    
+    [self cleanup];
+    
+    WXDiffResult *diffResult;
+    if (appendingData) {
+        newData = [oldData arrayByAddingObjectsFromArray:appendingData];
+        NSIndexSet *inserts = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(oldData.count, appendingData.count)];
+        diffResult = [[WXDiffResult alloc] initWithInserts:inserts deletes:nil updates:nil];
+    } else if (newData){
+        diffResult = [WXDiffUtil diffWithMinimumDistance:newData oldArray:oldData];
+    }
+    
+    WXRecycleListDiffResult *recycleListDiffResult = [self recycleListUpdatesByDiffResult:diffResult];
+    
+    if (![diffResult hasChanges] && self.reloadIndexPaths.count == 0) {
+        return;
+    }
+    
+    void (^updates)() = [^{
+        [self.delegate updateManager:self willUpdateData:newData];
+        [UIView setAnimationsEnabled:NO];
+        NSLog(@"UICollectionView update:%@", recycleListDiffResult);
+        [self applyUpdateWithDiffResult:recycleListDiffResult];
+    } copy];
+    
+    void (^completion)(BOOL) = [^(BOOL finished) {
+        [UIView setAnimationsEnabled:YES];
+        self.isUpdating = NO;
+        [self.delegate updateManager:self didUpdateData:newData withSuccess:finished];
+        
+        [self.reloadIndexPaths removeAllObjects];
+        [self checkUpdates];
+    } copy];
+    
+    self.isUpdating = YES;
+    
+    if (!self.delegate || !collectionView.dataSource) {
+        return;
+    }
+    
+    [collectionView performBatchUpdates:updates completion:completion];
+}
+
+- (WXRecycleListDiffResult *)recycleListUpdatesByDiffResult:(WXDiffResult *)diffResult
+{
+    NSMutableSet<NSIndexPath *> *reloadIndexPaths = [NSMutableSet set];
+    NSMutableSet<NSIndexPath *> *deleteIndexPaths = [NSMutableSet set];
+    NSMutableSet<NSIndexPath *> *insertIndexPaths = [NSMutableSet set];
+    
+    for (WXDiffUpdateIndex *update in diffResult.updates) {
+        NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0];
+        [reloadIndexPaths addObject:reloadIndexPath];
+    }
+    
+    [diffResult.updates enumerateObjectsUsingBlock:^(WXDiffUpdateIndex * _Nonnull update, NSUInteger idx, BOOL * _Nonnull stop) {
+        NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0];
+        [reloadIndexPaths addObject:reloadIndexPath];
+    }];
+    
+    [diffResult.inserts enumerateIndexesUsingBlock:^(NSUInteger insertIndex, BOOL * _Nonnull stop) {
+        NSIndexPath *insertIndexPath = [NSIndexPath indexPathForItem:insertIndex inSection:0];
+        [insertIndexPaths addObject:insertIndexPath];
+    }];
+    
+    [diffResult.deletes enumerateIndexesUsingBlock:^(NSUInteger deleteIndex, BOOL * _Nonnull stop) {
+        NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForItem:deleteIndex inSection:0];
+        [deleteIndexPaths addObject:deleteIndexPath];
+    }];
+    
+    WXRecycleListDiffResult *result = [[WXRecycleListDiffResult alloc] initWithInsertIndexPaths:insertIndexPaths deleteIndexPaths:deleteIndexPaths reloadIndexPaths:reloadIndexPaths];
+    
+    return result;
+}
+
+
+- (void)applyUpdateWithDiffResult:(WXRecycleListDiffResult *)diffResult
+{
+    if (!_collectionView) {
+        return;
+    }
+    
+    // reload index paths should not inculde delete index paths, otherwise it will cause crash:
+    // Assertion failure in
+    // -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:]
+    NSMutableSet *reloadIndexPaths = self.reloadIndexPaths ? [[diffResult.reloadIndexPaths setByAddingObjectsFromSet:self.reloadIndexPaths] mutableCopy]: [diffResult.reloadIndexPaths mutableCopy];
+    [reloadIndexPaths minusSet:diffResult.deleteIndexPaths];
+    
+    [_collectionView deleteItemsAtIndexPaths:[diffResult.deleteIndexPaths allObjects]];
+    [_collectionView insertItemsAtIndexPaths:[diffResult.insertIndexPaths allObjects]];
+    [_collectionView reloadItemsAtIndexPaths:[reloadIndexPaths allObjects]];
+}
+
+- (void)cleanup
+{
+    self.newerData = nil;
+    self.appendingData = nil;
+    self.olderData = nil;
+    [self.completions removeAllObjects];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
index af1f760..1bc7d23 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
@@ -65,7 +65,7 @@
     return [super hash];
 }
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
 {
     if ([object isKindOfClass:[WXSectionDataController class]]) {
         WXSectionDataController *controller = (WXSectionDataController *)object;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
index e579139..07621c7 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -56,7 +56,7 @@
     
 }
 
-- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
+- (BOOL)weex_isEqualTo:(id<WXDiffable>)object
 {
     return self == object;
 }
@@ -100,7 +100,7 @@
 
 - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index
 {
-    if (self.delegate == newSupercomponent) {
+    if (self.delegate == (id<WXCellRenderDelegate>)newSupercomponent) {
         [self.delegate cell:self didMoveToIndex:index];
         [super _removeFromSupercomponent];
         [newSupercomponent _insertSubcomponent:self atIndex:index];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 0316321..5d9b687 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -25,6 +25,7 @@
 @class WXTouchGestureRecognizer;
 @class WXThreadSafeCounter;
 
+typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 /**
  * The following variables and methods are used in Weex INTERNAL logic.
@@ -132,6 +133,25 @@
     BOOL _lazyCreateView;
     
     WXTransform *_transform;
+    
+    /**
+     * Data Binding
+     */
+    BOOL _isTemplate;
+    WXComponent *_templateComponent;
+    WXDataBindingBlock _bindingMatch;
+    WXDataBindingBlock _bindingRepeat;
+    NSString *_repeatIndexIdentify;
+    NSString *_repeatLabelIdentify;
+    BOOL _isRepeating;
+    BOOL _isSkipUpdate;
+    
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingProps;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingAttributes;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingStyles;
+    NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingEvents;
+    
+    NSMutableDictionary<NSString *, NSArray *> *_eventParameters;
 }
 
 ///--------------------------------------
@@ -207,6 +227,10 @@
 
 - (void)_removeAllEvents;
 
+- (void)_addEventParams:(NSDictionary *)params;
+
+- (NSArray *)_paramsForEvent:(NSString *)eventName;
+
 - (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles attributes:(NSMutableDictionary *)attributes;
 
 - (void)_initCompositingAttribute:(NSDictionary *)attributes;
@@ -227,6 +251,10 @@
 
 - (void)setGradientLayer;
 
+- (void)_storeBindingsWithProps:(NSDictionary *)props styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSDictionary *)events;
+
+- (void)_didInserted;
+
 @end
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
index 39bf0d7..db0c155 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
@@ -34,5 +34,7 @@
 
 - (void)handleAppear;
 
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component;
+
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
index a960cc6..306631b 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
@@ -566,25 +566,30 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     }
 }
 
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component
+{
+    return [component->_view.superview convertPoint:component->_view.frame.origin toView:_view];
+}
+
 #pragma mark  Private Methods
 
 - (void)scrollToTarget:(WXScrollToTarget *)target scrollRect:(CGRect)rect
 {
     WXComponent *component = target.target;
-    if (![component isViewLoaded]) {
+    if (![component isViewLoaded]) { 
         return;
     }
     
     CGFloat ctop;
     if (component && component->_view && component->_view.superview) {
-        ctop = [component->_view.superview convertPoint:component->_view.frame.origin toView:_view].y;
+        ctop = [self absolutePositionForComponent:component].y;
     } else {
         ctop = 0.0;
     }
     CGFloat cbottom = ctop + CGRectGetHeight(component.calculatedFrame);
     CGFloat cleft;
     if (component && component->_view && component->_view.superview) {
-        cleft = [component->_view.superview convertPoint:component->_view.frame.origin toView:_view].x;
+        cleft = [self absolutePositionForComponent:component].x;
     } else {
         cleft = 0.0;
     }
@@ -595,6 +600,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         if(!target.hasAppear && component){
             target.hasAppear = YES;
             if (component->_appearEvent) {
+//                NSLog(@"appear:%@, %.2f", component, ctop);
                 [component fireEvent:@"appear" params:_direction ? @{@"direction":_direction} : nil];
             }
         }
@@ -602,6 +608,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         if(target.hasAppear && component){
             target.hasAppear = NO;
             if(component->_disappearEvent){
+//                NSLog(@"disappear:%@", component);
                 [component fireEvent:@"disappear" params:_direction ? @{@"direction":_direction} : nil];
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index cc9373b..e86221d 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -108,6 +108,10 @@
     [self registerComponent:@"textarea" withClass:NSClassFromString(@"WXTextAreaComponent")];
 	[self registerComponent:@"canvas" withClass:NSClassFromString(@"WXCanvasComponent")];
     [self registerComponent:@"slider-neighbor" withClass:NSClassFromString(@"WXSliderNeighborComponent")];
+    
+    [self registerComponent:@"recycle-list" withClass:NSClassFromString(@"WXRecycleListComponent")];
+    [self registerComponent:@"cell-slot" withClass:NSClassFromString(@"WXCellSlotComponent") withProperties: @{@"append":@"tree", @"isTemplate":@YES}];
+    
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
index 8eb799b..6247f07 100644
--- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
@@ -109,7 +109,10 @@
         [dict addEntriesFromDictionary:params];
     }
     
-    [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:self.ref type:eventName params:dict domChanges:domChanges];
+    NSArray *handlerArguments = [self _paramsForEvent:eventName];
+    NSString *ref = _templateComponent ? _templateComponent.ref  : self.ref;
+    
+    [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:ref type:eventName params:dict domChanges:domChanges handlerArguments:handlerArguments];
 }
 
 - (void)addEvent:(NSString *)addEventName

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
index fee0be7..7ff2e01 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -125,12 +125,23 @@ extern void WXPerformBlockOnBridgeThread(void (^block)());
  *  @param instanceId   instance id
  *  @param ref       :   node reference
  *  @param type      :   event type
- *  @param params    :   parameters
+ *  @param params    :   parameters in event object
  *  @param domChanges   dom value changes, used for two-way data binding
  **/
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges;
 
 /**
+ *  FireEvent
+ *  @param instanceId   instance id
+ *  @param ref       :   node reference
+ *  @param type      :   event type
+ *  @param params    :   parameters in event object
+ *  @param domChanges:   dom value changes, used for two-way data binding
+ *  @param eventArguments : arguments passed to event handler
+ **/
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments;
+
+/**
  *  callBack
  *
  *  @param instanceId instanceId

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index 0bf5aca..791aceb 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -304,12 +304,22 @@ void WXPerformBlockOnBridgeThread(void (^block)())
 
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges
 {
+    [self fireEvent:instanceId ref:ref type:type params:params domChanges:domChanges handlerArguments:nil];
+}
+
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments
+{
     if (!type || !ref) {
         WXLogError(@"Event type and component ref should not be nil");
         return;
     }
     
     NSArray *args = @[ref, type, params?:@{}, domChanges?:@{}];
+    if (handlerArguments) {
+        NSMutableArray *newArgs = [args mutableCopy];
+        [newArgs addObject:@{@"params":handlerArguments}];
+        args = newArgs;
+    }
     WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
     
     WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
index f2d2f6a..73b08e1 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
@@ -18,6 +18,16 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXInvocationConfig.h"
+
+@interface WXComponentConfig : WXInvocationConfig
+
+@property (nonatomic, strong) NSDictionary *properties;
+
+- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros;
+
+@end
+
 
 @interface WXComponentFactory : NSObject
 
@@ -53,6 +63,8 @@
  */
 + (Class)classWithComponentName:(NSString *)name;
 
++ (WXComponentConfig *)configWithComponentName:(NSString *)name;
+
 /**
  * @abstract Returns the registered components.
  */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
index 6970376..0101d7a 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
@@ -20,17 +20,9 @@
 #import "WXComponentFactory.h"
 #import "WXAssert.h"
 #import "WXLog.h"
-#import "WXInvocationConfig.h"
 
 #import <objc/runtime.h>
 
-@interface WXComponentConfig : WXInvocationConfig
-@property (nonatomic, strong) NSDictionary *properties;
-
-- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros;
-
-@end
-
 @implementation WXComponentConfig
 
 - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz pros:(NSDictionary *)pros
@@ -82,7 +74,17 @@
 
 + (Class)classWithComponentName:(NSString *)name
 {
-    return [[self sharedInstance] classWithComponentName:name];
+    WXComponentConfig *config = [self configWithComponentName:name];
+    if(!config || !config.clazz) {
+        return nil;
+    }
+    
+    return NSClassFromString(config.clazz);
+}
+
++ (WXComponentConfig *)configWithComponentName:(NSString *)name
+{
+    return [[self sharedInstance] configWithComponentName:name];
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros
@@ -195,9 +197,9 @@
     return componentDic;
 }
 
-- (Class)classWithComponentName:(NSString *)name
+- (WXComponentConfig *)configWithComponentName:(NSString *)name
 {
-    WXAssert(name, @"Can not find class for a nil component name");
+    WXAssert(name, @"Can not find config for a nil component name");
     
     WXComponentConfig *config = nil;
     
@@ -209,11 +211,7 @@
     }
     [_configLock unlock];
     
-    if(!config || !config.clazz) {
-        return nil;
-    }
-    
-    return NSClassFromString(config.clazz);
+    return config;
 }
 
 - (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5b99cc6b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
index 729e6d7..ff5182c 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -24,8 +24,16 @@
 @class WXSDKInstance;
 @class WXComponent;
 
-extern void WXPerformBlockOnComponentThread(void (^block)());
-
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+void WXPerformBlockOnComponentThread(void (^block)());
+void WXPerformBlockSyncOnComponentThread(void (^block)());
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXComponentManager : NSObject
 
@@ -91,6 +99,7 @@ extern void WXPerformBlockOnComponentThread(void (^block)());
  */
 - (NSUInteger)numberOfComponents;
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref;
 
 ///--------------------------------------
 /// @name Updating



[07/17] incubator-weex git commit: * [ios] add missing "}ā€œ

Posted by ac...@apache.org.
* [ios] add missing "}ā€œ


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

Branch: refs/heads/0.16-dev
Commit: 6132c1814316b7adffde24ec33f0b0639f7f4450
Parents: 6a272ab
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:27:35 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:27:35 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6132c181/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 5bdc7f3..2bad1c2 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -174,6 +174,7 @@
     });
     
     return component;
+}
 
 - (UIAccessibilityTraits)_parseAccessibilityTraitsWithTraits:(UIAccessibilityTraits)trait roles:(NSString*)roleStr
 {


[08/17] incubator-weex git commit: * [ios] update apache license header

Posted by ac...@apache.org.
* [ios] update apache license header


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

Branch: refs/heads/0.16-dev
Commit: 81c7816ee38f55d032ceaa1135299c3e5805eaf8
Parents: 6132c18
Author: yinfeng <cx...@apache.org>
Authored: Thu Sep 21 17:30:03 2017 +0800
Committer: yinfeng <cx...@apache.org>
Committed: Thu Sep 21 17:30:03 2017 +0800

----------------------------------------------------------------------
 .../Component/RecycleList/WXRecycleListLayout.h | 25 ++++++++++++++------
 .../Component/RecycleList/WXRecycleListLayout.m | 25 ++++++++++++++------
 2 files changed, 36 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/81c7816e/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
index 04e65ea..6e08b94 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.h
@@ -1,10 +1,21 @@
-//
-//  WXRecycleListLinearLayout.h
-//  WeexSDK
-//
-//  Created by yinfeng on 2017/9/19.
-//  Copyright Ā© 2017幓 taobao. All rights reserved.
-//
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 #import <UIKit/UIKit.h>
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/81c7816e/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
index e5bc8c3..73851de 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListLayout.m
@@ -1,10 +1,21 @@
-//
-//  WXRecycleListLinearLayout.m
-//  WeexSDK
-//
-//  Created by yinfeng on 2017/9/19.
-//  Copyright Ā© 2017幓 taobao. All rights reserved.
-//
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 #import "WXRecycleListLayout.h"
 


[13/17] incubator-weex git commit: Merge branch 'jsfm-release-0.22' of https://github.com/Hanks10100/incubator-weex into wip-us-0.16-dev

Posted by ac...@apache.org.
Merge branch 'jsfm-release-0.22' of https://github.com/Hanks10100/incubator-weex into wip-us-0.16-dev


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

Branch: refs/heads/0.16-dev
Commit: 8725289bcd2c84007fcd9458f75fd987501b3ac3
Parents: d06657d b7ff22e
Author: acton393 <zh...@gmail.com>
Authored: Thu Sep 21 21:42:28 2017 +0800
Committer: acton393 <zh...@gmail.com>
Committed: Thu Sep 21 21:42:28 2017 +0800

----------------------------------------------------------------------

----------------------------------------------------------------------



[12/17] incubator-weex git commit: Merge branch '0.17-dev-feature-recycle-list' of https://github.com/cxfeng1/incubator-weex into wip-us-0.16-dev

Posted by ac...@apache.org.
Merge branch '0.17-dev-feature-recycle-list' of https://github.com/cxfeng1/incubator-weex into wip-us-0.16-dev


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

Branch: refs/heads/0.16-dev
Commit: d06657dd87527a73046404c066d7ecb3b4b33564
Parents: af29230 523843a
Author: acton393 <zh...@gmail.com>
Authored: Thu Sep 21 21:42:03 2017 +0800
Committer: acton393 <zh...@gmail.com>
Committed: Thu Sep 21 21:42:03 2017 +0800

----------------------------------------------------------------------

----------------------------------------------------------------------



[11/17] incubator-weex git commit: * [jsfm] upgrade weex-js-framework to 0.22.3

Posted by ac...@apache.org.
* [jsfm] upgrade weex-js-framework to 0.22.3


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

Branch: refs/heads/0.16-dev
Commit: b7ff22e12605209c5ffb376dfa0d16a45ba45843
Parents: 8325077
Author: Hanks <zh...@gmail.com>
Authored: Thu Sep 21 19:17:23 2017 +0800
Committer: Hanks <zh...@gmail.com>
Committed: Thu Sep 21 19:17:23 2017 +0800

----------------------------------------------------------------------
 pre-build/native-bundle-main.js | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------



[10/17] incubator-weex git commit: * [jsfm] upgrade weex-js-framework to 0.22.3

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b7ff22e1/pre-build/native-bundle-main.js
----------------------------------------------------------------------
diff --git a/pre-build/native-bundle-main.js b/pre-build/native-bundle-main.js
index 462e4fc..70f4b57 100644
--- a/pre-build/native-bundle-main.js
+++ b/pre-build/native-bundle-main.js
@@ -1,8 +1,8 @@
-(this.nativeLog||function(e){console.log(e)})("START JS FRAMEWORK 0.21.11, Build 2017-08-23 15:52."),this.getJSFMVersion=function(){return"0.21.11"};var global=this,process={env:{}},setTimeout=global.setTimeout;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(0,function(){"use strict";function e(e){Qn.Document=e.Document,Qn.Element=e.Element,Qn.Comment=e.Comment,Qn.sendTasks=e.sendTasks}function t(e){}function n(e){}function r(e){}function o(e,t,n){}function i(e,t,n,r,o){var i=new Qn.Document(e,n.bundleUrl),a={},s=0;i.addCallback=function(e){return s++,a[s]=e,s},i.handleCallback=function(e,t,n){var r=a[e];return n&&delete a[e],r(t)},Yn[e]=i;var u=Object.assign({Document:Qn.Document,Element:Qn.Element,Comment:Qn.Comment,sendTasks:Qn.sendTasks,id:e,options:n,data:r,document:i},o),c=[],l=[];for(var f in u)c.push(f),l.push(u[f]);return c.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(c)))).app
 ly(void 0,l),{document:i}}function a(e,t){}function s(e){delete Yn[e]}function u(e){return Yn[e].body.toJSON()}function c(e,t){var n={fireEvent:function(e,t,n,r,o){var i=Yn[e],a=i.getRef(t);return i.fireEvent(a,n,r,o)},callback:function(e,t,n,r){return Yn[e].handleCallback(t,n,r)}};if(Yn[e]&&Array.isArray(t)){var r=[];return t.forEach(function(t){var o=n[t.method],i=[].concat(t.args);"function"==typeof o&&(i.unshift(e),r.push(o.apply(void 0,i)))}),r}}function l(e){return e&&e.__esModule?e.default:e}function f(e,t){return t={exports:{}},e(t,t.exports),t.exports}function d(e){console.warn("[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead");var t=this._ids[e];if(t)return t.vm}function p(e){var t=this._ids[e];if(t)return t.el}function h(e){var t=this._ids[e];if(t)return t.vm}function v(e){return this._app.differ.then(function(){e()})}function y(e,t){console.warn("[JS Framework] Vm#$scrollTo is deprecated, please use \"require('@weex-module/dom').scrollTo(el, options)\" inste
 ad");var n=this.$el(e);if(n){this._app.requireModule("dom").scrollToElement(n.ref,{offset:t})}}function m(e,t,n){var r=this,o=this.$el(e);if(o&&t&&t.styles){this._app.requireModule("animation").transition(o.ref,t,function(){for(var e=[],i=arguments.length;i--;)e[i]=arguments[i];r._setStyle(o,t.styles),n&&n.apply(void 0,e)})}}function _(e){var t=this._app.options;return"function"==typeof e&&(console.warn("[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, this api now can directly RETURN config info."),e(t)),t}function g(e,t){console.warn("[JS Framework] Vm#$sendHttp is deprecated, please use \"require('@weex-module/stream').sendHttp(params, callback)\" instead"),this._app.requireModule("stream").sendHttp(e,t)}function b(e){console.warn("[JS Framework] Vm#$openURL is deprecated, please use \"require('@weex-module/event').openURL(url)\" instead"),this._app.requireModule("event").openURL(e)}function w(e){console.warn("[JS Framework] Vm#$setTitle is deprecated, please
  use \"require('@weex-module/pageInfo').setTitle(title)\" instead"),this._app.requireModule("pageInfo").setTitle(e)}function O(e,t){for(var n=[],r=arguments.length-2;r-- >0;)n[r]=arguments[r+2];console.warn("[JS Framework] Vm#$call is deprecated, please use \"require('@weex-module/moduleName')\" instead");var o=this._app.requireModule(e);o&&o[t]&&o[t].apply(o,n)}function E(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];if("function"==typeof Object.assign)Object.assign.apply(Object,[e].concat(t));else{var r=t.shift();for(var o in r)e[o]=r[o];t.length&&E.apply(void 0,[e].concat(t))}return e}function x(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function S(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function C(e,t){return gr.call(e,t)}function k(e,t){return function(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}}function j(e){return null!==e&&"object"==typeof e}func
 tion A(e){return br.call(e)===wr}function I(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function T(){return"object"==typeof nativeSet?nativeSet.create():new Zn}function N(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1).toLowerCase()}function P(e){return e.replace(Er,"").replace(xr,"")}function M(e){return e.replace(Cr,"")}function $(){this.id=Tr++,this.subs=[]}function R(e){$.target&&Nr.push($.target),$.target=e}function D(){$.target=Nr.pop()}function F(){$.target=null,Nr=[]}function L(e,t,n,r){r&&E(this,r);var o="function"==typeof t;this.vm=e,e._watchers.push(this),this.expression=t,this.cb=n,this.id=++Pr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=T(),this.newDepIds=T(),o&&(this.getter=t),this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function V(e,t){var n,r,o,i;if(t||(t=Mr,t.clear()),o=Array.isArray(e),i=j(e),o||i){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.le
 ngth;n--;)V(e[n],t);else if(i)for(r=Object.keys(e),n=r.length;n--;)V(e[r[n]],t)}}function U(e){if(this.value=e,this.dep=new $,x(e,"__ob__",this),Array.isArray(e)){(Or?W:B)(e,Rr,Dr),this.observeArray(e)}else this.walk(e)}function W(e,t){e.__proto__=t}function B(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];x(e,i,t[i])}}function q(e,t){if(j(e)){var n;return C(e,"__ob__")&&e.__ob__ instanceof U?n=e.__ob__:(Array.isArray(e)||A(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new U(e)),n&&t&&n.addVm(t),n}}function z(e,t,n){var r=new $,o=Object.getOwnPropertyDescriptor(e,t);if(!o||!1!==o.configurable){var i=o&&o.get,a=o&&o.set,s=q(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=i?i.call(e):n;if($.target&&(r.depend(),s&&s.dep.depend(),Array.isArray(t)))for(var o=void 0,a=0,u=t.length;a<u;a++)(o=t[a])&&o.__ob__&&o.__ob__.dep.depend();return t},set:function(t){t!==(i?i.call(e):n)&&(a?a.call(e,t):n=t,s=q(t),r.notify())}})}}function J(e,t,n){if(Array.isArray(e))r
 eturn e.splice(t,1,n);if(C(e,t))return void(e[t]=n);if(e._isVue)return void J(e._data,t,n);var r=e.__ob__;if(!r)return void(e[t]=n);if(r.convert(t,n),r.dep.notify(),r.vms)for(var o=r.vms.length;o--;){var i=r.vms[o];G(i,t)}return n}function H(e,t){if(C(e,t)){delete e[t];var n=e.__ob__;if(!n)return void(e._isVue&&delete e._data[t]);if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var o=n.vms[r];X(o,t)}}}function G(e,t){(Fr.indexOf(t)>-1||!I(t))&&Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return e._data[t]},set:function(n){e._data[t]=n}})}function X(e,t){I(t)||delete e[t]}function K(e){e._watchers=[],Z(e),Y(e),te(e)}function Z(e){var t=e._data;A(t)||(t={});for(var n=Object.keys(t),r=n.length;r--;)G(e,n[r]);q(t,e)}function Q(){}function Y(e){var t=e._computed;if(t)for(var n in t){var r=t[n],o={enumerable:!0,configurable:!0};"function"==typeof r?(o.get=ee(r,e),o.set=Q):(o.get=r.get?!1!==r.cache?ee(r.get,e):k(r.get,e):Q,o.set=r.set?k(r.set,e):Q),Object.def
 ineProperty(e,n,o)}}function ee(e,t){var n=new L(t,e,null,{lazy:!0});return function(){return n.dirty&&n.evaluate(),$.target&&n.depend(),n.value}}function te(e){var t=e._methods;if(t)for(var n in t)e[n]=t[n]}function ne(e){var t=e.type,n=Vr[t];if("object"==typeof n)for(var r in n)if(null==e[r])e[r]=n[r];else if("object"===N(e[r])&&"object"===N(n[r]))for(var o in n[r])null==e[r][o]&&(e[r][o]=n[r][o])}function re(e,t,n){ce(e,t,n.id,e),le(e,t,n.attr),de(e,t,n.classList),pe(e,t,n.style),ve(e,t,n.events)}function oe(e,t,n,r){t=t||{},n=n||{};var o=t._options||{},i=o.props;Array.isArray(i)&&(i=i.reduce(function(e,t){return e[t]=!0,e},{})),ae(r,i,e,t),ae(n.attr,i,e,t)}function ie(e,t,n,r){void 0===r&&(r={}),ue(n.classList,e,t),se(n.style,e,t),r.children?r.children[r.children.length-1]._vm=t:r._vm=t}function ae(e,t,n,r){if(e){for(var o in e)!function(o){if(!t||t[o]){var i=e[o];if("function"==typeof i){var a=_e(n,i,function(e){r[o]=e});r[o]=a}else r[o]=i}}(o)}}function se(e,t,n){for(var r in 
 e)!function(r){var o=e[r];if("function"==typeof o){var i=_e(t,o,function(e){n._rootEl&&n._rootEl.setStyle(r,e)});n._rootEl.setStyle(r,i)}else n._rootEl&&n._rootEl.setStyle(r,o)}(r)}function ue(e,t,n){function r(e,t){"array"===N(e)&&e.unshift(t)}var o=t._options&&t._options.style||{};if(n._rootEl){var i="@originalRootEl";if(o[i]=n._rootEl.classStyle,"function"==typeof e){var a=_e(t,e,function(e){r(e,i),fe(n._rootEl,o,e)});r(a,i),fe(n._rootEl,o,a)}else null!=e&&(r(e,i),fe(n._rootEl,o,e))}}function ce(e,t,n,r){var o=Object.create(null);if(Object.defineProperties(o,{vm:{value:r,writable:!1,configurable:!1},el:{get:function(){return t||r._rootEl},configurable:!1}}),"function"==typeof n){var i=n;n=i.call(e),(n||0===n)&&(e._ids[n]=o),_e(e,i,function(t){t&&(e._ids[t]=o)})}else n&&"string"==typeof n&&(e._ids[n]=o)}function le(e,t,n){ye(e,t,"attr",n)}function fe(e,t,n){"string"==typeof n&&(n=n.split(/\s+/)),n.forEach(function(e,t){n.splice.apply(n,[t,1].concat(e.split(/\s+/)))});for(var r={},
 o=n.length,i=0;i<o;i++)!function(e){var o=t[n[e]];o&&Object.keys(o).forEach(function(e){r[e]=o[e]})}(i);e.setClassStyle(r)}function de(e,t,n){if("function"==typeof n||Array.isArray(n)){if(Array.isArray(n)&&!n.length)return void t.setClassStyle({});var r=e._options&&e._options.style||{};if("function"==typeof n){var o=_e(e,n,function(e){fe(t,r,e)});fe(t,r,o)}else fe(t,r,n)}}function pe(e,t,n){ye(e,t,"style",n)}function he(e,t,n,r){t.addEvent(n,k(r,e))}function ve(e,t,n){if(n)for(var r=Object.keys(n),o=r.length;o--;){var i=r[o],a=n[i];"string"==typeof a&&((a=e[a])||console.warn('[JS Framework] The event handler "'+a+'" is not defined.')),he(e,t,i,a)}}function ye(e,t,n,r){if(r)for(var o=Object.keys(r),i=o.length;i--;){var a=o[i],s=r[a];"function"==typeof s?me(e,t,n,a,s):t[Ur[n]](a,s)}}function me(e,t,n,r,o){var i=Ur[n],a=_e(e,o,function(n){function o(){t[i](r,n)}var a=e&&e._app&&e._app.differ;a?a.append("element",t.depth||0,t.ref,o):o()});t[i](r,a)}function _e(e,t,n){return e._static?t.
 call(e,e):new L(e,t,function(e,t){"object"!=typeof e&&e===t||n(e)}).value}function ge(e,t){return e._app.doc.createBody(t)}function be(e,t){return e._app.doc.createElement(t)}function we(e,t){var n=Oe(e),r=Ee(e),o=Wr++;if(t.element){var i=t.updateMark;i?(i.element&&(i=i.end),t.element.insertAfter(r,i),t.element.insertAfter(n,i),t.updateMark=r):(t.element.insertBefore(n,t.end),t.element.insertBefore(r,t.end)),t=t.element}else t.appendChild(n),t.appendChild(r);return{start:n,end:r,element:t,blockId:o}}function Oe(e){return e._app.doc.createComment("start")}function Ee(e){return e._app.doc.createComment("end")}function xe(e,t,n){if(n.element){var r=n.end,o=n.updateMark;if(n.children&&n.children.push(t),o){var i=Se(e,t,o);return n.updateMark=t.element?t.end:t,i}if(!t.element)return n.element.insertBefore(t,r);n.element.insertBefore(t.start,r),n.element.insertBefore(t.end,r)}else{if(!t.element)return n.appendChild(t);n.appendChild(t.start),n.appendChild(t.end)}}function Se(e,t,n){return 
 t.element?ke(t,n):Ce(t,n)}function Ce(e,t){var n=t.parentNode;if(n)return n.insertAfter(e,t)}function ke(e,t){var n=t.parentNode;if(n){for(var r,o=e.start,i=[o];o&&o!==e.end;)o=o.nextSibling,i.push(o);var a=t;return i.every(function(e){return r=n.insertAfter(e,a),a=e,-1!==r}),r}}function je(e,t,n){void 0===n&&(n=!1),t.element?Ie(t,n):Ae(t),t._vm&&t._vm.$emit("hook:destroyed")}function Ae(e){var t=e.parentNode;t&&t.removeChild(e)}function Ie(e,t){void 0===t&&(t=!1);for(var n=[],r=e.start.nextSibling;r&&r!==e.end;)n.push(r),r=r.nextSibling;t||Ae(e.start),n.forEach(function(e){Ae(e)}),t||Ae(e.end)}function Te(e){var t=e._options||{},n=t.template||{};t.replace?n.children&&1===n.children.length?Ne(e,n.children[0],e._parentEl):Ne(e,n.children,e._parentEl):Ne(e,n,e._parentEl),console.debug('[JS Framework] "ready" lifecycle in Vm('+e._type+")"),e.$emit("hook:ready"),e._ready=!0}function Ne(e,t,n,r){if(-1!==(e._app||{}).lastSignal){if(t.attr&&t.attr.hasOwnProperty("static")&&(e._static=!0),P
 e(t))return void Le(e,t,n,r);if(r=r||{},Me(t))return console.debug('[JS Framework] compile "content" block by',t),void(e._content=we(e,n));if($e(t,r))return console.debug('[JS Framework] compile "repeat" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `repeat` directive!"):Ve(e,t,n));if(Re(t,r))return console.debug('[JS Framework] compile "if" logic by',t),void("document"===n.type?console.warn("[JS Framework] The root element does't support `if` directive!"):Ue(e,t,n,r));var o=r.type||t.type;if(De(o,r))return void We(e,t,n,o,r);var i=o,a=Fe(e,t,i);if(a)return console.debug("[JS Framework] compile composed component by",t),void Be(e,a,t,n,i,r);console.debug("[JS Framework] compile native component by",t),qe(e,t,n,i)}}function Pe(e){return Array.isArray(e)}function Me(e){return"content"===e.type||"slot"===e.type}function $e(e,t){return!t.hasOwnProperty("repeat")&&e.repeat}function Re(e,t){return!t.hasOwnProperty("shown")&&e.shown}func
 tion De(e,t){return"function"==typeof e&&!t.hasOwnProperty("type")}function Fe(e,t,n){var r;return e._app&&e._app.customComponentMap&&(r=e._app.customComponentMap[n]),e._options&&e._options.components&&(r=e._options.components[n]),t.component&&(r=r||{}),r}function Le(e,t,n,r){var o=we(e,n);t.forEach(function(t){Ne(e,t,o,r)})}function Ve(e,t,n){var r=t.repeat,o="function"==typeof r,i=r.getter||r.expression||r;"function"!=typeof i&&(i=function(){return[]});var a=r.key||"$index",s=r.value||"$value",u=r.trackBy||t.trackBy||t.attr&&t.attr.trackBy,c=we(e,n);c.children=[],c.data=[],c.vms=[],Je(e,t,c,{getter:i,key:a,value:s,trackBy:u,oldStyle:o})}function Ue(e,t,n,r){var o={shown:!0},i=we(e,n);n.element&&n.children&&n.children.push(i),r.repeat&&(o.repeat=r.repeat),He(e,t,i,o)}function We(e,t,n,r,o){var i=r.call(e),a=E({type:i},o),s=we(e,n);n.element&&n.children&&n.children.push(s),_e(e,r,function(n){var r=E({type:n},o);je(e,s,!0),Ne(e,t,s,r)}),Ne(e,t,s,a)}function Be(e,t,n,r,o,i){var a=e.co
 nstructor,s=new a(o,t,e,r,void 0,{"hook:init":function(){e._static&&(this._static=e._static),ce(e,null,n.id,this),this._externalBinding={parent:e,template:n}},"hook:created":function(){oe(e,this,n,i.repeat)},"hook:ready":function(){this._content&&ze(e,n,this._content)}});ie(e,s,n,r)}function qe(e,t,n,r){ne(t);var o;if("_documentElement"===n.ref?(console.debug("[JS Framework] compile to create body for "+r),o=ge(e,r)):(console.debug("[JS Framework] compile to create element for "+r),o=be(e,r)),!e._rootEl){e._rootEl=o;var i=e._externalBinding||{},a=i.template,s=i.parent;if(a&&a.events&&s&&o)for(var u in a.events){var c=s[a.events[u]];c&&o.addEvent(u,k(c,s))}}re(e,o,t),t.attr&&t.attr.append&&(t.append=t.attr.append),t.append&&(o.attr=o.attr||{},o.attr.append=t.append);var l="tree"===t.append,f=e._app||{};-1===f.lastSignal||l||(console.debug("[JS Framework] compile to append single node for",o),f.lastSignal=xe(e,o,n)),-1!==f.lastSignal&&ze(e,t,o),-1!==f.lastSignal&&l&&(console.debug("[J
 S Framework] compile to append whole tree for",o),f.lastSignal=xe(e,o,n))}function ze(e,t,n){var r=e._app||{},o=t.children;o&&o.length&&o.every(function(t){return Ne(e,t,n),-1!==r.lastSignal})}function Je(e,t,n,r){function o(e,r,o){var a;c?(a=e,j(e)?(a[l]=r,a.hasOwnProperty("INDEX")||Object.defineProperty(a,"INDEX",{value:function(){console.warn('[JS Framework] "INDEX" in repeat is deprecated, please use "$index" instead')}})):(console.warn("[JS Framework] Each list item must be an object in old-style repeat, please use `repeat={{v in list}}` instead."),a={},a[l]=r,a[f]=e)):(a={},a[l]=r,a[f]=e);var s=Xe(o,a);i.push(s),Ne(s,t,n,{repeat:e})}var i=n.vms,a=n.children,s=r.getter,u=r.trackBy,c=r.oldStyle,l=r.key,f=r.value,d=Ge(e,n,s,"repeat",function(t){if(console.debug('[JS Framework] the "repeat" item has changed',t),n&&t){var r=a.slice(),s=i.slice(),d=n.data.slice(),p={},h={};t.forEach(function(e,t){var n=u?e[u]:c?e[l]:t;null!=n&&""!==n&&(p[n]=e)});var v=[];d.forEach(function(t,n){var 
 o=u?t[u]:c?t[l]:n;p.hasOwnProperty(o)?(h[o]={item:t,index:n,key:o,target:r[n],vm:s[n]},v.push(t)):je(e,r[n])}),a.length=0,i.length=0,n.data=t.slice(),n.updateMark=n.start,t.forEach(function(t,r){var s=u?t[u]:c?t[l]:r,d=h[s];d?(d.item===v[0]?v.shift():(v.$remove(d.item),Se(e,d.target,n.updateMark,!0)),a.push(d.target),i.push(d.vm),c?d.vm=t:d.vm[f]=t,d.vm[l]=r,n.updateMark=d.target):o(t,r,e)}),delete n.updateMark}});n.data=d.slice(0),d.forEach(function(t,n){o(t,n,e)})}function He(e,t,n,r){var o=Ge(e,n,t.shown,"shown",function(o){console.debug('[JS Framework] the "if" item was changed',o),n&&!!n.display!=!!o&&(n.display=!!o,o?Ne(e,t,n,r):je(e,n,!0))});n.display=!!o,o&&Ne(e,t,n,r)}function Ge(e,t,n,r,o){var i=e&&e._app&&e._app.differ,a={},s=(t.element.depth||0)+1;return _e(e,n,function(e){a.latestValue=e,i&&!a.recorded&&i.append(r,s,t.blockId,function(){var e=a.latestValue;o(e),a.recorded=!1,a.latestValue=void 0}),a.recorded=!0})}function Xe(e,t){var n=Object.create(e);return n._data=t,
 Z(n),Y(n),n._realParent=e,e._static&&(n._static=e._static),n}function Ke(e,t){if(t instanceof Ke)return t;this.timestamp=Date.now(),this.detail=t,this.type=e;var n=!1;this.stop=function(){n=!0},this.hasStopped=function(){return n}}function Ze(e,t){var n=this,r=this._vmEvents,o=r[e];if(o){var i=new Ke(e,t);o.forEach(function(e){e.call(n,i)})}}function Qe(e,t){var n=new Ke(e,t);this.$emit(e,n),!n.hasStopped()&&this._parent&&this._parent.$dispatch&&this._parent.$dispatch(e,n)}function Ye(e,t){var n=new Ke(e,t);this.$emit(e,n),!n.hasStopped()&&this._childrenVms&&this._childrenVms.forEach(function(t){t.$broadcast(e,n)})}function et(e,t){if(e&&"function"==typeof t){var n=this._vmEvents,r=n[e]||[];r.push(t),n[e]=r,"hook:ready"===e&&this._ready&&this.$emit("hook:ready")}}function tt(e,t){if(e){var n=this._vmEvents;if(!t)return void delete n[e];var r=n[e];r&&r.$remove(t)}}function nt(e,t){var n=e._options||{},r=n.events||{};for(var o in r)e.$on(o,r[o]);for(var i in t)e.$on(i,t[i]);Br.forEach
 (function(t){e.$on("hook:"+t,n[t])})}function rt(e,t,n,r,o,i){n=n||{},this._parent=n._realParent?n._realParent:n,this._app=n._app||{},n._childrenVms&&n._childrenVms.push(this),!t&&this._app.customComponentMap&&(t=this._app.customComponentMap[e]),t=t||{};var a=t.data||{};this._options=t,this._methods=t.methods||{},this._computed=t.computed||{},this._css=t.style||{},this._ids={},this._vmEvents={},this._childrenVms=[],this._type=e,nt(this,i),console.debug('[JS Framework] "init" lifecycle in Vm('+this._type+")"),this.$emit("hook:init"),this._inited=!0,this._data="function"==typeof a?a():a,o&&E(this._data,o),K(this),console.debug('[JS Framework] "created" lifecycle in Vm('+this._type+")"),this.$emit("hook:created"),this._created=!0,t.methods&&t.methods.ready&&(console.warn('"exports.methods.ready" is deprecated, please use "exports.created" instead'),t.methods.ready.call(this)),this._app.doc&&(this._parentEl=r||this._app.doc.documentElement,Te(this))}function ot(e,t){for(var n in e)!func
 tion(n){var r=qr[n];r||(r={},qr[n]=r),e[n].forEach(function(e){"string"==typeof e&&(e={name:e}),r[e.name]&&!t||(r[e.name]=e)})}(n)}function it(e,t){var n=e.prototype;for(var r in t)n.hasOwnProperty(r)||(n[r]=t[r])}function at(e,t){var n=qr[t],r={};for(var o in n)!function(n){Object.defineProperty(r,n,{configurable:!0,enumerable:!0,get:function(){return function(){for(var r=[],o=arguments.length;o--;)r[o]=arguments[o];return e.callTasks({module:t,method:n,args:r})}},set:function(r){if("function"==typeof r)return e.callTasks({module:t,method:n,args:[r]})}})}(o);return r}function st(e,t){return e.customComponentMap[t]}function ut(e,t,n){var r=e.customComponentMap;if(r[t])return void console.error("[JS Framework] define a component("+t+") that already exists");r[t]=n}function ct(e){if(zr.valid(e))return e;e="string"==typeof e?e:"";for(var t=e.split("."),n=0,r=[];n<3;){var o="string"==typeof t[n]&&t[n]?t[n]:"0";r.push(o),n++}return r.join(".")}function lt(e,t,n){var r={isDowngrade:!0,err
 orType:1,code:1e3},o=e.toLowerCase();return r.errorMessage=function(e,t,n){return"Downgrade["+e+"] :: deviceInfo "+t+" matched criteria "+n}(e,t,n),o.indexOf("osversion")>=0?r.code=1001:o.indexOf("appversion")>=0?r.code=1002:o.indexOf("weexversion")>=0?r.code=1003:o.indexOf("devicemodel")>=0&&(r.code=1004),r}function ft(e,t){t=t||global.WXEnvironment,t=A(t)?t:{};var n={isDowngrade:!1};if("function"===N(e)){var r=e.call(this,t,{semver:zr,normalizeVersion:ct});r=!!r,n=r?lt("custom","","custom params"):n}else{e=A(e)?e:{};var o=t.platform||"unknow",i=o.toLowerCase(),a=e[i]||{};for(var s in t){var u=s,c=u.toLowerCase(),l=t[s],f=c.indexOf("version")>=0,d=c.indexOf("devicemodel")>=0,p=a[s];if(p&&f){var h=ct(p),v=ct(t[s]);if(zr.satisfies(v,h)){n=lt(u,l,p);break}}else if(d){var y="array"===N(p)?p:[p];if(y.indexOf(l)>=0){n=lt(u,l,p);break}}}}return n}function dt(e,t){if(void 0===t&&(t={}),e&&e.callTasks)return e.callTasks([{module:"meta",method:"setViewport",args:[t]}])}function pt(e,t,n,r){c
 onsole.debug("[JS Framework] bootstrap for "+t);var o;if(kr(t))o=P(t);else{if(!Ir(t))return new Error("Wrong component name: "+t);if(o=M(t),!st(e,o))return new Error("It's not a component: "+t)}if(n=A(n)?n:{},"string"==typeof n.transformerVersion&&"string"==typeof global.transformerVersion&&!zr.satisfies(n.transformerVersion,global.transformerVersion))return new Error("JS Bundle version: "+n.transformerVersion+" not compatible with "+global.transformerVersion);var i=ft(n.downgrade);if(i.isDowngrade)return e.callTasks([{module:"instanceWrap",method:"error",args:[i.errorType,i.code,i.errorMessage]}]),new Error("Downgrade["+i.code+"]: "+i.errorMessage);n.viewport&&dt(e,n.viewport),e.vm=new rt(o,null,{_app:e},null,r)}function ht(e,t,n){console.warn("[JS Framework] Register is deprecated, please install lastest transformer."),ut(e,t,n)}function vt(e,t){console.debug("[JS Framework] Refresh with",t,"in instance["+e.id+"]");var n=e.vm;return n&&t?("function"==typeof n.refreshData?n.refresh
 Data(t):E(n,t),e.differ.flush(),void e.doc.taskCenter.send("dom",{action:"refreshFinish"},[])):new Error('invalid data "'+t+'"')}function yt(e){console.debug("[JS Framework] Destory an instance("+e.id+")"),e.vm&&mt(e.vm),e.id="",e.options=null,e.blocks=null,e.vm=null,e.doc.taskCenter.destroyCallback(),e.doc.destroy(),e.doc=null,e.customComponentMap=null,e.commonModules=null}function mt(e){if(delete e._app,delete e._computed,delete e._css,delete e._data,delete e._ids,delete e._methods,delete e._options,delete e._parent,delete e._parentEl,delete e._rootEl,e._watchers){for(var t=e._watchers.length;t--;)e._watchers[t].teardown();delete e._watchers}if(e._childrenVms){for(var n=e._childrenVms.length;n--;)mt(e._childrenVms[n]);delete e._childrenVms}console.debug('[JS Framework] "destroyed" lifecycle in Vm('+e._type+")"),e.$emit("hook:destroyed"),delete e._type,delete e._vmEvents}function _t(e){var t=e.doc||{},n=t.body||{};return n.toJSON?n.toJSON():{}}function gt(e,t,n,r,o){if(console.debu
 g('[JS Framework] Fire a "'+n+'" event on an element('+t+") in instance("+e.id+")"),Array.isArray(t))return void t.some(function(t){return!1!==gt(e,t,n,r)});var i=e.doc.getRef(t);if(i){var a=e.doc.fireEvent(i,n,r,o);return e.differ.flush(),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),a}return new Error('invalid element reference "'+t+'"')}function bt(e,t,n,r){console.debug("[JS Framework] Invoke a callback("+t+") with",n,"in instance("+e.id+")");var o=e.doc.taskCenter.callback(t,n,r);return wt(e),e.doc.taskCenter.send("dom",{action:"updateFinish"},[]),o}function wt(e){e.differ.flush()}function Ot(e,t){var n;return"array"!==N(t)&&(t=[t]),t.forEach(function(t){n=e.doc.taskCenter.send("module",{module:t.module,method:t.method},t.args)}),n}function Et(e,t,n,r){console.debug("[JS Framework] Intialize an instance with:\n",n);var o,i=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return Jr.apply(void 0,[e].concat(t))},a=function(t,r,i){o=pt(e,t,r,i||n),wt(e),e
 .doc.listener.createFinish(),console.debug("[JS Framework] After intialized an instance("+e.id+")")},s=rt,u=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];return ht.apply(void 0,[e].concat(t))},c=function(t,n){o=pt(e,t,{},n)},l=function(t){return function(n){o=pt(e,t,{},n)}},f=e.doc,d=function(t){return e.requireModule(P(t))},p={config:e.options,define:i,bootstrap:a,requireModule:d,document:f,Vm:s};Object.freeze(p);var h;"function"==typeof t?h=t.toString().substr(12):t&&(h=t.toString()),h='(function(global){\n\n"use strict";\n\n '+h+" \n\n})(Object.create(this))";var v=global.WXEnvironment,y={};if(v&&"Web"!==v.platform){var m=e.requireModule("timer");Object.assign(y,{setTimeout:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function(){t[0].apply(t,t.slice(2))};return m.setTimeout(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},setInterval:function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=function()
 {t[0].apply(t,t.slice(2))};return m.setInterval(r,t[1]),e.doc.taskCenter.callbackManager.lastCallbackId.toString()},clearTimeout:function(e){m.clearTimeout(e)},clearInterval:function(e){m.clearInterval(e)}})}var _=Object.assign({define:i,require:l,bootstrap:a,register:u,render:c,__weex_define__:i,__weex_bootstrap__:a,__weex_document__:f,__weex_require__:d,__weex_viewmodel__:s,weex:p},y,r);return St(_,h)||xt(_,h),o}function xt(e,t){var n=[],r=[];for(var o in e)n.push(o),r.push(e[o]);return n.push(t),(new(Function.prototype.bind.apply(Function,[null].concat(n)))).apply(void 0,r)}function St(e,t){if("function"!=typeof compileAndRunBundle)return!1;var n=void 0,r=!1,o="(function (",i=[],a=[];for(var s in e)i.push(s),a.push(e[s]);for(var u=0;u<i.length-1;++u)o+=i[u],o+=",";o+=i[i.length-1],o+=") {",o+=t,o+="} )";try{var c=e.weex||{},l=c.config||{};n=compileAndRunBundle(o,l.bundleUrl,l.bundleDigest,l.codeCachePath),n&&"function"==typeof n&&(n.apply(void 0,a),r=!0)}catch(e){console.error(e)
 }return r}function Ct(e,t){var n=e[t];for(var r in n)n[r]()}function kt(e,t){var n=e[t];for(var r in n){n[r].forEach(function(e){e()})}}function jt(e,t){this.id=e,this.options=t||{},this.vm=null,this.customComponentMap={},this.commonModules={},this.doc=new Lr.Document(e,this.options.bundleUrl,null,Lr.Listener),this.differ=new Hr(e)}function At(e,t,n,r,o){var i=o||{},a=i.services;F();var s=Gr[e];n=n||{};var u;return s?u=new Error('invalid instance id "'+e+'"'):(s=new jt(e,n),Gr[e]=s,u=Et(s,t,r,a)),u instanceof Error?u:s}function It(e){Lr.Document=e.Document,Lr.Element=e.Element,Lr.Comment=e.Comment,Lr.sendTasks=e.sendTasks,Lr.Listener=e.Listener}function Tt(e,t){var n=Gr[e];return n?vt(n,t):new Error('invalid instance id "'+e+'"')}function Nt(e){"function"==typeof markupState&&markupState(),F();var t=Gr[e];if(!t)return new Error('invalid instance id "'+e+'"');yt(t),delete Gr[e];var n=Math.round(e);if(n>0){n%18||"function"!=typeof notifyTrimMemory||notifyTrimMemory()}return Gr}functio
 n Pt(e){Array.isArray(e)&&e.forEach(function(e){e&&("string"==typeof e?Xr[e]=!0:"object"==typeof e&&"string"==typeof e.type&&(Xr[e.type]=e))})}function Mt(e){"object"==typeof e&&ot(e)}function $t(e){"object"==typeof e&&it(rt,e)}function Rt(e,t){if(Gr[e]&&Array.isArray(t)){var n=[];return t.forEach(function(t){var r=Kr[t.method],o=[].concat(t.args);"function"==typeof r&&(o.unshift(e),n.push(r.apply(void 0,o)))}),n}return new Error('invalid instance id "'+e+'" or tasks')}function Dt(e){var t=Gr[e];return t?_t(t):new Error('invalid instance id "'+e+'"')}function Ft(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=Qs(t),this.reject=Qs(n)}function Lt(){if(Ut(),global.WXEnvironment&&"Web"!==global.WXEnvironment.platform)global.console={debug:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("debug")&&global.nativeLog.apply(global,Bt(e).concat(["__DEBUG"]))},log:function(){for(var e=[]
 ,t=arguments.length;t--;)e[t]=arguments[t];Wt("log")&&global.nativeLog.apply(global,Bt(e).concat(["__LOG"]))},info:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("info")&&global.nativeLog.apply(global,Bt(e).concat(["__INFO"]))},warn:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("warn")&&global.nativeLog.apply(global,Bt(e).concat(["__WARN"]))},error:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("error")&&global.nativeLog.apply(global,Bt(e).concat(["__ERROR"]))}};else{var e=console.debug,t=console.log,n=console.info,r=console.warn,o=console.error;console.__ori__={debug:e,log:t,info:n,warn:r,error:o},console.debug=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("debug")&&console.__ori__.debug.apply(console,e)},console.log=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("log")&&console.__ori__.log.apply(console,e)},console.info=function(){for(var e=[],t=arguments.length;t--;)e[t
 ]=arguments[t];Wt("info")&&console.__ori__.info.apply(console,e)},console.warn=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("warn")&&console.__ori__.warn.apply(console,e)},console.error=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];Wt("error")&&console.__ori__.error.apply(console,e)}}}function Vt(){zu={},global.console=Ju}function Ut(){qu.forEach(function(e){var t=qu.indexOf(e);zu[e]={},qu.forEach(function(n){qu.indexOf(n)<=t&&(zu[e][n]=!0)})})}function Wt(e){var t=global.WXEnvironment&&global.WXEnvironment.logLevel||"log";return zu[t]&&zu[t][e]}function Bt(e){return e.map(function(e){return e="[object object]"===Object.prototype.toString.call(e).toLowerCase()?JSON.stringify(e):String(e)})}function qt(){if(void 0===setTimeout&&"function"==typeof Gu){var e={},t=0;global.setTimeout=function(n,r){e[++t]=n,Gu(t.toString(),r)},global.setTimeoutCallback=function(t){"function"==typeof e[t]&&(e[t](),delete e[t])}}}function zt(){global.setTimeout=H
 u,global.setTimeoutCallback=null}function Jt(){Object.freeze(Object),Object.freeze(Array),Ht(),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Gt(),Object.freeze(Date.prototype),Object.freeze(RegExp.prototype)}function Ht(){var e=Object.prototype,t="Object.prototype";Xt(e,"__defineGetter__",t),Xt(e,"__defineSetter__",t),Xt(e,"__lookupGetter__",t),Xt(e,"__lookupSetter__",t),Xt(e,"constructor",t),Xt(e,"hasOwnProperty",t),Xt(e,"isPrototypeOf",t),Xt(e,"propertyIsEnumerable",t),Xt(e,"toLocaleString",t),Xt(e,"toString",t),Xt(e,"valueOf",t),Object.seal(e)}function Gt(){var e=Error.prototype,t="Error.prototype";Xt(e,"name",t),Xt(e,"message",t),Xt(e,"toString",t),Xt(e,"constructor",t),Object.seal(e)}function Xt(e,t,n){if(e.hasOwnProperty(t)){var r=e[t];Object.defineProperty(e,t,{get:function(){return r},set:function(r){if(this===e)throw Error("Cannot assign to read only property "+t+" of "+n);return Object.define
 Property(this,t,{value:r,writable:!0}),r}})}}function Kt(e){var t=Object.prototype.toString.call(e);return t.substring(8,t.length-1)}function Zt(e){if("function"!=typeof btoa)return"";var t=Array.prototype.map.call(new Uint8Array(e),function(e){return String.fromCharCode(e)}).join("");return btoa(t)}function Qt(e){if("function"!=typeof atob)return new ArrayBuffer(0);var t=atob(e),n=new Uint8Array(t.length);return Array.prototype.forEach.call(t,function(e,t){n[t]=e.charCodeAt(0)}),n.buffer}function Yt(e){var t=Kt(e);switch(t){case"Undefined":case"Null":return"";case"RegExp":return e.toString();case"Date":return e.toISOString();case"Number":case"String":case"Boolean":case"Array":case"Object":return e;case"ArrayBuffer":return{"@type":"binary",dataType:t,base64:Zt(e)};case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":return{"@type":"binary",dataType:t,base64:Zt(e.buffer)};d
 efault:return JSON.stringify(e)}}function en(e){if("Object"===Kt(e)){
-if(e["@type"]&&"binary"===e["@type"])return Qt(e.base64||"");var t={};for(var n in e)t[n]=en(e[n]);return t}return"Array"===Kt(e)?e.map(en):e}function tn(e,t){e&&(Ku[e]=t)}function nn(e){return Ku[e]}function rn(e){delete Ku[e]}function on(e){var t=Ku[e];return t&&t.taskCenter?t.taskCenter:null}function an(){return(Zu++).toString()}function sn(e,t,n){var r=e.documentElement;if(!(r.pureChildren.length>0||t.parentNode)){var o=r.children,i=o.indexOf(n);i<0?o.push(t):o.splice(i,0,t),1===t.nodeType?("body"===t.role?(t.docId=e.id,t.ownerDocument=e,t.parentNode=r,ln(t,r)):(t.children.forEach(function(e){e.parentNode=t}),cn(e,t),t.docId=e.id,t.ownerDocument=e,ln(t,r),delete e.nodeMap[t.nodeId]),r.pureChildren.push(t),un(e,t)):(t.parentNode=r,e.nodeMap[t.ref]=t)}}function un(e,t){var n=t.toJSON(),r=n.children;delete n.children;var o=e.taskCenter.send("dom",{action:"createBody"},[n]);return r&&r.forEach(function(t){o=e.taskCenter.send("dom",{action:"addElement"},[n.ref,t,-1])}),o}function cn(
 e,t){t.role="body",t.depth=1,delete e.nodeMap[t.nodeId],t.ref="_root",e.nodeMap._root=t,e.body=t}function ln(e,t){e.parentNode=t,t.docId&&(e.docId=t.docId,e.ownerDocument=t.ownerDocument,e.ownerDocument.nodeMap[e.nodeId]=e,e.depth=t.depth+1),e.children.forEach(function(t){ln(t,e)})}function fn(e){for(;e;){if(1===e.nodeType)return e;e=e.nextSibling}}function dn(e){for(;e;){if(1===e.nodeType)return e;e=e.previousSibling}}function pn(e,t,n,r){n<0&&(n=0);var o=t[n-1],i=t[n];return t.splice(n,0,e),r&&(o&&(o.nextSibling=e),e.previousSibling=o,e.nextSibling=i,i&&(i.previousSibling=e)),n}function hn(e,t,n,r){var o=t.indexOf(e);if(o<0)return-1;if(r){var i=t[o-1],a=t[o+1];i&&(i.nextSibling=a),a&&(a.previousSibling=i)}t.splice(o,1);var s=n;o<=n&&(s=n-1);var u=t[s-1],c=t[s];return t.splice(s,0,e),r&&(u&&(u.nextSibling=e),e.previousSibling=u,e.nextSibling=c,c&&(c.previousSibling=e)),o===s?-1:n}function vn(e,t,n){var r=t.indexOf(e);if(!(r<0)){if(n){var o=t[r-1],i=t[r+1];o&&(o.nextSibling=i),i&&(i
 .previousSibling=o)}t.splice(r,1)}}function yn(){this.nodeId=an(),this.ref=this.nodeId,this.children=[],this.pureChildren=[],this.parentNode=null,this.nextSibling=null,this.previousSibling=null}function mn(e,t){if(t&&t.length){var n=function(t){Qu.call(this,e,t,!0)};n.prototype=Object.create(Qu.prototype),Object.defineProperty(n.prototype,"constructor",{configurable:!1,enumerable:!1,writable:!1,value:Qu}),t.forEach(function(t){n.prototype[t]=function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var o=on(this.docId);if(o)return o.send("component",{ref:this.ref,component:e,method:t},n)}}),Yu[e]=n}}function _n(e,t,n){void 0===e&&(e=ec);var r=Yu[e];if(r&&!n)return new r(t);t=t||{},this.nodeType=1,this.nodeId=an(),this.ref=this.nodeId,this.type=e,this.attr=t.attr||{},this.style=t.style||{},this.classStyle=t.classStyle||{},this.event={},this.children=[],this.pureChildren=[]}function gn(e,t){nn(e).nodeMap[t.nodeId]=t}function bn(){var e={createFinish:global.callCreateFinish,upd
 ateFinish: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},t=rc.prototype;for(var n in e)!function(n){var r=e[n];t[n]=r?function(e,t){return r.apply(void 0,[e].concat(t))}:function(e,t){return nc(e,[{module:"dom",method:n,args:t}],"-1")}}(n);t.componentHandler=global.callNativeComponent||function(e,t,n,r,o){return nc(e,[{component:o.component,ref:t,method:n,args:r}])},t.moduleHandler=global.callNativeModule||function(e,t,n,r){return nc(e,[{module:t,method:n,args:r}])}}function wn(e,t){En(e)?console.warn('Service "'+e+'" has been registered already!'):(t=Object.assign({},t),ac.push({name:e,options:t}))}function On(e){ac.some(function(t,n){if(t.name===e)return ac.splice(n,1),!0})}function En(e){return
  xn(e)>=0}function xn(e){return ac.map(function(e){return e.name}).indexOf(e)}function Sn(e){var t,n=sc.exec(e);if(n)try{t=JSON.parse(n[1])}catch(e){}return t}function Cn(e,t,n){var r=Object.create(null);return r.service=Object.create(null),ac.forEach(function(o){var i=(o.name,o.options),a=i.create;if(a){var s=a(e,t,n);Object.assign(r.service,s),Object.assign(r,s.instance)}}),delete r.service.instance,Object.freeze(r.service),r}function kn(e,t,n,r){var o=uc[e];if(!o){o=Sn(t)||{},oc[o.framework]||(o.framework="Weex"),n=JSON.parse(JSON.stringify(n||{})),n.bundleVersion=o.version,n.env=JSON.parse(JSON.stringify(global.WXEnvironment||{})),console.debug("[JS Framework] create an "+o.framework+"@"+n.bundleVersion+" instance from "+n.bundleVersion);var i={info:o,config:n,created:Date.now(),framework:o.framework};return i.services=Cn(e,i,ic),uc[e]=i,oc[o.framework].createInstance(e,t,n,r,i)}return new Error('invalid instance id "'+e+'"')}function jn(e){cc[e]=function(){for(var t=[],n=argume
 nts.length;n--;)t[n]=arguments[n];"registerComponents"===e&&An(t[0]);for(var r in oc){var o=oc[r];o&&o[e]&&o[e].apply(o,t)}}}function An(e){Array.isArray(e)&&e.forEach(function(e){e&&e.type&&e.methods&&mn(e.type,e.methods)})}function In(e){cc[e]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=uc[r];if(o&&oc[o.framework]){var i=(a=oc[o.framework])[e].apply(a,t);return"refreshInstance"===e?ac.forEach(function(e){var t=e.options.refresh;t&&t(r,{info:o,runtime:ic})}):"destroyInstance"===e&&(ac.forEach(function(e){var t=e.options.destroy;t&&t(r,{info:o,runtime:ic})}),delete uc[r]),i}return new Error('invalid instance id "'+r+'"');var a}}function Tn(e,t){cc[t]=function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var r=t[0],o=uc[r];return o&&oc[o.framework]?(i=oc[o.framework])[e].apply(i,t):new Error('invalid instance id "'+r+'"');var i}}function Nn(e){ic=e||{},oc=ic.frameworks||{},bn();for(var t in oc){oc[t].init(e)}return["registerComponents","
 registerModules","registerMethods"].forEach(jn),["destroyInstance","refreshInstance","receiveTasks","getRoot"].forEach(In),Tn("receiveTasks","callJS"),cc}function Pn(e){this.nodeType=8,this.nodeId=an(),this.ref=this.nodeId,this.type="comment",this.value=e,this.children=[],this.pureChildren=[]}function Mn(e,t){this.id=e,this.batched=!1,this.updates=[],"function"==typeof t?Object.defineProperty(this,"handler",{configurable:!0,enumerable:!0,writable:!0,value:t}):console.error("[JS Runtime] invalid parameter, handler must be a function")}function $n(e,t){return void 0===t&&(t=[]),{module:"dom",method:e,args:t}}function Rn(e,t){var n=t||global.callNative;return"function"!=typeof n&&console.error("[JS Runtime] no default handler"),function(t){Array.isArray(t)||(t=[t]);for(var r=0;r<t.length;r++){var o=Fn(e,t[r],n);if(-1===o)return o}}}function Dn(e,t){return"dom"===e&&lc[t]&&"function"==typeof global[lc[t]]}function Fn(e,t,n){var r=t.module,o=t.method,i=t.args;return Dn(r,o)?global[lc[o]]
 .apply(global,[e].concat(i,["-1"])):n(e,[t],"-1")}function Ln(e,t,n){e=e?e.toString():"",this.id=e,this.URL=t,tn(e,this),this.nodeMap={};var r=Ln.Listener||Mn;this.listener=new r(e,n||Rn(e,Ln.handler)),this.taskCenter=new rc(e,n?function(e){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];return n.apply(void 0,t)}:Ln.handler),this.createDocumentElement()}function Vn(e,t){var n=t.attrs||{};for(var r in n)e.setAttr(r,n[r],!0);var o=t.style||{};for(var i in o)e.setStyle(i,o[i],!0)}function Un(){Jt(),Object.freeze(fc.Element),Object.freeze(fc.Comment),Object.freeze(fc.Listener),Object.freeze(fc.Document.prototype),Object.freeze(fc.Element.prototype),Object.freeze(fc.Comment.prototype),Object.freeze(fc.Listener.prototype)}function Wn(e,t){void 0===t&&(t={}),this.type=e||"message",this.data=t.data||null,this.origin=t.origin||"",this.source=t.source||null,this.ports=t.ports||[],this.target=null,this.timeStamp=Date.now()}function Bn(){}function qn(e,t,n,r){console.warn("[Upgrad
 e Warning] $userTrack will be removed in the next version!"),console.warn("[JS Framework] Vm#$userTrack is deprecated, please use \"require('@weex-module/userTrack').commit(type, name, comName, param)\" instead"),this._app.requireModule("userTrack").commit(e,t,n,r)}function zn(e,t){if(console.warn("[Upgrade Warning] $sendMtop will be removed in the next version!"),console.warn("[JS Framework] Vm#$sendMtop is deprecated, please use \"require('@weex-module/stream').sendMtop(params, callback)\" instead"),"undefined"==typeof window){this._app.requireModule("windvane").call({class:"MtopWVPlugin",method:"send",data:e},t)}else{this._app.requireModule("stream").sendMtop(e,t)}}function Jn(e,t){console.warn("[Upgrade Warning] $callWindvane will be removed in the next version!"),console.warn("[JS Framework] Vm#$callWindvane is deprecated, please use \"require('@weex-module/windvane').call(params, callback)\" instead"),this._app.requireModule("windvane").call(e,t)}function Hn(e,t){console.warn(
 "[Upgrade Warning] $setSpm will be removed in the next version!"),console.warn("[JS Framework] Vm#$setSpm is deprecated, please use \"require('@weex-module/pageInfo').setSpm(a, b)\" instead"),this._app.requireModule("pageInfo").setSpm(e,t)}function Gn(e){console.warn("[Upgrade Warning] $getUserInfo will be removed in the next version!"),console.warn("[JS Framework] Vm#$getUserInfo is deprecated, please use \"require('@weex-module/user').getUserInfo(callback)\" instead"),this._app.requireModule("user").getUserInfo(e)}function Xn(e){console.warn("[Upgrade Warning] $login will be removed in the next version!"),console.warn("[JS Framework] Vm#$login is deprecated, please use \"require('@weex-module/user').login(callback)\" instead"),this._app.requireModule("user").login(e)}function Kn(e){console.warn("[Upgrade Warning] $logout will be removed in the next version!"),console.warn("[JS Framework] Vm#$logout is deprecated, please use \"require('@weex-module/user').logout(callback)\" instead
 "),this._app.requireModule("user").logout(e)}var Zn,Qn={},Yn={},er=Object.freeze({init:e,registerComponents:t,registerModules:n,registerMethods:r,prepareInstance:o,createInstance:i,refreshInstance:a,destroyInstance:s,getRoot:u,receiveTasks:c}),tr="undefined"!=typeof window?window:void 0!==global?global:"undefined"!=typeof self?self:{},nr=f(function(e){e.exports=function(e,t){function n(e){return void 0===e||null===e}function r(e){return void 0!==e&&null!==e}function o(e){return!0===e}function i(e){return!1===e}function a(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e}function s(e){return null!==e&&"object"==typeof e}function u(e){return"[object Object]"===kn.call(e)}function c(e){return"[object RegExp]"===kn.call(e)}function l(e){var t=parseFloat(e);return t>=0&&Math.floor(t)===t&&isFinite(e)}function f(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function d(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Objec
 t.create(null),r=e.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function v(e,t){return An.call(e,t)}function y(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function m(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function _(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function g(e,t){for(var n in t)e[n]=t[n];return e}function b(e){for(var t={},n=0;n<e.length;n++)e[n]&&g(t,e[n]);return t}function w(e,t,n){}function O(e,t){if(e===t)return!0;var n=s(e),r=s(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var o=Array.isArray(e),i=Array.isArray(t);if(o&&i)return e.length===t.length&&e.every(function(e,n){return O(e,t[n])});if(o||i)return!1;var a=Object.keys(e),u=Object.keys(t);return a.length===u.length&
 &a.every(function(n){return O(e[n],t[n])})}catch(e){return!1}}function E(e,t){for(var n=0;n<e.length;n++)if(O(e[n],t))return n;return-1}function x(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function C(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function k(e){if(!Wn.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function j(e,t,n){if(Vn.errorHandler)Vn.errorHandler.call(null,e,t,n);else{if(!zn||"undefined"==typeof console)throw e;console.error(e)}}function A(e){return"function"==typeof e&&/native code/.test(e.toString())}function I(e){ar.target&&sr.push(ar.target),ar.target=e}function T(){ar.target=sr.pop()}function N(e,t,n){e.__proto__=t}function P(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];C(e,i,t[i])}}function M(e,t){if(s(e)){var n;return v(e,"__ob__")&&e.__ob__ instanceof dr?n=e.__ob__
 :fr.shouldConvert&&!er()&&(Array.isArray(e)||u(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new dr(e)),t&&n&&n.vmCount++,n}}function $(e,t,n,r,o){var i=new ar,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,u=a&&a.set,c=!o&&M(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ar.target&&(i.depend(),c&&c.dep.depend(),Array.isArray(t)&&F(t)),t},set:function(t){var r=s?s.call(e):n;t===r||t!==t&&r!==r||(u?u.call(e,t):n=t,c=!o&&M(t),i.notify())}})}}function R(e,t,n){if(Array.isArray(e)&&l(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(v(e,t))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?($(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function D(e,t){if(Array.isArray(e)&&l(t))return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||v(e,t)&&(delete e[t],n&&n.dep.notify())}function F(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Arra
 y.isArray(t)&&F(t)}function L(e,t){if(!t)return e;for(var n,r,o,i=Object.keys(t),a=0;a<i.length;a++)n=i[a],r=e[n],o=t[n],v(e,n)?u(r)&&u(o)&&L(r,o):R(e,n,o);return e}function V(e,t,n){return n?e||t?function(){var r="function"==typeof t?t.call(n):t,o="function"==typeof e?e.call(n):void 0;return r?L(r,o):o}:void 0:t?e?function(){return L("function"==typeof t?t.call(this):t,"function"==typeof e?e.call(this):e)}:t:e}function U(e,t){return t?e?e.concat(t):Array.isArray(t)?t:[t]:e}function W(e,t){var n=Object.create(e||null);return t?g(n,t):n}function B(e){var t=e.props;if(t){var n,r,o,i={};if(Array.isArray(t))for(n=t.length;n--;)"string"==typeof(r=t[n])&&(o=Tn(r),i[o]={type:null});else if(u(t))for(var a in t)r=t[a],o=Tn(a),i[o]=u(r)?r:{type:r};e.props=i}}function q(e){var t=e.inject;if(Array.isArray(t))for(var n=e.inject={},r=0;r<t.length;r++)n[t[r]]=t[r]}function z(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function J(e,t,n){func
 tion r(r){var o=pr[r]||hr;u[r]=o(e[r],t[r],n,r)}"function"==typeof t&&(t=t.options),B(t),q(t),z(t);var o=t.extends;if(o&&(e=J(e,o,n)),t.mixins)for(var i=0,a=t.mixins.length;i<a;i++)e=J(e,t.mixins[i],n);var s,u={};for(s in e)r(s);for(s in t)v(e,s)||r(s);return u}function H(e,t,n,r){if("string"==typeof n){var o=e[t];if(v(o,n))return o[n];var i=Tn(n);if(v(o,i))return o[i];var a=Nn(i);if(v(o,a))return o[a];var s=o[n]||o[i]||o[a];return s}}function G(e,t,n,r){var o=t[e],i=!v(n,e),a=n[e];if(Z(Boolean,o.type)&&(i&&!v(o,"default")?a=!1:Z(String,o.type)||""!==a&&a!==Mn(e)||(a=!0)),void 0===a){a=X(r,o,e);var s=fr.shouldConvert;fr.shouldConvert=!0,M(a),fr.shouldConvert=s}return a}function X(e,t,n){if(v(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==K(t.type)?r.call(e):r}}function K(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function Z(e,t){if(!Array.is
 Array(t))return K(t)===K(e);for(var n=0,r=t.length;n<r;n++)if(K(t[n])===K(e))return!0;return!1}function Q(e){return new vr(void 0,void 0,void 0,String(e))}function Y(e){var t=new vr(e.tag,e.data,e.children,e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.isCloned=!0,t}function ee(e){for(var t=e.length,n=new Array(t),r=0;r<t;r++)n[r]=Y(e[r]);return n}function te(e){function t(){var e=arguments,n=t.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=n.slice(),o=0;o<r.length;o++)r[o].apply(null,e)}return t.fns=e,t}function ne(e,t,r,o,i){var a,s,u,c;for(a in e)s=e[a],u=t[a],c=gr(a),n(s)||(n(u)?(n(s.fns)&&(s=e[a]=te(s)),r(c.name,s,c.once,c.capture,c.passive)):s!==u&&(u.fns=s,e[a]=u));for(a in t)n(e[a])&&(c=gr(a),o(c.name,t[a],c.capture))}function re(e,t,i){function a(){i.apply(this,arguments),h(s.fns,a)}var s,u=e[t];n(u)?s=te([a]):r(u.fns)&&o(u.merged)?(s=u,s.fns.push(a)):s=te([u,a]),s.mer
 ged=!0,e[t]=s}function oe(e,t,o){var i=t.options.props;if(!n(i)){var a={},s=e.attrs,u=e.props;if(r(s)||r(u))for(var c in i){var l=Mn(c);ie(a,u,c,l,!0)||ie(a,s,c,l,!1)}return a}}function ie(e,t,n,o,i){if(r(t)){if(v(t,n))return e[n]=t[n],i||delete t[n],!0;if(v(t,o))return e[n]=t[o],i||delete t[o],!0}return!1}function ae(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function se(e){return a(e)?[Q(e)]:Array.isArray(e)?ce(e):void 0}function ue(e){return r(e)&&r(e.text)&&i(e.isComment)}function ce(e,t){var i,s,u,c=[];for(i=0;i<e.length;i++)s=e[i],n(s)||"boolean"==typeof s||(u=c[c.length-1],Array.isArray(s)?c.push.apply(c,ce(s,(t||"")+"_"+i)):a(s)?ue(u)?u.text+=String(s):""!==s&&c.push(Q(s)):ue(s)&&ue(u)?c[c.length-1]=Q(u.text+s.text):(o(e._isVList)&&r(s.tag)&&n(s.key)&&r(t)&&(s.key="__vlist"+t+"_"+i+"__"),c.push(s)));return c}function le(e,t){return e.__esModule&&e.default&&(e=e.default),s(e)?t.extend(e):e}function fe(e,t,n,r,o){var
  i=_r();return i.asyncFactory=e,i.asyncMeta={data:t,context:n,children:r,tag:o},i}function de(e,t,i){if(o(e.error)&&r(e.errorComp))return e.errorComp;if(r(e.resolved))return e.resolved;if(o(e.loading)&&r(e.loadingComp))return e.loadingComp;if(!r(e.contexts)){var a=e.contexts=[i],u=!0,c=function(){for(var e=0,t=a.length;e<t;e++)a[e].$forceUpdate()},l=x(function(n){e.resolved=le(n,t),u||c()}),f=x(function(t){r(e.errorComp)&&(e.error=!0,c())}),d=e(l,f);return s(d)&&("function"==typeof d.then?n(e.resolved)&&d.then(l,f):r(d.component)&&"function"==typeof d.component.then&&(d.component.then(l,f),r(d.error)&&(e.errorComp=le(d.error,t)),r(d.loading)&&(e.loadingComp=le(d.loading,t),0===d.delay?e.loading=!0:setTimeout(function(){n(e.resolved)&&n(e.error)&&(e.loading=!0,c())},d.delay||200)),r(d.timeout)&&setTimeout(function(){n(e.resolved)&&f(null)},d.timeout))),u=!1,e.loading?e.loadingComp:e.resolved}e.contexts.push(i)}function pe(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var n=e[t];
 if(r(n)&&r(n.componentOptions))return n}}function he(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&me(e,t)}function ve(e,t,n){n?mr.$once(e,t):mr.$on(e,t)}function ye(e,t){mr.$off(e,t)}function me(e,t,n){mr=e,ne(t,n||{},ve,ye,e)}function _e(e,t){var n={};if(!e)return n;for(var r=[],o=0,i=e.length;o<i;o++){var a=e[o];if(a.context!==t&&a.functionalContext!==t||!a.data||null==a.data.slot)r.push(a);else{var s=a.data.slot,u=n[s]||(n[s]=[]);"template"===a.tag?u.push.apply(u,a.children):u.push(a)}}return r.every(ge)||(n.default=r),n}function ge(e){return e.isComment||" "===e.text}function be(e,t){t=t||{};for(var n=0;n<e.length;n++)Array.isArray(e[n])?be(e[n],t):t[e[n].key]=e[n].fn;return t}function we(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._i
 sDestroyed=!1,e._isBeingDestroyed=!1}function Oe(e,t,n){e.$el=t,e.$options.render||(e.$options.render=_r),ke(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},e._watcher=new jr(e,r,w),n=!1,null==e.$vnode&&(e._isMounted=!0,ke(e,"mounted")),e}function Ee(e,t,n,r,o){var i=!!(o||e.$options._renderChildren||r.data.scopedSlots||e.$scopedSlots!==Un);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=o,e.$attrs=r.data&&r.data.attrs,e.$listeners=n,t&&e.$options.props){fr.shouldConvert=!1;for(var a=e._props,s=e.$options._propKeys||[],u=0;u<s.length;u++){var c=s[u];a[c]=G(c,e.$options.props,t,e)}fr.shouldConvert=!0,e.$options.propsData=t}if(n){var l=e.$options._parentListeners;e.$options._parentListeners=n,me(e,n,l)}i&&(e.$slots=_e(o,r.context),e.$forceUpdate())}function xe(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Se(e,t){if(t){if(e._directInactive=!1,xe(e))return}else if(e._directInactive)return;if(e._
 inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Se(e.$children[n]);ke(e,"activated")}}function Ce(e,t){if(!(t&&(e._directInactive=!0,xe(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)Ce(e.$children[n]);ke(e,"deactivated")}}function ke(e,t){var n=e.$options[t];if(n)for(var r=0,o=n.length;r<o;r++)try{n[r].call(e)}catch(n){j(n,e,t+" hook")}e._hasHookEvent&&e.$emit("hook:"+t)}function je(){Cr=wr.length=Or.length=0,Er={},xr=Sr=!1}function Ae(){Sr=!0;var e,t;for(wr.sort(function(e,t){return e.id-t.id}),Cr=0;Cr<wr.length;Cr++)e=wr[Cr],t=e.id,Er[t]=null,e.run();var n=Or.slice(),r=wr.slice();je(),Ne(n),Ie(r),nr&&Vn.devtools&&nr.emit("flush")}function Ie(e){for(var t=e.length;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&ke(r,"updated")}}function Te(e){e._inactive=!1,Or.push(e)}function Ne(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Se(e[t],!0)}function Pe(e){var t=e.id;if(null==Er[t]){if(Er[t]=!0,Sr){for(var n=wr.length-1;
 n>Cr&&wr[n].id>e.id;)n--;wr.splice(n+1,0,e)}else wr.push(e);xr||(xr=!0,or(Ae))}}function Me(e){Ar.clear(),$e(e,Ar)}function $e(e,t){var n,r,o=Array.isArray(e);if((o||s(e))&&Object.isExtensible(e)){if(e.__ob__){var i=e.__ob__.dep.id;if(t.has(i))return;t.add(i)}if(o)for(n=e.length;n--;)$e(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)$e(e[r[n]],t)}}function Re(e,t,n){Ir.get=function(){return this[t][n]},Ir.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Ir)}function De(e){e._watchers=[];var t=e.$options;t.props&&Fe(e,t.props),t.methods&&qe(e,t.methods),t.data?Le(e):M(e._data={},!0),t.computed&&Ue(e,t.computed),t.watch&&t.watch!==Xn&&ze(e,t.watch)}function Fe(e,t){var n=e.$options.propsData||{},r=e._props={},o=e.$options._propKeys=[],i=!e.$parent;fr.shouldConvert=i;for(var a in t)!function(i){o.push(i);var a=G(i,t,n,e);$(r,i,a),i in e||Re(e,"_props",i)}(a);fr.shouldConvert=!0}function Le(e){var t=e.$options.data;t=e._data="function"==typeof t?Ve(t,e):t||{},u(t)||(t={});for(
 var n=Object.keys(t),r=e.$options.props,o=(e.$options.methods,n.length);o--;){var i=n[o];r&&v(r,i)||S(i)||Re(e,"_data",i)}M(t,!0)}function Ve(e,t){try{return e.call(t)}catch(e){return j(e,t,"data()"),{}}}function Ue(e,t){var n=e._computedWatchers=Object.create(null);for(var r in t){var o=t[r],i="function"==typeof o?o:o.get;n[r]=new jr(e,i||w,w,Tr),r in e||We(e,r,o)}}function We(e,t,n){"function"==typeof n?(Ir.get=Be(t),Ir.set=w):(Ir.get=n.get?!1!==n.cache?Be(t):n.get:w,Ir.set=n.set?n.set:w),Object.defineProperty(e,t,Ir)}function Be(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ar.target&&t.depend(),t.value}}function qe(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?w:m(t[n],e)}function ze(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)Je(e,n,r[o]);else Je(e,n,r)}}function Je(e,t,n,r){return u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function He(e){var t=e.
 $options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function Ge(e){var t=Xe(e.$options.inject,e);t&&(fr.shouldConvert=!1,Object.keys(t).forEach(function(n){$(e,n,t[n])}),fr.shouldConvert=!0)}function Xe(e,t){if(e){for(var n=Object.create(null),r=rr?Reflect.ownKeys(e):Object.keys(e),o=0;o<r.length;o++)for(var i=r[o],a=e[i],s=t;s;){if(s._provided&&a in s._provided){n[i]=s._provided[a];break}s=s.$parent}return n}}function Ke(e,t,n,o,i){var a={},s=e.options.props;if(r(s))for(var u in s)a[u]=G(u,s,t||{});else r(n.attrs)&&Ze(a,n.attrs),r(n.props)&&Ze(a,n.props);var c=Object.create(o),l=function(e,t,n,r){return rt(c,e,t,n,r,!0)},f=e.options.render.call(null,l,{data:n,props:a,children:i,parent:o,listeners:n.on||{},injections:Xe(e.options.inject,o),slots:function(){return _e(i,o)}});return f instanceof vr&&(f.functionalContext=o,f.functionalOptions=e.options,n.slot&&((f.data||(f.data={})).slot=n.slot)),f}function Ze(e,t){for(var n in t)e[Tn(n)]=t[n]}function Qe(e,t,i,a,u){if(!
 n(e)){var c=i.$options._base;if(s(e)&&(e=c.extend(e)),"function"==typeof e){var l;if(n(e.cid)&&(l=e,void 0===(e=de(l,c,i))))return fe(l,t,i,a,u);t=t||{},_t(e),r(t.model)&&nt(e.options,t);var f=oe(t,e,u);if(o(e.options.functional))return Ke(e,f,t,i,a);var d=t.on;if(t.on=t.nativeOn,o(e.options.abstract)){var p=t.slot;t={},p&&(t.slot=p)}et(t);var h=e.options.name||u;return new vr("vue-component-"+e.cid+(h?"-"+h:""),t,void 0,void 0,void 0,i,{Ctor:e,propsData:f,listeners:d,tag:u,children:a},l)}}}function Ye(e,t,n,o){var i=e.componentOptions,a={_isComponent:!0,parent:t,propsData:i.propsData,_componentTag:i.tag,_parentVnode:e,_parentListeners:i.listeners,_renderChildren:i.children,_parentElm:n||null,_refElm:o||null},s=e.data.inlineTemplate;return r(s)&&(a.render=s.render,a.staticRenderFns=s.staticRenderFns),new i.Ctor(a)}function et(e){e.hook||(e.hook={});for(var t=0;t<Pr.length;t++){var n=Pr[t],r=e.hook[n],o=Nr[n];e.hook[n]=r?tt(o,r):o}}function tt(e,t){return function(n,r,o,i){e(n,r,o,i)
 ,t(n,r,o,i)}}function nt(e,t){var n=e.model&&e.model.prop||"value",o=e.model&&e.model.event||"input";(t.props||(t.props={}))[n]=t.model.value;var i=t.on||(t.on={});r(i[o])?i[o]=[t.model.callback].concat(i[o]):i[o]=t.model.callback}function rt(e,t,n,r,i,s){return(Array.isArray(n)||a(n))&&(i=r,r=n,n=void 0),o(s)&&(i=$r),ot(e,t,n,r,i)}function ot(e,t,n,o,i){if(r(n)&&r(n.__ob__))return _r();if(r(n)&&r(n.is)&&(t=n.is),!t)return _r();Array.isArray(o)&&"function"==typeof o[0]&&(n=n||{},n.scopedSlots={default:o[0]},o.length=0),i===$r?o=se(o):i===Mr&&(o=ae(o));var a,s;if("string"==typeof t){var u;s=Vn.getTagNamespace(t),a=Vn.isReservedTag(t)?new vr(Vn.parsePlatformTagName(t),n,o,void 0,void 0,e):r(u=H(e.$options,"components",t))?Qe(u,n,e,o,t):new vr(t,n,o,void 0,void 0,e)}else a=Qe(t,n,e,o);return r(a)?(s&&it(a,s),a):_r()}function it(e,t){if(e.ns=t,"foreignObject"!==e.tag&&r(e.children))for(var o=0,i=e.children.length;o<i;o++){var a=e.children[o];r(a.tag)&&n(a.ns)&&it(a,t)}}function at(e,t){
 var n,o,i,a,u;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),o=0,i=e.length;o<i;o++)n[o]=t(e[o],o);else if("number"==typeof e)for(n=new Array(e),o=0;o<e;o++)n[o]=t(o+1,o);else if(s(e))for(a=Object.keys(e),n=new Array(a.length),o=0,i=a.length;o<i;o++)u=a[o],n[o]=t(e[u],u,o);return r(n)&&(n._isVList=!0),n}function st(e,t,n,r){var o=this.$scopedSlots[e];if(o)return n=n||{},r&&(n=g(g({},r),n)),o(n)||t;var i=this.$slots[e];return i||t}function ut(e){return H(this.$options,"filters",e,!0)||Rn}function ct(e,t,n){var r=Vn.keyCodes[t]||n;return Array.isArray(r)?-1===r.indexOf(e):r!==e}function lt(e,t,n,r,o){if(n)if(s(n)){Array.isArray(n)&&(n=b(n));var i;for(var a in n)!function(a){if("class"===a||"style"===a||jn(a))i=e;else{var s=e.attrs&&e.attrs.type;i=r||Vn.mustUseProp(t,s,a)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}if(!(a in i)&&(i[a]=n[a],o)){(e.on||(e.on={}))["update:"+a]=function(e){n[a]=e}}}(a)}else;return e}function ft(e,t){var n=this._staticTrees[e];retur
 n n&&!t?Array.isArray(n)?ee(n):Y(n):(n=this._staticTrees[e]=this.$options.staticRenderFns[e].call(this._renderProxy),pt(n,"__static__"+e,!1),n)}function dt(e,t,n){return pt(e,"__once__"+t+(n?"_"+n:""),!0),e}function pt(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&ht(e[r],t+"_"+r,n);else ht(e,t,n)}function ht(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function vt(e,t){if(t)if(u(t)){var n=e.on=e.on?g({},e.on):{};for(var r in t){var o=n[r],i=t[r];n[r]=o?[].concat(i,o):i}}else;return e}function yt(e){e._vnode=null,e._staticTrees=null;var t=e.$vnode=e.$options._parentVnode,n=t&&t.context;e.$slots=_e(e.$options._renderChildren,n),e.$scopedSlots=Un,e._c=function(t,n,r,o){return rt(e,t,n,r,o,!1)},e.$createElement=function(t,n,r,o){return rt(e,t,n,r,o,!0)};var r=t&&t.data;$(e,"$attrs",r&&r.attrs,null,!0),$(e,"$listeners",e.$options._parentListeners,null,!0)}function mt(e,t){var n=e.$options=Object.create(e.constructor.options);n.parent=t.parent,n.propsData=
 t.propsData,n._parentVnode=t._parentVnode,n._parentListeners=t._parentListeners,n._renderChildren=t._renderChildren,n._componentTag=t._componentTag,n._parentElm=t._parentElm,n._refElm=t._refElm,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}function _t(e){var t=e.options;if(e.super){var n=_t(e.super);if(n!==e.superOptions){e.superOptions=n;var r=gt(e);r&&g(e.extendOptions,r),t=e.options=J(n,e.extendOptions),t.name&&(t.components[t.name]=e)}}return t}function gt(e){var t,n=e.options,r=e.extendOptions,o=e.sealedOptions;for(var i in n)n[i]!==o[i]&&(t||(t={}),t[i]=bt(n[i],r[i],o[i]));return t}function bt(e,t,n){if(Array.isArray(e)){var r=[];n=Array.isArray(n)?n:[n],t=Array.isArray(t)?t:[t];for(var o=0;o<e.length;o++)(t.indexOf(e[o])>=0||n.indexOf(e[o])<0)&&r.push(e[o]);return r}return e}function wt(e){this._init(e)}function Ot(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=_(arguments,1);return n.uns
 hift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}function Et(e){e.mixin=function(e){return this.options=J(this.options,e),this}}function xt(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,o=e._Ctor||(e._Ctor={});if(o[r])return o[r];var i=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=J(n.options,e),a.super=n,a.options.props&&St(a),a.options.computed&&Ct(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Fn.forEach(function(e){a[e]=n[e]}),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=g({},a.options),o[r]=a,a}}function St(e){var t=e.options.props;for(var n in t)Re(e.prototype,"_props",n)}function Ct(e){var t=e.options.computed;for(var n in t)We(e.prototype,n,t[n])}function kt(e){Fn.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&u(n)&&(n.name=n.na
 me||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function jt(e){return e&&(e.Ctor.options.name||e.tag)}function At(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!c(e)&&e.test(t)}function It(e,t,n){for(var r in e){var o=e[r];if(o){var i=jt(o.componentOptions);i&&!n(i)&&(o!==t&&Tt(o),e[r]=null)}}}function Tt(e){e&&e.componentInstance.$destroy()}function Nt(e){return new t.Element(e)}function Pt(e,n){return new t.Element(e+":"+n)}function Mt(e){return new t.TextNode(e)}function $t(e){return new t.Comment(e)}function Rt(e,t,n){if(3!==t.nodeType)e.insertBefore(t,n);else if("text"===e.type)e.setAttr("value",t.text),t.parentNode=e;else{var r=Nt("text");r.setAttr("value",t.text),e.insertBefore(r,n)}}function Dt(e,t){if(3===t.nodeType)return void e.setAttr("value","");e.removeChild(t)}function Ft(e,t){if(3!==t.nodeType)e.appendChild(t);else if(
 "text"===e.type)e.setAttr("value",t.text),t.parentNode=e;else{var n=Nt("text")
-;n.setAttr("value",t.text),e.appendChild(n)}}function Lt(e){return e.parentNode}function Vt(e){return e.nextSibling}function Ut(e){return e.type}function Wt(e,t){e.parentNode.setAttr("value",t)}function Bt(e,t,n){e.setAttr(t,n)}function qt(e,t){var n=e.data.ref;if(n){var r=e.context,o=e.componentInstance||e.elm,i=r.$refs;t?Array.isArray(i[n])?h(i[n],o):i[n]===o&&(i[n]=void 0):e.data.refInFor?Array.isArray(i[n])?i[n].indexOf(o)<0&&i[n].push(o):i[n]=[o]:i[n]=o}}function zt(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&r(e.data)===r(t.data)&&Jt(e,t)||o(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&n(t.asyncFactory.error))}function Jt(e,t){if("input"!==e.tag)return!0;var n;return(r(n=e.data)&&r(n=n.attrs)&&n.type)===(r(n=t.data)&&r(n=n.attrs)&&n.type)}function Ht(e,t,n){var o,i,a={};for(o=t;o<=n;++o)i=e[o].key,r(i)&&(a[i]=o);return a}function Gt(e,t){(e.data.directives||t.data.directives)&&Xt(e,t)}function Xt(e,t){var n,r,o,i=e===qr,a=t===qr,s=Kt(e.data
 .directives,e.context),u=Kt(t.data.directives,t.context),c=[],l=[];for(n in u)r=s[n],o=u[n],r?(o.oldValue=r.value,Qt(o,"update",t,e),o.def&&o.def.componentUpdated&&l.push(o)):(Qt(o,"bind",t,e),o.def&&o.def.inserted&&c.push(o));if(c.length){var f=function(){for(var n=0;n<c.length;n++)Qt(c[n],"inserted",t,e)};i?re(t.data.hook||(t.data.hook={}),"insert",f):f()}if(l.length&&re(t.data.hook||(t.data.hook={}),"postpatch",function(){for(var n=0;n<l.length;n++)Qt(l[n],"componentUpdated",t,e)}),!i)for(n in s)u[n]||Qt(s[n],"unbind",e,e,a)}function Kt(e,t){var n=Object.create(null);if(!e)return n;var r,o;for(r=0;r<e.length;r++)o=e[r],o.modifiers||(o.modifiers=Hr),n[Zt(o)]=o,o.def=H(t.$options,"directives",o.name,!0);return n}function Zt(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function Qt(e,t,n,r,o){var i=e.def&&e.def[t];if(i)try{i(n.elm,e,n,r,o)}catch(r){j(r,n.context,"directive "+e.name+" "+t+" hook")}}function Yt(e,t){if(e.data.attrs||t.data.attrs){var n,r,o=t.e
 lm,i=e.data.attrs||{},a=t.data.attrs||{};a.__ob__&&(a=t.data.attrs=g({},a));for(n in a)r=a[n],i[n]!==r&&o.setAttr(n,r);for(n in i)null==a[n]&&o.setAttr(n)}}function en(e,t){var n=t.elm,r=t.context,o=t.data,i=e.data;if(o.staticClass||o.class||i&&(i.staticClass||i.class)){var a=[],s=i.staticClass;s&&a.push.apply(a,s),i.class&&a.push.apply(a,i.class);var u=[],c=o.staticClass;c&&u.push.apply(u,c),o.class&&u.push.apply(u,o.class);var l=tn(a,u,r);for(var f in l)n.setStyle(f,l[f])}}function tn(e,t,n){var r=n.$options.style||{},o={};return t.forEach(function(e){g(o,r[e])}),e.forEach(function(e){var t=r[e];for(var n in t)o.hasOwnProperty(n)||(o[n]="")}),o}function nn(e,t,n,r){if(r)return void console.log("Weex do not support event in bubble phase.");if(n){var o=t,i=Vr;t=function(t){null!==(1===arguments.length?o(t):o.apply(null,arguments))&&rn(e,null,null,i)}}Vr.addEvent(e,t)}function rn(e,t,n,r){(r||Vr).removeEvent(e)}function on(e,t){if(e.data.on||t.data.on){var n=t.data.on||{},r=e.data.on
 ||{};Vr=t.elm,ne(n,r,nn,rn,t.context)}}function an(e,t){if(!t.data.staticStyle)return void sn(e,t);var n=t.elm,r=t.data.staticStyle;for(var o in r)r[o]&&n.setStyle(Qr(o),r[o]);sn(e,t)}function sn(e,t){if(e.data.style||t.data.style){var n,r,o=t.elm,i=e.data.style||{},a=t.data.style||{},s=a.__ob__;Array.isArray(a)&&(a=t.data.style=un(a)),s&&(a=t.data.style=g({},a));for(r in i)a[r]||o.setStyle(Qr(r),"");for(r in a)n=a[r],o.setStyle(Qr(r),n)}}function un(e){for(var t={},n=0;n<e.length;n++)e[n]&&g(t,e[n]);return t}function cn(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&g(t,eo(e.name||"v")),g(t,e),t}return"string"==typeof e?eo(e):void 0}}function ln(e,t){var n=t.elm;n._leaveCb&&(n._leaveCb.cancelled=!0,n._leaveCb());var r=cn(t.data.transition);if(r&&!n._enterCb){for(var o=r.enterClass,i=r.enterToClass,a=r.enterActiveClass,s=r.appearClass,u=r.appearToClass,c=r.appearActiveClass,l=r.beforeEnter,f=r.enter,d=r.afterEnter,p=r.enterCancelled,h=r.beforeAppear,v=r.appear,y=r.afterA
 ppear,m=r.appearCancelled,_=br,g=br.$vnode;g&&g.parent;)g=g.parent,_=g.context;var b=!_._isMounted||!t.isRootInsert;if(!b||v||""===v){var O=b?s:o,E=b?u:i,S=b?c:a,C=b?h||l:l,k=b&&"function"==typeof v?v:f,j=b?y||d:d,A=b?m||p:p,I=k&&(k._length||k.length)>1,T=t.context.$options.style||{},N=T[O],P=T["@TRANSITION"]&&T["@TRANSITION"][S]||{},M=dn(n,T,O,E,S,t.context),$=Object.keys(M).length>0,R=n._enterCb=x(function(){R.cancelled?A&&A(n):j&&j(n),n._enterCb=null});if(setTimeout(function(){var e=n.parentNode,r=e&&e._pending&&e._pending[t.key];if(r&&r.context===t.context&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),k&&k(n,R),$){t.context.$requireWeexModule("animation").transition(n.ref,{styles:M,duration:P.duration||0,delay:P.delay||0,timingFunction:P.timingFunction||"linear"},I?w:R)}else I||R()},16),C&&C(n),N)for(var D in N)n.setStyle(D,N[D]);$||I||R()}}}function fn(e,t){function n(){function t(){n.transition(r.ref,{styles:y,duration:m.duration||0,delay:m.delay||0,timingFunction:m.timingF
 unction||"linear"},p?w:_)}var n=e.context.$requireWeexModule("animation");_.cancelled||(e.data.show||((r.parentNode._pending||(r.parentNode._pending={}))[e.key]=e),u&&u(r),v?n.transition(r.ref,{styles:v},t):t(),c&&c(r,_),y||p||_())}var r=e.elm;r._enterCb&&(r._enterCb.cancelled=!0,r._enterCb());var o=cn(e.data.transition);if(!o)return t();if(!r._leaveCb){var i=o.leaveClass,a=o.leaveToClass,s=o.leaveActiveClass,u=o.beforeLeave,c=o.leave,l=o.afterLeave,f=o.leaveCancelled,d=o.delayLeave,p=c&&(c._length||c.length)>1,h=e.context.$options.style||{},v=h[i],y=h[a]||h[s],m=h["@TRANSITION"]&&h["@TRANSITION"][s]||{},_=r._leaveCb=x(function(){r.parentNode&&r.parentNode._pending&&(r.parentNode._pending[e.key]=null),_.cancelled?f&&f(r):(t(),l&&l(r)),r._leaveCb=null});d?d(n):n()}}function dn(e,t,n,r,o,i){var a={},s=t[n],u=t[r],c=t[o];if(s)for(var l in s)a[l]=e.style[l];if(c)for(var f in c)0!==f.indexOf("transition")&&(a[f]=c[f]);return u&&g(a,u),a}function pn(e){return e.tag?e.tag.replace(/vue\-com
 ponent\-(\d+\-)?/,""):""}function hn(e){return e.children&&1===e.children.length&&!e.children[0].tag}function vn(e){var t=String(e).match(ao);return t?Number(t[1]):e}function yn(e){if(e&&e.data){var t=e.data,n=t.staticStyle,r=t.staticClass;if(e.data.style||e.data.class||n||r){var o=Object.assign({},n,e.data.style),i=e.context.$options.style||{};[].concat(r,e.data.class).forEach(function(e){e&&i[e]&&Object.assign(o,i[e])});for(var a in o)o[a]=vn(o[a]);return o}}}function mn(e){if(e.length)return e.map(function(e){var t=pn(e),n={type:t};if(t){if(n.style=yn(e),e.data&&(n.attr=e.data.attrs,e.data.on&&(n.events=e.data.on)),"span"===t&&hn(e))return n.attr=n.attr||{},n.attr.value=e.children[0].text.trim(),n}else n.type="span",n.attr={value:(e.text||"").trim()};return e.children&&e.children.length&&(n.children=mn(e.children)),n})}function _n(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?_n(pe(t.children)):e}function gn(e){var t={},n=e.$options;for(var r in n.propsData)t[r
 ]=e[r];var o=n._parentListeners;for(var i in o)t[Tn(i)]=o[i];return t}function bn(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}function wn(e){for(;e=e.parent;)if(e.data.transition)return!0}function On(e,t){return t.key===e.key&&t.tag===e.tag}function En(e){return e.isComment&&e.asyncFactory}function xn(){}function Sn(){}function Cn(e,n){var r=new t.Comment("root");return r.hasAttribute=r.removeAttribute=function(){},n.documentElement.appendChild(r),r}var kn=Object.prototype.toString,jn=(p("slot,component",!0),p("key,ref,slot,is")),An=Object.prototype.hasOwnProperty,In=/-(\w)/g,Tn=y(function(e){return e.replace(In,function(e,t){return t?t.toUpperCase():""})}),Nn=y(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),Pn=/([^-])([A-Z])/g,Mn=y(function(e){return e.replace(Pn,"$1-$2").replace(Pn,"$1-$2").toLowerCase()}),$n=function(e,t,n){return!1},Rn=function(e){return e},Dn="data-server-rendered",Fn=["component","directive","filt
 er"],Ln=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated"],Vn={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:$n,isReservedAttr:$n,isUnknownElement:$n,getTagNamespace:w,parsePlatformTagName:Rn,mustUseProp:$n,_lifecycleHooks:Ln},Un=Object.freeze({}),Wn=/[^\w.$]/,Bn=w,qn="__proto__"in{},zn="undefined"!=typeof window,Jn=zn&&window.navigator.userAgent.toLowerCase(),Hn=(Jn&&/msie|trident/.test(Jn),Jn&&Jn.indexOf("msie 9.0"),Jn&&Jn.indexOf("edge/")>0),Gn=(Jn&&Jn.indexOf("android"),Jn&&/iphone|ipad|ipod|ios/.test(Jn)),Xn=(Jn&&/chrome\/\d+/.test(Jn),{}.watch),Kn=!1;if(zn)try{var Zn={};Object.defineProperty(Zn,"passive",{get:function(){Kn=!0}}),window.addEventListener("test-passive",null,Zn)}catch(e){}var Qn,Yn,er=function(){return void 0===Qn&&(Qn=!zn&&void 0!==tr&&"ser
 ver"===tr.process.env.VUE_ENV),Qn},nr=zn&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,rr="undefined"!=typeof Symbol&&A(Symbol)&&"undefined"!=typeof Reflect&&A(Reflect.ownKeys),or=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t<e.length;t++)e[t]()}var t,n=[],r=!1;if("undefined"!=typeof Promise&&A(Promise)){var o=Promise.resolve(),i=function(e){console.error(e)};t=function(){o.then(e).catch(i),Gn&&setTimeout(w)}}else if("undefined"==typeof MutationObserver||!A(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())t=function(){setTimeout(e,0)};else{var a=1,s=new MutationObserver(e),u=document.createTextNode(String(a));s.observe(u,{characterData:!0}),t=function(){a=(a+1)%2,u.data=String(a)}}return function(e,o){var i;if(n.push(function(){if(e)try{e.call(o)}catch(e){j(e,o,"nextTick")}else i&&i(o)}),r||(r=!0,t()),!e&&"undefined"!=typeof Promise)return new Promise(function(e,t){i=e})}}();Yn="undefined"!=typeof Set&&A(Set)?Set:function(){func
 tion e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ir=0,ar=function(){this.id=ir++,this.subs=[]};ar.prototype.addSub=function(e){this.subs.push(e)},ar.prototype.removeSub=function(e){h(this.subs,e)},ar.prototype.depend=function(){ar.target&&ar.target.addDep(this)},ar.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},ar.target=null;var sr=[],ur=Array.prototype,cr=Object.create(ur);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=ur[e];C(cr,e,function(){for(var n=arguments,r=[],o=arguments.length;o--;)r[o]=n[o];var i,a=t.apply(this,r),s=this.__ob__;switch(e){case"push":case"unshift":i=r;break;case"splice":i=r.slice(2)}return i&&s.observeArray(i),s.dep.notify(),a})});var lr=Object.getOwnPropertyNames(cr),fr={shouldConvert:!0},dr=function(e){if(this.val
 ue=e,this.dep=new ar,this.vmCount=0,C(e,"__ob__",this),Array.isArray(e)){(qn?N:P)(e,cr,lr),this.observeArray(e)}else this.walk(e)};dr.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)$(e,t[n],e[t[n]])},dr.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)M(e[t])};var pr=Vn.optionMergeStrategies;pr.data=function(e,t,n){return n?V(e,t,n):t&&"function"!=typeof t?e:V.call(this,e,t)},Ln.forEach(function(e){pr[e]=U}),Fn.forEach(function(e){pr[e+"s"]=W}),pr.watch=function(e,t){if(e===Xn&&(e=void 0),t===Xn&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var n={};g(n,e);for(var r in t){var o=n[r],i=t[r];o&&!Array.isArray(o)&&(o=[o]),n[r]=o?o.concat(i):Array.isArray(i)?i:[i]}return n},pr.props=pr.methods=pr.inject=pr.computed=function(e,t){if(!e)return t;var n=Object.create(null);return g(n,e),t&&g(n,t),n},pr.provide=V;var hr=function(e,t){return void 0===t?e:t},vr=function(e,t,n,r,o,i,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,th
 is.elm=o,this.ns=void 0,this.context=i,this.functionalContext=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},yr={child:{}};yr.child.get=function(){return this.componentInstance},Object.defineProperties(vr.prototype,yr);var mr,_r=function(e){void 0===e&&(e="");var t=new vr;return t.text=e,t.isComment=!0,t},gr=y(function(e){var t="&"===e.charAt(0);e=t?e.slice(1):e;var n="~"===e.charAt(0);e=n?e.slice(1):e;var r="!"===e.charAt(0);return e=r?e.slice(1):e,{name:e,once:n,capture:r,passive:t}}),br=null,wr=[],Or=[],Er={},xr=!1,Sr=!1,Cr=0,kr=0,jr=function(e,t,n,r){this.vm=e,e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++kr,this.active=!0,this.dirty=this.lazy,
 this.deps=[],this.newDeps=[],this.depIds=new Yn,this.newDepIds=new Yn,this.expression="","function"==typeof t?this.getter=t:(this.getter=k(t),this.getter||(this.getter=function(){})),this.value=this.lazy?void 0:this.get()};jr.prototype.get=function(){I(this);var e,t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;j(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&Me(e),T(),this.cleanupDeps()}return e},jr.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},jr.prototype.cleanupDeps=function(){for(var e=this,t=this.deps.length;t--;){var n=e.deps[t];e.newDepIds.has(n.id)||n.removeSub(e)}var r=this.depIds;this.depIds=this.newDepIds,this.newDepIds=r,this.newDepIds.clear(),r=this.deps,this.deps=this.newDeps,this.newDeps=r,this.newDeps.length=0},jr.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():Pe(this)},jr.prototype.run=function(){if(thi
 s.active){var e=this.get();if(e!==this.value||s(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){j(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},jr.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},jr.prototype.depend=function(){for(var e=this,t=this.deps.length;t--;)e.deps[t].depend()},jr.prototype.teardown=function(){var e=this;if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var t=this.deps.length;t--;)e.deps[t].removeSub(e);this.active=!1}};var Ar=new Yn,Ir={enumerable:!0,configurable:!0,get:w,set:w},Tr={lazy:!0},Nr={init:function(e,t,n,r){if(!e.componentInstance||e.componentInstance._isDestroyed){(e.componentInstance=Ye(e,br,n,r)).$mount(t?e.elm:void 0,t)}else if(e.data.keepAlive){var o=e;Nr.prepatch(o,o)}},prepatch:function(e,t){var n=t.componentOptions;Ee(t.componentInstance=e.componentInstance,n.propsData,n.listeners,t,n.children)},insert:funct
 ion(e){var t=e.context,n=e.componentInstance;n._isMounted||(n._isMounted=!0,ke(n,"mounted")),e.data.keepAlive&&(t._isMounted?Te(n):Se(n,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?Ce(t,!0):t.$destroy())}},Pr=Object.keys(Nr),Mr=1,$r=2,Rr=0;!function(e){e.prototype._init=function(e){var t=this;t._uid=Rr++,t._isVue=!0,e&&e._isComponent?mt(t,e):t.$options=J(_t(t.constructor),e||{},t),t._renderProxy=t,t._self=t,we(t),he(t),yt(t),ke(t,"beforeCreate"),Ge(t),De(t),He(t),ke(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(wt),function(e){var t={};t.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=R,e.prototype.$delete=D,e.prototype.$watch=function(e,t,n){var r=this;if(u(t))return Je(r,e,t,n);n=n||{},n.user=!0;var o=new jr(r,e,t,n);return n.immediate&&t.call(r,o.value),function(){o.teardown()}}}(wt),function(e
 ){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this,o=this;if(Array.isArray(e))for(var i=0,a=e.length;i<a;i++)r.$on(e[i],n);else(o._events[e]||(o._events[e]=[])).push(n),t.test(e)&&(o._hasHookEvent=!0);return o},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(r,arguments)}var r=this;return n.fn=t,r.$on(e,n),r},e.prototype.$off=function(e,t){var n=this,r=this;if(!arguments.length)return r._events=Object.create(null),r;if(Array.isArray(e)){for(var o=0,i=e.length;o<i;o++)n.$off(e[o],t);return r}var a=r._events[e];if(!a)return r;if(1===arguments.length)return r._events[e]=null,r;for(var s,u=a.length;u--;)if((s=a[u])===t||s.fn===t){a.splice(u,1);break}return r},e.prototype.$emit=function(e){var t=this,n=t._events[e];if(n){n=n.length>1?_(n):n;for(var r=_(arguments,1),o=0,i=n.length;o<i;o++)try{n[o].apply(t,r)}catch(n){j(n,t,'event handler for "'+e+'"')}}return t}}(wt),function(e){e.prototype._update=function(e,t){var n=this;n._isMounted&&ke(n,"beforeUpdate");var r=n
 .$el,o=n._vnode,i=br;br=n,n._vnode=e,o?n.$el=n.__patch__(o,e):(n.$el=n.__patch__(n.$el,e,t,!1,n.$options._parentElm,n.$options._refElm),n.$options._parentElm=n.$options._refElm=null),br=i,r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){var e=this;e._watcher&&e._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){ke(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||h(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),ke(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null)}}}(wt),function(e){e.prototype.$nextTick=function(e){return or(e,this)},e.prototype._render=function(){var e=this,t=e.$options,n=t.render,r=t.staticRenderFns,o=t._parentVnode;if(e._isM
 ounted)for(var i in e.$slots)e.$slots[i]=ee(e.$slots[i]);e.$scopedSlots=o&&o.data.scopedSlots||Un,r&&!e._staticTrees&&(e._staticTrees=[]),e.$vnode=o;var a;try{a=n.call(e._renderProxy,e.$createElement)}catch(t){j(t,e,"render function"),a=e._vnode}return a instanceof vr||(a=_r()),a.parent=o,a},e.prototype._o=dt,e.prototype._n=d,e.prototype._s=f,e.prototype._l=at,e.prototype._t=st,e.prototype._q=O,e.prototype._i=E,e.prototype._m=ft,e.prototype._f=ut,e.prototype._k=ct,e.prototype._b=lt,e.prototype._v=Q,e.prototype._e=_r,e.prototype._u=be,e.prototype._g=vt}(wt);var Dr=[String,RegExp,Array],Fr={name:"keep-alive",abstract:!0,props:{include:Dr,exclude:Dr},created:function(){this.cache=Object.create(null)},destroyed:function(){var e=this;for(var t in e.cache)Tt(e.cache[t])},watch:{include:function(e){It(this.cache,this._vnode,function(t){return At(e,t)})},exclude:function(e){It(this.cache,this._vnode,function(t){return!At(e,t)})}},render:function(){var e=pe(this.$slots.default),t=e&&e.compon
 entOptions;if(t){var n=jt(t);if(n&&(this.include&&!At(this.include,n)||this.exclude&&At(this.exclude,n)))return e;var r=null==e.key?t.Ctor.cid+(t.tag?"::"+t.tag:""):e.key;this.cache[r]?e.componentInstance=this.cache[r].componentInstance:this.cache[r]=e,e.data.keepAlive=!0}return e}},Lr={KeepAlive:Fr};!function(e){var t={};t.get=function(){return Vn},Object.defineProperty(e,"config",t),e.util={warn:Bn,extend:g,mergeOptions:J,defineReactive:$},e.set=R,e.delete=D,e.nextTick=or,e.options=Object.create(null),Fn.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,g(e.options.components,Lr),Ot(e),Et(e),xt(e),kt(e)}(wt),Object.defineProperty(wt.prototype,"$isServer",{get:er}),Object.defineProperty(wt.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),wt.version="2.4.2";var Vr,Ur={},Wr=Object.freeze({namespaceMap:Ur,createElement:Nt,createElementNS:Pt,createTextNode:Mt,createComment:$t,insertBefore:Rt,removeChild:Dt,appendChild:Ft,p
 arentNode:Lt,nextSibling:Vt,tagName:Ut,setTextContent:Wt,setAttribute:Bt}),Br={create:function(e,t){qt(t)},update:function(e,t){e.data.ref!==t.data.ref&&(qt(e,!0),qt(t))},destroy:function(e){qt(e,!0)}},qr=new vr("",{},[]),zr=["create","activate","update","remove","destroy"],Jr={create:Gt,update:Gt,destroy:function(e){Gt(e,qr)}},Hr=Object.create(null),Gr=[Br,Jr],Xr={create:Yt,update:Yt},Kr={create:en,update:en},Zr={create:on,update:on},Qr=y(Tn),Yr={create:an,update:sn},eo=y(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),to=(zn&&window.requestAnimationFrame&&window.requestAnimationFrame.bind(window),{create:ln,activate:ln,remove:fn}),no=[Xr,Kr,Zr,Yr,to],ro=no.concat(Gr),oo=function(e){function t(e){return new vr(I.tagName(e).toLowerCase(),{},[],void 0,e)}function i(e,t){function n(){0==--n.listeners&&s(e)}return n.listeners=t,n}function s(e){va
 r t=I.parentNode(e);r(t)&&I.removeChild(t,e)}function u(e,t,n,i,a){if(e.isRootInsert=!a,!c(e,t,n,i)){var s=e.data,u=e.children,l=e.tag;if(r(l)){e.elm=e.ns?I.createElementNS(e.ns,l):I.createElement(l,e),m(e);var f=r(s)&&o(s.appendAsTree);f||(r(s)&&y(e,t),d(n,e.elm,i)),h(e,u,t),f&&(r(s)&&y(e,t),d(n,e.elm,i))}else o(e.isComment)?(e.elm=I.createComment(e.text),d(n,e.elm,i)):(e.elm=I.createTextNode(e.text),d(n,e.elm,i))}}function c(e,t,n,i){var a=e.data;if(r(a)){var s=r(e.componentInstance)&&a.keepAlive;if(r(a=a.hook)&&r(a=a.init)&&a(e,!1,n,i),r(e.componentInstance))return l(e,t),o(s)&&f(e,t,n,i),!0}}function l(e,t){r(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,v(e)?(y(e,t),m(e)):(qt(e),t.push(e))}function f(e,t,n,o){for(var i,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,r(i=a.data)&&r(i=i.transition)){for(i=0;i<j.activate.length;++i)j.activate[i](qr,a);t.push(a);break}d(n,e.elm,o)}function d(e,t,n){r(e
 )&&(r(n)?n.parentNode===e&&I.insertBefore(e,t,n):I.appendChild(e,t))}function h(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)u(t[r],n,e.elm,null,!0);else a(e.text)&&I.appendChild(e.elm,I.createTextNode(e.text))}function v(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return r(e.tag)}function y(e,t){for(var n=0;n<j.create.length;++n)j.create[n](qr,e);C=e.data.hook,r(C)&&(r(C.create)&&C.create(qr,e),r(C.insert)&&t.push(e))}function m(e){for(var t,n=e;n;)r(t=n.context)&&r(t=t.$options._scopeId)&&I.setAttribute(e.elm,t,""),n=n.parent;r(t=br)&&t!==e.context&&r(t=t.$options._scopeId)&&I.setAttribute(e.elm,t,"")}function _(e,t,n,r,o,i){for(;r<=o;++r)u(n[r],i,e,t)}function g(e){var t,n,o=e.data;if(r(o))for(r(t=o.hook)&&r(t=t.destroy)&&t(e),t=0;t<j.destroy.length;++t)j.destroy[t](e);if(r(t=e.children))for(n=0;n<e.children.length;++n)g(e.children[n])}function b(e,t,n,o){for(;n<=o;++n){var i=t[n];r(i)&&(r(i.tag)?(w(i),g(i)):s(i.elm))}}function w(e,t){if(r(t)||r(e.data)){va
 r n,o=j.remove.length+1;for(r(t)?t.listeners+=o:t=i(e.elm,o),r(n=e.componentInstance)&&r(n=n._vnode)&&r(n.data)&&w(n,t),n=0;n<j.remove.length;++n)j.remove[n](e,t);r(n=e.data.hook)&&r(n=n.remove)?n(e,t):t()}else s(e.elm)}function O(e,t,o,i,a){for(var s,c,l,f,d=0,p=0,h=t.length-1,v=t[0],y=t[h],m=o.length-1,g=o[0],w=o[m],O=!a;d<=h&&p<=m;)n(v)?v=t[++d]:n(y)?y=t[--h]:zt(v,g)?(E(v,g,i),v=t[++d],g=o[++p]):zt(y,w)?(E(y,w,i),y=t[--h],w=o[--m]):zt(v,w)?(E(v,w,i),O&&I.insertBefore(e,v.elm,I.nextSibling(y.elm)),v=t[++d],w=o[--m]):zt(y,g)?(E(y,g,i),O&&I.insertBefore(e,y.elm,v.elm),y=t[--h],g=o[++p]):(n(s)&&(s=Ht(t,d,h)),c=r(g.key)?s[g.key]:null,n(c)?(u(g,i,e,v.elm),g=o[++p]):(l=t[c],zt(l,g)?(E(l,g,i),t[c]=void 0,O&&I.insertBefore(e,l.elm,v.elm),g=o[++p]):(u(g,i,e,v.elm),g=o[++p])));d>h?(f=n(o[m+1])?null:o[m+1].elm,_(e,f,o,p,m,i)):p>m&&b(e,t,d,h)}function E(e,t,i,a){if(e!==t){var s=t.elm=e.elm;if(o(e.isAsyncPlaceholder))return void(r(t.asyncFactory.resolved)?S(e.elm,t,i):t.isAsyncPlaceholder=!0);
 if(o(t.isStatic)&&o(e.isStatic)&&t.key===e.key&&(o(t.isCloned)||o(t.isOnce)))return void(t.componentInstance=e.componentInstance);var u,c=t.data;r(c)&&r(u=c.hook)&&r(u=u.prepatch)&&u(e,t);var l=e.children,f=t.children;if(r(c)&&v(t)){for(u=0;u<j.update.length;++u)j.update[u](e,t);r(u=c.hook)&&r(u=u.update)&&u(e,t)}n(t.text)?r(l)&&r(f)?l!==f&&O(s,l,f,i,a):r(f)?(r(e.text)&&I.setTextContent(s,""),_(s,null,f,0,f.length-1,i)):r(l)?b(s,l,0,l.length-1):r(e.text)&&I.setTextContent(s,""):e.text!==t.text&&I.setTextContent(s,t.text),r(c)&&r(u=c.hook)&&r(u=u.postpatch)&&u(e,t)}}function x(e,t,n){if(o(n)&&r(e.parent))e.parent.data.pendingInsert=t;else for(var i=0;i<t.length;++i)t[i].data.hook.insert(t[i])}function S(e,t,n){if(o(t.isComment)&&r(t.asyncFactory))return t.elm=e,t.isAsyncPlaceholder=!0,!0;t.elm=e;var i=t.tag,a=t.data,s=t.children;if(r(a)&&(r(C=a.hook)&&r(C=C.init)&&C(t,!0),r(C=t.componentInstance)))return l(t,n),!0;if(r(i)){if(r(s))if(e.hasChildNodes()){for(var u=!0,c=e.firstChild,f=0
 ;f<s.length;f++){if(!c||!S(c,s[f],n)){u=!1;break}c=c.nextSibling}if(!u||c)return!1}else h(t,s,n);if(r(a))for(var d in a)if(!T(d)){y(t,n);break}}else e.data!==t.text&&(e.data=t.text);return!0}var C,k,j={},A=e.modules,I=e.nodeOps;for

<TRUNCATED>