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 2018/04/26 12:39:56 UTC

[04/16] incubator-weex git commit: [WEEX-311] [iOS] use new layoutEngin to replace yoga

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.cpp
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.cpp b/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.cpp
new file mode 100644
index 0000000..11f8dc8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.cpp
@@ -0,0 +1,247 @@
+#include "WXCoreStyle.h"
+
+namespace WeexCore {
+
+  bool WXCoreMargin::setMargin(const WXCoreMarginEdge &edge, float margin) {
+    bool dirty = false;
+    switch (edge) {
+      case kMarginALL:
+        if (mMarginLeft != margin
+            || mMarginTop != margin
+            || mMarginRight != margin
+            || mMarginBottom != margin) {
+          mMarginLeft = margin;
+          mMarginTop = margin;
+          mMarginRight = margin;
+          mMarginBottom = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginLeft:
+        if (mMarginLeft != margin) {
+          mMarginLeft = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginTop:
+        if (mMarginTop != margin) {
+          mMarginTop = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginRight:
+        if (mMarginRight != margin) {
+          mMarginRight = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginBottom:
+        if (mMarginBottom != margin) {
+          mMarginBottom = margin;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCoreMargin::getMargin(const WXCoreMarginEdge &edge)const {
+    float margin = 0;
+    switch (edge) {
+      case kMarginLeft:
+        margin = mMarginLeft;
+        break;
+      case kMarginTop:
+        margin = mMarginTop;
+        break;
+      case kMarginRight:
+        margin = mMarginRight;
+        break;
+      case kMarginBottom:
+        margin = mMarginBottom;
+        break;
+      default:
+        break;
+    }
+    return margin;
+  }
+
+  bool WXCorePadding::setPadding(const WXCorePaddingEdge &edge, float padding) {
+    bool dirty = false;
+    switch (edge) {
+      case kPaddingALL:
+        if (mPaddingLeft != padding
+            || mPaddingTop != padding
+            || mPaddingRight != padding
+            || mPaddingBottom != padding) {
+          mPaddingLeft = padding;
+          mPaddingTop = padding;
+          mPaddingRight = padding;
+          mPaddingBottom = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingLeft:
+        if (mPaddingLeft != padding) {
+          mPaddingLeft = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingTop:
+        if (mPaddingTop != padding) {
+          mPaddingTop = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingRight:
+        if (mPaddingRight != padding) {
+          mPaddingRight = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingBottom:
+        if (mPaddingBottom != padding) {
+          mPaddingBottom = padding;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCorePadding::getPadding(const WXCorePaddingEdge &edge)const {
+    float padding = 0;
+    switch (edge) {
+      case kPaddingLeft:
+        padding = mPaddingLeft;
+        break;
+      case kPaddingTop:
+        padding = mPaddingTop;
+        break;
+      case kPaddingRight:
+        padding = mPaddingRight;
+        break;
+      case kPaddingBottom:
+        padding = mPaddingBottom;
+        break;
+      default:
+        break;
+    }
+    return padding;
+  }
+
+  bool WXCoreBorderWidth::setBorderWidth(const WXCoreBorderWidthEdge &edge, float borderWidth) {
+    bool dirty = false;
+    switch (edge) {
+      case kBorderWidthALL:
+        if (mBorderWidthLeft != borderWidth
+            || mBorderWidthTop != borderWidth
+            || mBorderWidthRight != borderWidth
+            || mBorderWidthBottom != borderWidth) {
+          mBorderWidthLeft = borderWidth;
+          mBorderWidthTop = borderWidth;
+          mBorderWidthRight = borderWidth;
+          mBorderWidthBottom = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthLeft:
+        if (mBorderWidthLeft != borderWidth) {
+          mBorderWidthLeft = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthTop:
+        if (mBorderWidthTop != borderWidth) {
+          mBorderWidthTop = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthRight:
+        if (mBorderWidthRight != borderWidth) {
+          mBorderWidthRight = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthBottom:
+        if (mBorderWidthBottom != borderWidth) {
+          mBorderWidthBottom = borderWidth;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCoreBorderWidth::getBorderWidth(const WXCoreBorderWidthEdge &edge)const {
+    float borderWidth = 0;
+    switch (edge) {
+      case kBorderWidthLeft:
+        borderWidth = mBorderWidthLeft;
+        break;
+      case kBorderWidthTop:
+        borderWidth = mBorderWidthTop;
+        break;
+      case kBorderWidthRight:
+        borderWidth = mBorderWidthRight;
+        break;
+      case kBorderWidthBottom:
+        borderWidth = mBorderWidthBottom;
+        break;
+      default:
+        break;
+    }
+    return borderWidth;
+  }
+
+  bool WXCorePosition::setPosition(const WXCorePositionEdge &edge, float position) {
+    bool dirty = false;
+    switch (edge) {
+      case kPositionEdgeLeft:
+        if (mLeft != position) {
+          mLeft = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeTop:
+        if (mTop != position) {
+          mTop = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeRight:
+        if (mRight != position) {
+          mRight = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeBottom:
+        if (mBottom != position) {
+          mBottom = position;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCorePosition::getPosition(const WXCorePositionEdge &edge) {
+    float position = 0;
+    switch (edge) {
+      case kPositionEdgeLeft:
+        position = mLeft;
+        break;
+      case kPositionEdgeTop:
+        position = mTop;
+        break;
+      case kPositionEdgeRight:
+        position = mRight;
+        break;
+      case kPositionEdgeBottom:
+        position = mBottom;
+        break;
+    }
+    return position;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.h b/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.h
new file mode 100644
index 0000000..bc7dd06
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXCoreStyle.h
@@ -0,0 +1,285 @@
+#ifdef __cplusplus
+
+#ifndef WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+#define WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+
+
+#include "WXCoreFlexEnum.h"
+#include <cmath>
+
+namespace WeexCore {
+
+  /**
+   * Margin: margin-left、margin-right、margin-top、margin-bottom
+   */
+  class WXCoreMargin {
+  private:
+    float mMarginTop;
+    float mMarginBottom;
+    float mMarginLeft;
+    float mMarginRight;
+
+  public:
+    WXCoreMargin() : mMarginTop(0),
+                     mMarginBottom(0),
+                     mMarginLeft(0),
+                     mMarginRight(0) {}
+
+    ~WXCoreMargin() {
+      mMarginTop = 0;
+      mMarginBottom = 0;
+      mMarginLeft = 0;
+      mMarginRight = 0;
+    }
+
+    bool setMargin(const WXCoreMarginEdge &edge, float margin);
+
+    float getMargin(const WXCoreMarginEdge &edge)const;
+  };
+
+
+  /**
+   * Padding:padding-left、padding-right、padding-top、padding-bottom
+   */
+  class WXCorePadding {
+  private:
+    float mPaddingTop;
+    float mPaddingBottom;
+    float mPaddingLeft;
+    float mPaddingRight;
+
+  public:
+    WXCorePadding() : mPaddingTop(0),
+                      mPaddingBottom(0),
+                      mPaddingLeft(0),
+                      mPaddingRight(0) {}
+
+    ~WXCorePadding() {
+      mPaddingTop = 0;
+      mPaddingBottom = 0;
+      mPaddingLeft = 0;
+      mPaddingRight = 0;
+    }
+
+    bool setPadding(const WXCorePaddingEdge &edge, float padding);
+
+    float getPadding(const WXCorePaddingEdge &edge)const;
+  };
+
+
+  /**
+   * BorderWidth:borderwidth-left、borderwidth-right、borderwidth-top、borderwidth-bottom
+   */
+  class WXCoreBorderWidth {
+  private:
+    float mBorderWidthTop;
+    float mBorderWidthBottom;
+    float mBorderWidthLeft;
+    float mBorderWidthRight;
+
+  public:
+    WXCoreBorderWidth() : mBorderWidthTop(0),
+                          mBorderWidthBottom(0),
+                          mBorderWidthLeft(0),
+                          mBorderWidthRight(0) {}
+
+    ~WXCoreBorderWidth() {
+      mBorderWidthTop = 0;
+      mBorderWidthBottom = 0;
+      mBorderWidthLeft = 0;
+      mBorderWidthRight = 0;
+    }
+
+    bool setBorderWidth(const WXCoreBorderWidthEdge &edge, float borderWidth);
+
+    float getBorderWidth(const WXCoreBorderWidthEdge &edge)const;
+  };
+
+
+  /**
+   * position:left、right、top、bottom
+   */
+  class WXCorePosition {
+  private:
+    float mTop;
+    float mBottom;
+    float mLeft;
+    float mRight;
+
+  public:
+    WXCorePosition() : mTop(NAN),
+                       mBottom(NAN),
+                       mLeft(NAN),
+                       mRight(NAN) {}
+
+    ~WXCorePosition() {
+      reset();
+    }
+
+    inline bool isNAN() {
+      return isnan(mTop) || isnan(mBottom) || isnan(mLeft) || isnan(mRight);
+    }
+
+    inline void reset() {
+      mTop = 0;
+      mBottom = 0;
+      mLeft = 0;
+      mRight = 0;
+    }
+
+    bool setPosition(const WXCorePositionEdge &edge, float position);
+
+    float getPosition(const WXCorePositionEdge &edge);
+  };
+
+  enum DimensionLevel{
+    CSS_STYLE = 1,
+    INSTANCE_STYLE = 2,
+    FALLBACK_STYLE = 3
+  };
+
+  /**
+   * css-style
+   */
+  class WXCoreCSSStyle {
+  public:
+    /**
+     * The direction children items are placed inside the Flexbox layout, it determines the
+     * direction of the main axis (and the cross axis, perpendicular to the main axis).
+     * The default value is {@link WXCoreFlexDirection #WXCore_Flex_Direction_Row}.
+     */
+    WXCoreFlexDirection mFlexDirection;
+
+    /**
+     * This attribute controls whether the flex container is single-line or multi-line, and the
+     * direction of the cross axis.
+     * <ul>
+     * <li>{@link WXCoreFlexWrap}: The flex container is single-line.</li>
+     * <li>{@link WXCoreFlexWrap}: The flex container is multi-line.</li>
+     * <li>{@link WXCoreFlexWrap}: The flex container is multi-line. The direction of the
+     * cross axis is opposed to the direction as the {@link WXCoreFlexWrap}</li>
+     * </ul>
+     * The default value is {@link WXCoreFlexWrap #WXCore_Wrap_NoWrap}.
+     */
+    WXCoreFlexWrap mFlexWrap;
+
+    /**
+     * This attribute controls the alignment along the main axis.
+     * The default value is {@link WXCoreJustifyContent #WXCore_Justify_Flex_Start}.
+     */
+    WXCoreJustifyContent mJustifyContent;
+
+    /**
+     * This attribute controls the alignment along the cross axis.
+     * The default value is {@link WXCoreAlignItems #WXCore_AlignItems_Stretch}.
+     */
+    WXCoreAlignItems mAlignItems;
+
+    /**
+     * This attribute controls the alignment along the cross axis.
+     * The default value is {@link WXCoreAlignSelf #WXCore_AlignSelf_Auto}.
+     */
+    WXCoreAlignSelf mAlignSelf;
+
+    WXCorePositionType mPositionType;
+
+    float mFlexGrow;
+
+    float mMinWidth;
+
+    float mMinHeight;
+
+    float mMaxWidth;
+
+    float mMaxHeight;
+
+    float mStyleWidth;
+
+    float mStyleHeight;
+
+    DimensionLevel mStyleWidthLevel;
+
+    DimensionLevel mStyleHeightLevel;
+
+    WXCoreMargin mMargin;
+
+    WXCorePadding mPadding;
+
+    WXCoreBorderWidth mBorderWidth;
+
+    WXCorePosition mStylePosition;
+
+    constexpr static float kFlexGrowDefault  = 0;
+
+    constexpr static WXCoreFlexDirection kFlexDirectionDefault= kFlexDirectionColumn;
+
+    constexpr static WXCoreFlexWrap kFlexWrapDefault = kNoWrap;
+
+    constexpr static WXCoreJustifyContent kFlexJustifyContentDefault = kJustifyFlexStart;
+
+    constexpr static WXCoreAlignItems kFlexAlignItemsDefault = kAlignItemsStretch;
+
+    constexpr static WXCoreAlignSelf kFlexAlignSelfDefault = kAlignSelfAuto;
+
+    constexpr static WXCorePositionType kWXCorePositionTypeDefault = kRelative;
+
+    WXCoreCSSStyle() : mFlexDirection(kFlexDirectionDefault),
+                       mFlexWrap(kFlexWrapDefault),
+                       mJustifyContent(kFlexJustifyContentDefault),
+                       mAlignItems(kFlexAlignItemsDefault),
+                       mAlignSelf(kFlexAlignSelfDefault),
+                       mFlexGrow(kFlexGrowDefault),
+                       mPositionType(kWXCorePositionTypeDefault),
+                       mStyleWidth(NAN), mStyleHeight(NAN),
+                       mStyleHeightLevel(FALLBACK_STYLE), mStyleWidthLevel(FALLBACK_STYLE),
+                       mMaxWidth(NAN), mMaxHeight(NAN),
+                       mMinWidth(NAN), mMinHeight(NAN) {
+
+    }
+
+    ~WXCoreCSSStyle() {
+      mFlexDirection = kFlexDirectionDefault;
+      mFlexWrap = kFlexWrapDefault;
+      mJustifyContent = kFlexJustifyContentDefault;
+      mAlignItems = kFlexAlignItemsDefault;
+      mAlignSelf = kFlexAlignSelfDefault;
+      mFlexGrow = kFlexGrowDefault;
+      mStyleWidth = NAN;
+      mStyleHeight = NAN;
+      mStyleWidthLevel = FALLBACK_STYLE;
+      mStyleHeightLevel = FALLBACK_STYLE;
+      mMaxWidth = NAN;
+      mMaxHeight = NAN;
+      mMinWidth = NAN;
+      mMinHeight = NAN;
+    }
+
+    inline float sumPaddingBorderOfEdge(const WXCoreEdge edge){
+      switch (edge) {
+        case kTop:
+          return mPadding.getPadding(kPaddingTop)
+              + mBorderWidth.getBorderWidth(kBorderWidthTop);
+        case kRight:
+          return mPadding.getPadding(kPaddingRight)
+              + mBorderWidth.getBorderWidth(kBorderWidthRight);
+        case kBottom:
+          return mPadding.getPadding(kPaddingBottom)
+              + mBorderWidth.getBorderWidth(kBorderWidthBottom);
+        case kLeft:
+          return mPadding.getPadding(kPaddingLeft)
+              + mBorderWidth.getBorderWidth(kBorderWidthLeft);
+      }
+    }
+
+    float sumMarginOfDirection(bool horizontal){
+      if(horizontal){
+        return mMargin.getMargin(kMarginLeft) + mMargin.getMargin(kMarginRight);
+      }
+      else{
+        return mMargin.getMargin(kMarginTop) + mMargin.getMargin(kMarginBottom);
+      }
+    }
+  };
+}
+#endif //WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXLayoutDefine.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXLayoutDefine.h b/ios/sdk/WeexSDK/Sources/Layout/WXLayoutDefine.h
index 7670085..93f43e9 100644
--- a/ios/sdk/WeexSDK/Sources/Layout/WXLayoutDefine.h
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXLayoutDefine.h
@@ -17,6 +17,9 @@
  * under the License.
  */
 
+#if defined __cplusplus
+extern "C" {
+#endif
 
 #define WX_LAYOUT_NAMESPACE wx_
 
@@ -53,5 +56,8 @@
 
 #import "Layout.h"
 
+#if defined __cplusplus
+};
+#endif
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.h b/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.h
new file mode 100644
index 0000000..c9b633f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.h
@@ -0,0 +1,42 @@
+/*
+ * 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 "WXScrollerComponent.h"
+#import "WXComponent+Layout.h"
+
+
+@interface WXScrollerComponent ()
+{
+//#ifndef USE_FLEX
+    css_node_t *_scrollerCSSNode;
+//#else
+    WeexCore::WXCoreLayoutNode *_flexScrollerCSSNode;
+//#endif
+}
+@end
+
+@interface WXScrollerComponent (FlexLayout)
+
+//#ifndef USE_FLEX
+@property (nonatomic, readonly, assign) css_node_t *scrollerCSSNode;
+//#else
+@property (nonatomic, readonly, assign) WeexCore::WXCoreLayoutNode *flexScrollerCSSNode;
+//#endif
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.mm b/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.mm
new file mode 100644
index 0000000..6eb8c9d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXScrollerComponent+Layout.mm
@@ -0,0 +1,53 @@
+/*
+ * 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 "WXScrollerComponent+Layout.h"
+#import "WXLog.h"
+
+@implementation WXScrollerComponent (FlexLayout)
+
+//#ifndef USE_FLEX
+- (css_node_t *)scrollerCSSNode
+{
+    return _scrollerCSSNode;
+}
+//#else
+- (WeexCore::WXCoreLayoutNode *)flexScrollerCSSNode{
+    return _flexScrollerCSSNode;
+}
+
+- (void)_insertChildCssNode:(WXComponent *)subcomponent atIndex:(NSInteger)index
+{
+    self.flexScrollerCSSNode->addChildAt(subcomponent.flexCssNode, (uint32_t) index);
+#ifdef DEBUG
+    WXLogDebug(@"flexLayout -> ref:%@,subNodeIndex:%ld,childCount:%ld",self.ref,(long)index,_flexScrollerCSSNode->getChildCount());
+#endif
+   
+//    WXLogInfo(@"FlexLayout -- P:%@ -> C:%@",self,subcomponent);
+}
+- (void)_rmChildCssNode:(WXComponent *)subcomponent
+{
+    self.flexScrollerCSSNode->removeChild(subcomponent->_flexCssNode);
+#ifdef DEBUG
+    WXLogDebug(@"flexLayout -> ref:%@ ,scrollerCSSNode->removeChild ,childRef:%@",self.ref,subcomponent.ref);
+#endif
+}
+
+//#endif
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/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
deleted file mode 100644
index 175aeb7..0000000
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ /dev/null
@@ -1,958 +0,0 @@
-/*
- * 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 "WXComponentManager.h"
-#import "WXComponent.h"
-#import "WXComponent_internal.h"
-#import "WXComponent+DataBinding.h"
-#import "WXComponentFactory.h"
-#import "WXDefine.h"
-#import "NSArray+Weex.h"
-#import "WXSDKInstance.h"
-#import "WXAssert.h"
-#import "WXUtility.h"
-#import "WXMonitor.h"
-#import "WXScrollerProtocol.h"
-#import "WXSDKManager.h"
-#import "WXSDKError.h"
-#import "WXInvocationConfig.h"
-#import "WXHandlerFactory.h"
-#import "WXValidateProtocol.h"
-#import "WXPrerenderManager.h"
-#import "WXTracingManager.h"
-#import "WXLayoutDefine.h"
-#import "WXSDKInstance_performance.h"
-#import "WXRootView.h"
-
-static NSThread *WXComponentThread;
-
-#define WXAssertComponentExist(component)  WXAssert(component, @"component not exists")
-
-@implementation WXComponentManager
-{
-    __weak WXSDKInstance *_weexInstance;
-    BOOL _isValid;
-    
-    BOOL _stopRunning;
-    NSUInteger _noTaskTickCount;
-    
-    // access only on component thread
-    NSMapTable<NSString *, WXComponent *> *_indexDict;
-    NSMutableArray<dispatch_block_t> *_uiTaskQueue;
-    NSMutableDictionary *_uiPrerenderTaskQueue;
-
-    WXComponent *_rootComponent;
-    NSMutableArray *_fixedComponents;
-    
-    css_node_t *_rootCSSNode;
-    CADisplayLink *_displayLink;
-}
-
-+ (instancetype)sharedManager
-{
-    static id _sharedInstance = nil;
-    static dispatch_once_t oncePredicate;
-    dispatch_once(&oncePredicate, ^{
-        _sharedInstance = [[self alloc] init];
-    });
-    return _sharedInstance;
-}
-
-- (instancetype)initWithWeexInstance:(id)weexInstance
-{
-    if (self = [self init]) {
-        _weexInstance = weexInstance;
-        
-        _indexDict = [NSMapTable strongToWeakObjectsMapTable];
-        _fixedComponents = [NSMutableArray wx_mutableArrayUsingWeakReferences];
-        _uiTaskQueue = [NSMutableArray array];
-        _isValid = YES;
-        [self _startDisplayLink];
-    }
-    
-    return self;
-}
-
-- (void)dealloc
-{
-    free_css_node(_rootCSSNode);
-    [NSMutableArray wx_releaseArray:_fixedComponents];
-}
-
-#pragma mark Thread Management
-
-+ (NSThread *)componentThread
-{
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        WXComponentThread = [[NSThread alloc] initWithTarget:[self sharedManager] selector:@selector(_runLoopThread) object:nil];
-        [WXComponentThread setName:WX_COMPONENT_THREAD_NAME];
-        if(WX_SYS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
-            [WXComponentThread setQualityOfService:[[NSThread mainThread] qualityOfService]];
-        } else {
-            [WXComponentThread setThreadPriority:[[NSThread mainThread] threadPriority]];
-        }
-        
-        [WXComponentThread start];
-    });
-    
-    return WXComponentThread;
-}
-
-- (void)_runLoopThread
-{
-    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
-    
-    while (!_stopRunning) {
-        @autoreleasepool {
-            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
-        }
-    }
-}
-
-+ (void)_performBlockOnComponentThread:(void (^)(void))block
-{
-    if([NSThread currentThread] == [self componentThread]){
-        block();
-    } else {
-        [self performSelector:@selector(_performBlockOnComponentThread:)
-                     onThread:WXComponentThread
-                   withObject:[block copy]
-                waitUntilDone:NO];
-    }
-}
-
-+ (void)_performBlockSyncOnComponentThread:(void (^)(void))block
-{
-    if([NSThread currentThread] == [self componentThread]){
-        block();
-    } else {
-        [self performSelector:@selector(_performBlockOnComponentThread:)
-                     onThread:WXComponentThread
-                   withObject:[block copy]
-                waitUntilDone:YES];
-    }
-}
-
-- (void)startComponentTasks
-{
-    [self _awakeDisplayLink];
-}
-
-- (void)rootViewFrameDidChange:(CGRect)frame
-{
-    WXAssertComponentThread();
-    
-    if (_rootCSSNode) {
-        [self _applyRootFrame:frame toRootCSSNode:_rootCSSNode];
-        if (!_rootComponent.styles[@"width"]) {
-            _rootComponent.cssNode->style.dimensions[CSS_WIDTH] = frame.size.width ?: CSS_UNDEFINED;
-        }
-        if (!_rootComponent.styles[@"height"]) {
-            _rootComponent.cssNode->style.dimensions[CSS_HEIGHT] = frame.size.height ?: CSS_UNDEFINED;
-        }
-        [_rootComponent setNeedsLayout];
-        [self startComponentTasks];
-    }
-}
-
-- (void)_applyRootFrame:(CGRect)rootFrame toRootCSSNode:(css_node_t *)rootCSSNode
-{
-    _rootCSSNode->style.position[CSS_LEFT] = self.weexInstance.frame.origin.x;
-    _rootCSSNode->style.position[CSS_TOP] = self.weexInstance.frame.origin.y;
-    
-    // if no instance width/height, use layout width/height, as Android's wrap_content
-    _rootCSSNode->style.dimensions[CSS_WIDTH] = self.weexInstance.frame.size.width ?: CSS_UNDEFINED;
-    _rootCSSNode->style.dimensions[CSS_HEIGHT] =  self.weexInstance.frame.size.height ?: CSS_UNDEFINED;
-}
-
-- (void)_addUITask:(void (^)(void))block
-{
-    if(!_uiPrerenderTaskQueue){
-        _uiPrerenderTaskQueue = [NSMutableDictionary new];
-    }
-    if(self.weexInstance.needPrerender){
-        NSMutableArray<dispatch_block_t> *tasks  = [_uiPrerenderTaskQueue objectForKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
-        if(!tasks){
-            tasks = [NSMutableArray new];
-        }
-        [tasks addObject:block];
-        [_uiPrerenderTaskQueue setObject:tasks forKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
-    }else{
-        [_uiTaskQueue addObject:block];
-    }
-}
-
-- (void)excutePrerenderUITask:(NSString *)url
-{
-    NSMutableArray *tasks  = [_uiPrerenderTaskQueue objectForKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
-    for (id block in tasks) {
-        [_uiTaskQueue addObject:block];
-    }
-    tasks = [NSMutableArray new];
-    [_uiPrerenderTaskQueue setObject:tasks forKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
-}
-
-#pragma mark Component Tree Building
-
-- (void)createRoot:(NSDictionary *)data
-{
-    WXAssertComponentThread();
-    WXAssertParam(data);
-    
-    _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;
-        strongSelf.weexInstance.rootView.wx_component = strongSelf->_rootComponent;
-        [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)
-{
-    WXComponentManager *manager = (__bridge WXComponentManager *)(context);
-    return [manager->_rootComponent needsLayout];
-}
-
-static css_node_t * rootNodeGetChild(void *context, int i)
-{
-    WXComponentManager *manager = (__bridge WXComponentManager *)(context);
-    if (i == 0) {
-        return manager->_rootComponent.cssNode;
-    } else if(manager->_fixedComponents.count >= i) {
-        return ((WXComponent *)((manager->_fixedComponents)[i-1])).cssNode;
-    }
-    
-    return NULL;
-}
-
-- (void)addComponent:(NSDictionary *)componentData toSupercomponent:(NSString *)superRef atIndex:(NSInteger)index appendingInTree:(BOOL)appendingInTree
-{
-    WXAssertComponentThread();
-    WXAssertParam(componentData);
-    WXAssertParam(superRef);
-    
-    WXComponent *supercomponent = [_indexDict objectForKey:superRef];
-    WXAssertComponentExist(supercomponent);
-    
-    [self _recursivelyAddComponent:componentData toSupercomponent:supercomponent atIndex:index appendingInTree:appendingInTree];
-}
-
-- (void)_recursivelyAddComponent:(NSDictionary *)componentData toSupercomponent:(WXComponent *)supercomponent atIndex:(NSInteger)index appendingInTree:(BOOL)appendingInTree
-{
-    WXComponent *component = [self _buildComponentForData:componentData supercomponent:supercomponent];
-    if (!supercomponent.subcomponents) {
-        index = 0;
-    } else {
-        index = (index == -1 ? supercomponent->_subcomponents.count : index);
-    }
-    
-    [supercomponent _insertSubcomponent:component atIndex:index];
-    // use _lazyCreateView to forbid component like cell's view creating
-    if(supercomponent && component && supercomponent->_lazyCreateView) {
-        component->_lazyCreateView = YES;
-    }
-    
-    [self recordMaximumVirtualDom:component];
-    
-    if (!component->_isTemplate) {
-        __weak typeof(self) weakSelf = self;
-        BOOL isFSCreateFinish = [self weexInstance].isJSCreateFinish;
-        [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}];
-            [weakSelf onElementChange:isFSCreateFinish];
-        }];
-    }
-    
-    NSArray *subcomponentsData = [componentData valueForKey:@"children"];
-    
-    BOOL appendTree = !appendingInTree && [component.attributes[@"append"] isEqualToString:@"tree"];
-    // if ancestor is appending tree, child should not be laid out again even it is appending tree.
-    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];
-    }
-}
-
-- (void)moveComponent:(NSString *)ref toSuper:(NSString *)superRef atIndex:(NSInteger)index
-{
-    WXAssertComponentThread();
-    WXAssertParam(ref);
-    WXAssertParam(superRef);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXComponent *newSupercomponent = [_indexDict objectForKey:superRef];
-    WXAssertComponentExist(component);
-    WXAssertComponentExist(newSupercomponent);
-    
-    if (component.supercomponent == newSupercomponent && [newSupercomponent.subcomponents indexOfObject:component] < index) {
-        // if the supercomponent moved to is the same as original supercomponent,
-        // unify it into the index after removing.
-        index--;
-    }
-    
-    [component _moveToSupercomponent:newSupercomponent atIndex:index];
-    __weak typeof(self) weakSelf = self;
-    [self _addUITask:^{
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingBegin functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-        [component moveToSuperview:newSupercomponent atIndex:index];
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
-    }];
-}
-
-- (void)removeComponent:(NSString *)ref
-{
-    WXAssertComponentThread();
-    WXAssertParam(ref);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(component);
-    
-    [component _removeFromSupercomponent];
-    
-    [_indexDict removeObjectForKey:ref];
-    
-    __weak typeof(self) weakSelf = self;
-    BOOL isFSCreateFinish = [self weexInstance].isJSCreateFinish;
-    [self _addUITask:^{
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingBegin functionName:@"removeElement" options:@{@"threadName":WXTUIThread}];
-        if (component.supercomponent) {
-            [component.supercomponent willRemoveSubview:component];
-        }
-        [component removeFromSuperview];
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingEnd functionName:@"removeElement" options:@{@"threadName":WXTUIThread}];
-        [weakSelf onElementChange:isFSCreateFinish];
-    }];
-    
-    [self _checkFixedSubcomponentToRemove:component];
-    
-}
-
-- (void)onElementChange:(BOOL)isFSCreateFinish
-{
-    if (!isFSCreateFinish) {
-        return;
-    }
-    
-    UIView *root = [self weexInstance].rootView;
-    BOOL hasEvent = TRUE;
-    if (root && [root isKindOfClass:[WXRootView class]]) {
-        WXRootView* wxRootView = (WXRootView *)root;
-        hasEvent = [wxRootView isHasEvent];
-    }
-    if (hasEvent) {
-        return;
-    }
-    double current = CACurrentMediaTime()*1000;
-    
-    double diff =  current - [self weexInstance].performance.jsCreateFinishTime;
-    if (diff > 8000) {
-        return;
-    }
-    [self weexInstance].performance.interactionTime = current - self.weexInstance.performance.renderTimeOrigin;
-}
-
-- (void)recordMaximumVirtualDom:(WXComponent*) component
-{
-    WXAssertComponentExist(component);
-    if(!component){
-        return;
-    }
-    int maxDeep =0;
-    while (component) {
-        maxDeep++;
-        component = component.supercomponent;
-    }
-    if(maxDeep > [self weexInstance].performance.maxVdomDeep)
-    {
-        [self weexInstance].performance.maxVdomDeep = maxDeep;
-    }
-   
-}
-
-- (void)_checkFixedSubcomponentToRemove:(WXComponent *)component
-{
-    for (WXComponent *subcomponent in component.subcomponents) {
-        if (subcomponent->_positionType == WXPositionTypeFixed) {
-             [self _addUITask:^{
-                 [subcomponent removeFromSuperview];
-             }];
-        }
-        
-        [self _checkFixedSubcomponentToRemove:subcomponent];
-    }
-}
-
-- (WXComponent *)componentForRef:(NSString *)ref
-{
-    WXAssertComponentThread();
-    
-    return [_indexDict objectForKey:ref];
-}
-
-- (WXComponent *)componentForRoot
-{
-    return _rootComponent;
-}
-
-- (NSUInteger)numberOfComponents
-{
-    WXAssertComponentThread();
-    
-    return _indexDict.count;
-}
-
-- (WXComponent *)_buildComponentForData:(NSDictionary *)data supercomponent:(WXComponent *)supercomponent
-{
-    NSString *ref = data[@"ref"];
-    NSString *type = data[@"type"];
-    NSDictionary *styles = data[@"style"];
-    NSDictionary *attributes = data[@"attr"];
-    NSArray *events = data[@"event"];
-    
-    if (self.weexInstance.needValidate) {
-        id<WXValidateProtocol> validateHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)];
-        if (validateHandler) {
-            WXComponentValidateResult* validateResult;
-            if ([validateHandler respondsToSelector:@selector(validateWithWXSDKInstance:component:supercomponent:)]) {
-                validateResult = [validateHandler validateWithWXSDKInstance:self.weexInstance component:type supercomponent:supercomponent];
-            }
-            if (validateResult==nil || !validateResult.isSuccess) {
-                type = validateResult.replacedComponent? validateResult.replacedComponent : @"div";
-                WXLogError(@"%@",[validateResult.error.userInfo objectForKey:@"errorMsg"]);
-            }
-        }
-    }
-    
-    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];
-    [component readyToRender];// notify redyToRender event when init
-    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
-            ||  [WXBindingOnceIdentify isEqualToString:attributeOrStyleName] // once
-            ||([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
-{
-    if([value isKindOfClass:[NSString class]]) {
-        if(!value || [@"" isEqualToString:value]) {
-            return YES;
-        }
-    }
-    return NO;
-}
-
--(void)filterStyles:(NSDictionary *)styles normalStyles:(NSMutableDictionary *)normalStyles resetStyles:(NSMutableArray *)resetStyles
-{
-    for (NSString *key in styles) {
-        id value = [styles objectForKey:key];
-        if([self isShouldReset:value]) {
-            [resetStyles addObject:key];
-        }else{
-            [normalStyles setObject:styles[key] forKey:key];
-        }
-    }
-}
-
-- (void)updateStyles:(NSDictionary *)styles forComponent:(NSString *)ref
-{
-    [self handleStyles:styles forComponent:ref isUpdateStyles:YES];
-}
-
-- (void)updatePseudoClassStyles:(NSDictionary *)styles forComponent:(NSString *)ref
-{
-    [self handleStyles:styles forComponent:ref isUpdateStyles:NO];
-}
-
-- (void)handleStyleOnMainThread:(NSDictionary*)styles forComponent:(WXComponent *)component isUpdateStyles:(BOOL)isUpdateStyles
-{
-    WXAssertParam(styles);
-    WXAssertParam(component);
-    WXAssertMainThread();
-    
-    NSMutableDictionary *normalStyles = [NSMutableDictionary new];
-    NSMutableArray *resetStyles = [NSMutableArray new];
-    [self filterStyles:styles normalStyles:normalStyles resetStyles:resetStyles];
-    [component _updateStylesOnMainThread:normalStyles resetStyles:resetStyles];
-    [component readyToRender];
-    
-    WXPerformBlockOnComponentThread(^{
-        [component _updateStylesOnComponentThread:normalStyles resetStyles:resetStyles isUpdateStyles:isUpdateStyles];
-    });
-}
-
-- (void)handleStyles:(NSDictionary *)styles forComponent:(NSString *)ref isUpdateStyles:(BOOL)isUpdateStyles
-{
-    WXAssertParam(styles);
-    WXAssertParam(ref);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(component);
-    
-    NSMutableDictionary *normalStyles = [NSMutableDictionary new];
-    NSMutableArray *resetStyles = [NSMutableArray new];
-    [self filterStyles:styles normalStyles:normalStyles resetStyles:resetStyles];
-    [component _updateStylesOnComponentThread:normalStyles resetStyles:resetStyles isUpdateStyles:isUpdateStyles];
-    [self _addUITask:^{
-        [component _updateStylesOnMainThread:normalStyles resetStyles:resetStyles];
-        [component readyToRender];
-    }];
-}
-
-- (void)updateAttributes:(NSDictionary *)attributes forComponent:(NSString *)ref
-{
-    WXAssertParam(attributes);
-    WXAssertParam(ref);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(component);
-    
-    [component _updateAttributesOnComponentThread:attributes];
-    __weak typeof(self) weakSelf = self;
-    [self _addUITask:^{
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingBegin functionName:@"updateAttrs" options:@{@"threadName":WXTUIThread}];
-        [component _updateAttributesOnMainThread:attributes];
-        [component readyToRender];
-        [WXTracingManager startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:ref className:nil name:nil phase:WXTracingEnd functionName:@"updateAttrs" options:@{@"threadName":WXTUIThread}];
-    }];
-}
-
-- (void)addEvent:(NSString *)eventName toComponent:(NSString *)ref
-{
-    WXAssertComponentThread();
-    WXAssertParam(eventName);
-    WXAssertParam(ref);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(component);
-    
-    [component _addEventOnComponentThread:eventName];
-    
-    [self _addUITask:^{
-        [component _addEventOnMainThread:eventName];
-    }];
-}
-
-- (void)removeEvent:(NSString *)eventName fromComponent:(NSString *)ref
-{
-    WXAssertComponentThread();
-    WXAssertParam(eventName);
-    WXAssertParam(ref);
-    
-    WXComponent *component = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(component);
-    
-    [component _removeEventOnComponentThread:eventName];
-    
-    [self _addUITask:^{
-        [component _removeEventOnMainThread:eventName];
-    }];
-}
-
-- (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options
-{
-    WXAssertComponentThread();
-    WXAssertParam(ref);
-    
-    WXComponent *toComponent = [_indexDict objectForKey:ref];
-    WXAssertComponentExist(toComponent);
-
-    id<WXScrollerProtocol> scrollerComponent = toComponent.ancestorScroller;
-    if (!scrollerComponent) {
-        return;
-    }
-
-    CGFloat offset = [[options objectForKey:@"offset"] floatValue];
-    BOOL animated = YES;
-    if ([options objectForKey:@"animated"]) {
-        animated = [[options objectForKey:@"animated"] boolValue];
-    }
-    
-    [self _addUITask:^{
-        [scrollerComponent scrollToComponent:toComponent withOffset:offset animated:animated];
-    }];
-}
-
-#pragma mark Life Cycle
-
-- (void)createFinish
-{
-    WXAssertComponentThread();
-    
-    WXSDKInstance *instance  = self.weexInstance;
-    [self _addUITask:^{
-        UIView *rootView = instance.rootView;
-        
-        //WX_MONITOR_INSTANCE_PERF_END(WXPTFirstScreenRender, instance);
-        WX_MONITOR_INSTANCE_PERF_END(WXPTAllRender, instance);
-        WX_MONITOR_SUCCESS(WXMTJSBridge);
-        WX_MONITOR_SUCCESS(WXMTNativeRender);
-        
-        if(instance.renderFinish){
-            [WXTracingManager startTracingWithInstanceId:instance.instanceId ref:nil className:nil name:nil phase:WXTracingInstant functionName:WXTRenderFinish options:@{@"threadName":WXTUIThread}];
-            instance.renderFinish(rootView);
-        }
-    }];
-    [instance updatePerDicAfterCreateFinish];
-}
-
-- (void)updateFinish
-{
-    WXAssertComponentThread();
-    
-    WXSDKInstance *instance = self.weexInstance;
-    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
-    
-    [self _addUITask:^{
-        if(instance.updateFinish){
-            instance.updateFinish(root.view);
-        }
-    }];
-}
-
-- (void)refreshFinish
-{
-    WXAssertComponentThread();
-    
-    WXSDKInstance *instance = self.weexInstance;
-    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
-    
-    [self _addUITask:^{
-        if(instance.refreshFinish){
-            instance.refreshFinish(root.view);
-        }
-    }];
-}
-
-- (void)unload
-{
-    WXAssertComponentThread();
-    [self invalidate];
-    [self _stopDisplayLink];
-    NSEnumerator *enumerator = [[_indexDict copy] objectEnumerator];
-    dispatch_async(dispatch_get_main_queue(), ^{
-        WXComponent *component;
-        while ((component = [enumerator nextObject])) {
-            [component _unloadViewWithReusing:NO];
-        }
-        _rootComponent = nil;
-    });
-    
-    [_indexDict removeAllObjects];
-    [_uiTaskQueue removeAllObjects];
-}
-
-- (void)invalidate
-{
-    _isValid = NO;
-}
-
-- (BOOL)isValid
-{
-    return _isValid;
-}
-
-#pragma mark Layout Batch
-
-- (void)_startDisplayLink
-{
-    WXAssertComponentThread();
-    
-    if(!_displayLink){
-        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_handleDisplayLink)];
-        [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
-    }
-}
-
-- (void)_stopDisplayLink
-{
-    WXAssertComponentThread();
-    
-    if(_displayLink){
-        [_displayLink invalidate];
-        _displayLink = nil;
-    }
-}
-
-- (void)_suspendDisplayLink
-{
-    WXAssertComponentThread();
-    
-    if(_displayLink && !_displayLink.paused) {
-        _displayLink.paused = YES;
-    }
-}
-
-- (void)_awakeDisplayLink
-{
-    WXAssertComponentThread();
-    
-    if(_displayLink && _displayLink.paused) {
-        _displayLink.paused = NO;
-    }
-}
-
-- (void)_handleDisplayLink
-{
-    WXAssertComponentThread();
-    
-    [self _layoutAndSyncUI];
-}
-
-- (void)_layoutAndSyncUI
-{
-    [self _layout];
-    if(_uiTaskQueue.count > 0){
-        [self _syncUITasks];
-        _noTaskTickCount = 0;
-    } else {
-        // suspend display link when there's no task for 1 second, in order to save CPU time.
-        _noTaskTickCount ++;
-        if (_noTaskTickCount > 60) {
-            [self _suspendDisplayLink];
-        }
-    }
-}
-
-- (void)_layout
-{
-    BOOL needsLayout = NO;
-
-    NSEnumerator *enumerator = [_indexDict objectEnumerator];
-    WXComponent *component;
-    while ((component = [enumerator nextObject])) {
-        if ([component needsLayout]) {
-            needsLayout = YES;
-            break;
-        }
-    }
-
-    if (!needsLayout) {
-        return;
-    }
-    
-    layoutNode(_rootCSSNode, _rootCSSNode->style.dimensions[CSS_WIDTH], _rootCSSNode->style.dimensions[CSS_HEIGHT], CSS_DIRECTION_INHERIT);
-    
-    if ([_rootComponent needsLayout]) {
-        if ([WXLog logLevel] >= WXLogLevelDebug) {
-            print_css_node(_rootCSSNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN);
-        }
-    }
-    
-    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
-    [_rootComponent _calculateFrameWithSuperAbsolutePosition:CGPointZero gatherDirtyComponents:dirtyComponents];
-    [self _calculateRootFrame];
-  
-    for (WXComponent *dirtyComponent in dirtyComponents) {
-        [self _addUITask:^{
-            [dirtyComponent _layoutDidFinish];
-        }];
-    }
-}
-
-- (void)_syncUITasks
-{
-    NSArray<dispatch_block_t> *blocks = _uiTaskQueue;
-    _uiTaskQueue = [NSMutableArray array];
-    dispatch_async(dispatch_get_main_queue(), ^{
-        for(dispatch_block_t block in blocks) {
-            block();
-        }
-    });
-}
-
-- (void)_initRootCSSNode
-{
-    _rootCSSNode = new_css_node();
-    
-    [self _applyRootFrame:self.weexInstance.frame toRootCSSNode:_rootCSSNode];
-    
-    _rootCSSNode->style.flex_wrap = CSS_NOWRAP;
-    _rootCSSNode->is_dirty = rootNodeIsDirty;
-    _rootCSSNode->get_child = rootNodeGetChild;
-    _rootCSSNode->context = (__bridge void *)(self);
-    _rootCSSNode->children_count = 1;
-}
-
-- (void)_calculateRootFrame
-{
-    if (!_rootCSSNode->layout.should_update) {
-        return;
-    }
-    _rootCSSNode->layout.should_update = false;
-    
-    CGRect frame = CGRectMake(WXRoundPixelValue(_rootCSSNode->layout.position[CSS_LEFT]),
-                              WXRoundPixelValue(_rootCSSNode->layout.position[CSS_TOP]),
-                              WXRoundPixelValue(_rootCSSNode->layout.dimensions[CSS_WIDTH]),
-                              WXRoundPixelValue(_rootCSSNode->layout.dimensions[CSS_HEIGHT]));
-    WXPerformBlockOnMainThread(^{
-        if(!self.weexInstance.isRootViewFrozen) {
-            self.weexInstance.rootView.frame = frame;
-        }
-    });
-    
-    resetNodeLayout(_rootCSSNode);
-}
-
-
-#pragma mark Fixed 
-
-- (void)addFixedComponent:(WXComponent *)fixComponent
-{
-    [_fixedComponents addObject:fixComponent];
-    _rootCSSNode->children_count = (int)[_fixedComponents count] + 1;
-}
-
-- (void)removeFixedComponent:(WXComponent *)fixComponent
-{
-    [_fixedComponents removeObject:fixComponent];
-    _rootCSSNode->children_count = (int)[_fixedComponents count] + 1;
-}
-
-@end
-
-void WXPerformBlockOnComponentThread(void (^block)(void))
-{
-    [WXComponentManager _performBlockOnComponentThread:block];
-}
-
-void WXPerformBlockSyncOnComponentThread(void (^block)(void))
-{
-    [WXComponentManager _performBlockSyncOnComponentThread:block];
-}