You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@weex.apache.org by GitBox <gi...@apache.org> on 2018/09/20 08:04:55 UTC

[GitHub] YorkShen closed pull request #1551: [WEEX-627][core] data render support opcode

YorkShen closed pull request #1551: [WEEX-627][core] data render support opcode
URL: https://github.com/apache/incubator-weex/pull/1551
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/android/sdk/src/main/java/com/taobao/weex/Script.java b/android/sdk/src/main/java/com/taobao/weex/Script.java
new file mode 100644
index 0000000000..e18bb7674d
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/Script.java
@@ -0,0 +1,55 @@
+/**
+ * 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;
+
+import android.text.TextUtils;
+
+public class Script {
+    private String mContent;
+    private byte[] mBinary;
+
+    public Script(String content) {
+        mContent = content;
+    }
+
+    public Script(byte[] binary) {
+        mBinary = binary;
+    }
+
+    public String getContent() {
+        return mContent;
+    }
+
+    public byte[] getBinary() {
+        return mBinary;
+    }
+
+    public int length() {
+        if (mContent != null) {
+            return mContent.length();
+        } else if (mBinary != null){
+            return mBinary.length;
+        }
+        return 0;
+    }
+
+    public boolean isEmpty() {
+        return TextUtils.isEmpty(mContent) && (mBinary == null || mBinary.length == 0);
+    }
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
index ab74905e34..386d0c19b6 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
@@ -596,6 +596,10 @@ public void render(String template, Map<String, Object> options, String jsonInit
    * @param flag     RenderStrategy {@link WXRenderStrategy}
    */
   public void render(String pageName, String template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag) {
+    render(pageName, new Script(template), options, jsonInitData, flag);
+  }
+
+  public void render(String pageName, Script template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag) {
     mWXPerformance.beforeInstanceRender(mInstanceId);
 
     if(WXEnvironment.isApkDebugable() && WXPerformance.DEFAULT.equals(pageName)){
@@ -615,6 +619,13 @@ public void render(String pageName, String template, Map<String, Object> options
     renderInternal(pageName,template,options,jsonInitData,flag);
   }
 
+  /**
+   * Render binary template asynchronously in DATA_RENDER_BINARY strategy.
+   */
+  public void render(String pageName, byte[] template, Map<String, Object> options, String jsonInitData) {
+    render(pageName, new Script(template), options, jsonInitData, WXRenderStrategy.DATA_RENDER_BINARY);
+  }
+
   private void ensureRenderArchor(){
     if(mRenderContainer == null){
       if (getContext() != null) {
@@ -631,10 +642,21 @@ private void renderInternal(String pageName,
                               String template,
                               Map<String, Object> options,
                               String jsonInitData,
-                              WXRenderStrategy flag){
+                              WXRenderStrategy flag) {
     if (mRendered || TextUtils.isEmpty(template)) {
       return;
     }
+    renderInternal(pageName, new Script(template), options, jsonInitData, flag);
+  }
+
+  private void renderInternal(String pageName,
+                              Script template,
+                              Map<String, Object> options,
+                              String jsonInitData,
+                              WXRenderStrategy flag){
+    if (mRendered || template == null || template.isEmpty()) {
+      return;
+    }
 
     //some case ,from render(template),but not render (url)
     if (!mApmForInstance.hasInit()){
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKManager.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKManager.java
index ad12499e83..afe73d28b2 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKManager.java
@@ -281,7 +281,7 @@ public void fireEvent(final String instanceId, String ref, String type, Map<Stri
     mBridgeManager.fireEventOnNode(instanceId, ref, type, params,domChanges);
   }
 
-  void createInstance(WXSDKInstance instance, String code, Map<String, Object> options, String jsonInitData) {
+  void createInstance(WXSDKInstance instance, Script code, Map<String, Object> options, String jsonInitData) {
     mWXRenderManager.registerInstance(instance);
     mBridgeManager.createInstance(instance.getInstanceId(), code, options, jsonInitData);
     if (mLifeCycleCallbacks != null) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
index f93e0fe61d..f1550aa3f6 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
@@ -66,6 +66,8 @@
 
   public native String nativeExecJSOnInstance(String instanceId, String script, int type);
 
+  public native void nativeFireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String params);
+
   private native void nativeTakeHeapSnapshot(String filename);
 
   private native void nativeBindMeasurementToRenderObject(long ptr);
@@ -677,4 +679,9 @@ public void reportNativeInitStatus(String statusCode, String errorMsg) {
       }
     }
   }
+
+  @Override
+  public void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String params) {
+    nativeFireEventOnDataRenderNode(instanceId,ref,type,data,params);
+  }
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
index 6c3b593ff1..bfb5f0576d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -30,10 +30,12 @@
 import android.support.annotation.UiThread;
 import android.support.v4.util.ArrayMap;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.taobao.weex.Script;
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.WXSDKEngine;
 import com.taobao.weex.WXSDKInstance;
@@ -48,20 +50,37 @@
 import com.taobao.weex.ui.action.*;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.module.WXDomModule;
-import com.taobao.weex.utils.*;
+import com.taobao.weex.utils.WXExceptionUtils;
+import com.taobao.weex.utils.WXFileUtils;
+import com.taobao.weex.utils.WXJsonUtils;
+import com.taobao.weex.utils.WXLogUtils;
+import com.taobao.weex.utils.WXUtils;
+import com.taobao.weex.utils.WXViewUtils;
+import com.taobao.weex.utils.WXWsonJSONSwitch;
 import com.taobao.weex.utils.batch.BactchExecutor;
 import com.taobao.weex.utils.batch.Interceptor;
 
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.InputStreamReader;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
-import android.util.Log;
 
 import static com.taobao.weex.bridge.WXModuleManager.createDomModule;
 
@@ -101,6 +120,7 @@
   public static final String METHD_COMPONENT_HOOK_SYNC = "componentHook";
   public static final String METHOD_CALLBACK = "callback";
   public static final String METHOD_REFRESH_INSTANCE = "refreshInstance";
+  public static final String METHOD_FIRE_EVENT_ON_DATA_RENDER_NODE = "fireEventOnDataRenderNode";
   public static final String METHOD_NOTIFY_TRIM_MEMORY = "notifyTrimMemory";
   public static final String METHOD_NOTIFY_SERIALIZE_CODE_CACHE =
           "notifySerializeCodeCache";
@@ -1106,14 +1126,44 @@ public void fireEventOnNode(final String instanceId, final String ref,
       throw new WXRuntimeException(
               "fireEvent must be called by main thread");
     }
-    if(callback == null) {
-      addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
-      sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
-    }else{
-      asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges);
+    if (WXSDKManager.getInstance().getAllInstanceMap().get(instanceId)!=null && WXSDKManager.getInstance().getAllInstanceMap().get(instanceId).getRenderStrategy()== WXRenderStrategy.DATA_RENDER) {
+      fireEventOnDataRenderNode(instanceId, ref, type, data, domChanges, params, callback);
+    } else {
+      if(callback == null) {
+        addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
+        sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
+      }else{
+        asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges);
+      }
     }
   }
 
+  private void fireEventOnDataRenderNode(final String instanceId, final String ref,
+                                         final String type, final Map<String, Object> data,
+                                         final Map<String, Object> domChanges, final List<Object> params, EventResult callback) {
+    mJSHandler.postDelayed(WXThread.secure(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
+          long start = System.currentTimeMillis();
+          if (WXEnvironment.isApkDebugable()) {
+            WXLogUtils.d("fireEventOnDataRenderNode >>>> instanceId:" + instanceId
+                + ", data:" + data);
+          }
+          mWXBridge.fireEventOnDataRenderNode(instanceId, ref,type,JSON.toJSONString(data),JSON.toJSONString(params));
+          WXLogUtils.renderPerformanceLog("fireEventOnDataRenderNode", System.currentTimeMillis() - start);
+        } catch (Throwable e) {
+          String err = "[WXBridgeManager] fireEventOnDataRenderNode " + WXLogUtils.getStackTrace(e);
+          WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "fireEventOnDataRenderNode",
+              err, null);
+          WXLogUtils.e(err);
+        }
+      }
+    }), 0);
+  }
+
   private boolean checkMainThread() {
     return Looper.myLooper() == Looper.getMainLooper();
   }
@@ -1252,12 +1302,17 @@ public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode erro
    */
   public void createInstance(final String instanceId, final String template,
                              final Map<String, Object> options, final String data) {
+    createInstance(instanceId, new Script(template), options, data);
+  }
+
+  public void createInstance(final String instanceId, final Script template,
+                             final Map<String, Object> options, final String data) {
     final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
     if (instance == null) {
       WXLogUtils.e("WXBridgeManager", "createInstance failed, SDKInstance is not exist");
       return;
     }
-    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(template) || mJSHandler == null) {
+    if (TextUtils.isEmpty(instanceId) || template == null || template.isEmpty() || mJSHandler == null) {
       instance.onRenderError(
               WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
               WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() +
@@ -1294,7 +1349,7 @@ public void run() {
     }, instanceId);
   }
 
-  private void invokeCreateInstance(@NonNull WXSDKInstance instance, String template,
+  private void invokeCreateInstance(@NonNull WXSDKInstance instance, Script template,
                                     Map<String, Object> options, String data) {
     // add for sandbox, will delete on sandbox ok
     initFramework("");
@@ -1318,7 +1373,7 @@ private void invokeCreateInstance(@NonNull WXSDKInstance instance, String templa
         BundType type = BundType.Others;
         try {
           long start = System.currentTimeMillis();
-          type = getBundleType(instance.getBundleUrl(), template);
+          type = getBundleType(instance.getBundleUrl(), template.getContent());
 
           if (WXEnvironment.isOpenDebugLog()) {
             long end = System.currentTimeMillis();
@@ -1360,7 +1415,7 @@ private void invokeCreateInstance(@NonNull WXSDKInstance instance, String templa
         WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
                 instance.getInstanceId());
         WXJSObject instanceObj = new WXJSObject(WXJSObject.String,
-                template);
+                template.getContent());
 
         WXJSObject optionsObj = new WXJSObject(WXJSObject.JSON,
                 options == null ? "{}"
@@ -1385,12 +1440,16 @@ private void invokeCreateInstance(@NonNull WXSDKInstance instance, String templa
         WXJSObject renderStrategy = null;
         if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
           renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.DATA_RENDER.getFlag());
+        } else if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY) {
+          renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.DATA_RENDER_BINARY.getFlag());
+          // In DATA_RENDER_BINARY strategy script is binary
+          instanceObj.data = template.getBinary();
         }
 
         WXJSObject[] args = {instanceIdObj, instanceObj, optionsObj,
                 dataObj, apiObj, renderStrategy};
 
-        instance.setTemplate(template);
+        instance.setTemplate(template.getContent());
 
         instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
 
@@ -1401,7 +1460,8 @@ private void invokeCreateInstance(@NonNull WXSDKInstance instance, String templa
           return;
         }
         if (type == BundType.Vue || type == BundType.Rax
-                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
+                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER
+                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY) {
           invokeCreateInstanceContext(instance.getInstanceId(), null, "createInstanceContext", args, false);
           return;
         } else {
@@ -2785,7 +2845,7 @@ public ContentBoxMeasurement getMeasurementFunc(String instanceId, long renderOb
     }
     return contentBoxMeasurement;
   }
-  
+
   public void bindMeasurementToRenderObject(long ptr){
     if (isJSFrameworkInit()) {
       mWXBridge.bindMeasurementToRenderObject(ptr);
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
index 3b7d9198d8..efc9bff5cf 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
@@ -200,4 +200,6 @@ int callUpdateAttrs(String instanceId, String ref,
   void setJSFrmVersion(String version);
 
   void resetWXBridge(boolean remoteDebug);
+
+  void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String params);
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/WXRenderStrategy.java b/android/sdk/src/main/java/com/taobao/weex/common/WXRenderStrategy.java
index db141d05fb..36ef8aa528 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/WXRenderStrategy.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/WXRenderStrategy.java
@@ -21,7 +21,8 @@
 public enum WXRenderStrategy {
   APPEND_ASYNC("APPEND_ASYNC"),
   APPEND_ONCE("APPEND_ONCE"),
-  DATA_RENDER("DATA_RENDER");
+  DATA_RENDER("DATA_RENDER"),
+  DATA_RENDER_BINARY("DATA_RENDER_BINARY");
 
   private String flag;
 
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java b/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java
index 8bba4f1231..530bea8211 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java
@@ -117,6 +117,24 @@ private static String readStreamToString(InputStream inputStream) {
     return "";
   }
 
+  public static byte[] readBytesFromAssets(String path, Context context) {
+    if (context == null || TextUtils.isEmpty(path)) {
+      return null;
+    }
+    InputStream inputStream = null;
+    try {
+      inputStream = context.getAssets().open(path);
+      byte[] data = new byte[4096];
+      int length = inputStream.read(data);
+      byte[] result = new byte[length];
+      System.arraycopy(data, 0, result, 0, length);
+      return result;
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+
   public static boolean saveFile(String path, byte[] content, Context context) {
     if (TextUtils.isEmpty(path) || content == null || context == null) {
       return false;
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 22ce0e4aba..9caf17bc13 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -71,6 +71,12 @@
 		4532670D213FCFB400DAA620 /* WXDisplayLinkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 45326709213FC84900DAA620 /* WXDisplayLinkManager.m */; };
 		453267142140E38900DAA620 /* vcomponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 453267122140E38900DAA620 /* vcomponent.h */; };
 		453267152140E38900DAA620 /* vcomponent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 453267132140E38900DAA620 /* vcomponent.cc */; };
+		453267202142731000DAA620 /* binary_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 4532671E2142731000DAA620 /* binary_file.h */; };
+		453267212142731000DAA620 /* binary_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4532671F2142731000DAA620 /* binary_file.cc */; };
+		4547FD012152048700E79971 /* class_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4547FCFF2152048600E79971 /* class_object.cc */; };
+		4547FD022152048700E79971 /* class_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 4547FD002152048600E79971 /* class_object.h */; };
+		4547FD032152049F00E79971 /* class_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 4547FD002152048600E79971 /* class_object.h */; };
+		4547FD04215204AB00E79971 /* class_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4547FCFF2152048600E79971 /* class_object.cc */; };
 		591324A31D49B7F1004E89ED /* WXTimerModuleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */; };
 		591DD3311D23AD5800BE8709 /* WXErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 591DD32F1D23AD5800BE8709 /* WXErrorView.m */; };
 		591DD3321D23AD5800BE8709 /* WXErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 591DD3301D23AD5800BE8709 /* WXErrorView.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1060,6 +1066,10 @@
 		45326709213FC84900DAA620 /* WXDisplayLinkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDisplayLinkManager.m; sourceTree = "<group>"; };
 		453267122140E38900DAA620 /* vcomponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcomponent.h; sourceTree = "<group>"; };
 		453267132140E38900DAA620 /* vcomponent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vcomponent.cc; sourceTree = "<group>"; };
+		4532671E2142731000DAA620 /* binary_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = binary_file.h; sourceTree = "<group>"; };
+		4532671F2142731000DAA620 /* binary_file.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = binary_file.cc; sourceTree = "<group>"; };
+		4547FCFF2152048600E79971 /* class_object.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_object.cc; sourceTree = "<group>"; };
+		4547FD002152048600E79971 /* class_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_object.h; sourceTree = "<group>"; };
 		591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModuleTests.m; sourceTree = "<group>"; };
 		591DD32F1D23AD5800BE8709 /* WXErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXErrorView.m; sourceTree = "<group>"; };
 		591DD3301D23AD5800BE8709 /* WXErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXErrorView.h; sourceTree = "<group>"; };
@@ -2196,11 +2206,15 @@
 				B8A72C97213F8BAD0024E7BE /* class_string.h */,
 				B8F2C6DD2133A83B00635B37 /* class_array.cc */,
 				B8F2C6CF2133A83A00635B37 /* class_array.h */,
+				4547FCFF2152048600E79971 /* class_object.cc */,
+				4547FD002152048600E79971 /* class_object.h */,
 				B8F2C6D42133A83A00635B37 /* class_factory.cc */,
 				B8F2C6D82133A83B00635B37 /* class_factory.h */,
 				B8F2C6D72133A83B00635B37 /* class.cc */,
 				B8F2C6D22133A83A00635B37 /* class.h */,
 				B8F2C6CE2133A83A00635B37 /* common_error.h */,
+				4532671F2142731000DAA620 /* binary_file.cc */,
+				4532671E2142731000DAA620 /* binary_file.h */,
 				B8F2C6D32133A83A00635B37 /* rax_jsx_ast.cc */,
 				B8F2C6D12133A83A00635B37 /* rax_jsx_ast.h */,
 				B8F2C6D92133A83B00635B37 /* rax_parser_builder.cc */,
@@ -2641,6 +2655,7 @@
 				B8D66BE12125572F003960BD /* handle.h in Headers */,
 				B8D66BCD2125572F003960BD /* statement.h in Headers */,
 				77D161241C02DDD10010B15B /* WXSDKInstance.h in Headers */,
+				453267202142731000DAA620 /* binary_file.h in Headers */,
 				DC6836E61EBB12B200AD2D84 /* WXConfigCenterProtocol.h in Headers */,
 				DC7764941F3C2CA300B5727E /* WXRecyclerDragController.h in Headers */,
 				74A4BAA61CB4F98300195969 /* WXStreamModule.h in Headers */,
@@ -2712,6 +2727,7 @@
 				744D61101E49979000B624B3 /* WXFooterComponent.h in Headers */,
 				744D61141E4AF23E00B624B3 /* WXDiffUtil.h in Headers */,
 				B8F2C7022133A83C00635B37 /* rax_parser_scope.h in Headers */,
+				4547FD022152048700E79971 /* class_object.h in Headers */,
 				74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */,
 				B8F2C6FA2133A83C00635B37 /* class_factory.h in Headers */,
 				2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */,
@@ -2928,6 +2944,7 @@
 				DCA445C31EFA57DC00D0CFA8 /* WXAppMonitorProtocol.h in Headers */,
 				B8D66BC42125572F003960BD /* vnode_render_context.h in Headers */,
 				DCA445AF1EFA575D00D0CFA8 /* WXModuleProtocol.h in Headers */,
+				4547FD032152049F00E79971 /* class_object.h in Headers */,
 				ED053501207F4DEB007B4568 /* JSContext+Weex.h in Headers */,
 				DCA4459F1EFA56EC00D0CFA8 /* WXURLRewriteProtocol.h in Headers */,
 				B8D66BAC2125572F003960BD /* code_generator.h in Headers */,
@@ -3402,6 +3419,7 @@
 				2A837AB71CD9DE9200AEDF03 /* WXRefreshComponent.mm in Sources */,
 				74A4BA9B1CB3BAA100195969 /* WXThreadSafeMutableDictionary.m in Sources */,
 				77E65A1A1C155F25008B8775 /* WXScrollerComponent.mm in Sources */,
+				453267212142731000DAA620 /* binary_file.cc in Sources */,
 				747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.mm in Sources */,
 				C4E375371E5FCBD3009B2D9C /* WXComponent+BoxShadow.m in Sources */,
 				C43C03E91EC8ACA40044C7FF /* WXPrerenderManager.m in Sources */,
@@ -3445,6 +3463,7 @@
 				B8D66BB72125572F003960BD /* vnode_exec_env.cc in Sources */,
 				74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */,
 				741081201CED585A001BC6E5 /* WXComponentManager.mm in Sources */,
+				4547FD012152048700E79971 /* class_object.cc in Sources */,
 				1D3000F21D40B9AC004F3B4F /* WXClipboardModule.m in Sources */,
 				B8F2C6EA2133A83C00635B37 /* rax_source_locator.cc in Sources */,
 				741DFE071DDD9B30009B020F /* UIBezierPath+Weex.m in Sources */,
@@ -3587,6 +3606,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				4547FD04215204AB00E79971 /* class_object.cc in Sources */,
 				4532670D213FCFB400DAA620 /* WXDisplayLinkManager.m in Sources */,
 				B863DF332107313400EA887D /* WXBridgeContext.m in Sources */,
 				B82A159A20F857450098A509 /* WXWebSocketLoader.m in Sources */,
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
index 3adc1cbaf3..c7532372f4 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
@@ -43,6 +43,18 @@
                options:(NSDictionary *)options
                   data:(id)data;
 
+/**
+ *  Create Instance with opcode
+ *  @param instance  :   instance id
+ *  @param contents  :   opcode data
+ *  @param options   :   parameters
+ *  @param data      :   external data
+ **/
+- (void)createInstance:(NSString *)instance
+              contents:(NSData *)contents
+               options:(NSDictionary *)options
+                  data:(id)data;
+
 /**
  *  Destroy Instance Method
  *  @param instance  :   instance id
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index 9923f153be..ea511c68d0 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -547,6 +547,42 @@ - (void) _mountInstanceInfoToGlobalContext:(WXSDKInstance*) instance
     globalContext[@"wxInstanceExtInfo"] = extInfo;
 }
 
+- (void)createInstance:(NSString *)instanceIdString
+              contents:(NSData *)contents
+               options:(NSDictionary *)options
+                  data:(id)data
+{
+    WXAssertBridgeThread();
+    WXAssertParam(instanceIdString);
+
+    @synchronized(self) {
+        if (![self.insStack containsObject:instanceIdString]) {
+            if ([options[@"RENDER_IN_ORDER"] boolValue]) {
+                [self.insStack addObject:instanceIdString];
+            } else {
+                [self.insStack insertObject:instanceIdString atIndex:0];
+            }
+        }
+    }
+    WXSDKInstance *sdkInstance = [WXSDKManager instanceForID:instanceIdString];
+    [sdkInstance.apmInstance onStage:KEY_PAGE_STAGES_LOAD_BUNDLE_START];
+
+    //create a sendQueue bind to the current instance
+    NSMutableArray *sendQueue = [NSMutableArray array];
+    [self.sendQueue setValue:sendQueue forKey:instanceIdString];
+
+    if (sdkInstance.dataRender) {
+        WX_MONITOR_INSTANCE_PERF_START(WXFirstScreenJSFExecuteTime, [WXSDKManager instanceForID:instanceIdString]);
+        WX_MONITOR_INSTANCE_PERF_START(WXPTJSCreateInstance, [WXSDKManager instanceForID:instanceIdString]);
+
+        WXPerformBlockOnComponentThread(^{
+            [WXCoreBridge createDataRenderInstance:instanceIdString contents:contents options:options data:data];
+            WX_MONITOR_INSTANCE_PERF_END(WXPTJSCreateInstance, [WXSDKManager instanceForID:instanceIdString]);
+        });
+        return;
+    }
+}
+
 - (NSString *)_pareJSBundleType:(NSString*)instanceIdString jsBundleString:(NSString*)jsBundleString
 {
     NSString * bundleType = nil;
@@ -831,6 +867,9 @@ - (void)registerModules:(NSDictionary *)modules
     if(!modules) return;
     
     [self callJSMethod:@"registerModules" args:@[modules]];
+    WXPerformBlockOnComponentThread(^{
+        [WXCoreBridge registerModules:modules];
+    });
 }
 
 - (void)registerComponents:(NSArray *)components
@@ -846,7 +885,8 @@ - (void)callJSMethod:(NSString *)method args:(NSArray *)args
 {
     if (self.frameworkLoadFinished) {
         [self.jsBridge callJSMethod:method args:args];
-    } else {
+    }
+    else {
         [_methodQueue addObject:@{@"method":method, @"args":args}];
     }
 }
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index bb25f17dc9..66bb9886f0 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -142,6 +142,8 @@ namespace WeexCore
 
 + (void)createDataRenderInstance:(NSString *)pageId template:(NSString *)temp options:(NSDictionary *)options data:(id)data;
 
++ (void)createDataRenderInstance:(NSString *)pageId contents:(NSData *)contents options:(NSDictionary *)options  data:(id)data;
+
 + (void)destroyDataRenderInstance:(NSString *)pageId;
 
 + (void)refreshDataRenderInstance:(NSString *)pageId data:(NSString *)data;
@@ -184,6 +186,10 @@ namespace WeexCore
 
 + (void)callUpdateFinish:(NSString*)pageId;
 
++ (void)fireEvent:(NSString *)pageId ref:(NSString *)ref event:(NSString *)event args:(NSDictionary *)args;
+
++ (void)registerModules:(NSDictionary *)modules;
+
 @end
 
 #endif
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index 72c07a9a12..54154ee7e6 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -44,6 +44,8 @@
 #include "base/TimeUtils.h"
 
 #import <objc/runtime.h>
+#include <fstream>
+
 
 #define NSSTRING(cstr) ((__bridge_transfer NSString*)(CFStringCreateWithCString(NULL, (const char *)(cstr), kCFStringEncodingUTF8)))
 #define NSSTRING_NO_COPY(cstr) ((__bridge_transfer NSString*)(CFStringCreateWithCStringNoCopy(NULL, (const char *)(cstr), kCFStringEncodingUTF8, kCFAllocatorNull)))
@@ -213,12 +215,33 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict,
         assert(false);
     }
     
-    std::unique_ptr<ValueWithType> IOSSide::CallNativeModule(const char* pageId, const char *module, const char *method,
-                                         const char *arguments, int argumentsLength,
+    std::unique_ptr<ValueWithType> IOSSide::CallNativeModule(const char *page_id, const char *module, const char *method,
+                                         const char *args, int argc,
                                          const char *options, int optionsLength)
     {
         // should not enter this function
-        assert(false);
+        do {
+            RenderPage *page = RenderManager::GetInstance()->GetPage(page_id);
+            if (page == nullptr) {
+                break;
+            }
+            NSString *instanceId = NSSTRING(page_id);
+            WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+            if (!instance) {
+                break;
+            }
+            NSString *moduleName = [NSString stringWithUTF8String:module];
+            NSString *methodName = [NSString stringWithUTF8String:method];
+            NSArray *newArguments;
+            if (argc > 0 && args) {
+                NSString *arguments = [NSString stringWithUTF8String:args];
+                newArguments = [WXUtility objectFromJSON:arguments];
+            }
+            WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:newArguments options:nil instance:instance];
+            [method invoke];
+            
+        } while (0);
+        
         return std::unique_ptr<ValueWithType>();
     }
         
@@ -803,6 +826,26 @@ + (void)createDataRenderInstance:(NSString *)pageId template:(NSString *)jsBundl
     node_manager->CreatePage([jsBundleString UTF8String] ?: "", [pageId UTF8String] ?: "", [optionsString UTF8String] ?: "", [dataString UTF8String] ?: "");
 }
 
++ (void)createDataRenderInstance:(NSString *)pageId contents:(NSData *)contents options:(NSDictionary *)options data:(id)data
+{
+    auto node_manager = weex::core::data_render::VNodeRenderManager::GetInstance();
+    NSString *optionsString = [WXUtility JSONString:options];
+    NSString *dataString = [WXUtility JSONString:data];
+
+//    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
+//    NSString *txtPath = [documentsPath stringByAppendingPathComponent:@"test.wasm"];
+//    std::string path = [txtPath UTF8String];
+//    std::ifstream fin(path, std::ios::in|std::ios::binary|std::ios::ate);
+//    unsigned length = static_cast<unsigned>(fin.tellg());
+//
+//    char* buffer = new char[length];
+//    fin.seekg (0, std::ios::beg);
+//    fin.read(buffer, length);
+//    fin.close();
+
+    node_manager->CreatePage(static_cast<const char*>(contents.bytes), contents.length, [pageId UTF8String], [optionsString UTF8String], dataString ? [dataString UTF8String] : "");
+}
+
 + (void)destroyDataRenderInstance:(NSString *)pageId
 {
     auto node_manager = weex::core::data_render::VNodeRenderManager::GetInstance();
@@ -815,6 +858,20 @@ + (void)refreshDataRenderInstance:(NSString *)pageId data:(NSString *)data;
     node_manager->RefreshPage([pageId UTF8String] ?: "", [data UTF8String] ?: "");
 }
 
++ (void)fireEvent:(NSString *)pageId ref:(NSString *)ref event:(NSString *)event args:(NSDictionary *)args
+{
+    NSString *params = [WXUtility JSONString:args];
+    auto vnode_manager = weex::core::data_render::VNodeRenderManager::GetInstance();
+    vnode_manager->FireEvent([pageId UTF8String] ? : "", [ref UTF8String] ? : "", [event UTF8String] ? : "", [params UTF8String] ? : "");
+}
+
++ (void)registerModules:(NSDictionary *)modules {
+    NSString *setting = [WXUtility JSONString:modules];
+    if (setting.length > 0) {
+        weex::core::data_render::VNodeRenderManager::GetInstance()->RegisterModules([setting UTF8String] ? : "");
+    }
+}
+
 + (void)setDefaultDimensionIntoRoot:(NSString*)pageId width:(CGFloat)width height:(CGFloat)height
                  isWidthWrapContent:(BOOL)isWidthWrapContent
                 isHeightWrapContent:(BOOL)isHeightWrapContent
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
index 6cc53cdced..41be70af21 100644
--- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
@@ -32,6 +32,7 @@
 #import <objc/runtime.h>
 #import <UIKit/UIGestureRecognizerSubclass.h>
 #import "WXComponent+PseudoClassManagement.h"
+#import "WXCoreBridge.h"
 
 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
 
@@ -165,8 +166,14 @@ - (void)fireEvent:(NSString *)eventName params:(NSDictionary *)params domChanges
     
     NSArray *handlerArguments = [self _paramsForEvent:eventName];
     NSString *ref = _templateComponent ? _templateComponent.ref  : self.ref;
-    
-    [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:ref type:eventName params:dict domChanges:domChanges handlerArguments:handlerArguments];
+    if (self.weexInstance.dataRender) {
+        WXPerformBlockOnComponentThread(^{
+            [WXCoreBridge fireEvent:self.weexInstance.instanceId ref:ref event:eventName args:dict];
+        });
+    }
+    else {
+        [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:ref type:eventName params:dict domChanges:domChanges handlerArguments:handlerArguments];
+    }
 }
 
 - (NSString *)recursiveFindTemplateIdWithComponent:(WXComponent *)component
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
index 163475bd81..3d062774b7 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -44,6 +44,18 @@ extern void WXPerformBlockOnBridgeThread(void (^block)(void));
                options:(NSDictionary *)options
                   data:(id)data;
 
+/**
+ *  Create Instance with opcode
+ *  @param instance  :   instance id
+ *  @param contents  :   opcode data
+ *  @param options   :   parameters
+ *  @param data      :   external data
+ **/
+- (void)createInstance:(NSString *)instance
+              contents:(NSData *)contents
+               options:(NSDictionary *)options
+                  data:(id)data;
+
 /**
  * @abstract return currentInstanceId
  **/
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index 811f918abd..5e076fea2f 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -172,6 +172,36 @@ - (void)createInstance:(NSString *)instance
     });
 }
 
+- (void)createInstance:(NSString *)instance
+              contents:(NSData *)contents
+               options:(NSDictionary *)options
+                  data:(id)data
+{
+    if (!instance || !contents) return;
+    if (![self.instanceIdStack containsObject:instance]) {
+        if ([options[@"RENDER_IN_ORDER"] boolValue]) {
+            [self.instanceIdStack addObject:instance];
+        } else {
+            [self.instanceIdStack insertObject:instance atIndex:0];
+        }
+    }
+    //third team impl...
+    WXSDKInstance* sdkInstance = [WXSDKManager instanceForID:instance];
+    if (sdkInstance) {
+        sdkInstance.apmInstance.isStartRender = YES;
+    }
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [WXTracingManager startTracingWithInstanceId:instance ref:nil className:nil name:WXTExecJS phase:WXTracingBegin functionName:@"createInstance" options:@{@"threadName":WXTJSBridgeThread}];
+        [weakSelf.bridgeCtx createInstance:instance
+                                  contents:contents
+                                   options:options
+                                      data:data];
+        [WXTracingManager startTracingWithInstanceId:instance ref:nil className:nil name:WXTExecJS phase:WXTracingEnd functionName:@"createInstance" options:@{@"threadName":WXTJSBridgeThread}];
+    });
+}
+
+
 - (NSMutableArray *)instanceIdStack
 {
     if (_instanceIdStack) return _instanceIdStack;
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
index 749462abea..165e0f82be 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
@@ -250,7 +250,7 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code
  *
  * @param data The data the bundle needs when rendered. Defalut is nil.
  **/
-- (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data;
+- (void)renderView:(id)source options:(NSDictionary *)options data:(id)data;
 
 /**
  * Reload the js bundle from the current URL and rerender.
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 3aaed72d65..45067f521f 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -243,9 +243,11 @@ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data
     [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTNetworkHanding phase:WXTracingBegin functionName:@"renderWithURL" options:@{@"bundleUrl":url?[url absoluteString]:@"",@"threadName":WXTMainThread}];
 }
 
-- (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data
+- (void)renderView:(id)source options:(NSDictionary *)options data:(id)data
 {
     WXLogDebug(@"Render source: %@, data:%@", self, [WXUtility JSONString:data]);
+    NSData* data1;
+    data1 = source;
     
     _options = options;
     _jsData = data;
@@ -253,7 +255,11 @@ - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)d
     self.needValidate = [[WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)] needValidate:self.scriptURL];
     
     [self _setPageNameValue:nil];
-    [self _renderWithMainBundleString:source];
+    if ([source isKindOfClass:[NSString class]]) {
+        [self _renderWithMainBundleString:source];
+    } else if ([source isKindOfClass:[NSData class]]) {
+        [self _renderWithOpcode:source];
+    }
     
     [WXTracingManager setBundleJSType:source instanceId:self.instanceId];
 }
@@ -263,13 +269,82 @@ - (NSString*) bundleTemplate
     return self.mainBundleString;
 }
 
+- (void)_renderWithOpcode:(NSData *)contents
+{
+    if (!self.instanceId) {
+        WXLogError(@"Fail to find instanceļ¼");
+        return;
+    }
+
+    //some case , with out render (url)
+    [self.apmInstance startRecord:self.instanceId];
+    self.apmInstance.isStartRender = YES;
+
+    self.performance.renderTimeOrigin = CACurrentMediaTime()*1000;
+    [self.apmInstance onStage:KEY_PAGE_STAGES_RENDER_ORGIGIN];
+
+    if (![WXUtility isBlankString:self.pageName]) {
+        WXLog(@"Start rendering page:%@", self.pageName);
+    } else {
+        WXLogWarning(@"WXSDKInstance's pageName should be specified.");
+        id<WXJSExceptionProtocol> jsExceptionHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXJSExceptionProtocol)];
+        if ([jsExceptionHandler respondsToSelector:@selector(onRuntimeCheckException:)]) {
+            WXRuntimeCheckException * runtimeCheckException = [WXRuntimeCheckException new];
+            runtimeCheckException.exception = @"We highly recommend you to set pageName.\n Using WXSDKInstance * instance = [WXSDKInstance new]; instance.pageName = @\"your page name\" to fix it";
+            [jsExceptionHandler onRuntimeCheckException:runtimeCheckException];
+        }
+    }
+
+    id<WXPageEventNotifyEventProtocol> pageEvent = [WXSDKEngine handlerForProtocol:@protocol(WXPageEventNotifyEventProtocol)];
+    if ([pageEvent respondsToSelector:@selector(pageStart:)]) {
+        [pageEvent pageStart:self.instanceId];
+    }
+
+    WX_MONITOR_INSTANCE_PERF_START(WXPTFirstScreenRender, self);
+    WX_MONITOR_INSTANCE_PERF_START(WXPTAllRender, self);
+
+    NSMutableDictionary *dictionary = [_options mutableCopy];
+    if ([WXLog logLevel] >= WXLogLevelLog) {
+        dictionary[@"debug"] = @(YES);
+    }
+
+    //TODO WXRootView
+    WXPerformBlockOnMainThread(^{
+        _rootView = [[WXRootView alloc] initWithFrame:self.frame];
+        _rootView.instance = self;
+        if(self.onCreate) {
+            self.onCreate(_rootView);
+        }
+    });
+    // ensure default modules/components/handlers are ready before create instance
+    [WXSDKEngine registerDefaults];
+    [[NSNotificationCenter defaultCenter] postNotificationName:WX_SDKINSTANCE_WILL_RENDER object:self];
+
+    if ([self _handleConfigCenter]) {
+        int wxErrorCode = 9999;
+        NSError * error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:wxErrorCode userInfo:nil];
+        if (self.onFailed) {
+            self.onFailed(error);
+        }
+        [self.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(wxErrorCode) stringValue]];
+        return;
+    }
+
+    [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTExecJS phase:WXTracingBegin functionName:@"renderWithOpcode" options:@{@"threadName":WXTMainThread}];
+    [[WXSDKManager bridgeMgr] createInstance:self.instanceId contents:contents options:dictionary data:_jsData];
+
+    [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTExecJS phase:WXTracingEnd functionName:@"renderWithOpcode" options:@{@"threadName":WXTMainThread}];
+
+   // WX_MONITOR_PERF_SET(WXPTBundleSize, [data length], self);
+}
+
 - (void)_renderWithMainBundleString:(NSString *)mainBundleString
 {
     if (!self.instanceId) {
         WXLogError(@"Fail to find instanceļ¼");
         return;
     }
-  
+
     //some case , with out render (url)
     [self.apmInstance startRecord:self.instanceId];
     self.apmInstance.isStartRender = YES;
@@ -469,6 +544,11 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)
             return;
         }
         
+        if ([options[@"DATA_RENDER"] boolValue] && [options[@"RENDER_WITH_BINARY"] boolValue]) {
+            [strongSelf _renderWithOpcode:data];
+            return;
+        }
+
         NSString *jsBundleString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
         if (!jsBundleString) {
             WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", strongSelf.pageName)
diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt
index dd99e523f9..c36636acb3 100644
--- a/weex_core/Source/CMakeLists.txt
+++ b/weex_core/Source/CMakeLists.txt
@@ -43,6 +43,7 @@ set(COMMON_SRCS
   ./core/render/action/render_action_add_event.cpp
   ./core/render/action/render_action_remove_event.cpp
   ./core/render/action/render_action_add_element.cpp
+  ./core/render/action/render_action_call_native_module.cpp
   ./core/render/action/render_action_remove_element.cpp
   ./core/render/action/render_action_move_element.cpp
   ./core/render/action/render_action_createbody.cpp
@@ -74,11 +75,13 @@ set(COMMON_SRCS
    ./core/data_render/class_json.cc
    ./core/data_render/class_string.cc
    ./core/data_render/class_factory.cc
+   ./core/data_render/class_object.cc
    ./core/data_render/code_generator.cc
    ./core/data_render/exec_state.cc
    ./core/data_render/object.cc
    ./core/data_render/parser.cc
    ./core/data_render/rax_jsx_ast.cc
+   ./core/data_render/js_common_function.cc
    ./core/data_render/rax_parser.cc
    ./core/data_render/rax_parser_builder.cc
    ./core/data_render/rax_parser_context.cc
@@ -91,6 +94,7 @@ set(COMMON_SRCS
    ./core/data_render/token.cc
    ./core/data_render/tokenizer.cc
    ./core/data_render/vm.cc
+   ./core/data_render/binary_file.cc
    ./core/data_render/vnode/vnode.cc
    ./core/data_render/vnode/vcomponent.cc
    ./core/data_render/vnode/vnode_exec_env.cc
diff --git a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
index 7512a0d8d1..171a7bb8af 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -37,6 +37,13 @@ static void RefreshInstance(JNIEnv* env, jobject jcaller,
     jstring function,
     jobjectArray args);
 
+static void FireEventOnRenderNode(JNIEnv* env, jobject jcaller,
+    jstring instanceId,
+    jstring _namespace,
+    jstring function,
+    jstring event,
+    jstring ref, jstring args);
+
 static jint ExecJS(JNIEnv* env, jobject jcaller,
     jstring instanceId,
     jstring name,
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp b/weex_core/Source/android/wrap/wx_bridge.cpp
index adefc82169..497c32fa52 100644
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -20,6 +20,7 @@
 #include "android/wrap/wx_bridge.h"
 #include <fstream>
 #include "android/base/jni_type.h"
+#include "android/base/jni/jbytearray_ref.h"
 #include "android/base/string/string_utils.h"
 #include "android/bridge/platform/android_bridge.h"
 #include "android/bridge/platform/android_bridge_in_multi_process.h"
@@ -38,6 +39,7 @@
 #include "core/layout/layout.h"
 #include "core/layout/measure_func_adapter_impl_android.h"
 #include "core/manager/weex_core_manager.h"
+#include "core/data_render/vnode/vnode_render_manager.h"
 
 using namespace WeexCore;
 jlongArray jFirstScreenRenderTime = nullptr;
@@ -369,6 +371,23 @@ static void RefreshInstance(JNIEnv* env, jobject jcaller, jstring instanceId,
   freeParams(params);
 }
 
+static void FireEventOnRenderNode(JNIEnv* env, jobject jcaller, jstring instanceId,
+                            jstring _namespace, jstring _function,jstring _event,
+                            jstring _ref,
+                            jstring _args) {
+  ScopedJStringUTF8 instance_id(env, instanceId);
+  ScopedJStringUTF8 name_space(env, _namespace);
+  ScopedJStringUTF8 function(env, _function);
+  ScopedJStringUTF8 event(env, _event);
+  ScopedJStringUTF8 ref(env, _ref);
+  ScopedJStringUTF8 args(env, _args);
+
+  weex::core::data_render::VNodeRenderManager::GetInstance()->FireEvent(
+      instance_id.getChars(),
+      event.getChars(),ref.getChars(),args.getChars()
+  );
+}
+
 static jint ExecJSService(JNIEnv* env, jobject object, jstring script) {
   if (script == nullptr) return false;
   ScopedJStringUTF8 source(env, script);
@@ -513,20 +532,35 @@ static jint CreateInstanceContext(JNIEnv* env, jobject jcaller,
   auto japi = arg4->GetData(env);
   ScopedJStringUTF8 scoped_id(env, instanceId);
   ScopedJStringUTF8 scoped_func(env, function);
-  ScopedJStringUTF8 scoped_script(env, static_cast<jstring>(jscript.Get()));
   ScopedJStringUTF8 scoped_opts(env, opts.Get());
   ScopedJStringUTF8 scoped_init_data(env, initData.Get());
   ScopedJStringUTF8 scoped_api(env, static_cast<jstring>(japi.Get()));
   ScopedJStringUTF8 scoped_render_strategy(
       env, static_cast<jstring>(render_strategy->GetData(env).Release()));
 
-  return WeexCoreManager::Instance()
-      ->getPlatformBridge()
-      ->core_side()
-      ->CreateInstance(scoped_id.getChars(), scoped_func.getChars(),
-                       scoped_script.getChars(), scoped_opts.getChars(),
-                       scoped_init_data.getChars(), scoped_api.getChars(),
-                       scoped_render_strategy.getChars());
+  // If strategy is DATA_RENDER_BINARY, jscript is a jbyteArray, otherwise jstring
+  // TODO use better way
+  if (scoped_render_strategy.getChars() != nullptr
+      && strcmp(scoped_render_strategy.getChars(), "DATA_RENDER_BINARY") == 0) {
+    JByteArrayRef byte_array(env, static_cast<jbyteArray>(jscript.Get()));
+    return WeexCoreManager::Instance()
+            ->getPlatformBridge()
+            ->core_side()
+            ->CreateInstance(scoped_id.getChars(), scoped_func.getChars(),
+                             byte_array.getBytes(), byte_array.length(), scoped_opts.getChars(),
+                             scoped_init_data.getChars(), scoped_api.getChars(),
+                             scoped_render_strategy.getChars());
+  } else {
+    ScopedJStringUTF8 scoped_script(env, static_cast<jstring>(jscript.Get()));
+    return WeexCoreManager::Instance()
+            ->getPlatformBridge()
+            ->core_side()
+            ->CreateInstance(scoped_id.getChars(), scoped_func.getChars(),
+                             scoped_script.getChars(), strlen(scoped_script.getChars()), scoped_opts.getChars(),
+                             scoped_init_data.getChars(), scoped_api.getChars(),
+                             scoped_render_strategy.getChars());
+  }
+
 }
 
 static jint DestoryInstance(JNIEnv* env, jobject jcaller, jstring instanceId,
diff --git a/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp b/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
index 5540a53479..3ada98ae48 100644
--- a/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
+++ b/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
@@ -413,18 +413,28 @@ std::unique_ptr<WeexJSResult> CoreSideInPlatform::ExecJSWithResult(
 }
 
 int CoreSideInPlatform::CreateInstance(const char *instanceId, const char *func,
-                                       const char *script, const char *opts,
+                                       const char *script, int script_length,
+                                       const char *opts,
                                        const char *initData,
                                        const char *extendsApi,
                                        const char *render_strategy) {
-  if (render_strategy != nullptr &&
-      strcmp(render_strategy, "DATA_RENDER") == 0) {
-    auto node_manager =
-        weex::core::data_render::VNodeRenderManager::GetInstance();
-    node_manager->CreatePage(script, instanceId, render_strategy, initData);
-
-    return true;
+  // First check about DATA_RENDER mode
+  if (render_strategy != nullptr) {
+    if (strcmp(render_strategy, "DATA_RENDER") == 0) {
+      auto node_manager =
+              weex::core::data_render::VNodeRenderManager::GetInstance();
+      node_manager->CreatePage(script, instanceId, render_strategy, initData);
+
+      return true;
+    } else if (strcmp(render_strategy, "DATA_RENDER_BINARY") == 0) {
+      auto node_manager =
+              weex::core::data_render::VNodeRenderManager::GetInstance();
+      node_manager->CreatePage(script, script_length, instanceId, render_strategy, initData);
+
+      return true;
+    }
   }
+
   return WeexCoreManager::Instance()
       ->script_bridge()
       ->script_side()
diff --git a/weex_core/Source/core/bridge/platform/core_side_in_platform.h b/weex_core/Source/core/bridge/platform/core_side_in_platform.h
index 9f66e01bfb..87b762a13a 100644
--- a/weex_core/Source/core/bridge/platform/core_side_in_platform.h
+++ b/weex_core/Source/core/bridge/platform/core_side_in_platform.h
@@ -92,7 +92,7 @@ class CoreSideInPlatform : public PlatformBridge::CoreSide {
       const char *instanceId, const char *nameSpace, const char *func,
       std::vector<VALUE_WITH_TYPE *> &params) override;
   int CreateInstance(const char *instanceId, const char *func,
-                     const char *script, const char *opts, const char *initData,
+                     const char *script, int script_length, const char *opts, const char *initData,
                      const char *extendsApi, const char* render_strategy) override;
   std::unique_ptr<WeexJSResult> ExecJSOnInstance(const char *instanceId,
                                const char *script) override;
diff --git a/weex_core/Source/core/bridge/platform_bridge.h b/weex_core/Source/core/bridge/platform_bridge.h
index af87864a77..63152f624c 100644
--- a/weex_core/Source/core/bridge/platform_bridge.h
+++ b/weex_core/Source/core/bridge/platform_bridge.h
@@ -114,7 +114,7 @@ class PlatformBridge {
         const char* instanceId, const char* nameSpace, const char* func,
         std::vector<VALUE_WITH_TYPE*>& params) = 0;
     virtual int CreateInstance(const char* instanceId, const char* func,
-                               const char* script, const char* opts,
+                               const char* script, int script_length, const char* opts,
                                const char* initData, const char* extendsApi,
                                const char* render_strategy) = 0;
     virtual std::unique_ptr<WeexJSResult> ExecJSOnInstance(const char* instanceId,
diff --git a/weex_core/Source/core/data_render/ast.h b/weex_core/Source/core/data_render/ast.h
index fc0c0ef91b..43a384237c 100644
--- a/weex_core/Source/core/data_render/ast.h
+++ b/weex_core/Source/core/data_render/ast.h
@@ -450,10 +450,10 @@ class CallExpression : public Expression {
 
  private:
   MemberAccessKind kind_;
-  Handle<Expression> expr_;
-  Handle<Expression> member_;
-  Handle<Expression> callee_;
-  Handle<Expression> args_expr_;
+  Handle<Expression> expr_{nullptr};
+  Handle<Expression> member_{nullptr};
+  Handle<Expression> callee_{nullptr};
+  Handle<Expression> args_expr_{nullptr};
   std::vector<Handle<Expression>> args_;
 };
 
@@ -572,9 +572,12 @@ class NewExpression : public Expression {
 
     Handle<Expression> member() { return member_; }
     bool ProduceRValue() override { return false; }
+    void set_is_class_(bool is_class) { is_class_ = is_class; };
+    bool is_class() { return is_class_; }
     DEFINE_NODE_TYPE(NewExpression, Expression);
 private:
     Handle<Expression> member_;
+    bool is_class_{false};
 };
     
 class ThisExpression : public Expression {
diff --git a/weex_core/Source/core/data_render/ast_factory.cc b/weex_core/Source/core/data_render/ast_factory.cc
index a134dc658a..a1742ee4d9 100644
--- a/weex_core/Source/core/data_render/ast_factory.cc
+++ b/weex_core/Source/core/data_render/ast_factory.cc
@@ -132,7 +132,7 @@ Handle<Expression> ASTFactory::NewNullConstant() {
 Handle<Expression> ASTFactory::NewCallExpression(MemberAccessKind kind, Handle<Expression> expr, Handle<Expression> member, std::vector<Handle<Expression>> args) {
     return MakeHandle<CallExpression>(kind, expr, member, args);
 }
-    
+        
 Handle<Expression> ASTFactory::NewCallExpression(Handle<Expression> func, std::vector<Handle<Expression>> args) {
   return MakeHandle<CallExpression>(func, args);
 }
@@ -165,6 +165,11 @@ Handle<Expression> ASTFactory::NewAssignExpression(Handle<Expression> lhs, Handl
 Handle<Expression> ASTFactory::NewIfStatement(Handle<Expression> condition, Handle<Expression> then) {
   return MakeHandle<IfStatement>(condition, then);
 }
+    
+Handle<Expression> ASTFactory::NewIfElseStatement(Handle<Expression> condition, Handle<Expression> then, Handle<Expression> els)
+{
+    return MakeHandle<IfElseStatement>(condition, then, els);
+}
 
 Handle<Expression> ASTFactory::NewUndefinedConstant(Position &loc, Scope *scope)
 {
diff --git a/weex_core/Source/core/data_render/ast_factory.h b/weex_core/Source/core/data_render/ast_factory.h
index 0f3f74785c..40c46b1361 100644
--- a/weex_core/Source/core/data_render/ast_factory.h
+++ b/weex_core/Source/core/data_render/ast_factory.h
@@ -67,7 +67,7 @@ class ASTFactory {
     virtual Handle<Expression> NewObjectConstant(ProxyObject obj);
     virtual Handle<Expression> NewAssignExpression(Handle<Expression> lhs, Handle<Expression> rhs);
     virtual Handle<Expression> NewIfStatement(Handle<Expression> condition, Handle<Expression> then);
-    
+    virtual Handle<Expression> NewIfElseStatement(Handle<Expression> condition, Handle<Expression> then, Handle<Expression> els);
     virtual Handle<ChunkStatement> NewChunkStatement(Position &loc, Scope *scope, Handle<ExpressionList> list);
     virtual Handle<Expression> NewLabelledStatement(Position &loc, Scope *scope, std::string label, Handle<Expression> expr);
     // create a new node representing undefined
diff --git a/weex_core/Source/core/data_render/binary_file.cc b/weex_core/Source/core/data_render/binary_file.cc
new file mode 100644
index 0000000000..989e9aeea8
--- /dev/null
+++ b/weex_core/Source/core/data_render/binary_file.cc
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+
+#include "core/data_render/binary_file.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+    BinaryFile* BinaryFile::g_instance_ = nullptr;
+
+    BinaryFile::BinaryFile():fout_(nullptr), position_(0), length_(0){
+    }
+
+    BinaryFile* BinaryFile::instance() {
+        if (!g_instance_) {
+            g_instance_ = new BinaryFile();
+        }
+        return g_instance_;
+    }
+
+    void BinaryFile::set_input(const char* input) {
+        input_ = input;
+    }
+
+    void BinaryFile::set_length(unsigned long length) {
+        length_ = length;
+    }
+
+    void BinaryFile::setWriteFileUrl(const std::string& url) {
+        fout_.reset(new std::ofstream(url, std::ios::binary));
+    }
+
+    void BinaryFile::write(const char *stream, unsigned count) {
+        fout_->write(stream, count);
+    }
+
+    void BinaryFile::read(char *stream, unsigned count) {
+        for (int i=0; i<count; i++) {
+            stream[i] = input_[position_++];
+        }
+    }
+
+    void BinaryFile::writeFinish() {
+        fout_->close();
+    }
+
+    void BinaryFile::readFinish() {
+        position_ = 0;
+        length_ = 0;
+        input_ = nullptr;
+    }
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
diff --git a/weex_core/Source/core/data_render/binary_file.h b/weex_core/Source/core/data_render/binary_file.h
new file mode 100644
index 0000000000..c6764469e5
--- /dev/null
+++ b/weex_core/Source/core/data_render/binary_file.h
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+#ifndef CORE_DATA_RENDER_BINARY_FILE_H_
+#define CORE_DATA_RENDER_BINARY_FILE_H_
+
+#include <fstream>
+#include <memory>
+
+namespace weex {
+namespace core {
+namespace data_render {
+    enum Section {
+        NULL_SECTION,
+        STRING_SECTION,
+        TABLE_SECTION,
+        FUNCTION_SECTION,
+        START_SECTION,
+        GLOBAL_SECTION,
+        STYLE_SECTION,
+        ARRAY_SECTION,
+        REF_SECTION,
+        CLASS_SECTION
+    };
+
+    class BinaryFile {
+    public:
+        static BinaryFile* instance();
+        void set_input(const char* input);
+        void set_length(unsigned long length);
+        void setWriteFileUrl(const std::string& url);
+        void write(const char *stream, unsigned count);
+        void read(char *stream, unsigned count);
+        void writeFinish();
+        void readFinish();
+        bool eof() {return length_ == position_;}
+    private:
+        BinaryFile();
+
+        static BinaryFile* g_instance_;
+        std::unique_ptr<std::ofstream> fout_;
+        const char* input_;
+        unsigned long position_;
+        unsigned long length_;
+    };
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
+#endif //CORE_DATA_RENDER_BINARY_FILE_H_
diff --git a/weex_core/Source/core/data_render/class.cc b/weex_core/Source/core/data_render/class.cc
index eb67c0d39b..f65cbb9434 100644
--- a/weex_core/Source/core/data_render/class.cc
+++ b/weex_core/Source/core/data_render/class.cc
@@ -44,6 +44,62 @@ void AddClassCFunc(ClassDescriptor *p_desc, const std::string& name, CFunction f
 ClassInstance *NewClassInstance(ClassDescriptor *p_desc) {
     return new ClassInstance(p_desc);
 }
+    
+Value *GetClassMember(ClassInstance *inst, std::string &name) {
+    Value *ret = nullptr;
+    do {
+        ClassInstance *inst_current = inst;
+        while (inst_current) {
+            Variables *funcs = inst_current->p_desc_->funcs_.get();
+            int index = funcs->IndexOf(name);
+            if (index < 0) {
+                Variables *vars = inst_current->vars_.get();
+                index = vars->IndexOf(name);
+                if (index >= 0) {
+                    ret = vars->Find(index);
+                }
+            }
+            else {
+                ret = funcs->Find(index);
+            }
+            if (ret) {
+                break;
+            }
+            // ęž„é€ å‡½ę•°äøę‰¾super
+            if (name == "constructor") {
+                break;
+            }
+            inst_current = inst_current->p_super_;
+        }
+        
+    } while (0);
+    
+    return ret;
+}
+
+Value *GetClassMemberVar(ClassInstance *inst, std::string &name) {
+    Value *ret = nullptr;
+    do {
+        Variables *funcs = inst->p_desc_->funcs_.get();
+        int index = funcs->IndexOf(name);
+        if (index < 0) {
+            Variables *vars = inst->vars_.get();
+            index = vars->IndexOf(name);
+            if (index < 0) {
+                Value var;
+                SetNil(&var);
+                index = vars->Add(name, var);
+            }
+            ret = vars->Find(index);
+        }
+        else {
+            ret = funcs->Find(index);
+        }
+        
+    } while (0);
+    
+    return ret;
+}
 
 }  // namespace data_render
 }  // namespace core
diff --git a/weex_core/Source/core/data_render/class.h b/weex_core/Source/core/data_render/class.h
index 1a194f662e..134b776811 100644
--- a/weex_core/Source/core/data_render/class.h
+++ b/weex_core/Source/core/data_render/class.h
@@ -38,6 +38,9 @@ void AddClassCFunc(ClassDescriptor *p_desc, const std::string& name, CFunction f
 
 ClassInstance *NewClassInstance(ClassDescriptor *p_desc);
     
+Value *GetClassMember(ClassInstance *inst, std::string &name);
+Value *GetClassMemberVar(ClassInstance *inst, std::string &name);
+
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/class_array.cc b/weex_core/Source/core/data_render/class_array.cc
index d2436ae62a..784d3722e2 100644
--- a/weex_core/Source/core/data_render/class_array.cc
+++ b/weex_core/Source/core/data_render/class_array.cc
@@ -74,6 +74,14 @@ int SetArray(Array *array, Value *index, const Value &val) {
     return ret;
 }
     
+void ClearArray(Array *array) {
+    array->items.clear();
+}
+    
+void PushArray(Array *array, Value val) {
+    array->items.push_back(val);
+}
+    
 int SetArray(Array *array, int index, const Value &val) {
     int ret = 0;
     do {
@@ -150,7 +158,7 @@ static Value forEach(ExecState *exec_state) {
             throw VMExecError("forEach caller isn't a Array");
         }
         Value *func = exec_state->GetArgument(1);
-        if (!IsFunc(func)) {
+        if (!IsFunction(func)) {
             throw VMExecError("forEach => isn't a function");
         }
         std::vector<Value> items = ValueTo<Array>(array)->items;
diff --git a/weex_core/Source/core/data_render/class_array.h b/weex_core/Source/core/data_render/class_array.h
index be954ee776..e74be75c3f 100644
--- a/weex_core/Source/core/data_render/class_array.h
+++ b/weex_core/Source/core/data_render/class_array.h
@@ -37,6 +37,8 @@ Value GetArrayValue(Array *array, const Value &index);
 Value* GetArrayVar(Array *array, const Value &index);
 Value GetArraySizeValue(Array *array);
 size_t GetArraySize(Array *array);
+void ClearArray(Array *array);
+void PushArray(Array *array, Value val);
 
 }  // namespace data_render
 }  // namespace core
diff --git a/weex_core/Source/core/data_render/class_factory.cc b/weex_core/Source/core/data_render/class_factory.cc
index 03db5155f8..bca5d9e8a8 100644
--- a/weex_core/Source/core/data_render/class_factory.cc
+++ b/weex_core/Source/core/data_render/class_factory.cc
@@ -7,6 +7,7 @@
 #include "core/data_render/class_array.h"
 #include "core/data_render/class_string.h"
 #include "core/data_render/class_json.h"
+#include "core/data_render/class_object.h"
 #include "core/data_render/table.h"
 
 namespace weex {
@@ -18,6 +19,7 @@ Value ClassFactory::CreateClassDescriptor(ClassDescriptor *p_super) {
     Value value;
     SetCDValue(&value, reinterpret_cast<GCObject *>(desc));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(desc), value.type));
+    descs_.push_back(desc);
     return value;
 }
     
@@ -26,6 +28,7 @@ Value ClassFactory::CreateArray() {
     Value value;
     SetAValue(&value, reinterpret_cast<GCObject *>(array));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(array), value.type));
+    arrays_.push_back(array);
     return value;
 }
     
@@ -34,6 +37,7 @@ Value ClassFactory::CreateTable() {
     Value value;
     SetTValue(&value, reinterpret_cast<GCObject *>(table));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(table), value.type));
+    tables_.push_back(table);
     return value;
 }
     
@@ -42,6 +46,7 @@ Value ClassFactory::ClassString() {
     Value value;
     SetCDValue(&value, reinterpret_cast<GCObject *>(desc));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(desc), value.type));
+    descs_.push_back(desc);
     return value;
 }
     
@@ -50,6 +55,7 @@ Value ClassFactory::ClassJSON() {
     Value value;
     SetCDValue(&value, reinterpret_cast<GCObject *>(desc));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(desc), value.type));
+    descs_.push_back(desc);
     return value;
 }
     
@@ -58,9 +64,30 @@ Value ClassFactory::ClassArray() {
     Value value;
     SetCDValue(&value, reinterpret_cast<GCObject *>(desc));
     stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(desc), value.type));
+    descs_.push_back(desc);
     return value;
 }
     
+Value ClassFactory::ClassObject() {
+    ClassDescriptor *desc = NewClassOject();
+    Value value;
+    SetCDValue(&value, reinterpret_cast<GCObject *>(desc));
+    stores_.push_back(std::make_pair(reinterpret_cast<GCObject *>(desc), value.type));
+    descs_.push_back(desc);
+    return value;
+}
+    
+int ClassFactory::findDesc(const ClassDescriptor *desc) {
+    int index = 0;
+    for (auto d : descs_) {
+        if (desc == d) {
+            return index;
+        }
+        index++;
+    }
+    return -1;
+}
+
 ClassInstance *ClassFactory::CreateClassInstanceFromSuper(ClassDescriptor *p_desc) {
     ClassInstance *p_super = nullptr;
     ClassInstance *inst = NewClassInstance(p_desc);
diff --git a/weex_core/Source/core/data_render/class_factory.h b/weex_core/Source/core/data_render/class_factory.h
index 78bf0b259f..5a09922c63 100644
--- a/weex_core/Source/core/data_render/class_factory.h
+++ b/weex_core/Source/core/data_render/class_factory.h
@@ -38,13 +38,25 @@ class ClassFactory {
     virtual Value ClassArray();
     virtual Value ClassString();
     virtual Value ClassJSON();
+    virtual Value ClassObject();
     virtual Value CreateArray();
     virtual Value CreateTable();
+    int findDesc(const ClassDescriptor *desc);
+    inline const std::vector<std::pair<GCObject *, Value::Type>>& stores() {return stores_;}
+    inline std::vector<Array *> arrays() {return arrays_;}
+    inline std::vector<ClassDescriptor *> descs() {return descs_;}
+    inline std::vector<Table *> tables() {return tables_;}
+
     ~ClassFactory();
     
 private:
     ClassInstance *CreateClassInstanceFromSuper(ClassDescriptor *p_desc);
     std::vector<std::pair<GCObject *, Value::Type>> stores_;
+
+    //for binary encode and decode
+    std::vector<ClassDescriptor *> descs_;
+    std::vector<Array *> arrays_;
+    std::vector<Table *> tables_;
 };
 
 }
diff --git a/weex_core/Source/core/data_render/class_object.cc b/weex_core/Source/core/data_render/class_object.cc
new file mode 100644
index 0000000000..a77cc60c3d
--- /dev/null
+++ b/weex_core/Source/core/data_render/class_object.cc
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+#include <algorithm>
+#include "core/data_render/class.h"
+#include "core/data_render/class_object.h"
+#include "core/data_render/exec_state.h"
+#include "core/data_render/common_error.h"
+#include "core/data_render/table.h"
+#include "core/data_render/class_array.h"
+#include <base/LogDefines.h>
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+static Value keys(ExecState *exec_state);
+
+ClassDescriptor *NewClassOject() {
+    ClassDescriptor *object_desc = new ClassDescriptor(nullptr);
+    AddClassStaticCFunc(object_desc, "keys", keys);
+    return object_desc;
+}
+    
+static Value keys(ExecState *exec_state) {
+    Value ret = exec_state->class_factory()->CreateArray();
+    do {
+        size_t length = exec_state->GetArgumentCount();
+        if (length < 1) {
+            break;
+        }
+        Value *value = exec_state->GetArgument(0);
+        if (!IsArray(value) && !IsTable(value)) {
+            throw VMExecError("Object.keys caller isn't a Array or Table");
+        }
+        if (IsTable(value)) {
+            std::vector<std::string> keys = GetTableKeys(ValueTo<Table>(value));
+            Array *array = ValueTo<Array>(&ret);
+            for (int i = 0; i < keys.size(); i++) {
+                SetArray(array, i, exec_state->string_table()->StringFromUTF8(keys[i]));
+            }
+        }
+        
+    } while (0);
+    
+    return ret;
+}
+    
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
diff --git a/weex_core/Source/core/data_render/class_object.h b/weex_core/Source/core/data_render/class_object.h
new file mode 100644
index 0000000000..8467d8b25b
--- /dev/null
+++ b/weex_core/Source/core/data_render/class_object.h
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+//
+// Created by pentao.pt on 2018/7/25.
+//
+
+#ifndef DATA_RENDER_OBJECT_CLASS_H
+#define DATA_RENDER_OBJECT_CLASS_H
+
+#include "core/data_render/object.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+        
+ClassDescriptor *NewClassOject();
+    
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
+
+#endif  // DATA_RENDER_OBJECT_CLASS_H
diff --git a/weex_core/Source/core/data_render/class_string.cc b/weex_core/Source/core/data_render/class_string.cc
index 1ce308f647..9a518fe11f 100644
--- a/weex_core/Source/core/data_render/class_string.cc
+++ b/weex_core/Source/core/data_render/class_string.cc
@@ -34,33 +34,29 @@ namespace data_render {
 
 static Value split(ExecState *exec_state);
 static Value trim(ExecState* exec_state);
+static Value indexOf(ExecState* exec_state);
 
 ClassDescriptor *NewClassString() {
     ClassDescriptor *array_desc = new ClassDescriptor(nullptr);
     AddClassCFunc(array_desc, "split", split);
     AddClassCFunc(array_desc, "trim", trim);
+    AddClassCFunc(array_desc, "indexOf", indexOf);
     return array_desc;
 }
     
-std::vector<std::string> split_string(std::string srcStr, std::string delimStr, bool repeatedCharIgnored)
+template <class Container>
+void split_string(const std::string& str, Container& container, const std::string& delims = " ")
 {
-    std::vector<std::string> resultStringVector;
-    std::replace_if(srcStr.begin(), srcStr.end(), [&](const char& c){if(delimStr.find(c)!=std::string::npos){return true;}else{return false;}}/*pred*/, delimStr.at(0));//将å‡ŗēŽ°ēš„ę‰€ęœ‰åˆ†éš”ē¬¦éƒ½ę›æę¢ęˆäøŗäø€äøŖē›ø同ēš„å­—ē¬¦ļ¼ˆåˆ†éš”ē¬¦å­—ē¬¦äø²ēš„ē¬¬äø€äøŖļ¼‰
-    size_t pos=srcStr.find(delimStr.at(0));
-    std::string addedString="";
-    while (pos!=std::string::npos) {
-        addedString=srcStr.substr(0,pos);
-        if (!addedString.empty()||!repeatedCharIgnored) {
-            resultStringVector.push_back(addedString);
-        }
-        srcStr.erase(srcStr.begin(), srcStr.begin()+pos+1);
-        pos=srcStr.find(delimStr.at(0));
+    std::size_t current, previous = 0;
+    current = str.find(delims);
+    while (current != std::string::npos) {
+        container.push_back(str.substr(previous, current - previous));
+        previous = current + delims.length();
+        current = str.find(delims, previous);
     }
-    addedString=srcStr;
-    if (!addedString.empty()||!repeatedCharIgnored) {
-        resultStringVector.push_back(addedString);
+    if (str.length() > previous) {
+        container.push_back(str.substr(previous, str.length() - previous));
     }
-    return resultStringVector;
 }
  
 static Value split(ExecState *exec_state) {
@@ -80,7 +76,8 @@ static Value split(ExecState *exec_state) {
         }
         std::string src = CStringValue(string);
         std::string delim = CStringValue(split);
-        std::vector<std::string> split_array = split_string(src, delim, true);
+        std::vector<std::string>split_array;
+        split_string<std::vector<std::string>>(src, split_array, delim);
         Array *array = ValueTo<Array>(&ret);
         for (int i = 0; i < split_array.size(); i++) {
             Value string_value = exec_state->string_table()->StringFromUTF8(split_array[i]);
@@ -186,7 +183,29 @@ Value encodeURIComponent(ExecState *exec_state) {
     }
     return exec_state->string_table()->StringFromUTF8(dst);
 }
-    
+
+Value indexOf(ExecState* exec_state) {
+    size_t length = exec_state->GetArgumentCount();
+    if (length != 2) {
+        throw VMExecError("trim caller args wrong");
+    }
+
+    Value* string = exec_state->GetArgument(0);
+    Value* subs = exec_state->GetArgument(1);
+    if (!IsString(string) || !IsString(subs)) {
+        throw VMExecError("trim caller isn't a string");
+    }
+
+    std::string src = CStringValue(string);
+    std::string sub_src = CStringValue(subs);
+
+    auto pos = src.find(sub_src);
+    if (pos == std::string::npos) {
+        return Value(-1);
+    }
+
+    return Value(static_cast<int64_t>(pos));
+}
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/code_generator.cc b/weex_core/Source/core/data_render/code_generator.cc
index 9668919d46..bfb7ba5988 100644
--- a/weex_core/Source/core/data_render/code_generator.cc
+++ b/weex_core/Source/core/data_render/code_generator.cc
@@ -342,12 +342,15 @@ void CodeGenerator::Visit(IfElseStatement *node, void *data) {
     
 void CodeGenerator::Visit(ContinueStatement *node, void *data) {
     do {
-        int for_start_index = block_->for_start_index();
-        if (for_start_index < 0) {
-            throw GeneratorError("continue must in for statement");
-            break;
+        FuncState *func_state = func_->func_state();
+        int for_update_index = block_->for_update_index();
+        if (for_update_index >= 0) {
+            func_state->AddInstruction(CREATE_Ax(OP_GOTO, for_update_index));
+        }
+        else {
+            auto slot = func_state->AddInstruction(0);
+            block_->for_continue_slots().push_back(slot);
         }
-        func_->func_state()->AddInstruction(CREATE_Ax(OP_GOTO, for_start_index));
         
     } while (0);
 }
@@ -355,6 +358,7 @@ void CodeGenerator::Visit(ContinueStatement *node, void *data) {
 void CodeGenerator::Visit(ForStatement *node, void *data) {
     BlockScope for_scope(this);  // for var index = 0;
     FuncState *func_state = func_->func_state();
+    block_->set_is_loop(true);
     long condition = block_->NextRegisterId();
     if (node->init().get() != NULL) {
         node->init()->Accept(this, node->kind() == ForKind::kForIn ? &condition : nullptr);
@@ -370,17 +374,25 @@ void CodeGenerator::Visit(ForStatement *node, void *data) {
     if (node->condition().get() != NULL) {
         node->condition()->Accept(this, &condition);
     }
-    auto slot = func_->func_state()->AddInstruction(0);
+    auto slot = func_state->AddInstruction(0);
     if (node->body().get() != NULL) {
         node->body()->Accept(this, nullptr);
     }
+    int for_update_index = condition_start_index;
     if (node->update().get() != NULL) {
+        for_update_index = (int)func_state->instructions().size();  // aka next one.
         long update = block_->NextRegisterId();
         node->update()->Accept(this, &update);
     }
+    block_->set_for_update_index(for_update_index);
     func_state->AddInstruction(CREATE_Ax(OP_GOTO, condition_start_index));
     int for_end_index = (int)func_->func_state()->instructions().size() - 1;
     func_state->ReplaceInstruction(slot, (CREATE_ABx(OP_JMP, condition, for_end_index - slot)));
+    std::vector<size_t> for_contiue_slots = block_->for_continue_slots();
+    for (int i = 0; i < for_contiue_slots.size(); i++) {
+        func_state->ReplaceInstruction(for_contiue_slots[i], CREATE_Ax(OP_GOTO, for_update_index));
+    }
+    for_contiue_slots.clear();
 }
 
 void CodeGenerator::Visit(BlockStatement* node, void* data) {
@@ -410,7 +422,8 @@ void CodeGenerator::Visit(FunctionStatement *node, void *data) {
             value.f = func_->func_state();
             value.type = Value::FUNC;
             ClassDescriptor *class_desc = ValueTo<ClassDescriptor>(class_->class_value());
-            class_desc->funcs_->Add(proto->GetName(), value);
+            class_desc->funcs_->Add(proto->GetName(), value);            
+            func_->func_state()->set_is_class_func(is_class_func);
         }
         // skip func value in the fornt of stack;
         block_->NextRegisterId();
@@ -470,21 +483,46 @@ void CodeGenerator::Visit(ThisExpression *node, void *data) {
     
 void CodeGenerator::Visit(ArrowFunctionStatement *node, void *data) {
     RegisterScope register_scope(block_);
-    long ret = data == nullptr ? block_->NextRegisterId()
-    : *static_cast<long *>(data);
+    long ret = data == nullptr ? block_->NextRegisterId() : *static_cast<long *>(data);
+    bool is_class_func = func_->parent() == nullptr && class_ ? true : false;
     // body
     // Slot
     auto slot = func_->func_state()->AddInstruction(0);
     {
         FuncScope scope(this);
+        if (is_class_func) {
+            Value value;
+            value.f = func_->func_state();
+            value.type = Value::FUNC;
+            ClassDescriptor *class_desc = ValueTo<ClassDescriptor>(class_->class_value());
+            if (node->name().size() > 0) {
+                class_desc->funcs_->Add(node->name(), value);
+            }
+            func_->func_state()->set_is_class_func(is_class_func);
+        }
         // skip func value in the fornt of stack;
         block_->NextRegisterId();
-
+        // make arguments var in thie front of stack;
+        if (is_class_func) {
+            block_->AddVariable("this", block_->NextRegisterId());
+        }
         // make arguments var in thie front of stack;
         for (int i = 0; i < node->args().size(); i++) {
-            assert(node->args()[i]->IsIdentifier());
-            std::string arg = node->args()[i]->AsIdentifier()->GetName();
-            block_->AddVariable(arg, block_->NextRegisterId());
+            if (node->args()[i]->IsIdentifier()) {
+                std::string arg = node->args()[i]->AsIdentifier()->GetName();
+                block_->AddVariable(arg, block_->NextRegisterId());
+            }
+            else if (node->args()[i]->IsCommaExpression()) {
+                Handle<ExpressionList> arg_list = node->args()[i]->AsCommaExpression()->exprs();
+                for (int j = 0; j < arg_list->Size(); j++) {
+                    std::string arg = arg_list->raw_list()[j]->AsIdentifier()->GetName();
+                    block_->AddVariable(arg, block_->NextRegisterId());
+                }
+            }
+            else {
+                // force to error
+                throw GeneratorError("arrow function only supporting args list");
+            }
         }
         if (node->body()->IsJSXNodeExpression()) {
             long return1 = block_->NextRegisterId();
@@ -497,14 +535,16 @@ void CodeGenerator::Visit(ArrowFunctionStatement *node, void *data) {
     }
     // associate function_name and function_state
     if (func_->parent() == nullptr) {
-        // in chunk
-        Value value;
-        assert(data);
-        value.f = func_->func_state()->GetChild(func_->func_state()->children().size() - 1);
-        value.type = Value::FUNC;
-        int index = exec_state_->global()->Add(value);
-        if (index >= 0) {
-            func_->func_state()->AddInstruction(CREATE_ABx(OP_GETGLOBAL, ret, index));
+        if (!is_class_func) {
+            // in chunk
+            Value value;
+            assert(data);
+            value.f = func_->func_state()->GetChild(func_->func_state()->children().size() - 1);
+            value.type = Value::FUNC;
+            int index = exec_state_->global()->Add(value);
+            if (index >= 0) {
+                func_->func_state()->AddInstruction(CREATE_ABx(OP_GETGLOBAL, ret, index));
+            }
         }
     }
     else {
@@ -563,14 +603,21 @@ void CodeGenerator::Visit(NewExpression *node, void *data) {
             FuncState *state = func_->func_state();
             long rhs = block_->FindRegisterId(node->member()->AsIdentifier()->GetName());
             if (rhs >= 0) {
-                state->AddInstruction(CREATE_ABC(OP_MOVE, lhs, rhs, 0));
+                if (node->is_class()) {
+                    state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC, rhs));
+                }
+                else {
+                    state->AddInstruction(CREATE_ABC(OP_MOVE, lhs, rhs, 0));
+                }
                 break;
             }
             int index = exec_state_->global()->IndexOf(node->member()->AsIdentifier()->GetName());
             if (index >= 0) {
                 Value *value = exec_state_->global()->Find(index);
                 if (IsClass(value)) {
-                    state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC ,index));
+                    rhs = block_->NextRegisterId();
+                    state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, rhs, index));
+                    state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC, rhs));
                 }
                 else {
                     state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, lhs, index));
@@ -666,6 +713,30 @@ void CodeGenerator::Visit(BinaryExpression *node, void *data) {
             func_state->AddInstruction(CREATE_ABC(OP_ADD, ret, left, right));
             break;
         }
+        case BinaryOperation::kSubtraction:
+        {
+            // a - b
+            func_state->AddInstruction(CREATE_ABC(OP_SUB, ret, left, right));
+            break;
+        }
+        case BinaryOperation::kMultiplication:
+        {
+            // a * b
+            func_state->AddInstruction(CREATE_ABC(OP_MUL, ret, left, right));
+            break;
+        }
+        case BinaryOperation::kDivision:
+        {
+            // a / b
+            func_state->AddInstruction(CREATE_ABC(OP_DIV, ret, left, right));
+            break;
+        }
+        case BinaryOperation::kMod:
+        {
+            // a % b
+            func_state->AddInstruction(CREATE_ABC(OP_MOD, ret, left, right));
+            break;
+        }
         case BinaryOperation::kLessThan:
         {
             func_state->AddInstruction(CREATE_ABC(OP_LT, ret, left, right));
@@ -1128,17 +1199,53 @@ bool CodeGenerator::BlockCnt::FindVariable(const std::string &name) {
 }
     
 int CodeGenerator::BlockCnt::for_start_index() {
-    if (for_start_index_ >= 0) {
+    if (is_loop()) {
         return for_start_index_;
     }
     if (parent() != nullptr) {
-        if (parent()->func_state() == func_state_) {
+        if (parent()->is_loop()) {
             return parent()->for_start_index();
         }
     }
     return -1;
 }
     
+std::vector<size_t>& CodeGenerator::BlockCnt::for_continue_slots() {
+    if (is_loop()) {
+        return for_continue_slots_;
+    }
+    if (parent() != nullptr) {
+        if (parent()->is_loop()) {
+            return parent()->for_continue_slots_;
+        }
+    }
+    return for_continue_slots_;
+}
+    
+std::vector<size_t>& CodeGenerator::BlockCnt::for_break_slots() {
+    if (is_loop()) {
+        return for_break_slots_;
+    }
+    if (parent() != nullptr) {
+        if (parent()->is_loop()) {
+            return parent()->for_break_slots_;
+        }
+    }
+    return for_break_slots_;
+}
+
+int CodeGenerator::BlockCnt::for_update_index() {
+    if (is_loop()) {
+        return for_update_index_;
+    }
+    if (parent() != nullptr) {
+        if (parent()->is_loop()) {
+            return parent()->for_update_index();
+        }
+    }
+    return -1;
+}
+
 void CodeGenerator::BlockCnt::reset() {
     for (int i = 0; i < reg_refs_.size(); i++) {
         if (func_state()) {
diff --git a/weex_core/Source/core/data_render/code_generator.h b/weex_core/Source/core/data_render/code_generator.h
index b976acfef5..b1a9aaa407 100644
--- a/weex_core/Source/core/data_render/code_generator.h
+++ b/weex_core/Source/core/data_render/code_generator.h
@@ -93,7 +93,7 @@ class CodeGenerator : public ASTVisitor {
 
   class BlockCnt : public Node<BlockCnt> {
    public:
-    BlockCnt() : reg_refs_(), variables_(), idx_(0), is_loop_(false) {}
+    BlockCnt() : for_continue_slots_(), for_break_slots_(), reg_refs_(), variables_(), idx_(0), is_loop_(false) {}
     ~BlockCnt() {}
 
     inline long NextRegisterId() { return idx_++; }
@@ -113,14 +113,18 @@ class CodeGenerator : public ASTVisitor {
     
     inline ExecState *exec_state() { return exec_state_; }
     int for_start_index();
+    int for_update_index();
+    std::vector<size_t>& for_continue_slots();
+    std::vector<size_t>& for_break_slots();
     void set_for_start_index(int index) { for_start_index_ = index; }
-    inline std::vector<int>& for_break_slots() { return for_break_slots_; }
+    void set_for_update_index(int index) { for_update_index_ = index; }
     inline std::unordered_map<std::string, long> &variables() {
       return variables_;
     }
     inline void set_idx(int idx) { idx_ = idx; }
     inline int idx() { return idx_; }
     inline bool is_loop() { return is_loop_; }
+    inline void set_is_loop(bool is_loop) { is_loop_ = is_loop; }
     inline std::vector<long>& reg_refs() { return reg_refs_; }
     inline bool& is_register_scope() { return is_register_scope_; }
     void reset();
@@ -135,7 +139,9 @@ class CodeGenerator : public ASTVisitor {
     FuncState *func_state_{nullptr};
     ExecState *exec_state_{nullptr};
     int for_start_index_{-1};
-    std::vector<int> for_break_slots_;
+    int for_update_index_{-1};
+    std::vector<size_t> for_break_slots_;
+    std::vector<size_t> for_continue_slots_;
   };
 
   class FuncCnt : public Node<FuncCnt> {
diff --git a/weex_core/Source/core/data_render/exec_state.cc b/weex_core/Source/core/data_render/exec_state.cc
index 947e85d04c..9e253222c4 100644
--- a/weex_core/Source/core/data_render/exec_state.cc
+++ b/weex_core/Source/core/data_render/exec_state.cc
@@ -26,6 +26,8 @@
 #include "core/data_render/rax_parser.h"
 #include "core/data_render/rax_parser_context.h"
 #include "core/data_render/common_error.h"
+#include "core/data_render/binary_file.h"
+#include "core/data_render/class_array.h"
 
 #if DEBUG
 #include "core/data_render/monitor/vm_monitor.h"
@@ -106,9 +108,9 @@ void ExecState::Execute(std::string& err) {
   Value chunk;
   chunk.type = Value::Type::FUNC;
   chunk.f = func_state_.get();
-  *stack_->base() = chunk;
+  **stack_->top() = chunk;
   try {
-      CallFunction(stack_->base(), 0, nullptr);
+      CallFunction(*stack_->top(), 0, nullptr);
   } catch (std::exception &e) {
       auto error = static_cast<Error *>(&e);
       if (error) {
@@ -119,23 +121,840 @@ void ExecState::Execute(std::string& err) {
   }
 }
 
-const Value ExecState::Call(const std::string& func_name,
-                             const std::vector<Value>& params) {
-  Value ret;
-  auto it = global_variables_.find(func_name);
-  if (it != global_variables_.end()) {
-    long reg = it->second;
-    Value* function = *stack_->top() + 1;
-    *function = *(stack_->base() + reg);
-    for (int i = 0; i < params.size(); ++i) {
-      *(function + i + 1) = params[i];
+void ExecState::startEncode() {
+    BinaryFile* file = BinaryFile::instance();
+
+    int magic_number = 0x6d736100;
+    unsigned version = 1;
+    file->write((char*)&magic_number, sizeof(int));
+    file->write((char*)&version, sizeof(unsigned));
+
+    encodeStringSection();
+    encodeTableSection();
+    encodeFunctionSection();
+    encodeStartSection();
+    encodeGlobalSection();
+    encodeStyleSection();
+    encodeArraySection();
+    encodeRefSection();
+    encodeClassSection();
+}
+
+void ExecState::encodeStringSection() {
+    unsigned id = Section::STRING_SECTION; //string_section
+
+    const std::vector<std::pair<std::string, std::unique_ptr<String>>>& store = string_table_->store();
+    unsigned size = static_cast<unsigned>(store.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+    for (auto &mapString : store) {
+        unsigned length = static_cast<unsigned int>(mapString.first.length()) + 1;
+        file->write(mapString.first.c_str(), static_cast<unsigned int>(sizeof(char) * length));
+    }
+}
+
+void ExecState::encodeArraySection() {
+    unsigned id = Section::ARRAY_SECTION;
+    std::vector<Array*> arrays = class_factory_->arrays();
+    unsigned size = static_cast<unsigned>(arrays.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+    for (auto array : arrays) {
+        unsigned itemSize = static_cast<unsigned>(array->items.size());
+        file->write((char*)&itemSize, sizeof(unsigned));
+        for (auto &value : array->items) {
+            encodeValue(value);
+        }
+    }
+}
+
+void ExecState::encodeTableSection() {
+    unsigned id = Section::TABLE_SECTION;
+    std::vector<Table *> tables = class_factory_->tables();
+
+    unsigned size = static_cast<unsigned>(tables.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+
+    for (auto table : tables) {
+        unsigned mapSize = static_cast<unsigned>(table->map.size());
+        file->write((char*)&mapSize, sizeof(unsigned));
+        for (auto &map : table->map) {
+            std::string name = map.first;
+            Value value = map.second;
+            String str(name);
+            unsigned length = static_cast<unsigned>(str.length()) + 1;
+            file->write(str.c_str(), static_cast<unsigned>(sizeof(char) * length));
+            encodeValue(value);
+        }
+    }
+}
+
+void ExecState::encodeFunctionSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned id = Section::FUNCTION_SECTION;
+
+    FuncState* func_state_base = func_state_.get();
+    std::vector<FuncState*> children = func_state_base->getAllChildren();
+    std::vector<FuncState*> func_states;
+    func_states.push_back(func_state_base);
+    for (auto &func : children) {
+        func_states.push_back(func);
+    }
+    unsigned size = static_cast<unsigned>(func_states.size());
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+
+    for (auto &func_state : func_states) {
+        auto it = std::find(func_states.begin(), func_states.end(), func_state->super_func());
+        int super_index = -1;
+        if (it != func_states.end()) {
+            super_index = static_cast<int>(it - func_states.begin());
+        }
+        file->write((char*)&super_index, sizeof(int));
+        unsigned opcodeSize = static_cast<unsigned>(func_state->instructions().size());
+        file->write((char*)&opcodeSize, sizeof(unsigned));
+        for (int i=0; i<opcodeSize; i++) {
+            unsigned opcode = static_cast<unsigned>(func_state->instructions()[i]);
+            file->write((char*)&opcode, sizeof(unsigned));
+        }
+
+        unsigned constantSize = static_cast<unsigned>(func_state->GetConstantSize());
+        file->write((char*)&constantSize, sizeof(unsigned));
+        for (int i=0; i<constantSize; i++) {
+            encodeValue(*(func_state->GetConstant(i)));
+        }
+    }
+}
+
+void ExecState::encodeStartSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned id = Section::START_SECTION;
+    unsigned index = 0;
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&index, sizeof(unsigned));
+}
+
+void ExecState::encodeGlobalSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned id = Section::GLOBAL_SECTION;
+    unsigned size = static_cast<unsigned>(global_->size()) - global_->register_size();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+    int init_data_index = global_->IndexOf("_init_data");
+    int weex_data_index = global_->IndexOf("__weex_data__");
+    file->write((char*)&init_data_index, sizeof(int));
+    file->write((char*)&weex_data_index, sizeof(int));
+
+    for (int i=global_->register_size(); i<global_->size(); i++) {
+        Value* value = global_->Find(i);
+        encodeValue(*value);
+    }
+}
+
+void ExecState::encodeStyleSection() {
+    unsigned id = Section::STYLE_SECTION;
+    std::map<std::string, json11::Json>& styles = render_context_->style_json();
+
+    unsigned size = static_cast<unsigned>(styles.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+
+    for (auto style : styles) {
+        Value value(string_table()->StringFromUTF8(style.first));
+        encodeValue(value);
+        const json11::Json::object& items = style.second.object_items();
+        unsigned itemsSize = static_cast<unsigned>(items.size());
+        file->write((char*)&itemsSize, sizeof(unsigned));
+        for (auto it = items.begin(); it != items.end(); it++) {
+            unsigned length = static_cast<unsigned>(it->first.length()) + 1;
+            file->write(it->first.c_str(), static_cast<unsigned int>(sizeof(char) * length));
+
+            unsigned strLen = static_cast<unsigned int>(it->second.string_value().length()) + 1;
+            file->write(it->second.string_value().c_str(), static_cast<unsigned int>(sizeof(char) * strLen));
+        }
+    }
+}
+
+void ExecState::encodeRefSection() {
+    unsigned id = Section::REF_SECTION;
+    unsigned size = static_cast<unsigned>(refs_.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+    for (auto ref : refs_) {
+        Value value;
+        value.type = Value::Type::FUNC;
+        value.f = ref->func_state_;
+        encodeValue(value);
+        long register_id = ref->register_id();
+        file->write((char*)&register_id, sizeof(long));
+        encodeValue(ref->value_);
+    }
+}
+
+void ExecState::encodeClassSection() {
+    unsigned id = Section::CLASS_SECTION;
+    std::vector<ClassDescriptor *> descs = class_factory_->descs();
+
+    unsigned size = static_cast<unsigned>(descs.size());
+    BinaryFile* file = BinaryFile::instance();
+
+    file->write((char*)&id, sizeof(unsigned));
+    file->write((char*)&size, sizeof(unsigned));
+
+    int count = 0;
+    for (auto desc : descs) {
+        count++;
+        if (count <= 3) {
+            continue;
+        }
+
+        int superIndex = class_factory_->findDesc(desc->p_super_);
+        file->write((char*)&superIndex, sizeof(int));
+        unsigned static_func_size = static_cast<unsigned>(desc->static_funcs_->size());
+        file->write((char*)&static_func_size, sizeof(unsigned));
+        for (int i=0; i<static_func_size; i++) {
+            Value* value = desc->static_funcs_->Find(i);
+            encodeValue(*value);
+
+            unsigned length = 0;
+            for (auto &item : desc->static_funcs_->map()) {
+                if (item.second == i) {
+                    length = static_cast<unsigned>(item.first.length()) + 1;
+                    file->write((char*)&length, sizeof(unsigned));
+                    file->write(item.first.c_str(), static_cast<unsigned int>(sizeof(char) * length));
+                    break;
+                }
+            }
+            if (length == 0) {
+                file->write((char*)&length, sizeof(unsigned));
+            }
+        }
+
+        unsigned class_func_size = static_cast<unsigned>(desc->funcs_->size());
+        file->write((char*)&class_func_size, sizeof(unsigned));
+        for (int i=0; i<class_func_size; i++) {
+            Value* value = desc->funcs_->Find(i);
+            encodeValue(*value);
+
+            unsigned length = 0;
+            for (auto &item : desc->funcs_->map()) {
+                if (item.second == i) {
+                    length = static_cast<unsigned>(item.first.length()) + 1;
+                    file->write((char*)&length, sizeof(unsigned));
+                    file->write(item.first.c_str(), static_cast<unsigned int>(sizeof(char) * length));
+                    break;
+                }
+            }
+            if (length == 0) {
+                file->write((char*)&length, sizeof(unsigned));
+            }
+        }
+    }
+}
+
+void ExecState::encodeValue(const Value &value) {
+    BinaryFile* file = BinaryFile::instance();
+    file->write((char*)&value.type, sizeof(unsigned));
+
+    if (value.type == Value::Type::TABLE) {
+        std::vector<Table *> tables = class_factory_->tables();
+        int payload = 0;
+        for (auto table : tables) {
+            if (value.gc == reinterpret_cast<GCObject *>(table)) {
+                break;
+            }
+            payload++;
+        }
+        file->write((char*)&payload, sizeof(int));
+    }
+
+    if (value.type == Value::Type::STRING) {
+        //int payload = static_cast<int>(strings.size());
+        int payload = 0;
+        for (auto &store : string_table_->store() ) {
+            if (value.str == store.second.get()) {
+                // printf("---- %s  \n", str.get()->c_str());
+                break;
+            }
+            payload++;
+        }
+        file->write((char*)&payload, sizeof(int));
+    }
+
+    if (value.type == Value::Type::INT) {
+        file->write((char*)&value.i, sizeof(int64_t));
+    }
+
+    if (value.type == Value::Type::NUMBER) {
+        file->write((char*)&value.n, sizeof(double));
+    }
+
+    if (value.type == Value::Type::BOOL) {
+        file->write((char*)&value.b, sizeof(char));
+    }
+
+    if (value.type == Value::Type::FUNC) {
+        FuncState* func_state_base = func_state_.get();
+        const std::vector<FuncState*> &children = func_state_base->getAllChildren();
+        std::vector<FuncState*> func_states;
+        func_states.push_back(func_state_base);
+        for (auto &func : children) {
+            func_states.push_back(func);
+        }
+
+        int payload = 0;
+        for (auto func_state : func_states) {
+            if (value.f == func_state) {
+                break;
+            }
+            payload++;
+        }
+        file->write((char*)&payload, sizeof(int));
+    }
+
+    if (value.type == Value::Type::ARRAY) {
+        std::vector<Array*> arrays = class_factory_->arrays();
+        int payload = 0;
+        for (auto array : arrays ) {
+            if (value.gc == reinterpret_cast<GCObject *>(array)) {
+                break;
+            }
+            payload++;
+        }
+        file->write((char*)&payload, sizeof(int));
+    }
+
+    if (value.type == Value::Type::CLASS_DESC) {
+        int payload = 0;
+        std::vector<ClassDescriptor *> descs = class_factory_->descs();
+        for (auto desc : descs) {
+            if (value.gc == reinterpret_cast<GCObject *>(desc)) {
+                break;
+            }
+            payload++;
+        }
+        file->write((char*)&payload, sizeof(int));
+    }
+}
+
+void ExecState::endEncode() {
+    BinaryFile* file = BinaryFile::instance();
+    file->writeFinish();
+}
+
+bool ExecState::startDecode() {
+    ValueRef::gs_ref_id = 0;
+
+    BinaryFile* file = BinaryFile::instance();
+    int magic_number;
+    file->read((char*)&magic_number, sizeof(int));
+    if (magic_number != 0x6d736100) {
+        return false;
+    }
+    unsigned version;
+    file->read((char*)&version, sizeof(unsigned));
+    if (version != 1) {
+        return false;
+    }
+
+    while (!file->eof()) {
+        Section section_id = NULL_SECTION;
+        file->read((char*)&section_id, sizeof(unsigned));
+        switch (section_id) {
+            case STRING_SECTION:
+                decodeStringSection();
+                break;
+            case TABLE_SECTION:
+                decodeTableSection();
+                break;
+            case FUNCTION_SECTION:
+                decodeFunctionSection();
+                break;
+            case START_SECTION:
+                decodeStartSection();
+                break;
+            case GLOBAL_SECTION:
+                decodeGlobalSection();
+                break;
+            case STYLE_SECTION:
+                decodeStyleSection();
+                break;
+            case ARRAY_SECTION:
+                decodeArraySection();
+                break;
+            case REF_SECTION:
+                decodeRefSection();
+                break;
+            case CLASS_SECTION:
+                decodeClassSection();
+                break;
+            default:
+                break;
+        }
+    }
+    return true;
+}
+
+void ExecState::decodeStringSection()
+{
+    BinaryFile* file = BinaryFile::instance();
+
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    if (count == 0) {
+        return;
+    }
+
+    for (int i=0; i<count; i++) {
+        std::string str;
+        char c;
+        while (true) {
+            file->read(&c, sizeof(char));
+            if (c == 0) {
+                break;
+            }
+            str += c;
+        }
+        string_table_->StringFromUTF8(str);
+    }
+}
+
+void ExecState::decodeTableSection() {
+    BinaryFile* file = BinaryFile::instance();
+
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    if (count == 0) {
+        return;
+    }
+
+    for (int i=0; i<count; i++) {
+        Value tableValue = class_factory_->CreateTable();
+        Table* table = reinterpret_cast<Table *>(tableValue.gc);
+        unsigned mapSize=0;
+        file->read((char*)&mapSize, sizeof(unsigned));
+        for (int j=0; j<mapSize; j++) {
+            std::string str;
+            char c;
+            while (true) {
+                file->read(&c, sizeof(char));
+                if (c == 0) {
+                    break;
+                }
+                str += c;
+            }
+            Value value;
+            decodeValue(value);
+            table->map.insert(std::make_pair(str, value));
+        }
+    }
+}
+
+void ExecState::decodeFunctionSection() {
+    BinaryFile* file = BinaryFile::instance();
+
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    if (count == 0) {
+        return;
+    }
+
+    std::vector<FuncState*> func_states;
+    for (int i=0; i<count; i++) {
+        FuncState* func_state = new FuncState;
+        int super_index = -1;
+        file->read((char*)&super_index, sizeof(int));
+        func_state->set_super_index(super_index);
+
+        unsigned op_code_count = 0;
+        file->read((char*)&op_code_count, sizeof(unsigned));
+        for (int j=0; j<op_code_count; j++) {
+            unsigned opcode;
+            file->read((char*)&opcode, sizeof(unsigned));
+            func_state->AddInstruction(opcode);
+        }
+        unsigned local_count = 0;
+        file->read((char*)&local_count, sizeof(unsigned));
+        for (int j=0; j<local_count; j++) {
+            Value value;
+            decodeValue(value);
+            func_state->AddConstant(value);
+        }
+        func_states.push_back(func_state);
+    }
+
+    func_state_.reset(func_states[0]);
+    for (auto func : func_states) {
+        int index = func->super_index();
+        if (index > -1) {
+            func_states[index]->AddChild(func);
+        }
+    }
+}
+
+void ExecState::decodeStartSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned start_index;
+    file->read((char*)&start_index, sizeof(unsigned));
+}
+
+void ExecState::decodeGlobalSection() {
+    BinaryFile* file = BinaryFile::instance();
+
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+
+    int init_data_index = -1;
+    int weex_data_index = -1;
+    file->read((char*)&init_data_index, sizeof(int));
+    file->read((char*)&weex_data_index, sizeof(int));
+
+    unsigned register_size = global_->register_size();
+    for (int i=0; i<count; i++) {
+        Value value;
+        decodeValue(value);
+        if (value.type != Value::Type::CFUNC) {
+            if (register_size + i == init_data_index) {
+                global_->Add("_init_data", value);
+            } else if (register_size + i == weex_data_index) {
+                global_->Add("__weex_data__", value);
+            } else  {
+                global_->Add(value);
+            }
+        }
+    }
+}
+
+void ExecState::decodeStyleSection() {
+    BinaryFile* file = BinaryFile::instance();
+
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    if (count == 0) {
+        return;
+    }
+
+    for (int i=0; i<count; i++) {
+        Value value;
+        decodeValue(value);
+
+        unsigned itemsSize = 0;
+        file->read((char*)&itemsSize, sizeof(unsigned));
+        //json11::Json::object items;
+        std::unordered_map<std::string, json11::Json> items;
+        for (int j=0; j<itemsSize; j++) {
+            std::string key;
+            char c;
+            while (true) {
+                file->read(&c, sizeof(char));
+                if (c == 0) {
+                    break;
+                }
+                key += c;
+            }
+
+            std::string value;
+            char v;
+            while (true) {
+                file->read(&v, sizeof(char));
+                if (v == 0) {
+                    break;
+                }
+                value += v;
+            }
+            json11::Json json(value);
+            items.insert(std::make_pair(std::move(key), std::move(json)));
+        }
+        json11::Json json(std::move(items));
+        styles_.insert(std::make_pair(value.index, std::move(json)));
+    }
+}
+
+void ExecState::decodeArraySection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    for (int i=0; i<count; i++) {
+        Value value = class_factory_->CreateArray();
+        Array* array = reinterpret_cast<Array *>(value.gc);
+        unsigned itemSize = 0;
+        file->read((char*)&itemSize, sizeof(unsigned));
+        for (int j=0; j<itemSize; j++) {
+            Value itemValue;
+            decodeValue(itemValue);
+            array->items.push_back(itemValue);
+        }
+    }
+}
+
+void ExecState::decodeRefSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+    for (int i=0; i<count; i++) {
+        Value value;
+        decodeValue(value);
+        long register_id;
+        file->read((char*)&register_id, sizeof(long));
+        ValueRef *ref = new ValueRef(nullptr, register_id);
+        ref->func_index_ = value.index;
+        decodeValue(ref->value_);
+        refs_.push_back(ref);
+    }
+}
+
+void ExecState::decodeClassSection() {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned count = 0;
+    file->read((char*)&count, sizeof(unsigned));
+
+    size_t size = class_factory_->descs().size();
+    for (int i=0; i<count - size; i++) {
+        Value value = class_factory_->CreateClassDescriptor(nullptr);
+        ClassDescriptor* desc = reinterpret_cast<ClassDescriptor *>(value.gc);
+        int super_index = -1;
+        file->read((char*)&super_index, sizeof(int));
+        desc->super_index_ = super_index;
+
+        unsigned static_func_size = 0;
+        file->read((char*)&static_func_size, sizeof(unsigned));
+        for (int j=0; j<static_func_size; j++) {
+            Value static_value;
+            decodeValue(static_value);
+            unsigned length = 0;
+            file->read((char*)&length, sizeof(unsigned));
+            if (length > 0) {
+                std::unique_ptr<char[]> str(new char[length]);
+                file->read(str.get(), sizeof(char)*length);
+                desc->static_funcs_->Add(str.get(), static_value);
+            } else {
+                desc->static_funcs_->Add(static_value);
+            }
+        }
+
+        unsigned class_func_size = 0;
+        file->read((char*)&class_func_size, sizeof(unsigned));
+        for (int j=0; j<class_func_size; j++) {
+            Value class_value;
+            decodeValue(class_value);
+
+            unsigned length = 0;
+            file->read((char*)&length, sizeof(unsigned));
+            if (length > 0) {
+                std::unique_ptr<char[]> str(new char[length]);
+                file->read(str.get(), sizeof(char)*length);
+                desc->funcs_->Add(str.get(), class_value);
+            } else {
+                desc->funcs_->Add(class_value);
+            }
+        }
+    }
+}
+
+void ExecState::decodeValue(Value &value) {
+    BinaryFile* file = BinaryFile::instance();
+    unsigned valueType;
+    file->read((char*)&valueType, sizeof(int));
+    value.type = Value::Type(valueType);
+
+    switch (valueType) {
+        case Value::Type::TABLE:
+        case Value::Type::STRING:
+        case Value::Type::FUNC:
+        case Value::Type::ARRAY:
+        case Value::Type::CLASS_DESC: {
+            value.gc = nullptr;
+            file->read((char*)&(value.index), sizeof(int));
+        }
+            break;
+        case Value::Type::INT: {
+            file->read((char*)&(value.i), sizeof(int64_t));
+        }
+            break;
+        case Value::Type::NUMBER: {
+            file->read((char*)&(value.n), sizeof(double));
+        }
+            break;
+        case Value::Type::BOOL: {
+            file->read((char*)&(value.b), sizeof(char));
+        }
+            break;
+        default:
+            break;
     }
-    CallFunction(function, params.size(), &ret);
-  }
-  return ret;
+}
+
+void ExecState::endDecode() {
+    BinaryFile* file = BinaryFile::instance();
+    file->readFinish();
+
+    std::vector<Table *> tables = class_factory_->tables();
+    for (auto table : tables ) {
+        for (auto &map : table->map) {
+            Value& value = map.second;
+            serializeValue(value);
+        }
+    }
+
+    std::vector<Value>& constants = func_state_->constants();
+    for (auto &value : constants) {
+        serializeValue(value);
+    }
+    std::vector<FuncState*> children = func_state_->getAllChildren();
+    for (auto func_state : children) {
+        std::vector<Value>& child_constants = func_state->constants();
+        for (auto &value : child_constants) {
+            serializeValue(value);
+        }
+    }
+
+    for (int i=0; i<global_->size(); i++) {
+        Value* value = global_->Find(i);
+        serializeValue(*value);
+    }
+
+    std::map<std::string, json11::Json>& styles = render_context_->style_json();
+    for (auto &style : styles_) {
+        Value value;
+        value.index = style.first;
+        value.type = Value::Type::STRING;
+        serializeValue(value);
+        styles.insert(std::make_pair(value.str->c_str(), style.second));
+    }
+
+    std::vector<Array *> arrays = class_factory_->arrays();
+    for (auto array : arrays) {
+        for (auto &value : array->items) {
+            serializeValue(value);
+        }
+    }
+
+    for (auto ref : refs_) {
+        if (ref->func_index_ == 0) {
+            ref->func_state_ = func_state_.get();
+        } else {
+            ref->func_state_ = func_state_->children()[ref->func_index_-1].get();
+        }
+        serializeValue(ref->value_);
+    }
+
+    std::vector<ClassDescriptor *> descs = class_factory_->descs();
+    int count = 0;
+    for (auto desc : descs) {
+        count++;
+        if (count <= 4) {
+            continue;
+        }
+        if (desc->super_index_ != -1) {
+            desc->p_super_ = descs[desc->super_index_];
+        }
+        for (int i=0; i<desc->static_funcs_->size(); i++) {
+            Value* value = desc->static_funcs_->Find(i);
+            serializeValue(*value);
+        }
+        for (int i=0; i<desc->funcs_->size(); i++) {
+            Value* value = desc->funcs_->Find(i);
+            serializeValue(*value);
+        }
+    }
+}
+
+void ExecState::serializeValue(Value &value) {
+    if (value.index == -1) {
+        return;
+    }
+
+    if (value.type == Value::Type::TABLE) {
+        std::vector<Table *> tables = class_factory_->tables();
+        value.gc = reinterpret_cast<GCObject *>(tables[value.index]);
+    }
+
+    if (value.type == Value::Type::STRING) {
+        const std::vector<std::pair<std::string, std::unique_ptr<String>>>& store = string_table_->store();
+        if (value.index >= store.size()) {
+            value.str = store[0].second.get();
+        } else {
+            value.str = store[value.index].second.get();
+        }
+    }
+
+    if (value.type == Value::Type::FUNC) {
+        if (value.index == 0) {
+            value.f = func_state_.get();
+        } else {
+            value.f = func_state_->getAllChildren()[value.index-1];
+        }
+    }
+
+    if (value.type == Value::Type::ARRAY) {
+        std::vector<Array *> arrays = class_factory_->arrays();
+        value.gc = reinterpret_cast<GCObject *>(arrays[value.index]);
+    }
+
+    if (value.type == Value::Type::CLASS_DESC) {
+        std::vector<ClassDescriptor *> descs = class_factory_->descs();
+        value.gc = reinterpret_cast<GCObject *>(descs[value.index]);
+    }
+}
+
+const Value ExecState::Call(const std::string& func_name, const std::vector<Value>& args) {
+    Value ret;
+    do {
+        int index = global()->IndexOf(func_name);
+        long caller = -1;
+        if (index >= 0) {
+            **stack_->top() = *(global()->Find(index));
+        }
+        else {
+            auto iter = global_variables_.find(func_name);
+            if (iter == global_variables_.end()) {
+                break;
+            }
+            caller = iter->second;
+            if (caller < 0) {
+                break;
+            }
+            **stack_->top() = *(stack_->base() + caller);
+        }
+        for (int i = 0; i < args.size(); ++i) {
+            *(*stack_->top() + i + 1) = args[i];
+        }
+        CallFunction(*stack_->top(), args.size(), &ret);
+
+    } while (0);
+    
+    return ret;
 }
     
-const Value ExecState::Call(Value *func, const std::vector<Value>& params) {
+const Value ExecState::Call(FuncState *func_state, const std::vector<Value>& args) {
+    Value ret;
+    do {
+        Value func(func_state);
+        **stack_->top() = func;
+        int index = 0;
+        for (int i = 0; i < args.size(); i++) {
+            *(*stack_->top() + i + 1 + index) = args[i];
+        }
+        CallFunction(*stack_->top(), args.size(), &ret);
+        
+    } while (0);
+    
+    return ret;
+}
+    
+const Value ExecState::Call(Value *func, const std::vector<Value>& args) {
     Value ret;
     do {
         // é¦–å…ˆę£€ęŸ„å‡½ę•°ę˜Æ否属äŗŽå †ę ˆå‡½ę•°
@@ -144,15 +963,49 @@ const Value ExecState::Call(Value *func, const std::vector<Value>& params) {
             throw VMExecError("call function out of stack");
             break;
         }
-        for (int i = 0; i < params.size(); i++) {
-            *(func + i + 1) = params[i];
+        for (int i = 0; i < args.size(); i++) {
+            *(func + i + 1) = args[i];
         }
-        CallFunction(func, params.size(), &ret);
+        CallFunction(func, args.size(), &ret);
         
     } while (0);
     
     return ret;
 }
+    
+void ExecState::resetArguments(Value *func, size_t argc) {
+    do {
+        auto iter = global_variables_.find(JS_GLOBAL_ARGUMENTS);
+        if (iter == global_variables_.end()) {
+            break;
+        }
+        long caller = iter->second;
+        if (caller < 0) {
+            break;
+        }
+        Value *arguments = stack_->base() + caller;
+        if (!IsArray(arguments)) {
+            break;
+        }
+        ClearArray(ValueTo<Array>(arguments));
+        for (int i = 0; i < argc; i++) {
+            PushArray(ValueTo<Array>(arguments), *(func + i + 1));
+        }
+        
+    } while (0);
+}
+    
+void ExecState::Register(const std::string& name, CFunction func) {
+    Value funcVal;
+    funcVal.type = Value::Type::CFUNC;
+    funcVal.cf = reinterpret_cast<void *>(func);
+    Register(name, funcVal);
+}
+    
+void ExecState::Register(const std::string& name, Value value) {
+    global()->Add(name, value);
+    global()->incrementRegisterSize();
+}
 
 void ExecState::CallFunction(Value *func, size_t argc, Value *ret) {
     *stack_->top() = func + argc;
@@ -175,6 +1028,7 @@ void ExecState::CallFunction(Value *func, size_t argc, Value *ret) {
         frame.pc = &(*func->f->instructions().begin());
         frame.end = &(*func->f->instructions().end());
         frames_.push_back(frame);
+        resetArguments(func, argc);
         vm_->RunFrame(this, frame, ret);
         stack_->reset();
         frames_.pop_back();
diff --git a/weex_core/Source/core/data_render/exec_state.h b/weex_core/Source/core/data_render/exec_state.h
index f4892dfe4a..fbe6866bbe 100644
--- a/weex_core/Source/core/data_render/exec_state.h
+++ b/weex_core/Source/core/data_render/exec_state.h
@@ -41,7 +41,7 @@ namespace data_render {
 class ValueRef {
     friend class ExecState;
 public:
-    ValueRef(FuncState *func_state, long register_id) : func_state_(func_state), register_id_(register_id), ref_id_(gs_ref_id++) { SetNil(&value_); };
+    ValueRef(FuncState *func_state, long register_id) : func_state_(func_state), register_id_(register_id), ref_id_(gs_ref_id++), func_index_(-1) { SetNil(&value_); };
     inline int ref_id() { return ref_id_; }
     inline FuncState *func_state() { return func_state_; }
     inline long register_id() { return register_id_; }
@@ -52,12 +52,15 @@ class ValueRef {
     FuncState *func_state_{nullptr};
     int ref_id_;
     long register_id_;
+    int func_index_;
     Value value_;
 };
+    
+struct ClassInstance;
 
 class FuncState {
  public:
-  FuncState() : instructions_(), constants_(), children_() {}
+  FuncState() : instructions_(), constants_(), children_(), super_index_(-1) {}
   virtual ~FuncState() {}
 
   int AddConstant(Value value) {
@@ -71,6 +74,7 @@ class FuncState {
   }
 
   inline Value* GetConstant(int index) { return &constants_[index]; }
+  inline size_t GetConstantSize() { return constants_.size();}
   inline size_t AddInstruction(Instruction i) {
     instructions_.push_back(i);
     return instructions_.size() - 1;
@@ -81,29 +85,52 @@ class FuncState {
   }
   inline std::vector<Instruction>& instructions() { return instructions_; }
   inline void AddChild(FuncState* func) {
+    func->super_func_ = this;
     children_.push_back(std::unique_ptr<FuncState>(func));
   }
-  inline std::vector<std::unique_ptr<FuncState>>& children() {
+  inline const std::vector<std::unique_ptr<FuncState>>& children() {
     return children_;
   }
   inline FuncState* GetChild(size_t pos) { return children_[pos].get(); }
+  inline std::vector<Value>& constants() {return constants_;}
+  inline FuncState* super_func() {return super_func_;}
+  inline void set_super_func(FuncState* func) {super_func_ = func;}
+  inline void set_is_class_func(bool is_class_func) { is_class_func_ = is_class_func; }
+  inline bool is_class_func() { return is_class_func_; }
+  inline ClassInstance * &class_inst() { return class_inst_; }
+  std::vector<FuncState *> getAllChildren() {
+      std::vector<FuncState*> all_children;
+      for (auto &child : children_) {
+          all_children.push_back(child.get());
+          std::vector<FuncState*> children = child->getAllChildren();
+          all_children.insert(all_children.end(), children.begin(), children.end());
+      }
+      return all_children;
+  }
+
+  inline int super_index() const {return super_index_;}
+  inline void set_super_index(int super_index) {super_index_ = super_index;}
 
  private:
   std::vector<Instruction> instructions_;
   std::vector<Value> constants_;
   std::vector<std::unique_ptr<FuncState>> children_;
+  FuncState *super_func_{nullptr};
+  int super_index_;
+  bool is_class_func_{false};
+  ClassInstance *class_inst_{nullptr};
 };
     
 // TODO Each Func should contain a stack whose size is 256
 class ExecStack {
  public:
-  ExecStack() : stack_(VM_EXEC_STACK_SIZE) {}
+  ExecStack() : stack_(VM_EXEC_STACK_SIZE), top_(&stack_[0]) {}
   Value** top() { return &top_; }
   Value* base() { return &stack_[0]; }
   void reset();
  private:
   std::vector<Value> stack_;
-  Value* top_;
+  Value *top_;
 };
 
 class ExecState {
@@ -112,12 +139,16 @@ class ExecState {
   virtual ~ExecState() {}
   void Compile(std::string& error);
   void Execute(std::string& error);
-  const Value Call(const std::string& func_name, const std::vector<Value>& params);
-  const Value Call(Value *func, const std::vector<Value>& params);
+  const Value Call(const std::string& func_name, const std::vector<Value>& args);
+  const Value Call(Value *func, const std::vector<Value>& args);
+  const Value Call(FuncState *func, const std::vector<Value>& args);
+    
   size_t GetArgumentCount();
   Value* GetArgument(int index);
   ValueRef *AddRef(FuncState *func_state, long register_id);
   ValueRef *FindRef(int index);
+  void Register(const std::string& name, CFunction function);
+  void Register(const std::string& name, Value value);
   std::vector<ValueRef *> &refs() { return refs_; };
   inline Variables* global() { return global_.get(); }
   inline ExecStack* stack() { return stack_.get(); }
@@ -125,10 +156,41 @@ class ExecState {
   inline VNodeRenderContext* context() { return render_context_.get(); }
   inline ClassFactory *class_factory() { return class_factory_.get(); }
 
+  void startEncode();
+  void endEncode();
+
+  bool startDecode();
+  void endDecode();
+
  private:
   friend class VM;
   friend class CodeGenerator;
+
+  void encodeGlobalSection();
+  void encodeFunctionSection();
+  void encodeStartSection();
+  void encodeTableSection();
+  void encodeStringSection();
+  void encodeStyleSection();
+  void encodeArraySection();
+  void encodeRefSection();
+  void encodeClassSection();
+  void encodeValue(const Value &value);
+
+  void decodeValue(Value &value);
+  void decodeStringSection();
+  void decodeTableSection();
+  void decodeFunctionSection();
+  void decodeStartSection();
+  void decodeGlobalSection();
+  void decodeStyleSection();
+  void decodeArraySection();
+  void decodeRefSection();
+  void decodeClassSection();
+  void serializeValue(Value &value);
+  void resetArguments(Value *func, size_t argc);
   void CallFunction(Value *func, size_t argc, Value *ret);
+  int findSuperIndex(const std::vector<FuncState*>& func_states);
 
   VM* vm_;
 
@@ -143,8 +205,9 @@ class ExecState {
   std::unique_ptr<StringTable> string_table_;
   std::unique_ptr<VNodeRenderContext> render_context_;
   std::unordered_map<std::string, long> global_variables_;
+  std::unordered_map<int, json11::Json> styles_;
 };
-    
+
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/js_common_function.cc b/weex_core/Source/core/data_render/js_common_function.cc
new file mode 100644
index 0000000000..5134d19404
--- /dev/null
+++ b/weex_core/Source/core/data_render/js_common_function.cc
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+#include "core/data_render/js_common_function.h"
+#include "core/data_render/common_error.h"
+#include <base/LogDefines.h>
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+static Value ParseInt(ExecState *state) {
+    Value ret;
+    do {
+        if (state->GetArgumentCount() < 2) {
+            throw VMExecError("parseInt must have 2 args");
+            break;
+        }
+        ret = *state->GetArgument(1);
+        Value *toInt = state->GetArgument(0);
+        int64_t toIntVal = 0;
+        if (ToInteger(toInt, 2, toIntVal)) {
+            ret = Value(toIntVal);
+        }
+        
+    } while (0);
+    
+    return ret;
+}
+
+static Value IsClass(ExecState *state) {
+    Value ret(false);
+    do {
+        if (state->GetArgumentCount() < 1) {
+            throw VMExecError("IsClass must have 1 args");
+            break;
+        }
+        Value *arg = state->GetArgument(0);
+        ret = IsClass(arg) ? Value(true) : Value(false);
+        
+    } while (0);
+    
+    return ret;
+}
+
+void RegisterJSCommonFunction(ExecState *state) {
+    state->Register("parseInt", ParseInt);
+    state->Register("isClass", IsClass);
+}
+    
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
diff --git a/weex_core/Source/core/data_render/js_common_function.h b/weex_core/Source/core/data_render/js_common_function.h
new file mode 100644
index 0000000000..3602deb37b
--- /dev/null
+++ b/weex_core/Source/core/data_render/js_common_function.h
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+
+//
+// Created by pentao.pt on 2018/7/25.
+//
+
+#ifndef DATA_RENDER_JS_COMMON_FUNCTION_H
+#define DATA_RENDER_JS_COMMON_FUNCTION_H
+
+#include "core/data_render/object.h"
+#include "core/data_render/exec_state.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+ 
+void RegisterJSCommonFunction(ExecState *state);
+    
+}  // namespace data_render
+}  // namespace core
+}  // namespace weex
+
+#endif  // DATA_RENDER_JS_COMMON_FUNCTION_H
diff --git a/weex_core/Source/core/data_render/object.cc b/weex_core/Source/core/data_render/object.cc
index e75c08e149..56dee147b5 100644
--- a/weex_core/Source/core/data_render/object.cc
+++ b/weex_core/Source/core/data_render/object.cc
@@ -18,6 +18,7 @@
  */
 
 #include <sstream>
+#include <cstdlib>
 #include "core/data_render/object.h"
 
 namespace weex {
@@ -52,6 +53,10 @@ int ToInteger(const Value *o, const int &mode, int64_t &v) {
     SetDValue(&tmp, d);
     o = &tmp;
     goto label;
+  } else if (IsString(o)) {
+      v = atoi(CStringValue(o));
+      return 1;
+      
   } else {
     return 0;
   }
@@ -144,10 +149,10 @@ bool ValueStrictEquals(const Value *a, const Value *b) {
 }
     
 bool ValueAND(const Value *a, const Value *b) {
-    if (IsBool(a) && IsBool(b)) {
-        return BoolValue(a) && BoolValue(b);
-    }
-    return false;
+    bool aval = false, bval = false;
+    ToBool(a, aval);
+    ToBool(b, bval);
+    return aval && bval;
 }
     
 bool ValueOR(const Value *a, const Value *b) {
@@ -279,7 +284,7 @@ void SetRefValue(Value *o) {
         value = value->ref;
     }
 }
-
+    
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/object.h b/weex_core/Source/core/data_render/object.h
index 826ea8f833..88671996b4 100644
--- a/weex_core/Source/core/data_render/object.h
+++ b/weex_core/Source/core/data_render/object.h
@@ -25,6 +25,8 @@
 #include <cmath>
 #include <sstream>
 #include <map>
+#include <memory>
+#include "base/string_util.h"
 #include "core/data_render/object.h"
 #include "core/data_render/string_table.h"
 #include "core/data_render/vm.h"
@@ -93,6 +95,8 @@ struct Value {
 
   Type type;
 
+  int index = -1;
+
   Value() : type(NIL) {}
     
   Value(int value) : i(value), type(INT) {}
@@ -104,9 +108,12 @@ struct Value {
   Value(bool value) : b(value), type(BOOL) {}
 
   Value(String *value) : str(value), type(STRING) {}
-
+    
+  explicit Value(FuncState *func) : f(func), type(FUNC) {}
+    
   Value(const Value &value) {
     type = value.type;
+    index = value.index;
     switch (type) {
       case INT:i = value.i;
         break;
@@ -129,7 +136,8 @@ struct Value {
       case CLASS_DESC:
       case CLASS_INST:
         gc = value.gc;
-        gc->increment();
+        if(gc)
+          gc->increment();
         break;
       default:break;
     }
@@ -138,6 +146,7 @@ struct Value {
   inline Value operator=(Value value) {
       GCRelease(this);
       type = value.type;
+      index = value.index;
       switch (type) {
           case INT:
               i = value.i;
@@ -168,7 +177,8 @@ struct Value {
           case CLASS_DESC:
           case CLASS_INST:
               gc = value.gc;
-              gc->increment();
+              if(gc)
+                gc->increment();
               break;
           default:break;
       }
@@ -176,6 +186,7 @@ struct Value {
   }
   friend bool operator==(const Value &left, const Value &right) {
     if (left.type != right.type) return false;
+    if (left.index != right.index) return false;
     switch (left.type) {
       case NIL:return true;
       case INT:return left.i == right.i;
@@ -220,27 +231,32 @@ class Variables {
     int Add(Value value);
     int Add(const std::string& name, Value value);
     int Set(const std::string& name, Value value);
+    inline size_t size() {return values_.size();}
+    inline const std::map<std::string, int>& map() {return map_;}
+    inline unsigned register_size() {return register_size_;}
+    void incrementRegisterSize() {register_size_++;}
     
 private:
     std::map<std::string, int> map_;
     std::vector<Value> values_;
+    unsigned register_size_ = 0;
 };
 
 struct ClassDescriptor;
     
 typedef struct ClassDescriptor {
     CommonHeader;
-    ClassDescriptor *p_super_;
+    ClassDescriptor *p_super_{nullptr};
     std::unique_ptr<Variables> static_funcs_;
     std::unique_ptr<Variables> funcs_;
-    ClassDescriptor(ClassDescriptor *p_super) : p_super_(p_super), funcs_(new Variables), static_funcs_(new Variables) {}
-    
+    ClassDescriptor(ClassDescriptor *p_super) : p_super_(p_super), funcs_(new Variables), static_funcs_(new Variables), super_index_(-1) {}
+    int super_index_;
 } ClassDescriptor;
 
 typedef struct ClassInstance {
     CommonHeader;
-    ClassInstance *p_super_;
-    ClassDescriptor *p_desc_;
+    ClassInstance *p_super_{nullptr};
+    ClassDescriptor *p_desc_{nullptr};
     std::unique_ptr<Variables> vars_;
     ClassInstance(ClassDescriptor *p_desc) : p_desc_(p_desc), vars_(new Variables) {}
     
@@ -332,8 +348,10 @@ inline int64_t ShiftLeft(const int64_t &a, const int64_t &b) {
 
 inline bool IsInt(const Value *o) { return Value::Type::INT == o->type; }
     
-inline bool IsFunc(const Value *o) { return Value::Type::FUNC == o->type || Value::Type::CFUNC == o->type; }
-
+inline bool IsFunction(const Value *o) { return Value::Type::FUNC == o->type || Value::Type::CFUNC == o->type; }
+    
+inline bool IsPrototypeFunction(const Value *o) { return Value::Type::FUNC == o->type; }
+    
 inline bool IsValueRef(const Value *o) { return Value::Type::VALUE_REF == o->type; }
     
 inline bool IsNil(const Value *o) {
@@ -341,13 +359,13 @@ inline bool IsNil(const Value *o) {
 }
     
 inline void GCRelease(Value *o) {
-    if (iscollectable(o)) {
+    if (iscollectable(o) && o->gc) {
         o->gc->decrement();
     }
 }
     
 inline void GCRetain(Value *o) {
-    if (iscollectable(o)) {
+    if (iscollectable(o) && o->gc) {
         o->gc->increment();
     }
 }
@@ -538,25 +556,42 @@ inline int ToBool(const Value *o, bool &b) {
     else if (Value::Type::NUMBER == o->type) {
         b = NumValue(o);
     }
+    else if (ttype(o) == Value::Type::STRING) {
+        b = o->str ? true : false;
+    }
     else if (Value::Type::VALUE_REF == o->type) {
         return ToBool(o->var, b);
     }
     else if (ToNum(o, d1)) {
         b = d1;
     }
-    else if (Value::Type::NIL == o->type) {
-        b = false;
-    }
     else if (Value::Type::FUNC == o->type) {
         b = o->f ? true : false;
     }
     else {
-        b = false;
-        return 0;
+        b = ttype(o) == Value::Type::NIL ? false : true;
     }
     return 1;
 }
 
+inline std::string ToString(const Value *o) {
+    switch (o->type) {
+        case Value::Type::BOOL:
+            return weex::base::to_string(o->b);
+        case Value::Type::INT:
+            return weex::base::to_string(o->n);
+        case Value::Type::NUMBER:
+            return weex::base::to_string(o->n);
+        case Value::Type::STRING:
+            return o->str->c_str();
+        case Value::Type::NIL:
+            return "[nil]";
+        default:
+            return "[not support]";
+    }
+    return std::string();
+}
+
 inline void ArrayCopyFrom(Value &src, Value &dest, int start, int end) {
     Array *st = ValueTo<Array>(&src);
     Array *dt = ValueTo<Array>(&dest);
diff --git a/weex_core/Source/core/data_render/parser.cc b/weex_core/Source/core/data_render/parser.cc
index 0984a8f093..db3cd7df4b 100644
--- a/weex_core/Source/core/data_render/parser.cc
+++ b/weex_core/Source/core/data_render/parser.cc
@@ -89,9 +89,11 @@ struct ASTParser final {
           if (class_style.is_string()) {
             args.push_back(
                 factory_->NewStringConstant(wrap_prefix + class_style.string_value()));
-            statement->PushExpression(factory_->NewCallExpression(func_id, args));
-            args.pop_back();
+          } else {
+            args.push_back(ParseBindingExpression(class_style));
           }
+          statement->PushExpression(factory_->NewCallExpression(func_id, args));
+          args.pop_back();
         }
       }
     }
@@ -162,9 +164,6 @@ struct ASTParser final {
     do {
       json11::Json repeat = json["repeat"];
       json11::Json index = repeat["iterator1"];
-      if (!index.is_string()) {
-        break;
-      }
       Handle<DeclarationList> for_init = factory_->NewDeclarationList();
       // var index=0
       for_init->Append(factory_->NewDeclaration(index.is_null() ? "index" : index.string_value(), factory_->NewIntegralConstant(0)));
@@ -527,6 +526,7 @@ struct ASTParser final {
   //        var child = createElement(tag_name, node_id);
   //        appendChild(parent, child);
   //        setClassList(child, class_name);
+  //        setStyle(child, key, value);
   //        setAttr(child, key, value);
   //        {
   //            ...
@@ -559,15 +559,19 @@ struct ASTParser final {
       }
       json11::Json node_id = json["nodeId"];
       json11::Json tag_name = json["tagName"];
+      json11::Json ref = json11::Json("");
+      if (json["attributes"].is_object() && json["attributes"]["ref"].is_string()) {
+        ref = json["attributes"]["ref"];
+      }
       Handle<Expression> node_id_expr = nullptr;
       if (tag_name.is_string()) {
         Handle<Expression> call_expr = nullptr;
         Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
         std::vector<Handle<Expression>> args;
 
-        // var child = createElement(tag_name, node_id);
+        // var child = createElement(tag_name, node_id, ref);
         // or
-        // var child = createComponent(template_id, tag_name, node_id);
+        // var child = createComponent(template_id, tag_name, node_id, ref);
         {
             Handle<Expression> func;
             node_id_expr = ParseNodeId(control, control_exprs, node_id.string_value());
@@ -577,6 +581,7 @@ struct ASTParser final {
                 args.push_back(
                         factory_->NewStringConstant(tag_name.string_value()));
                 args.push_back(node_id_expr);
+                args.push_back(factory_->NewStringConstant(ref.string_value()));
                 call_expr = factory_->NewCallExpression(func, args);
             } else {
                 // Component Node call createComponent
@@ -589,6 +594,7 @@ struct ASTParser final {
                 args.push_back(
                         factory_->NewStringConstant(tag_name.string_value()));
                 args.push_back(node_id_expr);
+                args.push_back(factory_->NewStringConstant(ref.string_value()));
                 call_expr = factory_->NewCallExpression(func, args);
             }
             Handle<Declaration> child_declaration =
@@ -611,6 +617,32 @@ struct ASTParser final {
       // setClassList(child, class_name)
       AddSetClassListCall(json, child_identifier, component_name);
 
+      // setStyle(child, key, value)
+      json11::Json style = json["style"];
+      if (style.is_object()) {
+        auto items = style.object_items();
+        for (auto it = items.begin(); it != items.end(); ++it) {
+          const auto& key = it->first;
+          const auto& value = it->second;
+          std::vector<Handle<Expression>> args;
+          args.push_back(child_identifier);
+          args.push_back(factory_->NewStringConstant(key));
+          if (value.is_string()) {
+            args.push_back(
+                    factory_->NewStringConstant(value.string_value()));
+          } else {
+            args.push_back(ParseBindingExpression(value));
+          }
+
+          Handle<Expression> set_style_func_expr =
+                  factory_->NewIdentifier("setStyle");
+          Handle<CallExpression> call_func =
+                  factory_->NewCallExpression(set_style_func_expr, args);
+          Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
+          statement->PushExpression(call_func);
+        }
+      }
+
       // setAttr(child, key, value)
       json11::Json attributes = json["attributes"];
       if (attributes.is_object()) {
diff --git a/weex_core/Source/core/data_render/rax_jsx_ast.cc b/weex_core/Source/core/data_render/rax_jsx_ast.cc
index 60794a1edb..546c2b3d8c 100644
--- a/weex_core/Source/core/data_render/rax_jsx_ast.cc
+++ b/weex_core/Source/core/data_render/rax_jsx_ast.cc
@@ -43,7 +43,7 @@ bool JSXNodeExpression::LowerIdentifier() {
     std::string name = Identifier()->AsIdentifier()->GetName();
     return name[0] == tolower(name[0]) ? true : false;
 }
-
+    
 std::vector<Handle<Expression>>& JSXNodeExpression::funcexprs() {
     if (!funcexprs_.size()) {
         ASTFactory *factory = ASTFactory::GetFactoryInstance();
@@ -68,8 +68,11 @@ std::vector<Handle<Expression>>& JSXNodeExpression::funcexprs() {
                 funcexprs_.push_back(factory->NewCallExpression(set_props_func_expr, args));
             }
         }
-        else if (!is_class_) {
-            Handle<Expression> call_func_expr = factory->NewIdentifier(name);
+        else if (is_class_) {
+            std::string class_inst = vnode_ptr + "_inst";
+            funcexprs_.push_back(factory->NewDeclaration(vnode_ptr));
+            funcexprs_.push_back(factory->NewDeclaration(class_inst, factory->NewNewExpression(identifier_)));
+            // call constructor
             std::vector<Handle<Expression>> args;
             if (props_) {
                 args.push_back(props_);
@@ -78,13 +81,64 @@ std::vector<Handle<Expression>>& JSXNodeExpression::funcexprs() {
                 ProxyObject proxy;
                 args.push_back(factory->NewObjectConstant(proxy));
             }
-            funcexprs_.push_back(factory->NewDeclaration(vnode_ptr,factory->NewCallExpression(call_func_expr, args)));
+            Handle<Expression> class_inst_expr = factory->NewIdentifier(class_inst);
+            funcexprs_.push_back(factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, factory->NewIdentifier("constructor"), args));
+            // if (vnode_ptr.xxxx) then vnode_ptr.xxxx()
+            Handle<Expression> render_expr = factory->NewIdentifier("render");
+            Handle<MemberExpression> member_func_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, render_expr);
+            Handle<ExpressionList> if_then_stmts = factory->NewExpressionList();
+            if_then_stmts->Insert(factory->NewAssignExpression(factory->NewIdentifier(vnode_ptr), factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, render_expr, {})));
+            Handle<Expression> compoent_expr = factory->NewIdentifier("vcompoent_ptr");
+            Handle<Expression> compoent_member_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, compoent_expr);
+            compoent_member_expr->AsMemberExpression()->is_assignment() = true;
+            if_then_stmts->Insert(factory->NewAssignExpression(compoent_member_expr, factory->NewIdentifier(vnode_ptr)));
+            Handle<Expression> if_block_expr = factory->NewBlockStatement(if_then_stmts);
+            funcexprs_.push_back(factory->NewIfStatement(member_func_expr, if_block_expr));
         }
         else {
             std::string class_inst = vnode_ptr + "_inst";
-            funcexprs_.push_back(factory->NewDeclaration(class_inst, factory->NewNewExpression(identifier_)));
-            // call constructor
             std::vector<Handle<Expression>> args;
+            // vnode_ptr = null, vnode_inst = null;
+            funcexprs_.push_back(factory->NewDeclaration(class_inst));
+            funcexprs_.push_back(factory->NewDeclaration(vnode_ptr));
+            Handle<Expression> identifier = factory->NewIdentifier(name);
+            Handle<Expression> is_class_func_expr = factory->NewIdentifier("isClass");
+            args.push_back(identifier);
+            Handle<ExpressionList> if_then_stmts = factory->NewExpressionList();
+            Handle<Expression> if_block_expr = factory->NewBlockStatement(if_then_stmts);
+            Handle<ExpressionList> if_else_stmts = factory->NewExpressionList();
+            Handle<Expression> if_else_expr = factory->NewBlockStatement(if_else_stmts);
+            funcexprs_.push_back(factory->NewIfElseStatement(factory->NewCallExpression(is_class_func_expr, args), if_block_expr, if_else_expr));
+            // if isClass
+            {
+                Handle<Expression> class_inst_expr = factory->NewIdentifier(class_inst);
+                Handle<Expression> new_expr = factory->NewNewExpression(identifier_);
+                new_expr->AsNewExpression()->set_is_class_(true);
+                if_then_stmts->Insert(factory->NewAssignExpression(class_inst_expr, new_expr));
+                // call constructor
+                args.clear();
+                if (props_) {
+                    args.push_back(props_);
+                }
+                else {
+                    ProxyObject proxy;
+                    args.push_back(factory->NewObjectConstant(proxy));
+                }
+                if_then_stmts->Insert(factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, factory->NewIdentifier("constructor"), args));
+                // if (vnode_ptr.xxxx) then vnode_ptr.xxxx()
+                Handle<Expression> render_expr = factory->NewIdentifier("render");
+                Handle<MemberExpression> member_func_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, render_expr);
+                Handle<ExpressionList> if_then_stmts_inner = factory->NewExpressionList();
+                if_then_stmts_inner->Insert(factory->NewAssignExpression(factory->NewIdentifier(vnode_ptr), factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, render_expr, {})));
+                Handle<Expression> compoent_expr = factory->NewIdentifier("vcompoent_ptr");
+                Handle<Expression> compoent_member_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, compoent_expr);
+                compoent_member_expr->AsMemberExpression()->is_assignment() = true;
+                if_then_stmts_inner->Insert(factory->NewAssignExpression(compoent_member_expr, factory->NewIdentifier(vnode_ptr)));
+                Handle<Expression> if_block_expr_inner = factory->NewBlockStatement(if_then_stmts_inner);
+                if_then_stmts->Insert(factory->NewIfStatement(member_func_expr, if_block_expr_inner));
+            }
+            // else
+            args.clear();
             if (props_) {
                 args.push_back(props_);
             }
@@ -92,14 +146,7 @@ std::vector<Handle<Expression>>& JSXNodeExpression::funcexprs() {
                 ProxyObject proxy;
                 args.push_back(factory->NewObjectConstant(proxy));
             }
-            Handle<Expression> class_inst_expr = factory->NewIdentifier(class_inst);
-            funcexprs_.push_back(factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, factory->NewIdentifier("constructor"), args));
-            // if (vnode_ptr.xxxx) then vnode_ptr.xxxx()
-            Handle<Expression> render_expr = factory->NewIdentifier("render");
-            Handle<MemberExpression> member_func_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, render_expr);
-            funcexprs_.push_back(factory->NewDeclaration(vnode_ptr));
-            Handle<Expression> assign_expr = factory->NewAssignExpression(factory->NewIdentifier(vnode_ptr), factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, render_expr, {}));
-            funcexprs_.push_back(factory->NewIfStatement(member_func_expr, assign_expr));
+            if_else_stmts->Insert(factory->NewAssignExpression(factory->NewIdentifier(vnode_ptr), factory->NewCallExpression(identifier, args)));
         }
     }
     return funcexprs_;
diff --git a/weex_core/Source/core/data_render/rax_jsx_ast.h b/weex_core/Source/core/data_render/rax_jsx_ast.h
index bdb5808372..061fbcfb75 100644
--- a/weex_core/Source/core/data_render/rax_jsx_ast.h
+++ b/weex_core/Source/core/data_render/rax_jsx_ast.h
@@ -30,6 +30,8 @@ namespace core {
 namespace data_render {
     
 #define JSX_GLOBAL_VNODE_INDEX               "global_vnode_index"
+#define JS_GLOBAL_ARGUMENTS                  "__arguments"
+
     
 class JSXNodeExpression : public Expression {
 public:
diff --git a/weex_core/Source/core/data_render/rax_parser.cc b/weex_core/Source/core/data_render/rax_parser.cc
index 71396556bb..f507e2cbd1 100644
--- a/weex_core/Source/core/data_render/rax_parser.cc
+++ b/weex_core/Source/core/data_render/rax_parser.cc
@@ -830,6 +830,69 @@ Handle<Expression> RAXParser::ParseJSXNodeStatement() {
     return expr;
 }
     
+Handle<Expression> RAXParser::ParseJSXNodeProperty() {
+    Handle<Expression> props = nullptr;
+    ProxyObject proxy;
+    ProxyArray spread_property;
+    std::vector<std::pair<ProxyOrder, std::string>> orders;
+    std::string key;
+    do {
+        Handle<Expression> prop;
+        while (true) {
+            auto tok = Peek();
+            if (tok == Token::STRING) {
+                key = GetStringConstant();
+            }
+            else if (tok == Token::IDENTIFIER || Token::IsKeyword(tok) || tok == Token::NUMBER) {
+                key = lex()->CurrentToken().view();
+            }
+            else if (tok == Token::UNFOLD) {
+                Handle<Expression> unfold_expr = ParseAssignExpression();
+                spread_property.push_back(unfold_expr);
+                orders.push_back(std::make_pair(ProxyOrder::ProxyArray, to_string((int)spread_property.size() - 1)));
+                continue;
+            }
+            else if (tok == Token::RBRACE || tok == Token::LBRACE) {
+                Advance();
+                continue;
+            }
+            else if (tok == Token::DIV) {
+                break;
+            }
+            else {
+                throw SyntaxError(lex()->CurrentToken(), "expected an Identifier or a string");
+            }
+            Advance();
+            if (Peek() == Token::ASSIGN) {
+                Advance();
+                EXPECT(Token::LBRACE);
+                prop = ParseAssignExpression();
+                EXPECT(Token::RBRACE);
+            }
+            if (prop == NULL) {
+                prop = builder()->NewIdentifier(key);
+            }
+            proxy[key] = Handle<Expression>(prop);
+            orders.push_back(std::make_pair(ProxyOrder::ProxyObject, key));
+        }
+        
+    } while (0);
+    
+    if (proxy.size() > 0 || spread_property.size() > 1) {
+        props = builder()->NewObjectConstant(proxy);
+        if (spread_property.size() > 0) {
+            for (int i = 0; i < spread_property.size(); i++) {
+                props->AsObjectConstant()->SpreadProperty().push_back(spread_property[i]);
+            }
+            props->AsObjectConstant()->Orders() = orders;
+        }
+    }
+    else {
+        props = spread_property[0];
+    }
+    return props;
+}
+    
 Handle<Expression> RAXParser::ParseJSXNodeExpression(Handle<Expression> parent) {
     Handle<Expression> expr = nullptr;
     Handle<Expression> props = nullptr;
@@ -838,9 +901,7 @@ Handle<Expression> RAXParser::ParseJSXNodeExpression(Handle<Expression> parent)
     auto tok = Peek();
     // props process
     if (tok == Token::LBRACE) {
-        Advance();
-        props = ParseExpression();
-        EXPECT(Token::RBRACE);
+        props = ParseJSXNodeProperty();
     }
     else if (tok == Token::IDENTIFIER) {
         // props process
@@ -1025,6 +1086,10 @@ Handle<Expression> RAXParser::ParseClassBody(std::string &clsname) {
         auto one = ParseClassMethodStatement(clsname);
         clsbody->Insert(one);
         auto tok = Peek();
+        if (tok == Token::SEMICOLON) {
+            Advance();
+            tok = Peek();
+        }
         if (tok == Token::RBRACE) {
             break;
         }
@@ -1040,11 +1105,20 @@ Handle<Expression> RAXParser::ParseClassMethodStatement(std::string &clsname) {
     }
     std::string identifier = GetIdentifierName();
     Advance();
-    auto args = ParseParameterList();
-    auto body = ParseBlockStatement();
-    auto proto = builder()->NewFunctionPrototype(identifier, args);
-    proto->AsFunctionPrototype()->SetClassName(clsname);
-    return builder()->NewFunctionStatement(proto->AsFunctionPrototype(), body);
+    tok = Peek();
+    if (tok == Token::ASSIGN) {
+        Advance();
+        Handle<Expression> arrow_function = ParseAssignExpression();
+        arrow_function->AsArrowFunctionStatement()->name() = identifier;
+        return arrow_function;
+    }
+    else {
+        auto args = ParseParameterList();
+        auto body = ParseBlockStatement();
+        auto proto = builder()->NewFunctionPrototype(identifier, args);
+        proto->AsFunctionPrototype()->SetClassName(clsname);
+        return builder()->NewFunctionStatement(proto->AsFunctionPrototype(), body);
+    }
 }
     
 Handle<Expression> RAXParser::ParseIfStatement()
@@ -1176,12 +1250,13 @@ Handle<Expression> RAXParser::ParseProgram()
     Handle<ExpressionList> exprs = builder()->NewExpressionList();
     Handle<ChunkStatement> chunk = builder()->NewChunkStatement(exprs);
     exprs->Insert(builder()->NewDeclaration(JSX_GLOBAL_VNODE_INDEX, builder()->NewIntegralConstant(0)));
+    exprs->Insert(builder()->NewDeclaration(JS_GLOBAL_ARGUMENTS, builder()->NewArrayConstant({})));
     try {
         while (Peek() != Token::EOS) {
             exprs->Insert(ParseStatement());
         }
     } catch (std::exception &e) {
-        auto error = static_cast<SyntaxError*>(&e);
+        auto error = static_cast<SyntaxError *>(&e);
         
         if (error) {
             std::cerr << error->what() << " (" << error->token().position().row()
@@ -1292,6 +1367,9 @@ Handle<Expression> RAXParser::ParseVariableStatement()
         else if (tok == Token::IN || tok == Token::CONST) {
             break;
         }
+        else if (tok == Token::CLASS) {
+            break;
+        }
         else if (tok != Token::COMMA) {
             throw SyntaxError(lex()->CurrentToken(), "expected a ',' or ';'");
         }
diff --git a/weex_core/Source/core/data_render/rax_parser.h b/weex_core/Source/core/data_render/rax_parser.h
index a168cc9c9d..659fbe12d7 100644
--- a/weex_core/Source/core/data_render/rax_parser.h
+++ b/weex_core/Source/core/data_render/rax_parser.h
@@ -102,6 +102,7 @@ class RAXParser {
     Handle<Expression> ParseClassStatement();
     Handle<Expression> ParseClassBody(std::string &clsname);
     Handle<Expression> ParseClassMethodStatement(std::string &clsname);
+    Handle<Expression> ParseJSXNodeProperty();
 private:
     const std::string& GetIdentifierName();
     const std::string& GetStringConstant();
diff --git a/weex_core/Source/core/data_render/statement.h b/weex_core/Source/core/data_render/statement.h
index 4b16bcb866..acd7e1ffa6 100755
--- a/weex_core/Source/core/data_render/statement.h
+++ b/weex_core/Source/core/data_render/statement.h
@@ -159,10 +159,12 @@ class ArrowFunctionStatement : public Expression {
     DEFINE_NODE_TYPE(ArrowFunctionStatement, Expression);
 public:
     ArrowFunctionStatement(Position &loc, Scope *scope, Handle<Expression> body, std::vector<Handle<Expression>> args)
-    : Expression(loc, scope), body_{ body }, args_{std::move(args)} { }
+    : Expression(loc, scope), body_{ body }, args_{std::move(args) } { }
     Handle<Expression> body() { return body_; }
     std::vector<Handle<Expression>>& args() { return args_; }
+    std::string &name() { return name_; }
 private:
+    std::string name_;
     Handle<Expression> body_;
     std::vector<Handle<Expression>> args_;
 };
diff --git a/weex_core/Source/core/data_render/string_table.cc b/weex_core/Source/core/data_render/string_table.cc
index 004b7d8fc6..d0152f1b67 100644
--- a/weex_core/Source/core/data_render/string_table.cc
+++ b/weex_core/Source/core/data_render/string_table.cc
@@ -35,14 +35,15 @@ String::String(const std::string &str) : String(str.c_str(), str.length()) {}
 String::~String() {}
 
 String *StringTable::StringFromUTF8(const std::string &str) {
-  auto it = store_.find(str);
-  if (it != store_.end()) {
-    return it->second.get();
-  }
-  std::string key = str;
-  auto result = new String(key);
-  store_.insert(std::make_pair(std::move(key), std::unique_ptr<String>(result)));
-  return result;
+    for (auto &it : store_) {
+        if (it.first == str) {
+            return it.second.get();
+        }
+    }
+    std::string key = str;
+    auto result = new String(key);
+    store_.push_back(std::make_pair(std::move(key), std::unique_ptr<String>(result)));
+    return result;
 }
 
 StringTable::~StringTable() {}
diff --git a/weex_core/Source/core/data_render/string_table.h b/weex_core/Source/core/data_render/string_table.h
index 8bfd6eb01c..5d1dddd6bd 100644
--- a/weex_core/Source/core/data_render/string_table.h
+++ b/weex_core/Source/core/data_render/string_table.h
@@ -22,7 +22,8 @@
 
 #include <memory>
 #include <string>
-#include <unordered_map>
+#include <map>
+#include <vector>
 
 namespace weex {
 namespace core {
@@ -48,9 +49,10 @@ class StringTable {
   ~StringTable();
 
   String *StringFromUTF8(const std::string &str);
+  inline const std::vector<std::pair<std::string, std::unique_ptr<String>>>& store() {return store_;}
 
  private:
-  std::unordered_map<std::string, std::unique_ptr<String>> store_;
+  std::vector<std::pair<std::string, std::unique_ptr<String>>> store_;
 };
 }  // namespace data_render
 }  // namespace core
diff --git a/weex_core/Source/core/data_render/table.cc b/weex_core/Source/core/data_render/table.cc
index 2d2be10f2c..fc320c44e2 100644
--- a/weex_core/Source/core/data_render/table.cc
+++ b/weex_core/Source/core/data_render/table.cc
@@ -35,7 +35,7 @@ int IndexOf(const std::vector<Value> *arr, const Value *val) {
   }
 }
 
-int SetTableForTable(Table *table, const Value *src, const Value &val) {
+int SetTableForTable(Table *table, const Value *src) {
     int ret = 0;
     do {
         if (!IsTable(src)) {
@@ -75,18 +75,20 @@ int SetTableForKey(Table *t, const Value *key, const Value &val) {
     GCRetain((Value *)&val);
     return 1;
 }
-
-Value *GetTableForKey(Table *t, const Value *key) {
-    std::string str = CStringValue(key);
-    if (!str.empty()) {
-        auto it = t->map.find(str);
-        if (it != t->map.end()) {
-            return &(it->second);
-        }
+    
+Value *GetTableForKey(Table *table, const std::string &key) {
+    auto iter = table->map.find(key);
+    if (iter != table->map.end()) {
+        return &(iter->second);
     }
     return nullptr;
 }
 
+Value *GetTableForKey(Table *table, const Value *key) {
+    std::string keystr = CStringValue(key);
+    return GetTableForKey(table, keystr);
+}
+
 Value *GetTableValue(Table *t, const Value &key) {
     if (IsString(&key)) {
         return GetTableForKey(t, &key);
@@ -111,13 +113,34 @@ Value *GetTableVar(Table *table, const Value &key) {
     
     return ret;
 }
+    
+Value *GetTableValue(Table *table, std::string key)
+{
+    return GetTableForKey(table, key);
+}
+    
+std::vector<std::string> GetTableKeys(Table *table)
+{
+    std::vector<std::string>keys;
+    do {
+        if (!table->map.size()) {
+            break;
+        }
+        for (auto iter = table->map.begin(); iter != table->map.end(); iter++) {
+            keys.push_back(iter->first);
+        }
+        
+    } while (0);
+    
+    return keys;
+}
 
 int SetTableValue(Table *t, Value *key, const Value &val) {
     if (IsString(key)) {
         return SetTableForKey(t, key, val);
     }
     else if (IsTable(key)) {
-        return SetTableForTable(t, key, val);
+        return SetTableForTable(t, key);
     }
     return 0;
 }
@@ -132,24 +155,37 @@ size_t GetTableSize(Table *table) {
     
 json11::Json TableToJson(Table *table);
     
-json11::Json ArrayToJson(Array *array) {
-    json11::Json::array json;
-    for (int i = 0; i < array->items.size(); i++) {
-        Value item = array->items[i];
-        if (item.type == Value::Type::TABLE) {
-            json.push_back(TableToJson(ValueTo<Table>(&item)));
+json11::Json ArrayToJson(Array *p_array) {
+    json11::Json::array array;
+    for (auto it = p_array->items.begin(); it != p_array->items.end(); it++) {
+        if (it->type == Value::STRING) {
+            array.push_back(json11::Json(it->str->c_str()));
+            continue;
+        }
+        if (it->type == Value::BOOL) {
+            array.push_back(json11::Json(it->b));
+            continue;
         }
-        else if (item.type == Value::Type::STRING) {
-            json.push_back(CStringValue(&item));
+        if (it->type == Value::Type::INT) {
+            array.push_back(json11::Json(static_cast<double>(it->i)));
+            continue;
         }
-        else if (item.type == Value::Type::INT) {
-            json.push_back(to_string(IntValue(&item)));
+        if (it->type == Value::Type::NUMBER) {
+            array.push_back(json11::Json(it->n));
+            continue;
         }
-        else if (item.type == Value::Type::ARRAY) {
-            json.push_back(ArrayToJson(ValueTo<Array>(&item)));
+
+        if (it->type == Value::TABLE) {
+            array.push_back(TableToJson(ValueTo<Table>(&*it)));
+            continue;
+        }
+
+        if (it->type == Value::ARRAY) {
+            array.push_back(ArrayToJson(ValueTo<Array>(&*it)));
+            continue;
         }
     }
-    return json;
+    return json11::Json(array);
 }
     
 std::string ArrayToString(Array *array) {
@@ -160,22 +196,39 @@ std::string ArrayToString(Array *array) {
 }
     
 json11::Json TableToJson(Table *table) {
-    json11::Json::object obj;
-    for (auto iter = table->map.begin(); iter != table->map.end(); iter++) {
-        if (iter->second.type == Value::Type::TABLE) {
-            obj.insert(std::make_pair(iter->first, TableToJson(ValueTo<Table>(&iter->second))));
+    json11::Json::object object;
+    for (auto it = table->map.begin(); it != table->map.end(); it++) {
+        if (it->second.type == Value::STRING) {
+            object.insert({it->first, json11::Json(it->second.str->c_str())});
+            continue;
+        }
+        if (it->second.type == Value::BOOL) {
+            object.insert({it->first, json11::Json(it->second.b)});
+            continue;
+        }
+        if (it->second.type == Value::Type::INT) {
+            object.insert(
+                std::make_pair(it->first, json11::Json(static_cast<double>(it->second.i))));
+            continue;
+        }
+        if (it->second.type == Value::Type::NUMBER) {
+            object.insert(
+                std::make_pair(it->first, json11::Json(NumValue(&it->second))));
+            continue;
         }
-        else if (iter->second.type == Value::Type::STRING) {
-            obj.insert(std::make_pair(iter->first, CStringValue(&iter->second)));
+        if (it->second.type == Value::TABLE) {
+            object.insert({it->first, TableToJson(ValueTo<Table>(&it->second))});
+            continue;
         }
-        else if (iter->second.type == Value::Type::INT) {
-            obj.insert(std::make_pair(iter->first, to_string(IntValue(&iter->second))));
+        if (it->second.type == Value::ARRAY) {
+            object.insert({it->first, ArrayToJson(ValueTo<Array>(&it->second))});
+            continue;
         }
-        else if (iter->second.type == Value::Type::ARRAY) {
-            obj.insert(std::make_pair(iter->first, ArrayToJson(ValueTo<Array>(&iter->second))));
+        if (it->second.type == Value::FUNC) {
+            object.insert({it->first, json11::Json("FUNC")});
         }
     }
-    return json11::Json(obj);
+    return json11::Json(object);
 }
     
 std::string TableToString(Table *table) {
diff --git a/weex_core/Source/core/data_render/table.h b/weex_core/Source/core/data_render/table.h
index 97b6c1d495..ffddb2e2bb 100644
--- a/weex_core/Source/core/data_render/table.h
+++ b/weex_core/Source/core/data_render/table.h
@@ -32,6 +32,10 @@ Value *GetTableValue(Table *, const Value &);
     
 Value *GetTableVar(Table *table, const Value &key);
     
+Value *GetTableValue(Table *table, std::string key);
+    
+std::vector<std::string> GetTableKeys(Table *table);
+    
 size_t GetTableSize(Table *);
     
 std::string TableToString(Table *table);
diff --git a/weex_core/Source/core/data_render/vm.cc b/weex_core/Source/core/data_render/vm.cc
index 255da586bd..de057b1146 100644
--- a/weex_core/Source/core/data_render/vm.cc
+++ b/weex_core/Source/core/data_render/vm.cc
@@ -19,6 +19,7 @@
 #include "core/data_render/vm.h"
 #include "core/data_render/exec_state.h"
 #include "core/data_render/object.h"
+#include "core/data_render/class.h"
 #include "core/data_render/table.h"
 #include "core/data_render/common_error.h"
 #include "core/data_render/class_array.h"
@@ -30,6 +31,8 @@ namespace data_render {
 
 void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
 #define LOGTEMP(...)
+//#define LOGTEMP(...)     printf(__VA_ARGS__)
+
 #if DEBUG
   //TimeCost tc;
 #endif
@@ -205,7 +208,7 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
           a = frame.reg + GET_ARG_A(instruction);
           size_t argc = GET_ARG_B(instruction);
           c = frame.reg + GET_ARG_C(instruction);
-          if (!IsFunc(c)) {
+          if (!IsFunction(c)) {
               throw VMExecError("Unspport Type With OP_CODE [OP_CALL]");
           }
           exec_state->CallFunction(c, argc, a);
@@ -302,7 +305,20 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
             a = frame.reg + GET_ARG_A(instruction);
             b = frame.reg + GET_ARG_B(instruction);
             c = frame.reg + GET_ARG_C(instruction);
-            SetBValue(a, ValueOR(b, c));
+            bool bval = false;
+            ToBool(b, bval);
+            if (bval) {
+                *a = *b;
+            }
+            else {
+                ToBool(c, bval);
+                if (bval) {
+                    *a = *c;
+                }
+                else {
+                    SetNil(a);
+                }
+            }
             break;
         }
       case OP_UNM: {
@@ -482,11 +498,11 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
                   }
                   case Value::CLASS_DESC:
                   {
-                      b = exec_state->global()->Find((int)(GET_ARG_C(instruction)));
-                      if (!IsClass(b)) {
+                      c = frame.reg + GET_ARG_C(instruction);
+                      if (!IsClass(c)) {
                           throw VMExecError("Unspport Find Desc with OP_CODE [OP_NEWCLASS]");
                       }
-                      *a = exec_state->class_factory()->CreateClassInstance(ValueTo<ClassDescriptor>(b));
+                      *a = exec_state->class_factory()->CreateClassInstance(ValueTo<ClassDescriptor>(c));
                       break;
                   }
                   default:
@@ -519,13 +535,14 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
         }
         case OP_SETMEMBERVAR:
         {
-            LOGTEMP("OP_SETMEMBER A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction));
+            LOGTEMP("OP_SETMEMBERVAR A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction));
             a = frame.reg + GET_ARG_A(instruction);
             b = frame.reg + GET_ARG_B(instruction);
             if (!IsValueRef(a)) {
                 throw VMExecError("Only ValueRef Support With OP_CODE [OP_SETMEMBER]");
             }
             *a->var = *b;
+            SetNil(a);
             break;
         }
         case OP_GETCLASS:
@@ -540,11 +557,14 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
             if (!IsString(c)) {
                 throw VMExecError("Type Error For Member with OP_CODE [OP_GETCLASS]");
             }
-            int index = ValueTo<ClassInstance>(b)->p_desc_->funcs_->IndexOf(StringValue(c)->c_str());
+            std::string var_name = CStringValue(c);
+            int index = ValueTo<ClassInstance>(b)->p_desc_->funcs_->IndexOf(var_name);
             if (index < 0) {
-                throw VMExecError("Can't Find " + std::string(StringValue(c)->c_str()) + " With OP_CODE [OP_GETCLASS]");
+                SetNil(a);
+            }
+            else {
+                *a = *ValueTo<ClassInstance>(b)->p_desc_->funcs_->Find(index);
             }
-            *a = *ValueTo<ClassInstance>(b)->p_desc_->funcs_->Find(index);
             break;
         }
         case OP_GETMEMBERVAR:
@@ -566,35 +586,20 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
             std::string var_name = CStringValue(c);
             // first find member func
             if (IsClassInstance(b)) {
-                Variables *funcs = ValueTo<ClassInstance>(b)->p_desc_->funcs_.get();
-                int index = funcs->IndexOf(var_name);
-                if (index < 0) {
-                    Variables *vars = ValueTo<ClassInstance>(b)->vars_.get();
-                    index = vars->IndexOf(var_name);
-                    if (index < 0 && op == OP_GETMEMBER) {
+                Value *ret = nullptr;
+                if (op == OP_GETMEMBER) {
+                    ret = GetClassMember(ValueTo<ClassInstance>(b), var_name);
+                    if (!ret) {
                         throw VMExecError("can't find " + var_name + "[OP_GETMEMBER]");
                     }
-                    if (index < 0) {
-                        Value var;
-                        SetNil(&var);
-                        index = vars->Add(var_name, var);
-                    }
-                    Value *ret = vars->Find(index);
-                    if (op == OP_GETMEMBER) {
-                        *a = *ret;
-                    }
-                    else {
-                        SetValueRef(a, ret);
+                    if (IsPrototypeFunction(ret) && ret->f->is_class_func()) {
+                        ret->f->class_inst() = ValueTo<ClassInstance>(b);
                     }
+                    *a = *ret;
                 }
                 else {
-                    Value *ret = funcs->Find(index);
-                    if (op == OP_GETMEMBER) {
-                        *a = *ret;
-                    }
-                    else {
-                        SetValueRef(a, ret);
-                    }
+                    ret = GetClassMemberVar(ValueTo<ClassInstance>(b), var_name);
+                    SetValueRef(a, ret);
                 }
             }
             else if (IsArray(b)) {
@@ -639,9 +644,6 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
                 if (op == OP_GETMEMBER) {
                     Value *ret = GetTableValue(ValueTo<Table>(b), *c);
                     if (!IsNil(ret)) {
-                        if (IsTable(ret)) {
-                            LOGTEMP("[OP_GETMEMBER]:%s\n", TableToString(ValueTo<Table>(ret)).c_str());
-                        }
                         *a = *ret;
                     }
                     else {
diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.cc b/weex_core/Source/core/data_render/vnode/vcomponent.cc
index fd9137dec4..f885cc78c4 100644
--- a/weex_core/Source/core/data_render/vnode/vcomponent.cc
+++ b/weex_core/Source/core/data_render/vnode/vcomponent.cc
@@ -27,9 +27,9 @@ namespace data_render {
 static int g_component_id = 0;
 
 VComponent::VComponent(ExecState *exec_state, int template_id,
-                       const std::string &name, const std::string &ref,
-                       const std::string &tag_name)
-    : VNode(ref, tag_name),
+                       const std::string &name, const std::string &tag_name,
+                       const std::string &node_id, const std::string &ref)
+    : VNode(tag_name, node_id, ref),
       exec_state_(exec_state),
       id_(g_component_id++),
       template_id_(template_id),
diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.h b/weex_core/Source/core/data_render/vnode/vcomponent.h
index 1605f0ba95..6ba011d7bb 100644
--- a/weex_core/Source/core/data_render/vnode/vcomponent.h
+++ b/weex_core/Source/core/data_render/vnode/vcomponent.h
@@ -38,7 +38,8 @@ class VComponent : public VNode {
     virtual void OnDestroyed(VComponent* component) = 0;
   };
   VComponent(ExecState* exec_state, int template_id, const std::string& name,
-             const std::string& ref, const std::string& tag_name);
+             const std::string& tag_name, const std::string& node_id,
+             const std::string& ref);
   ~VComponent();
   void UpdateData(std::unordered_map<std::string, Value> datas);
   void DispatchCreated();
diff --git a/weex_core/Source/core/data_render/vnode/vnode.cc b/weex_core/Source/core/data_render/vnode/vnode.cc
index a8f0a68eb2..4fb66341ff 100644
--- a/weex_core/Source/core/data_render/vnode/vnode.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode.cc
@@ -23,12 +23,15 @@ namespace weex {
 namespace core {
 namespace data_render {
 
-VNode::VNode(const std::string &ref, const std::string &tag_name) {
+VNode::VNode(const std::string &tag_name, const std::string &node_id,
+             const std::string &ref) {
   ref_ = ref;
   tag_name_ = tag_name;
+  node_id_ = node_id;
 
   styles_ = new std::map<std::string, std::string>();
   attributes_ = new std::map<std::string, std::string>();
+  events_ = new std::map<std::string, void *>();
 }
 
 VNode::~VNode() {
@@ -43,7 +46,10 @@ VNode::~VNode() {
     delete attributes_;
     attributes_ = nullptr;
   }
-
+  if (events_) {
+      delete events_;
+      events_ = nullptr;
+  }
   for (auto it = child_list_.begin(); it != child_list_.end(); it++) {
     VNode *&reference = *it;
     if (reference != nullptr) {
@@ -60,23 +66,69 @@ void VNode::SetStyle(const std::string &key, const std::string &value) {
 void VNode::SetAttribute(const std::string &key, const std::string &value) {
   MapInsertOrAssign(attributes_, key, value);
 }
+    
+void VNode::AddEvent(const std::string &event, void *func, void *inst) {
+    std::map<std::string, void *>::iterator it = events_->find(event);
+    if (it != events_->end()) {
+        it->second = func;
+    }
+    else {
+        events_->insert({event, func});
+    }
+    inst_ = inst;
+}
+    
+VNode *VNode::FindNode(const std::string &ref) {
+    VNode *node = nullptr;
+    do {
+        if (this->ref() == ref) {
+            node = this;
+            break;
+        }
+        for (int i = 0; i < child_list_.size(); i++) {
+            node = child_list_[i]->FindNode(ref);
+            if (node) {
+                break;
+            }
+        }
+        
+    } while (0);
+    
+    return node;
+}
 
 void VNode::AddEvent(const std::string &event, const std::string &function,
                      const std::vector<std::string> &params) {
   //todo
 }
-
+    
 void VNode::AddChild(VNode *child) {
   child->parent_ = this;
   child_list_.push_back(child);
 }
+    
+void VNode::InsertChild(VNode *child, int index) {
+    do {
+        child->parent_ = this;
+        if (index < child_list_.size()) {
+            child_list_.insert(child_list_.begin() + index, child);
+            break;
+        }
+        child_list_.push_back(child);
+        
+    } while (0);
+}
 
 void VNode::RemoveChild(VNode *child) {
   child->parent_ = nullptr;
   auto it = child_list_.begin();
   for (; it != child_list_.end(); ++it) {
     if (*it == child) {
+      VNode *&reference = *it;
       child_list_.erase(it);
+      if (reference != nullptr) {
+          delete reference;
+      }
       break;
     }
   }
@@ -93,4 +145,4 @@ void VNode::MapInsertOrAssign(std::map<std::string, std::string> *target_map, co
 }
 }  // namespace data_render
 }  // namespace core
-}  // namespace weex
\ No newline at end of file
+}  // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vnode.h b/weex_core/Source/core/data_render/vnode/vnode.h
index 2d8e3662c6..db2d6b1079 100644
--- a/weex_core/Source/core/data_render/vnode/vnode.h
+++ b/weex_core/Source/core/data_render/vnode/vnode.h
@@ -31,7 +31,8 @@ class VNode;
 
 class VNode {
  public:
-  VNode(const std::string &ref, const std::string &tag_name);
+  VNode(const std::string &tag_name, const std::string &node_id,
+        const std::string &ref);
 
   virtual ~VNode();
 
@@ -41,14 +42,21 @@ class VNode {
 
   void AddEvent(const std::string &event, const std::string &function,
                 const std::vector<std::string> &params);
+  void AddEvent(const std::string &event, void *func, void *inst);
 
   void AddChild(VNode *child);
 
   void RemoveChild(VNode *child);
+    
+  void InsertChild(VNode *child, int index);
+
+  VNode *FindNode(const std::string &ref);
 
  public:
   inline const std::string &tag_name() const { return tag_name_; }
 
+  inline const std::string &node_id() const { return ref_; }
+
   inline const std::string &ref() const { return ref_; }
 
   inline const std::string &render_object_ref() const {
@@ -58,7 +66,7 @@ class VNode {
   inline void set_render_object_ref(std::string ref) {
     render_object_ref_ = std::move(ref);
   }
-
+  inline void *& inst() { return inst_; }
   inline const VNode *parent() const { return parent_; }
 
   inline std::vector<VNode *> *child_list() { return &child_list_; }
@@ -68,21 +76,27 @@ class VNode {
   inline std::map<std::string, std::string> *attributes() const {
     return attributes_;
   }
+  inline std::map<std::string, void *> *events() const {
+    return events_;
+  }
 
   inline bool HasChildren() { return !child_list_.empty(); }
 
  private:
   std::string tag_name_;
+  // Not unique
+  std::string node_id_;
+  // Should be unique
   std::string ref_;
   // Ref point to RenderObject is set when PatchVNode or ParseVNode2RenderObject
   std::string render_object_ref_;
 
   VNode *parent_ = nullptr;
+  void *inst_ = nullptr;
   std::vector<VNode *> child_list_;
-
   std::map<std::string, std::string> *styles_;
   std::map<std::string, std::string> *attributes_;
-
+  std::map<std::string, void *> *events_;
   void MapInsertOrAssign(std::map<std::string, std::string> *target_map,
                          const std::string &key, const std::string &value);
 };
@@ -91,4 +105,4 @@ class VNode {
 }  // namespace core
 }  // namespace weex
 
-#endif  // CORE_DATA_RENDER_VNODE_VNODE_
\ No newline at end of file
+#endif  // CORE_DATA_RENDER_VNODE_VNODE_
diff --git a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc
index 73aea7a673..609b935f48 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc
@@ -24,15 +24,18 @@
 #include "core/data_render/class_factory.h"
 #include "core/data_render/class_array.h"
 #include "core/data_render/class_string.h"
+#include "core/data_render/class_object.h"
 #include "core/data_render/common_error.h"
+#include "core/data_render/js_common_function.h"
 #include "core/data_render/vnode/vcomponent.h"
+#include "core/data_render/vnode/vnode_render_manager.h"
 #include <base/LogDefines.h>
 
 namespace weex {
 namespace core {
 namespace data_render {
 
-json11::Json ParseValue2Json(const Value& value);
+json11::Json ValueToJSON(const Value& value);
 
 static Value Log(ExecState *exec_state) {
   size_t length = exec_state->GetArgumentCount();
@@ -51,6 +54,15 @@ static Value Log(ExecState *exec_state) {
       case Value::Type::TABLE:
         std::cout << "[log]:=>" << TableToString(ValueTo<Table>(a)) << "\n";
         break;
+      case Value::Type::ARRAY:
+        std::cout << "[log]:=>" << ArrayToString(ValueTo<Array>(a)) << "\n";
+        break;
+      case Value::Type::CPTR:
+      {
+          VNode *node = (VNode *)a->cptr;
+          std::cout << "[log]:=> cptr" << node->tag_name() <<"\n";
+          break;
+      }
       default:
         break;
     }
@@ -104,7 +116,7 @@ static Value ToString(ExecState* exec_state) {
     return Value();
   }
 
-  const json11::Json& json = ParseValue2Json(*table);
+  const json11::Json& json = ValueToJSON(*table);
   std::string s;
   json.dump(s);
   String* new_value = exec_state->string_table()->StringFromUTF8(s);
@@ -135,8 +147,42 @@ static Value Slice(ExecState *exec_state) {
     ArrayCopyFrom(*array, new_value, v_start, v_end);
     return new_value;
 }
+    
+static Value CallNativeModule(ExecState *exec_state) {
+    do {
+        if (exec_state->GetArgumentCount() < 1) {
+            break;
+        }
+        Value *arg = exec_state->GetArgument(0);
+        if (!IsTable(arg)) {
+            break;
+        }
+        Value *module = GetTableValue(ValueTo<Table>(arg), std::string("module"));
+        if (!module || !IsString(module)) {
+            break;
+        }
+        Value *method = GetTableValue(ValueTo<Table>(arg), std::string("method"));
+        if (!method || !IsString(method)) {
+            break;
+        }
+        Value *args = GetTableValue(ValueTo<Table>(arg), std::string("args"));
+        if (!args || !IsArray(args)) {
+            break;
+        }
+        int argc = (int)GetArraySize(ValueTo<Array>(args));
+        weex::core::data_render::VNodeRenderManager::GetInstance()->CallNativeModule(exec_state, CStringValue(module), CStringValue(method), argc > 0 ? ArrayToString(ValueTo<Array>(args)) : "", argc);
+        
+    } while(0);
+    
+    return Value();
+}
+    
+static Value RegisterModules(ExecState *exec_state) {
+    weex::core::data_render::VNodeRenderManager::GetInstance()->ExecuteRegisterModules(exec_state);
+    return Value();
+}
 
-static Value AppendUrlParam(ExecState* exec_state) {
+static Value AppendUrlParam(ExecState *exec_state) {
   size_t length = exec_state->GetArgumentCount();
   if (length != 2) {
     return Value();
@@ -193,36 +239,41 @@ static Value AppendChildComponent(ExecState* exec_state) {
   return Value();
 }
 
-// createComponent(template_id, "template_name", "tag_name", "id");
+// createComponent(template_id, "template_name", "tag_name", "id", ref);
 static Value CreateComponent(ExecState* exec_state) {
   int template_id = 0;
   if (exec_state->GetArgument(0)->type == Value::Type::NUMBER) {
     template_id = static_cast<int>(exec_state->GetArgument(0)->i);
   }
   auto template_name = exec_state->GetArgument(1)->str;
-  Value* arg_ref = exec_state->GetArgument(3);
-  std::string ref;
-  if (IsString(arg_ref)) {
-    ref = CStringValue(arg_ref);
-  } else if (IsInt(arg_ref)) {
+  Value* arg_node_id = exec_state->GetArgument(3);
+  std::string node_id;
+  if (IsString(arg_node_id)) {
+    node_id = CStringValue(arg_node_id);
+  } else if (IsInt(arg_node_id)) {
     std::ostringstream os;
-    os << IntValue(arg_ref);
-    ref = "vn_" + os.str();
+    os << IntValue(arg_node_id);
+    node_id = "vn_" + os.str();
   } else {
     throw VMExecError("CreateElement only support int for string");
   }
   std::string tag_name = exec_state->GetArgument(2)->str->c_str();
-  LOGD("[VM][VNode][CreateDocument]: %s  %s\n", ref.c_str(), tag_name.c_str());
+  std::string ref = "";
+  if (exec_state->GetArgumentCount() > 4 &&
+      exec_state->GetArgument(4)->type == Value::Type::STRING) {
+    ref = exec_state->GetArgument(4)->str->c_str();
+  }
+  LOGD("[VM][VNode][CreateDocument]: %s  %s\n", node_id.c_str(), tag_name.c_str());
   VComponent* component = NULL;
   if (tag_name == "root") {
     component = new VComponent(exec_state, template_id, template_name->c_str(),
-                               ref, "div");
+                               "div", node_id, ref);
     if (exec_state->context()->root() == nullptr) {
       exec_state->context()->set_root(component);
     }
   } else {
     component = new VComponent(exec_state, template_id, template_name->c_str(),
-                               ref, tag_name);
+                               tag_name, node_id, ref);
   }
   if (exec_state->context()->root() == nullptr) {
     exec_state->context()->set_root(component);
@@ -232,33 +283,57 @@ static Value CreateComponent(ExecState* exec_state) {
   result.cptr = component;
   return result;
 }
+    
+static Value UpdateElement(ExecState *exec_state) {
+    do {
+        if (exec_state->GetArgumentCount() < 2) {
+            throw VMExecError("UpdateElement needs >= 2 args");
+        }
+        Value *prev = exec_state->GetArgument(0);
+        Value *next = exec_state->GetArgument(1);
+        if (!IsCptr(prev) || !IsCptr(next)) {
+            throw VMExecError("UpdateElement only supporting cptr");
+        }
+        VNode *vn_prev = reinterpret_cast<VNode *>(prev->cptr);
+        VNode *vn_next = reinterpret_cast<VNode *>(next->cptr);
+        VNodeRenderManager::GetInstance()->PatchVNode(exec_state, vn_prev, vn_next);
+        
+    } while (0);
+    
+    return Value();
+}
 
-// createElement("tag_name", "id");
+// createElement("tag_name", "id", ref);
 static Value CreateElement(ExecState *exec_state) {
-    Value *arg_ref = exec_state->GetArgument(1);
-    std::string ref;
-    if (IsString(arg_ref)) {
-        ref = CStringValue(arg_ref);
-    }
-    else if (IsInt(arg_ref)) {
+    Value *arg_node_id = exec_state->GetArgument(1);
+    std::string node_id;
+    if (IsString(arg_node_id)) {
+        node_id = CStringValue(arg_node_id);
+    } else if (IsInt(arg_node_id)) {
         std::ostringstream os;
-        os << IntValue(arg_ref) ;
-        ref = "vn_" + os.str();
-    }
-    else {
+        os << IntValue(arg_node_id) ;
+        node_id = "vn_" + os.str();
+    } else {
         throw VMExecError("CreateElement only support int for string");
     }
     std::string tag_name = exec_state->GetArgument(0)->str->c_str();
-    LOGD("[VM][VNode][CreateElement]: %s  %s\n", ref.c_str(), tag_name.c_str());
+    std::string ref = "";
+    if (exec_state->GetArgumentCount() > 2 &&
+        exec_state->GetArgument(2)->type == Value::Type::STRING) {
+      ref = exec_state->GetArgument(2)->str->c_str();
+    }
+    LOGD("[VM][VNode][CreateElement]: %s  %s\n", node_id.c_str(), tag_name.c_str());
     VNode *node = NULL;
     if (tag_name == "root") {
-        node = new VNode(ref, "div");
-    } else {
-        node = new VNode(ref, tag_name);
-    }
-    if (exec_state->context()->root() == nullptr) {
+        node = new VNode("div", node_id, ref);
         exec_state->context()->set_root(node);
     }
+    else {
+        node = new VNode(tag_name, node_id, ref);
+        if (exec_state->context()->root() == nullptr) {
+            exec_state->context()->set_root(node);
+        }
+    }
     Value result;
     result.type = Value::Type::CPTR;
     result.cptr = node;
@@ -273,35 +348,45 @@ static void AppendChild(ExecState *exec_state, VNode *parent, VNode *children) {
 
 // appendChild(parent, node);
 static Value AppendChild(ExecState *exec_state) {
-  VNode *parent = exec_state->GetArgument(0)->type == Value::Type::NIL ?
-    nullptr : reinterpret_cast<VNode *>(exec_state->GetArgument(0)->cptr);
-  Value *childrens = exec_state->GetArgument(1);
-  if (IsString(childrens) && parent->tag_name() != "text") {
-      throw VMExecError("AppendChild only support string for span");
-  }
-  else if (!IsArray(childrens) && !IsCptr(childrens) && !IsString(childrens)) {
-      throw VMExecError("AppendChild unsupport array or cptr");
-  }
-  if (IsArray(childrens)) {
-      std::vector<Value> items = ValueTo<Array>(childrens)->items;
-      for (int i = 0; i < items.size(); i++) {
-          if (!IsCptr(&items[i])) {
-              throw VMExecError("AppendChild unspport array or cptr");
-          }
-          VNode *children = reinterpret_cast<VNode *>(items[i].cptr);
-          AppendChild(exec_state, parent, children);
-      }
-  }
-  else if (IsString(childrens) && parent) {
-      LOGD("[VM][VNode][AppendChild]:string:%s\n", CStringValue(childrens));
-      parent->SetAttribute("value", CStringValue(childrens));
-  }
-  else {
-      VNode *children = reinterpret_cast<VNode *>(exec_state->GetArgument(1)->cptr);
-      LOGD("[VM][VNode][AppendChild]: %s  %s\n", parent ? parent->ref().c_str() : "null", children->ref().c_str());
-      AppendChild(exec_state, parent, children);
-  }
-  return Value();
+    do {
+        VNode *parent = exec_state->GetArgument(0)->type == Value::Type::NIL ?
+        nullptr : reinterpret_cast<VNode *>(exec_state->GetArgument(0)->cptr);
+        Value *childrens = exec_state->GetArgument(1);
+        if (IsString(childrens) && parent->tag_name() != "text") {
+            throw VMExecError("AppendChild only support string for span");
+        }
+        else if (IsNil(childrens)) {
+            break;
+        }
+        else if (!IsArray(childrens) && !IsCptr(childrens) && !IsString(childrens)) {
+            throw VMExecError("AppendChild unsupport array or cptr");
+        }
+        if (IsArray(childrens)) {
+            std::vector<Value> items = ValueTo<Array>(childrens)->items;
+            for (int i = 0; i < items.size(); i++) {
+                if (IsNil(&items[i])) {
+                    continue;
+                }
+                if (!IsCptr(&items[i])) {
+                    throw VMExecError("AppendChild unspport array or cptr");
+                }
+                VNode *children = reinterpret_cast<VNode *>(items[i].cptr);
+                AppendChild(exec_state, parent, children);
+            }
+        }
+        else if (IsString(childrens) && parent) {
+            LOGD("[VM][VNode][AppendChild]:string:%s\n", CStringValue(childrens));
+            parent->SetAttribute("value", CStringValue(childrens));
+        }
+        else {
+            VNode *children = reinterpret_cast<VNode *>(exec_state->GetArgument(1)->cptr);
+            LOGD("[VM][VNode][AppendChild]: %s  %s\n", parent ? parent->ref().c_str() : "null", children->ref().c_str());
+            AppendChild(exec_state, parent, children);
+        }
+        
+    } while (0);
+    
+    return Value();
 }
 
 // setAttr(node, "value");
@@ -354,8 +439,13 @@ static Value SetProps(ExecState *exec_state) {
                                 node->SetStyle(iter_style->first, to_string(iter_style->second.i));
                                 break;
                             }
+                            case Value::NUMBER:
+                            {
+                                node->SetStyle(iter_style->first, to_string(iter_style->second.n));
+                                break;
+                            }
                             default:
-                                LOGE("can't support type:%i", iter_style->second.type);
+                                LOGE("can't support type:%i\n", iter_style->second.type);
                                 break;
                         }
                     }
@@ -373,8 +463,25 @@ static Value SetProps(ExecState *exec_state) {
                         node->SetAttribute(iter->first, to_string(iter->second.i));
                         break;
                     }
+                    case Value::FUNC:
+                    {
+                        std::string::size_type pos = iter->first.find("on");
+                        if (pos != 0) {
+                            throw VMExecError("AddEvent isn't a function");
+                        }
+                        std::string event = iter->first.substr(pos + 2);
+                        transform(event.begin(), event.end(), event.begin(), ::tolower);
+                        FuncState *func_state = iter->second.f;
+                        node->AddEvent(event, func_state, func_state->class_inst());
+                        break;
+                    }
+                    case Value::NUMBER:
+                    {
+                        node->SetStyle(iter->first, to_string(iter->second.n));
+                        break;
+                    }
                     default:
-                        LOGE("can't support type:%i", iter->second.type);
+                        LOGE("can't support type:%i\n", iter->second.type);
                         break;
                 }
 
@@ -387,14 +494,17 @@ static Value SetProps(ExecState *exec_state) {
 // setClassList(node, "class-name");
 static Value SetClassList(ExecState* exec_state) {
   VNode* node = reinterpret_cast<VNode*>(exec_state->GetArgument(0)->cptr);
-  char* key = exec_state->GetArgument(1)->str->c_str();
+  Value* key = exec_state->GetArgument(1);
+  if (key->type != Value::Type::STRING) {
+      return Value();
+  }
 
   if (node == nullptr) {
     return Value();
   }
 
   auto styles = exec_state->context()->style_json();
-  const json11::Json& style = styles[key];
+  const json11::Json& style = styles[key->str->c_str()];
   if (style.is_null()) {
     return Value();
   }
@@ -405,127 +515,121 @@ static Value SetClassList(ExecState* exec_state) {
   return Value();
 }
 
-void RegisterCFunc(ExecState* state, const std::string& name,
-                   CFunction function) {
-  Value func;
-  func.type = Value::Type::CFUNC;
-  func.cf = reinterpret_cast<void*>(function);
-  state->global()->Add(name, func);
-}
-
-void RegisterClass(ExecState *state, const std::string& name, Value value) {
-    state->global()->Add(name, value);
+// setStyle(node, key, value);
+static Value SetStyle(ExecState* exec_state) {
+  VNode* node = reinterpret_cast<VNode*>(exec_state->GetArgument(0)->cptr);
+  Value* key = exec_state->GetArgument(1);
+  Value* value = exec_state->GetArgument(2);
+  if (node == nullptr || key->type != Value::Type::STRING ||
+      value->type == Value::Type::NIL) {
+    return Value();
+  }
+  node->SetStyle(key->str->c_str(), ToString(value));
+  return Value();
 }
 
-void VNodeExecEnv::InitCFuncEnv(ExecState* state) {
-  // log
-  RegisterCFunc(state, "log", Log);
-  RegisterCFunc(state, "sizeof", SizeOf);
-  RegisterCFunc(state, "slice", Slice);
-  RegisterCFunc(state, "appendUrlParam", AppendUrlParam);
-  RegisterCFunc(state, "merge", Merge);
-  RegisterCFunc(state, "tostring", ToString);
-  RegisterCFunc(state, "createElement", CreateElement);
-  RegisterCFunc(state, "createComponent", CreateComponent);
-  RegisterCFunc(state, "saveComponentDataAndProps", SaveComponentDataAndProps);
-  RegisterCFunc(state, "appendChildComponent", AppendChildComponent);
-  RegisterCFunc(state, "appendChild", AppendChild);
-  RegisterCFunc(state, "encodeURIComponent", encodeURIComponent);
-  RegisterCFunc(state, "setAttr", SetAttr);
-  RegisterCFunc(state, "setProps", SetProps);
-  RegisterCFunc(state, "setClassList", SetClassList);
-  RegisterClass(state, "Array", state->class_factory()->ClassArray());
-  RegisterClass(state, "String", state->class_factory()->ClassString());
-  RegisterClass(state, "JSON", state->class_factory()->ClassJSON());
+void VNodeExecEnv::InitCFuncEnv(ExecState *state) {
+    state->Register("log", Log);
+    state->Register("sizeof", SizeOf);
+    state->Register("slice", Slice);
+    state->Register("appendUrlParam", AppendUrlParam);
+    state->Register("merge", Merge);
+    state->Register("tostring", ToString);
+    state->Register("createElement", CreateElement);
+    state->Register("updateElement", UpdateElement);
+    state->Register("createComponent", CreateComponent);
+    state->Register("saveComponentDataAndProps", SaveComponentDataAndProps);
+    state->Register("appendChildComponent", AppendChildComponent);
+    state->Register("appendChild", AppendChild);
+    state->Register("encodeURIComponent", encodeURIComponent);
+    state->Register("setAttr", SetAttr);
+    state->Register("setProps", SetProps);
+    state->Register("setClassList", SetClassList);
+    state->Register("setStyle", SetStyle);
+    state->Register("__callNativeModule", CallNativeModule);
+    state->Register("__registerModules", RegisterModules);
+    state->Register("Array", state->class_factory()->ClassArray());
+    state->Register("String", state->class_factory()->ClassString());
+    state->Register("JSON", state->class_factory()->ClassJSON());
+    state->Register("Object", state->class_factory()->ClassObject());
+    RegisterJSCommonFunction(state);
 }
 
-Value ParseJson2Value(ExecState* state, const json11::Json& json) {
-  if (json.is_null()) {
-    return Value();
-  } else if (json.is_bool()) {
-    return Value(json.bool_value());
-  } else if (json.is_number()) {
-    std::string value;
-    json.dump(value);
-    if (value.find('.') == std::string::npos) {
-      //int
-      return Value(static_cast<int64_t>(json.number_value()));
-    } else {
-      return Value(json.number_value());
+Value JSONToValue(ExecState *state, const json11::Json& json) {
+    if (json.is_null()) {
+        return Value();
     }
-  } else if (json.is_string()) {
-    String* p_str = state->string_table()->StringFromUTF8(json.string_value());
-    return Value(p_str);
-  } else if (json.is_array()) {
-    Value value = state->class_factory()->CreateArray();
-    const json11::Json::array& data_objects = json.array_items();
-    int64_t array_size = data_objects.size();
-    for (int index = 0; index < array_size; index++) {
-      // will be free by table
-      Value key(index);
-      Value val(ParseJson2Value(state, json[index]));
-      SetArray(ValueTo<Array>(&value), &key, val);
+    else if (json.is_bool()) {
+        return Value(json.bool_value());
     }
-    return value;
-  } else if (json.is_object()) {
-    Value value = state->class_factory()->CreateTable();
-    const json11::Json::object& data_objects = json.object_items();
-    for (auto it = data_objects.begin(); it != data_objects.end(); it++) {
-      // will be free by table
-      Value key(state->string_table()->StringFromUTF8(it->first));
-      Value val(ParseJson2Value(state, it->second));
-      SetTableValue(ValueTo<Table>(&value), &key, val);
+    else if (json.is_number()) {
+        std::string value;
+        json.dump(value);
+        if (value.find('.') == std::string::npos) {
+            //int
+            return Value(static_cast<int64_t>(json.number_value()));
+        }
+        else {
+            return Value(json.number_value());
+        }
+    }
+    else if (json.is_string()) {
+        String *p_str = state->string_table()->StringFromUTF8(json.string_value());
+        return Value(p_str);
+    }
+    else if (json.is_array()) {
+        Value value = state->class_factory()->CreateArray();
+        const json11::Json::array& data_objects = json.array_items();
+        int64_t array_size = data_objects.size();
+        for (int index = 0; index < array_size; index++) {
+            // will be free by table
+            Value key(index);
+            Value val(JSONToValue(state, json[index]));
+            SetArray(ValueTo<Array>(&value), &key, val);
+        }
+        return value;
+    }
+    else if (json.is_object()) {
+        Value value = state->class_factory()->CreateTable();
+        const json11::Json::object& data_objects = json.object_items();
+        for (auto it = data_objects.begin(); it != data_objects.end(); it++) {
+            // will be free by table
+            Value key(state->string_table()->StringFromUTF8(it->first));
+            Value val(JSONToValue(state, it->second));
+            SetTableValue(ValueTo<Table>(&value), &key, val);
+        }
+        return value;
+        
+    }
+    else {
+        return Value();
     }
-    return value;
-  } else {
-    return Value();
-  }
 };
 
-json11::Json ParseValue2Json(const Value& value) {
+json11::Json ValueToJSON(const Value& value) {
     if (value.type != Value::TABLE) {
         return json11::Json();
     }
     Table *p_table = ValueTo<Table>(&value);
-//  if (p_table->array.size() > 0) {
-//    json11::Json::array array;
-//
-//    for (auto it = p_table->array.begin(); it != p_table->array.end(); it++) {
-//      if ((*it).type == Value::STRING) {
-//        array.push_back(json11::Json((*it).str->c_str()));
-//        continue;
-//      }
-//
-//      if ((*it).type == Value::TABLE) {
-//        array.push_back(ParseValue2Json((*it)));
-//        continue;
-//      }
-//    }
-//
-//    return json11::Json(array);
-//  }
-
-  json11::Json::object object;
-  for (auto it = p_table->map.begin(); it != p_table->map.end(); it++) {
-    if (it->second.type == Value::STRING) {
-      object.insert({it->first, json11::Json(it->second.str->c_str())});
-      continue;
-    }
-
-    if (it->second.type == Value::TABLE) {
-      object.insert({it->first, ParseValue2Json(it->second)});
-      continue;
+    json11::Json::object object;
+    for (auto it = p_table->map.begin(); it != p_table->map.end(); it++) {
+        if (it->second.type == Value::STRING) {
+            object.insert({it->first, json11::Json(it->second.str->c_str())});
+            continue;
+        }
+        if (it->second.type == Value::TABLE) {
+            object.insert({it->first, ValueToJSON(it->second)});
+            continue;
+        }
     }
-  }
-
-  return json11::Json(object);
+    return json11::Json(object);
 }
 
 void VNodeExecEnv::InitGlobalValue(ExecState* state) {
   const json11::Json& json = state->context()->raw_json();
   Variables* global = state->global();
   const json11::Json& data = json["data"];
-  Value value = ParseJson2Value(state, data);
+  Value value = JSONToValue(state, data);
   if (value.type != Value::Type::TABLE) {
     value = state->class_factory()->CreateTable();
   }
@@ -542,10 +646,10 @@ void VNodeExecEnv::InitGlobalValue(ExecState* state) {
       if (!name.is_string()) {
         continue;
       }
-      auto temp_data = ParseJson2Value(state, (*it)["data"]);
+      auto temp_data = JSONToValue(state, (*it)["data"]);
       Value key(state->string_table()->StringFromUTF8(name.string_value()));
       SetTableValue(ValueTo<Table>(&components_data), &key, temp_data);
-      auto temp_props = ParseJson2Value(state, (*it)["props"]);
+      auto temp_props = JSONToValue(state, (*it)["props"]);
       SetTableValue(ValueTo<Table>(&components_props), &key, temp_props);
     }
   }
@@ -564,7 +668,7 @@ void VNodeExecEnv::InitInitDataValue(ExecState *state, const std::string& init_d
     return;
   }
 
-  Value value = ParseJson2Value(state, json);
+  Value value = JSONToValue(state, json);
   if (value.type != Value::Type::TABLE) {
     value = state->class_factory()->CreateTable();
   }
@@ -600,6 +704,22 @@ void VNodeExecEnv::InitStyleList(ExecState* state) {
   }
 
 }
+    
+Value StringToValue(ExecState *exec_state,const std::string &str) {
+    Value ret;
+    do {
+        std::string err;
+        json11::Json json = json11::Json::parse(str, err);
+        if (!err.empty() || json.is_null()) {
+            ret = exec_state->string_table()->StringFromUTF8(str);
+            break;
+        }
+        ret = JSONToValue(exec_state, json);
+        
+    } while (0);
+    
+    return ret;
+}
 
 }  // namespace data_render
 }  // namespace core
diff --git a/weex_core/Source/core/data_render/vnode/vnode_exec_env.h b/weex_core/Source/core/data_render/vnode/vnode_exec_env.h
index 8261d5a19e..87ebc90871 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_exec_env.h
+++ b/weex_core/Source/core/data_render/vnode/vnode_exec_env.h
@@ -25,6 +25,7 @@
 namespace weex {
 namespace core {
 namespace data_render {
+    
 class VNodeExecEnv {
  public:
   static void InitCFuncEnv(ExecState* state);
@@ -33,6 +34,9 @@ class VNodeExecEnv {
                                 const std::string& init_data_str);
   static void InitStyleList(ExecState* state);
 };
+    
+Value StringToValue(ExecState *exec_state, const std::string &str);
+
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc
index a3c7ee8dd2..405ad5e50a 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc
@@ -29,6 +29,7 @@
 #include "core/render/manager/render_manager.h"
 #include "core/render/node/factory/render_creator.h"
 #include "core/bridge/platform_bridge.h"
+#include "core/data_render/binary_file.h"
 
 #define VRENDER_LOG true
 
@@ -48,6 +49,8 @@ using std::string;
 using std::vector;
 using WeexCore::RenderManager;
 
+void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node);
+
 VNodeRenderManager* VNodeRenderManager::g_instance = nullptr;
 VM* VNodeRenderManager::g_vm = nullptr;
 // TODO establish linkages between page ref_id
@@ -58,10 +61,12 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode,
                                                 int index,
                                                 const string& pageId) {
   std::string ref_str;
-  if (!isRoot) {
-    ref_str = base::to_string(ref_id++);
-  } else {
+  if (isRoot) {
     ref_str = "_root";
+  } else if (!vnode->ref().empty()) {
+    ref_str = vnode->ref();
+  } else {
+    ref_str = base::to_string(ref_id++);
   }
 
   WeexCore::RenderObject* render_object = static_cast<WeexCore::RenderObject*>(
@@ -83,8 +88,10 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode,
   }
 
   // event,todo
-  //  std::set<string> *event = vnode->event();
-  //  renderObject->events()->insert(event->begin(), event->end());
+  std::map<std::string, void *> *events = vnode->events();
+  for (auto iter = events->begin(); iter != events->end(); iter++) {
+      render_object->events()->insert(iter->first);
+  }
 
   // child
   vector<VNode*>* children = (const_cast<VNode*>(vnode))->child_list();
@@ -105,7 +112,7 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode,
   return render_object;
 }
 
-WeexCore::RenderObject* VNode2RenderObject(VNode* root, const string& page_id) {
+WeexCore::RenderObject *VNode2RenderObject(VNode *root, const string& page_id) {
   return ParseVNode2RenderObject(root, nullptr, true, 0, page_id);
 }
 
@@ -158,54 +165,91 @@ void VNodeRenderManager::InitVM() {
   }
 }
 
-void VNodeRenderManager::CreatePage(const std::string& input,
-                                    const std::string& page_id,
-                                    const std::string& options,
-                                    const std::string& init_data) {
+void VNodeRenderManager::CreatePage(const std::string &input, const std::string &page_id, const  std::string &options, const std::string &init_data) {
+    InitVM();
+    auto start = std::chrono::steady_clock::now();
+    ExecState *exec_state = new ExecState(g_vm);
+    exec_states_.insert({page_id, exec_state});
+    VNodeExecEnv::InitCFuncEnv(exec_state);
+    std::string err;
+    json11::Json json = json11::Json::parse(input, err);
+    if (!err.empty() || json.is_null()) {
+        exec_state->context()->raw_source() = input;
+    }
+    else {
+        exec_state->context()->raw_json() = json;
+    }
+    VNodeExecEnv::InitGlobalValue(exec_state);
+    if (init_data.length() > 0) {
+        VNodeExecEnv::InitInitDataValue(exec_state, init_data);
+    }
+    VNodeExecEnv::InitStyleList(exec_state);
+    exec_state->context()->page_id(page_id);
+    //auto compile_start = std::chrono::steady_clock::now();
+    exec_state->Compile(err);
+    if (!err.empty()) {
+        return;
+    }
+    //auto exec_start = std::chrono::steady_clock::now();
+    exec_state->Execute(err);
+    if (!err.empty()) {
+        return;
+    }
+    if (exec_state->context()->root() == NULL) {
+        return;
+    }
+    CreatePageInternal(page_id, exec_state->context()->root());
+    auto duration_post = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
+
+    LOGE("DATA_RENDER, All time %lld", duration_post.count());
+}
+    
+void VNodeRenderManager::ExecuteRegisterModules(ExecState *exec_state) {
     do {
-        InitVM();
-        auto start = std::chrono::steady_clock::now();
-        ExecState *exec_state = new ExecState(g_vm);
-        exec_states_.insert({page_id, exec_state});
-        VNodeExecEnv::InitCFuncEnv(exec_state);
-        std::string err;
-        json11::Json json = json11::Json::parse(input, err);
-        if (!err.empty() || json.is_null()) {
-            exec_state->context()->raw_source() = input;
-        }
-        else {
-            exec_state->context()->raw_json() = json;
-            if (json["script"].is_string()) {
-                exec_state->context()->set_script(json["script"].string_value());
-            }
-        }
-        VNodeExecEnv::InitGlobalValue(exec_state);
-        if (init_data.length() > 0) {
-            VNodeExecEnv::InitInitDataValue(exec_state, init_data);
-        }
-        VNodeExecEnv::InitStyleList(exec_state);
-        exec_state->context()->page_id(page_id);
-        //auto compile_start = std::chrono::steady_clock::now();
-        exec_state->Compile(err);
-        if (!err.empty()) {
-            break;
-        }
-        //auto exec_start = std::chrono::steady_clock::now();
-        exec_state->Execute(err);
-        if (!err.empty()) {
+        if (!modules_.size()) {
             break;
         }
-        if (exec_state->context()->root() == NULL) {
-            break;
+        const std::string func_name = "registerModule";
+        for (auto iter = modules_.begin(); iter != modules_.end(); iter++) {
+            Value arg = StringToValue(exec_state, *iter);
+            exec_state->Call(func_name, {arg});
         }
-        CreatePageInternal(page_id, exec_state->context()->root());
-        exec_state->context()->Reset();
-        auto duration_post = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
-        
-        LOGE("DATA_RENDER, All time %lld", duration_post.count());
         
     } while (0);
 }
+
+void VNodeRenderManager::CreatePage(const char *contents, unsigned long length, const std::string& page_id, const std::string& options, const std::string& init_data) {
+    BinaryFile *file = BinaryFile::instance();
+    file->set_input(contents);
+    file->set_length(length);
+
+    InitVM();
+    auto start = std::chrono::steady_clock::now();
+    ExecState *exec_state = new ExecState(g_vm);
+    exec_states_.insert({page_id, exec_state});
+    VNodeExecEnv::InitCFuncEnv(exec_state);
+
+    std::string err;
+    exec_state->startDecode();
+    exec_state->endDecode();
+    if (init_data.length() > 0) {
+        VNodeExecEnv::InitInitDataValue(exec_state, init_data);
+    }
+    //auto exec_start = std::chrono::steady_clock::now();
+    exec_state->Execute(err);
+    if (!err.empty()) {
+        return;
+    }
+    if (exec_state->context()->root() == NULL) {
+        return;
+    }
+    CreatePageInternal(page_id, exec_state->context()->root());
+    //exec_state->context()->Reset();
+    auto duration_post = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
+
+    LOGE("DATA_RENDER, All time %lld", duration_post.count());
+}
+
 bool VNodeRenderManager::RefreshPage(const std::string& page_id,
                                      const std::string& init_data) {
     do {
@@ -216,12 +260,12 @@ bool VNodeRenderManager::RefreshPage(const std::string& page_id,
         ExecState *exec_state = it->second;
         VNodeExecEnv::InitInitDataValue(exec_state, init_data);
         std::string err;
+        exec_state->context()->Reset();
         exec_state->Execute(err);  // refresh root
         if (!err.empty()) {
             break;
         }
         RefreshPageInternal(page_id, exec_state->context()->root());
-        exec_state->context()->Reset();
         WeexCore::WeexCoreManager::Instance()
         ->getPlatformBridge()
         ->platform_side()
@@ -238,16 +282,73 @@ bool VNodeRenderManager::ClosePage(const std::string& page_id) {
   if (it == exec_states_.end()) {
     return false;
   }
-  ExecState* exec_state = it->second;
-
+  ExecState *exec_state = it->second;
   ClosePageInternal(page_id);
   delete exec_state;
   exec_states_.erase(it);
   return true;
 }
+        
+void VNodeRenderManager::FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args) {
+    do {
+        auto iter = exec_states_.find(page_id);
+        if (iter == exec_states_.end()) {
+            break;
+        }
+        auto node = vnode_trees_.find(page_id);
+        if (node == vnode_trees_.end()) {
+            break;
+        }
+        auto vnode = node->second->FindNode(ref);
+        if (!vnode) {
+            break;
+        }
+        auto iter_event = vnode->events()->find(event);
+        if (iter_event == vnode->events()->end()) {
+            break;
+        }
+        FuncState *func_state = (FuncState *)iter_event->second;
+        if (!func_state) {
+            break;
+        }
+        ExecState *exec_state = iter->second;
+        std::vector<Value> caller_args;
+        if (func_state->is_class_func() && vnode->inst()) {
+            Value inst;
+            SetCIValue(&inst, reinterpret_cast<GCObject *>(vnode->inst()));
+            caller_args.push_back(inst);
+        }
+        caller_args.push_back(StringToValue(exec_state, args));
+        exec_state->Call(func_state, caller_args);
+        
+    } while (0);
+}
+    
+void VNodeRenderManager::CallNativeModule(ExecState *exec_state, const std::string &module, const std::string &method, const std::string &args, int argc) {
+    do {
+        for (auto iter = exec_states_.begin(); iter != exec_states_.end(); iter++) {
+            if (iter->second == exec_state) {
+                RenderManager::GetInstance()->CallNativeModule(iter->first, module, method, args, argc);
+                break;
+            }
+        }
+        
+    } while (0);
 
-void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node);
-
+}
+    
+void VNodeRenderManager::PatchVNode(ExecState *exec_state, VNode *v_node, VNode *new_node) {
+    do {
+        for (auto iter = exec_states_.begin(); iter != exec_states_.end(); iter++) {
+            if (iter->second == exec_state) {
+                Patch(iter->first, v_node, new_node);
+                break;
+            }
+        }
+        
+    } while (0);
+}
+    
 bool SameNode(VNode* a, VNode* b) {
   return a->tag_name() == b->tag_name() &&
          a->ref() == b->ref();  // todo to be more accurate
@@ -500,7 +601,7 @@ void RemoveNodes(const string& pageId, vector<VNode*>& vec,
                  vector<VNode*>& ref_list, unsigned int start,
                  unsigned int end) {
   for (int i = start; i <= end; ++i) {
-    auto p_node = vec[start];
+    auto p_node = vec[i];
     // some might already been used for patch, which is null.
     if (p_node == nullptr) {
       continue;
@@ -581,10 +682,24 @@ void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) {
   }
 }
 
-void Patch(const string& page_id, VNode* old_root, VNode* new_root) {
-  // root must be the same;
-  PatchVNode(page_id, old_root, new_root);
+void Patch(const string& page_id, VNode *old_node, VNode *new_node) {
+    if (old_node->parent() == NULL || SameNode(old_node, new_node)) {
+        // root must be the same;
+        PatchVNode(page_id, old_node, new_node);
+    }
+    else {
+        VNode *parent = (VNode *)old_node->parent();
+        vector<VNode *> &old_children = *parent->child_list();
+        WeexCore::RenderObject *new_render_object = ParseVNode2RenderObject(new_node, nullptr, false, 0, page_id);
+        auto pos = std::find(old_children.begin(), old_children.end(), old_node);
+        int index = static_cast<int>(std::distance(old_children.begin(), pos));
+        parent->InsertChild(new_node, index);
+        RenderManager::GetInstance()->AddRenderObject(page_id, parent->render_object_ref(), index, new_render_object);
+        parent->RemoveChild(old_node);
+        RenderManager::GetInstance()->RemoveRenderObject(page_id, old_node->render_object_ref());
+    }
 }
+    
 }  // namespace data_render
 }  // namespace core
 }  // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_manager.h b/weex_core/Source/core/data_render/vnode/vnode_render_manager.h
index adc3ae8031..e573016fe7 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_manager.h
+++ b/weex_core/Source/core/data_render/vnode/vnode_render_manager.h
@@ -35,6 +35,7 @@ namespace core {
 namespace data_render {
 
 class VNodeRenderManager {
+ friend class VNode;
  private:
   VNodeRenderManager() {}
 
@@ -42,9 +43,16 @@ class VNodeRenderManager {
 
  public:
   void CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data);
+
+  void CreatePage(const char* contents, unsigned long length, const std::string& page_id, const std::string& options, const std::string& init_data);
+
   bool RefreshPage(const std::string &page_id, const std::string &init_data);
   bool ClosePage(const std::string &page_id);
-
+  void FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args);
+  void ExecuteRegisterModules(ExecState *exec_state);
+  void RegisterModules(const std::string &modules) { modules_.push_back(modules); }
+  void PatchVNode(ExecState *exec_state, VNode *v_node, VNode *new_node);
+  void CallNativeModule(ExecState *exec_state, const std::string &module, const std::string &method, const std::string &args, int argc = 0);
   static VNodeRenderManager *GetInstance() {
     if (!g_instance) {
       g_instance = new VNodeRenderManager();
@@ -64,6 +72,7 @@ class VNodeRenderManager {
   std::map<std::string, VNode *> vnode_trees_;
   std::unordered_map<int, VComponent *> vcomponent_tree_;
   std::map<std::string, ExecState *> exec_states_;
+  std::vector<std::string> modules_;
 };
 }  // namespace data_render
 }  // namespace core
diff --git a/weex_core/Source/core/render/action/render_action_call_native_module.cpp b/weex_core/Source/core/render/action/render_action_call_native_module.cpp
new file mode 100644
index 0000000000..f6d476354c
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_call_native_module.cpp
@@ -0,0 +1,44 @@
+/**
+ * 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.
+ */
+
+#include "core/render/action/render_action_call_native_module.h"
+#include "core/manager/weex_core_manager.h"
+
+namespace WeexCore {
+
+RenderActionCallNativeModule::RenderActionCallNativeModule(const std::string &page_id,
+                                                           const std::string &module,
+                                                           const std::string &method,
+                                                           const std::string &args,
+                                                           int argc) {
+  this->page_id_ = page_id;
+  this->module_ = module;
+  this->method_ = method;
+  this->args_ = args;
+  this->argc_ = argc;
+}
+
+void RenderActionCallNativeModule::ExecuteAction() {
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+    ->CallNativeModule(page_id_.c_str(), module_.c_str(), method_.c_str(), args_.length() > 0 ? args_.c_str() : nullptr, argc_, nullptr, 0);
+    
+}
+}  // namespace WeexCore
diff --git a/weex_core/Source/core/render/action/render_action_call_native_module.h b/weex_core/Source/core/render/action/render_action_call_native_module.h
new file mode 100644
index 0000000000..f21ee38391
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_call_native_module.h
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+#ifndef CORE_RENDER_ACTION_RENDER_ACTION_CALL_NATIVE_MODULE_H_
+#define CORE_RENDER_ACTION_RENDER_ACTION_CALL_NATIVE_MODULE_H_
+
+#include <string>
+
+#include "core/render/action/render_action_interface.h"
+
+namespace WeexCore {
+
+class RenderActionCallNativeModule: public RenderAction {
+ public:
+  explicit RenderActionCallNativeModule(const std::string &page_id,
+                                   const std::string &module,
+                                   const std::string &method, const std::string &args, int argc = 0);
+
+  void ExecuteAction();
+
+ public:
+  std::string page_id_;
+  std::string module_;
+  std::string method_;
+  std::string args_;
+  int argc_;
+};
+}  // namespace WeexCore
+
+#endif  // CORE_RENDER_ACTION_RENDER_ACTION_CALL_NATIVE_MODULE_H_
diff --git a/weex_core/Source/core/render/manager/render_manager.cpp b/weex_core/Source/core/render/manager/render_manager.cpp
index d9a569aee2..49403b8969 100644
--- a/weex_core/Source/core/render/manager/render_manager.cpp
+++ b/weex_core/Source/core/render/manager/render_manager.cpp
@@ -305,6 +305,13 @@ void RenderManager::CallNativeModule(const char *page_id, const char *module, co
     CallMetaModule(page_id, method, arguments);
   }
 }
+    
+void RenderManager::CallNativeModule(const std::string &page_id, const std::string &module, const std::string &method, const std::string &args, int argc) {
+    RenderPage *page = GetPage(page_id);
+    if (page) {
+        page->CallNativeModule(module, method, args, argc);
+    }
+}
 
 void RenderManager::CallMetaModule(const char *page_id, const char *method, const char *arguments) {
   if (strcmp(method, "setViewport") == 0) {
diff --git a/weex_core/Source/core/render/manager/render_manager.h b/weex_core/Source/core/render/manager/render_manager.h
index 20b76b1b70..0507886473 100644
--- a/weex_core/Source/core/render/manager/render_manager.h
+++ b/weex_core/Source/core/render/manager/render_manager.h
@@ -93,7 +93,7 @@ class RenderManager {
                    const std::string &event);
 
   bool CreateFinish(const std::string &page_id);
-
+  void CallNativeModule(const std::string &page_id, const std::string &module, const std::string &method, const std::string &args, int argc = 0);
   void CallNativeModule(const char *page_id, const char *module, const char *method,
                         const char *arguments, int arguments_length, const char *options,
                         int options_length);
diff --git a/weex_core/Source/core/render/page/render_page.cpp b/weex_core/Source/core/render/page/render_page.cpp
index 27a21d8b25..872ce9d318 100644
--- a/weex_core/Source/core/render/page/render_page.cpp
+++ b/weex_core/Source/core/render/page/render_page.cpp
@@ -38,6 +38,7 @@
 #include "core/render/action/render_action_update_attr.h"
 #include "core/render/action/render_action_update_style.h"
 #include "core/render/action/render_action_trigger_vsync.h"
+#include "core/render/action/render_action_call_native_module.h"
 #include "core/render/manager/render_manager.h"
 #include "core/render/node/factory/render_type.h"
 #include "core/render/node/render_list.h"
@@ -405,10 +406,17 @@ bool RenderPage::CreateFinish() {
   SendCreateFinishAction();
   // RenderSuccess means the Dom created after executing script finishes layout
   // and render, it will be trigger even though body not yet attaches to parent.
+#ifdef OS_ANDROID
   LayoutInner();
+#endif
   SendRenderSuccessAction();
   return true;
 }
+    
+void RenderPage::CallNativeModule(const std::string &module,
+                      const std::string &method, const std::string &args, int argc) {
+  SendCallNativeModuleAction(module, method, args, argc);
+}
 
 void RenderPage::LayoutInner() {
   CalculateLayout();
@@ -539,6 +547,12 @@ void RenderPage::SendLayoutAction(RenderObject *render, int index) {
   RenderAction *action = new RenderActionLayout(page_id(), render, index);
   PostRenderAction(action);
 }
+    
+void RenderPage::SendCallNativeModuleAction(const std::string &module,
+                                const std::string &method, const std::string &args, int argc) {
+  RenderAction *action = new RenderActionCallNativeModule(page_id(), module, method, args, argc);
+  PostRenderAction(action);
+}
 
 void RenderPage::SendUpdateStyleAction(
     RenderObject *render,
diff --git a/weex_core/Source/core/render/page/render_page.h b/weex_core/Source/core/render/page/render_page.h
index ee739fbc79..46cbd77618 100644
--- a/weex_core/Source/core/render/page/render_page.h
+++ b/weex_core/Source/core/render/page/render_page.h
@@ -66,6 +66,9 @@ class RenderPage {
       RenderObject *render,
       std::vector<std::pair<std::string, std::string>> *attrs);
 
+  void SendCallNativeModuleAction(const std::string &module,
+                                  const std::string &method, const std::string &args, int argc = 0);
+    
   void SendCreateFinishAction();
 
   void SendRenderSuccessAction();
@@ -73,7 +76,7 @@ class RenderPage {
   void SendAppendTreeCreateFinish(const std::string &ref);
 
   void PostRenderAction(RenderAction *action);
-
+  
   void LayoutInner();
 
 public:
@@ -127,6 +130,9 @@ class RenderPage {
                             std::map<std::string, std::string> *attrs);
 
   RenderObject *GetRenderObject(const std::string &ref);
+    
+  void CallNativeModule(const std::string &module,
+                          const std::string &method, const std::string &args, int argc = 0);
 
   void SetRootRenderObject(RenderObject *root);
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services