YorkShen closed pull request #1600: [core][Android] fix thread block when 
nested sync method to JSS in JS…
URL: https://github.com/apache/incubator-weex/pull/1600
 
 
   

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

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

diff --git a/android/sdk/libs/armeabi-v7a/libweexcore.so 
b/android/sdk/libs/armeabi-v7a/libweexcore.so
index c5a1c68d56..dcd049243e 100644
Binary files a/android/sdk/libs/armeabi-v7a/libweexcore.so and 
b/android/sdk/libs/armeabi-v7a/libweexcore.so differ
diff --git a/android/sdk/libs/armeabi/libweexcore.so 
b/android/sdk/libs/armeabi/libweexcore.so
index 86e8bb37ba..602f9b7483 100644
Binary files a/android/sdk/libs/armeabi/libweexcore.so and 
b/android/sdk/libs/armeabi/libweexcore.so differ
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallback.java 
b/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallback.java
new file mode 100644
index 0000000000..368a5b1bef
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallback.java
@@ -0,0 +1,23 @@
+/**
+ * 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;
+
+public interface ResultCallback<T> {
+    void onReceiveResult(T result);
+}
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallbackManager.java 
b/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallbackManager.java
new file mode 100644
index 0000000000..59475be914
--- /dev/null
+++ 
b/android/sdk/src/main/java/com/taobao/weex/bridge/ResultCallbackManager.java
@@ -0,0 +1,48 @@
+/**
+ * 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.util.SparseArray;
+
+/**
+ * Manage async callbacks which waiting for the result of executing javascript
+ */
+/* default */ class ResultCallbackManager {
+    // Unique id for callback after executing js
+    private static long sCallbackId = 0;
+    // Map for save callbacks, key is id
+    private static SparseArray<ResultCallback> mResultCallbacks = new 
SparseArray<>();
+
+    // Generate unique id
+    static long generateCallbackId(ResultCallback callback) {
+        if (sCallbackId >= Integer.MAX_VALUE) {
+            sCallbackId = 0;
+        }
+        int id = (int) sCallbackId++;
+        mResultCallbacks.put(id, callback);
+        return id;
+    }
+
+    // Remove id from callback map
+    static ResultCallback removeCallbackById(long id) {
+        ResultCallback callback = mResultCallbacks.get((int) id);
+        mResultCallbacks.remove((int) id);
+        return callback;
+    }
+}
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 a60917e093..28ffa3b4ed 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
@@ -19,6 +19,7 @@
 package com.taobao.weex.bridge;
 
 import android.util.Log;
+
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -60,6 +61,7 @@
   private native int nativeExecJSService(String javascript);
 
   public native byte[] nativeExecJSWithResult(String instanceId, String 
_namespace, String _function, WXJSObject[] args);
+  public native void nativeExecJSWithCallback(String instanceId, String 
_namespace, String _function, WXJSObject[] args, long callbackId);
 
   public native int nativeCreateInstanceContext(String instanceId, String 
name, String function, WXJSObject[] args);
 
@@ -138,8 +140,21 @@ public int execJS(String instanceId, String namespace, 
String function, WXJSObje
   }
 
   @Override
-  public byte[] execJSWithResult(String instanceId, String namespace, String 
function, WXJSObject[] args) {
-    return nativeExecJSWithResult(instanceId, namespace, function, args);
+  public void execJSWithCallback(String instanceId, String namespace, String 
function, WXJSObject[] args, ResultCallback callback) {
+    if (callback == null) {
+      execJS(instanceId, namespace, function, args);
+    }
+    nativeExecJSWithCallback(instanceId, namespace, function, args,
+            ResultCallbackManager.generateCallbackId(callback));
+  }
+
+  // Result from js engine
+  @CalledByNative
+  public void onReceivedResult(long callbackId, byte[] result) {
+    ResultCallback callback = 
ResultCallbackManager.removeCallbackById(callbackId);
+    if (callback != null) {
+       callback.onReceiveResult(result);
+    }
   }
 
   @Override
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 50b21f87af..8189237211 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
@@ -999,20 +999,21 @@ public void run() {
           WXJSObject[] jsArgs = {
                   new WXJSObject(WXJSObject.String, instanceId),
                   WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)};
-          byte[] taskResult = 
invokeExecJSWithResult(String.valueOf(instanceId), null, METHOD_CALL_JS, 
jsArgs, true);
-          if(eventCallback == null){
-            return;
-          }
-          if(taskResult != null){
-            JSONArray arrayResult = (JSONArray) 
WXWsonJSONSwitch.parseWsonOrJSON(taskResult);
-            if(arrayResult != null && arrayResult.size() > 0){
-              result = arrayResult.get(0);
-            }
+          ResultCallback<byte[]> resultCallback = null;
+          if (eventCallback != null) {
+            resultCallback = new ResultCallback<byte[]>() {
+              @Override
+              public void onReceiveResult(byte[] result) {
+                JSONArray arrayResult = (JSONArray) 
WXWsonJSONSwitch.parseWsonOrJSON(result);
+                if(arrayResult != null && arrayResult.size() > 0){
+                  eventCallback.onCallback(arrayResult.get(0));
+                }
+              }
+            };
           }
-          eventCallback.onCallback(result);
+          invokeExecJSWithCallback(String.valueOf(instanceId), null, 
METHOD_CALL_JS,
+                  jsArgs, resultCallback, true);
           jsArgs[0] = null;
-          taskResult = null;
-          jsArgs = null;
         }catch (Exception e){
           WXLogUtils.e("asyncCallJSEventWithResult" , e);
         }
@@ -1741,8 +1742,8 @@ private String invokeExecJSOnInstance(String instanceId, 
String js, int type) {
     return null;
   }
 
-  private byte[] invokeExecJSWithResult(String instanceId, String namespace, 
String function,
-                                        WXJSObject[] args,boolean 
logTaskDetail){
+  private void invokeExecJSWithCallback(String instanceId, String namespace, 
String function,
+                                        WXJSObject[] args , ResultCallback 
callback, boolean logTaskDetail){
     if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) {
       mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
               .append("function:").append(function);
@@ -1753,9 +1754,8 @@ private String invokeExecJSOnInstance(String instanceId, 
String js, int type) {
       mLodBuilder.setLength(0);
     }
     if (isJSFrameworkInit()) {
-      return mWXBridge.execJSWithResult(instanceId, namespace, function, args);
+      mWXBridge.execJSWithCallback(instanceId, namespace, function, args, 
callback);
     }
-    return null;
   }
 
   public @NonNull static String argsToJSON(WXJSObject[] args) {
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 130e8795e1..20f53465ac 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
@@ -20,6 +20,7 @@
 
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.base.CalledByNative;
+import com.taobao.weex.bridge.ResultCallback;
 import com.taobao.weex.bridge.WXBridgeManager;
 import com.taobao.weex.bridge.WXJSObject;
 import com.taobao.weex.bridge.WXParams;
@@ -63,9 +64,9 @@
   int execJS(String instanceId, String namespace, String function, 
WXJSObject[] args);
 
   /**
-   * execute javascript function, return execute result as json array
+   * execute javascript function with asynchronous callback
    */
-  byte[] execJSWithResult(String instanceId, String namespace, String 
function, WXJSObject[] args);
+  void execJSWithCallback(String instanceId, String namespace, String 
function, WXJSObject[] args, ResultCallback callback);
 
   int execJSService(String javascript);
 
diff --git a/weex_core/Source/IPC/IPCMessageJS.h 
b/weex_core/Source/IPC/IPCMessageJS.h
index 5a8a86eee8..ec0ecf2683 100644
--- a/weex_core/Source/IPC/IPCMessageJS.h
+++ b/weex_core/Source/IPC/IPCMessageJS.h
@@ -33,6 +33,7 @@ enum class IPCJSMsg {
     DESTORYINSTANCE,
     EXECJSONINSTANCE,
     EXECJSWITHRESULT,
+    EXECJSWITHCALLBACK,
     UPDATEGLOBALCONFIG,
     EXECTIMERCALLBACK,
        INITAPPFRAMEWORK,
@@ -68,6 +69,7 @@ enum class IPCProxyMsg {
     CLEARINTERVAL,
        POSTMESSAGE,
        DISPATCHMESSAGE,
+       ONRECEIVEDRESULT,
 };
 // Message from Script to Core in ScriptBridge
 
diff --git a/weex_core/Source/android/bridge/platform/android_side.cpp 
b/weex_core/Source/android/bridge/platform/android_side.cpp
index f7c198a802..bce1656c15 100644
--- a/weex_core/Source/android/bridge/platform/android_side.cpp
+++ b/weex_core/Source/android/bridge/platform/android_side.cpp
@@ -363,6 +363,11 @@ void AndroidSide::DispatchMessage(const char *client_id,
   wml_bridge_->DispatchMessage(env, client_id,  data, dataLength, callback, 
vm_id);
 }
 
+void AndroidSide::OnReceivedResult(long callback_id, 
std::unique_ptr<WeexJSResult>& result) {
+  JNIEnv *env = base::android::AttachCurrentThread();
+  wx_bridge_->OnReceivedResult(env, callback_id,  result);
+}
+
 jobject AndroidSide::getMeasureFunc(const char *pageId, jlong renderObjectPtr) 
{
   JNIEnv *env = base::android::AttachCurrentThread();
   return wx_bridge_->GetMeasureFunc(env, pageId, renderObjectPtr).Release();
diff --git a/weex_core/Source/android/bridge/platform/android_side.h 
b/weex_core/Source/android/bridge/platform/android_side.h
index 3f1117226c..53fc0b2a6f 100644
--- a/weex_core/Source/android/bridge/platform/android_side.h
+++ b/weex_core/Source/android/bridge/platform/android_side.h
@@ -109,6 +109,7 @@ class AndroidSide : public PlatformBridge::PlatformSide {
   void PostMessage(const char* vm_id, const char* data, int dataLength) 
override;
   void DispatchMessage(const char* client_id,
                        const char* data, int dataLength, const char* callback, 
const char* vm_id) override;
+  void OnReceivedResult(long callback_id, std::unique_ptr<WeexJSResult>& 
result) override;
 
   jobject getMeasureFunc(const char* pageId, jlong renderObjectPtr);
 
diff --git 
a/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp 
b/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp
index d4c8240018..19ecd997cf 100644
--- a/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp
+++ b/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp
@@ -391,6 +391,46 @@ std::unique_ptr<WeexJSResult> 
ScriptSideInMultiProcess::ExecJSWithResult(
   }
 }
 
+void ScriptSideInMultiProcess::ExecJSWithCallback(
+    const char *instanceId, const char *nameSpace, const char *func,
+    std::vector<VALUE_WITH_TYPE *> &params, long callback_id) {
+    std::unique_ptr<WeexJSResult> ret;
+  try {
+    if(sender_ == nullptr) {
+      LOGE("ExecJSWithResult sender is null");
+      return;
+    }
+    std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+    serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSWITHCALLBACK));
+    serializer->add(instanceId, strlen(instanceId));
+    if (nameSpace)
+      serializer->add(nameSpace, strlen(nameSpace));
+    else {
+      uint16_t tmp = 0;
+      serializer->add(&tmp, 0);
+    }
+    serializer->add(func, strlen(func));
+    // pass callback_id before params
+    serializer->add(static_cast<int64_t>(callback_id));
+
+    for (int i = 0; i < params.size(); i++) {
+      VALUE_WITH_TYPE *param = params[i];
+      addParamsToIPCSerializer(serializer.get(), param);
+    }
+
+    std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+    std::unique_ptr<IPCResult> result = sender_->send(buffer.get());
+
+  } catch (IPCException &e) {
+    LOGE("%s", e.msg());
+    // report crash here
+    WeexCoreManager::Instance()
+        ->getPlatformBridge()
+        ->platform_side()
+        ->ReportServerCrash(instanceId);
+  }
+}
+
 int ScriptSideInMultiProcess::CreateInstance(
     const char *instanceId, const char *func, const char *script,
     const char *opts, const char *initData, const char *extendsApi) {
diff --git 
a/weex_core/Source/android/bridge/script/script_side_in_multi_process.h 
b/weex_core/Source/android/bridge/script/script_side_in_multi_process.h
index 8d7e71e8a7..24d243a2c7 100644
--- a/weex_core/Source/android/bridge/script/script_side_in_multi_process.h
+++ b/weex_core/Source/android/bridge/script/script_side_in_multi_process.h
@@ -55,6 +55,11 @@ class ScriptSideInMultiProcess : public 
ScriptBridge::ScriptSide {
                                 const char *func,
                                 std::vector<VALUE_WITH_TYPE *> &params) 
override;
 
+  void ExecJSWithCallback(const char *instanceId, const char *nameSpace,
+                          const char *func,
+                          std::vector<VALUE_WITH_TYPE *> &params,
+                          long callback_id) override;
+
   int CreateInstance(const char *instanceId, const char *func,
                      const char *script, const char *opts, const char 
*initData,
                      const char *extendsApi) override;
diff --git a/weex_core/Source/android/bridge/script/script_side_in_multi_so.cpp 
b/weex_core/Source/android/bridge/script/script_side_in_multi_so.cpp
index f5a29e9ccd..02f063b1b8 100644
--- a/weex_core/Source/android/bridge/script/script_side_in_multi_so.cpp
+++ b/weex_core/Source/android/bridge/script/script_side_in_multi_so.cpp
@@ -125,6 +125,18 @@ std::unique_ptr<WeexJSResult> 
ScriptSideInMultiSo::ExecJSWithResult(
                                                      func, params);
 }
 
+void ScriptSideInMultiSo::ExecJSWithCallback(
+    const char *instanceId, const char *nameSpace, const char *func,
+    std::vector<VALUE_WITH_TYPE *> &params, long callback_id) {
+  if (script_side_functions_ == nullptr) {
+    LOGE(
+        "ScriptSideInMultiSo::ExecJSWithCallback script_side_functions_ is 
null");
+    return;
+  }
+  script_side_functions_->funcExeJSWithResultId(instanceId, nameSpace, func,
+                                                params, callback_id);
+}
+
 int ScriptSideInMultiSo::CreateInstance(const char *instanceId,
                                         const char *func, const char *script,
                                         const char *opts, const char *initData,
diff --git a/weex_core/Source/android/bridge/script/script_side_in_multi_so.h 
b/weex_core/Source/android/bridge/script/script_side_in_multi_so.h
index 781b3ff1f2..87ed718315 100644
--- a/weex_core/Source/android/bridge/script/script_side_in_multi_so.h
+++ b/weex_core/Source/android/bridge/script/script_side_in_multi_so.h
@@ -54,6 +54,11 @@ class ScriptSideInMultiSo : public ScriptBridge::ScriptSide {
                                 const char *func,
                                 std::vector<VALUE_WITH_TYPE *> &params) 
override;
 
+  void ExecJSWithCallback(const char *instanceId, const char *nameSpace,
+                          const char *func,
+                          std::vector<VALUE_WITH_TYPE *> &params,
+                          long callback_id) override;
+
   int CreateInstance(const char *instanceId, const char *func,
                      const char *script, const char *opts, const char 
*initData,
                      const char *extendsApi) override;
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 907162663a..7888f31111 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
@@ -906,6 +906,31 @@ std::unique_ptr<IPCResult> 
HandleDispatchMessage(IPCArguments *arguments) {
   return createInt32Result(static_cast<int32_t>(true));
 }
 
+std::unique_ptr<IPCResult> OnReceivedResult(IPCArguments *arguments) {
+  long callback_id = arguments->get<long>(0);
+  std::unique_ptr<WeexJSResult> result;
+  result.reset(new WeexJSResult);
+  if (arguments->getType(1) == IPCType::BYTEARRAY &&
+      arguments->getByteArray(1)->length > 0) {
+    result->length = arguments->getByteArray(1)->length;
+    char *string = new char[result->length + 1];
+    result->data.reset(string);
+    memset(string, 0, result->length);
+    memcpy(string, arguments->getByteArray(1)->content, result->length);
+    string[result->length] = '\0';
+  }
+  WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
+      weex::base::MakeCopyable([callback_id, result = std::move(result)]() {
+        WeexCoreManager::Instance()
+            ->script_bridge()
+            ->core_side()
+            ->OnReceivedResult(
+                callback_id,
+                const_cast<std::unique_ptr<WeexJSResult> &>(result));
+      }));
+  return createInt32Result(static_cast<int32_t>(true));
+}
+
 ScriptBridgeInMultiProcess::ScriptBridgeInMultiProcess() {
   set_script_side(new bridge::script::ScriptSideInMultiProcess);
   set_core_side(new CoreSideInScript);
@@ -995,6 +1020,8 @@ void 
ScriptBridgeInMultiProcess::RegisterIPCCallback(IPCHandler *handler) {
                            HandlePostMessage);
   handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::DISPATCHMESSAGE),
                            HandleDispatchMessage);
+  
handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::ONRECEIVEDRESULT),
+                           OnReceivedResult);
 }
 
 }  // 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 03b6e141f2..685f69f3a6 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
@@ -442,6 +442,20 @@ static void DispatchMessage(const char *client_id, const 
char *data, int dataLen
                                   callback.c_str(), vm_id.c_str());
           }));
 }
+
+static void OnReceivedResult(long callback_id,
+                             std::unique_ptr<WeexJSResult> &result) {
+  WeexCoreManager::Instance()->script_thread()->message_loop()->PostTask(
+      weex::base::MakeCopyable([callback_id, result = std::move(result)]() {
+        WeexCoreManager::Instance()
+            ->script_bridge()
+            ->core_side()
+            ->OnReceivedResult(
+                callback_id,
+                const_cast<std::unique_ptr<WeexJSResult> &>(result));
+      }));
+}
+
 static void ReportException(const char *page_id, const char *func,
                             const char *exception_string) {
   //  
WeexCoreManager::Instance()->script_bridge()->core_side()->ReportException(
@@ -491,7 +505,8 @@ FunctionsExposedByCore 
*ScriptBridgeInMultiSo::GetExposedFunctions() {
                                  CallGCanvasLinkNative,
                                  CallT3DLinkNative,
                                  PostMessage,
-                                 DispatchMessage};
+                                 DispatchMessage,
+                                 OnReceivedResult};
   auto functions =
       (FunctionsExposedByCore *)malloc(sizeof(FunctionsExposedByCore));
   memset(functions, 0, sizeof(FunctionsExposedByCore));
diff --git a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h 
b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
index e973cc713d..46da177daa 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -16,11 +16,14 @@
 //#include "base/android/jni_int_wrapper.h"
 
 // Step 1: forward declarations.
+namespace {
 const char kWXBridgeClassPath[] = "com/taobao/weex/bridge/WXBridge";
 // Leaking this jclass as we cannot use LazyInstance from some threads.
 jclass g_WXBridge_clazz = NULL;
 #define WXBridge_clazz(env) g_WXBridge_clazz
 
+}  // namespace
+
 static jint InitFrameworkEnv(JNIEnv* env, jobject jcaller,
     jstring framework,
     jobject params,
@@ -46,11 +49,12 @@ static jint ExecJS(JNIEnv* env, jobject jcaller,
 static jint ExecJSService(JNIEnv* env, jobject jcaller,
     jstring javascript);
 
-static jbyteArray ExecJSWithResult(JNIEnv* env, jobject jcaller,
+static void ExecJSWithCallback(JNIEnv* env, jobject jcaller,
     jstring instanceId,
     jstring _namespace,
     jstring _function,
-    jobjectArray args);
+    jobjectArray args,
+    jlong callbackId);
 
 static jint CreateInstanceContext(JNIEnv* env, jobject jcaller,
     jstring instanceId,
@@ -156,6 +160,32 @@ static void UpdateGlobalConfig(JNIEnv* env, jobject 
jcaller,
 
 // Step 2: method stubs.
 
+static intptr_t g_WXBridge_onReceivedResult = 0;
+static void Java_WXBridge_onReceivedResult(JNIEnv* env, jobject obj, jlong
+    callbackId,
+    jbyteArray result) {
+  /* Must call RegisterNativesImpl()  */
+  //CHECK_CLAZZ(env, obj,
+  //    WXBridge_clazz(env));
+  jmethodID method_id =
+      base::android::GetMethod(
+      env, WXBridge_clazz(env),
+      base::android::INSTANCE_METHOD,
+      "onReceivedResult",
+
+"("
+"J"
+"[B"
+")"
+"V",
+      &g_WXBridge_onReceivedResult);
+
+     env->CallVoidMethod(obj,
+          method_id, callbackId, result);
+  base::android::CheckException(env);
+
+}
+
 static intptr_t g_WXBridge_callNative = 0;
 static jint Java_WXBridge_callNative(JNIEnv* env, jobject obj, jstring
     instanceId,
@@ -923,14 +953,15 @@ static const JNINativeMethod kMethodsWXBridge[] = {
 "Ljava/lang/String;"
 ")"
 "I", reinterpret_cast<void*>(ExecJSService) },
-    { "nativeExecJSWithResult",
+    { "nativeExecJSWithCallback",
 "("
 "Ljava/lang/String;"
 "Ljava/lang/String;"
 "Ljava/lang/String;"
 "[Lcom/taobao/weex/bridge/WXJSObject;"
+"J"
 ")"
-"[B", reinterpret_cast<void*>(ExecJSWithResult) },
+"V", reinterpret_cast<void*>(ExecJSWithCallback) },
     { "nativeCreateInstanceContext",
 "("
 "Ljava/lang/String;"
@@ -1100,16 +1131,11 @@ static bool RegisterNativesImpl(JNIEnv* env) {
   return true;
 }
 
-
-
 static void Java_WXBridge_reset_clazz(JNIEnv* env, const char* className) {
     LOGE("Java_WXBridge_reset_clazz class Name is %s", className);
     g_WXBridge_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
-            base::android::GetClass(env, className).Get()));
-
-
-
-    g_WXBridge_callNative = 0;
+                    base::android::GetClass(env, className).Get()));
+                            g_WXBridge_callNative = 0;
     g_WXBridge_reportJSException = 0;
     g_WXBridge_callNativeModule = 0;
     g_WXBridge_callNativeComponent = 0;
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp 
b/weex_core/Source/android/wrap/wx_bridge.cpp
index 9108b1b320..a97d927388 100644
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -422,12 +422,15 @@ static jint ExecJS(JNIEnv* env, jobject jthis, jstring 
jinstanceid,
   return result;
 }
 
-static jbyteArray ExecJSWithResult(JNIEnv* env, jobject jcaller,
-                                   jstring instanceId, jstring _namespace,
-                                   jstring _function, jobjectArray args) {
+static void ExecJSWithCallback(JNIEnv* env, jobject jcaller,
+                             jstring instanceId,
+                             jstring _namespace,
+                             jstring _function,
+                             jobjectArray args,
+                             jlong callbackId) {
   if (_function == NULL || instanceId == NULL) {
     LOGE("native_execJS function is NULL");
-    return NULL;
+    return;
   }
   ScopedJStringUTF8 instance_id(env, instanceId);
   ScopedJStringUTF8 name_space(env, _namespace);
@@ -444,27 +447,19 @@ static jbyteArray ExecJSWithResult(JNIEnv* env, jobject 
jcaller,
     param = getValueWithTypePtr();
 
     auto wx_js_object = std::unique_ptr<WXJSObject>(
-        new WXJSObject(env, base::android::ScopedLocalJavaRef<jobject>(
-            env, env->GetObjectArrayElement(args, i))
-            .Get()));
+            new WXJSObject(env, base::android::ScopedLocalJavaRef<jobject>(
+                    env, env->GetObjectArrayElement(args, i))
+                    .Get()));
     addParamsFromJArgs(params, param, env, wx_js_object);
   }
 
-  auto result =
-      WeexCoreManager::Instance()
-          ->getPlatformBridge()
-          ->core_side()
-          ->ExecJSWithResult(instance_id.getChars(), name_space.getChars(),
-                             function.getChars(), params);
-
-  if (result.get() == nullptr || result->data.get() == nullptr)
-    return nullptr;
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->core_side()
+      ->ExecJSWithCallback(instance_id.getChars(), name_space.getChars(),
+                           function.getChars(), params, callbackId);
 
-  jbyteArray array = env->NewByteArray(result->length);
-  env->SetByteArrayRegion(array, 0, result->length,
-                          reinterpret_cast<const jbyte*>(result->data.get()));
   freeParams(params);
-  return array;
 }
 
 static void UpdateGlobalConfig(JNIEnv* env, jobject jcaller, jstring config) {
@@ -1050,9 +1045,23 @@ void WXBridge::ReportNativeInitStatus(JNIEnv* env, const 
char* statusCode,
                                        jni_error_msg.Get());
 }
 
+
+void WXBridge::OnReceivedResult(JNIEnv *env, long callback_id,
+                                std::unique_ptr<WeexJSResult>& result) {
+
+  auto array = base::android::ScopedLocalJavaRef<jbyteArray>();
+  if (result != nullptr && result->length != 0) {
+    array.Reset(env, env->NewByteArray(result->length));
+    env->SetByteArrayRegion(array.Get(), 0, result->length,
+                            reinterpret_cast<const 
jbyte*>(result->data.get()));
+  }
+  Java_WXBridge_onReceivedResult(env, jni_object(), callback_id, array.Get());
+
+}
+
 void WXBridge::reset_clazz(JNIEnv* env, const char* className) {
   LOGE("class Name is %s", className);
   Java_WXBridge_reset_clazz(env, className);
 }
 
-}  // namespace WeexCore
\ No newline at end of file
+}  // namespace WeexCore
diff --git a/weex_core/Source/android/wrap/wx_bridge.h 
b/weex_core/Source/android/wrap/wx_bridge.h
index 1fa7a12469..c7dfcc8eee 100644
--- a/weex_core/Source/android/wrap/wx_bridge.h
+++ b/weex_core/Source/android/wrap/wx_bridge.h
@@ -28,6 +28,7 @@
 #include "android/base/jni/scoped_java_ref.h"
 #include "android/wrap/jni_object_wrap.h"
 #include "base/common.h"
+#include "include/WeexApiHeader.h"
 
 namespace WeexCore {
 class WXCoreMargin;
@@ -103,6 +104,8 @@ class WXBridge : public JNIObjectWrap {
                          const char *info);
   void ReportNativeInitStatus(JNIEnv *env, const char *statusCode,
                               const char *errorMsg);
+  void OnReceivedResult(JNIEnv *env, long callback_id,
+                        std::unique_ptr<WeexJSResult> &result);
 
   void reset_clazz(JNIEnv* env, const char* className);
  private:
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 3ada98ae48..a35ac01ecb 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
@@ -412,6 +412,15 @@ std::unique_ptr<WeexJSResult> 
CoreSideInPlatform::ExecJSWithResult(
       ->ExecJSWithResult(instanceId, nameSpace, func, params);
 }
 
+void CoreSideInPlatform::ExecJSWithCallback(
+    const char *instanceId, const char *nameSpace, const char *func,
+    std::vector<VALUE_WITH_TYPE *> &params, long callback_id) {
+  WeexCoreManager::Instance()
+      ->script_bridge()
+      ->script_side()
+      ->ExecJSWithCallback(instanceId, nameSpace, func, params, callback_id);
+}
+
 int CoreSideInPlatform::CreateInstance(const char *instanceId, const char 
*func,
                                        const char *script, int script_length,
                                        const char *opts,
diff --git a/weex_core/Source/core/bridge/platform/core_side_in_platform.h 
b/weex_core/Source/core/bridge/platform/core_side_in_platform.h
index 87b762a13a..490c7d9817 100644
--- a/weex_core/Source/core/bridge/platform/core_side_in_platform.h
+++ b/weex_core/Source/core/bridge/platform/core_side_in_platform.h
@@ -91,6 +91,10 @@ class CoreSideInPlatform : public PlatformBridge::CoreSide {
   std::unique_ptr<WeexJSResult> ExecJSWithResult(
       const char *instanceId, const char *nameSpace, const char *func,
       std::vector<VALUE_WITH_TYPE *> &params) override;
+  void ExecJSWithCallback(const char *instanceId, const char *nameSpace,
+                          const char *func,
+                          std::vector<VALUE_WITH_TYPE *> &params,
+                          long callback_id) override;
   int CreateInstance(const char *instanceId, const char *func,
                      const char *script, int script_length, const char *opts, 
const char *initData,
                      const char *extendsApi, const char* render_strategy) 
override;
diff --git a/weex_core/Source/core/bridge/platform_bridge.h 
b/weex_core/Source/core/bridge/platform_bridge.h
index 63152f624c..9792258fe2 100644
--- a/weex_core/Source/core/bridge/platform_bridge.h
+++ b/weex_core/Source/core/bridge/platform_bridge.h
@@ -113,6 +113,10 @@ class PlatformBridge {
     virtual std::unique_ptr<WeexJSResult> ExecJSWithResult(
         const char* instanceId, const char* nameSpace, const char* func,
         std::vector<VALUE_WITH_TYPE*>& params) = 0;
+    virtual void ExecJSWithCallback(const char* instanceId,
+                                    const char* nameSpace, const char* func,
+                                    std::vector<VALUE_WITH_TYPE*>& params,
+                                    long callback_id) = 0;
     virtual int CreateInstance(const char* instanceId, const char* func,
                                const char* script, int script_length, const 
char* opts,
                                const char* initData, const char* extendsApi,
@@ -224,6 +228,8 @@ class PlatformBridge {
     virtual void PostMessage(const char* vm_id, const char* data, int 
dataLength) = 0;
     virtual void DispatchMessage(const char* client_id,
                                  const char* data, int dataLength, const char* 
callback, const char* vm_id) = 0;
+    virtual void OnReceivedResult(long callback_id,
+                                  std::unique_ptr<WeexJSResult>& result) = 0;
 
     inline PlatformBridge* bridge() { return bridge_; }
 
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 0e644be02c..128b50927d 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
@@ -451,4 +451,12 @@ void CoreSideInScript::SetJSVersion(const char 
*js_version) {
       ->platform_side()
       ->SetJSVersion(js_version);
 }
+
+void CoreSideInScript::OnReceivedResult(long callback_id,
+                                        std::unique_ptr<WeexJSResult> &result) 
{
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->OnReceivedResult(callback_id, result);
+}
 }  // 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 9b20650756..6c872d9c2b 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
@@ -74,6 +74,8 @@ class CoreSideInScript : public ScriptBridge::CoreSide {
   void ReportException(const char *page_id, const char *func,
                        const char *exception_string) override;
   void SetJSVersion(const char *js_version) override;
+  void OnReceivedResult(long callback_id,
+                        std::unique_ptr<WeexJSResult> &result) 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 5d7bd76d0d..d7df29bd5f 100644
--- a/weex_core/Source/core/bridge/script_bridge.h
+++ b/weex_core/Source/core/bridge/script_bridge.h
@@ -79,6 +79,8 @@ class ScriptBridge {
     virtual void ReportException(const char *page_id, const char *func,
                                  const char *exception_string) = 0;
     virtual void SetJSVersion(const char *js_version) = 0;
+    virtual void OnReceivedResult(long callback_id,
+                                  std::unique_ptr<WeexJSResult> &result) = 0;
 
     inline ScriptBridge *bridge() { return bridge_; }
 
@@ -124,6 +126,11 @@ class ScriptBridge {
         const char *instanceId, const char *nameSpace, const char *func,
         std::vector<VALUE_WITH_TYPE *> &params) = 0;
 
+    virtual void ExecJSWithCallback(const char *instanceId,
+                                    const char *nameSpace, const char *func,
+                                    std::vector<VALUE_WITH_TYPE *> &params,
+                                    long callback_id) = 0;
+
     virtual int CreateInstance(const char *instanceId, const char *func,
                                const char *script, const char *opts,
                                const char *initData,
diff --git a/weex_core/Source/include/WeexApiHeader.h 
b/weex_core/Source/include/WeexApiHeader.h
index 00959d0d7a..7642bbfe84 100644
--- a/weex_core/Source/include/WeexApiHeader.h
+++ b/weex_core/Source/include/WeexApiHeader.h
@@ -146,6 +146,9 @@ typedef void (*FuncCallHandlePostMessage)(const char 
*vimId, const char *data, i
 typedef void
 (*FuncCallDIspatchMessage)(const char *clientId, const char *data, int 
dataLength, const char *callback, const char *vmId);
 
+typedef void
+(*FuncOnReceivedResult)(long callback_id, std::unique_ptr<WeexJSResult>& 
result);
+
 
 typedef struct FunctionsExposedByCore {
     FuncSetJSVersion funcSetJSVersion;
@@ -172,6 +175,7 @@ typedef struct FunctionsExposedByCore {
     FuncT3dLinkNative funcT3dLinkNative;
     FuncCallHandlePostMessage funcCallHandlePostMessage;
     FuncCallDIspatchMessage funcCallDIspatchMessage;
+    FuncOnReceivedResult  funcOnReceivedResult;
 } FunctionsExposedByCore;
 
 typedef void (*FuncCallSetJSVersion)(const char* version);
@@ -270,6 +274,9 @@ typedef int (*FuncExeJS)(const char *instanceId, const char 
*nameSpace, const ch
 typedef std::unique_ptr<WeexJSResult>(*FuncExeJSWithResult)(const char 
*instanceId, const char *nameSpace, const char *func,
                                            std::vector<VALUE_WITH_TYPE *> 
&params);
 
+typedef void(*FuncExeJSWithResultId)(const char *instanceId, const char 
*nameSpace, const char *func,
+                                           std::vector<VALUE_WITH_TYPE *> 
&params, long callback_id);
+
 typedef int (*FuncCreateInstance)(const char *instanceId, const char *func, 
const char *script, const char *opts,
                                   const char *initData, const char 
*extendsApi);
 
@@ -290,6 +297,7 @@ typedef struct FunctionsExposedByJS {
     FuncExeCTimeCallback funcExeCTimeCallback;
     FuncExeJS funcExeJS;
     FuncExeJSWithResult funcExeJSWithResult;
+    FuncExeJSWithResultId funcExeJSWithResultId;
     FuncCreateInstance funcCreateInstance;
     FuncExeJSOnInstance funcExeJSOnInstance;
     FuncDestroyInstance funcDestroyInstance;


 

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


With regards,
Apache Git Services

Reply via email to