You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/04/28 06:53:46 UTC
[18/48] incubator-weex git commit: * [android] Merge WeexCore-master
to master.
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
new file mode 100644
index 0000000..4afb185
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
@@ -0,0 +1,662 @@
+#include <android/base/string/string_utils.h>
+#include <base/ViewUtils.h>
+#include "ExtendJSApi.h"
+
+using namespace WeexCore;
+
+static WeexCore::FunType gCanvasFunc = nullptr;
+
+static WeexCore::FunTypeT3d t3dFunc = nullptr;
+
+/**
+* This class aim to extend JS Api
+**/
+ExtendJSApi::ExtendJSApi() {
+}
+
+void ExtendJSApi::initFunction(IPCHandler *handler) {
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETJSFVERSION),
+ handleSetJSVersion);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::REPORTEXCEPTION),
+ handleReportException);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVE),
+ handleCallNative);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVEMODULE),
+ handleCallNativeModule);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVECOMPONENT),
+ handleCallNativeComponent);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLADDELEMENT),
+ handleCallAddElement);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETTIMEOUT),
+ handleSetTimeout);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::NATIVELOG),
+ handleCallNativeLog);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLCREATEBODY),
+ functionCallCreateBody);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATEFINISH),
+ functionCallUpdateFinish);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLCREATEFINISH),
+ functionCallCreateFinish);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREFRESHFINISH),
+ functionCallRefreshFinish);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATEATTRS),
+ functionCallUpdateAttrs);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATESTYLE),
+ functionCallUpdateStyle);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREMOVEELEMENT),
+ functionCallRemoveElement);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLMOVEELEMENT),
+ functionCallMoveElement);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLADDEVENT),
+ functionCallAddEvent);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREMOVEEVENT),
+ functionCallRemoveEvent);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETINTERVAL),
+ handleSetInterval);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CLEARINTERVAL),
+ handleClearInterval);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLGCANVASLINK),
+ handleCallGCanvasLinkNative);
+ handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLT3DLINK),
+ handleT3DLinkNative);
+}
+
+std::unique_ptr<IPCResult> handleSetJSVersion(IPCArguments *arguments) {
+ const char* version = getArumentAsCStr(arguments, 0);
+ LOGA("init JSFrm version %s", version);
+ Bridge_Impl_Android::getInstance()->setJSVersion(version);
+ return createVoidResult();
+}
+
+void reportException(const char* pageId, const char *func, const char *exception_string) {
+ Bridge_Impl_Android::getInstance()->reportException(pageId, func, exception_string);
+}
+
+std::unique_ptr<IPCResult> handleReportException(IPCArguments *arguments) {
+ const char *pageId = nullptr;
+ const char *func = nullptr;
+ const char *exceptionInfo = nullptr;
+
+ if (arguments->getType(0) == IPCType::BYTEARRAY) {
+ const IPCByteArray *instanceIDBA = arguments->getByteArray(0);
+ pageId = instanceIDBA->content;
+ }
+
+ if (arguments->getType(1) == IPCType::BYTEARRAY) {
+ const IPCByteArray *funcBA = arguments->getByteArray(1);
+ func = funcBA->content;
+ }
+
+ if (arguments->getType(2) == IPCType::BYTEARRAY) {
+ const IPCByteArray *exceptionInfoBA = arguments->getByteArray(2);
+ exceptionInfo = exceptionInfoBA->content;
+ }
+
+ LOGE(" ReportException : %s", exceptionInfo);
+ reportException(pageId, func, exceptionInfo);
+ return createVoidResult();
+}
+
+std::unique_ptr<IPCResult> handle(IPCArguments *arguments) {
+ const char* str_array = getArumentAsCStr(arguments, 0);
+ Bridge_Impl_Android::getInstance()->callNativeLog(str_array);
+ return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleCallNativeLog(IPCArguments *arguments) {
+ const char* str_array = getArumentAsCStr(arguments, 0);
+ Bridge_Impl_Android::getInstance()->callNativeLog(str_array);
+ return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleSetTimeout(IPCArguments *arguments) {
+ char* callbackID = getArumentAsCStr(arguments, 0);
+ char* time = getArumentAsCStr(arguments, 1);
+
+ if (callbackID == nullptr || time == nullptr)
+ return createInt32Result(static_cast<int32_t>(false));
+
+ Bridge_Impl_Android::getInstance()->setTimeout(callbackID, time);
+
+ if (callbackID != nullptr) {
+ delete[]callbackID;
+ callbackID = nullptr;
+ }
+ if (time != nullptr) {
+ delete[]time;
+ time = nullptr;
+ }
+ return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleSetInterval(IPCArguments *arguments) {
+ const char *pageId = getArumentAsCStr(arguments, 0);
+ const char *callbackID = getArumentAsCStr(arguments, 1);
+ const char *_time = getArumentAsCStr(arguments, 2);
+ if (pageId == nullptr || callbackID == nullptr || _time == nullptr)
+ return createInt32Result(-1);
+
+ long time_ = atoi(_time);
+ int _timerId = (atoi(pageId) << 16) | (atoi(callbackID));
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (callbackID != nullptr) {
+ delete[]callbackID;
+ callbackID = nullptr;
+ }
+ if (_time != nullptr) {
+ delete[]_time;
+ _time = nullptr;
+ }
+ return createInt32Result(_timerId);
+}
+
+std::unique_ptr<IPCResult> handleClearInterval(IPCArguments *arguments) {
+ const char *pageId = getArumentAsCStr(arguments, 0);
+ const char *callbackID = getArumentAsCStr(arguments, 1);
+ long id = atoi(callbackID);
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (callbackID != nullptr) {
+ delete[]callbackID;
+ callbackID = nullptr;
+ }
+ return createVoidResult();
+}
+
+std::unique_ptr<IPCResult> handleCallNative(IPCArguments *arguments) {
+ char* pageId = getArumentAsCStr(arguments, 0);
+ char* task = getArumentAsCStr(arguments, 1);
+ char* callback = getArumentAsCStr(arguments, 2);
+
+ if (pageId != nullptr && task != nullptr) {
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] handleCallNative >>>> pageId: %s, task: %s", pageId, task);
+#endif
+
+ if (strcmp(task, "[{\"module\":\"dom\",\"method\":\"createFinish\",\"args\":[]}]") == 0) {
+ RenderManager::GetInstance()->CreateFinish(pageId) ? 0 : -1;
+ } else {
+ Bridge_Impl_Android::getInstance()->callNative(pageId, task, callback);
+ }
+ }
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (task != nullptr) {
+ delete[]task;
+ task = nullptr;
+ }
+ if (callback != nullptr) {
+ delete[]callback;
+ callback = nullptr;
+ }
+ return createInt32Result(0);
+}
+
+static std::unique_ptr<IPCResult> handleCallGCanvasLinkNative(IPCArguments *arguments) {
+ JNIEnv *env = getJNIEnv();
+ jstring jPageId = getArgumentAsJString(env, arguments, 0);
+ const char *pageId = env->GetStringUTFChars(jPageId, NULL);
+ int type = getArgumentAsInt32(env, arguments, 1);
+ jstring val = getArgumentAsJString(env, arguments, 2);
+ const char *args = env->GetStringUTFChars(val, NULL);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] handleCallGCanvasLinkNative >>>> pageId: %s, type: %d, args: %s", pageId, type, args);
+#endif
+
+ const char *retVal = NULL;
+ if (gCanvasFunc) {
+ retVal = callGCanvasFun(gCanvasFunc, pageId, type, args);
+ }
+
+ std::unique_ptr<IPCResult> ret = createVoidResult();
+ if (retVal) {
+ jstring jDataStr = env->NewStringUTF(retVal);
+ ret = std::move(createStringResult(env, jDataStr));
+ env->DeleteLocalRef(jDataStr);
+ retVal = NULL;
+ }
+ env->DeleteLocalRef(jPageId);
+ env->DeleteLocalRef(val);
+ return ret;
+}
+
+static std::unique_ptr<IPCResult> handleT3DLinkNative(IPCArguments* arguments)
+{
+ JNIEnv* env = getJNIEnv();
+ int type = getArgumentAsInt32(env, arguments, 0);
+ jstring val = getArgumentAsJString(env, arguments, 1);
+ const char* args = env->GetStringUTFChars(val, NULL);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] handleT3DLinkNative >>>> type: %d, args: %s", type, args);
+#endif
+
+ const char* retVal = NULL;
+ if (t3dFunc) {
+ retVal = WeexCore::weexCallT3dFunc(t3dFunc, type, args);
+ }
+
+
+
+ std::unique_ptr<IPCResult> ret = createVoidResult();
+ if (retVal) {
+ jstring jDataStr = env->NewStringUTF(retVal);
+ ret = std::move(createStringResult(env, jDataStr));
+ env->DeleteLocalRef(jDataStr);
+ retVal = NULL;
+ }
+ env->DeleteLocalRef(val);
+ return ret;
+}
+
+std::unique_ptr<IPCResult> handleCallNativeModule(IPCArguments *arguments) {
+ char* pageId = getArumentAsCStr(arguments, 0);
+ char* module = getArumentAsCStr(arguments, 1);
+ char* method = getArumentAsCStr(arguments, 2);
+ char* argString = getArumentAsCStr(arguments, 3);
+ char* optString = getArumentAsCStr(arguments, 4);
+
+ std::unique_ptr<IPCResult> ret = createInt32Result(-1);
+
+ if (pageId != nullptr && module != nullptr && method != nullptr) {
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] handleCallNativeModule >>>> pageId: %s, module: %s, method: %s, arg: %s, opt: %s",
+ pageId, module, method, argString, optString);
+#endif
+
+ // add for android support
+ jobject result;
+ result = Bridge_Impl_Android::getInstance()->callNativeModule(pageId, module, method,
+ argString, optString);
+
+ if (result == nullptr)
+ return ret;
+
+ JNIEnv *env = getJNIEnv();
+ jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I");
+ jint jTypeInt = env->GetIntField(result, jTypeId);
+ jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;");
+ jobject jDataObj = env->GetObjectField(result, jDataId);
+ if (jTypeInt == 1) {
+ if (jDoubleValueMethodId == NULL) {
+ jclass jDoubleClazz = env->FindClass("java/lang/Double");
+ jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D");
+ env->DeleteLocalRef(jDoubleClazz);
+ }
+ jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId);
+ ret = std::move(createDoubleResult(jDoubleObj));
+
+ } else if (jTypeInt == 2) {
+ jstring jDataStr = (jstring) jDataObj;
+ ret = std::move(createStringResult(env, jDataStr));
+ } else if (jTypeInt == 3) {
+ jstring jDataStr = (jstring) jDataObj;
+ ret = std::move(createJSONStringResult(env, jDataStr));
+ }
+ env->DeleteLocalRef(jDataObj);
+ }
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (module != nullptr) {
+ delete[]module;
+ module = nullptr;
+ }
+ if (method != nullptr) {
+ delete[]method;
+ method = nullptr;
+ }
+ if (argString != nullptr) {
+ delete[]argString;
+ argString = nullptr;
+ }
+ if (optString != nullptr) {
+ delete[]optString;
+ optString = nullptr;
+ }
+ return ret;
+}
+
+std::unique_ptr<IPCResult> handleCallNativeComponent(IPCArguments *arguments) {
+ char* pageId = getArumentAsCStr(arguments, 0);
+ char* ref = getArumentAsCStr(arguments, 1);
+ char* method = getArumentAsCStr(arguments, 2);
+ char* argString = getArumentAsCStr(arguments, 3);
+ char* optString = getArumentAsCStr(arguments, 4);
+
+ if (pageId != nullptr && ref != nullptr && method != nullptr) {
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] handleCallNativeComponent >>>> pageId: %s, ref: %s, method: %s, arg: %s, opt: %s",
+ pageId, ref, method, argString, optString);
+#endif
+
+ Bridge_Impl_Android::getInstance()->callNativeComponent(pageId, ref, method, argString, optString);
+ }
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (ref != nullptr) {
+ delete[]ref;
+ ref = nullptr;
+ }
+ if (method != nullptr) {
+ delete[]method;
+ method = nullptr;
+ }
+ if (argString != nullptr) {
+ delete[]argString;
+ argString = nullptr;
+ }
+ if (optString != nullptr) {
+ delete[]optString;
+ optString = nullptr;
+ }
+ return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> functionCallCreateBody(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *domStr = getArumentAsCStr(arguments, 1);
+
+ if (pageId == nullptr || domStr == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallCreateBody >>>> pageId: %s, domStr: %s", pageId, domStr);
+#endif
+
+ RenderManager::GetInstance()->CreatePage(pageId, domStr) ? 0 : -1;
+
+ delete[]pageId;
+ delete[]domStr;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> handleCallAddElement(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *parentRef = getArumentAsCStr(arguments, 1);
+ char *domStr = getArumentAsCStr(arguments, 2);
+ char *index_cstr = getArumentAsCStr(arguments, 3);
+ int index = atoi(index_cstr);
+
+ if (pageId == nullptr || parentRef == nullptr || domStr == nullptr || index_cstr == nullptr ||
+ index < -1)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+
+ std::string log = "";
+ log.append("pageId: ").append(pageId).append(", parentRef: ").append(parentRef).append(", domStr: ").append(domStr);
+ int log_index = 0;
+ int maxLength = 800;
+ std::string sub;
+ while (log_index < log.length()) {
+ if (log.length() <= log_index + maxLength) {
+ sub = log.substr(log_index);
+ } else {
+ sub = log.substr(log_index, maxLength);
+ }
+
+
+ if (log_index == 0)
+ LOGD("[ExtendJSApi] functionCallAddElement >>>> %s", sub.c_str());
+ else
+ LOGD(" [ExtendJSApi] functionCallAddElement >>>> %s", sub.c_str());
+
+ log_index += maxLength;
+ }
+#endif
+
+ RenderManager::GetInstance()->AddRenderObject(pageId, parentRef, index, domStr);
+
+ delete[]pageId;
+ delete[]parentRef;
+ delete[]domStr;
+ delete[]index_cstr;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallRemoveElement(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+
+ if (pageId == nullptr || ref == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallRemoveElement >>>> pageId: %s, ref: %s", pageId,
+ ref);
+#endif
+
+ RenderManager::GetInstance()->RemoveRenderObject(pageId, ref);
+
+ delete[]pageId;
+ delete[]ref;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallMoveElement(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+ char *parentRef = getArumentAsCStr(arguments, 2);
+ char *index_str = getArumentAsCStr(arguments, 3);
+ int index = atoi(index_str);
+
+ if (pageId == nullptr || ref == nullptr || parentRef == nullptr || index_str == nullptr ||
+ index < -1)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallRemoveElement >>>> pageId: %s, ref: %s, parentRef: %s, index: %d",
+ pageId, ref, parentRef, index);
+#endif
+
+ RenderManager::GetInstance()->MoveRenderObject(pageId, ref, parentRef, index);
+
+ delete[]pageId;
+ delete[]ref;
+ delete[]parentRef;
+ delete[]index_str;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallAddEvent(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+ char *event = getArumentAsCStr(arguments, 2);
+
+ if (pageId == nullptr || ref == nullptr || event == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallAddEvent >>>> pageId: %s, ref: %s, event: %s", pageId,
+ ref, event);
+#endif
+
+ RenderManager::GetInstance()->AddEvent(pageId, ref, event);
+
+ delete[]pageId;
+ delete[]ref;
+ delete[]event;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallRemoveEvent(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+ char *event = getArumentAsCStr(arguments, 2);
+
+ if (pageId == nullptr || ref == nullptr || event == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallRemoveEvent >>>> pageId: %s, ref: %s, event: %s", pageId,
+ ref, event);
+#endif
+
+ RenderManager::GetInstance()->RemoveEvent(pageId, ref, event);
+
+ delete[]pageId;
+ delete[]ref;
+ delete[]event;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateStyle(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+ char *data = getArumentAsCStr(arguments, 2);
+
+ if (pageId == nullptr || ref == nullptr || data == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallUpdateStyle >>>> pageId: %s, ref: %s, data: %s", pageId,
+ ref, data);
+#endif
+
+ RenderManager::GetInstance()->UpdateStyle(pageId, ref, data);
+
+ delete[] pageId;
+ delete[] ref;
+ delete[] data;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateAttrs(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *ref = getArumentAsCStr(arguments, 1);
+ char *data = getArumentAsCStr(arguments, 2);
+
+ if (pageId == nullptr || ref == nullptr || data == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallUpdateAttrs >>>> pageId: %s, ref: %s, data: %s", pageId,
+ ref, data);
+#endif
+
+ RenderManager::GetInstance()->UpdateAttr(pageId, ref, data);
+
+ delete[] pageId;
+ delete[] ref;
+ delete[] data;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallCreateFinish(IPCArguments *arguments) {
+
+ char *pageId = getArumentAsCStr(arguments, 0);
+
+ if (pageId == nullptr)
+ return createInt32Result(0);
+
+#if JSAPI_LOG
+ LOGD("[ExtendJSApi] functionCallCreateFinish >>>> pageId: %s", pageId);
+#endif
+
+ RenderManager::GetInstance()->CreateFinish(pageId);
+
+ delete[]pageId;
+ return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateFinish(IPCArguments *arguments) {
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *task = getArumentAsCStr(arguments, 1);
+ char *callback = getArumentAsCStr(arguments, 2);
+
+ int flag = 0;
+
+ if (pageId == nullptr || task == nullptr)
+ return createInt32Result(flag);
+
+ flag = Bridge_Impl_Android::getInstance()->callUpdateFinish(pageId, task, callback);
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (task != nullptr) {
+ delete[]task;
+ task = nullptr;
+ }
+ if (callback != nullptr) {
+ delete[]callback;
+ callback = nullptr;
+ }
+ return createInt32Result(flag);
+}
+
+std::unique_ptr<IPCResult> functionCallRefreshFinish(IPCArguments *arguments) {
+ char *pageId = getArumentAsCStr(arguments, 0);
+ char *task = getArumentAsCStr(arguments, 1);
+ char *callback = getArumentAsCStr(arguments, 2);
+
+ int flag = 0;
+
+ if (pageId == nullptr)
+ return createInt32Result(flag);
+
+ flag = Bridge_Impl_Android::getInstance()->callRefreshFinish(pageId, task, callback);
+
+ if (pageId != nullptr) {
+ delete[]pageId;
+ pageId = nullptr;
+ }
+ if (task != nullptr) {
+ delete[]task;
+ task = nullptr;
+ }
+ if (callback != nullptr) {
+ delete[]callback;
+ callback = nullptr;
+ }
+ return createInt32Result(flag);
+}
+
+namespace WeexCore {
+
+ extern "C" void Inject_GCanvasFunc(FunType fp) {
+ gCanvasFunc = fp;
+ LOGE("weexjsc injectGCanvasFunc gCanvasFunc");
+ }
+
+ const char *callGCanvasFun(FunType fp, const char *conextId, int x, const char *args) {
+ return fp(conextId, x, args);
+ }
+
+ extern "C" void Inject_T3dFunc(FunTypeT3d fp) {
+ t3dFunc = fp;
+ LOGE("weexjsc Inject_T3dFunc t3d Func");
+ }
+
+const char* weexCallT3dFunc(FunTypeT3d fp, int x, const char* args) {
+ return fp(x, args);
+}
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
new file mode 100644
index 0000000..d23cda1
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
@@ -0,0 +1,87 @@
+#ifndef _EXTEND_JSAPI_H_
+#define _EXTEND_JSAPI_H_
+
+#include <android/base/log_utils.h>
+#include <android/bridge/impl/bridge_impl_android.h>
+#include "IPC/IPCHandler.h"
+#include "IPC/IPCMessageJS.h"
+#include "IPC/IPCResult.h"
+#include "IPC/IPCSender.h"
+#include "IPC/IPCString.h"
+#include "IPC/Serializing/IPCSerializer.h"
+#include <core/render/manager/render_manager.h>
+#include <jni.h>
+#include <sys/types.h>
+
+
+static std::unique_ptr<IPCResult> handleSetJSVersion(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleReportException(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNative(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeModule(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeComponent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallAddElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleSetTimeout(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeLog(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallCreateBody(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallCreateFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRefreshFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateAttrs(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateStyle(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRemoveElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallMoveElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallAddEvent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRemoveEvent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleSetInterval(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleClearInterval(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallGCanvasLinkNative(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleT3DLinkNative(IPCArguments *arguments);
+
+
+static void reportException(const int instanceID, const char *func, const char *exception_string);
+
+namespace WeexCore {
+
+ typedef const char *(*FunType)(const char *, int, const char *);
+
+ const char *callGCanvasFun(FunType fp, const char *conextId, int x, const char *args);
+
+ extern "C" void Inject_GCanvasFunc(FunType fp);
+
+ typedef const char* (*FunTypeT3d)(int, const char*);
+
+ const char* weexCallT3dFunc(FunTypeT3d fp, int x, const char* args);
+
+ extern "C" void Inject_T3dFunc(FunTypeT3d fp);
+
+ class ExtendJSApi {
+ public:
+ ExtendJSApi();
+
+ void initFunction(IPCHandler *handler);
+ };
+
+} //WeexCore
+
+#endif // _EXTENSION_JSAPI_H_
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
new file mode 100644
index 0000000..420cbb8
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
@@ -0,0 +1,411 @@
+#include "WeexJSConnection.h"
+
+#include "ashmem.h"
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <IPC/IPCFutexPageQueue.h>
+#include <IPC/IPCException.h>
+#include <IPC/IPCSender.h>
+#include <unistd.h>
+#include <android/base/log_utils.h>
+
+extern const char *s_cacheDir;
+extern bool s_start_pie;
+
+static void doExec(int fd, bool traceEnable, bool startupPie = true);
+
+static int copyFile(const char *SourceFile, const char *NewFile);
+
+static void closeAllButThis(int fd);
+
+static void printLogOnFile(const char *log);
+
+#if PRINT_LOG_CACHEFILE
+static std::string logFilePath = "/data/data/com.taobao.taobao/cache";
+#endif
+
+struct WeexJSConnection::WeexJSConnectionImpl {
+ std::unique_ptr<IPCSender> serverSender;
+ std::unique_ptr<IPCFutexPageQueue> futexPageQueue;
+ pid_t child{0};
+};
+
+WeexJSConnection::WeexJSConnection()
+ : m_impl(new WeexJSConnectionImpl) {
+}
+
+WeexJSConnection::~WeexJSConnection() {
+ end();
+}
+
+IPCSender *WeexJSConnection::start(IPCHandler *handler, bool reinit) {
+ int fd = ashmem_create_region("WEEX_IPC", IPCFutexPageQueue::ipc_size);
+ if (-1 == fd) {
+ throw IPCException("failed to create ashmem region: %s", strerror(errno));
+ }
+ void *base = mmap(nullptr, IPCFutexPageQueue::ipc_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+ if (base == MAP_FAILED) {
+ int _errno = errno;
+ close(fd);
+ throw IPCException("failed to map ashmem region: %s", strerror(_errno));
+ }
+ std::unique_ptr<IPCFutexPageQueue> futexPageQueue(
+ new IPCFutexPageQueue(base, IPCFutexPageQueue::ipc_size, 0));
+ std::unique_ptr<IPCSender> sender(createIPCSender(futexPageQueue.get(), handler));
+ m_impl->serverSender = std::move(sender);
+ m_impl->futexPageQueue = std::move(futexPageQueue);
+#if PRINT_LOG_CACHEFILE
+ if (s_cacheDir) {
+ logFilePath = s_cacheDir;
+ }
+ logFilePath.append("/jsserver_start.log");
+ std::ofstream mcfile;
+ if (reinit) {
+ mcfile.open(logFilePath, std::ios::app);
+ mcfile << "restart fork a process" << std::endl;
+ } else {
+ mcfile.open(logFilePath);
+ mcfile << "start fork a process" << std::endl;
+ }
+#endif
+
+ static bool startupPie = s_start_pie;
+ LOGE("startupPie :%d", startupPie);
+
+ pid_t child;
+ if (reinit) {
+#if PRINT_LOG_CACHEFILE
+ mcfile << "reinit is ture use vfork" << std::endl;
+ mcfile.close();
+#endif
+ child = vfork();
+ } else {
+#if PRINT_LOG_CACHEFILE
+ mcfile << "reinit is false use fork" << std::endl;
+ mcfile.close();
+#endif
+ child = fork();
+ }
+ if (child == -1) {
+ int myerrno = errno;
+ munmap(base, IPCFutexPageQueue::ipc_size);
+ close(fd);
+ throw IPCException("failed to fork: %s", strerror(myerrno));
+ } else if (child == 0) {
+ // the child
+ closeAllButThis(fd);
+ // implements close all but handles[1]
+ // do exec
+ doExec(fd, true, startupPie);
+ LOGE("exec Failed completely.");
+ // failed to exec
+ _exit(1);
+ } else {
+ printLogOnFile("fork success on main process and start m_impl->futexPageQueue->spinWaitPeer()");
+ close(fd);
+ m_impl->child = child;
+ try {
+ m_impl->futexPageQueue->spinWaitPeer();
+ } catch (IPCException &e) {
+ LOGE("WeexJSConnection catch: %s", e.msg());
+ // TODO throw exception
+ return nullptr;
+ }
+ }
+ return m_impl->serverSender.get();
+}
+
+void WeexJSConnection::end() {
+ m_impl->serverSender.reset();
+ m_impl->futexPageQueue.reset();
+ if (m_impl->child) {
+ int wstatus;
+ pid_t child;
+ kill(m_impl->child, 9);
+ while (true) {
+ child = waitpid(m_impl->child, &wstatus, 0);
+ if (child != -1)
+ break;
+ if (errno != EINTR)
+ break;
+ }
+ }
+}
+
+void printLogOnFile(const char *log) {
+#if PRINT_LOG_CACHEFILE
+ std::ofstream mcfile;
+ mcfile.open(logFilePath, std::ios::app);
+ mcfile << log << std::endl;
+ mcfile.close();
+#endif
+}
+
+static std::string __attribute__((noinline)) findPath();
+
+static void findPath(std::string &executablePath, std::string &icuDataPath) {
+ unsigned long target = reinterpret_cast<unsigned long>(__builtin_return_address(0));
+ FILE *f = fopen("/proc/self/maps", "r");
+ if (!f) {
+ return;
+ }
+ char buffer[256];
+ char *line;
+ while ((line = fgets(buffer, 256, f))) {
+ if (icuDataPath.empty() && strstr(line, "icudt")) {
+ icuDataPath.assign(strstr(line, "/"));
+ icuDataPath = icuDataPath.substr(0, icuDataPath.length() - 1);
+ continue;
+ }
+ char *end;
+ unsigned long val;
+ errno = 0;
+ val = strtoul(line, &end, 16);
+ if (errno)
+ continue;
+ if (val > target)
+ continue;
+ end += 1;
+ errno = 0;
+ val = strtoul(end, &end, 16);
+ if (errno)
+ continue;
+ if (val > target) {
+ executablePath.assign(strstr(end, "/"));
+ std::size_t found = executablePath.rfind('/');
+ if (found != std::string::npos) {
+ executablePath = executablePath.substr(0, found);
+ }
+ }
+ if (!executablePath.empty()
+ && !icuDataPath.empty()) {
+ break;
+ }
+ }
+ fclose(f);
+ return;
+}
+
+class EnvPBuilder {
+public:
+ EnvPBuilder();
+
+ ~EnvPBuilder() = default;
+
+ void addNew(const char *n);
+
+ std::unique_ptr<const char *[]> build();
+
+private:
+ std::vector<const char *> m_vec;
+};
+
+EnvPBuilder::EnvPBuilder() {
+ for (char **env = environ; *env; env++) {
+ // fixme:add for ANDROID_ROOT envp
+ // if cannot find some env, can use such as
+ // PATH/ANDROID_BOOTLOGO/ANDROID_ASSETS/ANDROID_DATA/ASEC_MOUNTPOINT
+ // LOOP_MOUNTPOINT/BOOTCLASSPATH and etc
+ // but don't use LD_LIBRARY_PATH env may cause so cannot be found
+ const char *android_root_env = "ANDROID_ROOT=";
+ if (strstr(*env, android_root_env) != nullptr) {
+ addNew(*env);
+ break;
+ }
+ }
+}
+
+void EnvPBuilder::addNew(const char *n) {
+ m_vec.emplace_back(n);
+}
+
+std::unique_ptr<const char *[]> EnvPBuilder::build() {
+ std::unique_ptr<const char *[]> ptr(new const char *[m_vec.size() + 1]);
+ for (size_t i = 0; i < m_vec.size(); ++i) {
+ ptr.get()[i] = m_vec[i];
+ }
+ ptr.get()[m_vec.size()] = nullptr;
+ return ptr;
+}
+
+void doExec(int fd, bool traceEnable, bool startupPie) {
+ std::string executablePath;
+ std::string icuDataPath;
+ findPath(executablePath, icuDataPath);
+#if PRINT_LOG_CACHEFILE
+ std::ofstream mcfile;
+ mcfile.open(logFilePath, std::ios::app);
+ mcfile << "jsengine WeexJSConnection::doExec executablePath:" << executablePath << std::endl;
+ mcfile << "jsengine WeexJSConnection::doExec icuDataPath:" << icuDataPath << std::endl;
+#endif
+
+ if (executablePath.empty()) {
+ LOGE("executablePath is empty");
+
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec executablePath is empty and return" << std::endl;
+ mcfile.close();
+#endif
+
+ return;
+ }
+ if (icuDataPath.empty()) {
+ LOGE("icuDataPath is empty");
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec icuDataPath is empty and return" << std::endl;
+ mcfile.close();
+#endif
+ return;
+ }
+ std::string ldLibraryPathEnv("LD_LIBRARY_PATH=");
+ std::string icuDataPathEnv("ICU_DATA_PATH=");
+ std::string crashFilePathEnv("CRASH_FILE_PATH=");
+ ldLibraryPathEnv.append(executablePath);
+ icuDataPathEnv.append(icuDataPath);
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine ldLibraryPathEnv:" << ldLibraryPathEnv << " icuDataPathEnv:" << icuDataPathEnv
+ << std::endl;
+#endif
+ if (!s_cacheDir) {
+ crashFilePathEnv.append("/data/data/com.taobao.taobao/cache");
+ } else {
+ crashFilePathEnv.append(s_cacheDir);
+ }
+ crashFilePathEnv.append("/jsserver_crash");
+ char fdStr[16];
+ snprintf(fdStr, 16, "%d", fd);
+ EnvPBuilder envpBuilder;
+ envpBuilder.addNew(ldLibraryPathEnv.c_str());
+ envpBuilder.addNew(icuDataPathEnv.c_str());
+ envpBuilder.addNew(crashFilePathEnv.c_str());
+ auto envp = envpBuilder.build();
+ {
+ std::string executableName = executablePath + '/' + "libweexjsb64.so";
+ chmod(executableName.c_str(), 0755);
+ const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+ if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+ const_cast<char *const *>(envp.get()))) {
+ }
+ }
+
+ std::string start_so = "";
+ if (startupPie) {
+ start_so = "libweexjsb.so";
+ } else {
+ start_so = "libweexjst.so";
+ }
+
+ {
+ std::string executableName = executablePath + '/' + start_so;
+ chmod(executableName.c_str(), 0755);
+ int result = access(executableName.c_str(), 01);
+
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec file exsist result:"
+ << result << " startupPie:" << startupPie << std::endl;
+#endif
+ if (result == -1) {
+ executableName = std::string(s_cacheDir) + '/' + start_so;
+ int result_cache = access(executableName.c_str(), 00);
+ if (result_cache == -1) {
+ std::string sourceSo = executablePath + '/' + start_so;
+ int ret = copyFile(sourceSo.c_str(), executableName.c_str());
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec copy so from:" << sourceSo
+ << " to:" << executableName << ", success: " << ret << std::endl;
+#endif
+ }
+ chmod(executableName.c_str(), 0755);
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec start path on sdcard, start execve so name:"
+ << executableName << std::endl;
+#endif
+ const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+ if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+ const_cast<char *const *>(envp.get()))) {
+#if PRINT_LOG_CACHEFILE
+ mcfile << "execve failed11:" << strerror(errno) << std::endl;
+#endif
+ }
+ } else {
+ // std::string executableName = executablePath + '/' + "libweexjsb.so";
+ chmod(executableName.c_str(), 0755);
+#if PRINT_LOG_CACHEFILE
+ mcfile << "jsengine WeexJSConnection::doExec start execve so name:" << executableName
+ << std::endl;
+#endif
+ const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+ if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+ const_cast<char *const *>(envp.get()))) {
+#if PRINT_LOG_CACHEFILE
+ mcfile << "execve failed:" << strerror(errno) << std::endl;
+#endif
+ }
+ }
+
+ }
+#if PRINT_LOG_CACHEFILE
+ mcfile.close();
+#endif
+}
+
+static void closeAllButThis(int exceptfd) {
+ DIR *dir = opendir("/proc/self/fd");
+ if (!dir) {
+ return;
+ }
+ int dirFd = dirfd(dir);
+ struct dirent *cur;
+ struct timespec start;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ while ((cur = readdir(dir))) {
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ if ((now.tv_sec - start.tv_sec) > 6) {
+ break;
+ }
+ if (!strcmp(cur->d_name, ".")
+ || !strcmp(cur->d_name, "..")) {
+ continue;
+ }
+ errno = 0;
+ unsigned long curFd = strtoul(cur->d_name, nullptr, 10);
+ if (errno)
+ continue;
+ if (curFd <= 2)
+ continue;
+ if ((curFd != dirFd) && (curFd != exceptfd)) {
+ close(curFd);
+ }
+ }
+ closedir(dir);
+}
+
+int copyFile(const char *SourceFile, const char *NewFile) {
+ std::ifstream in;
+ std::ofstream out;
+ in.open(SourceFile, std::ios::binary);
+ if (in.fail()) {
+ in.close();
+ out.close();
+ return 0;
+ }
+ out.open(NewFile, std::ios::binary);
+ if (out.fail()) {
+ out.close();
+ in.close();
+ return 0;
+ } else {
+ out << in.rdbuf();
+ out.close();
+ in.close();
+ return 1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
new file mode 100644
index 0000000..e09a51c
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
@@ -0,0 +1,25 @@
+#ifndef WEEXJSCONNECTION_H
+#define WEEXJSCONNECTION_H
+
+#include <memory>
+
+class IPCSender;
+class IPCHandler;
+
+class WeexJSConnection {
+public:
+ WeexJSConnection();
+
+ ~WeexJSConnection();
+
+ IPCSender *start(IPCHandler *handler, bool reinit = false);
+
+ void end();
+
+private:
+ struct WeexJSConnectionImpl;
+
+ std::unique_ptr<WeexJSConnectionImpl> m_impl;
+};
+
+#endif /* WEEXJSCONNECTION_H */
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp
new file mode 100644
index 0000000..5bb2a8a
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp
@@ -0,0 +1,690 @@
+// Copyright [2017-12-07] <WeexCore>
+#include "WeexProxy.h"
+
+#include <android/base/log_utils.h>
+#include <android/base/string/string_utils.h>
+#include <core/config/core_environment.h>
+#include <android/jsengine/multiprocess/ExtendJSApi.h>
+
+
+const char *s_cacheDir;
+bool s_start_pie = true;
+
+static IPCSender *sSender;
+static std::unique_ptr <IPCHandler> sHandler;
+static std::unique_ptr <WeexJSConnection> sConnection;
+
+
+namespace WeexCore {
+void WeexProxy::reset() {
+ sConnection.reset();
+ sHandler.reset();
+}
+
+jint WeexProxy::doInitFramework(JNIEnv *env, jobject object,
+ jstring script, jobject params,
+ jstring cacheDir, jboolean pieSupport) {
+ const char *cache = env->GetStringUTFChars(
+ reinterpret_cast<jstring>(cacheDir), nullptr);
+ if (strlen(cache) > 0) {
+ s_cacheDir = cache;
+ }
+ s_start_pie = pieSupport;
+ return doInitFramework(env, jThis, script, params);
+}
+
+jint WeexProxy::doInitFramework(JNIEnv *env,
+ jobject object,
+ jstring script,
+ jobject params) {
+ bool reinit = false;
+ startInitFrameWork:
+ try {
+ sHandler = std::move(createIPCHandler());
+ sConnection.reset(new WeexJSConnection());
+ sSender = sConnection->start(sHandler.get(), reinit);
+ if (sSender == nullptr) {
+ LOGE("JSFreamwork init start sender is null");
+ if (!reinit) {
+ reinit = true;
+ goto startInitFrameWork;
+ } else {
+ return false;
+ }
+ } else {
+ // initHandler(sHandler.get());
+ ExtendJSApi *pExtensionJSApi = new ExtendJSApi();
+ Bridge_Impl_Android::getInstance()->setGlobalRef(jThis);
+ pExtensionJSApi->initFunction(sHandler.get());
+
+ // using base::debug::TraceEvent;
+ // TraceEvent::StartATrace(env);
+ std::unique_ptr <IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::INITFRAMEWORK));
+ initFromParam(env, script, params, serializer.get());
+ std::unique_ptr <IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr <IPCResult> result = sSender->send(buffer.get());
+ if (result->getType() != IPCType::INT32) {
+ LOGE("initFramework Unexpected result type");
+ reportException("", "initFramework",
+ "error, initFramework Unexpected result type");
+ return false;
+ }
+ return result->get<jint>();
+ }
+ } catch (IPCException &e) {
+ LOGE("WeexProxy catch:%s", e.msg());
+ if (!reinit) {
+ reinit = true;
+ goto startInitFrameWork;
+ } else {
+ LOGE("%s", e.msg());
+ reportException("", "initFramework", e.msg());
+ return false;
+ }
+ }
+}
+
+bool WeexProxy::execJSService(JNIEnv *env, jobject object, jstring script) {
+ if (!sSender) {
+ LOGE("have not connected to a js server");
+ return false;
+ }
+ try {
+ std::unique_ptr <IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSSERVICE));
+ addString(env, serializer.get(), script);
+ std::unique_ptr <IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr <IPCResult> result = sSender->send(buffer.get());
+ if (result->getType() != IPCType::INT32) {
+ LOGE("execJSService Unexpected result type");
+ return false;
+ }
+ return result->get<jint>();
+ } catch (IPCException &e) {
+ LOGE("%s", e.msg());
+ return false;
+ }
+ return true;
+}
+
+bool WeexProxy::execJS(JNIEnv *env,
+ jobject jthis,
+ jstring jinstanceid,
+ jstring jnamespace,
+ jstring jfunction,
+ jobjectArray jargs) {
+ std::string mMessage = "";
+ if (!sSender) {
+ LOGE("have not connected to a js server");
+ return false;
+ }
+ int length = 0;
+ if (jargs != NULL) {
+ length = env->GetArrayLength(jargs);
+ }
+ try {
+ std::unique_ptr <IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJS));
+ addString(env, serializer.get(), jinstanceid);
+ if (jnamespace) {
+ addString(env, serializer.get(), jnamespace);
+ } else {
+ uint16_t tmp = 0;
+ serializer->add(&tmp, 0);
+ }
+ addString(env, serializer.get(), jfunction);
+
+ for (int i = 0; i < length; i++) {
+ jobject jArg = env->GetObjectArrayElement(jargs, i);
+
+ jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I");
+ jint jTypeInt = env->GetIntField(jArg, jTypeId);
+
+ jfieldID jDataId = env->GetFieldID(jWXJSObject,
+ "data", "Ljava/lang/Object;");
+ jobject jDataObj = env->GetObjectField(jArg, jDataId);
+ if (jTypeInt == 1) {
+ if (jDoubleValueMethodId == NULL) {
+ jclass jDoubleClazz = env->FindClass("java/lang/Double");
+ jDoubleValueMethodId = env->GetMethodID(jDoubleClazz,
+ "doubleValue", "()D");
+ env->DeleteLocalRef(jDoubleClazz);
+ }
+ jdouble jDoubleObj = env->CallDoubleMethod(jDataObj,
+ jDoubleValueMethodId);
+ serializer->add(jDoubleObj);
+
+ } else if (jTypeInt == 2) {
+ jstring jDataStr = (jstring) jDataObj;
+ addString(env, serializer.get(), jDataStr);
+ } else if (jTypeInt == 3) {
+ jstring jDataStr = (jstring) jDataObj;
+ addJSONString(env, serializer.get(), jDataStr);
+ } else {
+ serializer->addJSUndefined();
+ }
+ env->DeleteLocalRef(jDataObj);
+ env->DeleteLocalRef(jArg);
+ }
+
+ std::unique_ptr <IPCBuffer> buffer = serializer->finish();
+
+ std::unique_ptr <IPCResult> result = sSender->send(buffer.get());
+
+ if (result->getType() != IPCType::INT32) {
+ LOGE("execJS Unexpected result type");
+ return false;
+ }
+
+ return result->get<jint>();
+ } catch (IPCException &e) {
+ LOGE("%s", e.msg());
+ // report crash here
+ WeexProxy::reportServerCrash(jinstanceid);
+ return false;
+ }
+ return true;
+}
+
+
+void WeexProxy::initFromParam(JNIEnv *env,
+ jstring script,
+ jobject params,
+ IPCSerializer *serializer) {
+ {
+ ScopedJString scopedString(env, script);
+ const jchar *chars = scopedString.getChars();
+ int charLength = scopedString.getCharsLength();
+ serializer->add(chars, charLength);
+ }
+#define ADDSTRING(name) \
+ { \
+ const char* myname = #name; \
+ serializer->add(myname, strlen(myname)); \
+ ScopedJStringUTF8 scopedString(env, (jstring)name); \
+ const char* chars = scopedString.getChars(); \
+ int charLength = strlen(chars); \
+ serializer->add(chars, charLength); \
+ }
+ jclass c_params = env->GetObjectClass(params);
+
+ jmethodID m_platform = env->GetMethodID(c_params,
+ "getPlatform",
+ "()Ljava/lang/String;");
+ jobject platform = env->CallObjectMethod(params, m_platform);
+ if (!WXCoreEnvironment::getInstance()->SetPlatform(
+ jString2StrFast(env, reinterpret_cast<jstring &>(platform)))) {
+ LOGD("setPlatform");
+ }
+ ADDSTRING(platform);
+
+ jmethodID m_osVersion = env->GetMethodID(
+ c_params, "getOsVersion", "()Ljava/lang/String;");
+ jobject osVersion = env->CallObjectMethod(params, m_osVersion);
+ ADDSTRING(osVersion);
+
+ // use param ti get cacheDir
+ jmethodID m_cacheMethod = env->GetMethodID(
+ c_params, "getCacheDir", "()Ljava/lang/String;");
+ if (m_cacheMethod != NULL) {
+ jobject cacheDir = env->CallObjectMethod(params, m_cacheMethod);
+ if (cacheDir != NULL) {
+ ADDSTRING(cacheDir);
+ }
+ }
+
+ jmethodID m_appVersion = env->GetMethodID(
+ c_params, "getAppVersion", "()Ljava/lang/String;");
+ jobject appVersion = env->CallObjectMethod(params, m_appVersion);
+ ADDSTRING(appVersion);
+
+ jmethodID m_weexVersion = env->GetMethodID(
+ c_params, "getWeexVersion", "()Ljava/lang/String;");
+ jobject weexVersion = env->CallObjectMethod(params, m_weexVersion);
+ ADDSTRING(weexVersion);
+
+ jmethodID m_deviceModel = env->GetMethodID(
+ c_params, "getDeviceModel", "()Ljava/lang/String;");
+ jobject deviceModel = env->CallObjectMethod(params, m_deviceModel);
+ ADDSTRING(deviceModel);
+
+ jmethodID m_appName = env->GetMethodID(
+ c_params, "getAppName", "()Ljava/lang/String;");
+ jobject appName = env->CallObjectMethod(params, m_appName);
+ ADDSTRING(appName);
+
+ jmethodID m_deviceWidth = env->GetMethodID(
+ c_params, "getDeviceWidth", "()Ljava/lang/String;");
+ jobject deviceWidth = env->CallObjectMethod(params, m_deviceWidth);
+ if (!WXCoreEnvironment::getInstance()->SetDeviceWidth(
+ jString2StrFast(env, reinterpret_cast<jstring &>(deviceWidth)))) {
+ LOGD("setDeviceWidth");
+ }
+ ADDSTRING(deviceWidth);
+
+ jmethodID m_deviceHeight = env->GetMethodID(
+ c_params, "getDeviceHeight", "()Ljava/lang/String;");
+ jobject deviceHeight = env->CallObjectMethod(params, m_deviceHeight);
+ if (!WXCoreEnvironment::getInstance()->SetDeviceHeight(
+ jString2StrFast(env, reinterpret_cast<jstring &>(deviceHeight)))) {
+ LOGD("setDeviceHeight");
+ }
+ ADDSTRING(deviceHeight);
+
+ jmethodID m_options = env->GetMethodID(
+ c_params, "getOptions", "()Ljava/lang/Object;");
+ jobject options = env->CallObjectMethod(params, m_options);
+ jclass jmapclass = env->FindClass("java/util/HashMap");
+ jmethodID jkeysetmid = env->GetMethodID(jmapclass,
+ "keySet",
+ "()Ljava/util/Set;");
+ jmethodID jgetmid = env->GetMethodID(
+ jmapclass,
+ "get",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ jobject jsetkey = env->CallObjectMethod(options, jkeysetmid);
+ jclass jsetclass = env->FindClass("java/util/Set");
+ jmethodID jtoArraymid = env->GetMethodID(jsetclass,
+ "toArray",
+ "()[Ljava/lang/Object;");
+ jobjectArray jobjArray =
+ (jobjectArray) env->CallObjectMethod(jsetkey, jtoArraymid);
+ env->DeleteLocalRef(jsetkey);
+ if (jobjArray != NULL) {
+ jsize arraysize = env->GetArrayLength(jobjArray);
+ for (int i = 0; i < arraysize; i++) {
+ jstring jkey = (jstring) env->GetObjectArrayElement(jobjArray, i);
+ jstring jvalue = (jstring) env->CallObjectMethod(options, jgetmid, jkey);
+
+ if (jkey != NULL) {
+ // const char* c_key = env->GetStringUTFChars(jkey, NULL);
+ // addString(vm, WXEnvironment, c_key, jString2String(env, jvalue));
+ // serializer->add(c_key, strlen(c_key));
+ // env->DeleteLocalRef(jkey);
+ // if (jvalue != NULL) {
+ // env->DeleteLocalRef(jvalue);
+ // }
+ ScopedJStringUTF8 c_key(env, jkey);
+ ScopedJStringUTF8 c_value(env, jvalue);
+ const char *c_key_chars = c_key.getChars();
+ int c_key_len = strlen(c_key_chars);
+ const char *c_value_chars = c_value.getChars();
+ int c_value_len = strlen(c_value_chars);
+ serializer->add(c_key_chars, c_key_len);
+ serializer->add(c_value_chars, c_value_len);
+ WXCoreEnvironment::getInstance()->AddOption(jString2Str(env, jkey), jString2Str(env, jvalue));
+ }
+ }
+ env->DeleteLocalRef(jobjArray);
+ }
+ env->DeleteLocalRef(options);
+}
+
+void
+WeexProxy::reportException(const char *instanceID,
+ const char *func,
+ const char *exception_string) {
+ JNIEnv *env = getJNIEnv();
+ jstring jExceptionString = env->NewStringUTF(exception_string);
+ jstring jInstanceId = env->NewStringUTF(instanceID);
+ jstring jFunc = env->NewStringUTF(func);
+ jmethodID tempMethodId = env->GetMethodID(
+ jBridgeClazz,
+ "reportJSException",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ env->CallVoidMethod(jThis,
+ tempMethodId,
+ jInstanceId,
+ jFunc,
+ jExceptionString);
+ env->DeleteLocalRef(jExceptionString);
+ env->DeleteLocalRef(jInstanceId);
+ env->DeleteLocalRef(jFunc);
+}
+
+void WeexProxy::reportServerCrash(jstring jinstanceid) {
+ JNIEnv *env = getJNIEnv();
+ jmethodID reportMethodId;
+ jstring crashFile;
+ std::string crashFileStr;
+ reportMethodId = env->GetMethodID(jBridgeClazz,
+ "reportServerCrash",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ if (!reportMethodId)
+ goto no_method;
+
+ crashFileStr.assign("/jsserver_crash/jsserver_crash_info.log");
+
+ crashFile = env->NewStringUTF(crashFileStr.c_str());
+ env->CallVoidMethod(jThis, reportMethodId, jinstanceid, crashFile);
+ env->DeleteLocalRef(crashFile);
+ no_method:
+ env->ExceptionClear();
+}
+
+const char *WeexProxy::getCacheDir(JNIEnv *env) {
+ jclass activityThreadCls, applicationCls, fileCls;
+ jobject applicationObj, fileObj, pathStringObj;
+ jmethodID currentApplicationMethodId,
+ getCacheDirMethodId,
+ getAbsolutePathMethodId;
+ static std::string storage;
+ const char *tmp;
+ const char *ret = nullptr;
+ if (!storage.empty()) {
+ ret = storage.c_str();
+ goto no_empty;
+ }
+ activityThreadCls = env->FindClass("android/app/ActivityThread");
+ if (!activityThreadCls || env->ExceptionOccurred()) {
+ goto no_class;
+ }
+ currentApplicationMethodId = env->GetStaticMethodID(
+ activityThreadCls,
+ "currentApplication",
+ "()Landroid/app/Application;");
+ if (!currentApplicationMethodId || env->ExceptionOccurred()) {
+ goto no_currentapplication_method;
+ }
+ applicationObj = env->CallStaticObjectMethod(activityThreadCls,
+ currentApplicationMethodId,
+ nullptr);
+ if (!applicationObj || env->ExceptionOccurred()) {
+ goto no_application;
+ }
+ applicationCls = env->GetObjectClass(applicationObj);
+ getCacheDirMethodId = env->GetMethodID(applicationCls,
+ "getCacheDir",
+ "()Ljava/io/File;");
+ if (!getCacheDirMethodId || env->ExceptionOccurred()) {
+ goto no_getcachedir_method;
+ }
+ fileObj = env->CallObjectMethod(applicationObj, getCacheDirMethodId, nullptr);
+ if (!fileObj || env->ExceptionOccurred()) {
+ goto no_file_obj;
+ }
+ fileCls = env->GetObjectClass(fileObj);
+ getAbsolutePathMethodId = env->GetMethodID(fileCls,
+ "getAbsolutePath",
+ "()Ljava/lang/String;");
+ if (!getAbsolutePathMethodId || env->ExceptionOccurred()) {
+ goto no_getabsolutepath_method;
+ }
+ pathStringObj = env->CallObjectMethod(fileObj,
+ getAbsolutePathMethodId,
+ nullptr);
+ if (!pathStringObj || env->ExceptionOccurred()) {
+ goto no_path_string;
+ }
+ tmp = env->GetStringUTFChars(reinterpret_cast<jstring>(pathStringObj),
+ nullptr);
+ storage.assign(tmp);
+ env->ReleaseStringUTFChars(reinterpret_cast<jstring>(pathStringObj),
+ tmp);
+ ret = storage.c_str();
+ no_path_string:
+ no_getabsolutepath_method:
+ env->DeleteLocalRef(fileCls);
+ env->DeleteLocalRef(fileObj);
+ no_file_obj:
+ no_getcachedir_method:
+ env->DeleteLocalRef(applicationCls);
+ env->DeleteLocalRef(applicationObj);
+ no_application:
+ no_currentapplication_method:
+ env->DeleteLocalRef(activityThreadCls);
+ no_class:
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ no_empty:
+ return ret;
+}
+
+void WeexProxy::setCacheDir(JNIEnv *env) {
+ s_cacheDir = getCacheDir(env);
+}
+
+jbyteArray WeexProxy::execJSWithResult(JNIEnv* env, jobject jthis,
+ jstring jinstanceid,
+ jstring jnamespace,
+ jstring jfunction,
+ jobjectArray jargs) {
+ if (!sSender) {
+ LOGE("have not connected to a js server");
+ return NULL;
+ }
+ if (jfunction == NULL || jinstanceid == NULL) {
+ LOGE("native_execJS function is NULL");
+ return NULL;
+ }
+
+ int length = 0;
+ if (jargs != NULL) {
+ length = env->GetArrayLength(jargs);
+ }
+ try {
+ std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSWITHRESULT));
+ addString(env, serializer.get(), jinstanceid);
+ if (jnamespace)
+ addString(env, serializer.get(), jnamespace);
+ else {
+ uint16_t tmp = 0;
+ serializer->add(&tmp, 0);
+ }
+ addString(env, serializer.get(), jfunction);
+
+ for (int i = 0; i < length; i++) {
+ jobject jArg = env->GetObjectArrayElement(jargs, i);
+
+ jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I");
+ jint jTypeInt = env->GetIntField(jArg, jTypeId);
+
+ jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;");
+ jobject jDataObj = env->GetObjectField(jArg, jDataId);
+ if (jTypeInt == 1) {
+ if (jDoubleValueMethodId == NULL) {
+ jclass jDoubleClazz = env->FindClass("java/lang/Double");
+ jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D");
+ env->DeleteLocalRef(jDoubleClazz);
+ }
+ jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId);
+ serializer->add(jDoubleObj);
+
+ } else if (jTypeInt == 2) {
+ jstring jDataStr = (jstring)jDataObj;
+ addString(env, serializer.get(), jDataStr);
+ } else if (jTypeInt == 3) {
+ jstring jDataStr = (jstring)jDataObj;
+ addJSONString(env, serializer.get(), jDataStr);
+ } else {
+ serializer->addJSUndefined();
+ }
+ env->DeleteLocalRef(jDataObj);
+ env->DeleteLocalRef(jArg);
+ }
+ std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr<IPCResult> result = sSender->send(buffer.get());
+ if (result->getType() != IPCType::BYTEARRAY) {
+ return NULL;
+ }
+ if(result->getByteArrayLength() == 0){
+ return NULL;
+ }
+ jbyteArray array = env->NewByteArray(result->getByteArrayLength());
+ env->SetByteArrayRegion(array, 0, result->getByteArrayLength(), reinterpret_cast<const jbyte*>(result->getByteArrayContent()));
+ return array;
+ } catch (IPCException& e) {
+ LOGE("%s", e.msg());
+ // report crash here
+ reportServerCrash(jinstanceid);
+ return NULL;
+ }
+ return NULL;
+}
+
+void WeexProxy::updateGlobalConfig(JNIEnv *env, jobject jcaller, jstring config) {
+ if (!sSender) {
+ LOGE("have not connected to a js server");
+ return;
+ }
+ if (config == NULL) {
+ LOGE("native_execJS function is NULL");
+ return;
+ }
+ try {
+ std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::UPDATEGLOBALCONFIG));
+ addString(env, serializer.get(), config);
+ std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr<IPCResult> result = sSender->send(buffer.get());
+ } catch (IPCException& e) {
+ LOGE("%s", e.msg());
+ }
+}
+
+static jstring getJsonData(JNIEnv *env, jobjectArray jargs, int index) {
+ int length = 0;
+ if (jargs != NULL) {
+ length = env->GetArrayLength(jargs);
+ }
+ jstring ret = NULL;
+ if (length < (index + 1)) {
+ return ret;
+ }
+ jobject jArg = env->GetObjectArrayElement(jargs, index);
+
+ jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I");
+ jint jTypeInt = env->GetIntField(jArg, jTypeId);
+ jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;");
+ jobject jDataObj = env->GetObjectField(jArg, jDataId);
+ if (jTypeInt == 3) {
+ ret = (jstring) jDataObj;
+ }
+ // env->DeleteLocalRef(jDataObj);
+ env->DeleteLocalRef(jArg);
+ return ret;
+}
+
+jint
+WeexProxy::createInstanceContext(JNIEnv *env, jobject jcaller, jstring jinstanceid, jstring name,
+ jstring jfunction, jobjectArray jargs) {
+ if (!sSender) {
+ LOGE("have not connected to a js server");
+ return false;
+ }
+ if (jfunction == NULL || jinstanceid == NULL) {
+ LOGE("native_createInstanceContext function is NULL");
+ return false;
+ }
+
+ int length = 0;
+ if (jargs != NULL) {
+ length = env->GetArrayLength(jargs);
+ }
+ if (length < 4) {
+ LOGE("native_createInstanceContext jargs format error");
+ return false;
+ }
+ try {
+ std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::CREATEINSTANCE));
+ addString(env, serializer.get(), jinstanceid);
+ addString(env, serializer.get(), jfunction);
+
+ // get temp data, such as js bundle
+ jobject jArg = env->GetObjectArrayElement(jargs,1);
+ jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;");
+ jobject jDataObj = env->GetObjectField(jArg, jDataId);
+ jstring jscript = (jstring) jDataObj;
+ addString(env, serializer.get(), jscript);
+ jstring opts = getJsonData(env, jargs, 2);
+ addJSONString(env, serializer.get(), opts);
+ // init jsonData
+ jstring initData = getJsonData(env, jargs, 3);
+ addJSONString(env, serializer.get(), initData);
+
+ // get extend api data, such as rax-api
+ jArg = env->GetObjectArrayElement(jargs, 4);
+ jDataObj = env->GetObjectField(jArg, jDataId);
+ jstring japi = (jstring) jDataObj;
+ addString(env, serializer.get(), japi);
+
+ std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr<IPCResult> result = sSender->send(buffer.get());
+ env->DeleteLocalRef(jArg);
+ env->DeleteLocalRef(jDataObj);
+ env->DeleteLocalRef(opts);
+ if (result->getType() != IPCType::INT32) {
+ LOGE("createInstanceContext Unexpected result type");
+ return false;
+ }
+ return result->get<jint>();
+ } catch (IPCException& e) {
+ LOGE("%s", e.msg());
+ // report crash here
+ reportServerCrash(jinstanceid);
+ return false;
+ }
+ return true;
+}
+
+jint WeexProxy::destoryInstance(JNIEnv *env, jobject jcaller, jstring jinstanceid, jstring jnamespace,
+ jstring jfunction, jobjectArray jargs) {
+ int ret = execJS(env, nullptr, jinstanceid, jnamespace, jfunction, jargs);
+ if (jfunction == NULL || jinstanceid == NULL) {
+ LOGE("native_destoryInstance function is NULL");
+ return false;
+ }
+ try {
+ std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::DESTORYINSTANCE));
+ addString(env, serializer.get(), jinstanceid);
+
+ std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr<IPCResult> result = sSender->send(buffer.get());
+ if (result->getType() != IPCType::INT32) {
+ LOGE("destoryInstance Unexpected result type");
+ return false;
+ }
+ return result->get<jint>();
+ } catch (IPCException& e) {
+ LOGE("%s", e.msg());
+ // report crash here
+ reportServerCrash(jinstanceid);
+ return false;
+ }
+ return true;
+}
+
+jstring
+WeexProxy::execJSOnInstance(JNIEnv *env, jobject jcaller, jstring instanceId, jstring script,
+ jint type) {
+ if (instanceId == NULL || script == NULL) {
+ return env->NewStringUTF("");
+ }
+ try {
+ // base::debug::TraceScope traceScope("weex", "native_execJSOnInstance");
+ std::unique_ptr<IPCSerializer> serializer(createIPCSerializer());
+ serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSONINSTANCE));
+
+ addString(env, serializer.get(), instanceId);
+ addString(env, serializer.get(), script);
+
+ std::unique_ptr<IPCBuffer> buffer = serializer->finish();
+ std::unique_ptr<IPCResult> result = sSender->send(buffer.get());
+ if (result->getType() != IPCType::BYTEARRAY) {
+ // LOGE("native_execJSOnInstance return type error");
+ return env->NewStringUTF("");
+ }
+ return env->NewStringUTF(result->getByteArrayContent());
+ } catch (IPCException& e) {
+ LOGE("%s", e.msg());
+ // report crash here
+ reportServerCrash(instanceId);
+ return env->NewStringUTF("");
+ }
+}
+
+} // namespace WeexCore
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
new file mode 100644
index 0000000..942f619
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
@@ -0,0 +1,76 @@
+#ifndef _WEEX_PROXY_H_
+#define _WEEX_PROXY_H_
+
+
+#include <jni.h>
+#include <unistd.h>
+#include <IPC/Serializing/IPCSerializer.h>
+#include <IPC/IPCHandler.h>
+#include <android/bridge/impl/bridge_impl_android.h>
+#include <IPC/Buffering/IPCBuffer.h>
+#include <IPC/IPCArguments.h>
+#include <IPC/IPCByteArray.h>
+#include <IPC/IPCException.h>
+#include <IPC/IPCHandler.h>
+#include <IPC/IPCMessageJS.h>
+#include <IPC/IPCResult.h>
+#include <IPC/IPCSender.h>
+#include <IPC/IPCString.h>
+#include <IPC/Serializing/IPCSerializer.h>
+
+namespace WeexCore {
+
+class WeexProxy {
+private:
+public:
+ static void reset();
+
+ static jint doInitFramework(JNIEnv *env, jobject object, jstring script, jobject params,
+ jstring cacheDir, jboolean pieSupport);
+
+ static jint doInitFramework(JNIEnv *env, jobject object, jstring script, jobject params);
+
+ static void
+ initFromParam(JNIEnv *env, jstring script, jobject params, IPCSerializer *serializer);
+
+ static const char *getCacheDir(JNIEnv *env);
+
+ static void setCacheDir(JNIEnv *env);
+
+ static bool execJSService(JNIEnv *env, jobject object, jstring script);
+
+ static bool
+ execJS(JNIEnv *env, jobject jthis, jstring jinstanceid, jstring jnamespace, jstring jfunction,
+ jobjectArray jargs);
+
+ static void
+ reportException(const char *instanceID, const char *func, const char *exception_string);
+
+ static void reportServerCrash(jstring jinstanceid);
+
+ static jbyteArray execJSWithResult(JNIEnv* env, jobject jthis,
+ jstring jinstanceid,
+ jstring jnamespace,
+ jstring jfunction,
+ jobjectArray jargs);
+
+ static void updateGlobalConfig(JNIEnv* env, jobject jcaller,
+ jstring config);
+ static jint createInstanceContext(JNIEnv* env, jobject jcaller, jstring instanceId,
+ jstring name,
+ jstring function,
+ jobjectArray args);
+
+ static jint destoryInstance(JNIEnv* env, jobject jcaller,
+ jstring instanceId,
+ jstring name,
+ jstring function,
+ jobjectArray args);
+
+ static jstring execJSOnInstance(JNIEnv* env, jobject jcaller,
+ jstring instanceId,
+ jstring script,
+ jint type);
+};
+}
+#endif //_WEEX_PROXY_H_
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/Compatible.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/Compatible.cpp b/weex_core/Source/base/Compatible.cpp
new file mode 100644
index 0000000..3fb0e5c
--- /dev/null
+++ b/weex_core/Source/base/Compatible.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <math.h>
+#include <mntent.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace WeexCore {
+int sigemptyset(sigset_t *set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, 0, sizeof(sigset_t));
+ return 0;
+}
+
+int sigfillset(sigset_t *set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, ~0, sizeof(sigset_t));
+ return 0;
+}
+
+int sigaddset(sigset_t *set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ unsigned long *local_set = reinterpret_cast<unsigned long *>(set);
+ if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
+ }
+ local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
+ return 0;
+}
+
+int sigdelset(sigset_t *set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ unsigned long *local_set = reinterpret_cast<unsigned long *>(set);
+ if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
+ }
+ local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
+ return 0;
+}
+
+int getpagesize() {
+ // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
+ return PAGE_SIZE;
+}
+
+void srandom(unsigned int __s) { srand48(__s); }
+
+int isinf(double n) {
+ return __builtin_isinf(n);
+}
+
+int posix_memalign(void **memptr, size_t alignment, size_t bytes) {
+ if (!memptr)
+ return EINVAL;
+ *memptr = memalign(alignment, bytes);
+ if (!*memptr)
+ return ENOMEM;
+ return 0;
+}
+
+int sigismember(const sigset_t *set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ const unsigned long *local_set = reinterpret_cast<const unsigned long *>(set);
+ if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
+ }
+ return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
+}
+
+int abs(int j) {
+ return (j < 0 ? -j : j);
+}
+
+long labs(long j) {
+ return (j < 0 ? -j : j);
+}
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/CoreConstants.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/CoreConstants.h b/weex_core/Source/base/CoreConstants.h
new file mode 100644
index 0000000..d918a7c
--- /dev/null
+++ b/weex_core/Source/base/CoreConstants.h
@@ -0,0 +1,10 @@
+
+#ifndef WEEXV8_CONSTANTSNAME_H
+#define WEEXV8_CONSTANTSNAME_H
+
+#include <string>
+
+const std::string OS_Android = "android";
+const std::string OS_iOS = "iOS";
+
+#endif //WEEXV8_CONSTANTSNAME_H
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/TimeUtils.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/TimeUtils.h b/weex_core/Source/base/TimeUtils.h
new file mode 100644
index 0000000..072d9be
--- /dev/null
+++ b/weex_core/Source/base/TimeUtils.h
@@ -0,0 +1,12 @@
+#ifndef WEEX_PROJECT_TIMEUTILS_H
+#define WEEX_PROJECT_TIMEUTILS_H
+
+#include <sys/time.h>
+
+static long long getCurrentTime() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (long long) tv.tv_sec * 1000 + (long long) tv.tv_usec / 1000;
+}
+
+#endif //WEEX_PROJECT_TIMEUTILS_H
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/ViewUtils.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/ViewUtils.h b/weex_core/Source/base/ViewUtils.h
new file mode 100644
index 0000000..624c510
--- /dev/null
+++ b/weex_core/Source/base/ViewUtils.h
@@ -0,0 +1,102 @@
+#ifndef WEEX_PROJECT_VIEWUTILS_H
+#define WEEX_PROJECT_VIEWUTILS_H
+
+#include <core/config/core_environment.h>
+#include <cmath>
+#include <cstdlib>
+
+namespace WeexCore {
+
+ const std::string WX("wx");
+ const std::string PX("px");
+ const std::string UNDEFINE("undefined");
+ const std::string SCALE("scale");
+ const std::string AUTO_UNIT("auto");
+ const std::string NONE("none");
+
+ inline std::string &Trim(std::string &s) {
+ if (s.empty()) {
+ return s;
+ }
+ s.erase(0, s.find_first_not_of(" "));
+ s.erase(s.find_last_not_of(" ") + 1);
+ return s;
+ }
+
+ inline float getFloat(const char* src) {
+ char *end;
+ float ret = strtof(src, &end);
+ if(*end != '\0'){
+ ret = NAN;
+ }
+ return ret;
+ }
+
+ inline float getFloat(const float &src, const float &viewport) {
+ if (isnan(src))
+ return NAN;
+
+ float realPx = (src * WXCoreEnvironment::getInstance()->DeviceWidth() /
+ viewport);
+ float result = realPx > 0.005 && realPx < 1 ? 1 : rint(realPx);
+ return result;
+ }
+
+ inline float getFloat(const std::string &src, const float &viewport) {
+ float ret = NAN;
+ if (UNDEFINE == src
+ || AUTO_UNIT == src
+ || NONE == src
+ || src.empty()) {
+ return ret;
+ }
+ float original_value = getFloat(src.c_str());
+ ret = getFloat(original_value, viewport);
+ return ret;
+ }
+
+ inline bool endWidth(const std::string &src, const std::string &suffix) {
+ return src.size() > suffix.size() &&
+ src.compare(src.size() - suffix.size(), suffix.size(), suffix) == 0;
+ }
+
+ inline float transferWx(const std::string &stringWithWXPostfix, const float &viewport) {
+ std::string temp = stringWithWXPostfix;
+ if (endWidth(stringWithWXPostfix, WX)) {
+ temp = stringWithWXPostfix.substr(0, stringWithWXPostfix.size() - WX.size());
+ }
+ float f = getFloat(temp.c_str());
+ float density = getFloat(WXCoreEnvironment::getInstance()->GetOption(SCALE).c_str());
+ return density * f * viewport / WXCoreEnvironment::getInstance()->DeviceWidth();
+ }
+
+ inline static float getFloatByViewport(std::string src, const float &viewport) {
+ float ret = NAN;
+ if (UNDEFINE == src
+ || AUTO_UNIT == src
+ || NONE == src
+ || src.empty()) {
+ return ret;
+ }
+ Trim(src);
+ if (endWidth(src, WX)) {
+ ret = getFloat(transferWx(src, viewport), viewport);
+ } else if (endWidth(src, PX)) {
+ ret = getFloat(src.substr(0, src.size() - PX.size()), viewport);
+ } else {
+ ret = getFloat(src, viewport);
+ }
+ return ret;
+ }
+
+ inline static float getWebPxByWidth(float pxValue, float customViewport) {
+ if (isnan(pxValue))
+ return NAN;
+
+ float realPx = (pxValue * customViewport / WXCoreEnvironment::getInstance()->DeviceWidth());
+ float result = realPx > 0.005 && realPx < 1 ? 1 : rint(realPx);
+ return result;
+ }
+}
+
+#endif //WEEX_PROJECT_VIEWUTILS_H
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/fpconv.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/fpconv.cpp b/weex_core/Source/base/fpconv.cpp
new file mode 100755
index 0000000..3fbd55a
--- /dev/null
+++ b/weex_core/Source/base/fpconv.cpp
@@ -0,0 +1,332 @@
+#include <stdbool.h>
+#include <string.h>
+
+#include "fpconv.h"
+#include "powers.h"
+
+#define fracmask 0x000FFFFFFFFFFFFFU
+#define expmask 0x7FF0000000000000U
+#define hiddenbit 0x0010000000000000U
+#define signmask 0x8000000000000000U
+#define expbias (1023 + 52)
+
+#define absv(n) ((n) < 0 ? -(n) : (n))
+#define minv(a, b) ((a) < (b) ? (a) : (b))
+
+static uint64_t tens[] = {
+ 10000000000000000000U, 1000000000000000000U, 100000000000000000U,
+ 10000000000000000U, 1000000000000000U, 100000000000000U,
+ 10000000000000U, 1000000000000U, 100000000000U,
+ 10000000000U, 1000000000U, 100000000U,
+ 10000000U, 1000000U, 100000U,
+ 10000U, 1000U, 100U,
+ 10U, 1U
+};
+
+static inline uint64_t get_dbits(double d)
+{
+ union {
+ double dbl;
+ uint64_t i;
+ } dbl_bits = { d };
+
+ return dbl_bits.i;
+}
+
+static Fp build_fp(double d)
+{
+ uint64_t bits = get_dbits(d);
+
+ Fp fp;
+ fp.frac = bits & fracmask;
+ fp.exp = (bits & expmask) >> 52;
+
+ if(fp.exp) {
+ fp.frac += hiddenbit;
+ fp.exp -= expbias;
+
+ } else {
+ fp.exp = -expbias + 1;
+ }
+
+ return fp;
+}
+
+static void normalize(Fp* fp)
+{
+ while ((fp->frac & hiddenbit) == 0) {
+ fp->frac <<= 1;
+ fp->exp--;
+ }
+
+ int shift = 64 - 52 - 1;
+ fp->frac <<= shift;
+ fp->exp -= shift;
+}
+
+static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
+{
+ upper->frac = (fp->frac << 1) + 1;
+ upper->exp = fp->exp - 1;
+
+ while ((upper->frac & (hiddenbit << 1)) == 0) {
+ upper->frac <<= 1;
+ upper->exp--;
+ }
+
+ int u_shift = 64 - 52 - 2;
+
+ upper->frac <<= u_shift;
+ upper->exp = upper->exp - u_shift;
+
+
+ int l_shift = fp->frac == hiddenbit ? 2 : 1;
+
+ lower->frac = (fp->frac << l_shift) - 1;
+ lower->exp = fp->exp - l_shift;
+
+
+ lower->frac <<= lower->exp - upper->exp;
+ lower->exp = upper->exp;
+}
+
+static Fp multiply(Fp* a, Fp* b)
+{
+ const uint64_t lomask = 0x00000000FFFFFFFF;
+
+ uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
+ uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
+ uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
+ uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
+
+ uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
+ /* round up */
+ tmp += 1U << 31;
+
+ Fp fp = {
+ ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
+ a->exp + b->exp + 64
+ };
+
+ return fp;
+}
+
+static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
+{
+ while (rem < frac && delta - rem >= kappa &&
+ (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+
+ digits[ndigits - 1]--;
+ rem += kappa;
+ }
+}
+
+static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
+{
+ uint64_t wfrac = upper->frac - fp->frac;
+ uint64_t delta = upper->frac - lower->frac;
+
+ Fp one;
+ one.frac = 1ULL << -upper->exp;
+ one.exp = upper->exp;
+
+ uint64_t part1 = upper->frac >> -one.exp;
+ uint64_t part2 = upper->frac & (one.frac - 1);
+
+ int idx = 0, kappa = 10;
+ uint64_t* divp;
+ /* 1000000000 */
+ for(divp = tens + 10; kappa > 0; divp++) {
+
+ uint64_t div = *divp;
+ unsigned digit = part1 / div;
+
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part1 -= digit * div;
+ kappa--;
+
+ uint64_t tmp = (part1 <<-one.exp) + part2;
+ if (tmp <= delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
+
+ return idx;
+ }
+ }
+
+ /* 10 */
+ uint64_t* unit = tens + 18;
+
+ while(true) {
+ part2 *= 10;
+ delta *= 10;
+ kappa--;
+
+ unsigned digit = part2 >> -one.exp;
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part2 &= one.frac - 1;
+ if (part2 < delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
+
+ return idx;
+ }
+
+ unit--;
+ }
+}
+
+static int grisu2(double d, char* digits, int* K)
+{
+ Fp w = build_fp(d);
+
+ Fp lower, upper;
+ get_normalized_boundaries(&w, &lower, &upper);
+
+ normalize(&w);
+
+ int k;
+ Fp cp = find_cachedpow10(upper.exp, &k);
+
+ w = multiply(&w, &cp);
+ upper = multiply(&upper, &cp);
+ lower = multiply(&lower, &cp);
+
+ lower.frac++;
+ upper.frac--;
+
+ *K = -k;
+
+ return generate_digits(&w, &upper, &lower, digits, K);
+}
+
+static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
+{
+ int exp = absv(K + ndigits - 1);
+
+ /* write plain integer */
+ if(K >= 0 && (exp < (ndigits + 7))) {
+ memcpy(dest, digits, ndigits);
+ memset(dest + ndigits, '0', K);
+
+ return ndigits + K;
+ }
+
+ /* write decimal w/o scientific notation */
+ if(K < 0 && (K > -7 || exp < 4)) {
+ int offset = ndigits - absv(K);
+ /* fp < 1.0 -> write leading zero */
+ if(offset <= 0) {
+ offset = -offset;
+ dest[0] = '0';
+ dest[1] = '.';
+ memset(dest + 2, '0', offset);
+ memcpy(dest + offset + 2, digits, ndigits);
+
+ return ndigits + 2 + offset;
+
+ /* fp > 1.0 */
+ } else {
+ memcpy(dest, digits, offset);
+ dest[offset] = '.';
+ memcpy(dest + offset + 1, digits + offset, ndigits - offset);
+
+ return ndigits + 1;
+ }
+ }
+
+ /* write decimal w/ scientific notation */
+ ndigits = minv(ndigits, 18 - neg);
+
+ int idx = 0;
+ dest[idx++] = digits[0];
+
+ if(ndigits > 1) {
+ dest[idx++] = '.';
+ memcpy(dest + idx, digits + 1, ndigits - 1);
+ idx += ndigits - 1;
+ }
+
+ dest[idx++] = 'e';
+
+ char sign = K + ndigits - 1 < 0 ? '-' : '+';
+ dest[idx++] = sign;
+
+ int cent = 0;
+
+ if(exp > 99) {
+ cent = exp / 100;
+ dest[idx++] = cent + '0';
+ exp -= cent * 100;
+ }
+ if(exp > 9) {
+ int dec = exp / 10;
+ dest[idx++] = dec + '0';
+ exp -= dec * 10;
+
+ } else if(cent) {
+ dest[idx++] = '0';
+ }
+
+ dest[idx++] = exp % 10 + '0';
+
+ return idx;
+}
+
+static int filter_special(double fp, char* dest)
+{
+ if(fp == 0.0) {
+ dest[0] = '0';
+ return 1;
+ }
+
+ uint64_t bits = get_dbits(fp);
+
+ bool nan = (bits & expmask) == expmask;
+
+ if(!nan) {
+ return 0;
+ }
+
+ if(bits & fracmask) {
+ dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+
+ } else {
+ dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ }
+
+ return 3;
+}
+
+int fpconv_dtoa(double d, char dest[24])
+{
+ char digits[18];
+
+ int str_len = 0;
+ bool neg = false;
+
+ if(get_dbits(d) & signmask) {
+ dest[0] = '-';
+ str_len++;
+ neg = true;
+ }
+
+ int spec = filter_special(d, dest + str_len);
+
+ if(spec) {
+ return str_len + spec;
+ }
+
+ int K = 0;
+ int ndigits = grisu2(d, digits, &K);
+
+ str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
+
+ return str_len;
+}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/fpconv.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/fpconv.h b/weex_core/Source/base/fpconv.h
new file mode 100755
index 0000000..58bbccc
--- /dev/null
+++ b/weex_core/Source/base/fpconv.h
@@ -0,0 +1,33 @@
+#ifndef FPCONV_H
+#define FPCONV_H
+
+/* Fast and accurate double to string conversion based on Florian Loitsch's
+ * Grisu-algorithm[1].
+ *
+ * Input:
+ * fp -> the double to convert, dest -> destination buffer.
+ * The generated string will never be longer than 24 characters.
+ * Make sure to pass a pointer to at least 24 bytes of memory.
+ * The emitted string will not be null terminated.
+ *
+ * Output:
+ * The number of written characters.
+ *
+ * Exemplary usage:
+ *
+ * void print(double d)
+ * {
+ * char buf[24 + 1] // plus null terminator
+ * int str_len = fpconv_dtoa(d, buf);
+ *
+ * buf[str_len] = '\0';
+ * printf("%s", buf);
+ * }
+ *
+ */
+
+int fpconv_dtoa(double fp, char dest[24]);
+
+#endif
+
+/* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/powers.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/powers.h b/weex_core/Source/base/powers.h
new file mode 100755
index 0000000..52e5da5
--- /dev/null
+++ b/weex_core/Source/base/powers.h
@@ -0,0 +1,129 @@
+#include <stdint.h>
+
+#define npowers 87
+#define steppowers 8
+#define firstpower -348 /* 10 ^ -348 */
+
+#define expmax -32
+#define expmin -60
+
+
+typedef struct Fp {
+ uint64_t frac;
+ int exp;
+} Fp;
+
+static Fp powers_ten[] = {
+ {18054884314459144840U, -1220},
+ {13451937075301367670U, -1193},
+ {10022474136428063862U, -1166},
+ {14934650266808366570U, -1140},
+ {11127181549972568877U, -1113},
+ {16580792590934885855U, -1087},
+ {12353653155963782858U, -1060},
+ {18408377700990114895U, -1034},
+ {13715310171984221708U, -1007},
+ {10218702384817765436U, -980},
+ {15227053142812498563U, -954},
+ {11345038669416679861U, -927},
+ {16905424996341287883U, -901},
+ {12595523146049147757U, -874},
+ {9384396036005875287U, -847},
+ {13983839803942852151U, -821},
+ {10418772551374772303U, -794},
+ {15525180923007089351U, -768},
+ {11567161174868858868U, -741},
+ {17236413322193710309U, -715},
+ {12842128665889583758U, -688},
+ {9568131466127621947U, -661},
+ {14257626930069360058U, -635},
+ {10622759856335341974U, -608},
+ {15829145694278690180U, -582},
+ {11793632577567316726U, -555},
+ {17573882009934360870U, -529},
+ {13093562431584567480U, -502},
+ {9755464219737475723U, -475},
+ {14536774485912137811U, -449},
+ {10830740992659433045U, -422},
+ {16139061738043178685U, -396},
+ {12024538023802026127U, -369},
+ {17917957937422433684U, -343},
+ {13349918974505688015U, -316},
+ {9946464728195732843U, -289},
+ {14821387422376473014U, -263},
+ {11042794154864902060U, -236},
+ {16455045573212060422U, -210},
+ {12259964326927110867U, -183},
+ {18268770466636286478U, -157},
+ {13611294676837538539U, -130},
+ {10141204801825835212U, -103},
+ {15111572745182864684U, -77},
+ {11258999068426240000U, -50},
+ {16777216000000000000U, -24},
+ {12500000000000000000U, 3},
+ {9313225746154785156U, 30},
+ {13877787807814456755U, 56},
+ {10339757656912845936U, 83},
+ {15407439555097886824U, 109},
+ {11479437019748901445U, 136},
+ {17105694144590052135U, 162},
+ {12744735289059618216U, 189},
+ {9495567745759798747U, 216},
+ {14149498560666738074U, 242},
+ {10542197943230523224U, 269},
+ {15709099088952724970U, 295},
+ {11704190886730495818U, 322},
+ {17440603504673385349U, 348},
+ {12994262207056124023U, 375},
+ {9681479787123295682U, 402},
+ {14426529090290212157U, 428},
+ {10748601772107342003U, 455},
+ {16016664761464807395U, 481},
+ {11933345169920330789U, 508},
+ {17782069995880619868U, 534},
+ {13248674568444952270U, 561},
+ {9871031767461413346U, 588},
+ {14708983551653345445U, 614},
+ {10959046745042015199U, 641},
+ {16330252207878254650U, 667},
+ {12166986024289022870U, 694},
+ {18130221999122236476U, 720},
+ {13508068024458167312U, 747},
+ {10064294952495520794U, 774},
+ {14996968138956309548U, 800},
+ {11173611982879273257U, 827},
+ {16649979327439178909U, 853},
+ {12405201291620119593U, 880},
+ {9242595204427927429U, 907},
+ {13772540099066387757U, 933},
+ {10261342003245940623U, 960},
+ {15290591125556738113U, 986},
+ {11392378155556871081U, 1013},
+ {16975966327722178521U, 1039},
+ {12648080533535911531U, 1066}
+};
+
+static Fp find_cachedpow10(int exp, int *k) {
+ const double one_log_ten = 0.30102999566398114;
+
+ int approx = -(exp + npowers) * one_log_ten;
+ int idx = (approx - firstpower) / steppowers;
+
+ while (1) {
+ int current = exp + powers_ten[idx].exp + 64;
+
+ if (current < expmin) {
+ idx++;
+ continue;
+ }
+
+ if (current > expmax) {
+ idx--;
+ continue;
+ }
+
+ *k = (firstpower + idx * steppowers);
+
+ return powers_ten[idx];
+ }
+}