From 7f8938cf7bf1b2933a76cae3d3ac418e27a7c90e Mon Sep 17 00:00:00 2001 From: ekibun Date: Wed, 19 Aug 2020 00:43:19 +0800 Subject: [PATCH] fix crash with js Symbol type --- .vscode/launch.json | 28 +---------- android/src/main/jni/java_js_wrapper.hpp | 40 +++++++--------- linux/dart_js_wrapper.hpp | 59 ++++++++---------------- windows/dart_js_wrapper.hpp | 55 ++++++++-------------- 4 files changed, 58 insertions(+), 124 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2ac90dd..3331972 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,37 +4,11 @@ // 欲了解更多信息,请访问: 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", "request": "launch", - "program": "example/build/windows/runner/Debug/flutter_qjs_example.exe", + "program": "${workspaceFolder}/example/build/windows/runner/Debug/example.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/android/src/main/jni/java_js_wrapper.hpp b/android/src/main/jni/java_js_wrapper.hpp index 91fd2aa..dcdf8a3 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-18 23:41:02 + * @LastEditTime: 2020-08-19 00:40:54 */ #include #include @@ -18,7 +18,7 @@ namespace std { std::size_t operator()(const qjs::Value &key) const { - return std::hash()((std::string)key); + return JS_VALUE_GET_TAG(key.v); } }; } // namespace std @@ -146,24 +146,19 @@ namespace qjs jobject jsToJava(JNIEnv *env, qjs::Value val, std::unordered_map cache = std::unordered_map()) { - if (cache.find(val) != cache.end()) - return cache[val]; - if (JS_IsBool(val.v)) + int tag = JS_VALUE_GET_TAG(val.v); + if (JS_TAG_IS_FLOAT64(tag)) + return jniWrapPrimity(env, (double)val); + switch (tag) + { + case JS_TAG_BOOL: return jniWrapPrimity(env, (bool)val); - { - int tag = JS_VALUE_GET_TAG(val.v); - if (tag == JS_TAG_INT) - { - return jniWrapPrimity(env, (int64_t)val); - } - else if (JS_TAG_IS_FLOAT64(tag)) - { - return jniWrapPrimity(env, (double)val); - } - } - if (JS_IsString(val.v)) + case JS_TAG_INT: + return jniWrapPrimity(env, (int64_t)val); + case JS_TAG_STRING: return env->NewStringUTF(((std::string)val).c_str()); - { + case JS_TAG_OBJECT: + { // ArrayBuffer size_t size; uint8_t *buf = JS_GetArrayBuffer(val.ctx, &size, val.v); if (buf) @@ -173,10 +168,8 @@ namespace qjs return arr; } } - if (JS_IsUndefined(val.v) || JS_IsNull(val.v) || JS_IsUninitialized(val.v)) - return nullptr; - if (JS_IsObject(val.v)) - { + if (cache.find(val) != cache.end()) + return cache[val]; if (JS_IsFunction(val.ctx, val.v)) { std::map retMap; @@ -215,7 +208,8 @@ namespace qjs cache[val] = ret; return ret; } + default: + return nullptr; } - return nullptr; } } // namespace qjs diff --git a/linux/dart_js_wrapper.hpp b/linux/dart_js_wrapper.hpp index 1b280ec..4e75a99 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-18 20:29:34 + * @LastEditTime: 2020-08-19 00:34:43 */ #include "../cxx/js_engine.hpp" #include @@ -13,30 +13,19 @@ namespace std template <> struct hash { - std::size_t operator()(const qjs::Value &key) const + size_t operator()(const qjs::Value &key) const { - return std::hash()((std::string)key); - } - }; - - template <> - struct hash - { - std::size_t operator()(const FlValue *&key) const - { - return 0; + return JS_VALUE_GET_TAG(key.v); } }; } // namespace std namespace qjs { - JSValue dartToJs(JSContext *ctx, FlValue *val, std::unordered_map cache = std::unordered_map()) + JSValue dartToJs(JSContext *ctx, FlValue *val) { - if (val == nullptr || fl_value_get_type(val) == FL_VALUE_TYPE_NULL) + if (val == nullptr) return JS_UNDEFINED; - if (cache.find(val) != cache.end()) - return cache[val]; FlValueType valType = fl_value_get_type(val); switch (valType) { @@ -59,7 +48,6 @@ namespace qjs 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]), @@ -70,11 +58,10 @@ namespace qjs { 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), + dartToJs(ctx, fl_value_get_list_value(val, i)), JS_PROP_C_W_E); return array; } @@ -82,46 +69,39 @@ namespace qjs { 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_ValueToAtom(ctx, dartToJs(ctx, fl_value_get_map_key(val, i))), + dartToJs(ctx, fl_value_get_map_value(val, i)), JS_PROP_C_W_E); return obj; } default: return JS_UNDEFINED; } - 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)) + int tag = JS_VALUE_GET_TAG(val.v); + if (JS_TAG_IS_FLOAT64(tag)) + return fl_value_new_float((double)val); + switch (tag) + { + case JS_TAG_BOOL: return fl_value_new_bool((bool)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)) + case JS_TAG_INT: + return fl_value_new_int((int64_t)val); + case JS_TAG_STRING: return fl_value_new_string(((std::string)val).c_str()); + case JS_TAG_OBJECT: { // ArrayBuffer size_t size; uint8_t *buf = JS_GetArrayBuffer(val.ctx, &size, val.v); if (buf) return fl_value_new_uint8_list(buf, size); } - if (JS_IsObject(val.v)) - { if (JS_IsFunction(val.ctx, val.v)) { FlValue *retMap = fl_value_new_map(); @@ -158,7 +138,8 @@ namespace qjs js_free(val.ctx, ptab); return retMap; } + default: + return fl_value_new_null(); } - return fl_value_new_null(); } } // namespace qjs diff --git a/windows/dart_js_wrapper.hpp b/windows/dart_js_wrapper.hpp index 2260e48..44b62a3 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-18 13:44:05 + * @LastEditTime: 2020-08-19 00:35:29 */ #include "../cxx/js_engine.hpp" #include @@ -14,30 +14,19 @@ namespace std template <> struct hash { - std::size_t operator()(const qjs::Value &key) const + size_t operator()(const qjs::Value &key) const { - return std::hash()((std::string)key); - } - }; - - template <> - struct hash - { - std::size_t operator()(const flutter::EncodableValue &key) const - { - return key.index(); + return JS_VALUE_GET_TAG(key.v); } }; } // namespace std namespace qjs { - JSValue dartToJs(JSContext *ctx, flutter::EncodableValue val, std::unordered_map cache = std::unordered_map()) + JSValue dartToJs(JSContext *ctx, flutter::EncodableValue val) { if (val.IsNull()) return JS_UNDEFINED; - if (cache.find(val) != cache.end()) - return cache[val]; if (std::holds_alternative(val)) return JS_NewBool(ctx, std::get(val)); if (std::holds_alternative(val)) @@ -78,11 +67,10 @@ namespace qjs { 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), + ctx, array, JS_NewAtomUInt32(ctx, i), dartToJs(ctx, list[i]), JS_PROP_C_W_E); return array; } @@ -90,10 +78,9 @@ namespace qjs { 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), + ctx, obj, JS_ValueToAtom(ctx, dartToJs(ctx, iter->first)), dartToJs(ctx, iter->second), JS_PROP_C_W_E); return obj; } @@ -102,29 +89,26 @@ 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)) - return (bool)val; + int tag = JS_VALUE_GET_TAG(val.v); + if (JS_TAG_IS_FLOAT64(tag)) + return (double)val; + switch (tag) { - 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)) + case JS_TAG_BOOL: + return (bool)val; + case JS_TAG_INT: + return (int64_t)val; + case JS_TAG_STRING: return (std::string)val; + case JS_TAG_OBJECT: { // ArrayBuffer size_t size; uint8_t *buf = JS_GetArrayBuffer(val.ctx, &size, val.v); if (buf) return (std::vector(buf, buf + size)); } - if (JS_IsObject(val.v)) - { + if (cache.find(val) != cache.end()) + return cache[val]; if (JS_IsFunction(val.ctx, val.v)) { flutter::EncodableMap retMap; @@ -159,7 +143,8 @@ namespace qjs js_free(val.ctx, ptab); return retMap; } + default: + return flutter::EncodableValue(); } - return flutter::EncodableValue(); } } // namespace qjs