You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by GitBox <gi...@apache.org> on 2018/12/20 06:10:08 UTC
[GitHub] doumafang closed pull request #1937: * [Android][iOS][C++] Add
eagle version of data-render
doumafang closed pull request #1937: * [Android][iOS][C++] Add eagle version of data-render
URL: https://github.com/apache/incubator-weex/pull/1937
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/WeexSDK.podspec b/WeexSDK.podspec
index bcb274354d..f0ae7627d1 100644
--- a/WeexSDK.podspec
+++ b/WeexSDK.podspec
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
Alibaba-INC copyright
LICENSE
}
- s.authors = {
+ s.authors = {
"cxfeng1" => "cxfeng1@gmail.com",
"boboning" => "ningli928@163.com",
"yangshengtao" => "yangshengtao1314@163.com",
@@ -32,7 +32,7 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '8.0'
# use for public
- # s.source = {
+ # s.source = {
# :git => 'https://github.com/apache/incubator-weex.git',
# :tag => #{s.version}
# }
@@ -46,7 +46,8 @@ Pod::Spec.new do |s|
'weex_core/Source/wson/**/*.{h,hpp,m,mm,c,cpp,cc}',
'weex_core/Source/third_party/**/*.{h,hpp,m,mm,c,cpp,cc}',
'weex_core/Source/include/**/*.{h,hpp,m,mm,c,cpp,cc}'
- s.exclude_files = 'weex_core/Source/**/*android.{h,hpp,m,mm,c,cpp,cc}'
+ s.exclude_files = 'weex_core/Source/**/*android.{h,hpp,m,mm,c,cpp,cc}',
+ 'weex_core/Source/core/network/android/'
s.private_header_files = 'ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.h'
s.public_header_files = 'ios/sdk/WeexSDK/Sources/WeexSDK.h',
diff --git a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
index b6d8e56eeb..606b5d1442 100644
--- a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
+++ b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
@@ -44,7 +44,6 @@
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;
-
import com.alibaba.fastjson.JSON;
import com.alibaba.weex.commons.WXAnalyzerDelegate;
import com.alibaba.weex.constants.Constants;
@@ -63,7 +62,6 @@
import com.taobao.weex.ui.component.WXVContainer;
import com.taobao.weex.utils.WXFileUtils;
import com.taobao.weex.utils.WXLogUtils;
-
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
@@ -246,8 +244,11 @@ public void onSuccess(WXHttpTask task) {
try {
Uri uri = Uri.parse(url);
mConfigMap.put("bundleUrl", url);
- if (uri.getPath().endsWith(".wlasm")){
+ if(TextUtils.equals(uri.getQueryParameter("__eagle"), Boolean.TRUE.toString())){
mInstance.render(TAG, task.response.data, mConfigMap, null);
+ }
+ else if (TextUtils.equals(uri.getQueryParameter("__data_render"), Boolean.TRUE.toString())){
+ mInstance.render(TAG, new String(task.response.data, "UTF-8"), mConfigMap, null, WXRenderStrategy.DATA_RENDER);
} else {
mInstance.render(TAG, new String(task.response.data, "utf-8"), mConfigMap, null, WXRenderStrategy.APPEND_ASYNC);
}
diff --git a/android/sdk/.gitignore b/android/sdk/.gitignore
index 25d11795bb..9c18c2d738 100755
--- a/android/sdk/.gitignore
+++ b/android/sdk/.gitignore
@@ -14,6 +14,3 @@ lint.xml
project.properties
assets/main.js
.externalNativeBuild
-libs/armeabi/libweexcore.so
-libs/armeabi-v7a/libweexcore.so
-libs/x86/libweexcore.so
\ No newline at end of file
diff --git a/android/sdk/build.gradle b/android/sdk/build.gradle
index ecba7bc571..e8986f530a 100755
--- a/android/sdk/build.gradle
+++ b/android/sdk/build.gradle
@@ -60,6 +60,10 @@ version = project.hasProperty('weexVersion')? project.getProperty('weexVersion')
android {
+ delete 'libs/armeabi/libweexcore.so'
+ delete 'libs/armeabi-v7a/libweexcore.so'
+ delete 'libs/x86/libweexcore.so'
+
compileSdkVersion project.compileSdkVersion
buildToolsVersion project.buildToolsVersion
resourcePrefix "weex"
diff --git a/android/sdk/libs/armeabi-v7a/libweexjss.so b/android/sdk/libs/armeabi-v7a/libweexjss.so
index de119edb24..50e261a9c2 100755
Binary files a/android/sdk/libs/armeabi-v7a/libweexjss.so and b/android/sdk/libs/armeabi-v7a/libweexjss.so differ
diff --git a/android/sdk/libs/armeabi/libweexjss.so b/android/sdk/libs/armeabi/libweexjss.so
index de119edb24..50e261a9c2 100755
Binary files a/android/sdk/libs/armeabi/libweexjss.so and b/android/sdk/libs/armeabi/libweexjss.so differ
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXHttpListener.java b/android/sdk/src/main/java/com/taobao/weex/WXHttpListener.java
new file mode 100644
index 0000000000..4e10863e2c
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/WXHttpListener.java
@@ -0,0 +1,260 @@
+/**
+ * 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.net.Uri;
+import android.text.TextUtils;
+
+import com.taobao.weex.adapter.IWXHttpAdapter;
+import com.taobao.weex.adapter.IWXUserTrackAdapter;
+import com.taobao.weex.common.WXErrorCode;
+import com.taobao.weex.common.WXPerformance;
+import com.taobao.weex.common.WXRenderStrategy;
+import com.taobao.weex.common.WXResponse;
+import com.taobao.weex.performance.WXInstanceApm;
+import com.taobao.weex.tracing.WXTracing;
+import com.taobao.weex.utils.WXLogUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * load bundle js listener
+ */
+public class WXHttpListener implements IWXHttpAdapter.OnHttpListener {
+
+ private String pageName;
+ private Map<String, Object> options;
+ private String jsonInitData;
+ private WXRenderStrategy flag;
+ private WXSDKInstance instance;
+ private long startRequestTime;
+ private int traceId;
+ private WXPerformance mWXPerformance;
+ private WXInstanceApm mApmForInstance;
+ private IWXUserTrackAdapter mUserTrackAdapter;
+
+ private String mBundleUrl;
+
+ public WXHttpListener(WXSDKInstance instance) {
+ this.instance = instance;
+ this.traceId = WXTracing.nextId();
+ this.mWXPerformance = instance.getWXPerformance();
+ this.mApmForInstance = instance.getApmForInstance();
+ this.mUserTrackAdapter = WXSDKManager.getInstance().getIWXUserTrackAdapter();
+ if (WXTracing.isAvailable()) {
+ WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -1);
+ event.iid = instance.getInstanceId();
+ event.tname = "Network";
+ event.ph = "B";
+ event.traceId = traceId;
+ event.submit();
+ }
+ }
+
+ public WXHttpListener(WXSDKInstance instance, String bundleUrl) {
+ this(instance);
+ this.startRequestTime = System.currentTimeMillis();
+ this.mBundleUrl = bundleUrl;
+ }
+
+ public WXHttpListener(WXSDKInstance instance, String pageName, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag, long startRequestTime) {
+ this(instance);
+ this.pageName = pageName;
+ this.options = options;
+ this.jsonInitData = jsonInitData;
+ this.flag = flag;
+ this.startRequestTime = startRequestTime;
+ this.mBundleUrl = instance.getBundleUrl();
+ }
+
+ public void setSDKInstance(WXSDKInstance instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public void onHttpStart() {
+ if (this.instance != null
+ && this.instance.getWXStatisticsListener() != null) {
+ this.instance.getWXStatisticsListener().onHttpStart();
+ }
+ }
+
+ @Override
+ public void onHeadersReceived(int statusCode, Map<String,List<String>> headers) {
+ if (this.instance != null
+ && this.instance.getWXStatisticsListener() != null) {
+ this.instance.getWXStatisticsListener().onHeadersReceived();
+ this.instance.onHttpStart();
+ }
+ if(this.instance != null
+ && this.instance.responseHeaders != null
+ && headers != null){
+ this.instance.responseHeaders.putAll(headers);
+ }
+ }
+
+ @Override
+ public void onHttpUploadProgress(int uploadProgress) {
+
+ }
+
+ @Override
+ public void onHttpResponseProgress(int loadedLength) {
+ instance.getApmForInstance().extInfo.put(WXInstanceApm.VALUE_BUNDLE_LOAD_LENGTH,loadedLength);
+ }
+
+ @Override
+ public void onHttpFinish(WXResponse response) {
+
+ if (this.instance != null
+ && this.instance.getWXStatisticsListener() != null) {
+ this.instance.getWXStatisticsListener().onHttpFinish();
+ }
+
+ if (WXTracing.isAvailable()) {
+ WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -1);
+ event.traceId = traceId;
+ event.tname = "Network";
+ event.ph = "E";
+ event.extParams = new HashMap<>();
+ if (response != null && response.originalData != null) {
+ event.extParams.put("BundleSize", response.originalData.length);
+ }
+ event.submit();
+ }
+
+ mWXPerformance.networkTime = System.currentTimeMillis() - startRequestTime;
+ if(null!= response && response.extendParams!=null){
+ mApmForInstance.updateRecordInfo(response.extendParams);
+ Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
+ mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;
+
+ Object pureNetworkTime=response.extendParams.get("pureNetworkTime");
+ mWXPerformance.pureNetworkTime=pureNetworkTime instanceof Long?(long)pureNetworkTime:0;
+
+ Object connectionType=response.extendParams.get("connectionType");
+ mWXPerformance.connectionType=connectionType instanceof String?(String)connectionType:"";
+
+ Object packageSpendTime=response.extendParams.get("packageSpendTime");
+ mWXPerformance.packageSpendTime=packageSpendTime instanceof Long ?(long)packageSpendTime:0;
+
+ Object syncTaskTime=response.extendParams.get("syncTaskTime");
+ mWXPerformance.syncTaskTime=syncTaskTime instanceof Long ?(long)syncTaskTime:0;
+
+ Object requestType=response.extendParams.get("requestType");
+ mWXPerformance.requestType=requestType instanceof String?(String)requestType:"none";
+
+ Object cacheType = response.extendParams.get(WXPerformance.Dimension.cacheType.toString());
+ if(cacheType instanceof String){
+ mWXPerformance.cacheType = (String) cacheType;
+ }
+
+ Object zCacheInfo = response.extendParams.get("zCacheInfo");
+ mWXPerformance.zCacheInfo = zCacheInfo instanceof String?(String)zCacheInfo:"";
+
+ if(isNet(mWXPerformance.requestType) && mUserTrackAdapter!=null){
+ WXPerformance performance=new WXPerformance(instance.getInstanceId());
+ if(!TextUtils.isEmpty(mBundleUrl)){
+ try {
+ performance.args= Uri.parse(mBundleUrl).buildUpon().clearQuery().toString();
+ } catch (Exception e) {
+ performance.args=pageName;
+ }
+ }
+ if(!"200".equals(response.statusCode)){
+ performance.errCode= WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
+ performance.appendErrMsg(response.errorCode);
+ performance.appendErrMsg("|");
+ performance.appendErrMsg(response.errorMsg);
+
+ }else if("200".equals(response.statusCode) && (response.originalData==null || response.originalData.length<=0)){
+ performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
+ performance.appendErrMsg(response.statusCode);
+ performance.appendErrMsg("|template is null!");
+ }else {
+ performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
+ }
+
+ if (mUserTrackAdapter != null) {
+ mUserTrackAdapter.commit(instance.getContext(), null, IWXUserTrackAdapter.JS_DOWNLOAD, performance, null);
+ }
+ }
+ }
+ String wxErrorCode = WXInstanceApm.VALUE_ERROR_CODE_DEFAULT;
+ if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
+ mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_END);
+ onSuccess(response);
+
+ // check content-type
+ } else if (TextUtils.equals(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
+ response.statusCode)) {
+ WXLogUtils.e("user intercept: WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR");
+ wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode();
+ instance.onRenderError(wxErrorCode,
+ "|response.errorMsg==" + response.errorMsg +
+ "|instance bundleUrl = \n" + instance.getBundleUrl() +
+ "|instance requestUrl = \n" + Uri.decode(WXSDKInstance.requestUrl)
+ );
+ onFail(response);
+
+ // check content-length
+ } else if (response!=null && response.originalData!=null && TextUtils.equals("-206", response.statusCode)) {
+ WXLogUtils.e("user intercept: WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED");
+ wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode();
+ instance.onRenderError(wxErrorCode ,
+ WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode() +
+ "|response.errorMsg==" + response.errorMsg
+ );
+ onFail(response);
+ }
+ else {
+ wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode();
+ instance.onRenderError(wxErrorCode,
+ response.errorMsg);
+ onFail(response);
+ }
+ if (!WXInstanceApm.VALUE_ERROR_CODE_DEFAULT.equals(wxErrorCode)){
+ mApmForInstance.addProperty(WXInstanceApm.KEY_PROPERTIES_ERROR_CODE,wxErrorCode);
+ }
+ }
+
+ private boolean isNet(String requestType){
+
+ return "network".equals(requestType) || "2g".equals(requestType) || "3g".equals(requestType)
+ || "4g".equals(requestType) || "wifi".equals(requestType) || "other".equals(requestType)
+ || "unknown".equals(requestType);
+ }
+
+ public void onSuccess(WXResponse response) {
+ if (flag==WXRenderStrategy.DATA_RENDER_BINARY){
+ instance.render(pageName, response.originalData, options, jsonInitData);
+ }else {
+ String template = new String(response.originalData);
+ instance.render(pageName, template, options, jsonInitData, flag);
+ }
+ }
+
+ public void onFail(WXResponse response) {
+
+ }
+}
+
+
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 19404b3f05..36ca0bb56d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
@@ -18,6 +18,9 @@
*/
package com.taobao.weex;
+import static com.taobao.weex.common.WXErrorCode.WX_ERR_RELOAD_PAGE;
+import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
@@ -37,12 +40,11 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
-
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.adapter.IDrawableLoader;
-import com.taobao.weex.adapter.IWXJscProcessManager;
import com.taobao.weex.adapter.IWXHttpAdapter;
import com.taobao.weex.adapter.IWXImgLoaderAdapter;
+import com.taobao.weex.adapter.IWXJscProcessManager;
import com.taobao.weex.adapter.IWXUserTrackAdapter;
import com.taobao.weex.adapter.URIAdapter;
import com.taobao.weex.appfram.websocket.IWebSocketAdapter;
@@ -57,11 +59,9 @@
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.common.WXModule;
import com.taobao.weex.common.WXPerformance;
-import com.taobao.weex.common.WXPerformance.Dimension;
import com.taobao.weex.common.WXRefreshData;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.common.WXRequest;
-import com.taobao.weex.common.WXResponse;
import com.taobao.weex.dom.WXEvent;
import com.taobao.weex.http.WXHttpUtil;
import com.taobao.weex.instance.InstanceOnFireEventInterceptor;
@@ -82,7 +82,6 @@
import com.taobao.weex.utils.WXReflectionUtils;
import com.taobao.weex.utils.WXUtils;
import com.taobao.weex.utils.WXViewUtils;
-
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -92,9 +91,6 @@
import java.util.PriorityQueue;
import java.util.concurrent.ConcurrentHashMap;
-import static com.taobao.weex.common.WXErrorCode.WX_ERR_RELOAD_PAGE;
-import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT;
-
/**
* Each instance of WXSDKInstance represents an running weex instance.
@@ -797,7 +793,7 @@ private void renderByUrlInternal(String pageName,
wxRequest.paramMap.put(KEY_USER_AGENT, WXHttpUtil.assembleUserAgent(mContext,WXEnvironment.getConfig()));
wxRequest.paramMap.put("isBundleRequest","true");
WXHttpListener httpListener =
- new WXHttpListener(pageName, renderOptions, jsonInitData, flag, System.currentTimeMillis());
+ new WXHttpListener(this, pageName, renderOptions, jsonInitData, flag, System.currentTimeMillis());
httpListener.setSDKInstance(this);
mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_START);
adapter.sendRequest(wxRequest, (IWXHttpAdapter.OnHttpListener) httpListener);
@@ -1908,198 +1904,6 @@ public void onHttpStart(){
}
}
- /**
- * load bundle js listener
- */
- class WXHttpListener implements IWXHttpAdapter.OnHttpListener {
-
- private String pageName;
- private Map<String, Object> options;
- private String jsonInitData;
- private WXRenderStrategy flag;
- private WXSDKInstance instance;
- private long startRequestTime;
- private int traceId;
-
- private WXHttpListener(String pageName, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag, long startRequestTime) {
- this.pageName = pageName;
- this.options = options;
- this.jsonInitData = jsonInitData;
- this.flag = flag;
- this.startRequestTime = startRequestTime;
- this.traceId = WXTracing.nextId();
-
- if (WXTracing.isAvailable()) {
- WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", mInstanceId, -1);
- event.iid = mInstanceId;
- event.tname = "Network";
- event.ph = "B";
- event.traceId = traceId;
- event.submit();
- }
- }
-
- public void setSDKInstance(WXSDKInstance instance) {
- this.instance = instance;
- }
-
- @Override
- public void onHttpStart() {
- if (this.instance != null
- && this.instance.getWXStatisticsListener() != null) {
- this.instance.getWXStatisticsListener().onHttpStart();
- }
- }
-
- @Override
- public void onHeadersReceived(int statusCode, Map<String,List<String>> headers) {
- if (this.instance != null
- && this.instance.getWXStatisticsListener() != null) {
- this.instance.getWXStatisticsListener().onHeadersReceived();
- this.instance.onHttpStart();
- }
- if(this.instance != null
- && this.instance.responseHeaders != null
- && headers != null){
- this.instance.responseHeaders.putAll(headers);
- }
- }
-
- @Override
- public void onHttpUploadProgress(int uploadProgress) {
-
- }
-
- @Override
- public void onHttpResponseProgress(int loadedLength) {
- getApmForInstance().extInfo.put(WXInstanceApm.VALUE_BUNDLE_LOAD_LENGTH,loadedLength);
- }
-
- @Override
- public void onHttpFinish(WXResponse response) {
-
- if (this.instance != null
- && this.instance.getWXStatisticsListener() != null) {
- this.instance.getWXStatisticsListener().onHttpFinish();
- }
-
- if (WXTracing.isAvailable()) {
- WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", mInstanceId, -1);
- event.traceId = traceId;
- event.tname = "Network";
- event.ph = "E";
- event.extParams = new HashMap<>();
- if (response != null && response.originalData != null) {
- event.extParams.put("BundleSize", response.originalData.length);
- }
- event.submit();
- }
-
- mWXPerformance.networkTime = System.currentTimeMillis() - startRequestTime;
- if(null!= response && response.extendParams!=null){
- mApmForInstance.updateRecordInfo(response.extendParams);
- Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
- mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;
-
- Object pureNetworkTime=response.extendParams.get("pureNetworkTime");
- mWXPerformance.pureNetworkTime=pureNetworkTime instanceof Long?(long)pureNetworkTime:0;
-
- Object connectionType=response.extendParams.get("connectionType");
- mWXPerformance.connectionType=connectionType instanceof String?(String)connectionType:"";
-
- Object packageSpendTime=response.extendParams.get("packageSpendTime");
- mWXPerformance.packageSpendTime=packageSpendTime instanceof Long ?(long)packageSpendTime:0;
-
- Object syncTaskTime=response.extendParams.get("syncTaskTime");
- mWXPerformance.syncTaskTime=syncTaskTime instanceof Long ?(long)syncTaskTime:0;
-
- Object requestType=response.extendParams.get("requestType");
- mWXPerformance.requestType=requestType instanceof String?(String)requestType:"none";
-
- Object cacheType = response.extendParams.get(Dimension.cacheType.toString());
- if(cacheType instanceof String){
- mWXPerformance.cacheType = (String) cacheType;
- }
-
- Object zCacheInfo = response.extendParams.get("zCacheInfo");
- mWXPerformance.zCacheInfo = zCacheInfo instanceof String?(String)zCacheInfo:"";
-
- if(isNet(mWXPerformance.requestType) && mUserTrackAdapter!=null){
- WXPerformance performance=new WXPerformance(mInstanceId);
- if(!TextUtils.isEmpty(mBundleUrl)){
- try {
- performance.args= Uri.parse(mBundleUrl).buildUpon().clearQuery().toString();
- } catch (Exception e) {
- performance.args=pageName;
- }
- }
- if(!"200".equals(response.statusCode)){
- performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
- performance.appendErrMsg(response.errorCode);
- performance.appendErrMsg("|");
- performance.appendErrMsg(response.errorMsg);
-
- }else if("200".equals(response.statusCode) && (response.originalData==null || response.originalData.length<=0)){
- performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
- performance.appendErrMsg(response.statusCode);
- performance.appendErrMsg("|template is null!");
- }else {
- performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
- }
-
- if (mUserTrackAdapter != null) {
- mUserTrackAdapter.commit(getContext(), null, IWXUserTrackAdapter.JS_DOWNLOAD, performance, null);
- }
- }
- }
- String wxErrorCode = WXInstanceApm.VALUE_ERROR_CODE_DEFAULT;
- if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
- mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_END);
- if (flag==WXRenderStrategy.DATA_RENDER_BINARY){
- render(pageName, response.originalData, options, jsonInitData);
- } else {
- String template = new String(response.originalData);
- render(pageName, template, options, jsonInitData, flag);
- }
-
- // check content-type
- } else if (TextUtils.equals(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
- response.statusCode)) {
- WXLogUtils.e("user intercept: WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR");
- wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode();
- onRenderError(wxErrorCode,
- "|response.errorMsg==" + response.errorMsg +
- "|instance bundleUrl = \n" + instance.getBundleUrl() +
- "|instance requestUrl = \n" + Uri.decode(WXSDKInstance.requestUrl)
- );
-
- // check content-length
- } else if (response!=null && response.originalData!=null && TextUtils.equals("-206", response.statusCode)) {
- WXLogUtils.e("user intercept: WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED");
- wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode();
- onRenderError(wxErrorCode ,
- WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode() +
- "|response.errorMsg==" + response.errorMsg
- );
- }
- else {
- wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode();
- onRenderError(wxErrorCode,
- response.errorMsg);
- }
- if (!WXInstanceApm.VALUE_ERROR_CODE_DEFAULT.equals(wxErrorCode)){
- mApmForInstance.addProperty(WXInstanceApm.KEY_PROPERTIES_ERROR_CODE,wxErrorCode);
- }
- }
- }
-
- private boolean isNet(String requestType){
-
- return "network".equals(requestType) || "2g".equals(requestType) || "3g".equals(requestType)
- || "4g".equals(requestType) || "wifi".equals(requestType) || "other".equals(requestType)
- || "unknown".equals(requestType);
- }
-
/**
* return md5, and bytes length
* */
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/RequestHandler.java b/android/sdk/src/main/java/com/taobao/weex/bridge/RequestHandler.java
new file mode 100644
index 0000000000..a5bf160b80
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/RequestHandler.java
@@ -0,0 +1,101 @@
+/**
+ * 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.bridge;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.WXHttpListener;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.adapter.IWXHttpAdapter;
+import com.taobao.weex.adapter.URIAdapter;
+import com.taobao.weex.base.CalledByNative;
+import com.taobao.weex.common.WXRequest;
+import com.taobao.weex.common.WXResponse;
+import com.taobao.weex.http.WXHttpUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT;
+
+public class RequestHandler {
+
+ native void nativeInvokeOnSuccess(long callback, String result);
+ native void nativeInvokeOnFailed(long callback);
+
+ @CalledByNative
+ public static RequestHandler create() {
+ return new RequestHandler();
+ }
+
+ @CalledByNative
+ public void send(String instanceId, String url, long nativeCallback) {
+ if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(url) ||
+ nativeCallback == 0 ||
+ !WXSDKManager.getInstance().getAllInstanceMap().containsKey(
+ instanceId)) {
+ return;
+ }
+
+ WXSDKManager manager = WXSDKManager.getInstance();
+ WXSDKInstance instance =
+ WXSDKManager.getInstance().getSDKInstance(instanceId);
+ if (instance == null)
+ return;
+ IWXHttpAdapter adapter = WXSDKManager.getInstance().getIWXHttpAdapter();
+
+ WXRequest wxRequest = new WXRequest();
+ wxRequest.url = manager.getURIAdapter()
+ .rewrite(instance, URIAdapter.BUNDLE, Uri.parse(url))
+ .toString();
+
+ if (wxRequest.paramMap == null) {
+ wxRequest.paramMap = new HashMap<>();
+ }
+ wxRequest.paramMap.put(
+ KEY_USER_AGENT, WXHttpUtil.assembleUserAgent(
+ instance.getContext(), WXEnvironment.getConfig()));
+ wxRequest.paramMap.put("isBundleRequest", "true");
+ adapter.sendRequest(wxRequest, new OnHttpListenerInner(instance, nativeCallback, url));
+ }
+
+ class OnHttpListenerInner extends WXHttpListener {
+ private long sNativeCallback;
+
+ OnHttpListenerInner(WXSDKInstance instance, long nativeCallback, String bundlUrl) {
+ super(instance, bundlUrl);
+ sNativeCallback = nativeCallback;
+ }
+
+ @Override
+ public void onSuccess(WXResponse response) {
+ String script = new String(response.originalData);
+ nativeInvokeOnSuccess(sNativeCallback, script);
+ }
+
+ @Override
+ public void onFail(WXResponse response) {
+ nativeInvokeOnFailed(sNativeCallback);
+ }
+ }
+}
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 de3db66392..15fd4386f5 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
@@ -69,7 +69,7 @@
public native String nativeExecJSOnInstance(String instanceId, String script, int type);
- public native void nativeFireEventOnDataRenderNode(String instanceId, String ref, String type, String data);
+ public native void nativeFireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String domChanges);
public native void nativeRegisterModuleOnDataRenderNode( String data);
@@ -256,7 +256,12 @@ public Object callNativeModule(String instanceId, String module, String method,
// TODO use a better way
if (instance!=null && (instance.getRenderStrategy()== WXRenderStrategy.DATA_RENDER
|| instance.getRenderStrategy()== WXRenderStrategy.DATA_RENDER_BINARY)){
- argArray = (JSONArray) JSON.parse(new String(arguments, "UTF-8"));
+ try {
+ argArray = (JSONArray) JSON.parse(new String(arguments, "UTF-8"));
+ } catch (Exception e) {
+ // For wson use in data render mode
+ argArray = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(arguments);
+ }
} else {
argArray = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(arguments);
}
@@ -705,9 +710,8 @@ public void reportNativeInitStatus(String statusCode, String errorMsg) {
}
}
- @Override
- public void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data) {
- nativeFireEventOnDataRenderNode(instanceId,ref,type,data);
+ public void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String domChanges) {
+ nativeFireEventOnDataRenderNode(instanceId,ref,type,data, domChanges);
}
public void registerModuleOnDataRenderNode(String data) {
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 e7ccda6620..83cb7087f6 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
@@ -1169,7 +1169,7 @@ public void fireEventOnNode(final String instanceId, final String ref,
WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
if (instance != null && (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER ||
instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY)) {
- fireEventOnDataRenderNode(instanceId, ref, type, data);
+ fireEventOnDataRenderNode(instanceId, ref, type, data, domChanges);
} else {
if(callback == null) {
addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
@@ -1181,7 +1181,7 @@ public void fireEventOnNode(final String instanceId, final String ref,
}
private void fireEventOnDataRenderNode(final String instanceId, final String ref,
- final String type, final Map<String, Object> data) {
+ final String type, final Map<String, Object> data, final Map<String, Object> domChanges) {
mJSHandler.postDelayed(WXThread.secure(new Runnable() {
@Override
public void run() {
@@ -1192,7 +1192,10 @@ public void run() {
WXLogUtils.d("fireEventOnDataRenderNode >>>> instanceId:" + instanceId
+ ", data:" + data);
}
- mWXBridge.fireEventOnDataRenderNode(instanceId, ref,type,JSON.toJSONString(data));
+ if (mWXBridge instanceof WXBridge) {
+ ((WXBridge) mWXBridge).fireEventOnDataRenderNode(instanceId, ref,type,JSON.toJSONString(data), JSON.toJSONString(domChanges));
+ }
+ WXLogUtils.renderPerformanceLog("fireEventOnDataRenderNode", System.currentTimeMillis() - start);
} catch (Throwable e) {
String err = "[WXBridgeManager] fireEventOnDataRenderNode " + WXLogUtils.getStackTrace(e);
WXExceptionUtils.commitCriticalExceptionRT(instanceId,
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 40c484fa4c..847b40b281 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
@@ -198,6 +198,4 @@ int callUpdateAttrs(String instanceId, String ref,
void resetWXBridge(boolean remoteDebug);
- void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data);
-
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
index 483d5aedd1..777374fa61 100644
--- a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
@@ -67,6 +67,10 @@
public static final String KEY_PAGE_STAGES_NEW_FSRENDER = "wxNewFsRender";
public static final String KEY_PAGE_STAGES_INTERACTION = "wxInteraction";
public static final String KEY_PAGE_STAGES_DESTROY = "wxDestroy";
+ //Custom preprocessing start, called when activity created or other time. Called by other activity
+ public static final String KEY_PAGE_STAGES_CUSTOM_PREPROCESS_START = "wxCustomPreprocessStart";
+ //Custom preprocessing end, called when you'are able to start weex render. Called by other activity
+ public static final String KEY_PAGE_STAGES_CUSTOM_PREPROCESS_END = "wxCustomPreprocessEnd";
/************** stats *****************/
public static final String KEY_PAGE_STATS_BUNDLE_SIZE = "wxBundleSize";
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateStyle.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateStyle.java
index e464cc1f1b..bddb338df2 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateStyle.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateStyle.java
@@ -35,6 +35,7 @@
private Map<String, Object> mStyle;
private WXComponent component;
private boolean mIsCausedByPesudo;
+ private boolean mIsBorderSet;
public GraphicActionUpdateStyle(WXSDKInstance instance, String ref,
Map<String, Object> style,
@@ -77,6 +78,7 @@ public GraphicActionUpdateStyle(WXSDKInstance instance, String ref,
}
if (null != borders) {
+ mIsBorderSet = true;
component.setBorders(borders);
}
}
@@ -114,23 +116,26 @@ public GraphicActionUpdateStyle(WXSDKInstance instance, String ref,
}
if (null != borders) {
+ mIsBorderSet = true;
component.addShorthand(borders);
}
}
@Override
public void executeAction() {
- if (component == null || mStyle == null) {
- return;
- }
- if(component.getTransition() != null){
- component.getTransition().updateTranstionParams(mStyle);
- if(component.getTransition().hasTransitionProperty(mStyle)){
- component.getTransition().startTransition(mStyle);
+ if (component == null) return;
+ if (mStyle != null) {
+ if(component.getTransition() != null){
+ component.getTransition().updateTranstionParams(mStyle);
+ if(component.getTransition().hasTransitionProperty(mStyle)){
+ component.getTransition().startTransition(mStyle);
+ }
+ } else {
+ component.setTransition(WXTransition.fromMap(mStyle, component));
+ component.updateStyles(mStyle);
}
- } else {
- component.setTransition(WXTransition.fromMap(mStyle, component));
- component.updateStyles(mStyle);
+ } else if (mIsBorderSet) {
+ component.updateStyles(component);
}
}
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
index 7c6134ff03..c06f6116cb 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
@@ -609,6 +609,9 @@ public void setValue(String value) {
if ((view = getHostView()) == null) {
return;
}
+ if (TextUtils.equals(view.getText(), value)) {
+ return;
+ }
mIgnoreNextOnInputEvent = true;
int oldIndex = view.getSelectionStart();
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
index 33cd5cb589..d592038d3a 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
@@ -579,20 +579,22 @@ View getBoxShadowHost(boolean isClear) {
mBoxShadowHost = new BoxShadowHost(getContext());
WXViewUtils.setBackGround(mBoxShadowHost, null, this);
- CSSShorthand padding = this.getPadding();
- CSSShorthand border = this.getBorder();
+ hostView.addView(mBoxShadowHost);
+ }
- int left = (int) (padding.get(CSSShorthand.EDGE.LEFT) + border.get(CSSShorthand.EDGE.LEFT));
- int top = (int) (padding.get(CSSShorthand.EDGE.TOP) + border.get(CSSShorthand.EDGE.TOP));
- int right = (int) (padding.get(CSSShorthand.EDGE.RIGHT) + border.get(CSSShorthand.EDGE.RIGHT));
- int bottom = (int) (padding.get(CSSShorthand.EDGE.BOTTOM) + border.get(CSSShorthand.EDGE.BOTTOM));
+ CSSShorthand padding = this.getPadding();
+ CSSShorthand border = this.getBorder();
- ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(hostView.getLayoutParams()) ;
- this.setMarginsSupportRTL(layoutParams, -left, -top, -right, -bottom);
- mBoxShadowHost.setLayoutParams(layoutParams);
+ int left = (int) (padding.get(CSSShorthand.EDGE.LEFT) + border.get(CSSShorthand.EDGE.LEFT));
+ int top = (int) (padding.get(CSSShorthand.EDGE.TOP) + border.get(CSSShorthand.EDGE.TOP));
+ int right = (int) (padding.get(CSSShorthand.EDGE.RIGHT) + border.get(CSSShorthand.EDGE.RIGHT));
+ int bottom = (int) (padding.get(CSSShorthand.EDGE.BOTTOM) + border.get(CSSShorthand.EDGE.BOTTOM));
- hostView.addView(mBoxShadowHost);
- }
+ ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(hostView.getLayoutParams()) ;
+ this.setMarginsSupportRTL(layoutParams, -left, -top, -right, -bottom);
+
+ mBoxShadowHost.setLayoutParams(layoutParams);
+
hostView.removeView(mBoxShadowHost);
hostView.addView(mBoxShadowHost);
return mBoxShadowHost;
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXDataStructureUtil.java b/android/sdk/src/main/java/com/taobao/weex/utils/WXDataStructureUtil.java
index a6ab07fcdc..ee28e45c49 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXDataStructureUtil.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXDataStructureUtil.java
@@ -1,19 +1,21 @@
-/*
- * Copyright (C) 2007 The Guava Authors
+/**
+ * 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
*
- * Licensed 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
*
- * 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.
+ * 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.utils;
import java.util.HashMap;
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index aeb4d3b9b1..90b9bb0dba 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -96,6 +96,34 @@
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 */; };
+ 453F374D219A76A600A03F1D /* WXConvertUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F374B219A76A500A03F1D /* WXConvertUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 453F374E219A76A600A03F1D /* WXConvertUtility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F374C219A76A500A03F1D /* WXConvertUtility.mm */; };
+ 453F3756219A76CA00A03F1D /* default_request_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3750219A76CA00A03F1D /* default_request_handler.h */; };
+ 453F3757219A76CA00A03F1D /* http_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 453F3751219A76CA00A03F1D /* http_module.cc */; };
+ 453F3758219A76CA00A03F1D /* default_request_handler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F3753219A76CA00A03F1D /* default_request_handler.mm */; };
+ 453F3759219A76CA00A03F1D /* request_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3754219A76CA00A03F1D /* request_handler.h */; };
+ 453F375A219A76CA00A03F1D /* http_module.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3755219A76CA00A03F1D /* http_module.h */; };
+ 453F375E219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F375C219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm */; };
+ 453F375F219A76FA00A03F1D /* vnode_on_event_listener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F375D219A76FA00A03F1D /* vnode_on_event_listener.mm */; };
+ 453F3762219A770900A03F1D /* vcomponent_lifecycle_listener.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3760219A770900A03F1D /* vcomponent_lifecycle_listener.h */; };
+ 453F3763219A770900A03F1D /* vnode_on_event_listener.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3761219A770900A03F1D /* vnode_on_event_listener.h */; };
+ 453F3764219A77EE00A03F1D /* vcomponent_lifecycle_listener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F375C219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm */; };
+ 453F3765219A77FF00A03F1D /* vnode_on_event_listener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F375D219A76FA00A03F1D /* vnode_on_event_listener.mm */; };
+ 453F3766219A780A00A03F1D /* vcomponent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 453267132140E38900DAA620 /* vcomponent.cc */; };
+ 453F3767219A781900A03F1D /* vcomponent_lifecycle_listener.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3760219A770900A03F1D /* vcomponent_lifecycle_listener.h */; };
+ 453F3768219A782900A03F1D /* vnode_on_event_listener.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3761219A770900A03F1D /* vnode_on_event_listener.h */; };
+ 453F3769219A783400A03F1D /* vcomponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 453267122140E38900DAA620 /* vcomponent.h */; };
+ 453F376A219A784F00A03F1D /* http_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 453F3751219A76CA00A03F1D /* http_module.cc */; };
+ 453F376B219A785C00A03F1D /* http_module.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3755219A76CA00A03F1D /* http_module.h */; };
+ 453F376C219A786F00A03F1D /* request_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3754219A76CA00A03F1D /* request_handler.h */; };
+ 453F376D219A788800A03F1D /* default_request_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F3750219A76CA00A03F1D /* default_request_handler.h */; };
+ 453F376E219A789A00A03F1D /* default_request_handler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F3753219A76CA00A03F1D /* default_request_handler.mm */; };
+ 453F376F219A78D700A03F1D /* WXConvertUtility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 453F374C219A76A500A03F1D /* WXConvertUtility.mm */; };
+ 453F3770219A78E200A03F1D /* WXConvertUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 453F374B219A76A500A03F1D /* WXConvertUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 453F3771219A790100A03F1D /* binary_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4532671F2142731000DAA620 /* binary_file.cc */; };
+ 453F3772219A790A00A03F1D /* binary_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 4532671E2142731000DAA620 /* binary_file.h */; };
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 */; };
@@ -1117,6 +1145,19 @@
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>"; };
+ 453F374B219A76A500A03F1D /* WXConvertUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXConvertUtility.h; sourceTree = "<group>"; };
+ 453F374C219A76A500A03F1D /* WXConvertUtility.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WXConvertUtility.mm; sourceTree = "<group>"; };
+ 453F3750219A76CA00A03F1D /* default_request_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = default_request_handler.h; sourceTree = "<group>"; };
+ 453F3751219A76CA00A03F1D /* http_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_module.cc; sourceTree = "<group>"; };
+ 453F3753219A76CA00A03F1D /* default_request_handler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = default_request_handler.mm; sourceTree = "<group>"; };
+ 453F3754219A76CA00A03F1D /* request_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = request_handler.h; sourceTree = "<group>"; };
+ 453F3755219A76CA00A03F1D /* http_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_module.h; sourceTree = "<group>"; };
+ 453F375C219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = vcomponent_lifecycle_listener.mm; sourceTree = "<group>"; };
+ 453F375D219A76FA00A03F1D /* vnode_on_event_listener.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = vnode_on_event_listener.mm; sourceTree = "<group>"; };
+ 453F3760219A770900A03F1D /* vcomponent_lifecycle_listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcomponent_lifecycle_listener.h; sourceTree = "<group>"; };
+ 453F3761219A770900A03F1D /* vnode_on_event_listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnode_on_event_listener.h; 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>"; };
4547FD0B215392F900E79971 /* js_common_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = js_common_function.h; sourceTree = "<group>"; };
@@ -1672,6 +1713,35 @@
name = Layout;
sourceTree = "<group>";
};
+ 453F374F219A76CA00A03F1D /* network */ = {
+ isa = PBXGroup;
+ children = (
+ 453F3750219A76CA00A03F1D /* default_request_handler.h */,
+ 453F3751219A76CA00A03F1D /* http_module.cc */,
+ 453F3752219A76CA00A03F1D /* ios */,
+ 453F3754219A76CA00A03F1D /* request_handler.h */,
+ 453F3755219A76CA00A03F1D /* http_module.h */,
+ );
+ path = network;
+ sourceTree = "<group>";
+ };
+ 453F3752219A76CA00A03F1D /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ 453F3753219A76CA00A03F1D /* default_request_handler.mm */,
+ );
+ path = ios;
+ sourceTree = "<group>";
+ };
+ 453F375B219A76FA00A03F1D /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ 453F375C219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm */,
+ 453F375D219A76FA00A03F1D /* vnode_on_event_listener.mm */,
+ );
+ path = ios;
+ sourceTree = "<group>";
+ };
59A583031CF5B2FD0081FD3E /* Handler */ = {
isa = PBXGroup;
children = (
@@ -2073,6 +2143,8 @@
77D161481C02E3670010B15B /* Utility */ = {
isa = PBXGroup;
children = (
+ 453F374B219A76A500A03F1D /* WXConvertUtility.h */,
+ 453F374C219A76A500A03F1D /* WXConvertUtility.mm */,
C4D872231E5DDF7500E39BC1 /* WXBoxShadow.h */,
C4D872241E5DDF7500E39BC1 /* WXBoxShadow.m */,
59D3CA481CFC3CE1008835DC /* NSTimer+Weex.h */,
@@ -2253,6 +2325,7 @@
B8D66AEC2125572F003960BD /* core */ = {
isa = PBXGroup;
children = (
+ 453F374F219A76CA00A03F1D /* network */,
B8D66AED2125572F003960BD /* data_render */,
B8D66B192125572F003960BD /* moniter */,
B8D66B1C2125572F003960BD /* css */,
@@ -2353,7 +2426,10 @@
B8D66AF52125572F003960BD /* vnode */ = {
isa = PBXGroup;
children = (
+ 453F375B219A76FA00A03F1D /* ios */,
B8D66AF62125572F003960BD /* vnode.h */,
+ 453F3760219A770900A03F1D /* vcomponent_lifecycle_listener.h */,
+ 453F3761219A770900A03F1D /* vnode_on_event_listener.h */,
B8D66AF72125572F003960BD /* vnode_exec_env.cc */,
B8D66AF82125572F003960BD /* vnode.cc */,
453267132140E38900DAA620 /* vcomponent.cc */,
@@ -2695,6 +2771,7 @@
files = (
7715EB6221A69DD9001F1108 /* WXRichText.h in Headers */,
4532670A213FC84A00DAA620 /* WXDisplayLinkManager.h in Headers */,
+ 453F374D219A76A600A03F1D /* WXConvertUtility.h in Headers */,
B8D66C1B21255730003960BD /* style.h in Headers */,
B8D66C2321255730003960BD /* layout.h in Headers */,
B8D66C2521255730003960BD /* flex_enum.h in Headers */,
@@ -2790,6 +2867,7 @@
B8D66C0F21255730003960BD /* core_side_in_platform.h in Headers */,
B8D66C9121255730003960BD /* render_factory_interface.h in Headers */,
DCE2CF9B1F46D4220021BDC4 /* WXVoiceOverModule.h in Headers */,
+ 453F3756219A76CA00A03F1D /* default_request_handler.h in Headers */,
74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */,
98399A9621916A9800D83CCE /* class_function.h in Headers */,
DCA0EF641D6EED6F00CB18B9 /* WXGlobalEventModule.h in Headers */,
@@ -2799,6 +2877,7 @@
841CD1051F974DFA0081196D /* WXExceptionUtils.h in Headers */,
745B2D6A1E5A8E1E0092D38A /* WXRecyclerComponent.h in Headers */,
C42E8F9B1F39DF07001EBE9D /* WXTracingProtocol.h in Headers */,
+ 453F3763219A770900A03F1D /* vnode_on_event_listener.h in Headers */,
B8D66C6D21255730003960BD /* render_text.h in Headers */,
7423899F1C32733800D748CA /* WXType.h in Headers */,
59A582FC1CF5B17B0081FD3E /* WXBridgeContext.h in Headers */,
@@ -2823,6 +2902,7 @@
B8F2C7022133A83C00635B37 /* rax_parser_scope.h in Headers */,
4547FD022152048700E79971 /* class_object.h in Headers */,
74862F791E02B88D00B7A041 /* JSValue+Weex.h in Headers */,
+ 453F375A219A76CA00A03F1D /* http_module.h in Headers */,
B8F2C6FA2133A83C00635B37 /* class_factory.h in Headers */,
2A1F57B71C75C6A600B58017 /* WXTextInputComponent.h in Headers */,
B8D66C2D21255730003960BD /* render_manager.h in Headers */,
@@ -2920,6 +3000,7 @@
59A596241CB6311F0012CD52 /* WXStorageModule.h in Headers */,
74A4BA851CAD453400195969 /* WXNetworkProtocol.h in Headers */,
7461F8A81CFC33A800F62D44 /* WXThreadSafeMutableArray.h in Headers */,
+ 453F3759219A76CA00A03F1D /* request_handler.h in Headers */,
D33451081D3E19480083598A /* WXCanvasComponent.h in Headers */,
17036A4E20FDE72F0029AE3D /* WXApmForInstance.h in Headers */,
74B8BEFE1DC47B72004A6027 /* WXRootView.h in Headers */,
@@ -2953,6 +3034,7 @@
B8D66C9321255730003960BD /* dom_wson.h in Headers */,
B8D66CAF21255730003960BD /* wson_parser.h in Headers */,
D317338C1C57257000BB7539 /* WXTransform.h in Headers */,
+ 453F3762219A770900A03F1D /* vcomponent_lifecycle_listener.h in Headers */,
B8D66BC32125572F003960BD /* vnode_render_context.h in Headers */,
77D161301C02DE4E0010B15B /* WXComponent.h in Headers */,
B8D66CB121255730003960BD /* TimeUtils.h in Headers */,
@@ -2985,6 +3067,7 @@
7715EB6321A69DD9001F1108 /* WXRichText.h in Headers */,
4532670C213FCF2300DAA620 /* WXDisplayLinkManager.h in Headers */,
B8D66C1C21255730003960BD /* style.h in Headers */,
+ 453F3770219A78E200A03F1D /* WXConvertUtility.h in Headers */,
B8D66C2421255730003960BD /* layout.h in Headers */,
B8D66C2621255730003960BD /* flex_enum.h in Headers */,
B85ED3032126715100EBEC11 /* WXRecyclerComponent.h in Headers */,
@@ -3045,6 +3128,11 @@
B8D66BC42125572F003960BD /* vnode_render_context.h in Headers */,
DCA445AF1EFA575D00D0CFA8 /* WXModuleProtocol.h in Headers */,
4547FD102153932A00E79971 /* js_common_function.h in Headers */,
+ 453F376D219A788800A03F1D /* default_request_handler.h in Headers */,
+ 453F376C219A786F00A03F1D /* request_handler.h in Headers */,
+ 453F376B219A785C00A03F1D /* http_module.h in Headers */,
+ 453F3768219A782900A03F1D /* vnode_on_event_listener.h in Headers */,
+ 453F3767219A781900A03F1D /* vcomponent_lifecycle_listener.h in Headers */,
B8D66BF02125572F003960BD /* op_code.h in Headers */,
4505D12D219B21760083A1A2 /* class_window.h in Headers */,
4505D12B219B21470083A1A2 /* class_regex.h in Headers */,
@@ -3588,6 +3676,7 @@
B8D66BAF2125572F003960BD /* ast_factory.cc in Sources */,
7461F8A91CFC33A800F62D44 /* WXThreadSafeMutableArray.m in Sources */,
745B2D6D1E5A8E1E0092D38A /* WXRecyclerDataController.m in Sources */,
+ 453F375F219A76FA00A03F1D /* vnode_on_event_listener.mm in Sources */,
B8D66BF32125572F003960BD /* object.cc in Sources */,
2AC750251C7565690041D390 /* WXIndicatorComponent.m in Sources */,
591DD3311D23AD5800BE8709 /* WXErrorView.m in Sources */,
@@ -3624,6 +3713,7 @@
DCA0EF651D6EED6F00CB18B9 /* WXGlobalEventModule.m in Sources */,
453267152140E38900DAA620 /* vcomponent.cc in Sources */,
2A919DA71E321F1F006EB6B5 /* WXBridgeMethod.m in Sources */,
+ 453F3758219A76CA00A03F1D /* default_request_handler.mm in Sources */,
7423EB521F4ADE30001662D1 /* WXComponent+DataBinding.mm in Sources */,
DCAB35FF1D658EB700C0EA70 /* WXRuleManager.m in Sources */,
77D161251C02DDD10010B15B /* WXSDKInstance.m in Sources */,
@@ -3635,6 +3725,7 @@
17B122262090AAB000387E33 /* WXSDKError.m in Sources */,
B8D66C1F21255730003960BD /* layout.cpp in Sources */,
B8D66C2B21255730003960BD /* render_manager.cpp in Sources */,
+ 453F374E219A76A600A03F1D /* WXConvertUtility.mm in Sources */,
C4B3D6D51E6954300013F38D /* WXEditComponent.mm in Sources */,
C4C30DE81E1B833D00786B6C /* WXComponent+PseudoClassManagement.m in Sources */,
B8D66C4F21255730003960BD /* render_action_add_element.cpp in Sources */,
@@ -3645,6 +3736,7 @@
74A4BA5C1CABBBD000195969 /* WXDebugTool.m in Sources */,
98399A9721916A9800D83CCE /* op_code.cc in Sources */,
742AD73B1DF98C8B007DC46C /* WXResourceLoader.m in Sources */,
+ 453F3757219A76CA00A03F1D /* http_module.cc in Sources */,
B8A72CA0213F8BAE0024E7BE /* class_string.cc in Sources */,
B8D66C6721255730003960BD /* render_scroller.cpp in Sources */,
B8D66C5321255730003960BD /* render_action_createbody.cpp in Sources */,
@@ -3709,6 +3801,7 @@
B8D66BBB2125572F003960BD /* vnode_render_context.cc in Sources */,
841CD1031F9739890081196D /* WXExceptionUtils.m in Sources */,
B8D66CD921255730003960BD /* message_pump_posix.cc in Sources */,
+ 453F375E219A76FA00A03F1D /* vcomponent_lifecycle_listener.mm in Sources */,
C4E97D341F1EF46D00ABC314 /* WXTracingManager.m in Sources */,
742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */,
7461F8931CFB373100F62D44 /* WXLayer.m in Sources */,
@@ -3727,6 +3820,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 453F376F219A78D700A03F1D /* WXConvertUtility.mm in Sources */,
+ 453F376E219A789A00A03F1D /* default_request_handler.mm in Sources */,
+ 453F376A219A784F00A03F1D /* http_module.cc in Sources */,
+ 453F3765219A77FF00A03F1D /* vnode_on_event_listener.mm in Sources */,
+ 453F3764219A77EE00A03F1D /* vcomponent_lifecycle_listener.mm in Sources */,
4505D12E219B22630083A1A2 /* op_code.cc in Sources */,
4505D12C219B216D0083A1A2 /* class_window.cc in Sources */,
4505D12A219B213B0083A1A2 /* class_regex.cc in Sources */,
@@ -4199,7 +4297,10 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VALID_ARCHS = "arm64 armv7 x86_64 i386";
- WARNING_CFLAGS = "-Wno-documentation";
+ WARNING_CFLAGS = (
+ "-Wno-documentation",
+ "-Wno-c++14-extensions",
+ );
};
name = Debug;
};
@@ -4253,7 +4354,10 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VALID_ARCHS = "arm64 armv7 x86_64 i386";
- WARNING_CFLAGS = "-Wno-documentation";
+ WARNING_CFLAGS = (
+ "-Wno-documentation",
+ "-Wno-c++14-extensions",
+ );
};
name = Release;
};
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index 093945bf7f..4b4b5452ed 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -134,6 +134,15 @@ - (void)registerGlobalFunctions
[WXCoreBridge install];
+ [_jsBridge registerCallUpdateComponentData:^NSInteger(NSString *instanceId, NSString *componentId, NSString *jsonData) {
+
+ WXPerformBlockOnComponentThread(^{
+ [WXTracingManager startTracingWithInstanceId:instanceId ref:componentId className:nil name:WXTDomCall phase:WXTracingBegin functionName:@"__updateComponentData" options:@{@"threadName":WXTDOMThread}];
+ [WXCoreBridge callUpdateComponentData:instanceId componentId:componentId jsonData:jsonData];
+ });
+ return 0;
+ }];
+
[_jsBridge registerCallAddElement:^NSInteger(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index) {
WXPerformBlockOnComponentThread(^{
@@ -406,7 +415,7 @@ - (void)createInstance:(NSString *)instanceIdString
NSMutableArray *sendQueue = [NSMutableArray array];
[self.sendQueue setValue:sendQueue forKey:instanceIdString];
- if (sdkInstance.dataRender) {
+ if (sdkInstance.dataRender && ![options[@"EXEC_JS"] boolValue]) {
WX_MONITOR_INSTANCE_PERF_START(WXFirstScreenJSFExecuteTime, [WXSDKManager instanceForID:instanceIdString]);
WX_MONITOR_INSTANCE_PERF_START(WXPTJSCreateInstance, [WXSDKManager instanceForID:instanceIdString]);
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index 12c1f0740e..ca5fd83fa1 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -173,6 +173,8 @@ namespace WeexCore
+ (void)removeRenderObjectFromMap:(NSString*)pageId object:(void*)object;
++ (void)callUpdateComponentData:(NSString*)pageId componentId:(NSString*)componentId jsonData:(NSString*)jsonData;
+
+ (void)callAddElement:(NSString*)pageId parentRef:(NSString*)parentRef data:(NSDictionary*)data index:(int)index;
+ (void)callCreateBody:(NSString*)pageId data:(NSDictionary*)data;
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index b2ea970ee0..37b5e9b05f 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -28,6 +28,7 @@
#import "WXUtility.h"
#import "WXAssert.h"
#import "WXAppConfiguration.h"
+#import "WXConvertUtility.h"
#import "WXSDKEngine.h"
#import "WXAppMonitorProtocol.h"
@@ -44,122 +45,13 @@
#include "core/bridge/platform/core_side_in_platform.h"
#include "core/bridge/script/core_side_in_script.h"
#include "base/TimeUtils.h"
+#include "core/network/http_module.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)))
-
namespace WeexCore
-{
- static NSString* const JSONSTRING_SUFFIX = @"\t\n\t\r";
-
- static NSString* TO_JSON(id object)
- {
- if (object == nil) {
- return nil;
- }
-
- @try {
- if ([object isKindOfClass:[NSArray class]] || [object isKindOfClass:[NSDictionary class]]) {
- NSError *error = nil;
- NSData *data = [NSJSONSerialization dataWithJSONObject:object
- options:0
- error:&error];
-
- if (error) {
- WXLogError(@"%@", error);
- WXAssert(NO, @"Fail to convert object to json. %@", error);
- return nil;
- }
-
- return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByAppendingString:JSONSTRING_SUFFIX]; // add suffix so that we know this is a json string
- }
- } @catch (NSException *exception) {
- WXLogError(@"%@", exception);
- WXAssert(NO, @"Fail to convert object to json. %@", exception);
- return nil;
- }
-
- return nil;
- }
-
- static id TO_OBJECT(NSString* s)
- {
- if ([s hasSuffix:JSONSTRING_SUFFIX]) {
- if ([s length] == [JSONSTRING_SUFFIX length]) {
- return [NSNull null];
- }
-
- // s is a json string
- @try {
- NSError* error = nil;
- id jsonObj = [NSJSONSerialization JSONObjectWithData:[s dataUsingEncoding:NSUTF8StringEncoding]
- options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves
- error:&error];
-
- if (jsonObj == nil) {
- WXLogError(@"%@", error);
- WXAssert(NO, @"Fail to convert json to object. %@", error);
- }
- else {
- return jsonObj;
- }
- } @catch (NSException *exception) {
- WXLogError(@"%@", exception);
- WXAssert(NO, @"Fail to convert json to object. %@", exception);
- }
- }
- return s; // return s instead
- }
-
- static NSMutableDictionary* NSDICTIONARY(std::map<std::string, std::string>* map)
- {
- if (map == nullptr || map->size() == 0)
- return [[NSMutableDictionary alloc] init];
-
- NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithCapacity:map->size()];
- for (auto it = map->begin(); it != map->end(); it ++) {
- id object = TO_OBJECT(NSSTRING(it->second.c_str()));
- if (object) {
- [result setObject:object forKey:NSSTRING(it->first.c_str())];
- }
- }
- return result;
- }
-
- static NSMutableDictionary* NSDICTIONARY(std::vector<std::pair<std::string, std::string>>* vec)
- {
- if (vec == nullptr || vec->size() == 0)
- return [[NSMutableDictionary alloc] init];
-
- NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithCapacity:vec->size()];
- for (auto& p : *vec) {
- id object = TO_OBJECT(NSSTRING(p.second.c_str()));
- if (object) {
- [result setObject:object forKey:NSSTRING(p.first.c_str())];
- }
- }
- return result;
- }
-
- static NSMutableArray* NSARRAY(std::set<std::string>* set)
- {
- if (set == nullptr || set->size() == 0)
- return [[NSMutableArray alloc] init];
-
- NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:set->size()];
- for (auto& s : *set) {
- id object = TO_OBJECT(NSSTRING(s.c_str()));
- if (object) {
- [result addObject:object];
- }
- }
- return result;
- }
-
+{
static void consoleWithArguments(NSArray *arguments, WXLogFlag logLevel)
{
NSMutableString *jsLog = [NSMutableString string];
@@ -206,7 +98,7 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict,
dict[@"borderRightWidth"] = @(borders.getBorderWidth(kBorderWidthRight) / pixelScaleFactor);
}
}
-
+
static void MergeBorderWidthValues(NSMutableDictionary* dict,
std::vector<std::pair<std::string, std::string>>* borders,
float pixelScaleFactor)
@@ -222,7 +114,7 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict,
dict[NSSTRING(p.first.c_str())] = @(atof(p.second.c_str()) / pixelScaleFactor);
}
}
-
+
void IOSSide::SetJSVersion(const char* version)
{
NSString *jsVersion = NSSTRING(version);
@@ -820,7 +712,6 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict,
page->CallBridgeTime(getCurrentTime() - startTime);
return result;
}
-
#pragma mark - Layout Impl
WXCoreSize WXCoreMeasureFunctionBridge::Measure(const char* page_id, long render_ptr, float width, MeasureMode widthMeasureMode, float height, MeasureMode heightMeasureMode)
@@ -878,7 +769,13 @@ + (void)createDataRenderInstance:(NSString *)pageId template:(NSString *)jsBundl
auto node_manager = weex::core::data_render::VNodeRenderManager::GetInstance();
NSString *optionsString = [WXUtility JSONString:options];
NSString *dataString = [WXUtility JSONString:data];
- node_manager->CreatePage([jsBundleString UTF8String] ?: "", [pageId UTF8String] ?: "", [optionsString UTF8String] ?: "", [dataString UTF8String] ?: "");
+
+ node_manager->CreatePage([jsBundleString UTF8String] ?: "", [pageId UTF8String] ?: "", [optionsString UTF8String] ?: "", [dataString UTF8String] ?: "", [=](const char* javascript){
+ if (!javascript) {
+ return;
+ }
+ [[WXSDKManager bridgeMgr] createInstanceForJS:pageId template:NSSTRING(javascript) options:options data:data];
+ });
}
+ (void)createDataRenderInstance:(NSString *)pageId contents:(NSData *)contents options:(NSDictionary *)options data:(id)data
@@ -886,7 +783,12 @@ + (void)createDataRenderInstance:(NSString *)pageId contents:(NSData *)contents
auto node_manager = weex::core::data_render::VNodeRenderManager::GetInstance();
NSString *optionsString = [WXUtility JSONString:options];
NSString *dataString = [WXUtility JSONString:data];
- node_manager->CreatePage(static_cast<const char *>(contents.bytes), contents.length, [pageId UTF8String], [optionsString UTF8String], dataString ? [dataString UTF8String] : "");
+ node_manager->CreatePage(static_cast<const char *>(contents.bytes), contents.length, [pageId UTF8String], [optionsString UTF8String], dataString ? [dataString UTF8String] : "", [=](const char* javascript) {
+ if (!javascript) {
+ return;
+ }
+ [[WXSDKManager bridgeMgr] createInstanceForJS:pageId template:NSSTRING(javascript) options:options data:data];
+ });
}
+ (void)destroyDataRenderInstance:(NSString *)pageId
@@ -905,7 +807,7 @@ + (void)fireEvent:(NSString *)pageId ref:(NSString *)ref event:(NSString *)event
{
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] ? : "");
+ vnode_manager->FireEvent([pageId UTF8String] ? : "", [ref UTF8String] ? : "", [event UTF8String] ? : "", [params UTF8String] ? : "", "");
}
+ (void)registerModules:(NSDictionary *)modules {
@@ -1050,30 +952,12 @@ + (void)removeRenderObjectFromMap:(NSString*)pageId object:(void*)object
}
}
-static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
-{
- if ([obj isKindOfClass:[NSString class]]) {
- callback([obj UTF8String]);
- }
- else if ([obj isKindOfClass:[NSNumber class]]) {
- callback([[(NSNumber*)obj stringValue] UTF8String]);
- }
- else if ([obj isKindOfClass:[NSNull class]]) {
- callback([JSONSTRING_SUFFIX UTF8String]);
- }
- else {
- NSString* jsonstring = WeexCore::TO_JSON(obj);
- if (jsonstring != nil) {
- callback([jsonstring UTF8String]);
- }
- }
-}
+ (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:(WeexCore::RenderObject*)render
{
id data = styles[key];
if (data) {
- _convertToCString(data, ^(const char * value) {
+ ConvertToCString(data, ^(const char * value) {
if (value != nullptr) {
render->AddStyle([key UTF8String], value);
}
@@ -1095,7 +979,7 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:
}
[data[@"attr"] enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
- _convertToCString(obj, ^(const char * value) {
+ ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddAttr([key UTF8String], value);
}
@@ -1111,7 +995,7 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:
if ([key isEqualToString:@"margin"] || [key isEqualToString:@"padding"] || [key isEqualToString:@"borderWidth"]) {
return;
}
- _convertToCString(obj, ^(const char * value) {
+ ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddStyle([key UTF8String], value);
}
@@ -1119,7 +1003,7 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:
}];
for (id obj in data[@"event"]) {
- _convertToCString(obj, ^(const char * value) {
+ ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddEvent(value);
}
@@ -1143,7 +1027,7 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:
{
std::vector<std::pair<std::string, std::string>>* result = new std::vector<std::pair<std::string, std::string>>();
[data enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
- _convertToCString(obj, ^(const char * value) {
+ ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
result->emplace_back([key UTF8String], value);
}
@@ -1152,6 +1036,12 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:
return result;
}
++ (void)callUpdateComponentData:(NSString*)pageId componentId:(NSString*)componentId jsonData:(NSString*)jsonData
+{
+ weex::core::data_render::VNodeRenderManager::GetInstance()
+ ->UpdateComponentData([pageId UTF8String] ?: "", [componentId UTF8String] ?: "", [jsonData UTF8String] ?: "");
+}
+
+ (void)callAddElement:(NSString*)pageId parentRef:(NSString*)parentRef data:(NSDictionary*)data index:(int)index
{
using namespace WeexCore;
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
index 3652a0dc17..7577b3d918 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
@@ -156,6 +156,21 @@ - (JSValue*)executeJavascript:(NSString *)script withSourceURL:(NSURL*)sourceURL
}
}
+- (void)registerCallUpdateComponentData:(WXJSCallUpdateComponentData)callUpdateComponentData;
+{
+ id callUpdateComponentDataBlock = ^(JSValue *instanceId, JSValue *cid, JSValue *data, JSValue *ifCallback) {
+ NSString *instanceIdString = [instanceId toString];
+ NSString *componentId = [cid toString];
+ NSDictionary* jsonData = [data toDictionary];
+ NSString* dataString = [WXUtility JSONString:jsonData];
+ WXLogDebug(@"CallUpdateComponentData...%@, %@, %@", instanceIdString, componentId, jsonData);
+
+ return [JSValue valueWithInt32:(int32_t)callUpdateComponentData(instanceIdString, componentId, dataString) inContext:[JSContext currentContext]];
+ };
+
+ _jsContext[@"__updateComponentData"] = callUpdateComponentDataBlock;
+}
+
- (void)registerCallAddElement:(WXJSCallAddElement)callAddElement
{
id callAddElementBlock = ^(JSValue *instanceId, JSValue *ref, JSValue *element, JSValue *index, JSValue *ifCallback) {
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
index 33867636cd..29d9fd1a24 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -39,6 +39,18 @@ extern "C" {
**/
@property (nonatomic, weak, readonly) WXSDKInstance *topInstance;
+/**
+ * Create Instance Method
+ * @param instance : instance id
+ * @param temp : template data
+ * @param options : parameters
+ * @param data : external data
+ **/
+- (void)createInstanceForJS:(NSString *)instance
+ template:(NSString *)temp
+ options:(NSDictionary *)options
+ data:(id)data;
+
/**
* Create Instance Method
* @param instance : instance id
@@ -104,6 +116,12 @@ extern "C" {
**/
- (void)executeJsFramework:(NSString *)script;
+/**
+ + * download JS Script
+ + * @param scriptUrl : script url
+ + **/
+- (void)DownloadJS:(NSURL *)scriptUrl completion:(void (^)(NSString *script))complection;
+
/**
* Register JS service Script
* @param name : service name
@@ -217,4 +235,6 @@ extern "C" {
- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params DEPRECATED_MSG_ATTRIBUTE("Use fireEvent:ref:type:params:domChanges: method instead.");
- (void)executeJsMethod:(WXBridgeMethod *)method DEPRECATED_MSG_ATTRIBUTE();
+- (void)callJSMethod:(NSString *)method args:(NSArray *)args;
+
@end
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index f5c7a47e7d..ba412d7f66 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -142,6 +142,21 @@ + (void)_performBlockSyncOnBridgeThread:(void (^)(void))block
}
#pragma mark JSBridge Management
+- (void)createInstanceForJS:(NSString *)instance
+ template:(NSString *)temp
+ options:(NSDictionary *)options
+ data:(id)data {
+ if (!instance || !temp) return;
+ __weak typeof(self) weakSelf = self;
+ NSMutableDictionary *newOptions = [options mutableCopy] ?: [NSMutableDictionary new];
+ newOptions[@"EXEC_JS"] = @(YES);
+ WXPerformBlockOnBridgeThread(^(){
+ [weakSelf.bridgeCtx createInstance:instance
+ template:temp
+ options:newOptions
+ data:data];
+ });
+}
- (void)createInstance:(NSString *)instance
template:(NSString *)temp
@@ -288,6 +303,26 @@ - (JSValue *)callJSMethodWithResult:(WXCallJSMethod *)method
return value;
}
+- (void)DownloadJS:(NSURL *)scriptUrl completion:(void (^)(NSString *script))complection;
+{
+ if (!scriptUrl) {
+ complection(nil);
+ return;
+ }
+ WXResourceRequest* request = [WXResourceRequest requestWithURL:scriptUrl];
+ WXResourceLoader* jsLoader = [[WXResourceLoader alloc] initWithRequest:request];
+ jsLoader.onFinished = ^(WXResourceResponse *response, NSData *data) {
+ NSString* jsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ complection(jsString);
+ };
+ jsLoader.onFailed = ^(NSError *loadError) {
+ WXLogError(@"No js URL found");
+ complection(nil);
+ };
+
+ [jsLoader start];
+}
+
- (void)registerService:(NSString *)name withServiceUrl:(NSURL *)serviceScriptUrl withOptions:(NSDictionary *)options completion:(void(^)(BOOL result))completion
{
if (!name || !serviceScriptUrl || !options) {
@@ -483,6 +518,16 @@ - (void)resetEnvironment
});
}
+- (void)callJSMethod:(NSString *)method args:(NSArray *)args
+{
+ if (!method) return;
+
+ __weak typeof(self) weakSelf = self;
+ WXPerformBlockOnBridgeThread(^(){
+ [weakSelf.bridgeCtx callJSMethod:method args:args onContext:nil completion:nil];
+ });
+}
+
#pragma mark - Deprecated
- (void)executeJsMethod:(WXCallJSMethod *)method
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index ccab0e5af3..2bc521e289 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -473,6 +473,10 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)
newOptions[bundleUrlOptionKey] = url.absoluteString;
}
+ if ( [url.absoluteString containsString:@"__data_render=true"]) {
+ newOptions[@"DATA_RENDER"] = @(YES);
+ }
+
if ([url.absoluteString hasSuffix:WEEX_LITE_URL_SUFFIX] || [url.absoluteString containsString:@"__eagle=true"]) {
newOptions[@"WLASM_RENDER"] = @(YES);
}
diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
index a81624621f..da559bcd17 100644
--- a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
+++ b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
@@ -44,6 +44,8 @@ extern NSString* const KEY_PAGE_PROPERTIES_RENDER_TYPE;
extern NSString* const KEY_PAGE_STAGES_START;
extern NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_START;
extern NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_END;
+extern NSString* const KEY_PAGE_STAGES_CUSTOM_PREPROCESS_START;
+extern NSString* const KEY_PAGE_STAGES_CUSTOM_PREPROCESS_END;
extern NSString* const KEY_PAGE_STAGES_RENDER_ORGIGIN;
extern NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_START;
extern NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_END;
diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
index d44effd6ef..7a8822dcd0 100644
--- a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
@@ -57,6 +57,8 @@
NSString* const KEY_PAGE_STAGES_START = @"wxRecordStart";
NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_START = @"wxStartDownLoadBundle";
NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_END = @"wxEndDownLoadBundle";
+NSString* const KEY_PAGE_STAGES_CUSTOM_PREPROCESS_START = @"wxCustomPreprocessStart";
+NSString* const KEY_PAGE_STAGES_CUSTOM_PREPROCESS_END = @"wxCustomPreprocessEnd";
NSString* const KEY_PAGE_STAGES_RENDER_ORGIGIN = @"wxRenderTimeOrigin";
NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_START = @"wxStartLoadBundle";
NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_END = @"wxEndLoadBundle";
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
index 90bb9556e3..b3d10193d1 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
@@ -33,6 +33,7 @@ typedef NSInteger(^WXJSCallRefreshFinish)(NSString *instanceId);
typedef NSInteger(^WXJSCallUpdateFinish)(NSString *instanceId);
typedef NSInvocation *(^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options);
typedef void (^WXJSCallNativeComponent)(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options);
+typedef NSInteger(^WXJSCallUpdateComponentData)(NSString *instanceId, NSString *componentId, NSString *jsonData);
@protocol WXBridgeProtocol <NSObject>
@@ -74,6 +75,11 @@ typedef void (^WXJSCallNativeComponent)(NSString *instanceId, NSString *componen
@required
+/**
+ * Register callback when call __updateComponentData tasks occur. only use for data render
+ */
+- (void)registerCallUpdateComponentData:(WXJSCallUpdateComponentData)callUpdateComponentData;
+
/**
* Register callback when call native tasks occur
*/
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h
new file mode 100644
index 0000000000..25d6f3b891
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+#ifndef __WX_CONVERT_UTILITY_H__
+#define __WX_CONVERT_UTILITY_H__
+
+#if defined __cplusplus
+#include "core/data_render/vnode/vnode_render_manager.h"
+
+#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)))
+
+id _Nonnull GenValue(weex::core::data_render::Value* _Nonnull value);
+
+NSString* _Nullable TO_JSON(id _Nullable object);
+
+id _Nonnull TO_OBJECT(NSString* _Nonnull s);
+
+NSMutableDictionary* _Nonnull NSDICTIONARY(std::map<std::string, std::string>* _Nullable map);
+
+NSMutableDictionary* _Nonnull NSDICTIONARY(std::unordered_map<std::string, std::string>* _Nullable map);
+
+NSMutableDictionary* _Nonnull NSDICTIONARY(std::vector<std::pair<std::string, std::string>>* _Nullable vec);
+
+NSMutableDictionary* _Nonnull NSDICTIONARY(const std::unordered_map<std::string, weex::core::data_render::VComponent::VNodeRefs>& ref_map);
+
+NSMutableDictionary* _Nonnull NSDICTIONARY(weex::core::data_render::Table* _Nullable table);
+
+NSMutableArray* _Nonnull NSARRAY(std::set<std::string>* _Nullable set);
+
+NSMutableArray* _Nonnull NSARRAY(weex::core::data_render::Array* _Nullable array);
+
+NSMutableArray* _Nonnull NSARRAY(std::vector<std::unordered_map<std::string, std::string>> refs);
+
+NSMutableArray* _Nonnull NSARRAY(const std::vector<weex::core::data_render::Value>& params);
+
+void ConvertToCString(id _Nonnull obj, void (^ _Nonnull callback)(const char* _Nullable));
+
+#endif
+
+#endif
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm
new file mode 100644
index 0000000000..02ea25d093
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.mm
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXConvertUtility.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+NSString* const JSONSTRING_SUFFIX = @"\t\n\t\r";
+
+NSString* TO_JSON(id object)
+{
+ if (object == nil) {
+ return nil;
+ }
+
+ @try {
+ if ([object isKindOfClass:[NSArray class]] || [object isKindOfClass:[NSDictionary class]]) {
+ NSError *error = nil;
+ NSData *data = [NSJSONSerialization dataWithJSONObject:object
+ options:0
+ error:&error];
+
+ if (error) {
+ WXLogError(@"%@", error);
+ WXAssert(NO, @"Fail to convert object to json. %@", error);
+ return nil;
+ }
+
+ return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByAppendingString:JSONSTRING_SUFFIX]; // add suffix so that we know this is a json string
+ }
+ } @catch (NSException *exception) {
+ WXLogError(@"%@", exception);
+ WXAssert(NO, @"Fail to convert object to json. %@", exception);
+ return nil;
+ }
+
+ return nil;
+}
+
+id TO_OBJECT(NSString* s)
+{
+ if ([s hasSuffix:JSONSTRING_SUFFIX]) {
+ if ([s length] == [JSONSTRING_SUFFIX length]) {
+ return [NSNull null];
+ }
+
+ // s is a json string
+ @try {
+ NSError* error = nil;
+ id jsonObj = [NSJSONSerialization JSONObjectWithData:[s dataUsingEncoding:NSUTF8StringEncoding]
+ options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves
+ error:&error];
+
+ if (jsonObj == nil) {
+ WXLogError(@"%@", error);
+ WXAssert(NO, @"Fail to convert json to object. %@", error);
+ }
+ else {
+ return jsonObj;
+ }
+ } @catch (NSException *exception) {
+ WXLogError(@"%@", exception);
+ WXAssert(NO, @"Fail to convert json to object. %@", exception);
+ }
+ }
+ return s; // return s instead
+}
+
+NSMutableDictionary* NSDICTIONARY(std::map<std::string, std::string>* map)
+{
+ if (map == nullptr || map->size() == 0)
+ return [[NSMutableDictionary alloc] init];
+
+ NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithCapacity:map->size()];
+ for (auto it = map->begin(); it != map->end(); it ++) {
+ id object = TO_OBJECT(NSSTRING(it->second.c_str()));
+ if (object) {
+ [result setObject:object forKey:NSSTRING(it->first.c_str())];
+ }
+ }
+ return result;
+}
+
+NSMutableDictionary* NSDICTIONARY(std::unordered_map<std::string, std::string>* map)
+{
+ if (map == nullptr || map->size() == 0)
+ return [[NSMutableDictionary alloc] init];
+
+ NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithCapacity:map->size()];
+ for (auto it = map->begin(); it != map->end(); it ++) {
+ id object = TO_OBJECT(NSSTRING(it->second.c_str()));
+ if (object) {
+ [result setObject:object forKey:NSSTRING(it->first.c_str())];
+ }
+ }
+ return result;
+}
+
+NSMutableDictionary* NSDICTIONARY(std::vector<std::pair<std::string, std::string>>* vec)
+{
+ if (vec == nullptr || vec->size() == 0)
+ return [[NSMutableDictionary alloc] init];
+
+ NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithCapacity:vec->size()];
+ for (auto& p : *vec) {
+ id object = TO_OBJECT(NSSTRING(p.second.c_str()));
+ if (object) {
+ [result setObject:object forKey:NSSTRING(p.first.c_str())];
+ }
+ }
+ return result;
+}
+
+NSMutableDictionary* NSDICTIONARY(const std::unordered_map<std::string, weex::core::data_render::VComponent::VNodeRefs>& ref_map)
+{
+ if (ref_map.size() == 0) {
+ return [[NSMutableDictionary alloc] init];
+ }
+ NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithCapacity:ref_map.size()];
+ for (auto it : ref_map) {
+ if (it.first.empty()) {
+ continue;
+ }
+ [dic setObject:NSARRAY(it.second) forKey:NSSTRING(it.first.c_str())];
+ }
+ return dic;
+}
+
+NSMutableDictionary* NSDICTIONARY(weex::core::data_render::Table* table)
+{
+ if (table == nullptr || table->map.size() == 0)
+ return [[NSMutableDictionary alloc] init];
+
+ NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithCapacity:table->map.size()];
+ for (auto it=table->map.begin(); it!=table->map.end(); ++it) {
+ if (it->first.empty()) {
+ continue;
+ };
+ [dic setObject:GenValue(&it->second) forKey:NSSTRING(it->first.c_str())];
+ }
+ return dic;
+}
+
+NSMutableArray* NSARRAY(std::set<std::string>* set)
+{
+ if (set == nullptr || set->size() == 0)
+ return [[NSMutableArray alloc] init];
+
+ NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:set->size()];
+ for (auto& s : *set) {
+ id object = TO_OBJECT(NSSTRING(s.c_str()));
+ if (object) {
+ [result addObject:object];
+ }
+ }
+ return result;
+}
+
+NSMutableArray* NSARRAY(weex::core::data_render::Array* array)
+{
+ if (array == nullptr || array->items.size() == 0)
+ return [[NSMutableArray alloc] init];
+
+ NSMutableArray* ns_array = [[NSMutableArray alloc] initWithCapacity:array->items.size()];
+ for (auto it=array->items.begin(); it!=array->items.end(); ++it) {
+ [ns_array addObject:GenValue(&*it)];
+ }
+ return ns_array;
+}
+
+NSMutableArray* NSARRAY(std::vector<std::unordered_map<std::string, std::string>> refs)
+{
+ if (refs.size() == 0)
+ return [[NSMutableArray alloc] init];
+
+ NSMutableArray* ns_array = [[NSMutableArray alloc] initWithCapacity:refs.size()];
+ for (auto it : refs) {
+ [ns_array addObject:NSDICTIONARY(&it)];
+ }
+ return ns_array;
+}
+
+NSMutableArray* NSARRAY(const std::vector<weex::core::data_render::Value>& params)
+{
+ if (params.size() == 0) {
+ return [[NSMutableArray alloc] init];
+ }
+ NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:params.size()];
+ for (auto it : params) {
+ [array addObject:GenValue(&it)];
+ }
+ return array;
+}
+
+id GenValue(weex::core::data_render::Value* value)
+{
+ switch (value->type) {
+ case weex::core::data_render::Value::Type::ARRAY:
+ return NSARRAY( weex::core::data_render::ValueTo<weex::core::data_render::Array>(value));
+ case weex::core::data_render::Value::Type::TABLE:
+ return NSDICTIONARY( weex::core::data_render::ValueTo<weex::core::data_render::Table>(value));
+ case weex::core::data_render::Value::Type::INT:
+ return [NSNumber numberWithLong:
+ static_cast<long>(value->i)];
+ case weex::core::data_render::Value::Type::NUMBER:
+ return [NSNumber numberWithDouble:value->n];
+ case weex::core::data_render::Value::Type::STRING:
+ return NSSTRING(value->str->c_str());
+ case weex::core::data_render::Value::Type::BOOL:
+ return [NSNumber numberWithBool:value->b];
+ default:
+ return [NSNull null];
+ }
+}
+
+void ConvertToCString(id _Nonnull obj, void (^callback)(const char*))
+{
+ if ([obj isKindOfClass:[NSString class]]) {
+ callback([obj UTF8String]);
+ }
+ else if ([obj isKindOfClass:[NSNumber class]]) {
+ callback([[(NSNumber*)obj stringValue] UTF8String]);
+ }
+ else if ([obj isKindOfClass:[NSNull class]]) {
+ callback([JSONSTRING_SUFFIX UTF8String]);
+ }
+ else {
+ NSString* jsonstring = TO_JSON(obj);
+ if (jsonstring != nil) {
+ callback([jsonstring UTF8String]);
+ }
+ }
+}
diff --git a/ios/sdk/WeexSDK/Sources/WeexSDK.h b/ios/sdk/WeexSDK/Sources/WeexSDK.h
index a611390951..9d7f293c57 100644
--- a/ios/sdk/WeexSDK/Sources/WeexSDK.h
+++ b/ios/sdk/WeexSDK/Sources/WeexSDK.h
@@ -65,6 +65,7 @@
#import "WXDisplayLinkManager.h"
#import "WXDefine.h"
#import "WXDebugTool.h"
+#import "WXConvertUtility.h"
#import "WXConvert.h"
#import "WXConfigCenterProtocol.h"
#import "WXComponentManager.h"
diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt
index 2e5624aa7f..f3e5019aa4 100644
--- a/weex_core/Source/CMakeLists.txt
+++ b/weex_core/Source/CMakeLists.txt
@@ -124,6 +124,8 @@ set(COMMON_SRCS
./core/data_render/vnode/vnode_exec_env.cc
./core/data_render/vnode/vnode_render_manager.cc
./core/data_render/vnode/vnode_render_context.cc
+
+ ./core/network/http_module.cc
)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/wson)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/wson)
@@ -175,6 +177,11 @@ if (ANDROID)
./android/wrap/wx_params.cpp
./android/base/jni_type.cpp
+ ./core/data_render/vnode/android/vcomponent_lifecycle_listener.cc
+ ./core/data_render/vnode/android/vnode_on_event_listener.cc
+ ./core/data_render/vnode/android/conversion.cc
+ ./core/network/android/default_request_handler.cc
+
./android/jsengine/multiprocess/WeexJSConnection.cpp
./android/jsengine/multiprocess/ExtendJSApi.cpp
diff --git a/weex_core/Source/IPC/IPCMessageJS.h b/weex_core/Source/IPC/IPCMessageJS.h
index a99b2656ad..94f698c82b 100644
--- a/weex_core/Source/IPC/IPCMessageJS.h
+++ b/weex_core/Source/IPC/IPCMessageJS.h
@@ -71,6 +71,7 @@ enum class IPCProxyMsg {
DISPATCHMESSAGE,
DISPATCHMESSAGESYNC,
ONRECEIVEDRESULT,
+ UPDATECOMPONENTDATA,
};
// Message from Script to Core in ScriptBridge
diff --git a/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp b/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
index 5b10902412..9a5e4eb634 100644
--- a/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
+++ b/weex_core/Source/android/bridge/script_bridge_in_multi_process.cpp
@@ -954,6 +954,21 @@ std::unique_ptr<IPCResult> OnReceivedResult(IPCArguments *arguments) {
return createInt32Result(static_cast<int32_t>(true));
}
+std::unique_ptr<IPCResult> UpdateComponentData(IPCArguments *arguments) {
+ auto arg1 = std::unique_ptr<char[]>(getArumentAsCStr(arguments, 0));
+ auto arg2 = std::unique_ptr<char[]>(getArumentAsCStr(arguments, 1));
+ auto arg3 = std::unique_ptr<char[]>(getArumentAsCStr(arguments, 2));
+ WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
+ weex::base::MakeCopyable(
+ [page_id = std::move(arg1), cid = std::move(arg2), json_data = std::move(arg3)]() {
+ WeexCoreManager::Instance()
+ ->script_bridge()
+ ->core_side()
+ ->UpdateComponentData(page_id.get(), cid.get(), json_data.get());
+ }));
+ return createInt32Result(static_cast<int32_t>(true));
+}
+
ScriptBridgeInMultiProcess::ScriptBridgeInMultiProcess() {
set_script_side(new bridge::script::ScriptSideInMultiProcess);
set_core_side(new CoreSideInScript);
@@ -1047,6 +1062,8 @@ void ScriptBridgeInMultiProcess::RegisterIPCCallback(IPCHandler *handler) {
HandleDispatchMessageSync);
handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::ONRECEIVEDRESULT),
OnReceivedResult);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::UPDATECOMPONENTDATA),
+ UpdateComponentData);
}
} // namespace WeexCore
diff --git a/weex_core/Source/android/bridge/script_bridge_in_multi_so.cpp b/weex_core/Source/android/bridge/script_bridge_in_multi_so.cpp
index 400a83fe54..32f06e5efb 100644
--- a/weex_core/Source/android/bridge/script_bridge_in_multi_so.cpp
+++ b/weex_core/Source/android/bridge/script_bridge_in_multi_so.cpp
@@ -478,6 +478,19 @@ static void OnReceivedResult(long callback_id,
}));
}
+static void UpdateComponentData(const char* page_id,
+ const char* cid,
+ const char* json_data) {
+ WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
+ weex::base::MakeCopyable(
+ [page_id = std::string(page_id), cid = std::string(cid), json_data = std::string(json_data)]() {
+ WeexCoreManager::Instance()
+ ->script_bridge()
+ ->core_side()
+ ->UpdateComponentData(page_id.c_str(), cid.c_str(), json_data.c_str());
+ }));
+}
+
static void ReportException(const char *page_id, const char *func,
const char *exception_string) {
// WeexCoreManager::Instance()->script_bridge()->core_side()->ReportException(
@@ -529,7 +542,8 @@ FunctionsExposedByCore *ScriptBridgeInMultiSo::GetExposedFunctions() {
PostMessage,
DispatchMessage,
DispatchMessageSync,
- OnReceivedResult};
+ OnReceivedResult,
+ UpdateComponentData};
auto functions =
(FunctionsExposedByCore *)malloc(sizeof(FunctionsExposedByCore));
memset(functions, 0, sizeof(FunctionsExposedByCore));
diff --git a/weex_core/Source/android/jniprebuild/jni_files b/weex_core/Source/android/jniprebuild/jni_files
index fb9b291473..1d02d0103d 100644
--- a/weex_core/Source/android/jniprebuild/jni_files
+++ b/weex_core/Source/android/jniprebuild/jni_files
@@ -4,3 +4,4 @@ com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
com/taobao/weex/base/SystemMessageHandler.java
com/taobao/weex/bridge/WXBridge.java
com/taobao/weex/layout/ContentBoxMeasurement.java
+com/taobao/weex/bridge/RequestHandler.java
diff --git a/weex_core/Source/android/jniprebuild/jni_load.cc b/weex_core/Source/android/jniprebuild/jni_load.cc
index d668ae62e4..fba2c63ac7 100644
--- a/weex_core/Source/android/jniprebuild/jni_load.cc
+++ b/weex_core/Source/android/jniprebuild/jni_load.cc
@@ -31,6 +31,7 @@
#include "android/wrap/wx_js_object.h"
#include "android/wrap/wx_map.h"
#include "base/message_loop/message_pump_android.h"
+#include "core/network/android/default_request_handler.h"
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
base::android::InitVM(vm);
@@ -44,7 +45,8 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
WeexCore::WXJSObject::RegisterJNIUtils(env) &&
WeexCore::LogUtils::RegisterJNIUtils(env) &&
WeexCore::WXMap::RegisterJNIUtils(env) &&
- WeexCore::HashSet::RegisterJNIUtils(env);
+ WeexCore::HashSet::RegisterJNIUtils(env) &&
+ weex::core::network::DefaultRequestHandler::RegisterJNIUtils(env);
if (result) {
WeexCore::SoUtils::Init(env);
WeexCore::WMLBridge::RegisterJNIUtils(env);
diff --git a/weex_core/Source/android/jniprebuild/jniheader/RequestHandler_jni.h b/weex_core/Source/android/jniprebuild/jniheader/RequestHandler_jni.h
new file mode 100644
index 0000000000..f83ad376d3
--- /dev/null
+++ b/weex_core/Source/android/jniprebuild/jniheader/RequestHandler_jni.h
@@ -0,0 +1,122 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+// weex/weex_core/Source/android/jniprebuild/jni_generator.py
+// For
+// com/taobao/weex/bridge/RequestHandler
+
+#ifndef com_taobao_weex_bridge_RequestHandler_JNI
+#define com_taobao_weex_bridge_RequestHandler_JNI
+
+#include <jni.h>
+
+//#include "base/android/jni_int_wrapper.h"
+
+// Step 1: forward declarations.
+namespace {
+const char kRequestHandlerClassPath[] = "com/taobao/weex/bridge/RequestHandler";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_RequestHandler_clazz = NULL;
+#define RequestHandler_clazz(env) g_RequestHandler_clazz
+
+} // namespace
+
+static void InvokeOnSuccess(JNIEnv* env, jobject jcaller,
+ jlong callback,
+ jstring result);
+
+static void InvokeOnFailed(JNIEnv* env, jobject jcaller,
+ jlong callback);
+
+// Step 2: method stubs.
+
+static intptr_t g_RequestHandler_create = 0;
+static base::android::ScopedLocalJavaRef<jobject>
+ Java_RequestHandler_create(JNIEnv* env) {
+ /* Must call RegisterNativesImpl() */
+ //CHECK_CLAZZ(env, RequestHandler_clazz(env),
+ // RequestHandler_clazz(env), NULL);
+ jmethodID method_id =
+ base::android::GetMethod(
+ env, RequestHandler_clazz(env),
+ base::android::STATIC_METHOD,
+ "create",
+
+"("
+")"
+"Lcom/taobao/weex/bridge/RequestHandler;",
+ &g_RequestHandler_create);
+
+ jobject ret =
+ env->CallStaticObjectMethod(RequestHandler_clazz(env),
+ method_id);
+ base::android::CheckException(env);
+ return base::android::ScopedLocalJavaRef<jobject>(env, ret);
+}
+
+static intptr_t g_RequestHandler_send = 0;
+static void Java_RequestHandler_send(JNIEnv* env, jobject obj, jstring
+ instanceId,
+ jstring url,
+ jlong nativeCallback) {
+ /* Must call RegisterNativesImpl() */
+ //CHECK_CLAZZ(env, obj,
+ // RequestHandler_clazz(env));
+ jmethodID method_id =
+ base::android::GetMethod(
+ env, RequestHandler_clazz(env),
+ base::android::INSTANCE_METHOD,
+ "send",
+
+"("
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+"J"
+")"
+"V",
+ &g_RequestHandler_send);
+
+ env->CallVoidMethod(obj,
+ method_id, instanceId, url, nativeCallback);
+ base::android::CheckException(env);
+
+}
+
+// Step 3: RegisterNatives.
+
+static const JNINativeMethod kMethodsRequestHandler[] = {
+ { "nativeInvokeOnSuccess",
+"("
+"J"
+"Ljava/lang/String;"
+")"
+"V", reinterpret_cast<void*>(InvokeOnSuccess) },
+ { "nativeInvokeOnFailed",
+"("
+"J"
+")"
+"V", reinterpret_cast<void*>(InvokeOnFailed) },
+};
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+ g_RequestHandler_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+ base::android::GetClass(env, kRequestHandlerClassPath).Get()));
+
+ const int kMethodsRequestHandlerSize =
+ sizeof(kMethodsRequestHandler)/sizeof(kMethodsRequestHandler[0]);
+
+ if (env->RegisterNatives(RequestHandler_clazz(env),
+ kMethodsRequestHandler,
+ kMethodsRequestHandlerSize) < 0) {
+ //jni_generator::HandleRegistrationError(
+ // env, RequestHandler_clazz(env), __FILE__);
+ return false;
+ }
+
+ return true;
+}
+
+#endif // com_taobao_weex_bridge_RequestHandler_JNI
diff --git a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
index 0b746fd559..b431c4e660 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -77,7 +77,8 @@ static void FireEventOnDataRenderNode(JNIEnv* env, jobject jcaller,
jstring instanceId,
jstring ref,
jstring type,
- jstring data);
+ jstring data,
+ jstring domChanges);
static void RegisterModuleOnDataRenderNode(JNIEnv* env, jobject jcaller,
jstring data);
@@ -993,6 +994,7 @@ static const JNINativeMethod kMethodsWXBridge[] = {
"Ljava/lang/String;"
"Ljava/lang/String;"
"Ljava/lang/String;"
+"Ljava/lang/String;"
")"
"V", reinterpret_cast<void*>(FireEventOnDataRenderNode) },
{ "nativeRegisterModuleOnDataRenderNode",
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp b/weex_core/Source/android/wrap/wx_bridge.cpp
index a699324178..2e9cf92585 100644
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -582,7 +582,9 @@ static jstring ExecJSOnInstance(JNIEnv* env, jobject jcaller,
}
static void FireEventOnDataRenderNode(JNIEnv* env, jobject jcaller,
- jstring instanceId, jstring ref, jstring type, jstring data) {
+ jstring instanceId, jstring ref,
+ jstring type, jstring data,
+ jstring domChanges) {
if (instanceId == NULL || ref == NULL || type == NULL || data == NULL) {
return;
}
@@ -591,13 +593,14 @@ static void FireEventOnDataRenderNode(JNIEnv* env, jobject jcaller,
ScopedJStringUTF8 refChar(env, ref);
ScopedJStringUTF8 typeChar(env, type);
ScopedJStringUTF8 dataChar(env, data);
+ ScopedJStringUTF8 domChangesChar(env, domChanges);
try {
weex::core::data_render::VNodeRenderManager::GetInstance()->FireEvent(
- idChar.getChars(), refChar.getChars(), typeChar.getChars(), dataChar.getChars()
- );
- } catch (std::exception &e) {
- auto error = static_cast<weex::core::data_render::Error *>(&e);
+ idChar.getChars(), refChar.getChars(), typeChar.getChars(),
+ dataChar.getChars(), domChangesChar.getChars());
+ } catch (std::exception& e) {
+ auto error = static_cast<weex::core::data_render::Error*>(&e);
if (error) {
LOGE("Error on FireEventOnDataRenderNode %s", error->what());
}
diff --git a/weex_core/Source/base/string_util.h b/weex_core/Source/base/string_util.h
index 9e07c97c6d..4e0ea3b680 100644
--- a/weex_core/Source/base/string_util.h
+++ b/weex_core/Source/base/string_util.h
@@ -87,6 +87,35 @@ inline static std::string to_utf8(uint16_t* utf16, size_t length) {
return output;
}
+#ifdef OS_ANDROID
+static std::u16string to_utf16(char* utf8, size_t length) {
+ std::u16string dest_str;
+ dest_str.resize(length);
+ auto* dest = &dest_str[0];
+ int32_t dest_len = 0;
+
+ bool success = true;
+
+ for (int32_t i = 0; i < length;) {
+ int32_t code_point;
+ CBU8_NEXT(utf8, i, static_cast<int32_t>(length), code_point);
+
+ if (!IsValidCodepoint(code_point)) {
+ success = false;
+ code_point = kErrorCodePoint;
+ }
+
+ CBU16_APPEND_UNSAFE(dest, dest_len, code_point);
+ }
+ if (!success) {
+ return std::u16string();
+ }
+ dest_str.resize(dest_len);
+ dest_str.shrink_to_fit();
+ return dest_str;
+}
+#endif
+
} // namespace base
} // namespace weex
#endif // CORE_BASE_STRING_UTIL_H
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 a35ac01ecb..b767ed43fa 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
@@ -429,16 +429,36 @@ int CoreSideInPlatform::CreateInstance(const char *instanceId, const char *func,
const char *render_strategy) {
// First check about DATA_RENDER mode
if (render_strategy != nullptr) {
+ std::function<void(const char *)> exec_js =
+ [instanceId = std::string(instanceId), func = std::string(func),
+ opts = std::string(opts), initData = std::string(initData),
+ extendsApi = std::string(extendsApi)](const char *result) {
+ // FIXME Now only support vue, this should be fixed
+ std::string error;
+ auto opts_json = json11::Json::parse(opts, error);
+ std::map<std::string, json11::Json> &opts_map =
+ const_cast<std::map<std::string, json11::Json> &>(
+ opts_json.object_items());
+ opts_map["bundleType"] = "Vue";
+ WeexCoreManager::Instance()
+ ->script_bridge()
+ ->script_side()
+ ->CreateInstance(instanceId.c_str(), func.c_str(), result,
+ opts_json.dump().c_str(), initData.c_str(),
+ extendsApi.c_str());
+ };
if (strcmp(render_strategy, "DATA_RENDER") == 0) {
auto node_manager =
- weex::core::data_render::VNodeRenderManager::GetInstance();
- node_manager->CreatePage(script, instanceId, render_strategy, initData);
+ weex::core::data_render::VNodeRenderManager::GetInstance();
+ node_manager->CreatePage(script, instanceId, render_strategy, initData,
+ exec_js);
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);
+ weex::core::data_render::VNodeRenderManager::GetInstance();
+ node_manager->CreatePage(script, script_length, instanceId,
+ render_strategy, initData, exec_js);
return true;
}
diff --git a/weex_core/Source/core/bridge/script/core_side_in_script.cpp b/weex_core/Source/core/bridge/script/core_side_in_script.cpp
index d9412455c9..a9ba409e3b 100644
--- a/weex_core/Source/core/bridge/script/core_side_in_script.cpp
+++ b/weex_core/Source/core/bridge/script/core_side_in_script.cpp
@@ -25,6 +25,7 @@
#include "base/thread/waitable_event.h"
#include "core/manager/weex_core_manager.h"
#include "core/render/manager/render_manager.h"
+#include "core/data_render/vnode/vnode_render_manager.h"
#ifdef OS_ANDROID
#include "android/jsengine/multiprocess/ExtendJSApi.h"
#endif
@@ -468,4 +469,12 @@ void CoreSideInScript::OnReceivedResult(long callback_id,
->platform_side()
->OnReceivedResult(callback_id, result);
}
+
+void CoreSideInScript::UpdateComponentData(const char* page_id,
+ const char* cid,
+ const char* json_data) {
+ weex::core::data_render::VNodeRenderManager::GetInstance()
+ ->UpdateComponentData(page_id, cid, json_data);
+}
+
} // namespace WeexCore
diff --git a/weex_core/Source/core/bridge/script/core_side_in_script.h b/weex_core/Source/core/bridge/script/core_side_in_script.h
index 125b1af86a..2c53c1c87b 100644
--- a/weex_core/Source/core/bridge/script/core_side_in_script.h
+++ b/weex_core/Source/core/bridge/script/core_side_in_script.h
@@ -80,6 +80,9 @@ class CoreSideInScript : public ScriptBridge::CoreSide {
void SetJSVersion(const char *js_version) override;
void OnReceivedResult(long callback_id,
std::unique_ptr<WeexJSResult> &result) override;
+ void UpdateComponentData(const char* page_id,
+ const char* cid,
+ const char* json_data) override;
private:
DISALLOW_COPY_AND_ASSIGN(CoreSideInScript);
diff --git a/weex_core/Source/core/bridge/script_bridge.h b/weex_core/Source/core/bridge/script_bridge.h
index 0c85e0b143..7790792706 100644
--- a/weex_core/Source/core/bridge/script_bridge.h
+++ b/weex_core/Source/core/bridge/script_bridge.h
@@ -84,6 +84,9 @@ class ScriptBridge {
virtual void SetJSVersion(const char *js_version) = 0;
virtual void OnReceivedResult(long callback_id,
std::unique_ptr<WeexJSResult> &result) = 0;
+ virtual void UpdateComponentData(const char* page_id,
+ const char* cid,
+ const char* json_data) = 0;
inline ScriptBridge *bridge() { return bridge_; }
diff --git a/weex_core/Source/core/data_render/ast.h b/weex_core/Source/core/data_render/ast.h
index 1bdfa7ff64..c8509f7c7d 100644
--- a/weex_core/Source/core/data_render/ast.h
+++ b/weex_core/Source/core/data_render/ast.h
@@ -167,6 +167,8 @@ class ExpressionList : public Expression {
void Insert(Handle<Expression> expr) { exprs_.push_back(expr); }
+ void Insert(iterator position, Handle<Expression> expr) { exprs_.insert(position, expr); }
+
size_t Size() { return exprs_.size(); }
std::vector<Handle<Expression>>& raw_list() { return exprs_; }
diff --git a/weex_core/Source/core/data_render/class_json.cc b/weex_core/Source/core/data_render/class_json.cc
index ac1e143df5..4d80748115 100644
--- a/weex_core/Source/core/data_render/class_json.cc
+++ b/weex_core/Source/core/data_render/class_json.cc
@@ -58,7 +58,7 @@ static Value stringify(ExecState *exec_state) {
else if (IsArray(value)) {
json_string = ArrayToString(ValueTo<Array>(value));
}
- ret = exec_state->string_table()->StringFromUTF8(json_string);
+ ret = Value(exec_state->string_table()->StringFromUTF8(json_string));
} while (0);
diff --git a/weex_core/Source/core/data_render/class_math.cc b/weex_core/Source/core/data_render/class_math.cc
index 119f1b1206..9d1b282413 100644
--- a/weex_core/Source/core/data_render/class_math.cc
+++ b/weex_core/Source/core/data_render/class_math.cc
@@ -24,9 +24,9 @@ static Value Ceil(ExecState* exec_state){
}
if (IsNumber(value)){
- return static_cast<int64_t>(ceil(NumValue(value)));
+ return Value(static_cast<int64_t>(ceil(NumValue(value))));
} else {
- return static_cast<int64_t>(ceil(IntValue(value)));
+ return Value(static_cast<int64_t>(ceil(IntValue(value))));
}
}
@@ -41,15 +41,15 @@ static Value Floor(ExecState* exec_state){
}
if (IsNumber(value)){
- return static_cast<int64_t>(floor(NumValue(value)));
+ return Value(static_cast<int64_t>(floor(NumValue(value))));
} else {
- return static_cast<int64_t>(floor(IntValue(value)));
+ return Value(static_cast<int64_t>(floor(IntValue(value))));
}
}
static Value Random(ExecState* exec_state){
- return static_cast <double> (rand()) / static_cast <double>(RAND_MAX);
+ return Value(static_cast <double> (rand()) / static_cast <double>(RAND_MAX));
}
static Value Max(ExecState* exec_state){
diff --git a/weex_core/Source/core/data_render/class_object.cc b/weex_core/Source/core/data_render/class_object.cc
index eb38ef5398..720043f7e1 100644
--- a/weex_core/Source/core/data_render/class_object.cc
+++ b/weex_core/Source/core/data_render/class_object.cc
@@ -52,7 +52,7 @@ static Value keys(ExecState *exec_state) {
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]));
+ SetArray(array, i, Value(exec_state->string_table()->StringFromUTF8(keys[i])));
}
}
diff --git a/weex_core/Source/core/data_render/class_regex.cc b/weex_core/Source/core/data_render/class_regex.cc
index 95204f0687..3d55d3820e 100644
--- a/weex_core/Source/core/data_render/class_regex.cc
+++ b/weex_core/Source/core/data_render/class_regex.cc
@@ -69,7 +69,7 @@ static Value test(ExecState *exec_state) {
}
std::regex express(reg_str, type);
std::smatch match;
- ret = std::regex_search(test_str,match,express);
+ ret = Value(std::regex_search(test_str,match,express));
} while (0);
return ret;
@@ -115,7 +115,7 @@ static Value exec(ExecState *exec_state) {
std::string::const_iterator iterEnd = test_str.end();
bool succ = false;
while (std::regex_search(iterStart,iterEnd,match,express)){
- arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[0]));
+ arr->items.push_back(Value(exec_state->string_table()->StringFromUTF8(match[0])));
iterStart = match[0].second;
succ = true;
}
@@ -129,7 +129,7 @@ static Value exec(ExecState *exec_state) {
if (succ){
for (size_t i = 0; i < match.size(); ++i){
- arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[i]));
+ arr->items.push_back(Value(exec_state->string_table()->StringFromUTF8(match[i])));
}
} else {
ret = Value();
diff --git a/weex_core/Source/core/data_render/class_string.cc b/weex_core/Source/core/data_render/class_string.cc
index fa8b89db7c..50bcb29bdc 100644
--- a/weex_core/Source/core/data_render/class_string.cc
+++ b/weex_core/Source/core/data_render/class_string.cc
@@ -131,8 +131,8 @@ static Value replaceAll(ExecState *exec_state) {
std::string oldstr = CStringValue(oldValue);
std::string newstr = CStringValue(newValue);
std::string dststr = replace_all(srcstr, oldstr, newstr);
- ret = exec_state->string_table()->StringFromUTF8(dststr);
-
+ ret = Value(exec_state->string_table()->StringFromUTF8(dststr));
+
} while (0);
return ret;
@@ -160,7 +160,7 @@ static Value replace(ExecState *exec_state) {
std::string oldstr = CStringValue(oldValue);
std::string dststr = replace_normal(srcstr, oldstr, newstr);
- ret = exec_state->string_table()->StringFromUTF8(dststr);
+ ret = Value(exec_state->string_table()->StringFromUTF8(dststr));
} else if (IsClassInstance(oldValue)){
ClassInstance* instance = to_regex_inst(exec_state,oldValue);
Value* reg = GetClassMember(instance, "_reg");
@@ -178,7 +178,7 @@ static Value replace(ExecState *exec_state) {
std::regex express(reg_str, type);
std::string dststr = std::regex_replace(srcstr, express, newstr,std::regex_constants::format_first_only);
- ret = exec_state->string_table()->StringFromUTF8(dststr);
+ ret = Value(exec_state->string_table()->StringFromUTF8(dststr));
} else{
throw VMExecError("old caller isn't a string or regex");
}
@@ -221,7 +221,7 @@ static Value split(ExecState *exec_state) {
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]);
+ Value string_value(exec_state->string_table()->StringFromUTF8(split_array[i]));
array->items.push_back(string_value);
}
} else if(IsClassInstance(split)){
@@ -239,7 +239,7 @@ static Value split(ExecState *exec_state) {
Array *array = ValueTo<Array>(&ret);
for(auto st: ret_vec){
- Value string_value = exec_state->string_table()->StringFromUTF8(st);
+ Value string_value(exec_state->string_table()->StringFromUTF8(st));
array->items.push_back(string_value);
}
} else {
@@ -273,7 +273,7 @@ static Value trim(ExecState* exec_state) {
std::string src = CStringValue(string);
trim(src);
- Value string_value = exec_state->string_table()->StringFromUTF8(src);
+ Value string_value(exec_state->string_table()->StringFromUTF8(src));
return string_value;
}
@@ -342,7 +342,7 @@ Value encodeURIComponent(ExecState *exec_state) {
dst = uri;
free(uri);
}
- return exec_state->string_table()->StringFromUTF8(dst);
+ return Value(exec_state->string_table()->StringFromUTF8(dst));
}
std::string utf8chr(int cp)
@@ -468,9 +468,9 @@ Value search(ExecState* exec_state) {
std::smatch match;
bool succ = std::regex_search(test_str,match,express);
if (succ){
- ret = static_cast<int64_t>(match.position(0));
+ ret = Value(static_cast<int64_t>(match.position(0)));
} else{
- ret = -1;
+ ret = Value(-1);
}
} else {
throw VMExecError("split caller isn't a string or regex");
@@ -521,7 +521,7 @@ Value match(ExecState* exec_state) {
std::string::const_iterator iterEnd = test_str.end();
bool succ = false;
while (std::regex_search(iterStart,iterEnd,match,express)){
- arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[0]));
+ arr->items.push_back(Value(exec_state->string_table()->StringFromUTF8(match[0])));
iterStart = match[0].second;
succ = true;
}
@@ -535,7 +535,7 @@ Value match(ExecState* exec_state) {
if (succ){
for (size_t i = 0; i < match.size(); ++i){
- arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[i]));
+ arr->items.push_back(Value(exec_state->string_table()->StringFromUTF8(match[i])));
}
} else {
ret = Value();
diff --git a/weex_core/Source/core/data_render/code_generator.cc b/weex_core/Source/core/data_render/code_generator.cc
index 1cbc4e541a..a472243b53 100644
--- a/weex_core/Source/core/data_render/code_generator.cc
+++ b/weex_core/Source/core/data_render/code_generator.cc
@@ -117,8 +117,8 @@ void CodeGenerator::Visit(StringConstant* node, void* data) {
if (reg >= 0) {
FuncState *func_state = func_->func_state();
auto value = exec_state_->string_table_->StringFromUTF8(node->string());
- int index = func_state->AddConstant(std::move(value));
- Instruction i = CREATE_ABx(OP_LOADK, reg, index);
+ int index = func_state->AddConstant(Value(value));
+ Instruction i = CREATE_ABx(OP_LOADK, reg, index);
func_state->AddInstruction(i);
}
}
@@ -134,10 +134,10 @@ void CodeGenerator::Visit(RegexConstant* node, void* data) {
auto reg_mem_name = exec_state_->string_table_->StringFromUTF8("_reg");
auto flag_mem_name = exec_state_->string_table_->StringFromUTF8("_flag");
- int r_index = func_state->AddConstant(std::move(reg_ex));
- int f_index = func_state->AddConstant(std::move(flag));
- int mr_index = func_state->AddConstant(std::move(reg_mem_name));
- int mf_index = func_state->AddConstant(std::move(flag_mem_name));
+ int r_index = func_state->AddConstant(Value(reg_ex));
+ int f_index = func_state->AddConstant(Value(flag));
+ int mr_index = func_state->AddConstant(Value(reg_mem_name));
+ int mf_index = func_state->AddConstant(Value(flag_mem_name));
auto reg_class_index = exec_state_->global()->IndexOf("RegExp");
auto mr_id = block_->NextRegisterId();
@@ -229,7 +229,7 @@ void CodeGenerator::Visit(CallExpression *stms, void *data) {
if (stms->expr()->IsIdentifier() && stms->member() && stms->member()->IsIdentifier()) {
long reg_member = block_->NextRegisterId();
auto value = exec_state_->string_table_->StringFromUTF8(stms->member()->AsIdentifier()->GetName());
- int tableIndex = func_state->AddConstant(std::move(value));
+ int tableIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, reg_member, tableIndex));
long reg_class = block_->FindRegisterId(stms->expr()->AsIdentifier()->GetName());
if (reg_class < 0) {
@@ -427,8 +427,7 @@ void CodeGenerator::Visit(ForStatement *node, void *data) {
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);
+ node->update()->Accept(this, nullptr);
}
block_->set_for_update_index(for_update_index);
func_state->AddInstruction(CREATE_Ax(OP_GOTO, condition_start_index));
@@ -463,6 +462,7 @@ void CodeGenerator::Visit(FunctionStatement *node, void *data) {
auto slot = func_->func_state()->AddInstruction(0);
{
FuncScope scope(this);
+ func_->func_state()->set_name(proto->GetName());
if (is_class_func) {
Value value;
value.f = func_->func_state();
@@ -628,7 +628,7 @@ void CodeGenerator::Visit(ArrowFunctionStatement *node, void *data) {
void CodeGenerator::Visit(ClassStatement *node, void *data) {
do {
Handle<Expression> super_expr = node->Super();
- Value *super_value = nullptr,class_value = nullptr;
+ Value *super_value = nullptr;
if (super_expr) {
if (!super_expr->IsIdentifier()) {
throw GeneratorError("super isn't a Identifier");
@@ -651,7 +651,7 @@ void CodeGenerator::Visit(ClassStatement *node, void *data) {
throw GeneratorError(class_name + "redefine");
break;
}
- class_value = exec_state_->class_factory()->CreateClassDescriptor(super_value ? ValueTo<ClassDescriptor>(super_value) : nullptr);
+ Value class_value(exec_state_->class_factory()->CreateClassDescriptor(super_value ? ValueTo<ClassDescriptor>(super_value) : nullptr));
exec_state_->global()->Add(class_name, class_value);
ClassScope scope(this, &class_value);
class_->class_name() = class_name;
@@ -1039,7 +1039,7 @@ void CodeGenerator::Visit(IntegralConstant* node, void* data) {
if (reg >= 0) {
FuncState* func_state = func_->func_state();
int value = node->value();
- int index = func_state->AddConstant(static_cast<int64_t>(value));
+ int index = func_state->AddConstant(Value(static_cast<int64_t>(value)));
Instruction i = CREATE_ABx(OP_LOADK, reg, index);
func_state->AddInstruction(i);
}
@@ -1050,7 +1050,7 @@ void CodeGenerator::Visit(BooleanConstant* node, void* data) {
if (reg >= 0) {
FuncState* func_state = func_->func_state();
bool value = node->pred();
- int index = func_state->AddConstant(static_cast<bool>(value));
+ int index = func_state->AddConstant(Value(static_cast<bool>(value)));
Instruction i = CREATE_ABx(OP_LOADK, reg, index);
func_state->AddInstruction(i);
}
@@ -1061,7 +1061,7 @@ void CodeGenerator::Visit(DoubleConstant* node, void* data) {
if (reg >= 0) {
FuncState* func_state = func_->func_state();
double value = node->value();
- int index = func_state->AddConstant(static_cast<double>(value));
+ int index = func_state->AddConstant(Value(static_cast<double>(value)));
Instruction i = CREATE_ABx(OP_LOADK, reg, index);
func_state->AddInstruction(i);
}
@@ -1111,7 +1111,7 @@ void CodeGenerator::Visit(ObjectConstant *node, void *data) {
long key = block_->NextRegisterId();
iter->second->Accept(this, &item);
auto value = exec_state_->string_table_->StringFromUTF8(iter->first);
- int keyIndex = func_state->AddConstant(std::move(value));
+ int keyIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, key, keyIndex));
func_state->AddInstruction(CREATE_ABC(OP_SETTABLE, ret, key, item));
}
@@ -1131,7 +1131,7 @@ void CodeGenerator::Visit(ObjectConstant *node, void *data) {
auto ktemp = (*it).second;
ktemp->Accept(this, &item);
auto value = exec_state_->string_table_->StringFromUTF8(it->first);
- int keyIndex = func_state->AddConstant(std::move(value));
+ int keyIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, key, keyIndex));
func_state->AddInstruction(CREATE_ABC(OP_SETTABLE, ret, key, item));
}
@@ -1171,7 +1171,7 @@ void CodeGenerator::Visit(ClassProperty *node, void *data) {
}
func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, lhs, index));
auto constant = exec_state_->string_table_->StringFromUTF8(node->name());
- index = func_state->AddConstant(std::move(constant));
+ index = func_state->AddConstant(Value(constant));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, rhs, index));
func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, lhs, lhs, rhs));
if (node->init()) {
@@ -1209,7 +1209,7 @@ void CodeGenerator::Visit(MemberExpression *node, void *data) {
left->Accept(this, &ret);
long right = block_->NextRegisterId();
auto value = exec_state_->string_table_->StringFromUTF8(node->member()->AsIdentifier()->GetName());
- int tableIndex = func_state->AddConstant(std::move(value));
+ int tableIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, right, tableIndex));
if (!node->ProduceRValue()) {
func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, ret, ret, right));
@@ -1223,7 +1223,7 @@ void CodeGenerator::Visit(MemberExpression *node, void *data) {
left->Accept(this, &ret);
long right = block_->NextRegisterId();
auto value = exec_state_->string_table_->StringFromUTF8(node->member()->AsIdentifier()->GetName());
- int tableIndex = func_state->AddConstant(std::move(value));
+ int tableIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(CREATE_ABx(OP_LOADK, right, tableIndex));
if (!node->ProduceRValue()) {
func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, ret, ret, right));
@@ -1260,7 +1260,7 @@ void CodeGenerator::Visit(Identifier *node, void *data) {
FuncState* func_state = func_->func_state();
auto value = exec_state_->string_table_->StringFromUTF8(node->GetName());
- int tableIndex = func_state->AddConstant(std::move(value));
+ int tableIndex = func_state->AddConstant(Value(value));
func_state->AddInstruction(
CREATE_ABx(OP_LOADK, right, tableIndex));
@@ -1278,12 +1278,10 @@ void CodeGenerator::Visit(PrefixExpression *node, void *data) {
long ret = data == nullptr ? block_->NextRegisterId()
: *static_cast<long *>(data);
Handle<Expression> expr = node->expr();
- long reg = -1;
+ long reg = block_->NextRegisterId();
if (expr->IsIdentifier()) {
reg = block_->FindRegisterId(expr->AsIdentifier()->GetName());
- }
- else {
- reg = block_->NextRegisterId();
+ } else {
expr->Accept(this, ®);
}
PrefixOperation operation = node->op();
@@ -1566,8 +1564,8 @@ long CodeGenerator::BlockCnt::FindRegisterId(const std::string &name) {
ValueRef *ref = parent()->FindValueRef(name, reg_ref);
if (ref) {
BlockCnt *root_block = this;
- while (root_block->children() && root_block->children()->func_state() == func_state_)
- {
+ while (root_block->children() &&
+ root_block->children()->func_state() == func_state_) {
root_block = root_block->children();
}
reg_ref = root_block->NextRegisterId();
diff --git a/weex_core/Source/core/data_render/exec_state.cc b/weex_core/Source/core/data_render/exec_state.cc
index 6ba2054c3c..5016c43ca8 100644
--- a/weex_core/Source/core/data_render/exec_state.cc
+++ b/weex_core/Source/core/data_render/exec_state.cc
@@ -274,6 +274,8 @@ void ExecState::CallFunction(Value *func, size_t argc, Value *ret) {
if (ret) {
*ret = result;
}
+ // back to the top of params for clear register
+ *stack_->top() = func + 1;
stack_->reset();
frames_.pop_back();
}
@@ -292,6 +294,8 @@ void ExecState::CallFunction(Value *func, size_t argc, Value *ret) {
frames_.push_back(frame);
resetArguments(func, argc);
vm_->RunFrame(this, frame, ret);
+ // back to the top of params for clear register
+ *stack_->top() = func + 1;
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 398e73b7c3..10dcce8424 100644
--- a/weex_core/Source/core/data_render/exec_state.h
+++ b/weex_core/Source/core/data_render/exec_state.h
@@ -131,6 +131,7 @@ class FuncState {
inline bool is_class_func() { return is_class_func_; }
inline ClassInstance * &class_inst() { return class_inst_; }
inline int &argc() { return argc_; }
+ inline const std::string &name() { return name_; }
inline std::vector<long> &args() { return args_; }
std::vector<FuncState *> all_childrens() {
std::vector<FuncState *> all_childrens;
@@ -141,12 +142,15 @@ class FuncState {
}
return all_childrens;
}
+
inline std::vector<ValueRef *> &in_closure() { return in_closure_; }
inline std::vector<ValueRef *> &out_closure() { return out_closure_; }
inline int super_index() const { return super_index_; }
inline void set_super_index(int super_index) { super_index_ = super_index; }
inline std::vector<int32_t>& in_closure_refs() { return in_closure_refs_; }
inline std::vector<int32_t>& out_closure_refs() { return out_closure_refs_; }
+ inline void set_name(const std::string& name) {name_ = name;}
+
private:
std::vector<Instruction> instructions_;
std::vector<Value> constants_;
@@ -161,6 +165,7 @@ class FuncState {
bool is_class_func_{false};
ClassInstance *class_inst_{nullptr};
int argc_{0};
+ std::string name_{""};
};
// TODO Each Func should contain a stack whose size is 256
@@ -191,6 +196,8 @@ class ExecState {
ValueRef *FindRef(int index);
void Register(const std::string& name, CFunction function);
void Register(const std::string& name, Value value);
+ void AddEvent(const std::vector<std::string>& event) {event_queue_.push_back(event);}
+ void ClearEventQueue() {event_queue_.clear();}
inline std::vector<ValueRef *> &refs() { return refs_; };
inline Variables *global() { return global_.get(); }
inline void reset(FuncState *func_state) { func_state_.reset(func_state); }
@@ -202,6 +209,9 @@ class ExecState {
inline uint32_t global_compile_index() { return global_compile_index_; }
inline uint32_t class_compile_index() { return class_compile_index_; }
inline uint32_t string_compile_index() { return string_compile_index_; }
+ inline bool exec_js_finished() const {return exec_js_finished_;}
+ inline void set_exec_js_finished(bool exec_js_finished) {exec_js_finished_ = exec_js_finished;}
+ inline const std::vector<std::vector<std::string>>& event_queue() const {return event_queue_;}
inline std::unordered_map<std::string, long>& global_variables() { return global_variables_; }
private:
friend class VM;
@@ -223,6 +233,8 @@ class ExecState {
uint32_t global_compile_index_{0};
uint32_t class_compile_index_{0};
uint32_t string_compile_index_{0};
+ bool exec_js_finished_ = false;
+ std::vector<std::vector<std::string>> event_queue_;
};
} // namespace data_render
diff --git a/weex_core/Source/core/data_render/exec_state_section.cc b/weex_core/Source/core/data_render/exec_state_section.cc
index c40df1cce3..b5754a0869 100644
--- a/weex_core/Source/core/data_render/exec_state_section.cc
+++ b/weex_core/Source/core/data_render/exec_state_section.cc
@@ -1723,6 +1723,10 @@ uint32_t SectionFunction::size() {
if (func_state->argc() > 0) {
size += GetFTLVLength(kValueFunctionArgs, sizeof(int32_t) * func_state->argc());
}
+ if (!func_state->name().empty()) {
+ uint32_t length = static_cast<uint32_t>(func_state->name().length());
+ size += GetFTLVLength(kValueFunctionName, length);
+ }
if (func_state->in_closure().size() > 0) {
size += GetFTLVLength(kValueFunctionInClosure, sizeof(int32_t) * (uint32_t)func_state->in_closure().size());
}
@@ -1804,6 +1808,12 @@ bool SectionFunction::encoding() {
break;
}
}
+ if (!func_state->name().empty()) {
+ uint32_t length = static_cast<uint32_t>(func_state->name().length());
+ if (!Section::encoding(kValueFunctionName, length, (uint8_t *)func_state->name().c_str())) {
+ break;
+ }
+ }
if (func_state->in_closure().size() > 0) {
size_t size = sizeof(int32_t) * func_state->in_closure().size();
int32_t *buffer = (int32_t *)malloc(size);
@@ -1958,6 +1968,22 @@ bool SectionFunction::decoding() {
func_state->argc() = readcnt;
break;
}
+ case kValueFunctionName:
+ {
+ char *pstr = (char *)malloc(readbytes + 1);
+ if (!pstr) {
+ throw DecoderError("decoding read function low memory error");
+ break;
+ }
+ memset(pstr, 0, readbytes + 1);
+ if (stream->Read(pstr, 1, readbytes) != readbytes) {
+ throw DecoderError("decoding read function error");
+ break;
+ }
+ func_state->set_name(pstr);
+ free(pstr);
+ break;
+ }
case kValueFunctionInstructions:
{
uint8_t *buffer = (uint8_t *)malloc(readbytes);
@@ -2106,13 +2132,24 @@ uint32_t SectionGlobalConstants::size() {
break;
}
size += GetFTLVLength(kValueGlobalConstantsSize, sizeof(int32_t));
- uint32_t constant_length = 0;
for (uint32_t i = compile_index; i < global->size(); i++) {
+ size += GetFTLVLength(kValueGlobalConstantsValue, sizeof(int32_t));
Value *value = global->Find(compile_index);
- constant_length += GetValueLength(value);
+ uint32_t length = GetValueLength(value);
+ size += GetFTLVLength(kValueGlobalConstantsValue, length);
+
+ const std::map<std::string, int>& global_map = global->map();
+ for (auto it : global_map) {
+ if (it.second == compile_index + i) {
+ if (!it.first.empty()) {
+ uint32_t length = static_cast<uint32_t>(it.first.length());
+ size += GetFTLVLength(kValueGlobalConstantsName, length);
+ break;
+ }
+ }
+ }
}
- size += GetFTLVLength(kValueGlobalConstantsPayload, constant_length);
-
+ size += GetFTLVLength(kValueGlobalConstantsFinished, sizeof(uint8_t));
} while (0);
return size;
@@ -2135,33 +2172,40 @@ bool SectionGlobalConstants::encoding() {
if (!Section::encoding(kValueGlobalConstantsSize, sizeof(uint32_t), &constants_count)) {
break;
}
- uint32_t constants_payload_length = 0;
- for (int i = 0; i < constants_count; i++) {
- Value *value = global->Find(compile_index + i);
- constants_payload_length += GetValueLength(value);
- }
- uint8_t *buffer = (uint8_t *)malloc(constants_payload_length);
- if (!buffer) {
- throw EncoderError("low memory error");
- break;
- }
- uint8_t *write_buffer = buffer;
- uint32_t remain_length = constants_payload_length;
for (int i = 0; i < constants_count; i++) {
Value *value = global->Find(compile_index + i);
uint32_t length = GetValueLength(value);
- uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, value);
+ uint8_t *buffer = (uint8_t *)malloc(length);
+ if (!buffer) {
+ throw EncoderError("low memory error");
+ break;
+ }
+
+ uint32_t bytes_write = Section::encodingValueToBuffer(buffer, length, value);
if (bytes_write != length) {
throw EncoderError("encoding global constants value error");
break;
}
- remain_length -= bytes_write;
- write_buffer += bytes_write;
- }
- if (!Section::encoding(kValueGlobalConstantsPayload, constants_payload_length, buffer)) {
- break;
+ if (!Section::encoding(kValueGlobalConstantsValue, length, buffer)) {
+ throw EncoderError("encoding global constants value error");
+ break;
+ }
+ const std::map<std::string, int>& global_map = global->map();
+ for (auto it : global_map) {
+ if (it.second == compile_index + i) {
+ if (!it.first.empty()) {
+ uint32_t length = static_cast<uint32_t>(it.first.length());
+ if (!Section::encoding(kValueGlobalConstantsName, length, (uint8_t *)it.first.c_str())) {
+ throw DecoderError("encoding global constants name error");
+ break;
+ }
+ break;
+ }
+ }
+ }
+ free(buffer);
}
- free(buffer);
+
finished = true;
} while (0);
@@ -2186,25 +2230,7 @@ bool SectionGlobalConstants::decoding() {
if (!readbytes || target != kValueGlobalConstantsSize || !constants_count) {
break;
}
- if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) {
- throw DecoderError("decoding global constants target error");
- break;
- }
- if (target != kValueGlobalConstantsPayload) {
- break;
- }
- uint8_t *buffer = (uint8_t *)malloc(readbytes);
- if (!buffer) {
- throw DecoderError("low memory error");
- break;
- }
- if (stream->Read(buffer, 1, readbytes) != readbytes) {
- throw DecoderError("decoding global constants payload error");
- break;
- }
- uint8_t *read_buffer = buffer;
- uint32_t remain_length = readbytes;
- uint32_t bytes_read = 0;
+
Variables *global = decoder()->exec_state()->global();
if (global->IndexOf("__weex_data__") < 0) {
global->Set("__weex_data__", Value());
@@ -2212,21 +2238,75 @@ bool SectionGlobalConstants::decoding() {
if (global->IndexOf("_init_data") < 0) {
global->Set("_init_data", Value());
}
+
+ bool read_target = true;
for (int i = 0; i < constants_count; i++) {
+ if (read_target) {
+ if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) {
+ throw DecoderError("decoding global constants target error");
+ break;
+ }
+ }
+ read_target = true;
+ if (target != kValueGlobalConstantsValue) {
+ throw DecoderError("decoding global constants target error");
+ break;
+ }
+ uint8_t *buffer = (uint8_t *)malloc(readbytes);
+ if (!buffer) {
+ throw DecoderError("low memory error");
+ break;
+ }
+ if (stream->Read(buffer, 1, readbytes) != readbytes) {
+ throw DecoderError("decoding global constants payload error");
+ break;
+ }
Value value;
- if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &value))) {
- throw DecoderError("decoding function constants payload error");
+ if (!decodingValueFromBuffer(buffer, readbytes, &value)) {
+ throw DecoderError("decoding global constants value error");
break;
}
- read_buffer += bytes_read;
- remain_length -= bytes_read;
- global->Add(value);
- }
- if (remain_length != 0) {
- throw DecoderError("decoding function constants payload error");
- break;
+ free(buffer);
+ if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) {
+ throw DecoderError("decoding global constants target error");
+ break;
+ }
+ switch (target) {
+ case kValueGlobalConstantsName:
+ {
+ char *name = (char *)malloc(readbytes + 1);
+ if (!name) {
+ throw DecoderError("decoding global constants low memory error");
+ break;
+ }
+ memset(name, 0, readbytes + 1);
+ if (stream->Read(name, 1, readbytes) != readbytes) {
+ throw DecoderError("decoding global constants name error");
+ break;
+ }
+ global->Add(name, value);
+ free(name);
+ break;
+ }
+ case kValueGlobalConstantsValue:
+ {
+ global->Add(value);
+ read_target = false;
+ break;
+ }
+ case SECTION_VALUE_FINISHED:
+ {
+ break;
+ }
+ default:
+ {
+ if (stream->Seek(readbytes, SEEK_CUR) < 0) {
+ throw DecoderError("decoding global constants error");
+ }
+ break;
+ }
+ }
}
- free(buffer);
finished = true;
} while (0);
diff --git a/weex_core/Source/core/data_render/exec_state_section.h b/weex_core/Source/core/data_render/exec_state_section.h
index 2989ba1f7c..3770dfd8db 100644
--- a/weex_core/Source/core/data_render/exec_state_section.h
+++ b/weex_core/Source/core/data_render/exec_state_section.h
@@ -150,6 +150,7 @@ class SectionFunction : public Section {
kValueFunctionSuper,
kValueFunctionClass,
kValueFunctionArgs,
+ kValueFunctionName,
kValueFunctionInClosure,
kValueFunctionOutClosure,
kValueFunctionInstructions,
@@ -174,7 +175,9 @@ class SectionGlobalConstants : public Section {
public:
enum SectionKey {
kValueGlobalConstantsSize,
- kValueGlobalConstantsPayload,
+ kValueGlobalConstantsName,
+ kValueGlobalConstantsValue,
+ kValueGlobalConstantsFinished = 255,
};
SectionGlobalConstants(ExecStateEncoder *encoder) : Section(encoder) {}
SectionGlobalConstants(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {}
diff --git a/weex_core/Source/core/data_render/object.cc b/weex_core/Source/core/data_render/object.cc
index 38f5814eec..fee0d2d585 100644
--- a/weex_core/Source/core/data_render/object.cc
+++ b/weex_core/Source/core/data_render/object.cc
@@ -128,7 +128,7 @@ bool ValueStrictEquals(const Value *a, const Value *b) {
else if (IsInt(a)) {
return IntValue(a) == IntValue(b);
}
- else if (IsBool(a)) {
+ else if (IsBool(a) && IsBool(b)) {
return BoolValue(a) == BoolValue(b);
}
else if (ToNum(a, d1) && ToNum(b, d2)) {
diff --git a/weex_core/Source/core/data_render/object.h b/weex_core/Source/core/data_render/object.h
index b551ca315a..44df5f2f3b 100644
--- a/weex_core/Source/core/data_render/object.h
+++ b/weex_core/Source/core/data_render/object.h
@@ -100,16 +100,16 @@ struct Value {
Type type;
Value() : type(NIL) {}
-
- Value(int value) : i(value), type(INT) {}
- Value(int64_t value) : i(value), type(INT) {}
+ explicit Value(int value) : i(value), type(INT) {}
+
+ explicit Value(int64_t value) : i(value), type(INT) {}
- Value(double value) : n(value), type(NUMBER) {}
+ explicit Value(double value) : n(value), type(NUMBER) {}
explicit Value(bool value) : b(value), type(BOOL) {}
- Value(String *value) : str(value), type(STRING) {}
+ explicit Value(String *value) : str(value), type(STRING) {}
explicit Value(FuncState *func) : f(func), type(FUNC) {}
@@ -210,6 +210,8 @@ struct Value {
friend bool operator!=(const Value &left, const Value &right) {
return !(left == right);
}
+ explicit operator bool() const noexcept
+ { return !(type == NIL); }
};
typedef struct Array {
@@ -623,19 +625,43 @@ inline void ArrayCopy(Value &src, Value &dest) {
}
inline void TableCopy(Value &src, Value &dest) {
- Table *st = ValueTo<Table>(&src);
- Table *dt = ValueTo<Table>(&dest);
- for (auto iter = st->map.begin(); iter != st->map.end(); iter++) {
- GCRetain(&iter->second);
- dt->map[iter->first] = iter->second;
+ if (IsNil(&src)) {
+ return;
+ }
+ Table *st = ValueTo<Table>(&src);
+ Table *dt = ValueTo<Table>(&dest);
+ for (auto st_it = st->map.begin(); st_it != st->map.end(); st_it++) {
+ GCRetain(&st_it->second);
+ auto dt_it = dt->map.find(st_it->first);
+ if (dt_it != dt->map.end()) {
+ dt_it->second = st_it->second;
+ } else {
+ dt->map.insert({st_it->first, st_it->second});
}
+ }
}
-inline void TableMapAddAll(Table *src, Table *dest) {
- for (auto iter = src->map.begin(); iter != src->map.end(); iter++) {
- GCRetain(&iter->second);
- dest->map[iter->first] = iter->second;
+inline bool TableAddAll(Value &src, Value &dest) {
+ bool updated = false;
+ if (IsNil(&src)) {
+ return updated;
+ }
+ Table *st = ValueTo<Table>(&src);
+ Table *dt = ValueTo<Table>(&dest);
+ for (auto st_it = st->map.begin(); st_it != st->map.end(); st_it++) {
+ GCRetain(&st_it->second);
+ auto dt_it = dt->map.find(st_it->first);
+ if (dt_it != dt->map.end()) {
+ if (dt_it->second != st_it->second) {
+ dt_it->second = st_it->second;
+ updated = true;
+ }
+ } else {
+ dt->map.insert({st_it->first, st_it->second});
+ updated = true;
+ }
}
+ return updated;
}
} // namespace data_render
diff --git a/weex_core/Source/core/data_render/parser.cc b/weex_core/Source/core/data_render/parser.cc
index 38a18159e2..fd8f6ef7be 100644
--- a/weex_core/Source/core/data_render/parser.cc
+++ b/weex_core/Source/core/data_render/parser.cc
@@ -18,19 +18,24 @@
*/
#include "core/data_render/parser.h"
-#include <sstream>
#include <cstdlib>
+#include <sstream>
#include "base/string_util.h"
#include "core/data_render/ast_factory.h"
#include "core/data_render/rax_parser_builder.h"
#include "core/data_render/rax_parser_context.h"
-#include "third_party/json11/json11.hpp"
#include "core/data_render/statement.h"
+#include "third_party/json11/json11.hpp"
namespace weex {
namespace core {
namespace data_render {
+static const char kCreateComponentRecursively[] =
+ "__createComponentRecursively";
+static const char kCreateBodyFunction[] = "main";
+static const char kAttrRepeatControl[] = "[[repeat]]";
+
struct ASTParser final {
/* State */
const json11::Json& json_;
@@ -49,8 +54,7 @@ struct ASTParser final {
}
int GetTemplateId(const json11::Json& component) {
- json11::Json json_template_id =
- component["template_id"].type() == Json::Type::NUMBER;
+ json11::Json json_template_id = component["templateId"];
if (json_template_id.type() == Json::Type::NUMBER) {
return json_template_id.int_value();
} else {
@@ -58,7 +62,24 @@ struct ASTParser final {
}
}
- void AddAppendChildCall(json11::Json& json, Handle<Identifier>& parent_identifier,
+ inline void SetAttributeStatement(std::vector<Handle<Expression>> args,
+ Handle<BlockStatement>& block) {
+ Handle<Expression> set_attr_func_id = factory_->NewIdentifier("setAttr");
+ Handle<CallExpression> call_func =
+ factory_->NewCallExpression(set_attr_func_id, args);
+ block->PushExpression(call_func);
+ }
+
+ inline void AddEventStatement(std::vector<Handle<Expression>> args,
+ Handle<BlockStatement>& block) {
+ Handle<Expression> set_attr_func_id = factory_->NewIdentifier("addEvent");
+ Handle<CallExpression> call_func =
+ factory_->NewCallExpression(set_attr_func_id, args);
+ block->PushExpression(call_func);
+ }
+
+ void AddAppendChildCall(json11::Json& json,
+ Handle<Identifier>& parent_identifier,
Handle<Identifier>& child_identifier) {
Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
@@ -71,10 +92,12 @@ struct ASTParser final {
statement->PushExpression(call_append_expr);
}
- void AddSetClassListCall(json11::Json& json, Handle<weex::core::data_render::Identifier> child_identifier,
- const std::string& prefix) {
+ void AddSetClassListCall(
+ json11::Json& json,
+ Handle<weex::core::data_render::Identifier> child_identifier,
+ const std::string& prefix) {
std::string wrap_prefix;
- if (!prefix.empty()) {
+ if (!prefix.empty() && prefix.compare(kCreateBodyFunction) != 0) {
wrap_prefix = "_" + prefix + "_";
}
json11::Json class_list = json["classList"];
@@ -87,8 +110,8 @@ struct ASTParser final {
for (int i = 0; i < class_list.array_items().size(); i++) {
json11::Json class_style = class_list[i];
if (class_style.is_string()) {
- args.push_back(
- factory_->NewStringConstant(wrap_prefix + class_style.string_value()));
+ args.push_back(factory_->NewStringConstant(
+ wrap_prefix + class_style.string_value()));
} else {
args.push_back(factory_->NewBinaryExpression(
BinaryOperation::kAddition,
@@ -102,6 +125,35 @@ struct ASTParser final {
}
}
+ void AddEventForVNode(
+ const json11::Json& events,
+ Handle<weex::core::data_render::Identifier> child_identifier) {
+ if (!events.is_array()) return;
+ for (auto it = events.array_items().begin();
+ it != events.array_items().end(); it++) {
+ auto event = *it;
+ if (event.is_object()) {
+ auto event_type = event["type"];
+ auto params = event["params"];
+ Handle<StringConstant> event_constant =
+ factory_->NewStringConstant(event_type.string_value());
+ std::vector<Handle<Expression>> args{child_identifier, event_constant};
+ if (params.is_array()) {
+ for (auto jt = params.array_items().begin();
+ jt != params.array_items().end(); jt++) {
+ args.push_back(ParseExpression(*jt));
+ }
+ }
+ AddEventStatement(args, stacks_[stacks_.size() - 1]);
+ } else if (event.is_string()) {
+ Handle<StringConstant> event_constant =
+ factory_->NewStringConstant(event.string_value());
+ AddEventStatement({child_identifier, event_constant},
+ stacks_[stacks_.size() - 1]);
+ }
+ }
+ }
+
ParseResult Parse() {
ASTParseError error = UNKOWN_ERROR;
do {
@@ -121,7 +173,8 @@ struct ASTParser final {
stacks_.push_back(chunk);
auto& component = json["components"];
if (component.is_array()) {
- for (auto it = component.array_items().begin(); it != component.array_items().end(); it++) {
+ for (auto it = component.array_items().begin();
+ it != component.array_items().end(); it++) {
if (!it->is_object()) {
continue;
}
@@ -148,7 +201,7 @@ struct ASTParser final {
break;
}
RAXParserBuilder builder(match.string_value());
- RAXParser *parser = builder.parser();
+ RAXParser* parser = builder.parser();
Handle<Expression> expr = parser->ParseExpression();
Handle<Expression> if_block =
MakeHandle<BlockStatement>(factory_->NewExpressionList());
@@ -169,7 +222,9 @@ struct ASTParser final {
json11::Json index = repeat["iterator1"];
Handle<DeclarationList> for_init = factory_->NewDeclarationList();
// var index=0
- for_init->Append(factory_->NewDeclaration(index.is_null() ? "index" : index.string_value(), factory_->NewIntegralConstant(0)));
+ for_init->Append(factory_->NewDeclaration(
+ index.is_null() ? "index" : index.string_value(),
+ factory_->NewIntegralConstant(0)));
json11::Json expression = repeat["for"];
if (!expression.is_string()) {
break;
@@ -179,34 +234,32 @@ struct ASTParser final {
break;
}
RAXParserBuilder builder(expression.string_value());
- RAXParser *parser = builder.parser();
+ RAXParser* parser = builder.parser();
Handle<Expression> list_expr = parser->ParseExpression();
- Handle<Identifier> index_var =
- factory_->NewIdentifier(index.is_null() ? "index" : index.string_value());
+ Handle<Identifier> index_var = factory_->NewIdentifier(
+ index.is_null() ? "index" : index.string_value());
// expr[index]
Handle<MemberExpression> indexMember = factory_->NewMemberExpression(
MemberAccessKind::kIndex, list_expr, index_var);
// var iter = expr[index]
for_init->Append(
factory_->NewDeclaration(alias.string_value(), indexMember));
- Handle<Identifier> size_of_func_id =
- factory_->NewIdentifier("sizeof");
+ Handle<Identifier> size_of_func_id = factory_->NewIdentifier("sizeof");
// sizeof(expr)
Handle<CallExpression> size_of_call =
- factory_->NewCallExpression(size_of_func_id, {list_expr});
+ factory_->NewCallExpression(size_of_func_id, {list_expr});
// index<sizeof(expr)
- Handle<Expression> for_condition = factory_->NewBinaryExpression(BinaryOperation::kLessThan, index_var, size_of_call);
+ Handle<Expression> for_condition = factory_->NewBinaryExpression(
+ BinaryOperation::kLessThan, index_var, size_of_call);
// index++
- Handle<Expression> index_update = factory_->NewPrefixExpression(PrefixOperation::kIncrement, index_var);
+ Handle<Expression> index_update =
+ factory_->NewPrefixExpression(PrefixOperation::kIncrement, index_var);
// iter = expr[index]
Handle<Expression> alias_update = factory_->NewAssignExpression(
factory_->NewIdentifier(alias.string_value()),
- factory_->NewMemberExpression(
- MemberAccessKind::kIndex,
- list_expr, index_var
- )
- );
+ factory_->NewMemberExpression(MemberAccessKind::kIndex, list_expr,
+ index_var));
std::vector<Handle<Expression>> updates;
updates.push_back(index_update);
updates.push_back(alias_update);
@@ -214,9 +267,8 @@ struct ASTParser final {
Handle<Expression> for_block =
MakeHandle<BlockStatement>(factory_->NewExpressionList());
- for_expr =
- factory_->NewForStatement(ForKind::kForOf, for_init,
- for_condition, for_update, for_block);
+ for_expr = factory_->NewForStatement(
+ ForKind::kForOf, for_init, for_condition, for_update, for_block);
if (!for_expr) {
break;
}
@@ -247,19 +299,60 @@ struct ASTParser final {
return exprs;
}
+ inline Handle<Expression> ParseExpression(const json11::Json& json) {
+ if (json.is_string()) {
+ return factory_->NewStringConstant(json.string_value());
+ } if (json.is_number()) {
+ return factory_->NewIntegralConstant(json.number_value());
+ } else {
+ return ParseBindingExpression(json);
+ }
+ }
+
Handle<Expression> ParseBindingExpression(const json11::Json& json) {
const json11::Json& exp_str = json["@binding"];
if (exp_str.is_string()) {
RAXParserBuilder builder(exp_str.string_value());
- RAXParser *parser = builder.parser();
+ RAXParser* parser = builder.parser();
return parser->ParseExpression();
- }
- else {
+ } else {
return factory_->NewNullConstant();
}
}
- //function createComponent_xxx(nodeId, this){
+ std::string ParseCreateNodeInComponentFunction(
+ json11::Json& template_object, const std::string& component_name) {
+ std::string function_name("createNodeInComponent_" + component_name);
+
+ // Declare function createNodeInComponent_xxx(this)
+ std::vector<std::string> proto_args;
+ proto_args.push_back("this");
+ proto_args.push_back("component");
+ proto_args.push_back(kCreateComponentRecursively);
+ Handle<FunctionPrototype> func_proto =
+ factory_->NewFunctionPrototype(function_name, proto_args);
+ Handle<BlockStatement> func_body =
+ factory_->NewBlockStatement(factory_->NewExpressionList());
+
+ stacks_.push_back(func_body);
+
+ // ParseNode
+ ParseNode(template_object, true, component_name);
+
+ // Declare return
+ func_body->statements()->Insert(
+ factory_->NewReturnStatement(factory_->NewIdentifier("child")));
+ stacks_.pop_back();
+
+ Handle<FunctionStatement> func_decl =
+ factory_->NewFunctionStatement(func_proto, func_body);
+ Handle<BlockStatement> chunk = stacks_.front();
+ // Declare createNodeInComponent function in global
+ chunk->statements()->Insert(func_decl);
+ return function_name;
+ }
+
+ // function createComponent_xxx(nodeId, this){
// //initialState
// this = {
// count: this.start
@@ -274,118 +367,153 @@ struct ASTParser final {
//
// //return function
// return child;
- void ParseComponentFunction(json11::Json& json) {
+ std::string ParseComponentFunction(json11::Json& json) {
auto& name = json["name"];
- auto& initial_state = json["initialState"];
json11::Json template_obj = json["template"];
int template_id = GetTemplateId(json);
- Handle<BlockStatement> chunk = stacks_.back();
-
if (!name.is_string() || !template_obj.is_object()) {
- return;
+ return "";
}
- std::string function_name("createComponent_" + name.string_value());
+ return ParseComponentFunction(template_obj, name.string_value(),
+ template_id, false);
+ }
+
+ std::string ParseComponentFunction(json11::Json& template_obj,
+ const std::string& template_name,
+ int template_id, bool is_body) {
+ Handle<BlockStatement> chunk = stacks_.back();
+
+ std::string function_name("createComponent_" + template_name);
- //function createComponent_xxx(nodeId, this)
+ // Make function createComponent_xxx(this)
std::vector<std::string> proto_args;
- proto_args.push_back("nodeId");
proto_args.push_back("this");
+ proto_args.push_back(kCreateComponentRecursively);
Handle<FunctionPrototype> func_proto =
factory_->NewFunctionPrototype(function_name, proto_args);
Handle<BlockStatement> func_body =
factory_->NewBlockStatement(factory_->NewExpressionList());
- //{
stacks_.push_back(func_body);
- //initialState
- // this = {
- // count: this.start
- // }
- if (initial_state.is_object() && initial_state.object_items().size() > 0) {
- ProxyObject initial_obj;
- for (auto it = initial_state.object_items().begin();
- it != initial_state.object_items().end(); it++) {
- const auto& key = it->first;
- const auto& value = it->second;
- Handle<Expression> expr_value;
- if (value.is_string()) {
- expr_value = factory_->NewStringConstant(value.string_value());
- } else {
- expr_value = ParseBindingExpression(value);
- }
- initial_obj.insert({key, expr_value});
- }
- func_body->statements()->Insert(factory_->NewAssignExpression(
- factory_->NewIdentifier("this"),
- factory_->NewObjectConstant(initial_obj)
- ));
- }
+
func_body->statements()->Insert(factory_->NewDeclaration(
"template_id", factory_->NewIntegralConstant(template_id)));
func_body->statements()->Insert(factory_->NewDeclaration(
- "template_name", factory_->NewStringConstant(name.string_value())));
-
- //ParseNode
- ParseNode(template_obj, true, name.string_value());
+ "template_name", factory_->NewStringConstant(template_name)));
- //return function
- func_body->statements()->Insert(factory_->NewReturnStatement(factory_->NewIdentifier("child")));
+ std::vector<Handle<Expression>> merge_args;
+ Handle<Identifier> component_data = factory_->NewMemberExpression(
+ MemberAccessKind::kDot, factory_->NewIdentifier("_components_data"),
+ factory_->NewIdentifier(template_name));
+ Handle<Declaration> data_declaration =
+ factory_->NewDeclaration("data", component_data);
+ Handle<Identifier> component_props = factory_->NewMemberExpression(
+ MemberAccessKind::kDot, factory_->NewIdentifier("_components_props"),
+ factory_->NewIdentifier(template_name));
+ Handle<Declaration> props_declaration =
+ factory_->NewDeclaration("props", component_props);
+ Handle<Identifier> component_computed = factory_->NewMemberExpression(
+ MemberAccessKind::kDot, factory_->NewIdentifier("_components_computed"),
+ factory_->NewIdentifier(template_name));
+ Handle<Declaration> computed_declaration =
+ factory_->NewDeclaration("computed", component_computed);
+ func_body->PushExpression(data_declaration);
+ func_body->PushExpression(props_declaration);
+ func_body->PushExpression(computed_declaration);
+
+ // Update props
+ merge_args.clear();
+ merge_args.push_back(factory_->NewIdentifier("props"));
+ merge_args.push_back(factory_->NewIdentifier("this"));
+ func_body->PushExpression(factory_->NewAssignExpression(
+ factory_->NewIdentifier("props"),
+ factory_->NewCallExpression(factory_->NewIdentifier("merge"),
+ merge_args)));
+
+ // Declare createNodeInComponent function in global
+ const std::string& create_node_func =
+ ParseCreateNodeInComponentFunction(template_obj, template_name);
+
+ // Component Node call createComponent
+ Handle<Expression> func = factory_->NewIdentifier("createComponent");
+ std::vector<Handle<Expression>> args;
+ args.push_back(factory_->NewIdentifier("template_id"));
+ args.push_back(factory_->NewIdentifier("template_name"));
+ args.push_back(factory_->NewStringConstant(create_node_func));
+ Handle<Declaration> component_declaration = factory_->NewDeclaration(
+ "component", factory_->NewCallExpression(func, args));
+ func_body->statements()->Insert(component_declaration);
+ args.clear();
+ args.push_back(factory_->NewIdentifier("component"));
+ args.push_back(factory_->NewIdentifier("props"));
+ args.push_back(factory_->NewIdentifier("data"));
+ func_body->statements()->Insert(factory_->NewCallExpression(
+ factory_->NewIdentifier("saveComponentPropsAndData"), args));
+
+ // if (PreventCreateComponentRecursively) {
+ // this = merge(props, this);
+ // this = merge(data, this);
+ // createNodeInComponent(this);
+ // }
+ args.clear();
+ auto if_expression_list = factory_->NewExpressionList();
+ // merge props
+ if_expression_list->Insert(factory_->NewAssignExpression(
+ factory_->NewIdentifier("this"), factory_->NewIdentifier("props")));
+ // merge data
+ merge_args.clear();
+ merge_args.push_back(factory_->NewIdentifier("data"));
+ merge_args.push_back(factory_->NewIdentifier("this"));
+ if_expression_list->Insert(factory_->NewAssignExpression(
+ factory_->NewIdentifier("this"),
+ factory_->NewCallExpression(factory_->NewIdentifier("merge"),
+ merge_args)));
+ // merge computed
+ merge_args.clear();
+ merge_args.push_back(factory_->NewIdentifier("computed"));
+ merge_args.push_back(factory_->NewIdentifier("this"));
+ if_expression_list->Insert(factory_->NewAssignExpression(
+ factory_->NewIdentifier("this"),
+ factory_->NewCallExpression(factory_->NewIdentifier("merge"),
+ merge_args)));
+
+ args.clear();
+ args.push_back(factory_->NewIdentifier("this"));
+ args.push_back(factory_->NewIdentifier("component"));
+ args.push_back(factory_->NewIdentifier(kCreateComponentRecursively));
+ auto call_create_node = factory_->NewCallExpression(
+ factory_->NewIdentifier(create_node_func), args);
+ if_expression_list->Insert(call_create_node);
+ auto if_block = factory_->NewBlockStatement(if_expression_list);
+ auto if_stat = factory_->NewIfStatement(
+ factory_->NewIdentifier(kCreateComponentRecursively), if_block);
+ func_body->statements()->Insert(if_stat);
+
+ // return function
+ func_body->statements()->Insert(
+ factory_->NewReturnStatement(factory_->NewIdentifier("component")));
stacks_.pop_back();
- //}
+
+ // Declare createComponent function in global
Handle<FunctionStatement> func_decl =
factory_->NewFunctionStatement(func_proto, func_body);
chunk->statements()->Insert(func_decl);
+ return function_name;
}
- //function main(this);
+ // function main(this);
bool ParseBodyFunction(json11::Json& body) {
- std::vector<std::string> proto_args;
- proto_args.push_back("this");
- Handle<FunctionPrototype> main_func_proto =
- factory_->NewFunctionPrototype("main", proto_args);
- Handle<BlockStatement> main_func_body =
- factory_->NewBlockStatement(factory_->NewExpressionList());
- //{
- stacks_.push_back(main_func_body);
- // var parent = null;
- main_func_body->PushExpression(factory_->NewDeclaration("parent"));
- main_func_body->PushExpression(factory_->NewDeclaration(
- "template_id", factory_->NewIntegralConstant(GetTemplateId(body))));
- main_func_body->PushExpression(factory_->NewDeclaration(
- "template_name", factory_->NewStringConstant("body")));
- // body is considered as a component
- ParseNode(body, true, "");
-
- stacks_.pop_back();
- //}
- Handle<FunctionStatement> main_func_decl = factory_->NewFunctionStatement(main_func_proto,
- main_func_body);
+ const std::string& main =
+ ParseComponentFunction(body, kCreateBodyFunction, 0, true);
Handle<BlockStatement> chunk = stacks_[stacks_.size() - 1];
-
- //function main(this);
- chunk->statements()->Insert(main_func_decl);
-
std::vector<Handle<Expression>> args;
- std::vector<Handle<Expression>> merge_args;
-
- merge_args.push_back(factory_->NewIdentifier("_data_main"));
- merge_args.push_back(factory_->NewIdentifier("_init_data"));
-
- //merge(_data_main,_init_data)
- args.push_back(
- factory_->NewCallExpression(
- factory_->NewIdentifier("merge"),
- merge_args
- )
- );
-
- //main(merge(_data_main,_init_data)
- chunk->statements()->Insert(factory_->NewCallExpression(
- factory_->NewIdentifier("main"),
- args
- ));
+ args.push_back(factory_->NewIdentifier("_init_data"));
+ args.push_back(factory_->NewBooleanConstant(true));
+ // main(merge(_data_main,_init_data)
+ chunk->statements()->Insert(
+ factory_->NewCallExpression(factory_->NewIdentifier(main), args));
return true;
}
@@ -394,8 +522,7 @@ struct ASTParser final {
factory_->NewIdentifier("parent");
static Handle<Identifier> child_identifier =
factory_->NewIdentifier("child");
- static Handle<Identifier> attr_identifier =
- factory_->NewIdentifier("attr");
+ static Handle<Identifier> attr_identifier = factory_->NewIdentifier("attr");
json11::Json control = json["control"];
std::vector<Handle<Expression>> control_exprs;
@@ -407,14 +534,14 @@ struct ASTParser final {
json11::Json component_alias = json["componentAlias"];
if (node_id.is_string() && tag_name.is_string()) {
- const std::string& component_real_name = component_alias[tag_name.string_value()].string_value();
-
+ const std::string& component_real_name =
+ component_alias[tag_name.string_value()].string_value();
Handle<Expression> call_expr = nullptr;
Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
std::vector<Handle<Expression>> args;
- //var attr = { key1:value1 }
+ // var attr = { key1:value1 }
ProxyObject attr_obj;
json11::Json attributes = json["attributes"];
if (attributes.is_object()) {
@@ -433,78 +560,40 @@ struct ASTParser final {
}
Handle<ObjectConstant> attr_init = factory_->NewObjectConstant(attr_obj);
- // merge data props into attr_decl
- // attr = merge(merge(data, props), attr)
- Handle<Identifier> component_data = factory_->NewMemberExpression(
- MemberAccessKind::kDot, factory_->NewIdentifier("_components_data"),
- factory_->NewIdentifier("template_name"));
- Handle<Identifier> component_props = factory_->NewMemberExpression(
- MemberAccessKind::kDot, factory_->NewIdentifier("_components_props"),
- factory_->NewIdentifier("template_name"));
- std::vector<Handle<Expression>> merge_args1;
- merge_args1.push_back(component_data);
- merge_args1.push_back(component_props);
- std::vector<Handle<Expression>> merge_args2;
- merge_args2.push_back(factory_->NewCallExpression(
- factory_->NewIdentifier("merge"), merge_args1));
- merge_args2.push_back(attr_init);
- Handle<Declaration> attr_decl = factory_->NewDeclaration(
- "attr", factory_->NewCallExpression(factory_->NewIdentifier("merge"),
- merge_args2));
- statement->PushExpression(attr_decl);
// var child = createComponent_xxx("node_id", attr);
{
- //createComponent_xxx("node_id", attr))
- Handle<Expression> func = factory_->NewIdentifier("createComponent_" + component_real_name);
+ // createComponent_xxx("node_id", attr))
+ Handle<Expression> func =
+ factory_->NewIdentifier("createComponent_" + component_real_name);
- args.push_back(ParseNodeId(control, control_exprs, node_id.string_value()));
- args.push_back(attr_identifier);
+ args.push_back(attr_init);
+ args.push_back(factory_->NewIdentifier(kCreateComponentRecursively));
// var child = createComponent_xxx("node_id", attr);
call_expr = factory_->NewCallExpression(func, args);
Handle<Declaration> child_declaration =
factory_->NewDeclaration("child", call_expr);
statement->PushExpression(child_declaration);
-
- // addChildComponent(component, child)
- args.clear();
- Handle<Identifier> component_identifier =
- factory_->NewIdentifier("component");
- args.push_back(component_identifier);
- args.push_back(child_identifier);
- statement->PushExpression(factory_->NewCallExpression(
- factory_->NewIdentifier("appendChildComponent"), args));
-
- // saveComponentDataAndProps(component, data, props)
- args.clear();
- args.push_back(child_identifier);
- args.push_back(component_data);
- args.push_back(component_props);
- statement->PushExpression(factory_->NewCallExpression(
- factory_->NewIdentifier("saveComponentDataAndProps"), args));
}
- //appendChild(parent, child);
+ // appendChild(parent, child);
AddAppendChildCall(json, parent_identifier, child_identifier);
-
- //setClassList(child, class_name);
- AddSetClassListCall(json, child_identifier, component_name);
}
for (int i = 0; i < control_exprs.size(); i++) {
- stacks_.pop_back();
+ stacks_.pop_back();
}
return true;
}
- Handle<Expression> ParseNodeId(const json11::Json& body,
- const std::vector<Handle<Expression>>& control_exprs,
- const std::string& node_id) {
+ Handle<Expression> ParseNodeId(
+ const json11::Json& body,
+ const std::vector<Handle<Expression>>& control_exprs,
+ const std::string& node_id) {
Handle<Expression> node_id_expr = nullptr;
node_id_expr = this->factory_->NewStringConstant(node_id);
return node_id_expr;
}
-
// Code Detail:
// var parent = nil;
// var child = createElement(tag_name, node_id);
@@ -548,7 +637,8 @@ struct ASTParser final {
// setClassList(child, class_name);
// end for / end if
// }
- bool ParseNode(json11::Json& json, bool component_root, const std::string& component_name) {
+ bool ParseNode(json11::Json& json, bool component_root,
+ const std::string& component_name) {
static Handle<Identifier> parent_identifier =
factory_->NewIdentifier("parent");
static Handle<Identifier> child_identifier =
@@ -559,11 +649,19 @@ struct ASTParser final {
std::vector<Handle<Expression>> control_exprs;
if (control.is_object()) {
control_exprs = ParseControl(control);
+ if (!control["repeat"].is_null()) {
+ SetAttributeStatement(
+ {child_identifier,
+ factory_->NewStringConstant(kAttrRepeatControl),
+ factory_->NewStringConstant("")},
+ stacks_[stacks_.size() - 1]);
+ }
}
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()) {
+ if (json["attributes"].is_object() &&
+ json["attributes"]["ref"].is_string()) {
ref = json["attributes"]["ref"];
}
Handle<Expression> node_id_expr = nullptr;
@@ -573,43 +671,24 @@ struct ASTParser final {
std::vector<Handle<Expression>> args;
// var child = createElement(tag_name, node_id, ref);
- // or
- // var child = createComponent(template_id, tag_name, node_id, ref);
{
- Handle<Expression> func;
- node_id_expr = ParseNodeId(control, control_exprs, node_id.string_value());
- if (!component_root) {
- // Common Node call createElement function
- func = factory_->NewIdentifier("createElement");
- 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
- Handle<Expression> func =
- factory_->NewIdentifier("createComponent");
- args.push_back(
- factory_->NewIdentifier("template_id"));
- args.push_back(
- factory_->NewIdentifier("template_name"));
- 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 =
- factory_->NewDeclaration("child", call_expr);
- statement->PushExpression(child_declaration);
- if (component_root) {
- // One createComponent method has one component field for
- // build component tree
- Handle<Declaration> component_declaration =
- factory_->NewDeclaration("component", child_identifier);
- statement->PushExpression(component_declaration);
- }
+ Handle<Expression> func = factory_->NewIdentifier("createElement");
+ node_id_expr =
+ ParseNodeId(control, control_exprs, node_id.string_value());
+ 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 =
+ factory_->NewDeclaration("child", call_expr);
+ statement->PushExpression(child_declaration);
+ if (component_root) {
+ args.clear();
+ args.push_back(factory_->NewIdentifier("component"));
+ args.push_back(child_identifier);
+ statement->PushExpression(factory_->NewCallExpression(
+ factory_->NewIdentifier("setComponentRoot"), args));
+ }
}
if (!component_root) {
// appendChild(parent, child);
@@ -631,19 +710,34 @@ struct ASTParser final {
args.push_back(child_identifier);
args.push_back(factory_->NewStringConstant(key));
if (value.is_string()) {
- args.push_back(
- factory_->NewStringConstant(value.string_value()));
+ args.push_back(factory_->NewStringConstant(value.string_value()));
} else {
args.push_back(ParseBindingExpression(value));
}
Handle<Expression> set_style_func_expr =
- factory_->NewIdentifier("setStyle");
+ factory_->NewIdentifier("setStyle");
Handle<CallExpression> call_func =
- factory_->NewCallExpression(set_style_func_expr, args);
+ factory_->NewCallExpression(set_style_func_expr, args);
Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
statement->PushExpression(call_func);
}
+ } else if (style.is_array()) {
+ auto items = style.array_items();
+ for (auto it = items.begin(); it != items.end(); ++it) {
+ auto item = *it;
+ if (item.is_object()) {
+ std::vector<Handle<Expression>> args;
+ args.push_back(child_identifier);
+ args.push_back(ParseBindingExpression(item));
+ 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)
@@ -653,25 +747,34 @@ struct ASTParser final {
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));
+ Handle<Expression> value_statements;
if (value.is_string()) {
- args.push_back(
- factory_->NewStringConstant(value.string_value()));
+ value_statements =
+ factory_->NewStringConstant(value.string_value());
+ } else if (value.is_array()) {
+ for (auto jt = value.array_items().begin();
+ jt != value.array_items().end(); jt++) {
+ if (value_statements) {
+ value_statements = factory_->NewBinaryExpression(
+ BinaryOperation::kAddition, value_statements,
+ ParseExpression(*jt));
+ } else {
+ value_statements = ParseExpression(*jt);
+ }
+ }
} else {
- args.push_back(ParseBindingExpression(value));
+ value_statements = ParseBindingExpression(value);
}
-
- Handle<Expression> set_attr_func_id =
- factory_->NewIdentifier("setAttr");
- Handle<CallExpression> call_func =
- factory_->NewCallExpression(set_attr_func_id, args);
- Handle<BlockStatement> statement = stacks_[stacks_.size() - 1];
- statement->PushExpression(call_func);
+ SetAttributeStatement(
+ {child_identifier, factory_->NewStringConstant(key),
+ value_statements},
+ stacks_[stacks_.size() - 1]);
}
}
+ // addEvent
+ AddEventForVNode(json["event"], child_identifier);
+
// new block for appending grandson
// {
// var parent = child;
diff --git a/weex_core/Source/core/data_render/string_table.h b/weex_core/Source/core/data_render/string_table.h
index 5d1dddd6bd..568c0232bb 100644
--- a/weex_core/Source/core/data_render/string_table.h
+++ b/weex_core/Source/core/data_render/string_table.h
@@ -34,7 +34,7 @@ class String {
explicit String(const std::string &str);
~String();
- char *c_str() { return str_.get(); }
+ char *c_str() const { return str_.get(); }
std::size_t length() { return length_; }
diff --git a/weex_core/Source/core/data_render/vm.cc b/weex_core/Source/core/data_render/vm.cc
index 000fa4d8f3..b9331dfea4 100644
--- a/weex_core/Source/core/data_render/vm.cc
+++ b/weex_core/Source/core/data_render/vm.cc
@@ -646,7 +646,7 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
if (IsValueRef(b)) {
b = b->var;
}
- if (!IsClassInstance(b) && !IsClass(b) && !IsArray(b) && !IsTable(b) && !IsString(b)) {
+ if (!IsClassInstance(b) && !IsClass(b) && !IsArray(b) && !IsTable(b) && !IsString(b) && !IsNil(b)) {
throw VMExecError("Type Error For Class Instance Or Class With OP_CODE [OP_GETMEMBER]");
}
if (!IsString(c)) {
@@ -699,10 +699,11 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
Variables *funcs = ValueTo<ClassDescriptor>(class_desc)->funcs_.get();
index = funcs->IndexOf(var_name);
if (index < 0) {
- throw VMExecError("Can't Find String Func " + var_name + " With OP_CODE [OP_GETMEMBER]");
+ SetNil(a);
+ } else {
+ Value *func = funcs->Find(index);
+ *a = *func;
}
- Value *func = funcs->Find(index);
- *a = *func;
}
else if (IsTable(b)) {
if (op == OP_GETMEMBER) {
@@ -721,6 +722,9 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
}
}
}
+ else if (IsNil(b)) {
+ SetNil(a);
+ }
else {
// only can find class static funcs;
Variables *statics = ValueTo<ClassDescriptor>(b)->statics_.get();
@@ -889,10 +893,13 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) {
Value *ret = GetTableValue(ValueTo<Table>(b), *c);
if (!IsNil(ret)) {
*a = *ret;
- }
- else {
+ } else {
SetNil(a);
}
+ } else if (IsString(b)) {
+ //LOGE("type String can not get from index");
+ } else if (IsNil(b)) {
+ SetNil(a);
}
else {
throw VMExecError("Unsupport Type Error With OP_CODE [OP_GETINDEX]");
diff --git a/weex_core/Source/core/data_render/vnode/android/conversion.cc b/weex_core/Source/core/data_render/vnode/android/conversion.cc
new file mode 100644
index 0000000000..9248dd11c4
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/android/conversion.cc
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+#ifdef OS_ANDROID
+
+#include "core/data_render/vnode/android/conversion.h"
+#include "android/utils/params_utils.h"
+#include "core/data_render/exec_state.h"
+#include "core/data_render/object.h"
+#include "core/manager/weex_core_manager.h"
+#include "wson/wson.h"
+#include "wson/wson_parser.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+json11::Json Conversion::GenJSON(const Value* v) {
+ switch (v->type) {
+ case Value::Type::NUMBER:
+ return v->n;
+ case Value::Type::STRING:
+ return v->str->c_str();
+ case Value::Type::INT:
+ return static_cast<int>(v->i);
+ case Value::Type::BOOL:
+ return v->b;
+ case Value::Type::ARRAY: {
+ Array* array = ValueTo<Array>(v);
+ std::vector<json11::Json> json_array;
+ for (auto it = array->items.begin(); it != array->items.end(); it++) {
+ json_array.push_back(GenJSON(&*it));
+ }
+ return json_array;
+ }
+ case Value::Type::TABLE: {
+ Table* table = ValueTo<Table>(v);
+ std::map<std::string, json11::Json> json_table;
+ for (auto it = table->map.begin(); it != table->map.end(); it++) {
+ json_table.insert({it->first, GenJSON(&it->second)});
+ }
+ return json_table;
+ }
+ case Value::Type::NIL:
+ return nullptr;
+ }
+}
+
+VALUE_WITH_TYPE* Conversion::GenValueWithType(const char* event_str) {
+ VALUE_WITH_TYPE* event = getValueWithTypePtr();
+ event->type = ParamsType::BYTEARRAY;
+ auto buffer = wson_buffer_new();
+ wson_push_type_uint8_string(
+ buffer, reinterpret_cast<const uint8_t*>(event_str), strlen(event_str));
+ event->value.byteArray = genWeexByteArray(
+ static_cast<const char*>(buffer->data), buffer->position);
+ buffer->data = nullptr;
+ wson_buffer_free(buffer);
+ return event;
+}
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif
\ No newline at end of file
diff --git a/weex_core/Source/core/data_render/vnode/android/conversion.h b/weex_core/Source/core/data_render/vnode/android/conversion.h
new file mode 100644
index 0000000000..e3f91200c9
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/android/conversion.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.
+ */
+#ifdef OS_ANDROID
+
+#ifndef CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_
+#define CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include "include/WeexApiHeader.h"
+#include "third_party/json11/json11.hpp"
+
+namespace weex {
+namespace core {
+namespace data_render {
+class Value;
+class Conversion {
+ public:
+ static json11::Json GenJSON(const Value* v);
+ static VALUE_WITH_TYPE* GenValueWithType(const char* event_str);
+};
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif // CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_
+#endif
diff --git a/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc b/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc
new file mode 100644
index 0000000000..cc707fb4b1
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc
@@ -0,0 +1,265 @@
+/**
+ * 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.
+ */
+#ifdef OS_ANDROID
+
+#include "core/data_render/vnode/vcomponent_lifecycle_listener.h"
+#include "android/utils/params_utils.h"
+#include "core/data_render/exec_state.h"
+#include "core/data_render/vnode/android/conversion.h"
+#include "core/manager/weex_core_manager.h"
+#include "wson/wson.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+static const char* kMethodOnComponentEvent = "callJS";
+static const char* kComponentHook = "componentHook";
+static const char* kLifecycle = "lifecycle";
+static const char* kKeyMethod = "method";
+static const char* kKeyArgs = "args";
+static const char* kEventOnCreated = "created";
+static const char* kEventOnUpdated = "updated";
+static const char* kEventOnDestroyed = "destroyed";
+static int kNonParentId = -1;
+
+void GenWSONValue(wson_buffer* buffer, Value* value);
+void GenWSONValue(wson_buffer* buffer, Table* t);
+void GenWSONValue(wson_buffer* buffer, int32_t i);
+void GenWSONArray(wson_buffer* buffer, Array* array);
+void GenWSONTable(wson_buffer* buffer, Table* table);
+
+void GenWSONValue(wson_buffer* buffer, const std::string& str);
+template <typename Type>
+void GenWSONValue(wson_buffer* buffer, const std::vector<Type>& vector);
+template <typename Type>
+void GenWSONValue(wson_buffer* buffer,
+ const std::unordered_map<std::string, Type>& ref_map);
+
+void GenWSONValue(wson_buffer* buffer, Value* value) {
+ switch (value->type) {
+ case Value::Type::ARRAY:
+ return GenWSONArray(buffer, ValueTo<Array>(value));
+ case Value::Type::TABLE:
+ return GenWSONTable(buffer, ValueTo<Table>(value));
+ case Value::Type::INT:
+ wson_push_type_long(buffer, value->i);
+ break;
+ case Value::Type::NUMBER:
+ wson_push_type_double(buffer, value->n);
+ break;
+ case Value::Type::STRING:
+ wson_push_type_uint8_string(
+ buffer, reinterpret_cast<const uint8_t*>(value->str->c_str()),
+ strlen(value->str->c_str()));
+ break;
+ case Value::Type::BOOL:
+ wson_push_type_boolean(buffer, value->b);
+ break;
+ default:
+ wson_push_type_null(buffer);
+ break;
+ }
+}
+
+void GenWSONArray(wson_buffer* buffer, Array* array) {
+ wson_push_type_array(buffer, array->items.size());
+ for (auto it = array->items.begin(); it != array->items.end(); it++) {
+ GenWSONValue(buffer, &*it);
+ }
+}
+
+void GenWSONTable(wson_buffer* buffer, Table* table) {
+ wson_push_type_map(buffer, table->map.size());
+ for (auto it = table->map.begin(); it != table->map.end(); it++) {
+ if (it->first.empty()) continue;
+ // Use utf16 as wson only support utf16 as key in map
+ auto utf16_key = weex::base::to_utf16(const_cast<char*>(it->first.c_str()),
+ it->first.size());
+ wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t));
+ wson_push_bytes(buffer, utf16_key.c_str(),
+ utf16_key.size() * sizeof(uint16_t));
+ GenWSONValue(buffer, &it->second);
+ }
+}
+
+void GenWSONValue(wson_buffer* buffer, Table* t) { GenWSONTable(buffer, t); }
+
+void GenWSONValue(wson_buffer* buffer, int32_t i) {
+ wson_push_type_int(buffer, i);
+}
+
+void GenWSONValue(wson_buffer* buffer, const std::string& str) {
+ wson_push_type_uint8_string(
+ buffer, reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
+}
+
+template <typename Type>
+void GenWSONValue(wson_buffer* buffer, const std::vector<Type>& vector) {
+ wson_push_type_array(buffer, vector.size());
+ for (auto it = vector.begin(); it != vector.end(); it++) {
+ GenWSONValue(buffer, *it);
+ }
+}
+
+template <typename Type>
+void GenWSONValue(wson_buffer* buffer,
+ const std::unordered_map<std::string, Type>& ref_map) {
+ wson_push_type_map(buffer, ref_map.size());
+ for (auto it = ref_map.begin(); it != ref_map.end(); it++) {
+ if (it->first.empty()) continue;
+ // Use utf16 as wson only support utf16 as key in map
+ auto utf16_key = weex::base::to_utf16(const_cast<char*>(it->first.c_str()),
+ it->first.size());
+ wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t));
+ wson_push_bytes(buffer, utf16_key.c_str(),
+ utf16_key.size() * sizeof(uint16_t));
+ GenWSONValue(buffer, it->second);
+ }
+}
+
+static void UnpackAndGenWSONValue(wson_buffer* buffer) {}
+
+template <typename T>
+static void UnpackAndGenWSONValue(wson_buffer* buffer, T arg) {
+ GenWSONValue(buffer, std::forward<T>(arg));
+}
+
+template <typename T, typename... Args>
+static void UnpackAndGenWSONValue(wson_buffer* buffer, T arg, Args... args) {
+ GenWSONValue(buffer, std::forward<T>(arg));
+ UnpackAndGenWSONValue(buffer, args...);
+}
+
+template <typename... Args>
+static void GenParamsForCallJS(std::vector<VALUE_WITH_TYPE*>& params,
+ VComponent* component, const char* event,
+ int32_t id, size_t argc_inside,
+ Args... args_inside) {
+ auto page_id = component->exec_state()->context()->page_id();
+ // page_id
+ params.push_back(Conversion::GenValueWithType(page_id.c_str()));
+
+ // args -> { method: 'componentHook', args: [ id, 'lifecycle',
+ // event, [args_inside ] }
+ VALUE_WITH_TYPE* args = getValueWithTypePtr();
+ args->type = ParamsType::BYTEARRAY;
+ auto buffer = wson_buffer_new();
+ wson_push_type_array(buffer, 1);
+ wson_push_type_map(buffer, 2);
+ // key -> method
+ auto utf16_key_method =
+ weex::base::to_utf16(const_cast<char*>(kKeyMethod), strlen(kKeyMethod));
+ wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t));
+ wson_push_bytes(buffer, utf16_key_method.c_str(),
+ utf16_key_method.size() * sizeof(uint16_t));
+ // value -> 'componentHook'
+ wson_push_type_uint8_string(buffer,
+ reinterpret_cast<const uint8_t*>(kComponentHook),
+ strlen(kComponentHook));
+ // key -> args
+ auto utf16_key_args =
+ weex::base::to_utf16(const_cast<char*>(kKeyArgs), strlen(kKeyArgs));
+ wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t));
+ wson_push_bytes(buffer, utf16_key_args.c_str(),
+ utf16_key_args.size() * sizeof(uint16_t));
+ // value -> [ id, 'lifecycle', event, [ args_inside ] ]
+ {
+ wson_push_type_array(buffer, 4);
+ // templateId
+ wson_push_type_int(buffer, id);
+ // 'lifecycle'
+ wson_push_type_uint8_string(buffer,
+ reinterpret_cast<const uint8_t*>(kLifecycle),
+ strlen(kLifecycle));
+ // lifecycle
+ wson_push_type_uint8_string(buffer, reinterpret_cast<const uint8_t*>(event),
+ strlen(event));
+ // array -> [ args_inside ]
+ {
+ wson_push_type_array(buffer, argc_inside);
+ for (int i = 0; i < argc_inside; i++) {
+ UnpackAndGenWSONValue(buffer, args_inside...);
+ }
+ }
+ }
+
+ args->value.byteArray = genWeexByteArray(
+ static_cast<const char*>(buffer->data), buffer->position);
+ buffer->data = nullptr;
+ wson_buffer_free(buffer);
+ params.push_back(args);
+}
+
+void VComponentLifecycleListener::OnCreated(
+ VComponent* component, Table* data, Table* props,
+ const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map) {
+ std::vector<VALUE_WITH_TYPE*> params;
+ // parentId
+ int parentId = kNonParentId;
+ if (component->parent() != NULL) {
+ parentId = component->parent()->component()->id();
+ }
+ // [pageId, args]
+ //
+ // args -> { method: 'componentHook', args: [ templateId, 'lifecycle',
+ // lifecycle, [componentId, parentId, data, props, refList] ] }
+ GenParamsForCallJS(params, component, kEventOnCreated,
+ component->template_id(), 5, component->id(), parentId,
+ data, props, ref_map);
+ auto page_id = component->exec_state()->context()->page_id();
+ WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
+ page_id.c_str(), "", kMethodOnComponentEvent, params);
+ freeParams(params);
+}
+
+void VComponentLifecycleListener::OnUpdated(
+ VComponent* component, Table* props,
+ const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map) {
+ auto page_id = component->exec_state()->context()->page_id();
+
+ std::vector<VALUE_WITH_TYPE*> params;
+ // [pageId, args]
+ //
+ // args -> { method: 'componentHook', args: [ componentId, 'lifecycle',
+ // lifecycle, [props, refList] ] }
+ GenParamsForCallJS(params, component, kEventOnUpdated, component->id(), 2,
+ props, ref_map);
+ WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
+ page_id.c_str(), "", kMethodOnComponentEvent, params);
+ freeParams(params);
+}
+
+void VComponentLifecycleListener::OnDestroyed(VComponent* component) {
+ auto page_id = component->exec_state()->context()->page_id();
+ std::vector<VALUE_WITH_TYPE*> params;
+ // [pageId, args]
+ //
+ // args -> { method: 'componentHook', args: [ componentId, 'lifecycle',
+ // lifecycle, [] ] }
+ GenParamsForCallJS(params, component, kEventOnDestroyed, component->id(), 0);
+ WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
+ page_id.c_str(), "", kMethodOnComponentEvent, params);
+ freeParams(params);
+}
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif
\ No newline at end of file
diff --git a/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc b/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc
new file mode 100644
index 0000000000..a8229da738
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+#ifdef OS_ANDROID
+
+#include "core/data_render/vnode/vnode_on_event_listener.h"
+#include "android/utils/params_utils.h"
+#include "core/data_render/exec_state.h"
+#include "core/data_render/vnode/android/conversion.h"
+#include "core/data_render/vnode/vcomponent.h"
+#include "core/manager/weex_core_manager.h"
+#include "include/WeexApiHeader.h"
+#include "third_party/json11/json11.hpp"
+
+namespace weex {
+namespace core {
+namespace data_render {
+static const char* kMethodCallJS = "callJS";
+static const char* kMethodFireEvent = "fireEvent";
+static const char* kKeyMethod = "method";
+static const char* kKeyArgs = "args";
+static const char* kKeyParams = "params";
+
+void VNodeOnEventListener::OnEvent(VNode* node, const std::string& event,
+ const std::string& json_args,
+ const std::string dom_changes,
+ const VNode::Params& param_list) {
+ auto page_id = node->component()->exec_state()->context()->page_id();
+ std::vector<VALUE_WITH_TYPE*> params;
+ // page_id
+ params.push_back(Conversion::GenValueWithType(page_id.c_str()));
+
+ // args -> { method: 'fireEvent', args: [ref, "nodeEvent", args , domChanges, {params: [ {"templateId": templateId, "componentId": id, "type": type, "params" : [...]} ]}] }
+ VALUE_WITH_TYPE* args = getValueWithTypePtr();
+ args->type = ParamsType::JSONSTRING;
+ std::vector<json11::Json> args_object_list;
+ std::map<std::string, json11::Json> args_object;
+ // method: 'FireEvent'
+ args_object.insert({kKeyMethod, kMethodFireEvent});
+
+ std::vector<json11::Json> args_in_args_object;
+ // ref TODO make sure the difference between node id and ref
+ if (!node->ref().empty()) {
+ args_in_args_object.push_back(node->ref());
+ } else {
+ args_in_args_object.push_back(node->node_id());
+ }
+ // type -> "nodeEvent"
+ args_in_args_object.push_back("nodeEvent");
+ // args
+ std::string error;
+ args_in_args_object.push_back(json11::Json::parse(json_args, error));
+ // domChanges
+ args_in_args_object.push_back(json11::Json::parse(dom_changes, error));
+ // params -> [ {"templateId": templateId, "componentId": id, "type": type, "params" : [...]} ]
+ std::map<std::string, json11::Json> params_object;
+ std::vector<json11::Json> array_in_params_object;
+ {
+ std::map<std::string, json11::Json> inner_object;
+ // templateId
+ inner_object.insert({"templateId", node->component()->template_id()});
+ // componentId
+ inner_object.insert({"componentId", node->component()->id()});
+ // type
+ inner_object.insert({"type", event});
+ // params
+ std::vector<json11::Json> array_in_inner_object;
+ for (auto it = param_list.begin(); it != param_list.end(); it++) {
+ array_in_inner_object.push_back(Conversion::GenJSON(&*it));
+ }
+ inner_object.insert({kKeyParams, array_in_inner_object});
+ array_in_params_object.push_back(inner_object);
+ }
+ params_object.insert({kKeyParams, array_in_params_object});
+ args_in_args_object.push_back(params_object);
+ args_object.insert({kKeyArgs, args_in_args_object});
+ args_object_list.push_back(args_object);
+
+ json11::Json final_json(args_object_list);
+ auto temp = final_json.dump();
+ auto final_json_str = temp.c_str();
+ auto utf16_key = weex::base::to_utf16(const_cast<char*>(final_json_str),
+ strlen(final_json_str));
+ args->value.string = genWeexString(
+ reinterpret_cast<const uint16_t*>(utf16_key.c_str()), utf16_key.size());
+ params.push_back(args);
+
+ WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
+ page_id.c_str(), "", kMethodCallJS, params);
+ freeParams(params);
+}
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif
\ No newline at end of file
diff --git a/weex_core/Source/core/data_render/vnode/ios/vcomponent_lifecycle_listener.mm b/weex_core/Source/core/data_render/vnode/ios/vcomponent_lifecycle_listener.mm
new file mode 100644
index 0000000000..d47303f1d4
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/ios/vcomponent_lifecycle_listener.mm
@@ -0,0 +1,77 @@
+/**
+ * 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/vnode/vcomponent_lifecycle_listener.h"
+#include "core/manager/weex_core_manager.h"
+#include "core/data_render/vnode/vnode_render_manager.h"
+#import "WXSDKManager.h"
+#import "WXConvertUtility.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+void VComponentLifecycleListener::OnCreated(
+ VComponent* component, Table* data, Table* props,
+ const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map) {
+ std::string page_id = component->exec_state()->context()->page_id();
+ NSString *instanceId = NSSTRING(page_id.c_str());
+ WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+ if (!instance) {
+ return;
+ }
+
+ int template_id = component->template_id();
+ int component_id = component->id();
+ int parent_id = -1;
+ if (component->parent()) {
+ parent_id = component->parent()->component()->id();
+ }
+
+ [[WXSDKManager bridgeMgr] callJSMethod:@"callJS" args:@[instanceId, @[@{@"method":@"componentHook", @"args":@[[NSNumber numberWithInt:template_id], @"lifecycle", @"created", @[[NSNumber numberWithInt:component_id],[NSNumber numberWithInt:parent_id], NSDICTIONARY(data), NSDICTIONARY(props), NSDICTIONARY(ref_map)]]}]]];
+}
+
+void VComponentLifecycleListener::OnUpdated(
+ VComponent* component, Table* props, const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map) {
+ std::string page_id = component->exec_state()->context()->page_id();
+ NSString *instanceId = NSSTRING(page_id.c_str());
+ WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+ if (!instance) {
+ return;
+ }
+
+ int component_id = component->id();
+ [[WXSDKManager bridgeMgr] callJSMethod:@"callJS" args:@[instanceId, @[@{@"method":@"componentHook", @"args":@[[NSNumber numberWithInt:component_id], @"lifecycle", @"updated", @[NSDICTIONARY(props), NSDICTIONARY(ref_map)]]}]]];
+}
+
+void VComponentLifecycleListener::OnDestroyed(VComponent* component) {
+ std::string page_id = component->exec_state()->context()->page_id();
+ NSString *instanceId = NSSTRING(page_id.c_str());
+ WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+ if (!instance) {
+ return;
+ }
+
+ int component_id = component->id();
+ [[WXSDKManager bridgeMgr] callJSMethod:@"callJS" args:@[instanceId, @[@{@"method":@"componentHook", @"args":@[[NSNumber numberWithInt:component_id], @"lifecycle", @"destroyed", @[]]}]]];
+}
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/ios/vnode_on_event_listener.mm b/weex_core/Source/core/data_render/vnode/ios/vnode_on_event_listener.mm
new file mode 100644
index 0000000000..7a7fcb7f30
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/ios/vnode_on_event_listener.mm
@@ -0,0 +1,49 @@
+/**
+ * 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/vnode/vnode_on_event_listener.h"
+#include "core/data_render/vnode/vcomponent.h"
+#include "core/data_render/vnode/vnode_render_manager.h"
+#import "WXSDKManager.h"
+#import "WXConvertUtility.h"
+#import "WXUtility.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+void VNodeOnEventListener::OnEvent(VNode *node, const std::string &event,
+ const std::string &json_args, const std::string dom_changes,
+ const VNode::Params ¶ms)
+ {
+ std::string page_id = node->component()->exec_state()->context()->page_id();
+ NSString *instanceId = NSSTRING(page_id.c_str());
+ WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+ if (!instance) {
+ return;
+ }
+ int template_id = node->component()->template_id();
+ int component_id = node->component()->id();
+
+ [[WXSDKManager bridgeMgr] callJSMethod:@"callJS" args:@[instanceId, @[@{@"method":@"fireEvent", @"args":@[NSSTRING(node->ref().empty() ? node->node_id().c_str() : node->ref().c_str()), @"nodeEvent", [WXUtility objectFromJSON:NSSTRING(json_args.c_str())], NSSTRING(dom_changes.c_str()), @{@"params":@[@{@"templateId":[NSNumber numberWithInt:template_id], @"componentId":[NSNumber numberWithInt:component_id],@"type":NSSTRING(event.c_str()), @"params": NSARRAY(params)}]}]}]]];
+ }
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.cc b/weex_core/Source/core/data_render/vnode/vcomponent.cc
index f885cc78c4..c4243dc059 100644
--- a/weex_core/Source/core/data_render/vnode/vcomponent.cc
+++ b/weex_core/Source/core/data_render/vnode/vcomponent.cc
@@ -19,6 +19,8 @@
#include "core/data_render/vnode/vcomponent.h"
#include "core/data_render/exec_state.h"
+#include "vnode_render_manager.h"
+
namespace weex {
namespace core {
namespace data_render {
@@ -27,21 +29,21 @@ namespace data_render {
static int g_component_id = 0;
VComponent::VComponent(ExecState *exec_state, int template_id,
- 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),
+ const std::string &name, const std::string &func_name)
+ : VNode("", "", ""),
+ is_dirty_(false),
+ has_dispatch_created_(false),
+ has_moved_(false),
id_(g_component_id++),
template_id_(template_id),
name_(name),
- // This function name definition rule is in parser.cc
- func_name_("createComponent_" + name),
- data_(nullptr),
- props_(nullptr),
+ func_name_(func_name),
+ data_(exec_state->class_factory()->CreateTable()),
+ props_(exec_state->class_factory()->CreateTable()),
listener_(nullptr),
- dirty_(false),
- children_(),
- parent_(nullptr) {}
+ old_root_vnode_(nullptr),
+ root_vnode_(nullptr),
+ exec_state_(exec_state) {}
VComponent::~VComponent() {}
@@ -85,56 +87,199 @@ static bool Equals(Value a, Value b) {
return true;
}
-void VComponent::Compare(VComponent *old_component) {
+static void BuildRefsInner(
+ std::unordered_map<std::string, VComponent::VNodeRefs> &ref_map,
+ VNode *node, bool in_for_loop) {
+ if (node->attributes()->find("[[repeat]]") != node->attributes()->end()) {
+ in_for_loop = true;
+ }
+ if (!node->ref().empty()) {
+ VComponent::VNodeRef ref;
+ ref.insert({"ref", node->render_object_ref()});
+ auto it = ref_map.find(node->ref());
+ if (it != ref_map.end()) {
+ if (!in_for_loop) {
+ return;
+ }
+ it->second.push_back(ref);
+ } else {
+ VComponent::VNodeRefs refs;
+ refs.push_back(ref);
+ ref_map.insert({node->ref(), refs});
+ }
+ }
+ // Record { ref : node } in context
+ node->component()->exec_state()->context()->AddVNode(node->render_object_ref(), node);
+ if (node->child_list()->size() > 0 && !node->IsVirtualComponent()) {
+ for (auto it = node->child_list()->begin(); it != node->child_list()->end();
+ it++) {
+ BuildRefsInner(ref_map, *it, in_for_loop);
+ }
+ }
+}
+
+static void DetachVNodesInContext(VNode *node) {
+ // Remove { ref : node } in context
+ if (!node || node->IsVirtualComponent()) return;;
+ auto context = node->component()->exec_state()->context();
+ auto record = context->GetVNode(node->render_object_ref());
+ if (record != node) {
+ context->RemoveVNode(node->render_object_ref());
+ }
+ if (node->child_list()->size() > 0 && !node->IsVirtualComponent()) {
+ for (auto it = node->child_list()->begin(); it != node->child_list()->end();
+ it++) {
+ DetachVNodesInContext(*it);
+ }
+ }
+}
+
+void VComponent::BuildRefMap() {
+ ref_map_.clear();
+ BuildRefsInner(ref_map_, root_vnode(), false);
+}
+
+bool VComponent::Equal(VComponent *old_component) {
VComponent *new_component = this;
- if (old_component == new_component) return;
+ if (old_component == new_component) return true;
// Mainly compare props
- for (auto it = old_component->props_->map.begin();
- it != old_component->props_->map.end(); ++it) {
+ Table *old_table = ValueTo<Table>(&old_component->props_);
+ Table *new_table = ValueTo<Table>(&new_component->props_);
+ if (updated_props_.type == Value::Type::NIL) {
+ updated_props_ = exec_state_->class_factory()->CreateTable();
+ } else {
+ ValueTo<Table>(&updated_props_)->map.clear();
+ }
+ bool equal = true;
+ for (auto it = old_table->map.begin(); it != old_table->map.end(); ++it) {
auto old_value = it->second;
- auto new_value = new_component->props_->map[it->first];
+ auto new_value = new_table->map[it->first];
if (old_value.type != new_value.type || !Equals(old_value, new_value)) {
- updated_props_[it->first] = new_value;
- dirty_ = true;
+ ValueTo<Table>(&updated_props_)->map.insert({it->first, new_value});
+ equal = false;
}
}
+ return equal;
+}
+
+void VComponent::MoveTo(VComponent *new_component) {
+ new_component->has_dispatch_created_ = has_dispatch_created_;
+ new_component->id_ = id_;
+ new_component->SetRootNode(root_vnode_.release());
+ new_component->data_ = data_;
+ if (!new_component->Equal(this)) {
+ new_component->UpdateData();
+ }
+ exec_state_->context()->RemoveComponent(id_);
+ exec_state_->context()->AddComponent(new_component->id(), new_component);
+ has_moved_ = true;
}
-void VComponent::UpdateData(std::unordered_map<std::string, Value> datas) {
+void VComponent::UpdateData() {
+ // Merge data and props
Value new_value = exec_state_->class_factory()->CreateTable();
- TableMapAddAll(props_, ValueTo<Table>(&new_value));
- TableMapAddAll(data_, ValueTo<Table>(&new_value));
- //Value new_component = exec_state_->Call(func_name_, {new_value}).cptr;
+ TableAddAll(props_, new_value);
+ TableAddAll(data_, new_value);
+
+ Value component;
+ component.cptr = this;
+ component.type = Value::CPTR;
+ exec_state_->Call(func_name_, {new_value, component, Value(false)});
+ VNodeRenderManager::GetInstance()->PatchVNode(
+ exec_state_, old_root_vnode_.get(), root_vnode_.get());
+
+ TravelVComponentsWithFunc(&VComponent::DispatchDestroyed,
+ old_root_vnode_.get());
+ old_root_vnode_.reset(nullptr);
+ if (has_dispatch_created_) {
+ is_dirty_ = true;
+ DispatchUpdated();
+ }
+}
+
+void VComponent::UpdateData(Value *data) {
+ if (data->type == Value::Type::TABLE && TableAddAll(*data, data_)) {
+ UpdateData();
+ }
+}
+
+// TODO Depth-first traversal
+void VComponent::TravelVComponentsWithFunc(TravelTreeFunc func, VNode *root) {
+ if (!root) return;
+ std::vector<VNode *> list;
+ list.push_back(root);
+ VNode *node = nullptr;
+ while (!list.empty()) {
+ node = list.front();
+ list.erase(list.begin());
+ if (node->IsVirtualComponent()) {
+ (static_cast<VComponent *>(node)->*func)();
+ continue;
+ }
+ for (auto it = node->child_list()->begin(); it != node->child_list()->end();
+ it++) {
+ list.push_back(*it);
+ }
+ }
}
void VComponent::DispatchCreated() {
- for (auto it = children_.begin(); it != children_.end(); ++it) {
- (*it)->DispatchCreated();
+ if (has_dispatch_created_) return;
+ BuildRefMap();
+ if (listener_) {
+ listener_->OnCreated(this, ValueTo<Table>(&data_), ValueTo<Table>(&props_),
+ ref_map_);
}
+ TravelVComponentsWithFunc(&VComponent::DispatchCreated, root_vnode());
+ has_dispatch_created_ = true;
}
void VComponent::DispatchUpdated() {
- if (dirty_) {
- for (auto it = children_.begin(); it != children_.end(); ++it) {
- if ((*it)->dirty_) {
- (*it)->DispatchUpdated();
- }
+ if (!has_dispatch_created_) {
+ DispatchCreated();
+ return;
+ }
+ if (!is_dirty_) return;
+ BuildRefMap();
+ if (listener_) {
+ if (updated_props_.type == Value::Type::NIL) {
+ updated_props_ = exec_state_->class_factory()->CreateTable();
}
- dirty_ = false;
+ listener_->OnUpdated(this, ValueTo<Table>(&updated_props_), ref_map_);
}
+ TravelVComponentsWithFunc(&VComponent::DispatchUpdated, root_vnode());
+ is_dirty_ = false;
}
void VComponent::DispatchDestroyed() {
- for (auto it = children_.begin(); it != children_.end(); ++it) {
- (*it)->DispatchDestroyed();
+ if (listener_ && !has_moved_) {
+ listener_->OnDestroyed(this);
}
+ TravelVComponentsWithFunc(&VComponent::DispatchDestroyed, root_vnode());
+ if (!has_moved_) {
+ exec_state_->context()->RemoveComponent(id_);
+ }
+ DetachVNodesInContext(root_vnode());
}
-void VComponent::AppendChildComponent(VComponent *child) {
- children_.push_back(child);
- child->parent_ = this;
+void VComponent::SetRootNode(VNode *node) {
+ if (root_vnode_) {
+ old_root_vnode_ = std::move(root_vnode_);
+ }
+ root_vnode_.reset(node);
+ if (root_vnode_) {
+ root_vnode_->set_component(this);
+ }
}
+void VComponent::SetData(Value *data) { TableCopy(*data, data_); }
+
+void VComponent::SetProps(Value *props) { TableCopy(*props, props_); }
+
+void VComponent::DispatchAttachedToParent() {}
+
+void VComponent::DispatchDetachedFromParent() { DispatchDestroyed(); }
+
} // namespace data_render
} // namespace core
} // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.h b/weex_core/Source/core/data_render/vnode/vcomponent.h
index 884148c26f..927a3a4ca2 100644
--- a/weex_core/Source/core/data_render/vnode/vcomponent.h
+++ b/weex_core/Source/core/data_render/vnode/vcomponent.h
@@ -26,55 +26,84 @@
namespace weex {
namespace core {
namespace data_render {
-// VComponent is a VNode
class VComponent : public VNode {
public:
+ typedef std::unordered_map<std::string, std::string> VNodeRef;
+ typedef std::vector<VNodeRef> VNodeRefs;
class LifecycleListener {
- virtual void OnCreated(VComponent* component,
- std::unordered_map<std::string, Value> datas,
- std::unordered_map<std::string, Value> props) = 0;
- virtual void OnUpdated(VComponent* component,
- std::unordered_map<std::string, Value> props) = 0;
+ public:
+ virtual ~LifecycleListener() {}
+ virtual void OnCreated(
+ VComponent* component, Table* data, Table* props,
+ const std::unordered_map<std::string, VNodeRefs>& ref_map) = 0;
+ virtual void OnUpdated(
+ VComponent* component, Table* props,
+ const std::unordered_map<std::string, VNodeRefs>& ref_map) = 0;
virtual void OnDestroyed(VComponent* component) = 0;
};
VComponent(ExecState* exec_state, int template_id, const std::string& name,
- const std::string& tag_name, const std::string& node_id,
- const std::string& ref);
+ const std::string& func_name);
~VComponent();
- void UpdateData(std::unordered_map<std::string, Value> datas);
- void DispatchCreated();
- void DispatchUpdated();
- void DispatchDestroyed();
- void Compare(VComponent* component);
-
- void AppendChildComponent(VComponent* child);
+ void UpdateData();
+ void UpdateData(Value* datas);
+ inline bool IsSameNode(VComponent* old_component) {
+ return template_id_ == old_component->template_id_;
+ }
+ void MoveTo(VComponent* new_component);
- inline void set_lifecycle_listener(LifecycleListener* listener) {
- listener_ = listener;
+ inline const std::string render_object_ref() const override {
+ if (root_vnode_.get()) {
+ return root_vnode_->render_object_ref();
+ }
+ return "";
}
inline int id() { return id_; }
inline int template_id() { return template_id_; }
- VComponent* parent() { return parent_; }
- inline void set_data(Table* data) { data_ = data; }
- inline void set_props(Table* props) { props = props_; }
+ inline ExecState* exec_state() { return exec_state_; }
+ void SetData(Value* data);
+ void SetProps(Value* props);
+ inline VNode* root_vnode() { return root_vnode_.get(); }
+ void SetRootNode(VNode* node);
+ bool IsVirtualComponent() const override { return true; }
+
+ void DispatchCreated();
+ void DispatchUpdated();
+ void DispatchDestroyed();
+
+ inline void set_life_cycle_listener(
+ std::unique_ptr<LifecycleListener> listener) {
+ listener_ = std::move(listener);
+ }
private:
+ typedef void (VComponent::*TravelTreeFunc)();
+ void TravelVComponentsWithFunc(TravelTreeFunc func, VNode* root);
+
+ void BuildRefMap();
+ bool Equal(VComponent* old_component);
+ void DispatchAttachedToParent() override;
+ void DispatchDetachedFromParent() override;
+
+ bool is_dirty_;
+ bool has_dispatch_created_;
+ bool has_moved_;
+ // unique id for unique component
int id_;
+ // Unique id for unique template, a template to multiple component
int template_id_;
+ // Unique template name
std::string name_;
- // For invoke function in vm to create component
+ // For invoke function in vm to create nodes in component
std::string func_name_;
// Save data and props for diff and update
- Table* data_;
- Table* props_;
- std::unordered_map<std::string, Value> updated_props_;
- // Ptr should handle by outside
- LifecycleListener* listener_;
- // Mark if this component is a new one after diff & patch
- bool dirty_;
- std::vector<VComponent*> children_;
- VComponent* parent_;
+ Value data_;
+ Value props_;
+ Value updated_props_;
+ std::unique_ptr<LifecycleListener> listener_;
+ std::unordered_map<std::string, VNodeRefs> ref_map_;
+ std::unique_ptr<VNode> old_root_vnode_;
+ std::unique_ptr<VNode> root_vnode_;
ExecState* exec_state_;
};
} // namespace data_render
diff --git a/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h
new file mode 100644
index 0000000000..3cd6c71eea
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h
@@ -0,0 +1,41 @@
+/**
+ * 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_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_
+#define CORE_DATA_RENDER_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_
+
+#include "core/data_render/vnode/vcomponent.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+class VComponentLifecycleListener : public VComponent::LifecycleListener {
+ void OnCreated(
+ VComponent* component, Table* data, Table* props,
+ const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map);
+ void OnUpdated(
+ VComponent* component, Table* props,
+ const std::unordered_map<std::string, VComponent::VNodeRefs>& ref_map);
+ void OnDestroyed(VComponent* component);
+};
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif // CORE_DATA_RENDER_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_
diff --git a/weex_core/Source/core/data_render/vnode/vnode.cc b/weex_core/Source/core/data_render/vnode/vnode.cc
index d34cfc7c83..219ca1cb75 100644
--- a/weex_core/Source/core/data_render/vnode/vnode.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode.cc
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+#include "core/data_render/object.h"
#include "core/render/node/factory/render_creator.h"
#include "core/data_render/vnode/vnode.h"
@@ -24,7 +25,7 @@ namespace core {
namespace data_render {
VNode::VNode(const std::string &tag_name, const std::string &node_id,
- const std::string &ref) {
+ const std::string &ref) {
ref_ = ref;
tag_name_ = tag_name;
node_id_ = node_id;
@@ -32,6 +33,8 @@ VNode::VNode(const std::string &tag_name, const std::string &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 *>();
+ event_params_map_.reset(new EventParamsMap);
+ on_event_listener_.reset();
}
VNode::~VNode() {
@@ -50,12 +53,24 @@ VNode::~VNode() {
delete events_;
events_ = nullptr;
}
- for (auto it = child_list_.begin(); it != child_list_.end(); it++) {
- VNode *&reference = *it;
- if (reference != nullptr) {
- delete reference;
- *it = nullptr;
- }
+// for (auto it = child_list_.begin(); it != child_list_.end(); it++) {
+// VNode *&reference = *it;
+// if (reference != nullptr) {
+// delete reference;
+// *it = nullptr;
+// }
+// }
+}
+
+void VNode::OnEvent(const std::string &event, const std::string args,
+ const std::string dom_changes) {
+ if (!on_event_listener_) return;
+
+ auto it = event_params_map_->find(event);
+ if (it == event_params_map_->end()) return;
+ auto params_list = it->second;
+ for (auto it = params_list.begin(); it != params_list.end(); it++) {
+ on_event_listener_->OnEvent(this, event, args, dom_changes, *it);
}
}
@@ -97,26 +112,32 @@ VNode *VNode::FindNode(const std::string &render_object_ref) {
return node;
}
-void VNode::AddEvent(const std::string &event, const std::string &function,
- const std::vector<std::string> ¶ms) {
- //todo
+void VNode::AddEvent(const std::string &event,
+ const std::vector<Value> ¶ms) {
+ auto it = event_params_map_->find(event);
+ if (it != event_params_map_->end()) {
+ it->second.push_back(params);
+ } else {
+ event_params_map_->insert({event, {params}});
+ }
}
-
+
void VNode::AddChild(VNode *child) {
child->parent_ = this;
+ child->component_ = component_;
child_list_.push_back(child);
+ child->DispatchAttachedToParent();
}
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);
+ if (!child) return;
+ child->parent_ = this;
+ if (index < child_list_.size()) {
+ child_list_.insert(child_list_.begin() + index, child);
+ } else {
+ child_list_.push_back(child);
+ }
+ child->DispatchAttachedToParent();
}
void VNode::RemoveChild(VNode *child) {
@@ -124,6 +145,7 @@ void VNode::RemoveChild(VNode *child) {
auto it = child_list_.begin();
for (; it != child_list_.end(); ++it) {
if (*it == child) {
+ child->DispatchDetachedFromParent();
VNode *&reference = *it;
child_list_.erase(it);
if (reference != nullptr) {
diff --git a/weex_core/Source/core/data_render/vnode/vnode.h b/weex_core/Source/core/data_render/vnode/vnode.h
index bcc09e3a19..8cda5e5015 100644
--- a/weex_core/Source/core/data_render/vnode/vnode.h
+++ b/weex_core/Source/core/data_render/vnode/vnode.h
@@ -22,15 +22,32 @@
#include <map>
#include <string>
#include <vector>
+#include <unordered_set>
+#include <unordered_map>
+#include <memory>
#include "core/render/node/render_object.h"
namespace weex {
namespace core {
namespace data_render {
-class VNode;
+class VComponent;
+class Value;
class VNode {
public:
+ typedef std::vector<Value> Params;
+ typedef std::vector<Params> ParamsList;
+ typedef std::unordered_map<std::string, ParamsList> EventParamsMap;
+
+ class OnEventListener {
+ public:
+ virtual ~OnEventListener() {}
+ virtual void OnEvent(VNode *node, const std::string &event,
+ const std::string &json_args,
+ const std::string dom_changes,
+ const Params ¶ms) = 0;
+ };
+
VNode(const std::string &tag_name, const std::string &node_id,
const std::string &ref);
@@ -40,10 +57,12 @@ class VNode {
void SetAttribute(const std::string &key, const std::string &value);
- void AddEvent(const std::string &event, const std::string &function,
- const std::vector<std::string> ¶ms);
+ void AddEvent(const std::string &event,
+ const std::vector<Value> ¶ms);
void AddEvent(const std::string &event, void *func, void *inst);
+ void AddOnEventListener();
+
void AddChild(VNode *child);
void RemoveChild(VNode *child);
@@ -59,7 +78,7 @@ class VNode {
inline const std::string &ref() const { return ref_; }
- inline const std::string &render_object_ref() const {
+ virtual inline const std::string render_object_ref() const {
return render_object_ref_;
}
@@ -67,7 +86,7 @@ class VNode {
render_object_ref_ = std::move(ref);
}
inline void *& inst() { return inst_; }
- inline const VNode *parent() const { return parent_; }
+ inline VNode *parent() const { return parent_; }
inline std::vector<VNode *> *child_list() { return &child_list_; }
@@ -80,14 +99,37 @@ class VNode {
return events_;
}
+ inline EventParamsMap *event_params_map() const {
+ return event_params_map_.get();
+ }
+
+ void OnEvent(const std::string &event, const std::string args,
+ const std::string dom_changes);
+
+ inline void set_on_event_listener(std::unique_ptr<OnEventListener> listener) {
+ on_event_listener_ = std::move(listener);
+ }
+
inline bool HasChildren() { return !child_list_.empty(); }
+ inline void set_component(VComponent* c) {
+ component_ = c;
+ }
+
+ inline VComponent* component() {
+ return component_;
+ }
+
+ virtual bool IsVirtualComponent() const { return false; }
+
private:
std::string tag_name_;
// Not unique
std::string node_id_;
// Should be unique
std::string ref_;
+ // Context of vnode
+ VComponent* component_ = nullptr;
// Ref point to RenderObject is set when PatchVNode or ParseVNode2RenderObject
std::string render_object_ref_;
@@ -96,9 +138,16 @@ class VNode {
std::vector<VNode *> child_list_;
std::map<std::string, std::string> *styles_;
std::map<std::string, std::string> *attributes_;
+ // This events if record event with func from vm
std::map<std::string, void *> *events_;
+ // This events if record event with value from vm
+ std::unique_ptr<EventParamsMap> event_params_map_;
+ std::unique_ptr<OnEventListener> on_event_listener_;
+
void MapInsertOrAssign(std::map<std::string, std::string> *target_map,
const std::string &key, const std::string &value);
+ inline virtual void DispatchAttachedToParent() {}
+ inline virtual void DispatchDetachedFromParent() {}
};
} // namespace data_render
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 7fe2edc8a1..e2d3fe42e0 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
@@ -29,6 +29,8 @@
#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 "core/data_render/vnode/vcomponent_lifecycle_listener.h"
+#include "core/data_render/vnode/vnode_on_event_listener.h"
#include "base/LogDefines.h"
namespace weex {
@@ -58,7 +60,11 @@ static Value Merge(ExecState *exec_state) {
}
Value *lhs = exec_state->GetArgument(0);
Value *rhs = exec_state->GetArgument(1);
- if (!IsTable(lhs) && !IsTable(rhs)) {
+ if (IsTable(lhs) && IsNil(rhs)) {
+ return *lhs;
+ } else if (IsNil(lhs) && IsTable(rhs)) {
+ return *rhs;
+ } else if (!IsTable(lhs) && !IsTable(rhs)) {
return Value();
}
Value new_value = exec_state->class_factory()->CreateTable();
@@ -227,71 +233,50 @@ static Value AppendUrlParam(ExecState *exec_state) {
}
// saveComponentDataAndProps(component, data, props);
-static Value SaveComponentDataAndProps(ExecState* exec_state) {
+static Value saveComponentPropsAndData(ExecState *exec_state) {
VComponent *component = exec_state->GetArgument(0)->type == Value::Type::NIL ?
nullptr : reinterpret_cast<VComponent *>(exec_state->GetArgument(0)->cptr);
- Value *data = exec_state->GetArgument(1);
- Value *props = exec_state->GetArgument(2);
+ Value *props = exec_state->GetArgument(1);
+ Value *data = exec_state->GetArgument(2);
if (component) {
- component->set_data(ValueTo<Table>(data));
- component->set_props(ValueTo<Table>(props));
+ component->SetData(data);
+ component->SetProps(props);
}
return Value();
}
-// appendChildComponent(parent, child);
-static Value AppendChildComponent(ExecState* exec_state) {
- VNode *parent = exec_state->GetArgument(0)->type == Value::Type::NIL ?
- nullptr : reinterpret_cast<VNode *>(exec_state->GetArgument(0)->cptr);
- VNode *child = reinterpret_cast<VNode *>(exec_state->GetArgument(1)->cptr);
- if (parent && child) {
- static_cast<VComponent *>(parent)->AppendChildComponent(static_cast<VComponent *>(child));
+// setComponentRoot(component, node);
+static Value SetComponentRoot(ExecState* exec_state) {
+ VComponent *component = exec_state->GetArgument(0)->type == Value::Type::NIL ?
+ nullptr : reinterpret_cast<VComponent *>(exec_state->GetArgument(0)->cptr);
+ VNode* node = exec_state->GetArgument(1)->type == Value::Type::NIL ?
+ nullptr : reinterpret_cast<VNode *>(exec_state->GetArgument(1)->cptr);
+ if (component && node) {
+ component->SetRootNode(node);
}
return Value();
}
-// createComponent(template_id, "template_name", "tag_name", "id", ref);
+// createComponent(template_id, "template_name", func_name);
static Value CreateComponent(ExecState* exec_state) {
int template_id = 0;
- if (exec_state->GetArgument(0)->type == Value::Type::NUMBER) {
+ if (exec_state->GetArgument(0)->type == Value::Type::INT) {
template_id = static_cast<int>(exec_state->GetArgument(0)->i);
}
auto template_name = exec_state->GetArgument(1)->str;
- 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_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();
- 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(),
- "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(),
- tag_name, node_id, ref);
- }
- if (exec_state->context()->root() == nullptr) {
- exec_state->context()->set_root(component);
- }
+ auto func_name = exec_state->GetArgument(2)->str;
+ VComponent* component = new VComponent(
+ exec_state, template_id, template_name->c_str(), func_name->c_str());
Value result;
result.type = Value::Type::CPTR;
result.cptr = component;
+ if (exec_state->context()->root() == nullptr) {
+ exec_state->context()->set_root(component);
+ }
+ component->set_life_cycle_listener(
+ std::unique_ptr<VComponent::LifecycleListener>(
+ new VComponentLifecycleListener));
+ exec_state->context()->AddComponent(component->id(), component);
return result;
}
@@ -313,8 +298,6 @@ static Value UpdateElement(ExecState *exec_state) {
return Value();
}
-
-static size_t g_node_id = 0;
// createElement("tag_name", "id", ref);
static Value CreateElement(ExecState *exec_state) {
@@ -333,10 +316,7 @@ static Value CreateElement(ExecState *exec_state) {
throw VMExecError("CreateElement only support int for string");
}
std::string node_id,ref;
- std::ostringstream os;
- os << g_node_id++;
- node_id = "vn_" + os.str();
- ref = arg_id_str;
+ node_id = arg_id_str;
if (exec_state->GetArgumentCount() > 2 && exec_state->GetArgument(2)->type == Value::Type::STRING) {
ref = exec_state->GetArgument(2)->str->c_str();
}
@@ -545,10 +525,7 @@ static Value SetClassList(ExecState* exec_state) {
}
// 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);
+inline static Value SetStyle(VNode *node, Value *key, Value *value) {
if (node == nullptr || key->type != Value::Type::STRING ||
value->type == Value::Type::NIL) {
return Value();
@@ -557,6 +534,54 @@ static Value SetStyle(ExecState* exec_state) {
return Value();
}
+// setStyle(node, style);
+inline static Value SetStyle(VNode *node, Value *style) {
+ if (node == nullptr || style->type != Value::Type::TABLE) {
+ return Value();
+ }
+ auto style_map = ValueTo<Table>(style)->map;
+ for (auto it = style_map.begin(); it != style_map.end(); it++) {
+ node->SetStyle(it->first, ToString(&it->second));
+ }
+ return Value();
+}
+
+// setStyle(node, key, value);
+// or
+// setStyle(node, style);
+static Value SetStyle(ExecState *exec_state) {
+ VNode *node = reinterpret_cast<VNode *>(exec_state->GetArgument(0)->cptr);
+ auto length = exec_state->GetArgumentCount();
+ if (length == 3) {
+ Value *key = exec_state->GetArgument(1);
+ Value *value = exec_state->GetArgument(2);
+ SetStyle(node, key, value);
+ } else if (length == 2) {
+ Value *style = exec_state->GetArgument(1);
+ SetStyle(node, style);
+ }
+ return Value();
+}
+
+// addEvent(node, event, value);
+static Value AddEvent(ExecState* exec_state) {
+ VNode* node = reinterpret_cast<VNode*>(exec_state->GetArgument(0)->cptr);
+ Value *event = exec_state->GetArgument(1);
+ size_t argc = exec_state->GetArgumentCount() - 2;
+ std::vector<Value> args;
+ for (uint i = 0; i < argc; i++) {
+ Value *params = exec_state->GetArgument(2 + i);
+ args.push_back(*params);
+ }
+ if (node == nullptr || event->type != Value::Type::STRING) {
+ return Value();
+ }
+ node->AddEvent(event->str->c_str(), args);
+ node->set_on_event_listener(
+ std::unique_ptr<VNodeOnEventListener>(new VNodeOnEventListener));
+ return Value();
+}
+
void VNodeExecEnv::ImportExecEnv(ExecState *state) {
state->Register("sizeof", SizeOf);
state->Register("slice", Slice);
@@ -566,8 +591,8 @@ void VNodeExecEnv::ImportExecEnv(ExecState *state) {
state->Register("createElement", CreateElement);
state->Register("updateElement", UpdateElement);
state->Register("createComponent", CreateComponent);
- state->Register("saveComponentDataAndProps", SaveComponentDataAndProps);
- state->Register("appendChildComponent", AppendChildComponent);
+ state->Register("saveComponentPropsAndData", saveComponentPropsAndData);
+ state->Register("setComponentRoot", SetComponentRoot);
state->Register("appendChild", AppendChild);
state->Register("encodeURIComponent", encodeURIComponent);
state->Register("encodeURI", encodeURIComponent);
@@ -575,6 +600,7 @@ void VNodeExecEnv::ImportExecEnv(ExecState *state) {
state->Register("setProps", SetProps);
state->Register("setClassList", SetClassList);
state->Register("setStyle", SetStyle);
+ state->Register("addEvent", AddEvent);
state->Register("__callNativeModule", CallNativeModule);
// __registerModules deprecated in sversion 5.8 +
state->Register("__registerModules", RegisterModules);
@@ -664,17 +690,31 @@ json11::Json ValueToJSON(const Value& value) {
void VNodeExecEnv::ParseData(ExecState* state) {
const json11::Json& json = state->context()->raw_json();
Variables* global = state->global();
- const json11::Json& data = json["data"];
- Value value = JSONToValue(state, data);
- if (value.type != Value::Type::TABLE) {
- value = state->class_factory()->CreateTable();
- }
- global->Add("_data_main", value);
// Set component data and props
Value components_data = state->class_factory()->CreateTable();
Value components_props = state->class_factory()->CreateTable();
- const json11::Json& components_obj = json["components"];
+ Value components_computed = state->class_factory()->CreateTable();
+
+ // main means body
+ Value key(state->string_table()->StringFromUTF8("main"));
+ auto main_data = JSONToValue(state, json["data"]);
+ if (main_data.type != Value::Type::TABLE) {
+ main_data = state->class_factory()->CreateTable();
+ }
+ SetTableValue(ValueTo<Table>(&components_data), &key, main_data);
+ auto main_props = JSONToValue(state, json["props"]);
+ if (main_props.type != Value::Type::TABLE) {
+ main_props = state->class_factory()->CreateTable();
+ }
+ SetTableValue(ValueTo<Table>(&components_props), &key, main_props);
+ auto main_computed = JSONToValue(state, json["computed"]);
+ if (main_computed.type != Value::Type::TABLE) {
+ main_computed = state->class_factory()->CreateTable();
+ }
+ SetTableValue(ValueTo<Table>(&components_computed), &key, main_computed);
+
+ const json11::Json &components_obj = json["components"];
if (components_obj.is_array()) {
for (auto it = components_obj.array_items().begin();
it != components_obj.array_items().end(); it++) {
@@ -683,14 +723,23 @@ void VNodeExecEnv::ParseData(ExecState* state) {
continue;
}
auto temp_data = JSONToValue(state, (*it)["data"]);
+ if (temp_data.type != Value::Type::TABLE) {
+ temp_data = state->class_factory()->CreateTable();
+ }
Value key(state->string_table()->StringFromUTF8(name.string_value()));
SetTableValue(ValueTo<Table>(&components_data), &key, temp_data);
auto temp_props = JSONToValue(state, (*it)["props"]);
+ if (temp_props.type != Value::Type::TABLE) {
+ temp_props = state->class_factory()->CreateTable();
+ }
SetTableValue(ValueTo<Table>(&components_props), &key, temp_props);
+ auto temp_computed = JSONToValue(state, (*it)["computed"]);
+ SetTableValue(ValueTo<Table>(&components_computed), &key, temp_computed);
}
}
global->Add("_components_data", components_data);
global->Add("_components_props", components_props);
+ global->Add("_components_computed", components_computed);
}
void VNodeExecEnv::ImportExecData(ExecState *state, const std::string& init_data_str) {
diff --git a/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h
new file mode 100644
index 0000000000..3c974ab0fd
--- /dev/null
+++ b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.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.
+ */
+
+#ifndef CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_
+#define CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_
+
+#include "core/data_render/vnode/vnode.h"
+
+namespace weex {
+namespace core {
+namespace data_render {
+
+class VNodeOnEventListener : public VNode::OnEventListener {
+ void OnEvent(VNode *node, const std::string &event,
+ const std::string &json_args, const std::string dom_changes,
+ const VNode::Params ¶ms);
+};
+
+} // namespace data_render
+} // namespace core
+} // namespace weex
+
+#endif // CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
index 3f6c6ed57d..158e7eaa77 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
@@ -24,7 +24,12 @@ namespace core {
namespace data_render {
VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+ : page_id_(),
+ root_(nullptr),
+ raw_json_(),
+ script_(),
+ vcomponent_trees_(),
+ vnode_trees_() {}
VNodeRenderContext::~VNodeRenderContext() {}
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.h b/weex_core/Source/core/data_render/vnode/vnode_render_context.h
index b0a760a37a..456b1b5020 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.h
+++ b/weex_core/Source/core/data_render/vnode/vnode_render_context.h
@@ -53,6 +53,40 @@ class VNodeRenderContext {
script_json_ = script_json;
}
+ inline void AddComponent(int ref, VComponent *component) {
+ vcomponent_trees_.insert({ref, component});
+ }
+
+ inline void RemoveComponent(int ref) {
+ vcomponent_trees_.erase(ref);
+ }
+
+ inline VComponent* GetComponent(int ref) {
+ auto it = vcomponent_trees_.find(ref);
+ return it != vcomponent_trees_.end() ? it->second : nullptr;
+ }
+
+ inline void RemoveVNode(const std::string& ref) {
+ auto it = vnode_trees_.find(ref);
+ if (it != vnode_trees_.end()) {
+ vnode_trees_.erase(it);
+ }
+ }
+
+ inline void AddVNode(const std::string& ref, VNode* node) {
+ auto it = vnode_trees_.find(ref);
+ if (it != vnode_trees_.end()) {
+ vnode_trees_[ref] = node;
+ } else {
+ vnode_trees_.insert({ref, node});
+ }
+ }
+
+ inline VNode* GetVNode(const std::string &ref) {
+ auto it = vnode_trees_.find(ref);
+ return it != vnode_trees_.end() ? it->second : nullptr;
+ }
+
private:
// node context
std::string page_id_;
@@ -62,6 +96,8 @@ class VNodeRenderContext {
// script to execute
std::string script_;
std::map<std::string, json11::Json> style_json_;
+ std::unordered_map<int, VComponent *> vcomponent_trees_;
+ std::unordered_map<std::string, VNode*> vnode_trees_;
json11::Json script_json_;
};
} // namespace data_render
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 eb016cb162..9736d4b389 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
@@ -17,19 +17,22 @@
* under the License.
*/
+#include "core/data_render/vnode/vnode_render_manager.h"
#include <chrono>
#include <sstream>
-#include "core/data_render/vnode/vnode_render_manager.h"
+#include "base/make_copyable.h"
+#include "base/string_util.h"
+#include "core/bridge/platform_bridge.h"
#include "core/data_render/common_error.h"
-#include "core/data_render/exec_state_binary.h"
#include "core/data_render/exec_state.h"
+#include "core/data_render/exec_state_binary.h"
#include "core/data_render/string_table.h"
#include "core/data_render/vnode/vnode.h"
#include "core/data_render/vnode/vnode_exec_env.h"
#include "core/manager/weex_core_manager.h"
+#include "core/network/http_module.h"
#include "core/render/manager/render_manager.h"
#include "core/render/node/factory/render_creator.h"
-#include "core/bridge/platform_bridge.h"
#define VRENDER_LOG true
@@ -60,11 +63,17 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode,
WeexCore::RenderObject* parent, bool isRoot,
int index,
const string& pageId) {
+ if (vnode->IsVirtualComponent()) {
+ VComponent* component = static_cast<VComponent*>(vnode);
+ if (component->root_vnode() == nullptr) {
+ component->UpdateData();
+ }
+ return ParseVNode2RenderObject(component->root_vnode(), parent, isRoot,
+ index, pageId);
+ }
std::string ref_str;
if (isRoot) {
ref_str = "_root";
- } else if (!vnode->node_id().empty()) {
- ref_str = vnode->node_id();
} else {
ref_str = base::to_string(ref_id++);
}
@@ -87,14 +96,19 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode,
render_object->AddAttr(it->first, it->second);
}
- // event,todo
+ // event
std::map<std::string, void *> *events = vnode->events();
for (auto iter = events->begin(); iter != events->end(); iter++) {
render_object->events()->insert(iter->first);
}
+ auto event_params_map = vnode->event_params_map();
+ for (auto it = event_params_map->begin(); it != event_params_map->end();
+ it++) {
+ render_object->events()->insert(it->first);
+ }
// child
- vector<VNode*>* children = (const_cast<VNode*>(vnode))->child_list();
+ vector<VNode*>* children = vnode->child_list();
for (int i = 0; i < children->size(); i++) {
ParseVNode2RenderObject((*children)[i], render_object, false, i, pageId);
}
@@ -165,14 +179,14 @@ void VNodeRenderManager::InitVM() {
}
}
-void VNodeRenderManager::CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data) {
- std::string err = CreatePageWithContent(input, page_id, options, init_data);
+void VNodeRenderManager::CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data, std::function<void(const char*)> exec_js) {
+ std::string err = CreatePageWithContent(input, page_id, options, init_data, exec_js);
if (!err.empty()) {
WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(page_id.c_str(), nullptr, err.c_str());
}
}
-std::string VNodeRenderManager::CreatePageWithContent(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data) {
+std::string VNodeRenderManager::CreatePageWithContent(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data, std::function<void(const char*)> exec_js) {
InitVM();
#ifdef DEBUG
auto start = std::chrono::steady_clock::now();
@@ -214,14 +228,72 @@ std::string VNodeRenderManager::CreatePageWithContent(const std::string &input,
if (exec_state->context()->root() == NULL) {
return err;
}
+
CreatePageInternal(page_id, exec_state->context()->root());
#ifdef DEBUG
auto duration_post = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
LOGD("DATA_RENDER, All time %lld\n", duration_post.count());
#endif
+ DownloadAndExecScript(exec_state, page_id, exec_js);
return err;
}
-
+
+void VNodeRenderManager::DownloadAndExecScript(
+ ExecState* exec_state, const std::string& page_id,
+ std::function<void(const char*)> exec_js) {
+ // If script exists in json, run script into js vm
+ const json11::Json& script_array =
+ exec_state->context()->script_json();
+ if (script_array.is_array()) {
+ for (auto it = script_array.array_items().begin();
+ it != script_array.array_items().end(); it++) {
+ const json11::Json& script_obj = *it;
+ auto src = script_obj["src"];
+ auto content = script_obj["content"];
+ auto callback1 = weex::base::MakeCopyable(
+ [page_id = page_id, exec_js = exec_js, exec_state = exec_state](const char* result) {
+ exec_js(result);
+ auto root =
+ VNodeRenderManager::GetInstance()->GetRootVNode(page_id);
+ if (root && root->IsVirtualComponent()) {
+ static_cast<weex::core::data_render::VComponent*>(root)
+ ->DispatchCreated();
+
+ //fire event
+ exec_state->set_exec_js_finished(true);
+ const std::vector<std::vector<std::string>>& event_queue = exec_state->event_queue();
+ for (auto args : event_queue) {
+ VNodeRenderManager::GetInstance()->FireEvent(args[0], args[1], args[2], args[3], args[4]);
+ }
+ exec_state->ClearEventQueue();
+ }
+ });
+ // callback2, a wrap for callback1, will be post to script thread to
+ // execute callback1
+ auto callback2 = weex::base::MakeCopyable([callback = callback1](
+ const std::string& result) {
+#ifdef OS_ANDROID
+ WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
+ weex::base::MakeCopyable([result = std::move(result), callback]() {
+ callback(result.c_str());
+ }));
+#else
+ callback(result.c_str());
+#endif
+ });
+ // If script is a url, first download the script, else run script
+ // directly.
+ if (content.is_string() && !content.string_value().empty()) {
+ callback1(const_cast<char*>(content.string_value().c_str()));
+ } else if (src.is_string()) {
+ network::HttpModule http_module;
+ http_module.Send(page_id.c_str(), src.string_value().c_str(),
+ callback2);
+ }
+ }
+ }
+}
+
bool VNodeRenderManager::RequireModule(ExecState *exec_state, std::string &name, std::string &result)
{
bool finished = false;
@@ -262,7 +334,7 @@ void VNodeRenderManager::ExecuteRegisterModules(ExecState *exec_state, std::vect
} while (0);
}
-std::string VNodeRenderManager::CreatePageWithContent(const uint8_t *contents, size_t length, const std::string &page_id, const std::string &options, const std::string &init_data) {
+std::string VNodeRenderManager::CreatePageWithContent(const uint8_t *contents, size_t length, const std::string &page_id, const std::string &options, const std::string &init_data, std::function<void(const char*)> exec_js) {
InitVM();
#ifdef DEBUG
auto start = std::chrono::steady_clock::now();
@@ -295,11 +367,12 @@ std::string VNodeRenderManager::CreatePageWithContent(const uint8_t *contents, s
auto duration_post = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
LOGD("[DATA_RENDER], All time:[%lld]\n", duration_post.count());
#endif
+ DownloadAndExecScript(exec_state, page_id, exec_js);
return err;
}
-void VNodeRenderManager::CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data) {
- string err = CreatePageWithContent((const uint8_t *)contents, length, page_id, options, init_data);
+void VNodeRenderManager::CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data, std::function<void(const char*)> exec_js) {
+ string err = CreatePageWithContent((const uint8_t *)contents, length, page_id, options, init_data, exec_js);
if (!err.empty()) {
WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(page_id.c_str(), nullptr, err.c_str());
}
@@ -313,6 +386,18 @@ bool VNodeRenderManager::RefreshPage(const std::string& page_id,
break;
}
ExecState *exec_state = it->second;
+ // If component exsit, refresh by component
+ auto it_vnode = vnode_trees_.find(page_id);
+ if (it_vnode == vnode_trees_.end()) {
+ return false;
+ }
+ if (it_vnode->second->IsVirtualComponent()) {
+ auto component = static_cast<VComponent*>(it_vnode->second);
+ Value data = StringToValue(exec_state, init_data);
+ component->UpdateData(&data);
+ return true;
+ }
+ // Otherwise re-execute
VNodeExecEnv::ImportExecData(exec_state, init_data);
std::string err;
exec_state->context()->Reset();
@@ -325,9 +410,9 @@ bool VNodeRenderManager::RefreshPage(const std::string& page_id,
}
RefreshPageInternal(page_id, exec_state->context()->root());
WeexCore::WeexCoreManager::Instance()
- ->getPlatformBridge()
- ->platform_side()
- ->RefreshFinish(page_id.c_str(), nullptr, "");
+ ->getPlatformBridge()
+ ->platform_side()
+ ->RefreshFinish(page_id.c_str(), nullptr, "");
return true;
} while (0);
@@ -347,17 +432,38 @@ bool VNodeRenderManager::ClosePage(const std::string& page_id) {
return true;
}
-void VNodeRenderManager::FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args) {
+void VNodeRenderManager::FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args,const std::string &dom_changes) {
do {
auto iter = exec_states_.find(page_id);
if (iter == exec_states_.end()) {
break;
}
+ if (!iter->second->exec_js_finished()) {
+ std::vector<std::string> fire_event = {page_id, ref, event, args, dom_changes};
+ iter->second->AddEvent(fire_event);
+ break;
+ }
auto node = vnode_trees_.find(page_id);
if (node == vnode_trees_.end()) {
break;
}
+ // TODO merge two way to fire event
+ {
+ // First way to fire event from VNode::OnEvent
+ auto vnode = iter->second->context()->GetVNode(ref);
+ if (vnode) {
+ auto hit_test = vnode->event_params_map()->find(event);
+ if (hit_test != vnode->event_params_map()->end()) {
+ // If vnode has eat event, return.
+ vnode->OnEvent(event, args, dom_changes);
+ return;
+ }
+ }
+ }
+
+ // Second way to fire event from call vm func
auto vnode = node->second->FindNode(ref);
+ if (vnode == nullptr)
if (!vnode) {
break;
}
@@ -436,21 +542,35 @@ void VNodeRenderManager::WXLogNative(ExecState *exec_state, const std::string &i
}
}
+void VNodeRenderManager::UpdateComponentData(const std::string& page_id,
+ const char* cid,
+ const std::string& json_data) {
+ ExecState* exec_state = GetExecState(page_id);
+ if (!exec_state) return;
+ VComponent* component = exec_state->context()->GetComponent(atoi(cid));
+ if (component) {
+ Value value(StringToValue(exec_state, json_data));
+ component->UpdateData(&value);
+ }
+}
+
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;
- }
+ 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
+ if (a->IsVirtualComponent() && b->IsVirtualComponent()) {
+ return static_cast<VComponent*>(a)->IsSameNode(static_cast<VComponent*>(b));
+ } else {
+ // todo to be more accurate
+ return a->tag_name() == b->tag_name() && a->ref() == b->ref() &&
+ a->IsVirtualComponent() == b->IsVirtualComponent();
+ }
}
inline VNode* GetOrNull(vector<VNode*>& vec, int index) {
@@ -498,10 +618,10 @@ void UpdateChildren(const string& page_id, VNode* old_node, VNode* new_node) {
ref_list.push_back((*begin));
}
- unsigned int old_start = 0;
- unsigned int old_end = static_cast<unsigned int >(old_children.size()) - 1;
- unsigned int new_start = 0;
- unsigned int new_end = static_cast<unsigned int >(new_children.size()) - 1;
+ int old_start = 0;
+ int old_end = static_cast<int>(old_children.size()) - 1;
+ int new_start = 0;
+ int new_end = static_cast<int>(new_children.size()) - 1;
VNode* old_start_node = GetOrNull(old_children, old_start);
VNode* old_end_node = GetOrNull(old_children, old_end);
VNode* new_start_node = GetOrNull(new_children, new_start);
@@ -546,7 +666,7 @@ void UpdateChildren(const string& page_id, VNode* old_node, VNode* new_node) {
ref_to_index = new map<string, unsigned int>();
for (unsigned int i = old_start; i <= old_end; ++i) {
auto vnode = GetOrNull(old_children, i);
- if (vnode == nullptr) {
+ if (vnode == nullptr || vnode->ref().empty()) {
continue;
}
ref_to_index->insert({vnode->ref(), i});
@@ -623,7 +743,7 @@ void CreateAndInsertElm(const string& page_id, VNode* node,
int MoveToBackOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
const VNode* anchor_ref) {
auto move_pos = IndexOf(ref_list, move_ref);
- int index = static_cast<int>(std::distance(ref_list.begin(), move_pos));
+ auto anchor_pos = IndexOf(ref_list, anchor_ref);
if (move_pos == ref_list.end()) {
#if VRENDER_LOG
LOGE("[VRenderManager] moveToBackOfRef movePos == refList.end() ref: %s",
@@ -631,9 +751,6 @@ int MoveToBackOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
#endif
return -1; // wtf!
}
- VNode* value = *move_pos;
- ref_list.erase(move_pos);
- auto anchor_pos = IndexOf(ref_list, anchor_ref);
if (anchor_pos == ref_list.end()) {
#if VRENDER_LOG
LOGE("[VRenderManager] moveToBackOfRef anchorPos == refList.end() ref: %s",
@@ -641,14 +758,17 @@ int MoveToBackOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
#endif
return -1; // wtf
}
- ref_list.insert(++anchor_pos, value);
+ int index = static_cast<int>(std::distance(ref_list.begin(), anchor_pos));
+ VNode* value = *move_pos;
+ ref_list.erase(move_pos);
+ ref_list.insert(anchor_pos, value);
return index;
}
int MoveToFrontOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
const VNode* anchor_ref) {
auto move_pos = IndexOf(ref_list, move_ref);
- int index = static_cast<int>(std::distance(ref_list.begin(), move_pos));
+ auto anchor_pos = IndexOf(ref_list, anchor_ref);
if (move_pos == ref_list.end()) {
#if VRENDER_LOG
LOGE("[VRenderManager] moveToFrontOfRef movePos == refList.end() ref: %s",
@@ -656,9 +776,6 @@ int MoveToFrontOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
#endif
return -1; // wtf!
}
- VNode* value = *move_pos;
- ref_list.erase(move_pos);
- auto anchor_pos = IndexOf(ref_list, anchor_ref);
if (anchor_pos == ref_list.end()) {
#if VRENDER_LOG
LOGE("[VRenderManager] moveToFrontOfRef anchorPos == refList.end() ref: %s",
@@ -666,6 +783,9 @@ int MoveToFrontOfRef(vector<VNode*>& ref_list, const VNode* move_ref,
#endif
return -1; // wtf
}
+ int index = static_cast<int>(std::distance(ref_list.begin(), anchor_pos));
+ VNode* value = *move_pos;
+ ref_list.erase(move_pos);
ref_list.insert(anchor_pos, value);
return index;
}
@@ -728,7 +848,6 @@ vector<pair<string, string>>* CompareMap(const map<string, string>& oldMap,
auto p_vec = new vector<pair<string, string>>();
for (auto it = newMap.cbegin(); it != newMap.cend(); it++) {
auto pos = oldMap.find(it->first);
-
if (pos == oldMap.end() || pos->second != it->second) {
// key not exist, or value not same
p_vec->push_back({it->first, it->second});
@@ -737,7 +856,6 @@ vector<pair<string, string>>* CompareMap(const map<string, string>& oldMap,
for (auto it = oldMap.cbegin(); it != oldMap.cend(); it++) {
auto pos = newMap.find(it->first);
-
if (pos == newMap.end()) {
// key not exist, remove //todo check if this is correct
p_vec->push_back({it->first, ""});
@@ -745,8 +863,70 @@ vector<pair<string, string>>* CompareMap(const map<string, string>& oldMap,
}
return p_vec;
};
-
+
+void CompareAndApplyEvents1(const std::string& page_id, VNode* old_node,
+ VNode* new_node) {
+ std::map<std::string, void*> old_events = *old_node->events();
+ std::map<std::string, void*> new_events = *new_node->events();
+
+ for (auto it = old_events.cbegin(); it != old_events.cend(); it++) {
+ auto pos = new_events.find(it->first);
+ if (pos == new_events.end()) {
+ new_events.erase(pos);
+ }
+ }
+ for (auto it = new_events.cbegin(); it != new_events.cend(); it++) {
+ auto pos = old_events.find(it->first);
+ if (pos == old_events.end()) {
+ old_events.erase(pos);
+ }
+ }
+ for (auto it = old_events.cbegin(); it != old_events.cend(); it++) {
+ RenderManager::GetInstance()->RemoveEvent(
+ page_id, new_node->render_object_ref(), it->first);
+ }
+ for (auto it = new_events.cbegin(); it != new_events.cend(); it++) {
+ RenderManager::GetInstance()->AddEvent(
+ page_id, new_node->render_object_ref(), it->first);
+ }
+}
+
+void CompareAndApplyEvents2(const std::string& page_id, VNode* old_node,
+ VNode* new_node) {
+ VNode::EventParamsMap old_events = *old_node->event_params_map();
+ VNode::EventParamsMap new_events = *new_node->event_params_map();
+
+ for (auto it = old_events.cbegin(); it != old_events.cend(); it++) {
+ auto pos = new_events.find(it->first);
+
+ if (pos == new_events.end()) {
+ new_events.erase(pos);
+ }
+ }
+ for (auto it = new_events.cbegin(); it != new_events.cend(); it++) {
+ auto pos = old_events.find(it->first);
+
+ if (pos == old_events.end()) {
+ old_events.erase(pos);
+ }
+ }
+ for (auto it = old_events.cbegin(); it != old_events.cend(); it++) {
+ RenderManager::GetInstance()->RemoveEvent(
+ page_id, new_node->render_object_ref(), it->first);
+ }
+ for (auto it = new_events.cbegin(); it != new_events.cend(); it++) {
+ RenderManager::GetInstance()->AddEvent(
+ page_id, new_node->render_object_ref(), it->first);
+ }
+}
+
void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) {
+ if (old_node->IsVirtualComponent()) {
+ static_cast<VComponent*>(old_node)
+ ->MoveTo(static_cast<VComponent*>(new_node));
+ return;
+ }
+
// patch render object link
new_node->set_render_object_ref(old_node->render_object_ref());
@@ -754,8 +934,7 @@ void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) {
auto p_vec = CompareMap(*(old_node->attributes()), *(new_node->attributes()));
if (p_vec->size() > 0) {
RenderManager::GetInstance()->UpdateAttr(page_id, new_node->render_object_ref(), p_vec);
- }
- else {
+ } else {
delete p_vec;
p_vec = nullptr;
}
@@ -763,14 +942,14 @@ void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) {
p_vec = CompareMap(*(old_node->styles()), *(new_node->styles()));
if (p_vec->size()) {
RenderManager::GetInstance()->UpdateStyle(page_id, new_node->render_object_ref(), p_vec);
- }
- else {
+ } else {
delete p_vec;
p_vec = nullptr;
}
- // compare event
- // todo
+ // compare and apply event
+ CompareAndApplyEvents1(page_id, old_node, new_node);
+ CompareAndApplyEvents2(page_id, old_node, new_node);
// compare children
if (old_node->HasChildren() && new_node->HasChildren()) {
@@ -785,32 +964,39 @@ void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) {
int index = 0;
for (auto it = new_node->child_list()->cbegin();
it != new_node->child_list()->cend(); it++) {
- WeexCore::RenderObject *root = VNode2RenderObject(*it, page_id);
+ WeexCore::RenderObject *child_node = ParseVNode2RenderObject(*it, nullptr, false, 0, page_id);
RenderManager::GetInstance()->AddRenderObject(
- page_id, (*it)->parent()->render_object_ref(), index, root);
+ page_id, (*it)->parent()->render_object_ref(), index, child_node);
++index;
}
}
}
void Patch(const string& page_id, VNode *old_node, VNode *new_node) {
- if (old_node->parent() == NULL || SameNode(old_node, new_node)) {
+ if (!old_node) {
+ ParseVNode2RenderObject(new_node, nullptr, false, 0, page_id);
+ } else 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();
+ } else {
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());
+ VNode *parent = (VNode *)old_node->parent();
+ if (!parent && old_node->component()) {
+ parent = const_cast<VNode*>(old_node->component()->parent());
+ old_node = old_node->component();
+ }
+ if (parent) {
+ vector<VNode *> &old_children = *parent->child_list();
+ 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 85cb3b8b7c..cf33330c62 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
@@ -34,6 +34,7 @@ namespace weex {
namespace core {
namespace data_render {
+class HttpModule;
class VNodeRenderManager {
friend class VNode;
private:
@@ -42,18 +43,19 @@ class VNodeRenderManager {
~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 std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data, std::function<void(const char*)> exec_js);
- void CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data);
+ void CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data, std::function<void(const char*)> exec_js);
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 FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args,const std::string &dom_changes);
void ExecuteRegisterModules(ExecState *exec_state, std::vector<std::string>& registers);
void RegisterModules(const std::string &modules) { modules_.push_back(modules); }
bool RequireModule(ExecState *exec_state, std::string &name, std::string &result);
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);
+ void UpdateComponentData(const std::string& page_id, const char* cid, const std::string& json_data);
void WXLogNative(ExecState *exec_state, const std::string &info);
static VNodeRenderManager *GetInstance() {
if (!g_instance) {
@@ -62,20 +64,39 @@ class VNodeRenderManager {
return g_instance;
}
+ inline ExecState *GetExecState(const std::string &instance_id) {
+ auto it = exec_states_.find(instance_id);
+ return it != exec_states_.end() ? it->second : nullptr;
+ }
+
+ inline VNode *GetRootVNode(const std::string &instance_id) {
+ auto it = vnode_trees_.find(instance_id);
+ return it != vnode_trees_.end() ? it->second : nullptr;
+ }
+
private:
void InitVM();
bool CreatePageInternal(const std::string &page_id, VNode *v_node);
bool RefreshPageInternal(const std::string &page_id, VNode *new_node);
bool ClosePageInternal(const std::string &page_id);
+ void DownloadAndExecScript(ExecState *exec_state, const std::string &page_id,
+ std::function<void(const char *)> exec_js);
- std::string CreatePageWithContent(const uint8_t *contents, size_t length, const std::string &page_id, const std::string &options, const std::string &init_data);
- std::string CreatePageWithContent(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data);
+ std::string CreatePageWithContent(const uint8_t *contents, size_t length,
+ const std::string &page_id,
+ const std::string &options,
+ const std::string &init_data,
+ std::function<void(const char*)> exec_js);
+ std::string CreatePageWithContent(const std::string &input,
+ const std::string &page_id,
+ const std::string &options,
+ const std::string &init_data,
+ std::function<void(const char *)> exec_js);
static VM *g_vm;
static VNodeRenderManager *g_instance;
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_;
};
diff --git a/weex_core/Source/core/network/android/default_request_handler.cc b/weex_core/Source/core/network/android/default_request_handler.cc
new file mode 100644
index 0000000000..f44dc59679
--- /dev/null
+++ b/weex_core/Source/core/network/android/default_request_handler.cc
@@ -0,0 +1,77 @@
+/**
+ * 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.
+ */
+#if OS_ANDROID
+
+#include "core/network/android/default_request_handler.h"
+#include "android/base/jni/android_jni.h"
+#include "android/base/string/scoped_jstring_utf8.h"
+#include "android/jniprebuild/jniheader/RequestHandler_jni.h"
+
+using namespace weex::core::network;
+
+static void InvokeOnSuccess(JNIEnv* env, jobject jcaller, jlong callback,
+ jstring result) {
+ CallbackWrapper* callback_wrapper =
+ reinterpret_cast<CallbackWrapper*>(callback);
+ WeexCore::ScopedJStringUTF8 jni_result(env, result);
+ callback_wrapper->Invoke(jni_result.getChars() ? jni_result.getChars() : "");
+ delete callback_wrapper;
+}
+
+static void InvokeOnFailed(JNIEnv* env, jobject jcaller, jlong callback) {
+ CallbackWrapper* callback_wrapper =
+ reinterpret_cast<CallbackWrapper*>(callback);
+ delete callback_wrapper;
+}
+
+namespace weex {
+namespace core {
+namespace network {
+
+bool DefaultRequestHandler::RegisterJNIUtils(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+DefaultRequestHandler::DefaultRequestHandler() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Reset(env, Java_RequestHandler_create(env).Release());
+}
+
+DefaultRequestHandler::~DefaultRequestHandler() {}
+
+void DefaultRequestHandler::Send(const char* instance_id, const char* url,
+ Callback callback) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (!env) return;
+ CallbackWrapper* callback_wrapper = new CallbackWrapper(callback);
+ base::android::ScopedLocalJavaRef<jstring> jni_url(env,
+ env->NewStringUTF(url));
+ base::android::ScopedLocalJavaRef<jstring> jni_id(
+ env, env->NewStringUTF(instance_id));
+ Java_RequestHandler_send(env, jni_object(), jni_id.Get(), jni_url.Get(),
+ reinterpret_cast<jlong>(callback_wrapper));
+}
+
+RequestHandler* RequestHandler::CreateDefaultHandler() {
+ return new DefaultRequestHandler();
+}
+} // namespace network
+} // namespace core
+} // namespace weex
+#endif
\ No newline at end of file
diff --git a/weex_core/Source/core/network/android/default_request_handler.h b/weex_core/Source/core/network/android/default_request_handler.h
new file mode 100644
index 0000000000..cf1f556479
--- /dev/null
+++ b/weex_core/Source/core/network/android/default_request_handler.h
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+#if OS_ANDROID
+
+#ifndef CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+#define CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+
+#include <jni.h>
+#include "android/wrap/jni_object_wrap.h"
+#include "core/network/request_handler.h"
+
+namespace weex {
+namespace core {
+namespace network {
+
+class DefaultRequestHandler : public RequestHandler,
+ public WeexCore::JNIObjectWrap {
+ public:
+ static bool RegisterJNIUtils(JNIEnv* env);
+ DefaultRequestHandler();
+ ~DefaultRequestHandler() override;
+ void Send(const char* instance_id, const char* url,
+ Callback callback) override;
+};
+
+class CallbackWrapper {
+ public:
+ CallbackWrapper(Callback callback) : callback_(callback) {}
+ ~CallbackWrapper() {}
+ void Invoke(const std::string& result) { callback_(result); }
+
+ private:
+ Callback callback_;
+};
+
+} // namespace network
+} // namespace core
+} // namespace weex
+#endif // CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+#endif
diff --git a/weex_core/Source/core/network/http_module.cc b/weex_core/Source/core/network/http_module.cc
new file mode 100644
index 0000000000..200952fb5e
--- /dev/null
+++ b/weex_core/Source/core/network/http_module.cc
@@ -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.
+ */
+#include "core/network/http_module.h"
+#include "core/network/request_handler.h"
+
+namespace weex {
+namespace core {
+namespace network {
+
+HttpModule::HttpModule()
+ : request_handler_(RequestHandler::CreateDefaultHandler()) {}
+
+HttpModule::HttpModule(RequestHandler* request_handler)
+ : request_handler_(request_handler) {}
+
+void HttpModule::Send(const char* instance_id, const char* url,
+ Callback callback) {
+ request_handler_->Send(instance_id, url, callback);
+}
+
+} // namespace network
+} // namespace core
+} // namespace weex
diff --git a/weex_core/Source/core/network/http_module.h b/weex_core/Source/core/network/http_module.h
new file mode 100644
index 0000000000..4c4b57993c
--- /dev/null
+++ b/weex_core/Source/core/network/http_module.h
@@ -0,0 +1,41 @@
+/**
+ * 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_NETWORK_HTTP_MODULE_
+#define CORE_NETWORK_HTTP_MODULE_
+#include "core/network/request_handler.h"
+
+namespace weex {
+namespace core {
+namespace network {
+
+class HttpModule {
+ public:
+ HttpModule();
+ HttpModule(RequestHandler* request_handler);
+ void Send(const char* instance_id, const char* url, Callback callback);
+
+ private:
+ std::unique_ptr<RequestHandler> request_handler_;
+};
+
+} // namespace network
+} // namespace core
+} // namespace weex
+#endif // CORE_NETWORK_HTTP_MODULE_
diff --git a/weex_core/Source/core/network/ios/default_request_handler.h b/weex_core/Source/core/network/ios/default_request_handler.h
new file mode 100644
index 0000000000..2099d5303a
--- /dev/null
+++ b/weex_core/Source/core/network/ios/default_request_handler.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.
+ */
+
+#ifndef CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+#define CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+
+#include "core/network/request_handler.h"
+
+namespace weex {
+namespace core {
+namespace network {
+
+class DefaultRequestHandler : public RequestHandler {
+ public:
+ DefaultRequestHandler();
+ ~DefaultRequestHandler() override;
+ void Send(const char* instance_id, const char* url,
+ Callback callback) override;
+};
+
+} // namespace network
+} // namespace core
+} // namespace weex
+#endif // CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
diff --git a/weex_core/Source/core/network/ios/default_request_handler.mm b/weex_core/Source/core/network/ios/default_request_handler.mm
new file mode 100644
index 0000000000..11f12f2308
--- /dev/null
+++ b/weex_core/Source/core/network/ios/default_request_handler.mm
@@ -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.
+ */
+#include "core/network/ios/default_request_handler.h"
+#import "WXConvertUtility.h"
+#import "WXSDKManager.h"
+
+namespace weex {
+namespace core {
+namespace network {
+ DefaultRequestHandler::DefaultRequestHandler() {}
+
+ DefaultRequestHandler::~DefaultRequestHandler() {}
+
+ void DefaultRequestHandler::Send(const char* instance_id, const char* url, Callback callback) {
+ NSURL* nsURL = [NSURL URLWithString:NSSTRING(url)];
+ [[WXSDKManager bridgeMgr] DownloadJS:nsURL completion:^(NSString *script) {
+ if (!script) {
+ return;
+ }
+ callback([script UTF8String]);
+ }];
+ }
+
+ RequestHandler* RequestHandler::CreateDefaultHandler() {
+ return new DefaultRequestHandler();
+ }
+}
+}
+}
diff --git a/weex_core/Source/core/network/request_handler.h b/weex_core/Source/core/network/request_handler.h
new file mode 100644
index 0000000000..66a4a87a3f
--- /dev/null
+++ b/weex_core/Source/core/network/request_handler.h
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef CORE_NETWORK_REQUEST_HANDLER_H
+#define CORE_NETWORK_REQUEST_HANDLER_H
+#include <functional>
+#include <memory>
+
+namespace weex {
+namespace core {
+namespace network {
+typedef std::function<void(const std::string&)> Callback;
+
+class RequestHandler {
+ public:
+ RequestHandler() {}
+ virtual ~RequestHandler() {}
+ virtual void Send(const char* instance_id, const char* url,
+ Callback callback) = 0;
+ static RequestHandler* CreateDefaultHandler();
+};
+
+} // namespace network
+} // namespace core
+} // namespace weex
+#endif // CORE_NETWORK_REQUEST_HANDLER_H
diff --git a/weex_core/Source/include/WeexApiHeader.h b/weex_core/Source/include/WeexApiHeader.h
index 9470cf4fc0..53b5ef6161 100644
--- a/weex_core/Source/include/WeexApiHeader.h
+++ b/weex_core/Source/include/WeexApiHeader.h
@@ -153,6 +153,8 @@ typedef std::unique_ptr<WeexJSResult> (*FuncCallDispatchMessageSync)(
typedef void
(*FuncOnReceivedResult)(long callback_id, std::unique_ptr<WeexJSResult>& result);
+typedef void
+(*FuncUpdateComponentData)(const char* page_id, const char* cid, const char* json_data);
typedef struct FunctionsExposedByCore {
@@ -182,6 +184,7 @@ typedef struct FunctionsExposedByCore {
FuncCallDIspatchMessage funcCallDIspatchMessage;
FuncCallDispatchMessageSync funcCallDispatchMessageSync;
FuncOnReceivedResult funcOnReceivedResult;
+ FuncUpdateComponentData funcUpdateComponentData;
} FunctionsExposedByCore;
typedef void (*FuncCallSetJSVersion)(const char* version);
diff --git a/weex_core/release.sh b/weex_core/release.sh
index af143d0c81..02a01965a5 100755
--- a/weex_core/release.sh
+++ b/weex_core/release.sh
@@ -1,6 +1,6 @@
cd ../android
-rm -rf sdk/build/intermediates/bundles/release/jni/*
-./gradlew clean assemble
-cp sdk/build/intermediates/bundles/release/jni/armeabi/libweexcore.so sdk/libs/armeabi/libweexcore.so
-cp sdk/build/intermediates/bundles/release/jni/armeabi-v7a/libweexcore.so sdk/libs/armeabi-v7a/libweexcore.so
-cp sdk/build/intermediates/bundles/release/jni/x86/libweexcore.so sdk/libs/x86/libweexcore.so
+rm -rf sdk/build/intermediates/bundles/default/jni/*
+./gradlew clean assembleRelease
+cp sdk/build/intermediates/bundles/default/jni/armeabi/libweexcore.so sdk/libs/armeabi/libweexcore.so
+cp sdk/build/intermediates/bundles/default/jni/armeabi-v7a/libweexcore.so sdk/libs/armeabi-v7a/libweexcore.so
+cp sdk/build/intermediates/bundles/default/jni/x86/libweexcore.so sdk/libs/x86/libweexcore.so
----------------------------------------------------------------
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