http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java
new file mode 100644
index 0000000..42ca263
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+package com.taobao.weex.ui.flat.widget;
+
+
+import android.graphics.Canvas;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import com.taobao.weex.ui.flat.FlatGUIContext;
+import java.util.LinkedList;
+import java.util.List;
+
+@RestrictTo(Scope.LIBRARY)
+public class WidgetGroup extends BaseWidget {
+
+  private List<Widget> mChildren = new LinkedList<>();
+
+  public WidgetGroup(@NonNull FlatGUIContext context) {
+    super(context);
+  }
+
+  public void replaceAll(@NonNull List<Widget> widgets) {
+    mChildren = widgets;
+    invalidate();
+  }
+
+  public List<Widget> getChildren() {
+    return mChildren;
+  }
+
+  @Override
+  public void onDraw(@NonNull Canvas canvas) {
+    for (Widget child : mChildren) {
+      child.draw(canvas);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
index caa28a6..ae0ed99 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
@@ -27,6 +27,7 @@ import static 
com.taobao.weex.common.WXJSBridgeMsgType.MODULE_TIMEOUT;
 
 import android.os.Handler;
 import android.os.Message;
+import android.support.annotation.FloatRange;
 import android.support.annotation.IntDef;
 import android.support.annotation.IntRange;
 import android.support.annotation.VisibleForTesting;
@@ -63,16 +64,16 @@ public class WXTimerModule extends WXModule implements 
Destroyable, Handler.Call
 
 
   @JSMethod(uiThread = false)
-  public void setTimeout(@IntRange(from = 1) int funcId, @IntRange(from = 0) 
int delay) {
+  public void setTimeout(@IntRange(from = 1) int funcId, @FloatRange(from = 0) 
float delay) {
     if(mWXSDKInstance != null) {
-      postOrHoldMessage(MODULE_TIMEOUT, funcId, delay, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
+      postOrHoldMessage(MODULE_TIMEOUT, funcId, (int) delay, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
     }
   }
 
   @JSMethod(uiThread = false)
-  public void setInterval(@IntRange(from = 1) int funcId, @IntRange(from = 0) 
int interval) {
+  public void setInterval(@IntRange(from = 1) int funcId, @FloatRange(from = 
0) float interval) {
     if(mWXSDKInstance != null) {
-      postOrHoldMessage(MODULE_INTERVAL, funcId, interval, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
+      postOrHoldMessage(MODULE_INTERVAL, funcId, (int) interval, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/WXBaseCircleIndicator.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXBaseCircleIndicator.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXBaseCircleIndicator.java
index 1fdba29..5983f2d 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXBaseCircleIndicator.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXBaseCircleIndicator.java
@@ -37,7 +37,6 @@ import com.taobao.weex.utils.WXViewUtils;
 public class WXBaseCircleIndicator extends FrameLayout implements 
OnPageChangeListener, WXGestureObservable {
 
   private final Paint mPaintPage = new Paint();
-  private final Paint mPaintStroke = new Paint();
   private final Paint mPaintFill = new Paint();
   private WXGesture wxGesture;
   private WXCircleViewPager mCircleViewPager;
@@ -53,38 +52,24 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
   /**
    * Fill color of unselected circle
    */
-  private int pageColor;
+  private int pageColor = Color.LTGRAY;
   /**
    * Fill color of the selected circle
    */
-  private int fillColor;
+  private int fillColor = Color.DKGRAY;
   private int realCurrentItem;
-  private OnPageChangeListener mListener;
 
 
   public WXBaseCircleIndicator(Context context) {
     super(context);
-    getAttrs(context);
     init();
   }
 
-  /**
-   * Get attribute of xml
-   */
-  private void getAttrs(Context context) {
+  private void init() {
     radius = WXViewUtils.dip2px(5);
     circlePadding = WXViewUtils.dip2px(5);
-    pageColor = Color.parseColor("#ffffff");
-    //         strokeWidth= WAViewUtils.dip2px((float)1.5);
-    //         strokeColor = Color.parseColor("#FFDDDDDD");
-    fillColor = Color.parseColor("#ffd545");
-  }
-
-  private void init() {
-    mPaintStroke.setAntiAlias(true);
-    mPaintStroke.setStyle(Style.STROKE);
-    //         mPaintStroke.setColor(strokeColor);
-    //         mPaintStroke.setStrokeWidth(strokeWidth);
+    pageColor = Color.LTGRAY;
+    fillColor = Color.DKGRAY;
 
     mPaintFill.setStyle(Style.FILL);
     mPaintFill.setAntiAlias(true);
@@ -102,21 +87,9 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
    */
   public WXBaseCircleIndicator(Context context, AttributeSet attrs) {
     super(context, attrs);
-    getAttrs(context);
     init();
   }
 
-  public void setOnPageChangeListener(OnPageChangeListener listener) {
-    mListener = listener;
-  }
-
-  /**
-   * @return the mCircleViewPager
-   */
-  public WXCircleViewPager getCircleViewPager() {
-    return mCircleViewPager;
-  }
-
   /**
    * @param mCircleViewPager the mCircleViewPager to set
    */
@@ -125,38 +98,27 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
     if (this.mCircleViewPager != null) {
       this.mCircleViewPager.addOnPageChangeListener(this);
       this.realCurrentItem = mCircleViewPager.getRealCurrentItem();
+      if (realCurrentItem < 0) {
+        realCurrentItem = 0;
+      }
     }
     requestLayout();
   }
 
   @Override
   public void onPageScrolled(int position, float positionOffset, int 
positionOffsetPixels) {
-    if (mListener != null) {
-      mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
-    }
+
   }
 
   @Override
   public void onPageSelected(int position) {
     realCurrentItem = mCircleViewPager.getRealCurrentItem();
     invalidate();
-    if (mListener != null) {
-      mListener.onPageSelected(position);
-    }
   }
 
   @Override
   public void onPageScrollStateChanged(int state) {
-    if (mListener != null) {
-      mListener.onPageScrollStateChanged(state);
-    }
-  }
 
-  /**
-   * @return the radius
-   */
-  public float getRadius() {
-    return radius;
   }
 
   /**
@@ -167,27 +129,6 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
   }
 
   /**
-   * @return the circlePadding
-   */
-  public float getCirclePadding() {
-    return circlePadding;
-  }
-
-  /**
-   * @param circlePadding the circlePadding to set
-   */
-  public void setCirclePadding(float circlePadding) {
-    this.circlePadding = circlePadding;
-  }
-
-  /**
-   * @return the fillColor
-   */
-  public int getFillColor() {
-    return fillColor;
-  }
-
-  /**
    * @param fillColor the fillColor to set
    */
   public void setFillColor(int fillColor) {
@@ -212,36 +153,9 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
    */
   public void setRealCurrentItem(int realCurrentItem) {
     this.realCurrentItem = realCurrentItem;
+    invalidate();
   }
 
-  //   /**
-  //    * @return the strokeColor
-  //    */
-  //   public int getStrokeColor() {
-  //           return strokeColor;
-  //   }
-  //
-  //   /**
-  //    * @param strokeColor the strokeColor to set
-  //    */
-  //   public void setStrokeColor(int strokeColor) {
-  //           this.strokeColor = strokeColor;
-  //   }
-  //
-  //   /**
-  //    * @return the strokeWidth
-  //    */
-  //   public float getStrokeWidth() {
-  //           return strokeWidth;
-  //   }
-  //
-  //   /**
-  //    * @param strokeWidth the strokeWidth to set
-  //    */
-  //   public void setStrokeWidth(float strokeWidth) {
-  //           this.strokeWidth = strokeWidth;
-  //   }
-
   @Override
   public void registerGestureListener(WXGesture wxGesture) {
     this.wxGesture = wxGesture;
@@ -258,29 +172,22 @@ public class WXBaseCircleIndicator extends FrameLayout 
implements OnPageChangeLi
 
   @Override
   protected void onDraw(Canvas canvas) {
-    // TODO Auto-generated method stub
     super.onDraw(canvas);
 
-    float firstX = getWidth() / 2 + getPaddingLeft() - getCount() / 2.0f * 
(radius + circlePadding);// + radius;
-    float firstY = getHeight() / 2 + getPaddingTop();// + radius;
+    float dotWidth = (circlePadding + radius) * 2;
 
-    //draw stroked circles
-    for (int i = 0; i < getCount(); i++) {
-      float dx = firstX + circlePadding * i + radius * 2 * i;
-      float dy = firstY;
-      if (mPaintStroke.getStrokeWidth() > 0) {
-        canvas.drawCircle(dx, dy, radius, mPaintStroke);
-      }
+    float firstCenterX = getWidth() / 2 - (dotWidth * (getCount() - 1) / 2);
+    float firstCenterY = getHeight() / 2 + getPaddingTop();
 
-      if (mPaintPage.getAlpha() > 0) {
+    for (int i = 0; i < getCount(); i++) {
+      float dx = firstCenterX + dotWidth * i;
+      float dy = firstCenterY;
+      if (i != realCurrentItem) {
         canvas.drawCircle(dx, dy, radius, mPaintPage);
+      } else {
+        canvas.drawCircle(dx, dy, radius, mPaintFill);
       }
     }
-
-    //Draw the filled circle
-    float dx = firstX + realCurrentItem * circlePadding + radius * 2 * 
realCurrentItem;
-    float dy = firstY;
-    canvas.drawCircle(dx, dy, radius, mPaintFill);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java
index ec39462..28c7cef 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java
@@ -20,16 +20,19 @@ package com.taobao.weex.ui.view;
 
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.view.MotionEvent;
 import android.widget.FrameLayout;
-
 import com.taobao.weex.ui.component.WXDiv;
+import com.taobao.weex.ui.flat.widget.Widget;
 import com.taobao.weex.ui.view.gesture.WXGesture;
 import com.taobao.weex.ui.view.gesture.WXGestureObservable;
+import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXViewUtils;
-
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 /**
  * FrameLayout wrapper
@@ -41,6 +44,8 @@ public class WXFrameLayout extends FrameLayout implements 
WXGestureObservable,IR
 
   private WeakReference<WXDiv> mWeakReference;
 
+  private List<Widget> mWidgets;
+
   public WXFrameLayout(Context context) {
     super(context);
   }
@@ -60,12 +65,6 @@ public class WXFrameLayout extends FrameLayout implements 
WXGestureObservable,IR
   }
 
   @Override
-  protected void onDraw(Canvas canvas) {
-    WXViewUtils.clipCanvasWithinBorderBox(this, canvas);
-    super.onDraw(canvas);
-  }
-
-  @Override
   public void holdComponent(WXDiv component) {
     mWeakReference = new WeakReference<WXDiv>(component);
   }
@@ -75,4 +74,42 @@ public class WXFrameLayout extends FrameLayout implements 
WXGestureObservable,IR
   public WXDiv getComponent() {
     return null != mWeakReference ? mWeakReference.get() : null;
   }
+
+  public void mountFlatGUI(List<Widget> widgets){
+    this.mWidgets = widgets;
+    if (mWidgets != null) {
+      setWillNotDraw(true);
+    }
+    invalidate();
+  }
+
+  public void unmountFlatGUI(){
+    mWidgets = null;
+    setWillNotDraw(false);
+    invalidate();
+  }
+
+  @Override
+  protected boolean verifyDrawable(@NonNull Drawable who) {
+    return mWidgets != null || super.verifyDrawable(who);
+  }
+
+  @Override
+  protected void dispatchDraw(Canvas canvas) {
+    try {
+      if (mWidgets != null) {
+        canvas.save();
+        canvas.translate(getPaddingLeft(), getPaddingTop());
+        for (Widget widget : mWidgets) {
+          widget.draw(canvas);
+        }
+        canvas.restore();
+      } else {
+        WXViewUtils.clipCanvasWithinBorderBox(this, canvas);
+        super.dispatchDraw(canvas);
+      }
+    }catch (Throwable e){
+      WXLogUtils.e("FlatGUI Crashed when dispatchDraw", 
WXLogUtils.getStackTrace(e));
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderCorner.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderCorner.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderCorner.java
index a396063..07ff38f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderCorner.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderCorner.java
@@ -31,13 +31,15 @@ abstract class BorderCorner {
   private final float mPreBorderWidth;
   private final float mPostBorderWidth;
   private final RectF mBorderBox;
+  protected final float mAngleBisector;
 
-  BorderCorner(float cornerRadius, float preBorderWidth, float 
postBorderWidth, @NonNull RectF
-      borderBox) {
+  BorderCorner(float cornerRadius, float preBorderWidth, float postBorderWidth,
+      @NonNull RectF borderBox, float angleBisector) {
     mCornerRadius = cornerRadius;
     mPreBorderWidth = preBorderWidth;
     mPostBorderWidth = postBorderWidth;
     mBorderBox = borderBox;
+    mAngleBisector = angleBisector;
   }
 
   /**
@@ -61,18 +63,26 @@ abstract class BorderCorner {
     return getOuterCornerRadius() > 0 && !FloatUtil.floatsEqual(0, 
getOuterCornerRadius());
   }
 
-  protected float getPreBorderWidth() {
+  protected final float getPreBorderWidth() {
     return mPreBorderWidth;
   }
 
-  protected float getPostBorderWidth() {
+  protected final float getPostBorderWidth() {
     return mPostBorderWidth;
   }
 
-  protected float getOuterCornerRadius() {
+  protected final float getOuterCornerRadius() {
     return mCornerRadius;
   }
 
+  protected final float getAngleBisectorDegree(){
+    return mAngleBisector;
+  }
+
+  protected final RectF getBorderBox() {
+    return mBorderBox;
+  }
+
   /**
    * Get the staring point of the corner.
    * @return the starting point of the corner.
@@ -88,12 +98,6 @@ abstract class BorderCorner {
     return lineStart;
   }
 
-  @NonNull
-  abstract protected PointF getRoundCornerStart();
-
-  @NonNull
-  abstract protected PointF getSharpCornerVertex();
-
   /**
    * Get the ending point of the corner.
    * @return the ending point of the corner.
@@ -110,9 +114,13 @@ abstract class BorderCorner {
   }
 
   @NonNull
-  abstract protected PointF getRoundCornerEnd();
+  abstract protected PointF getRoundCornerStart();
+
+  @NonNull
+  abstract protected PointF getSharpCornerVertex();
 
-  abstract protected float getAngleBisectorDegree();
+  @NonNull
+  abstract protected PointF getRoundCornerEnd();
 
   @NonNull
   abstract protected PointF getSharpCornerStart();
@@ -126,7 +134,4 @@ abstract class BorderCorner {
   @NonNull
   abstract protected RectF getOvalIfInnerCornerNotExist();
 
-  protected RectF getBorderBox() {
-    return mBorderBox;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderUtil.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderUtil.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderUtil.java
index 4ce218e..b768eb5 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderUtil.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BorderUtil.java
@@ -78,30 +78,4 @@ class BorderUtil {
       }
     }
   }
-
-  static boolean areEdgesSame(float... numbers) {
-    if (numbers != null && numbers.length > 0) {
-      float init = numbers[0];
-      for (float number : numbers) {
-        if (number != init) {
-          return false;
-        }
-      }
-      return true;
-    }
-    return false;
-  }
-
-  static boolean areEdgesSame(int... numbers) {
-    if (numbers != null && numbers.length > 0) {
-      int init = numbers[0];
-      for (int number : numbers) {
-        if (number != init) {
-          return false;
-        }
-      }
-      return true;
-    }
-    return false;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomLeftCorner.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomLeftCorner.java
 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomLeftCorner.java
index cf24477..3c01a76 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomLeftCorner.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomLeftCorner.java
@@ -25,12 +25,7 @@ import android.support.annotation.NonNull;
 class BottomLeftCorner extends BorderCorner {
 
   BottomLeftCorner(float cornerRadius, float preBorderWidth, float 
postBorderWidth, @NonNull RectF borderBox) {
-    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox);
-  }
-
-  @Override
-  protected float getAngleBisectorDegree() {
-    return 135;
+    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox, 135);
   }
 
   @NonNull

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomRightCorner.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomRightCorner.java
 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomRightCorner.java
index de444c1..2ed50a4 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomRightCorner.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/BottomRightCorner.java
@@ -25,12 +25,7 @@ import android.support.annotation.NonNull;
 class BottomRightCorner extends BorderCorner {
 
   BottomRightCorner(float cornerRadius, float preBorderWidth, float 
postBorderWidth, @NonNull RectF borderBox) {
-    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox);
-  }
-
-  @Override
-  protected float getAngleBisectorDegree() {
-    return 45;
+    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox, 45);
   }
 
   @NonNull

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopLeftCorner.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopLeftCorner.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopLeftCorner.java
index ce63c4b..e83706f 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopLeftCorner.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopLeftCorner.java
@@ -25,12 +25,7 @@ import android.support.annotation.NonNull;
 class TopLeftCorner extends BorderCorner {
 
   TopLeftCorner(float cornerRadius, float preBorderWidth, float 
postBorderWidth, @NonNull RectF borderBox) {
-    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox);
-  }
-
-  @Override
-  protected float getAngleBisectorDegree() {
-    return 225;
+    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox, 225);
   }
 
   @NonNull

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopRightCorner.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopRightCorner.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopRightCorner.java
index 77a513f..0ea4377 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopRightCorner.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/view/border/TopRightCorner.java
@@ -25,12 +25,7 @@ import android.support.annotation.NonNull;
 class TopRightCorner extends BorderCorner {
 
   TopRightCorner(float cornerRadius, float preBorderWidth, float 
postBorderWidth, @NonNull RectF borderBox) {
-    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox);
-  }
-
-  @Override
-  protected float getAngleBisectorDegree() {
-    return 315;
+    super(cornerRadius, preBorderWidth, postBorderWidth, borderBox, 315);
   }
 
   @NonNull

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/FunctionParser.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/utils/FunctionParser.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/FunctionParser.java
index e138213..ba9103e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/FunctionParser.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/FunctionParser.java
@@ -227,12 +227,6 @@ public class FunctionParser<K, V> {
       return true;
     }
 
-    private void reset() {
-      pointer = 0;
-      value = null;
-      current = null;
-    }
-
     private boolean isCharacterOrDigit(char letter) {
       return (ZERO <= letter && letter <= NINE) || (A_LOWER <= letter && 
letter <= Z_LOWER) ||
               (A_UPPER <= letter && letter <= Z_UPPER);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/LogLevel.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/LogLevel.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/LogLevel.java
index 95dfd8a..0e10fa1 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/LogLevel.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/LogLevel.java
@@ -24,8 +24,8 @@ import android.util.Log;
  * Created by lixinke on 16/5/11.
  */
 public enum LogLevel {
-  ERROR("error", 0, Log.ERROR), WARN("warn", 1,Log.WARN), INFO("info", 
2,Log.INFO),
-  DEBUG("debug", 3,Log.DEBUG), VERBOSE("verbose", 4, Log.VERBOSE), 
ALL("debug", 5,Log.DEBUG),OFF("off",6,Log.DEBUG);
+  WTF("wtf", 0, Log.ASSERT), ERROR("error", 1, Log.ERROR), WARN("warn", 
2,Log.WARN), INFO("info", 3,Log.INFO),
+  DEBUG("debug", 4,Log.DEBUG), VERBOSE("verbose", 5, Log.VERBOSE), 
ALL("debug", 6,Log.DEBUG),OFF("off",7,Log.DEBUG),;
   String name;
   int value;
   int priority;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/OsVersion.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/OsVersion.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/OsVersion.java
index ef2f0c9..7c53095 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/OsVersion.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/OsVersion.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package com.taobao.weex.util;
+package com.taobao.weex.utils;
 
 /**
  * Android OS version utilities.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/Trace.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/Trace.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/Trace.java
index 7506804..cfe307e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/Trace.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/Trace.java
@@ -21,8 +21,6 @@ package com.taobao.weex.utils;
 import android.annotation.TargetApi;
 import android.os.Build;
 
-import com.taobao.weex.util.OsVersion;
-
 /**
  * Hepler class for systrace.
  *
@@ -82,7 +80,7 @@ public class Trace {
 
   /**
    * Writes a trace message to indicate that a given section of code has ended.
-   * This call must be preceeded by a corresponding call to {@link 
#beginSection()}
+   * This call must be preceeded by a corresponding call to {@link 
#beginSection(String)}
    * on the same thread.
    */
   public static void endSection() {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
index 43246ea..4f1b818 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
@@ -105,6 +105,10 @@ public class WXLogUtils {
     d(tag,new String(msg));
   }
 
+  public static void wtf(String msg){
+    wtf(WEEX_TAG, msg);
+  }
+
   public static void d(String tag, String msg) {
     if (WXEnvironment.isApkDebugable() && !TextUtils.isEmpty(msg) && 
WXEnvironment.sLogLevel.compare(LogLevel.DEBUG) >= 0) {
       Log.d(tag, msg);
@@ -170,6 +174,10 @@ public class WXLogUtils {
     log(tag, msg,LogLevel.ERROR);
   }
 
+  public static void wtf(String tag, String msg){
+    log(tag, msg, LogLevel.WTF);
+  }
+
   /**
    * 'p' for 'Performance', use {@link #WEEX_PERF_TAG}
    * @param msg
@@ -208,6 +216,12 @@ public class WXLogUtils {
     }
   }
 
+  public static void wtf(String prefix, Throwable e){
+    if (WXEnvironment.isApkDebugable()) {
+      wtf(prefix + getStackTrace(e));
+    }
+  }
+
   /**
    * 'p' for 'Performance', use {@link #WEEX_PERF_TAG}
    */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/main/java/com/taobao/weex/utils/WXViewUtils.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXViewUtils.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/WXViewUtils.java
index fb9ab8b..7d11d5a 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXViewUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXViewUtils.java
@@ -40,6 +40,8 @@ import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.common.WXRuntimeException;
+import com.taobao.weex.ui.flat.widget.Widget;
+import com.taobao.weex.ui.flat.widget.WidgetGroup;
 import com.taobao.weex.ui.view.border.BorderDrawable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -389,6 +391,22 @@ public class WXViewUtils {
     }
   }
 
+  public static void clipCanvasWithinBorderBox(Widget widget, Canvas canvas) {
+    BorderDrawable borderDrawable;
+    if (clipCanvasDueToAndroidVersion(canvas) &&
+        clipCanvasIfAnimationExist() &&
+        (borderDrawable=widget.getBackgroundAndBorder())!=null ) {
+      if (borderDrawable.isRounded() && 
clipCanvasIfBackgroundImageExist(widget, borderDrawable)) {
+          Path path = borderDrawable.getContentPath(
+              new RectF(0, 0, widget.getBorderBox().width(), 
widget.getBorderBox().height()));
+          canvas.clipPath(path);
+      }
+      else {
+        canvas.clipRect(widget.getBorderBox());
+      }
+    }
+  }
+
   /**
    * According to 
https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
    API 18 or higher supports clipPath to canvas based on hardware acceleration.
@@ -436,4 +454,17 @@ public class WXViewUtils {
     }
     return true;
   }
+
+  private static boolean clipCanvasIfBackgroundImageExist(@NonNull Widget 
widget,
+      @NonNull BorderDrawable borderDrawable) {
+    if (widget instanceof WidgetGroup) {
+      for (Widget child : ((WidgetGroup) widget).getChildren()) {
+        if (child.getBackgroundAndBorder().hasImage() &&
+            Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/test/java/com/taobao/weex/ui/component/WXDivTest.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/test/java/com/taobao/weex/ui/component/WXDivTest.java 
b/android/sdk/src/test/java/com/taobao/weex/ui/component/WXDivTest.java
index 53b52c3..480d5a6 100644
--- a/android/sdk/src/test/java/com/taobao/weex/ui/component/WXDivTest.java
+++ b/android/sdk/src/test/java/com/taobao/weex/ui/component/WXDivTest.java
@@ -18,6 +18,8 @@
  */
 package com.taobao.weex.ui.component;
 
+import static org.junit.Assert.assertEquals;
+
 import com.taobao.weappplus_sdk.BuildConfig;
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.WXSDKInstanceTest;
@@ -25,21 +27,15 @@ import com.taobao.weex.dom.TestDomObject;
 import com.taobao.weex.dom.WXDomObject;
 import com.taobao.weex.dom.WXEvent;
 import com.taobao.weex.dom.flex.Spacing;
-
+import com.taobao.weex.ui.flat.FlatGUIContext;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import static org.junit.Assert.*;
-
 /**
  * Created by gulin on 16/2/24.
  */
@@ -65,6 +61,7 @@ public class WXDivTest {
     public void setUp() throws Exception {
         WXSDKInstance instance = Mockito.mock(WXSDKInstance.class);
         
Mockito.when(instance.getContext()).thenReturn(RuntimeEnvironment.application);
+        Mockito.when(instance.getFlatUIContext()).thenReturn(new 
FlatGUIContext());
 
         WXDomObject divDom = new WXDomObject();
         WXDomObject spy = Mockito.spy(divDom);
@@ -80,6 +77,7 @@ public class WXDivTest {
     public void testAddChild(){
         WXSDKInstance instance = Mockito.mock(WXSDKInstance.class);
         
Mockito.when(instance.getContext()).thenReturn(RuntimeEnvironment.application);
+        Mockito.when(instance.getFlatUIContext()).thenReturn(new 
FlatGUIContext());
 
         WXDomObject testDom = Mockito.mock(WXDomObject.class);
         Mockito.when(testDom.getPadding()).thenReturn(new Spacing());

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/test/java/com/taobao/weex/ui/component/WXTextTest.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/test/java/com/taobao/weex/ui/component/WXTextTest.java 
b/android/sdk/src/test/java/com/taobao/weex/ui/component/WXTextTest.java
index 0181457..3b6700f 100644
--- a/android/sdk/src/test/java/com/taobao/weex/ui/component/WXTextTest.java
+++ b/android/sdk/src/test/java/com/taobao/weex/ui/component/WXTextTest.java
@@ -18,6 +18,11 @@
  */
 package com.taobao.weex.ui.component;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import com.taobao.weappplus_sdk.BuildConfig;
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.WXSDKInstance;
@@ -27,7 +32,9 @@ import com.taobao.weex.dom.WXDomObject;
 import com.taobao.weex.dom.WXTextDomObject;
 import com.taobao.weex.dom.flex.Spacing;
 import com.taobao.weex.ui.SimpleComponentHolder;
-
+import com.taobao.weex.ui.flat.FlatGUIContext;
+import java.util.HashMap;
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,14 +43,6 @@ import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 /**
  * Created by gulin on 16/2/4.
  */
@@ -60,6 +59,7 @@ public class WXTextTest {
         WXEnvironment.sApplication = RuntimeEnvironment.application;
         WXSDKInstance instance = Mockito.mock(WXSDKInstance.class);
         
Mockito.when(instance.getContext()).thenReturn(RuntimeEnvironment.application);
+        Mockito.when(instance.getFlatUIContext()).thenReturn(new 
FlatGUIContext());
 
         mParentDomObj = Mockito.spy(new WXDomObject());
         Mockito.when(mParentDomObj.getPadding()).thenReturn(new Spacing());

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/android/sdk/src/test/java/com/taobao/weex/ui/module/WXTimerModuleTest.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/test/java/com/taobao/weex/ui/module/WXTimerModuleTest.java 
b/android/sdk/src/test/java/com/taobao/weex/ui/module/WXTimerModuleTest.java
index 7fe508c..f4331b0 100644
--- a/android/sdk/src/test/java/com/taobao/weex/ui/module/WXTimerModuleTest.java
+++ b/android/sdk/src/test/java/com/taobao/weex/ui/module/WXTimerModuleTest.java
@@ -18,6 +18,8 @@
  */
 package com.taobao.weex.ui.module;
 
+import static android.R.attr.end;
+import static android.R.attr.start;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Matchers.any;
@@ -61,6 +63,7 @@ public class WXTimerModuleTest {
   public final static int DELAY = 50;
   public final static int IMMEDIATELY = 0;
   public final static int INVALID_DELAY = -50;
+  public final static float FLOAT_DELAY = 20.6f;
 
   @Rule
   public PowerMockRule rule = new PowerMockRule();
@@ -84,7 +87,26 @@ public class WXTimerModuleTest {
   @Test
   public void testSetTimeoutDelay() throws Exception {
     module.setTimeout(VALID_FUNC_ID, DELAY);
-    mLooper.idle(DELAY);
+    long start, end, duration;
+    start = mLooper.getScheduler().getCurrentTime();
+    mLooper.runOneTask();
+    end = mLooper.getScheduler().getCurrentTime();
+    duration = end - start;
+
+    assertThat(duration, is((long) DELAY));
+    Mockito.verify(module, times(1)).handleMessage(any(Message.class));
+  }
+
+  @Test
+  public void testSetTimeoutDelay2() throws Exception {
+    module.setTimeout(VALID_FUNC_ID, FLOAT_DELAY);
+    long start, end, duration;
+    start = mLooper.getScheduler().getCurrentTime();
+    mLooper.runOneTask();
+    end = mLooper.getScheduler().getCurrentTime();
+    duration = end - start;
+
+    assertThat(duration, is((long) FLOAT_DELAY));
     Mockito.verify(module, times(1)).handleMessage(any(Message.class));
   }
 
@@ -164,6 +186,23 @@ public class WXTimerModuleTest {
   }
 
   @Test
+  public void testSetIntervalDelay2() {
+    long start, end, duration;
+    module.setInterval(VALID_FUNC_ID, FLOAT_DELAY);
+
+    start = mLooper.getScheduler().getCurrentTime();
+    mLooper.runOneTask();
+    end = mLooper.getScheduler().getCurrentTime();
+    duration = end - start;
+
+    assertThat(duration, is((long) FLOAT_DELAY));
+
+    mLooper.runOneTask();
+    mLooper.runOneTask();
+    Mockito.verify(module, times(3)).handleMessage(any(Message.class));
+  }
+
+  @Test
   public void testClearTimeout() throws Exception {
     module.setTimeout(VALID_FUNC_ID, DELAY);
     module.clearTimeout(VALID_FUNC_ID);
@@ -180,7 +219,7 @@ public class WXTimerModuleTest {
   }
 
   @Test
-  public void setClearTimeout2(){
+  public void testClearTimeout2(){
     module.setTimeout(NO_CACHING_FUNC_ID, DELAY);
     module.clearTimeout(NO_CACHING_FUNC_ID);
     mLooper.idle(DELAY, TimeUnit.MILLISECONDS);
@@ -188,7 +227,7 @@ public class WXTimerModuleTest {
   }
 
   @Test
-  public void setClearInterval2(){
+  public void testClearInterval2(){
     module.setInterval(NO_CACHING_FUNC_ID, DELAY);
     module.clearInterval(NO_CACHING_FUNC_ID);
     mLooper.idle(DELAY, TimeUnit.MILLISECONDS);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/dangerfile-android.js
----------------------------------------------------------------------
diff --git a/dangerfile-android.js b/dangerfile-android.js
new file mode 100644
index 0000000..2e81f0a
--- /dev/null
+++ b/dangerfile-android.js
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+// Removed import
+import fs from "fs";
+import path from 'path';
+import GitHubApi from 'github';
+import parseDiff from 'parse-diff';
+import shell from "shelljs";
+
+const type_unknown = 0;
+const type_ios_sdk = 1;
+const type_android_sdk = 2;
+const type_ios_test = 3;
+const type_android_test = 4;
+const type_jsfm = 5;
+const type_jsfm_test = 6;
+const type_doc = 7;
+const type_ui_test = 8;
+
+const getFileType = file => {
+  if (file.match(/WeexSDK\/Sources\/.+\.(m|h|mm)/)) {
+    return type_ios_sdk;
+  } else if (file.match(/WeexSDKTests\//)) {
+    return type_ios_test;
+  } else if (file.match(/android\/sdk\/src\/test\/.+\.java/)) {
+    return type_android_test;
+  } else if (file.match(/android\/sdk\/src\/main\/java\/.+\.java/)) {
+    return type_android_sdk;
+  } else if (
+    file.match(/html5\/(shared|frameworks|render|runtime|services)\/.+\.js/)
+  ) {
+    return type_jsfm;
+  } else if (file.match(/html5\/test\/.+\.js/)) {
+    return type_jsfm_test;
+  } else if (file.match(/doc\/\.+\.md/)) {
+    return type_doc;
+  } else if(file.match(/test\/scripts\/.+\.js/) || 
file.match(/test\/pages\/.+\.vue/)){
+    return type_ui_test
+  }else{
+    return type_unknown
+  }
+}
+
+function checkAndroidFile(file){
+  var type = getFileType(file);
+  return type == type_android_test || type == type_android_sdk || type == 
type_jsfm;
+}
+
+var hasAndroidFile = false;
+
+if (!hasAndroidFile && danger.git.created_files) {
+  danger.git.created_files.some(file => {
+    var f = checkAndroidFile(file);
+    if(f){
+      hasAndroidFile =f;
+    }
+    return f;
+  });
+}
+if (!hasAndroidFile && danger.git.modified_files) {
+  danger.git.modified_files.some(file => {
+    var f = checkAndroidFile(file);
+    if(f){
+      hasAndroidFile =f;
+    }
+    return f;
+  });
+}
+if (!hasAndroidFile && danger.git.deleted_files) {
+  danger.git.deleted_files.some(file => {
+    var f = checkAndroidFile(file);
+    if(f){
+      hasAndroidFile =f;
+    }
+    return f;
+  });
+}
+
+if(hasAndroidFile){
+  var runTestCmd='source ~/.bash_profile; '
+    +'cd android; '
+    +'./gradlew clean assembleDebug :weex_sdk:testDebugUnitTest --info 
-PdisableCov=true '
+    +'-Dorg.gradle.daemon=true -Dorg.gradle.parallel=true 
-Dorg.gradle.jvmargs="-Xmx512m '
+    +'-XX:+HeapDumpOnOutOfMemoryError" -Dfile.encoding=UTF-8 '
+  var runSuccess = shell.exec(runTestCmd,{ async: false, timeout: 8 * 60 * 
1000 }).code == 0;
+  if(!runSuccess){
+    fail("android platform run unit test failed!");
+  }
+}else{
+  message('has no android file changed,skip test!');
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/dangerfile-ios.js
----------------------------------------------------------------------
diff --git a/dangerfile-ios.js b/dangerfile-ios.js
new file mode 100644
index 0000000..079e516
--- /dev/null
+++ b/dangerfile-ios.js
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+// Removed import
+import fs from "fs";
+import path from 'path';
+import GitHubApi from 'github';
+import parseDiff from 'parse-diff';
+import shell from "shelljs";
+
+const type_unknown = 0;
+const type_ios_sdk = 1;
+const type_android_sdk = 2;
+const type_ios_test = 3;
+const type_android_test = 4;
+const type_jsfm = 5;
+const type_jsfm_test = 6;
+const type_doc = 7;
+const type_ui_test = 8;
+
+const getFileType = file => {
+  if (file.match(/WeexSDK\/Sources\/.+\.(m|h|mm)/)) {
+    return type_ios_sdk;
+  } else if (file.match(/WeexSDKTests\//)) {
+    return type_ios_test;
+  } else if (file.match(/android\/sdk\/src\/test\/.+\.java/)) {
+    return type_android_test;
+  } else if (file.match(/android\/sdk\/src\/main\/java\/.+\.java/)) {
+    return type_android_sdk;
+  } else if (
+    file.match(/html5\/(shared|frameworks|render|runtime|services)\/.+\.js/)
+  ) {
+    return type_jsfm;
+  } else if (file.match(/html5\/test\/.+\.js/)) {
+    return type_jsfm_test;
+  } else if (file.match(/doc\/\.+\.md/)) {
+    return type_doc;
+  } else if(file.match(/test\/scripts\/.+\.js/) || 
file.match(/test\/pages\/.+\.vue/)){
+    return type_ui_test
+  }else{
+    return type_unknown
+  }
+}
+
+function checkIosFile(file){
+  var type = getFileType(file);
+  return type == type_ios_sdk || type == type_ios_test || type == type_jsfm;
+}
+
+var hasIosFile = false;
+
+if (!hasIosFile && danger.git.created_files) {
+  danger.git.created_files.some(file => {
+    var f = checkIosFile(file);
+    if(f){
+      hasIosFile =f;
+    }
+    return f;
+  });
+}
+if (!hasIosFile && danger.git.modified_files) {
+  danger.git.modified_files.some(file => {
+    var f = checkIosFile(file);
+    if(f){
+      hasIosFile =f;
+    }
+    return f;
+  });
+}
+if (!hasIosFile && danger.git.deleted_files) {
+  danger.git.deleted_files.some(file => {
+    var f = checkIosFile(file);
+    if(f){
+      hasIosFile =f;
+    }
+    return f;
+  });
+}
+
+if(hasIosFile){
+  var runTestCmd='source ~/.bash_profile; '
+    +'xcodebuild -project ios/sdk/WeexSDK.xcodeproj test '
+    +'-scheme WeexSDKTests CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO '
+    +'-destination "platform=iOS Simulator,name=iPhone 6"'
+  runSuccess = shell.exec(runTestCmd,{ async: false, timeout: 8 * 60 * 1000 
}).code == 0;
+  if(!runSuccess){
+    fail("ios platform run unit test failed!");
+  }
+}else{
+  message('has no ios file changed,skip test!');
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/dangerfile-jsfm.js
----------------------------------------------------------------------
diff --git a/dangerfile-jsfm.js b/dangerfile-jsfm.js
new file mode 100644
index 0000000..64b72f4
--- /dev/null
+++ b/dangerfile-jsfm.js
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+// Removed import
+import fs from "fs";
+import path from 'path';
+import GitHubApi from 'github';
+import parseDiff from 'parse-diff';
+import shell from "shelljs";
+
+const type_unknown = 0;
+const type_ios_sdk = 1;
+const type_android_sdk = 2;
+const type_ios_test = 3;
+const type_android_test = 4;
+const type_jsfm = 5;
+const type_jsfm_test = 6;
+const type_doc = 7;
+const type_ui_test = 8;
+
+const getFileType = file => {
+  if (file.match(/WeexSDK\/Sources\/.+\.(m|h|mm)/)) {
+    return type_ios_sdk;
+  } else if (file.match(/WeexSDKTests\//)) {
+    return type_ios_test;
+  } else if (file.match(/android\/sdk\/src\/test\/.+\.java/)) {
+    return type_android_test;
+  } else if (file.match(/android\/sdk\/src\/main\/java\/.+\.java/)) {
+    return type_android_sdk;
+  } else if (
+    file.match(/html5\/(shared|frameworks|render|runtime|services)\/.+\.js/)
+  ) {
+    return type_jsfm;
+  } else if (file.match(/html5\/test\/.+\.js/)) {
+    return type_jsfm_test;
+  } else if (file.match(/doc\/\.+\.md/)) {
+    return type_doc;
+  } else if(file.match(/test\/scripts\/.+\.js/) || 
file.match(/test\/pages\/.+\.vue/)){
+    return type_ui_test
+  }else{
+    return type_unknown
+  }
+}
+
+function checkJsfmFile(file){
+  var type = getFileType(file);
+  return type == type_jsfm || type == type_jsfm_test;
+}
+
+var hasJsfmFile = false;
+
+if (!hasJsfmFile && danger.git.created_files) {
+  danger.git.created_files.some(file => {
+    var f = checkJsfmFile(file);
+    if(f){
+      hasJsfmFile =f;
+    }
+    return f;
+  });
+}
+if (!hasJsfmFile && danger.git.modified_files) {
+  danger.git.modified_files.some(file => {
+    var f = checkJsfmFile(file);
+    if(f){
+      hasJsfmFile =f;
+    }
+    return f;
+  });
+}
+if (!hasJsfmFile && danger.git.deleted_files) {
+  danger.git.deleted_files.some(file => {
+    var f = checkJsfmFile(file);
+    if(f){
+      hasJsfmFile =f;
+    }
+    return f;
+  });
+}
+
+if(hasJsfmFile){
+  var runTestCmd='source ~/.bash_profile; '
+    + 'npm run build && npm run test'
+  var runSuccess = shell.exec(runTestCmd,{ async: false, timeout: 8 * 60 * 
1000 }).code == 0;
+  if(!runSuccess){
+    fail("jsfm run test failed!");
+  }
+}else{
+  message('has no jsfm file changed,skip test!');
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj 
b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index d43ec0e..3802d0e 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -48,8 +48,6 @@
                591DD3321D23AD5800BE8709 /* WXErrorView.h in Headers */ = {isa 
= PBXBuildFile; fileRef = 591DD3301D23AD5800BE8709 /* WXErrorView.h */; 
settings = {ATTRIBUTES = (Public, ); }; };
                594C28921CF9E61A009793A4 /* WXAnimationModule.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 594C28901CF9E61A009793A4 /* WXAnimationModule.m 
*/; };
                594C28931CF9E61A009793A4 /* WXAnimationModule.h in Headers */ = 
{isa = PBXBuildFile; fileRef = 594C28911CF9E61A009793A4 /* WXAnimationModule.h 
*/; };
-               59597F981D2A041700EE9317 /* WXDebugLoggerBridge.h in Headers */ 
= {isa = PBXBuildFile; fileRef = 59597F961D2A041700EE9317 /* 
WXDebugLoggerBridge.h */; };
-               59597F991D2A041700EE9317 /* WXDebugLoggerBridge.m in Sources */ 
= {isa = PBXBuildFile; fileRef = 59597F971D2A041700EE9317 /* 
WXDebugLoggerBridge.m */; };
                596FDD661D3F52700082CD5B /* WXAnimationModuleTests.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = 596FDD651D3F52700082CD5B /* 
WXAnimationModuleTests.m */; };
                596FDD691D3F9EFF0082CD5B /* TestSupportUtils.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 596FDD681D3F9EFF0082CD5B /* TestSupportUtils.m 
*/; };
                597334B11D4D9E7F00988789 /* WXSDKManagerTests.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 597334B01D4D9E7F00988789 /* WXSDKManagerTests.m 
*/; };
@@ -85,7 +83,6 @@
                740451EB1E14BB26004157CB /* WXServiceFactory.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 740451E91E14BB26004157CB /* WXServiceFactory.m 
*/; };
                7408C48E1CFB345D000BCCD0 /* WXComponent+Events.h in Headers */ 
= {isa = PBXBuildFile; fileRef = 7408C48C1CFB345D000BCCD0 /* 
WXComponent+Events.h */; };
                7408C48F1CFB345D000BCCD0 /* WXComponent+Events.m in Sources */ 
= {isa = PBXBuildFile; fileRef = 7408C48D1CFB345D000BCCD0 /* 
WXComponent+Events.m */; };
-               740938EC1D3D075700DBB801 /* SRWebSocket.m in Sources */ = {isa 
= PBXBuildFile; fileRef = 2A27E7D81C3E360B00D7A552 /* SRWebSocket.m */; };
                740938EE1D3D079100DBB801 /* JavaScriptCore.framework in 
Frameworks */ = {isa = PBXBuildFile; fileRef = 740938ED1D3D079100DBB801 /* 
JavaScriptCore.framework */; };
                740938EF1D3D083900DBB801 /* libicucore.tbd in Frameworks */ = 
{isa = PBXBuildFile; fileRef = 7469869B1C4DEAC20054A57E /* libicucore.tbd */; };
                740938F31D3D0D9300DBB801 /* WXComponentTests.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 740938EA1D3D026600DBB801 /* WXComponentTests.m 
*/; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@@ -243,8 +240,6 @@
                C42E8FAB1F3C7C09001EBE9D /* WXExtendCallNativeProtocol.h in 
Headers */ = {isa = PBXBuildFile; fileRef = C4424E591F24DA3D009F52E2 /* 
WXExtendCallNativeProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
                C42E8FAC1F3C7C3B001EBE9D /* WXExtendCallNativeManager.m in 
Sources */ = {isa = PBXBuildFile; fileRef = C47B78CD1F2998EE001D3B0C /* 
WXExtendCallNativeManager.m */; };
                C42E8FAD1F3C7C3F001EBE9D /* WXExtendCallNativeManager.h in 
Headers */ = {isa = PBXBuildFile; fileRef = C47B78CC1F2998EE001D3B0C /* 
WXExtendCallNativeManager.h */; };
-               C42E8FAE1F3C7C49001EBE9D /* WXRecyclerDragController.m in 
Sources */ = {isa = PBXBuildFile; fileRef = DC7764911F3C2CA300B5727E /* 
WXRecyclerDragController.m */; };
-               C42E8FAF1F3C7C4B001EBE9D /* WXRecyclerDragController.h in 
Headers */ = {isa = PBXBuildFile; fileRef = DC7764921F3C2CA300B5727E /* 
WXRecyclerDragController.h */; };
                C43C03E81EC8ACA40044C7FF /* WXPrerenderManager.h in Headers */ 
= {isa = PBXBuildFile; fileRef = C43C03E41EC8ACA40044C7FF /* 
WXPrerenderManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
                C43C03E91EC8ACA40044C7FF /* WXPrerenderManager.m in Sources */ 
= {isa = PBXBuildFile; fileRef = C43C03E51EC8ACA40044C7FF /* 
WXPrerenderManager.m */; };
                C4424E5B1F24DA3D009F52E2 /* WXExtendCallNativeProtocol.h in 
Headers */ = {isa = PBXBuildFile; fileRef = C4424E591F24DA3D009F52E2 /* 
WXExtendCallNativeProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -264,10 +259,6 @@
                C4E375381E5FCBD3009B2D9C /* WXComponent+BoxShadow.h in Headers 
*/ = {isa = PBXBuildFile; fileRef = C4E375361E5FCBD3009B2D9C /* 
WXComponent+BoxShadow.h */; };
                C4E97D331F1EF46D00ABC314 /* WXTracingManager.h in Headers */ = 
{isa = PBXBuildFile; fileRef = C4E97D311F1EF46D00ABC314 /* WXTracingManager.h 
*/; settings = {ATTRIBUTES = (Public, ); }; };
                C4E97D341F1EF46D00ABC314 /* WXTracingManager.m in Sources */ = 
{isa = PBXBuildFile; fileRef = C4E97D321F1EF46D00ABC314 /* WXTracingManager.m 
*/; };
-               C4F012791E1502A6003378D0 /* SRWebSocket+Weex.h in Headers */ = 
{isa = PBXBuildFile; fileRef = C4F012721E1502A6003378D0 /* SRWebSocket+Weex.h 
*/; };
-               C4F0127A1E1502A6003378D0 /* SRWebSocket+Weex.m in Sources */ = 
{isa = PBXBuildFile; fileRef = C4F012731E1502A6003378D0 /* SRWebSocket+Weex.m 
*/; };
-               C4F0127B1E1502A6003378D0 /* WXWebSocketDefaultImpl.h in Headers 
*/ = {isa = PBXBuildFile; fileRef = C4F012741E1502A6003378D0 /* 
WXWebSocketDefaultImpl.h */; };
-               C4F0127C1E1502A6003378D0 /* WXWebSocketDefaultImpl.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = C4F012751E1502A6003378D0 /* 
WXWebSocketDefaultImpl.m */; };
                C4F0127D1E1502A6003378D0 /* WXWebSocketHandler.h in Headers */ 
= {isa = PBXBuildFile; fileRef = C4F012761E1502A6003378D0 /* 
WXWebSocketHandler.h */; };
                C4F012821E1502E9003378D0 /* WXWebSocketModule.h in Headers */ = 
{isa = PBXBuildFile; fileRef = C4F012801E1502E9003378D0 /* WXWebSocketModule.h 
*/; };
                C4F012831E1502E9003378D0 /* WXWebSocketModule.m in Sources */ = 
{isa = PBXBuildFile; fileRef = C4F012811E1502E9003378D0 /* WXWebSocketModule.m 
*/; };
@@ -588,8 +579,6 @@
                1D3000F01D40B9AB004F3B4F /* WXClipboardModule.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXClipboardModule.m; sourceTree = "<group>"; };
                2A1F57B51C75C6A600B58017 /* WXTextInputComponent.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXTextInputComponent.h; sourceTree = "<group>"; };
                2A1F57B61C75C6A600B58017 /* WXTextInputComponent.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXTextInputComponent.m; sourceTree = "<group>"; };
-               2A27E7D71C3E360B00D7A552 /* SRWebSocket.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = 
SRWebSocket.h; path = dependency/SRWebSocket.h; sourceTree = "<group>"; };
-               2A27E7D81C3E360B00D7A552 /* SRWebSocket.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name 
= SRWebSocket.m; path = dependency/SRWebSocket.m; sourceTree = "<group>"; };
                2A42AF851C23B33E00818EA6 /* libWeexSDK_MTL.a */ = {isa = 
PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = 
libWeexSDK_MTL.a; sourceTree = BUILT_PRODUCTS_DIR; };
                2A42AF871C23B33E00818EA6 /* WeexSDK_MTL.h */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeexSDK_MTL.h; 
sourceTree = "<group>"; };
                2A42AF891C23B33E00818EA6 /* WeexSDK_MTL.m */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WeexSDK_MTL.m; 
sourceTree = "<group>"; };
@@ -624,8 +613,6 @@
                591DD3301D23AD5800BE8709 /* WXErrorView.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXErrorView.h; sourceTree = "<group>"; };
                594C28901CF9E61A009793A4 /* WXAnimationModule.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXAnimationModule.m; sourceTree = "<group>"; };
                594C28911CF9E61A009793A4 /* WXAnimationModule.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXAnimationModule.h; sourceTree = "<group>"; };
-               59597F961D2A041700EE9317 /* WXDebugLoggerBridge.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXDebugLoggerBridge.h; sourceTree = "<group>"; };
-               59597F971D2A041700EE9317 /* WXDebugLoggerBridge.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXDebugLoggerBridge.m; sourceTree = "<group>"; };
                596FDD651D3F52700082CD5B /* WXAnimationModuleTests.m */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; 
path = WXAnimationModuleTests.m; sourceTree = "<group>"; };
                596FDD671D3F9EFF0082CD5B /* TestSupportUtils.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
TestSupportUtils.h; sourceTree = "<group>"; };
                596FDD681D3F9EFF0082CD5B /* TestSupportUtils.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= TestSupportUtils.m; sourceTree = "<group>"; };
@@ -838,10 +825,6 @@
                C4E375361E5FCBD3009B2D9C /* WXComponent+BoxShadow.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
"WXComponent+BoxShadow.h"; sourceTree = "<group>"; };
                C4E97D311F1EF46D00ABC314 /* WXTracingManager.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXTracingManager.h; sourceTree = "<group>"; };
                C4E97D321F1EF46D00ABC314 /* WXTracingManager.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXTracingManager.m; sourceTree = "<group>"; };
-               C4F012721E1502A6003378D0 /* SRWebSocket+Weex.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
"SRWebSocket+Weex.h"; sourceTree = "<group>"; };
-               C4F012731E1502A6003378D0 /* SRWebSocket+Weex.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= "SRWebSocket+Weex.m"; sourceTree = "<group>"; };
-               C4F012741E1502A6003378D0 /* WXWebSocketDefaultImpl.h */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path 
= WXWebSocketDefaultImpl.h; sourceTree = "<group>"; };
-               C4F012751E1502A6003378D0 /* WXWebSocketDefaultImpl.m */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; 
path = WXWebSocketDefaultImpl.m; sourceTree = "<group>"; };
                C4F012761E1502A6003378D0 /* WXWebSocketHandler.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXWebSocketHandler.h; sourceTree = "<group>"; };
                C4F012801E1502E9003378D0 /* WXWebSocketModule.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
WXWebSocketModule.h; sourceTree = "<group>"; };
                C4F012811E1502E9003378D0 /* WXWebSocketModule.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WXWebSocketModule.m; sourceTree = "<group>"; };
@@ -929,15 +912,6 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-               2A27E7D61C3E360400D7A552 /* dependency */ = {
-                       isa = PBXGroup;
-                       children = (
-                               2A27E7D71C3E360B00D7A552 /* SRWebSocket.h */,
-                               2A27E7D81C3E360B00D7A552 /* SRWebSocket.m */,
-                       );
-                       name = dependency;
-                       sourceTree = "<group>";
-               };
                2A42AF861C23B33E00818EA6 /* WeexSDK_MTL */ = {
                        isa = PBXGroup;
                        children = (
@@ -1166,7 +1140,6 @@
                77D160FF1C02DBE70010B15B /* WeexSDK */ = {
                        isa = PBXGroup;
                        children = (
-                               2A27E7D61C3E360400D7A552 /* dependency */,
                                77D161171C02DCB90010B15B /* Resources */,
                                77D161181C02DCB90010B15B /* Sources */,
                        );
@@ -1221,8 +1194,6 @@
                                74862F801E03A24500B7A041 /* WXComponentMethod.m 
*/,
                                74D2051E1E091B8000128F44 /* WXCallJSMethod.h */,
                                74D2051F1E091B8000128F44 /* WXCallJSMethod.m */,
-                               59597F961D2A041700EE9317 /* 
WXDebugLoggerBridge.h */,
-                               59597F971D2A041700EE9317 /* 
WXDebugLoggerBridge.m */,
                                59A582FA1CF5B17B0081FD3E /* WXBridgeContext.h 
*/,
                                59A582FB1CF5B17B0081FD3E /* WXBridgeContext.m 
*/,
                                77D1613A1C02DEA60010B15B /* WXJSCoreBridge.h */,
@@ -1476,10 +1447,6 @@
                C4F012711E1502A6003378D0 /* WebSocket */ = {
                        isa = PBXGroup;
                        children = (
-                               C4F012721E1502A6003378D0 /* SRWebSocket+Weex.h 
*/,
-                               C4F012731E1502A6003378D0 /* SRWebSocket+Weex.m 
*/,
-                               C4F012741E1502A6003378D0 /* 
WXWebSocketDefaultImpl.h */,
-                               C4F012751E1502A6003378D0 /* 
WXWebSocketDefaultImpl.m */,
                                C4F012761E1502A6003378D0 /* 
WXWebSocketHandler.h */,
                        );
                        path = WebSocket;
@@ -1531,7 +1498,6 @@
                                1D3000F11D40B9AC004F3B4F /* WXClipboardModule.h 
in Headers */,
                                59A583081CF5B2FD0081FD3E /* 
WXNavigationDefaultImpl.h in Headers */,
                                775BEE4E1C16F993008D1629 /* WXDefine.h in 
Headers */,
-                               59597F981D2A041700EE9317 /* 
WXDebugLoggerBridge.h in Headers */,
                                77D161241C02DDD10010B15B /* WXSDKInstance.h in 
Headers */,
                                DC6836E61EBB12B200AD2D84 /* 
WXConfigCenterProtocol.h in Headers */,
                                DC7764941F3C2CA300B5727E /* 
WXRecyclerDragController.h in Headers */,
@@ -1575,7 +1541,6 @@
                                744D61141E4AF23E00B624B3 /* WXDiffUtil.h in 
Headers */,
                                74862F791E02B88D00B7A041 /* JSValue+Weex.h in 
Headers */,
                                2A1F57B71C75C6A600B58017 /* 
WXTextInputComponent.h in Headers */,
-                               C4F012791E1502A6003378D0 /* SRWebSocket+Weex.h 
in Headers */,
                                74A4BA9A1CB3BAA100195969 /* 
WXThreadSafeMutableDictionary.h in Headers */,
                                74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h 
in Headers */,
                                741DFE021DDD7D18009B020F /* WXRoundedRect.h in 
Headers */,
@@ -1604,7 +1569,6 @@
                                77E65A0D1C155E99008B8775 /* WXDivComponent.h in 
Headers */,
                                C41E1A971DC1FD15009C7F90 /* 
WXDatePickerManager.h in Headers */,
                                333D9A271F41507A007CED39 /* WXTransition.h in 
Headers */,
-                               C4F0127B1E1502A6003378D0 /* 
WXWebSocketDefaultImpl.h in Headers */,
                                7461F8901CFB373100F62D44 /* WXDisplayQueue.h in 
Headers */,
                                DCC77C141D770AE300CE7288 /* 
WXSliderNeighborComponent.h in Headers */,
                                747DF6821E31AEE4005C53A8 /* WXLength.h in 
Headers */,
@@ -1674,7 +1638,6 @@
                                333D9A281F41507A007CED39 /* WXTransition.h in 
Headers */,
                                DCA445A51EFA571600D0CFA8 /* WXSDKError.h in 
Headers */,
                                DCA445AD1EFA575100D0CFA8 /* 
WXNavigationProtocol.h in Headers */,
-                               C42E8FAF1F3C7C4B001EBE9D /* 
WXRecyclerDragController.h in Headers */,
                                DCA445B01EFA576200D0CFA8 /* WXModalUIModule.h 
in Headers */,
                                DCA445A61EFA571E00D0CFA8 /* WXSDKEngine.h in 
Headers */,
                                DCA445AA1EFA573900D0CFA8 /* WXResourceRequest.h 
in Headers */,
@@ -2019,7 +1982,6 @@
                                DC9F46831D61AC8800A88239 /* 
WXStreamModuleTests.m in Sources */,
                                1C1A2BED1D91172800539AA1 /* WXConvertTests.m in 
Sources */,
                                74EF31C31DE6935600667A07 /* WXURLRewriteTests.m 
in Sources */,
-                               740938EC1D3D075700DBB801 /* SRWebSocket.m in 
Sources */,
                                740938F31D3D0D9300DBB801 /* WXComponentTests.m 
in Sources */,
                                596FDD661D3F52700082CD5B /* 
WXAnimationModuleTests.m in Sources */,
                                591324A31D49B7F1004E89ED /* 
WXTimerModuleTests.m in Sources */,
@@ -2043,7 +2005,6 @@
                                74B8BEFF1DC47B72004A6027 /* WXRootView.m in 
Sources */,
                                742AD7321DF98C45007DC46C /* 
WXResourceRequestHandlerDefaultImpl.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 */,
@@ -2093,7 +2054,6 @@
                                746319031C60AFC100EFEBD4 /* 
WXThreadSafeCounter.m in Sources */,
                                74A4BAA71CB4F98300195969 /* WXStreamModule.m in 
Sources */,
                                744D610D1E49978200B624B3 /* WXHeaderComponent.m 
in Sources */,
-                               59597F991D2A041700EE9317 /* 
WXDebugLoggerBridge.m in Sources */,
                                77E659F21C0C3612008B8775 /* WXModuleFactory.m 
in Sources */,
                                DCF343681E49CAEE00A2FB34 /* WXJSExceptionInfo.m 
in Sources */,
                                59CE27E91CC387DB000BE37A /* WXEmbedComponent.m 
in Sources */,
@@ -2152,7 +2112,6 @@
                                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 */,
                        );
@@ -2243,7 +2202,6 @@
                                DCA4457A1EFA55B300D0CFA8 /* 
WXSimulatorShortcutManager.m in Sources */,
                                DCA4457B1EFA55B300D0CFA8 /* WXAssert.m in 
Sources */,
                                DCA4457C1EFA55B300D0CFA8 /* 
WXAppConfiguration.m in Sources */,
-                               C42E8FAE1F3C7C49001EBE9D /* 
WXRecyclerDragController.m in Sources */,
                                DCA4457D1EFA55B300D0CFA8 /* 
WXThreadSafeMutableDictionary.m in Sources */,
                                DCA4457E1EFA55B300D0CFA8 /* 
WXThreadSafeMutableArray.m in Sources */,
                                DCA4457F1EFA55B300D0CFA8 /* 
NSObject+WXSwizzle.m in Sources */,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.h 
b/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.h
deleted file mode 100644
index c86b12e..0000000
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.h
+++ /dev/null
@@ -1,26 +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 "WXBridgeProtocol.h"
-
-@interface WXDebugLoggerBridge : NSObject <WXBridgeProtocol>
-
-- (instancetype)initWithURL:(NSURL *) URL;
-
-@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m 
b/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
deleted file mode 100644
index fcc4cb3..0000000
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
+++ /dev/null
@@ -1,213 +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 "WXDebugLoggerBridge.h"
-#import "SRWebSocket.h"
-#import "WXSDKManager.h"
-#import "WXUtility.h"
-#import "WXLog.h"
-
-@interface WXDebugLoggerBridge()<SRWebSocketDelegate>
-
-@end
-
-@implementation WXDebugLoggerBridge
-{
-    BOOL    _isConnect;
-    SRWebSocket *_webSocket;
-    NSMutableArray  *_msgAry;
-    WXJSCallNative  _nativeCallBlock;
-    NSThread    *_curThread;
-}
-
-- (void)dealloc
-{
-    _nativeCallBlock = nil;
-    [self _disconnect];
-}
-
-- (instancetype)initWithURL:(NSURL *) URL
-{
-    self = [super init];
-    
-    _isConnect = NO;
-    _curThread = [NSThread currentThread];
-    
-    [self _connect:URL];
-    
-    return self;
-}
-
-- (void)_initEnvironment
-{
-    [self callJSMethod:@"setEnvironment" args:@[[WXUtility getEnvironment]]];
-}
-
-- (void)_disconnect
-{
-    _msgAry = nil;
-    _isConnect = NO;
-    _webSocket.delegate = nil;
-    [_webSocket close];
-    _webSocket = nil;
-}
-
-- (void)_connect:(NSURL *)URL
-{
-    _msgAry = nil;
-    _msgAry = [NSMutableArray array];
-    _webSocket.delegate = nil;
-    [_webSocket close];
-    
-    _webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest 
requestWithURL:URL]];
-    _webSocket.delegate = self;
-    
-    [_webSocket open];
-}
-
--(void)_executionMsgAry
-{
-    if (!_isConnect) return;
-    
-    NSArray *templateContainers = [NSArray arrayWithArray:_msgAry];
-    for (NSString *msg in templateContainers) {
-        [_webSocket send:msg];
-    }
-    [_msgAry removeAllObjects];
-}
-
--(void)_evaluateNative:(NSString *)data
-{
-    NSDictionary *dict = [WXUtility objectFromJSON:data];
-    NSString *method = [dict objectForKey:@"method"];
-    NSArray *args = [dict objectForKey:@"arguments"];
-    
-    if ([method isEqualToString:@"callNative"]) {
-        // call native
-        NSString *instanceId = args[0];
-        NSArray *methods = args[1];
-        NSString *callbackId = args[2];
-        
-        // params parse
-        if(!methods || methods.count <= 0){
-            return;
-        }
-        //call native
-        WXLogDebug(@"Calling native... instanceId:%@, methods:%@, 
callbackId:%@", instanceId, [WXUtility JSONString:methods], callbackId);
-        _nativeCallBlock(instanceId, methods, callbackId);
-    } else if ([method isEqualToString:@"setLogLevel"]) {
-        NSString *levelString = [args firstObject];
-        [WXLog setLogLevelString:levelString];
-    }
-}
-
-#pragma mark - WXBridgeProtocol
-
-- (void)executeJavascript:(NSString *)script
-{
-    [self callJSMethod:@"evalFramework" args:@[script]];
-}
-
-- (void)executeJSFramework:(NSString *)frameworkScript
-{
-    [self callJSMethod:@"evalFramework" args:@[frameworkScript]];
-}
-
-- (JSValue *)callJSMethod:(NSString *)method args:(NSArray *)args
-{
-    if (![method isEqualToString:@"__logger"]) {
-        // prevent recursion
-        WXLogDebug(@"Calling JS... method:%@, args:%@", method, [WXUtility 
JSONString:args]);
-    }
-    
-    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
-    [dict setObject:method forKey:@"method"];
-    [dict setObject:args forKey:@"arguments"];
-    
-    [_msgAry addObject:[WXUtility JSONString:dict]];
-    [self _executionMsgAry];
-    
-    return nil;
-}
-
-- (void)registerCallNative:(WXJSCallNative)callNative
-{
-    _nativeCallBlock = callNative;
-}
-
-- (JSValue*) exception
-{
-    return nil;
-}
-
-- (void)resetEnvironment
-{
-    [self _initEnvironment];
-}
-
-- (void)garbageCollect
-{
-    
-}
-
-- (void)executeBridgeThead:(dispatch_block_t)block
-{
-    if([NSThread currentThread] == _curThread){
-        block();
-    } else {
-        [self performSelector:@selector(executeBridgeThead:)
-                     onThread:_curThread
-                   withObject:[block copy]
-                waitUntilDone:NO];
-    }
-}
-
-#pragma mark - SRWebSocketDelegate
-
-- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
-{
-    WXLogWarning(@"Websocket Connected:%@", webSocket.url);
-    _isConnect = YES;
-    [self _initEnvironment];
-    __weak typeof(self) weakSelf = self;
-    [self executeBridgeThead:^() {
-        [weakSelf _executionMsgAry];
-    }];
-}
-
-- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
-{
-    WXLogError(@":( Websocket Failed With Error %@", error);
-}
-
-- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
-{
-    __weak typeof(self) weakSelf = self;
-    [self executeBridgeThead:^() {
-        [weakSelf _evaluateNative:message];
-    }];
-}
-
-- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code 
reason:(NSString *)reason wasClean:(BOOL)wasClean
-{
-    WXLogInfo(@"Websocket closed with code: %ld, reason:%@, wasClean: %d", 
(long)code, reason, wasClean);
-    _isConnect = NO;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m 
b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
index dd776a9..fb07935 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
@@ -46,6 +46,8 @@
 
 @property (nonatomic, strong)  JSContext *jsContext;
 @property (nonatomic, strong)  NSMutableArray *timers;
+@property (nonatomic, strong)  NSMutableDictionary *intervaltimers;
+@property (nonatomic)  long long intervalTimerId;
 @property (nonatomic, strong)  NSMutableDictionary *callbacks;
 
 @end
@@ -63,7 +65,9 @@
         }
         _timers = [NSMutableArray new];
         _callbacks = [NSMutableDictionary new];
-        
+        _intervalTimerId = 0;
+        _intervaltimers = [NSMutableDictionary new];
+
         __weak typeof(self) weakSelf = self;
         
         NSDictionary *data = [WXUtility getEnvironment];
@@ -76,16 +80,19 @@
             } afterDelay:[timeout toDouble] / 1000];
         };
         
-        _jsContext[@"setTimeoutWeex"] = ^(JSValue *appid, JSValue *ret,JSValue 
*arg ) {
-            [weakSelf triggerTimeout:[appid toString] ret:[ret toString] 
arg:[arg toString]];
+        _jsContext[@"setTimeoutWeex"] = ^(JSValue *appId, JSValue *ret,JSValue 
*arg ) {
+            [weakSelf triggerTimeout:[appId toString] ret:[ret toString] 
arg:[arg toString]];
         };
         
-        _jsContext[@"setIntervalWeex"] = ^(JSValue *appid, JSValue 
*ret,JSValue *arg) {
-            [weakSelf triggerInterval:[appid toString] ret:[ret toString] 
arg:[arg toString]];
+        _jsContext[@"setIntervalWeex"] = ^(JSValue *appId, JSValue 
*function,JSValue *arg) {
+            return [weakSelf triggerInterval:[appId toString] function:^() {
+                [function callWithArguments:@[]];
+            } arg:[arg toString]];
         };
         
-        _jsContext[@"clearIntervalWeex"] = ^(JSValue *appid, JSValue 
*ret,JSValue *arg) {
-            [weakSelf triggerClearInterval:[appid toString] ret:[ret toString] 
arg:[arg toString]];
+        _jsContext[@"clearIntervalWeex"] = ^(JSValue *appId, JSValue 
*ret,JSValue *arg) {
+            
+            [weakSelf triggerClearInterval:[appId toString] ret:[[ret 
toNumber] longLongValue]];
         };
         
         _jsContext[@"clearTimeoutWeex"] = ^(JSValue *ret) {
@@ -411,6 +418,7 @@
 #pragma mark - Public
 -(void)removeTimers:(NSString *)instance
 {
+    // remove timers
     if([_callbacks objectForKey:instance]){
         NSMutableArray *arr = [_callbacks objectForKey:instance];
         if(arr && [arr count]>0){
@@ -421,6 +429,10 @@
             }
         }
     }
+    // remove intervaltimers
+    if(_intervaltimers && [_intervaltimers objectForKey:instance]){
+        [_intervaltimers removeObjectForKey:instance];
+    }
 }
 
 #pragma mark - Private
@@ -451,20 +463,25 @@
 - (void)callBack:(NSDictionary *)dic
 {
     if([dic objectForKey:@"ret"] && [_timers containsObject:[dic 
objectForKey:@"ret"]]) {
-        [[WXSDKManager bridgeMgr] callBack:[dic objectForKey:@"appid"] 
funcId:[dic objectForKey:@"ret"]  params:[dic objectForKey:@"arg"] 
keepAlive:NO];
+        [[WXSDKManager bridgeMgr] callBack:[dic objectForKey:@"appId"] 
funcId:[dic objectForKey:@"ret"]  params:[dic objectForKey:@"arg"] 
keepAlive:NO];
     }
+
 }
 
 
-- (void)callBackInterval:(NSDictionary *)dic
+- (void)callBackInterval:(NSDictionary *)dic functon:(void(^)())block
 {
-    if([dic objectForKey:@"ret"] && [_timers containsObject:[dic 
objectForKey:@"ret"]]) {
-        [[WXSDKManager bridgeMgr] callBack:[dic objectForKey:@"appid"] 
funcId:[dic objectForKey:@"ret"]  params:nil keepAlive:YES];
-        [self triggerInterval:[dic objectForKey:@"appid"] ret:[dic 
objectForKey:@"ret"] arg:[dic objectForKey:@"arg"]];
+    if([dic objectForKey:@"appId"] && [_intervaltimers objectForKey:[dic 
objectForKey:@"appId"]]){
+        NSMutableArray *timers = [_intervaltimers objectForKey:[dic 
objectForKey:@"appId"]];
+        if([timers containsObject:[dic objectForKey:@"timerId"]]){
+            block();
+            [self executeInterval:[dic objectForKey:@"appId"] function:block 
arg:[dic objectForKey:@"arg"] timerId:[[dic objectForKey:@"timerId"] 
longLongValue]];
+        }
     }
 }
 
-- (void)triggerTimeout:(NSString *)appid ret:(NSString *)ret arg:(NSString 
*)arg
+
+- (void)triggerTimeout:(NSString *)appId ret:(NSString *)ret arg:(NSString 
*)arg
 {
     
     double interval = [arg doubleValue]/1000.0f;
@@ -473,42 +490,60 @@
     }
     if(![_timers containsObject:ret]){
         [_timers addObject:ret];
-        [self addInstance:appid callback:ret];
+        [self addInstance:appId callback:ret];
     }
+    __weak typeof(self) weakSelf = self;
     dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 
interval*NSEC_PER_SEC);
     dispatch_after(time, 
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         NSMutableDictionary *dic = [NSMutableDictionary new];
-        [dic setObject:appid forKey:@"appid"];
+        [dic setObject:appId forKey:@"appId"];
         [dic setObject:ret forKey:@"ret"];
         [dic setObject:arg forKey:@"arg"];
-        [self performSelector:@selector(callBack:) withObject:dic ];
+        [weakSelf performSelector:@selector(callBack:) withObject:dic ];
     });
 }
 
-- (void)triggerInterval:(NSString *)appid ret:(NSString *)ret arg:(NSString 
*)arg
+- (long long)triggerInterval:(NSString *)appId function:(void(^)())block 
arg:(NSString *)arg
 {
     double interval = [arg doubleValue]/1000.0f;
+    long long timerId = _intervalTimerId + 1;
     if(WXFloatEqual(interval,0)) {
-        return;
+        return timerId;
     }
-    if(![_timers containsObject:ret]){
-        [_timers addObject:ret];
-        [self addInstance:appid callback:ret];
+    if([_intervaltimers objectForKey:appId]){
+        NSMutableArray *timers = [[_intervaltimers objectForKey:appId] 
mutableCopy];
+        [timers addObject:@(timerId)];
+        [_intervaltimers setObject:timers forKey:appId];
+    }else {
+        NSMutableArray *timers = [NSMutableArray new];
+        [timers addObject:@(timerId)];
+        [_intervaltimers setObject:timers forKey:appId];
     }
+    [self executeInterval:appId function:block arg:arg timerId:timerId];
+    return timerId;
+}
+
+-(void)executeInterval:(NSString *)appId function:(void(^)())block 
arg:(NSString *)arg timerId:(long long)timerId
+{
+    double interval = [arg doubleValue]/1000.0f;
     dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 
interval*NSEC_PER_SEC);
+    __weak typeof(self) weakSelf = self;
     dispatch_after(time, 
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         NSMutableDictionary *dic = [NSMutableDictionary new];
-        [dic setObject:appid forKey:@"appid"];
-        [dic setObject:ret forKey:@"ret"];
+        [dic setObject:appId forKey:@"appId"];
         [dic setObject:arg forKey:@"arg"];
-        [self performSelector:@selector(callBackInterval:) withObject:dic ];
+        [dic setObject:@(timerId) forKey:@"timerId"];
+        [weakSelf performSelector:@selector(callBackInterval:functon:) 
withObject:dic withObject:block];
     });
 }
 
-- (void)triggerClearInterval:(NSString *)appid ret:(NSString *)ret 
arg:(NSString *)arg
+- (void)triggerClearInterval:(NSString *)appId ret:(long long)ret
 {
-    if([_timers containsObject:ret]){
-        [_timers removeObject:ret];
+    if(_intervaltimers && [_intervaltimers objectForKey:@"appId"]){
+        NSMutableArray *timers = [_intervaltimers objectForKey:@"appId"];
+        if(timers && [timers containsObject:@(ret)]){
+            [timers removeObject:@(ret)];
+        }
     }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m 
b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m
index e99e88f..8622ef8 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXMultiColumnLayout.m
@@ -182,19 +182,29 @@ NSString * const kMultiColumnLayoutCell = 
@"WXMultiColumnLayoutCell";
         }
         
         // cells
-        for (NSInteger item = 0; item < [self.collectionView 
numberOfItemsInSection:section]; item++) {
-            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item 
inSection:section];
-            CGFloat itemHeight = [self.delegate 
collectionView:self.collectionView layout:self 
heightForItemAtIndexPath:indexPath];
-            UICollectionViewLayoutAttributes *itemAttributes = 
[UICollectionViewLayoutAttributes 
layoutAttributesForCellWithIndexPath:indexPath];
-            NSUInteger column = [self _minHeightColumnForAllColumns];
-            CGFloat x = insets.left + (columnWidth + columnGap) * column;
-            CGFloat y = [self.columnsMaxHeights[column] floatValue];
-            itemAttributes.frame = CGRectMake(x, y, columnWidth, itemHeight);
-            cellAttributes[indexPath] = itemAttributes;
-            
-            self.columnsMaxHeights[column] = 
@(CGRectGetMaxY(itemAttributes.frame));
+        
+        @try {
+            for (NSInteger item = 0; item < [self.collectionView 
numberOfItemsInSection:section]; item++) {
+                NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item 
inSection:section];
+                CGFloat itemHeight = [self.delegate 
collectionView:self.collectionView layout:self 
heightForItemAtIndexPath:indexPath];
+                UICollectionViewLayoutAttributes *itemAttributes = 
[UICollectionViewLayoutAttributes 
layoutAttributesForCellWithIndexPath:indexPath];
+                NSUInteger column = [self _minHeightColumnForAllColumns];
+                CGFloat x = insets.left + (columnWidth + columnGap) * column;
+                if (column >= [self.columnsMaxHeights count]) {
+                    return;
+                }
+                CGFloat y = [self.columnsMaxHeights[column] floatValue];
+                itemAttributes.frame = CGRectMake(x, y, columnWidth, 
itemHeight);
+                cellAttributes[indexPath] = itemAttributes;
+                
+                self.columnsMaxHeights[column] = 
@(CGRectGetMaxY(itemAttributes.frame));
+            }
+        } @catch (NSException *exception) {
+            WXLog(@"%@", exception);
+        } @finally {
         }
         
+        
         currentHeight = [self _maxHeightForAllColumns];
         [self _columnsReachToHeight:currentHeight];
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/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 685ec07..0316321 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -64,7 +64,7 @@
     /**
      * accessibility support
      */
-    UIAccessibilityTraits _role; //accessibility
+    NSString * _roles; //accessibility
     NSString * _ariaLabel; //accessibilityLabel
     NSString * _ariaHidden; // accessibilityElementsHidden
     NSString * _accessible; // accessible

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
index b7027b1..bd31e97 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
@@ -29,6 +29,7 @@
 #import "UIBezierPath+Weex.h"
 #import "WXSDKEngine.h"
 #import "WXUtility.h"
+#import <pthread/pthread.h>
 
 @interface WXImageView : UIImageView
 
@@ -46,8 +47,12 @@
 static dispatch_queue_t WXImageUpdateQueue;
 
 @interface WXImageComponent ()
+{
+    NSString * _imageSrc;
+    pthread_mutex_t _imageSrcMutex;
+    pthread_mutexattr_t _propertMutexAttr;
+}
 
-@property (nonatomic, strong) NSString *imageSrc;
 @property (nonatomic, strong) NSString *placeholdSrc;
 @property (nonatomic, assign) CGFloat blurRadius;
 @property (nonatomic, assign) UIViewContentMode resizeMode;
@@ -72,8 +77,15 @@ WX_EXPORT_METHOD(@selector(save:))
         if (!WXImageUpdateQueue) {
             WXImageUpdateQueue = 
dispatch_queue_create("com.taobao.weex.ImageUpdateQueue", 
DISPATCH_QUEUE_SERIAL);
         }
+        
+        pthread_mutexattr_init(&(_propertMutexAttr));
+        pthread_mutexattr_settype(&(_propertMutexAttr), 
PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&(_imageSrcMutex), &(_propertMutexAttr));
+        
         if (attributes[@"src"]) {
+             pthread_mutex_lock(&(_imageSrcMutex));
             _imageSrc = [[WXConvert NSString:attributes[@"src"]] 
stringByTrimmingCharactersInSet:[NSCharacterSet 
whitespaceAndNewlineCharacterSet]];
+             pthread_mutex_unlock(&(_imageSrcMutex));
         } else {
             WXLogWarning(@"image src is nil");
         }
@@ -223,13 +235,14 @@ WX_EXPORT_METHOD(@selector(save:))
 - (void)dealloc
 {
     [self cancelImage];
+    pthread_mutex_destroy(&(_imageSrcMutex));
+    pthread_mutexattr_destroy(&_propertMutexAttr);
 }
 
 - (void)updateAttributes:(NSDictionary *)attributes
 {
     if (attributes[@"src"]) {
-        _imageSrc = [[WXConvert NSString:attributes[@"src"]] 
stringByTrimmingCharactersInSet:[NSCharacterSet 
whitespaceAndNewlineCharacterSet]];
-        [self updateImage];
+        [self setImageSrc:[[WXConvert NSString:attributes[@"src"]] 
stringByTrimmingCharactersInSet:[NSCharacterSet 
whitespaceAndNewlineCharacterSet]]];
     }
     if (attributes[@"quality"]) {
         _imageQuality = [WXConvert WXImageQuality:attributes[@"quality"]];
@@ -308,13 +321,24 @@ WX_EXPORT_METHOD(@selector(save:))
     }
 }
 
+- (NSString *)imageSrc
+{
+    pthread_mutex_lock(&(_imageSrcMutex));
+    NSString * imageSrcCpy = [_imageSrc copy];
+    pthread_mutex_unlock(&(_imageSrcMutex));
+    
+    return imageSrcCpy;
+}
+
 - (void)setImageSrc:(NSString*)src
 {
+    pthread_mutex_lock(&(_imageSrcMutex));
     if (![src isEqualToString:_imageSrc]) {
         _imageSrc = src;
         _imageDownloadFinish = NO;
         [self updateImage];
     }
+    pthread_mutex_unlock(&(_imageSrcMutex));
 }
 
 - (void)updateImage
@@ -348,7 +372,6 @@ WX_EXPORT_METHOD(@selector(save:))
     NSString *placeholderSrc = self.placeholdSrc;
     
     if ([WXUtility isBlankString:placeholderSrc]) {
-//        WXLogError(@"image placeholder src is empty");
         return;
     }
     
@@ -387,8 +410,7 @@ WX_EXPORT_METHOD(@selector(save:))
 
 - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError 
*))downloadFailedBlock
 {
-    NSString *imageSrc = self.imageSrc;
-    
+    NSString *imageSrc = [NSString stringWithFormat:@"%@", self.imageSrc?:@""];
     if ([WXUtility isBlankString:imageSrc]) {
         WXLogError(@"image src is empty");
         return;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b0e072a4/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
index 664b0e8..7556074 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
@@ -362,12 +362,14 @@ do {\
 
 - (NSAttributedString *)ctAttributedString
 {
+    NSAttributedString * attributedString = nil;
     pthread_mutex_lock(&(_ctAttributedStringMutex));
     if (!_ctAttributedString) {
-        _ctAttributedString = [[self buildCTAttributeString] copy];
+        _ctAttributedString = [self buildCTAttributeString];
     }
+    attributedString = [_ctAttributedString copy];
     pthread_mutex_unlock(&(_ctAttributedStringMutex));
-    return [_ctAttributedString copy];
+    return attributedString;
 }
 
 - (void)repaintText:(NSNotification *)notification


Reply via email to