diff --git a/cxx/ffi.cpp b/cxx/ffi.cpp index c300694..4e130dd 100644 --- a/cxx/ffi.cpp +++ b/cxx/ffi.cpp @@ -320,6 +320,11 @@ extern "C" return JS_IsArray(ctx, *val); } + DLLEXPORT int32_t jsIsMap(JSContext *ctx, JSValueConst *val) + { + return JS_IsMap(ctx, *val); + } + DLLEXPORT int32_t jsIsError(JSContext *ctx, JSValueConst *val) { return JS_IsError(ctx, *val); diff --git a/cxx/ffi.h b/cxx/ffi.h index 6939105..3d593b4 100644 --- a/cxx/ffi.h +++ b/cxx/ffi.h @@ -97,6 +97,8 @@ extern "C" DLLEXPORT int32_t jsIsArray(JSContext *ctx, JSValueConst *val); + DLLEXPORT int32_t jsIsMap(JSContext *ctx, JSValueConst *val); + DLLEXPORT int32_t jsIsError(JSContext *ctx, JSValueConst *val); DLLEXPORT JSValue *jsNewError(JSContext *ctx); diff --git a/cxx/quickjs/quickjs.c b/cxx/quickjs/quickjs.c index e9b0ac0..74c6130 100644 --- a/cxx/quickjs/quickjs.c +++ b/cxx/quickjs/quickjs.c @@ -12148,6 +12148,21 @@ int JS_IsArray(JSContext *ctx, JSValueConst val) } } +/* return -1 if exception (proxy case) or TRUE/FALSE */ +int JS_IsMap(JSContext *ctx, JSValueConst val) +{ + JSObject *p; + if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { + p = JS_VALUE_GET_OBJ(val); + if (unlikely(p->class_id == JS_CLASS_PROXY)) + return js_proxy_isMap(ctx, val); + else + return p->class_id == JS_CLASS_MAP; + } else { + return FALSE; + } +} + static double js_pow(double a, double b) { if (unlikely(!isfinite(b)) && fabs(a) == 1) { @@ -46709,6 +46724,22 @@ static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) return JS_IsArray(ctx, s->target); } +static int js_proxy_isMap(JSContext *ctx, JSValueConst obj) +{ + JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); + if (!s) + return FALSE; + if (js_check_stack_overflow(ctx->rt, 0)) { + JS_ThrowStackOverflow(ctx); + return -1; + } + if (s->is_revoked) { + JS_ThrowTypeErrorRevokedProxy(ctx); + return -1; + } + return JS_IsMap(ctx, s->target); +} + static const JSClassExoticMethods js_proxy_exotic_methods = { .get_own_property = js_proxy_get_own_property, .define_own_property = js_proxy_define_own_property, diff --git a/cxx/quickjs/quickjs.h b/cxx/quickjs/quickjs.h index 84597fc..d0042b9 100644 --- a/cxx/quickjs/quickjs.h +++ b/cxx/quickjs/quickjs.h @@ -738,6 +738,7 @@ JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val) JSValue JS_NewArray(JSContext *ctx); int JS_IsArray(JSContext *ctx, JSValueConst val); +int JS_IsMap(JSContext *ctx, JSValueConst val); JSValue JS_NewDate(JSContext *ctx, double epoch_ms); diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index d058a0d..cccf817 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,6 @@ import FlutterMacOS import Foundation -import flutter_qjs func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FlutterQjsPlugin.register(with: registry.registrar(forPlugin: "FlutterQjsPlugin")) } diff --git a/lib/src/engine.dart b/lib/src/engine.dart index 82cf412..be8ae79 100644 --- a/lib/src/engine.dart +++ b/lib/src/engine.dart @@ -51,25 +51,25 @@ class FlutterQjs { switch (type) { case JSChannelType.METHON: final pdata = ptr.cast>(); - final argc = pdata.elementAt(1).value.cast().value; + final argc = (pdata + 1).value.cast().value; final pargs = []; for (var i = 0; i < argc; ++i) { pargs.add(_jsToDart( ctx, Pointer.fromAddress( - pdata.elementAt(2).value.address + sizeOfJSValue * i, + (pdata + 2).value.address + sizeOfJSValue * i, ), )); } final JSInvokable func = _jsToDart( ctx, - pdata.elementAt(3).value, + (pdata + 3).value, ); return _dartToJs( ctx, func.invoke( pargs, - _jsToDart(ctx, pdata.elementAt(0).value), + _jsToDart(ctx, pdata.value), )); case JSChannelType.MODULE: if (moduleHandler == null) throw JSError('No ModuleHandler'); diff --git a/lib/src/ffi.dart b/lib/src/ffi.dart index 3bf18d5..2e38578 100644 --- a/lib/src/ffi.dart +++ b/lib/src/ffi.dart @@ -759,6 +759,19 @@ final int Function( )>>('jsIsArray') .asFunction(); +/// int32_t jsIsMap(JSContext *ctx, JSValueConst *val) +final int Function( + Pointer ctx, + Pointer val, + ) jsIsMap = _qjsLib + .lookup< + NativeFunction< + Int32 Function( + Pointer, + Pointer, + )>>('jsIsMap') + .asFunction(); + /// DLLEXPORT int32_t jsIsError(JSContext *ctx, JSValueConst *val); final int Function( Pointer ctx, diff --git a/lib/src/object.dart b/lib/src/object.dart index 9e810f6..c81d311 100644 --- a/lib/src/object.dart +++ b/lib/src/object.dart @@ -192,7 +192,7 @@ class _JSFunction extends _JSObject implements JSInvokable, _IsolateEncodable { } @override - call(List args) => invoke(args); + call(List args, [dynamic thisVal]) => invoke(args, thisVal); } /// Dart function wrapper for isolate diff --git a/lib/src/wrapper.dart b/lib/src/wrapper.dart index 71b03d5..a5ba8bf 100644 --- a/lib/src/wrapper.dart +++ b/lib/src/wrapper.dart @@ -218,7 +218,20 @@ dynamic _jsToDart(Pointer ctx, Pointer val, jsFreeValue(ctx, jsProp); } return ret; - } else { + } else if(jsIsMap(ctx, val) != 0) { + final map = Map(); + final jsMap = _JSObject(ctx, val); + void callback(key, value) { + map[key] = value; + }; + var jsFunc = jsEval(ctx, "(m, callback) => { m.forEach((value, key, _) => { callback(key, value) }) }", "eval", JSEvalFlag.GLOBAL); + var func = _jsToDart(ctx, jsFunc) as JSInvokable; + jsFreeValue(ctx, jsFunc); + func.invoke([jsMap, callback]); + jsMap.destroy(); + func.destroy(); + return map; + } else{ final ptab = malloc>(); final plen = malloc(); if (jsGetOwnPropertyNames(ctx, ptab, plen, val, -1) != 0) {