You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by xi...@apache.org on 2018/12/20 06:10:11 UTC
[incubator-weex] branch master updated: * [Android][iOS][C++] Add
eagle version of data-render (#1937)
This is an automated email from the ASF dual-hosted git repository.
xifang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git
The following commit(s) were added to refs/heads/master by this push:
new a11a9dc * [Android][iOS][C++] Add eagle version of data-render (#1937)
a11a9dc is described below
commit a11a9dc8280764fa66f99dcb3593ebb54f510cf8
Author: YorkShen <sh...@gmail.com>
AuthorDate: Thu Dec 20 14:10:06 2018 +0800
* [Android][iOS][C++] Add eagle version of data-render (#1937)
* [core] add vcomponent diff
* [core] support component ref finder
* [core][data_render] support class binding
* [core][data_render] add event support
* [core][data_render] support value array of attr parser
* [core][data_render] support vcomponent lifecycle and update from js
* [core][data_render] support event
* [iOS] add js binding on iOS
* [core][eagle] fix codegen prefix invalid problem
* [iOS] add createinstance to execute js
* [core] add http_module
* [core][eagle] fix event params
* [eagle] fix repeat bug
* [iOS] add requestHandle to download js
* [iOS] fix weexsdk compile error
* [iOS] fix weexsdk compile error
* [Android] make WXHttpListener be in common use
* [core][eagle] support httpmodule in android
* [eagle] support binding style and computed
* [eagle] fix bugs
* [Android] fix update styles bug when only border change
* [Android] do not set the same text repeatedly
* [Android] fix boxshadow not change size when view size changed
* * [Android] Update URL render rule
1. __data_render==true for WXRenderStrategy.DATA_RENDER
2. __eagle==true for WXRenderStrategy.DATA_RENDER_BINARY
3. others for WXRenderStrategy.APPEND_ASYNC
* [core] support javascript binding on iOS
* [iOS] update js framework
* [core] fix click event error on eagle
* [core] fix crash when data is null on eagle
* [core] fix crash when data array are null on eagle
* * [Android] Update libweexjss for updateComponentData.
* [core] fix bool type equre operator error
* [core] support js file cache
* [iOS] fix data null error
* [iOS] support bundleUrl on eagle
* [core] fix crash when root_node is null
* * [Android] Add libweexcore.so due to the malfunction of integration machine
* [jsframework] updata jsframework to support get data
* * [Android] Update jsfm.js
* [core] fix incorrect data this get from js
* * [Android] Update libweexcore.so
* [core] fix parent component bug
* [core] fix onAppear event can not exec
* * [Android] Update so
* [iOS] add CUSTOM_PREPROCESS record time
* * [Android] Add customPreprocess for APM
* * [Android] Update build.gradle
---
WeexSDK.podspec | 7 +-
.../main/java/com/alibaba/weex/WXPageActivity.java | 7 +-
android/sdk/.gitignore | 3 -
android/sdk/build.gradle | 4 +
android/sdk/libs/armeabi-v7a/libweexjss.so | Bin 341516 -> 341572 bytes
android/sdk/libs/armeabi/libweexjss.so | Bin 341516 -> 341572 bytes
.../main/java/com/taobao/weex/WXHttpListener.java | 260 ++++++++++
.../main/java/com/taobao/weex/WXSDKInstance.java | 206 +-------
.../com/taobao/weex/bridge/RequestHandler.java | 101 ++++
.../main/java/com/taobao/weex/bridge/WXBridge.java | 14 +-
.../com/taobao/weex/bridge/WXBridgeManager.java | 9 +-
.../java/com/taobao/weex/common/IWXBridge.java | 2 -
.../com/taobao/weex/performance/WXInstanceApm.java | 4 +
.../weex/ui/action/GraphicActionUpdateStyle.java | 25 +-
.../weex/ui/component/AbstractEditComponent.java | 3 +
.../com/taobao/weex/ui/component/WXVContainer.java | 24 +-
.../com/taobao/weex/utils/WXDataStructureUtil.java | 28 +-
ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 108 +++-
ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m | 11 +-
ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h | 2 +
ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm | 170 ++-----
ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm | 15 +
ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h | 20 +
ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m | 45 ++
ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 4 +
.../WeexSDK/Sources/Performance/WXApmForInstance.h | 2 +
.../WeexSDK/Sources/Performance/WXApmForInstance.m | 2 +
.../WeexSDK/Sources/Protocol/WXBridgeProtocol.h | 6 +
ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h | 60 +++
.../WeexSDK/Sources/Utility/WXConvertUtility.mm | 249 ++++++++++
ios/sdk/WeexSDK/Sources/WeexSDK.h | 1 +
weex_core/Source/CMakeLists.txt | 7 +
weex_core/Source/IPC/IPCMessageJS.h | 1 +
.../bridge/script_bridge_in_multi_process.cpp | 17 +
.../android/bridge/script_bridge_in_multi_so.cpp | 16 +-
weex_core/Source/android/jniprebuild/jni_files | 1 +
weex_core/Source/android/jniprebuild/jni_load.cc | 4 +-
.../jniprebuild/jniheader/RequestHandler_jni.h | 122 +++++
.../android/jniprebuild/jniheader/WXBridge_jni.h | 4 +-
weex_core/Source/android/wrap/wx_bridge.cpp | 13 +-
weex_core/Source/base/string_util.h | 29 ++
.../core/bridge/platform/core_side_in_platform.cpp | 28 +-
.../core/bridge/script/core_side_in_script.cpp | 9 +
.../core/bridge/script/core_side_in_script.h | 3 +
weex_core/Source/core/bridge/script_bridge.h | 3 +
weex_core/Source/core/data_render/ast.h | 2 +
weex_core/Source/core/data_render/class_json.cc | 2 +-
weex_core/Source/core/data_render/class_math.cc | 10 +-
weex_core/Source/core/data_render/class_object.cc | 2 +-
weex_core/Source/core/data_render/class_regex.cc | 6 +-
weex_core/Source/core/data_render/class_string.cc | 24 +-
.../Source/core/data_render/code_generator.cc | 50 +-
weex_core/Source/core/data_render/exec_state.cc | 4 +
weex_core/Source/core/data_render/exec_state.h | 12 +
.../Source/core/data_render/exec_state_section.cc | 184 +++++--
.../Source/core/data_render/exec_state_section.h | 5 +-
weex_core/Source/core/data_render/object.cc | 2 +-
weex_core/Source/core/data_render/object.h | 54 +-
weex_core/Source/core/data_render/parser.cc | 553 ++++++++++++---------
weex_core/Source/core/data_render/string_table.h | 2 +-
weex_core/Source/core/data_render/vm.cc | 19 +-
.../core/data_render/vnode/android/conversion.cc | 81 +++
.../conversion.h} | 27 +-
.../vnode/android/vcomponent_lifecycle_listener.cc | 265 ++++++++++
.../vnode/android/vnode_on_event_listener.cc | 112 +++++
.../vnode/ios/vcomponent_lifecycle_listener.mm | 77 +++
.../vnode/ios/vnode_on_event_listener.mm | 49 ++
.../Source/core/data_render/vnode/vcomponent.cc | 215 ++++++--
.../Source/core/data_render/vnode/vcomponent.h | 89 ++--
..._context.cc => vcomponent_lifecycle_listener.h} | 25 +-
weex_core/Source/core/data_render/vnode/vnode.cc | 62 ++-
weex_core/Source/core/data_render/vnode/vnode.h | 59 ++-
.../core/data_render/vnode/vnode_exec_env.cc | 181 ++++---
...render_context.cc => vnode_on_event_listener.h} | 19 +-
.../core/data_render/vnode/vnode_render_context.cc | 7 +-
.../core/data_render/vnode/vnode_render_context.h | 36 ++
.../core/data_render/vnode/vnode_render_manager.cc | 318 +++++++++---
.../core/data_render/vnode/vnode_render_manager.h | 33 +-
.../network/android/default_request_handler.cc | 77 +++
.../android/default_request_handler.h} | 53 +-
.../http_module.cc} | 23 +-
.../http_module.h} | 23 +-
.../ios/default_request_handler.h} | 24 +-
.../ios/default_request_handler.mm} | 31 +-
.../request_handler.h} | 26 +-
weex_core/Source/include/WeexApiHeader.h | 3 +
weex_core/release.sh | 10 +-
87 files changed, 3416 insertions(+), 1089 deletions(-)
diff --git a/WeexSDK.podspec b/WeexSDK.podspec
index bcb2743..f0ae762 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 b6d8e56..606b5d1 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.View;
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.WXComponent;
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 class WXPageActivity extends WXBaseActivity implements IWXRenderListener,
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 25d1179..9c18c2d 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 ecba7bc..e8986f5 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 de119ed..50e261a 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 de119ed..50e261a 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 0000000..4e10863
--- /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 19404b3..36ca0bb 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.Menu;
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.OnWXScrollListener;
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.WXLogUtils;
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.Map;
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 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
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);
@@ -1909,198 +1905,6 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
}
/**
- * 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
* */
public String getTemplateInfo() {
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 0000000..a5bf160
--- /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 de3db66..15fd438 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 class WXBridge implements IWXBridge {
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 class WXBridge implements IWXBridge {
// 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 class WXBridge implements IWXBridge {
}
}
- @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 e7ccda6..83cb708 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 class WXBridgeManager implements Callback, BactchExecutor {
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 class WXBridgeManager implements Callback, BactchExecutor {
}
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 class WXBridgeManager implements Callback, BactchExecutor {
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 40c484f..847b40b 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 @@ public interface IWXBridge extends IWXObject {
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 483d5ae..777374f 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 class WXInstanceApm {
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 e464cc1..bddb338 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 @@ public class GraphicActionUpdateStyle extends BasicGraphicAction {
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 class GraphicActionUpdateStyle extends BasicGraphicAction {
}
if (null != borders) {
+ mIsBorderSet = true;
component.setBorders(borders);
}
}
@@ -114,23 +116,26 @@ public class GraphicActionUpdateStyle extends BasicGraphicAction {
}
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 7c6134f..c06f611 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 abstract class AbstractEditComponent extends WXComponent<WXEditText> {
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 33cd5cb..d592038 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 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> {
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 a6ab07f..ee28e45 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 aeb4d3b..90b9bb0 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 093945b..4b4b545 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -134,6 +134,15 @@ _Pragma("clang diagnostic pop") \
[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 @@ _Pragma("clang diagnostic pop") \
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 12c1f07..ca5fd83 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 b2ea970..37b5e9b 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 @@ namespace WeexCore
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 @@ namespace WeexCore
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 @@ namespace WeexCore
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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
{
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 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
}
}
-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 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
}
[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 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
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 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
}];
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 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
{
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 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
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 3652a0d..7577b3d 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
@@ -156,6 +156,21 @@
}
}
+- (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 3386763..29d9fd1 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -46,6 +46,18 @@ extern "C" {
* @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
+ * @param temp : template data
+ * @param options : parameters
+ * @param data : external data
+ **/
- (void)createInstance:(NSString *)instance
template:(NSString *)temp
options:(NSDictionary *)options
@@ -105,6 +117,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
* @param serviceScript : script code
@@ -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 f5c7a47..ba412d7 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -142,6 +142,21 @@ void WXPerformBlockSyncOnBridgeThread(void (^block) (void))
}
#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 @@ void WXPerformBlockSyncOnBridgeThread(void (^block) (void))
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 WXPerformBlockSyncOnBridgeThread(void (^block) (void))
});
}
+- (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 ccab0e5..2bc521e 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -473,6 +473,10 @@ typedef enum : NSUInteger {
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 a816246..da559bc 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 d44effd..7a8822d 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_PROPERTIES_RENDER_TYPE = @"wxRenderType";
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 90bb955..b3d1019 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>
@@ -75,6 +76,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
*/
- (void)registerCallNative:(WXJSCallNative)callNative;
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvertUtility.h
new file mode 100644
index 0000000..25d6f3b
--- /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 0000000..02ea25d
--- /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 a611390..9d7f293 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 2e5624a..f3e5019 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 a99b265..94f698c 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 5b10902..9a5e4eb 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 400a83f..32f06e5 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 fb9b291..1d02d01 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 d668ae6..fba2c63 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 0000000..f83ad37
--- /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 0b746fd..b431c4e 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 a699324..2e9cf92 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 9e07c97..4e0ea3b 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 a35ac01..b767ed4 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 d941245..a9ba409 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 125b1af..2c53c1c 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 0c85e0b..7790792 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 1bdfa7f..c8509f7 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 ac1e143..4d80748 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 119f1b1..9d1b282 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 eb38ef5..720043f 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 95204f0..3d55d38 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 fa8b89d..50bcb29 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 1cbc4e5..a472243 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 6ba2054..5016c43 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 398e73b..10dcce8 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 c40df1c..b5754a0 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 2989ba1..3770dfd 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 @@ public:
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 38f5814..fee0d2d 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 b551ca3..44df5f2 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 38a1815..fd8f6ef 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 5d1dddd..568c023 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 000fa4d..b9331df 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 0000000..9248dd1
--- /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/vnode_render_context.cc b/weex_core/Source/core/data_render/vnode/android/conversion.h
similarity index 64%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/data_render/vnode/android/conversion.h
index 3f6c6ed..e3f9120 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/data_render/vnode/android/conversion.h
@@ -16,19 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
+#ifdef OS_ANDROID
-#include "core/data_render/vnode/vnode_render_context.h"
+#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);
+};
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
-
-VNodeRenderContext::~VNodeRenderContext() {}
-
-void VNodeRenderContext::Reset() { root_ = nullptr; }
} // namespace data_render
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // 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 0000000..cc707fb
--- /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 0000000..a8229da
--- /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 0000000..d47303f
--- /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 0000000..7a7fcb7
--- /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 f885cc7..c4243dc 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 884148c..927a3a4 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/vnode_render_context.cc b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h
similarity index 57%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h
index 3f6c6ed..3cd6c71 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h
@@ -17,18 +17,25 @@
* under the License.
*/
-#include "core/data_render/vnode/vnode_render_context.h"
+#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 {
-
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
-
-VNodeRenderContext::~VNodeRenderContext() {}
-
-void VNodeRenderContext::Reset() { root_ = nullptr; }
+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
\ No newline at end of file
+} // 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 d34cfc7..219ca1c 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 bcc09e3..8cda5e5 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 7fe2edc..e2d3fe4 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_render_context.cc b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h
similarity index 65%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h
index 3f6c6ed..3c974ab 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h
@@ -17,18 +17,23 @@
* under the License.
*/
-#include "core/data_render/vnode/vnode_render_context.h"
+#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 {
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
-
-VNodeRenderContext::~VNodeRenderContext() {}
+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);
+};
-void VNodeRenderContext::Reset() { root_ = nullptr; }
} // namespace data_render
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // 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 3f6c6ed..158e7ea 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 b0a760a..456b1b5 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 eb016cb..9736d4b 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 85cb3b8..cf33330 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 0000000..f44dc59
--- /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/data_render/string_table.h b/weex_core/Source/core/network/android/default_request_handler.h
similarity index 52%
copy from weex_core/Source/core/data_render/string_table.h
copy to weex_core/Source/core/network/android/default_request_handler.h
index 5d1dddd..cf1f556 100644
--- a/weex_core/Source/core/data_render/string_table.h
+++ b/weex_core/Source/core/network/android/default_request_handler.h
@@ -16,46 +16,41 @@
* specific language governing permissions and limitations
* under the License.
*/
+#if OS_ANDROID
-#ifndef CORE_DATA_RENDER_STRING_TABLE_H
-#define CORE_DATA_RENDER_STRING_TABLE_H
+#ifndef CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+#define CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
-#include <memory>
-#include <string>
-#include <map>
-#include <vector>
+#include <jni.h>
+#include "android/wrap/jni_object_wrap.h"
+#include "core/network/request_handler.h"
namespace weex {
namespace core {
-namespace data_render {
-class String {
- public:
- explicit String(const char *str, std::size_t len);
- explicit String(const std::string &str);
- ~String();
-
- char *c_str() { return str_.get(); }
+namespace network {
- std::size_t length() { return length_; }
-
- private:
- std::unique_ptr<char[]> str_;
- size_t length_;
+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 StringTable {
+class CallbackWrapper {
public:
- StringTable() : store_() {}
- ~StringTable();
-
- String *StringFromUTF8(const std::string &str);
- inline const std::vector<std::pair<std::string, std::unique_ptr<String>>>& store() {return store_;}
+ CallbackWrapper(Callback callback) : callback_(callback) {}
+ ~CallbackWrapper() {}
+ void Invoke(const std::string& result) { callback_(result); }
private:
- std::vector<std::pair<std::string, std::unique_ptr<String>>> store_;
+ Callback callback_;
};
-} // namespace data_render
+
+} // namespace network
} // namespace core
} // namespace weex
-
-#endif // CORE_DATA_RENDER_STRING_TABLE_H
+#endif // CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
+#endif
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/network/http_module.cc
similarity index 63%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/network/http_module.cc
index 3f6c6ed..200952f 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/network/http_module.cc
@@ -16,19 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-#include "core/data_render/vnode/vnode_render_context.h"
+#include "core/network/http_module.h"
+#include "core/network/request_handler.h"
namespace weex {
namespace core {
-namespace data_render {
+namespace network {
+
+HttpModule::HttpModule()
+ : request_handler_(RequestHandler::CreateDefaultHandler()) {}
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+HttpModule::HttpModule(RequestHandler* request_handler)
+ : request_handler_(request_handler) {}
-VNodeRenderContext::~VNodeRenderContext() {}
+void HttpModule::Send(const char* instance_id, const char* url,
+ Callback callback) {
+ request_handler_->Send(instance_id, url, callback);
+}
-void VNodeRenderContext::Reset() { root_ = nullptr; }
-} // namespace data_render
+} // namespace network
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // namespace weex
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/network/http_module.h
similarity index 66%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/network/http_module.h
index 3f6c6ed..4c4b579 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/network/http_module.h
@@ -17,18 +17,25 @@
* under the License.
*/
-#include "core/data_render/vnode/vnode_render_context.h"
+#ifndef CORE_NETWORK_HTTP_MODULE_
+#define CORE_NETWORK_HTTP_MODULE_
+#include "core/network/request_handler.h"
namespace weex {
namespace core {
-namespace data_render {
+namespace network {
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+class HttpModule {
+ public:
+ HttpModule();
+ HttpModule(RequestHandler* request_handler);
+ void Send(const char* instance_id, const char* url, Callback callback);
-VNodeRenderContext::~VNodeRenderContext() {}
+ private:
+ std::unique_ptr<RequestHandler> request_handler_;
+};
-void VNodeRenderContext::Reset() { root_ = nullptr; }
-} // namespace data_render
+} // namespace network
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // namespace weex
+#endif // CORE_NETWORK_HTTP_MODULE_
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/network/ios/default_request_handler.h
similarity index 64%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/network/ios/default_request_handler.h
index 3f6c6ed..2099d53 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/network/ios/default_request_handler.h
@@ -17,18 +17,24 @@
* under the License.
*/
-#include "core/data_render/vnode/vnode_render_context.h"
+#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 data_render {
-
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+namespace network {
-VNodeRenderContext::~VNodeRenderContext() {}
+class DefaultRequestHandler : public RequestHandler {
+ public:
+ DefaultRequestHandler();
+ ~DefaultRequestHandler() override;
+ void Send(const char* instance_id, const char* url,
+ Callback callback) override;
+};
-void VNodeRenderContext::Reset() { root_ = nullptr; }
-} // namespace data_render
+} // namespace network
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // namespace weex
+#endif // CORE_NETWORK_DEFAULT_REQUEST_HANDLER_H
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/network/ios/default_request_handler.mm
similarity index 53%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/network/ios/default_request_handler.mm
index 3f6c6ed..11f12f2 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/network/ios/default_request_handler.mm
@@ -16,19 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-#include "core/data_render/vnode/vnode_render_context.h"
+#include "core/network/ios/default_request_handler.h"
+#import "WXConvertUtility.h"
+#import "WXSDKManager.h"
namespace weex {
namespace core {
-namespace data_render {
+namespace network {
+ DefaultRequestHandler::DefaultRequestHandler() {}
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+ DefaultRequestHandler::~DefaultRequestHandler() {}
-VNodeRenderContext::~VNodeRenderContext() {}
+ 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]);
+ }];
+ }
-void VNodeRenderContext::Reset() { root_ = nullptr; }
-} // namespace data_render
-} // namespace core
-} // namespace weex
\ No newline at end of file
+ RequestHandler* RequestHandler::CreateDefaultHandler() {
+ return new DefaultRequestHandler();
+ }
+}
+}
+}
diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/network/request_handler.h
similarity index 62%
copy from weex_core/Source/core/data_render/vnode/vnode_render_context.cc
copy to weex_core/Source/core/network/request_handler.h
index 3f6c6ed..66a4a87 100644
--- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc
+++ b/weex_core/Source/core/network/request_handler.h
@@ -17,18 +17,26 @@
* under the License.
*/
-#include "core/data_render/vnode/vnode_render_context.h"
+#ifndef CORE_NETWORK_REQUEST_HANDLER_H
+#define CORE_NETWORK_REQUEST_HANDLER_H
+#include <functional>
+#include <memory>
namespace weex {
namespace core {
-namespace data_render {
+namespace network {
+typedef std::function<void(const std::string&)> Callback;
-VNodeRenderContext::VNodeRenderContext()
- : page_id_(), root_(nullptr), raw_json_(), script_() {}
+class RequestHandler {
+ public:
+ RequestHandler() {}
+ virtual ~RequestHandler() {}
+ virtual void Send(const char* instance_id, const char* url,
+ Callback callback) = 0;
+ static RequestHandler* CreateDefaultHandler();
+};
-VNodeRenderContext::~VNodeRenderContext() {}
-
-void VNodeRenderContext::Reset() { root_ = nullptr; }
-} // namespace data_render
+} // namespace network
} // namespace core
-} // namespace weex
\ No newline at end of file
+} // 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 9470cf4..53b5ef6 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 af143d0..02a0196 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