diff --git a/.vscode/launch.json b/.vscode/launch.json index 9a138fc..2ac90dd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,32 @@ // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "(gdb) Windows 上的 Bash 启动", + "type": "cppdbg", + "request": "launch", + "program": "example/build/linux/debug/flutter_qjs_example", + "args": [], + "stopAtEntry": false, + "cwd": "${command:extension.vscode-wsl-workspaceFolder}", + "environment": [], + "externalConsole": false, + "pipeTransport": { + "debuggerPath": "/usr/bin/gdb", + "pipeProgram": "${env:windir}\\system32\\bash.exe", + "pipeArgs": [ + "-c" + ], + "pipeCwd": "" + }, + "setupCommands": [ + { + "description": "为 gdb 启用整齐打印", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, { "name": "(Windows) 启动", "type": "cppvsdbg", diff --git a/android/src/main/jni/java_js_wrapper.hpp b/android/src/main/jni/java_js_wrapper.hpp index bb4c80e..91fd2aa 100644 --- a/android/src/main/jni/java_js_wrapper.hpp +++ b/android/src/main/jni/java_js_wrapper.hpp @@ -3,7 +3,7 @@ * @Author: ekibun * @Date: 2020-08-16 11:08:23 * @LastEditors: ekibun - * @LastEditTime: 2020-08-16 19:51:11 + * @LastEditTime: 2020-08-18 23:41:02 */ #include #include @@ -43,6 +43,29 @@ namespace qjs jsize len = env->GetArrayLength((jbyteArray)val); return JS_NewArrayBufferCopy(ctx, (uint8_t *)env->GetByteArrayElements((jbyteArray)val, 0), len); } + else if (className.compare("[I") == 0) + { + jsize len = env->GetArrayLength((jintArray)val); + return JS_NewArrayBufferCopy(ctx, (uint8_t *)env->GetIntArrayElements((jintArray)val, 0), len * 4); + } + else if (className.compare("[J") == 0) + { + jsize len = env->GetArrayLength((jlongArray)val); + return JS_NewArrayBufferCopy(ctx, (uint8_t *)env->GetLongArrayElements((jlongArray)val, 0), len * 8); + } + else if (className.compare("[D") == 0) + { + jobjectArray list = jniToArray(env, val); + jsize size = env->GetArrayLength(list); + JSValue array = JS_NewArray(ctx); + cache[val] = array; + for (uint32_t i = 0; i < size; i++) + JS_DefinePropertyValue( + ctx, array, JS_NewAtomUInt32(ctx, i), + javaToJs(ctx, env, env->GetObjectArrayElement(list, i), cache), + JS_PROP_C_W_E); + return array; + } else if (className.compare("java.lang.Boolean") == 0) { jmethodID getVal = env->GetMethodID(objclass, "booleanValue", "()Z"); @@ -112,7 +135,7 @@ namespace qjs // 读取一条数据 jobject entryObj = env->CallObjectMethod(iteratorObj, nextMID); JS_DefinePropertyValue( - ctx, obj, JS_ValueToAtom(ctx, javaToJs(ctx, env, env->CallObjectMethod(entryObj, getKeyMID), cache)), + ctx, obj, JS_ValueToAtom(ctx, javaToJs(ctx, env, env->CallObjectMethod(entryObj, getKeyMID), cache)), javaToJs(ctx, env, env->CallObjectMethod(entryObj, getValueMID), cache), JS_PROP_C_W_E); } @@ -129,9 +152,12 @@ namespace qjs return jniWrapPrimity(env, (bool)val); { int tag = JS_VALUE_GET_TAG(val.v); - if(tag == JS_TAG_INT) { + if (tag == JS_TAG_INT) + { return jniWrapPrimity(env, (int64_t)val); - } else if (JS_TAG_IS_FLOAT64(tag)) { + } + else if (JS_TAG_IS_FLOAT64(tag)) + { return jniWrapPrimity(env, (double)val); } } diff --git a/example/lib/test.dart b/example/lib/test.dart index 4f6afb8..20df8cf 100644 --- a/example/lib/test.dart +++ b/example/lib/test.dart @@ -3,7 +3,7 @@ * @Author: ekibun * @Date: 2020-07-18 23:28:55 * @LastEditors: ekibun - * @LastEditTime: 2020-08-17 21:52:14 + * @LastEditTime: 2020-08-18 23:23:46 */ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -52,6 +52,7 @@ class _TestPageState extends State { case "hello": return await arg[0](["hello: "]); default: + return JsMethodHandlerNotImplement(); } }); }), diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc index 1706bf8..a7fa026 100644 --- a/example/linux/my_application.cc +++ b/example/linux/my_application.cc @@ -14,11 +14,7 @@ G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) static void my_application_activate(GApplication* application) { GtkWindow* window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "flutter_qjs_example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_title(window, "flutter_qjs_example"); gtk_window_set_default_size(window, 1280, 720); gtk_widget_show(GTK_WIDGET(window)); diff --git a/lib/flutter_qjs.dart b/lib/flutter_qjs.dart index cfe4d68..d1ef1d1 100644 --- a/lib/flutter_qjs.dart +++ b/lib/flutter_qjs.dart @@ -3,7 +3,7 @@ * @Author: ekibun * @Date: 2020-08-08 08:29:09 * @LastEditors: ekibun - * @LastEditTime: 2020-08-17 23:31:55 + * @LastEditTime: 2020-08-18 23:23:22 */ import 'dart:async'; import 'dart:io'; @@ -11,6 +11,8 @@ import 'package:flutter/services.dart'; typedef JsMethodHandler = Future Function(String method, List args); +class JsMethodHandlerNotImplement {} + class _FlutterJs { factory _FlutterJs() => _getInstance(); static _FlutterJs get instance => _getInstance(); @@ -22,10 +24,10 @@ class _FlutterJs { print(call.arguments); var engine = call.arguments["engine"]; var args = call.arguments["args"]; - print(methodHandlers.entries); - print(methodHandlers[engine]); if (methodHandlers[engine] == null) return call.noSuchMethod(null); - return await methodHandlers[engine](call.method, _wrapFunctionArguments(args, engine)); + var ret = await methodHandlers[engine](call.method, _wrapFunctionArguments(args, engine)); + if (ret is JsMethodHandlerNotImplement) return call.noSuchMethod(null); + return ret; }); } dynamic _wrapFunctionArguments(dynamic val, dynamic engine) { diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 97ca317..539e213 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -1,13 +1,4 @@ cmake_minimum_required(VERSION 3.10) -set(PROJECT_NAME "flutter_qjs") -project(${PROJECT_NAME} LANGUAGES CXX) - -set(PLUGIN_NAME "${PROJECT_NAME}_plugin") - -add_library(${PLUGIN_NAME} SHARED - "${PLUGIN_NAME}.cc" -) - # quickjs set(QUICK_JS_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../cxx/quickjspp) file (STRINGS "${QUICK_JS_LIB_DIR}/quickjs/VERSION" QUICKJS_VERSION) @@ -21,6 +12,15 @@ add_library(libquickjs SHARED ) project(libquickjs LANGUAGES C) +set(PROJECT_NAME "flutter_qjs") +project(${PROJECT_NAME} LANGUAGES CXX) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +add_library(${PLUGIN_NAME} SHARED + "${PLUGIN_NAME}.cc" +) + apply_standard_settings(${PLUGIN_NAME}) set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) diff --git a/linux/dart_js_wrapper.hpp b/linux/dart_js_wrapper.hpp index 9fdcf08..1b280ec 100644 --- a/linux/dart_js_wrapper.hpp +++ b/linux/dart_js_wrapper.hpp @@ -3,7 +3,7 @@ * @Author: ekibun * @Date: 2020-08-14 21:45:02 * @LastEditors: ekibun - * @LastEditTime: 2020-08-17 22:43:20 + * @LastEditTime: 2020-08-18 20:29:34 */ #include "../cxx/js_engine.hpp" #include @@ -31,8 +31,12 @@ namespace std namespace qjs { - JSValue dartToJsAtom(JSContext *ctx, FlValue *val) + JSValue dartToJs(JSContext *ctx, FlValue *val, std::unordered_map cache = std::unordered_map()) { + if (val == nullptr || fl_value_get_type(val) == FL_VALUE_TYPE_NULL) + return JS_UNDEFINED; + if (cache.find(val) != cache.end()) + return cache[val]; FlValueType valType = fl_value_get_type(val); switch (valType) { @@ -47,121 +51,114 @@ namespace qjs case FL_VALUE_TYPE_UINT8_LIST: return JS_NewArrayBufferCopy(ctx, fl_value_get_uint8_list(val), fl_value_get_length(val)); case FL_VALUE_TYPE_INT32_LIST: - return JS_NewArrayBufferCopy(ctx, (uint8_t *)fl_value_get_int32_list(val), fl_value_get_length(val)); + return JS_NewArrayBufferCopy(ctx, (uint8_t *)fl_value_get_int32_list(val), fl_value_get_length(val) * 4); case FL_VALUE_TYPE_INT64_LIST: - return JS_NewArrayBufferCopy(ctx, (uint8_t *)fl_value_get_int64_list(val), fl_value_get_length(val)); - // case FL_VALUE_TYPE_FLOAT_LIST: - // auto buf = fl_value_get_float_list(val); - // auto size = fl_value_get_length(val); - // JSValue array = JS_NewArray(ctx); - // for (size_t i = 0; i < size; i++) - // JS_DefinePropertyValue( - // ctx, array, JS_NewAtomUInt32(ctx, i), JS_NewFloat64(ctx, buf[i]), - // JS_PROP_C_W_E); - // return array; + return JS_NewArrayBufferCopy(ctx, (uint8_t *)fl_value_get_int64_list(val), fl_value_get_length(val) * 8); + case FL_VALUE_TYPE_FLOAT_LIST: + { + auto buf = fl_value_get_float_list(val); + auto size = (uint32_t)fl_value_get_length(val); + JSValue array = JS_NewArray(ctx); + cache[val] = array; + for (uint32_t i = 0; i < size; ++i) + JS_DefinePropertyValue( + ctx, array, JS_NewAtomUInt32(ctx, i), JS_NewFloat64(ctx, buf[i]), + JS_PROP_C_W_E); + return array; + } + case FL_VALUE_TYPE_LIST: + { + auto size = (uint32_t)fl_value_get_length(val); + JSValue array = JS_NewArray(ctx); + cache[val] = array; + for (uint32_t i = 0; i < size; ++i) + JS_DefinePropertyValue( + ctx, array, JS_NewAtomUInt32(ctx, i), + dartToJs(ctx, fl_value_get_list_value(val, i), cache), + JS_PROP_C_W_E); + return array; + } + case FL_VALUE_TYPE_MAP: + { + auto size = (uint32_t)fl_value_get_length(val); + JSValue obj = JS_NewObject(ctx); + cache[val] = obj; + for (uint32_t i = 0; i < size; ++i) + JS_DefinePropertyValue( + ctx, obj, + JS_ValueToAtom(ctx, dartToJs(ctx, fl_value_get_map_key(val, i), cache)), + dartToJs(ctx, fl_value_get_map_value(val, i), cache), + JS_PROP_C_W_E); + return obj; + } default: return JS_UNDEFINED; } - } - - JSValue dartToJs(JSContext *ctx, FlValue *val, std::unordered_map cache = std::unordered_map()) - { - if (fl_value_get_type(val) == FL_VALUE_TYPE_NULL) - return JS_UNDEFINED; - if (cache.find(val) != cache.end()) - return cache[val]; - { - JSValue atomValue = dartToJsAtom(ctx, val); - if (!JS_IsUndefined(atomValue)) - return atomValue; - } - // if (std::holds_alternative(val)) - // { - // auto list = std::get(val); - // JSValue array = JS_NewArray(ctx); - // cache[val] = array; - // auto size = (uint32_t)list.size(); - // for (uint32_t i = 0; i < size; i++) - // JS_DefinePropertyValue( - // ctx, array, JS_NewAtomUInt32(ctx, i), dartToJs(ctx, list[i], cache), - // JS_PROP_C_W_E); - // return array; - // } - // if (std::holds_alternative(val)) - // { - // auto map = std::get(val); - // JSValue obj = JS_NewObject(ctx); - // cache[val] = obj; - // for (auto iter = map.begin(); iter != map.end(); ++iter) - // JS_DefinePropertyValue( - // ctx, obj, JS_ValueToAtom(ctx, dartToJs(ctx, iter->first, cache)), dartToJs(ctx, iter->second, cache), - // JS_PROP_C_W_E); - // return obj; - // } return JS_UNDEFINED; } FlValue *jsToDart(Value val, std::unordered_map cache = std::unordered_map()) { + if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v)) + return fl_value_new_null(); if (cache.find(val) != cache.end()) return cache[val]; if (JS_IsBool(val.v)) return fl_value_new_bool((bool)val); - if (JS_IsNumber(val.v)) - return fl_value_new_float((double)val); + { // Number + int tag = JS_VALUE_GET_TAG(val.v); + if (tag == JS_TAG_INT) + return fl_value_new_int((int64_t)val); + else if (JS_TAG_IS_FLOAT64(tag)) + return fl_value_new_float((double)val); + } if (JS_IsString(val.v)) return fl_value_new_string(((std::string)val).c_str()); { // ArrayBuffer size_t size; uint8_t *buf = JS_GetArrayBuffer(val.ctx, &size, val.v); if (buf) - // return (std::vector(buf, buf + size)); return fl_value_new_uint8_list(buf, size); } - FlValue *ret; - if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v)) - goto exception; - // if (JS_IsObject(val.v)) - // { - // if (JS_IsFunction(val.ctx, val.v)) - // { - // flutter::EncodableMap retMap; - // retMap[std::string("__js_function__")] = (int64_t) new JSValue{JS_DupValue(val.ctx, val.v)}; - // ret = retMap; - // } - // else if (JS_IsArray(val.ctx, val.v) > 0) - // { - // flutter::EncodableList retList; - // cache[val] = retList; - // uint32_t arrlen = (uint32_t)val["length"]; - // for (uint32_t i = 0; i < arrlen; i++) - // { - // retList.push_back(jsToDart(val[i], cache)); - // } - // ret = retList; - // } - // else - // { - // qjs::JSPropertyEnum *ptab; - // uint32_t plen; - // if (JS_GetOwnPropertyNames(val.ctx, &ptab, &plen, val.v, -1)) - // goto exception; - // flutter::EncodableMap retMap; - // cache[val] = retMap; - // for (uint32_t i = 0; i < plen; i++) - // { - // retMap[jsToDart({val.ctx, JS_AtomToValue(val.ctx, ptab[i].atom)}, cache)] = - // jsToDart({val.ctx, JS_GetProperty(val.ctx, val.v, ptab[i].atom)}, cache); - // JS_FreeAtom(val.ctx, ptab[i].atom); - // } - // js_free(val.ctx, ptab); - // ret = retMap; - // } - // goto done; - // } - exception: - ret = fl_value_new_null(); - done: - return ret; + if (JS_IsObject(val.v)) + { + if (JS_IsFunction(val.ctx, val.v)) + { + FlValue *retMap = fl_value_new_map(); + fl_value_set_string_take(retMap, "__js_function__", fl_value_new_int((int64_t) new JSValue{JS_DupValue(val.ctx, val.v)})); + return retMap; + } + else if (JS_IsArray(val.ctx, val.v) > 0) + { + FlValue *retList = fl_value_new_list(); + cache[val] = retList; + uint32_t arrlen = (uint32_t)val["length"]; + for (uint32_t i = 0; i < arrlen; i++) + { + fl_value_append_take(retList, jsToDart(val[i], cache)); + } + return retList; + } + else + { + qjs::JSPropertyEnum *ptab; + uint32_t plen; + if (JS_GetOwnPropertyNames(val.ctx, &ptab, &plen, val.v, -1)) + return fl_value_new_null(); + FlValue *retMap = fl_value_new_map(); + cache[val] = retMap; + for (uint32_t i = 0; i < plen; i++) + { + fl_value_set_take( + retMap, + jsToDart({val.ctx, JS_AtomToValue(val.ctx, ptab[i].atom)}, cache), + jsToDart({val.ctx, JS_GetProperty(val.ctx, val.v, ptab[i].atom)}, cache)); + JS_FreeAtom(val.ctx, ptab[i].atom); + } + js_free(val.ctx, ptab); + return retMap; + } + } + return fl_value_new_null(); } } // namespace qjs diff --git a/linux/flutter_qjs_plugin.cc b/linux/flutter_qjs_plugin.cc index 7dc0422..ccb3377 100644 --- a/linux/flutter_qjs_plugin.cc +++ b/linux/flutter_qjs_plugin.cc @@ -3,13 +3,12 @@ * @Author: ekibun * @Date: 2020-08-17 21:37:11 * @LastEditors: ekibun - * @LastEditTime: 2020-08-18 08:23:56 + * @LastEditTime: 2020-08-18 23:22:08 */ #include "include/flutter_qjs/flutter_qjs_plugin.h" #include #include -#include #include "dart_js_wrapper.hpp" #define FLUTTER_QJS_PLUGIN(obj) \ @@ -23,11 +22,44 @@ struct _FlutterQjsPlugin G_DEFINE_TYPE(FlutterQjsPlugin, flutter_qjs_plugin, g_object_get_type()) -g_autoptr(FlMethodChannel) channel = nullptr; +FlMethodChannel *channel = nullptr; + +void methodChannelInvokeCallback(GObject *object, GAsyncResult *result, gpointer user_data) +{ + auto promise = (std::promise *)user_data; + g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( + FL_METHOD_CHANNEL(object), result, nullptr); + g_autoptr(GError) error = nullptr; + g_autoptr(FlValue) res = fl_method_response_get_result(FL_METHOD_RESPONSE(response), &error); + fl_value_ref(res); + if (error) + { + promise->set_value((qjs::JSFutureReturn)[error_message = std::string(error->message)](qjs::JSContext * ctx) { + qjs::JSValue *ret = new qjs::JSValue{JS_NewString(ctx, error_message.c_str())}; + return qjs::JSOSFutureArgv{-1, ret}; + }); + } + else + { + auto pres = fl_value_ref(res); + promise->set_value((qjs::JSFutureReturn)[pres](qjs::JSContext * ctx) { + qjs::JSValue *ret = new qjs::JSValue{qjs::dartToJs(ctx, pres)}; + fl_value_unref(pres); + return qjs::JSOSFutureArgv{1, ret}; + }); + } +} std::promise *invokeChannelMethod(std::string name, qjs::Value args, qjs::Engine *engine) { auto promise = new std::promise(); + auto map = fl_value_new_map(); + fl_value_set_string_take(map, "engine", fl_value_new_int((int64_t)engine)); + fl_value_set_string_take(map, "args", qjs::jsToDart(args)); + fl_method_channel_invoke_method( + channel, name.c_str(), map, nullptr, + methodChannelInvokeCallback, + promise); return promise; } @@ -41,12 +73,8 @@ static void flutter_qjs_plugin_handle_method_call( if (strcmp(method, "createEngine") == 0) { qjs::Engine *engine = new qjs::Engine(invokeChannelMethod); - g_warning("engine %ld", engine); g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_int((int64_t)engine))); fl_method_call_respond(method_call, response, nullptr); - // g_autoptr(GError) error = nullptr; - // if (!fl_method_call_respond(method_call, response, &error)) - // g_warning("Failed to send method call response: %s", error->message); } else if (strcmp(method, "evaluate") == 0) { @@ -54,14 +82,12 @@ static void flutter_qjs_plugin_handle_method_call( qjs::Engine *engine = (qjs::Engine *)fl_value_get_int(fl_value_lookup_string(args, "engine")); std::string script(fl_value_get_string(fl_value_lookup_string(args, "script"))); std::string name(fl_value_get_string(fl_value_lookup_string(args, "name"))); - g_warning("engine %ld; script: %s; name: %s", (int64_t)engine, script.c_str(), name.c_str()); auto pmethod_call = (FlMethodCall *)g_object_ref(method_call); engine->commit(qjs::EngineTask{ [script, name](qjs::Context &ctx) { return ctx.eval(script, name.c_str(), JS_EVAL_TYPE_GLOBAL); }, [pmethod_call](qjs::Value resolve) { - g_warning("%s", fl_value_to_string(qjs::jsToDart(resolve))); g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(fl_method_success_response_new(qjs::jsToDart(resolve))); fl_method_call_respond(pmethod_call, response, nullptr); g_object_unref(pmethod_call); @@ -70,11 +96,37 @@ static void flutter_qjs_plugin_handle_method_call( fl_method_call_respond_error(pmethod_call, "FlutterJSException", qjs::getStackTrack(reject).c_str(), nullptr, nullptr); g_object_unref(pmethod_call); }}); - // g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(fl_method_success_response_new(args)); - // fl_method_call_respond(method_call, response, nullptr); - // g_autoptr(GError) error = nullptr; - // if (!fl_method_call_respond(method_call, response, &error)) - // g_warning("Failed to send method call response: %s", error->message); + } + else if (strcmp(method, "call") == 0) + { + FlValue *args = fl_method_call_get_args(method_call); + qjs::Engine *engine = (qjs::Engine *)fl_value_get_int(fl_value_lookup_string(args, "engine")); + qjs::JSValue *function = (qjs::JSValue *)fl_value_get_int(fl_value_lookup_string(args, "function")); + FlValue *arguments = fl_value_lookup_string(args, "arguments"); + auto pmethod_call = (FlMethodCall *)g_object_ref(method_call); + engine->commit(qjs::EngineTask{ + [function, arguments](qjs::Context &ctx) { + size_t argscount = fl_value_get_length(arguments); + qjs::JSValue *callargs = new qjs::JSValue[argscount]; + for (size_t i = 0; i < argscount; i++) + { + callargs[i] = qjs::dartToJs(ctx.ctx, fl_value_get_list_value(arguments, i)); + } + qjs::JSValue ret = JS_Call(ctx.ctx, *function, qjs::JSValue{qjs::JSValueUnion{0}, qjs::JS_TAG_UNDEFINED}, (int)argscount, callargs); + qjs::JS_FreeValue(ctx.ctx, *function); + if (qjs::JS_IsException(ret)) + throw qjs::exception{}; + return qjs::Value{ctx.ctx, ret}; + }, + [pmethod_call](qjs::Value resolve) { + g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(fl_method_success_response_new(qjs::jsToDart(resolve))); + fl_method_call_respond(pmethod_call, response, nullptr); + g_object_unref(pmethod_call); + }, + [pmethod_call](qjs::Value reject) { + fl_method_call_respond_error(pmethod_call, "FlutterJSException", qjs::getStackTrack(reject).c_str(), nullptr, nullptr); + g_object_unref(pmethod_call); + }}); } else { diff --git a/windows/dart_js_wrapper.hpp b/windows/dart_js_wrapper.hpp index dab1cf8..2260e48 100644 --- a/windows/dart_js_wrapper.hpp +++ b/windows/dart_js_wrapper.hpp @@ -3,7 +3,7 @@ * @Author: ekibun * @Date: 2020-08-14 21:45:02 * @LastEditors: ekibun - * @LastEditTime: 2020-08-16 19:52:35 + * @LastEditTime: 2020-08-18 13:44:05 */ #include "../cxx/js_engine.hpp" #include @@ -67,9 +67,8 @@ namespace qjs { auto buf = std::get>(val); JSValue array = JS_NewArray(ctx); - cache[val] = array; auto size = (uint32_t)buf.size(); - for (uint32_t i = 0; i < size; i++) + for (uint32_t i = 0; i < size; ++i) JS_DefinePropertyValue( ctx, array, JS_NewAtomUInt32(ctx, i), JS_NewFloat64(ctx, buf[i]), JS_PROP_C_W_E); @@ -103,6 +102,8 @@ namespace qjs flutter::EncodableValue jsToDart(Value val, std::unordered_map cache = std::unordered_map()) { + if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v)) + return flutter::EncodableValue(); if (cache.find(val) != cache.end()) return cache[val]; if (JS_IsBool(val.v)) @@ -110,13 +111,9 @@ namespace qjs { int tag = JS_VALUE_GET_TAG(val.v); if (tag == JS_TAG_INT) - { return (int64_t)val; - } else if (JS_TAG_IS_FLOAT64(tag)) - { return (double)val; - } } if (JS_IsString(val.v)) return (std::string)val; @@ -126,16 +123,13 @@ namespace qjs if (buf) return (std::vector(buf, buf + size)); } - flutter::EncodableValue ret; - if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v)) - goto exception; if (JS_IsObject(val.v)) { if (JS_IsFunction(val.ctx, val.v)) { flutter::EncodableMap retMap; retMap[std::string("__js_function__")] = (int64_t) new JSValue{JS_DupValue(val.ctx, val.v)}; - ret = retMap; + return retMap; } else if (JS_IsArray(val.ctx, val.v) > 0) { @@ -146,14 +140,14 @@ namespace qjs { retList.push_back(jsToDart(val[i], cache)); } - ret = retList; + return retList; } else { qjs::JSPropertyEnum *ptab; uint32_t plen; if (JS_GetOwnPropertyNames(val.ctx, &ptab, &plen, val.v, -1)) - goto exception; + return flutter::EncodableValue(); flutter::EncodableMap retMap; cache[val] = retMap; for (uint32_t i = 0; i < plen; i++) @@ -163,13 +157,9 @@ namespace qjs JS_FreeAtom(val.ctx, ptab[i].atom); } js_free(val.ctx, ptab); - ret = retMap; + return retMap; } - goto done; } - exception: - ret = flutter::EncodableValue(); - done: - return ret; + return flutter::EncodableValue(); } } // namespace qjs diff --git a/windows/flutter_qjs_plugin.cpp b/windows/flutter_qjs_plugin.cpp index 78d577b..ebfca37 100644 --- a/windows/flutter_qjs_plugin.cpp +++ b/windows/flutter_qjs_plugin.cpp @@ -35,7 +35,7 @@ namespace auto promise = new std::promise(); auto map = new flutter::EncodableMap(); (*map)[std::string("engine")] = (int64_t)engine; - (*map)[std::string("args")] = qjs::jsToDart(args, std::unordered_map()); + (*map)[std::string("args")] = qjs::jsToDart(args); channel->InvokeMethod( name, std::make_unique(*map),