diff --git a/CHANGELOG.md b/CHANGELOG.md index 7941b38..a2a2e57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ * @LastEditTime: 2020-12-02 11:36:40 --> +## 0.3.2 + +* fix Promise reject cannot get Exception string. + ## 0.3.1 * code clean up. diff --git a/README.md b/README.md index 1a1797e..2a85e43 100644 --- a/README.md +++ b/README.md @@ -100,16 +100,7 @@ To use async function in module handler, try [Run on isolate thread](#Run-on-iso Create a `IsolateQjs` object, pass handlers to resolving modules. Async function such as `rootBundle.loadString` can be used now to get modules: ```dart -dynamic methodHandler(String method, List arg) { - switch (method) { - case "http": - return Dio().get(arg[0]).then((response) => response.data); - default: - throw Exception("No such method"); - } -} final engine = IsolateQjs( - methodHandler: methodHandler, moduleHandler: (String module) async { return await rootBundle.loadString( "js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js"); @@ -134,9 +125,9 @@ Method `close` can destroy quickjs runtime that can be recreated again if you ca Method `bind` can help to pass instance function to isolate: ```dart -await setToGlobalObject("func", await engine.bind(({thisVal}) { +await jsFunc(await engine.bind(({thisVal}) { // DO SOMETHING -})) +})); ``` [This example](example/lib/main.dart) contains a complete demonstration on how to use this plugin. @@ -148,5 +139,5 @@ Use js function to set dart object globally: ```dart final setToGlobalObject = await engine.evaluate("(key, val) => this[key] = val;"); -setToGlobalObject("channel", methodHandler); +await setToGlobalObject("channel", methodHandler); ``` \ No newline at end of file diff --git a/example/pubspec.lock b/example/pubspec.lock index 2e79c76..0566f0c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -75,7 +75,7 @@ packages: path: ".." relative: true source: path - version: "0.3.1" + version: "0.3.2" flutter_test: dependency: "direct dev" description: flutter diff --git a/lib/ffi.dart b/lib/ffi.dart index 3a4d9bd..4a07bd5 100644 --- a/lib/ffi.dart +++ b/lib/ffi.dart @@ -57,14 +57,14 @@ class JSTag { final DynamicLibrary _qjsLib = Platform.environment['FLUTTER_TEST'] == 'true' ? (Platform.isWindows - ? DynamicLibrary.open("test/build/Debug/ffiquickjs.dll") + ? DynamicLibrary.open('test/build/Debug/ffiquickjs.dll') : Platform.isMacOS - ? DynamicLibrary.open("test/build/libffiquickjs.dylib") - : DynamicLibrary.open("test/build/libffiquickjs.so")) + ? DynamicLibrary.open('test/build/libffiquickjs.dylib') + : DynamicLibrary.open('test/build/libffiquickjs.so')) : (Platform.isWindows - ? DynamicLibrary.open("flutter_qjs_plugin.dll") + ? DynamicLibrary.open('flutter_qjs_plugin.dll') : Platform.isAndroid - ? DynamicLibrary.open("libqjs.so") + ? DynamicLibrary.open('libqjs.so') : DynamicLibrary.process()); /// JSValue *jsThrowInternalError(JSContext *ctx, char *message) @@ -77,7 +77,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsThrowInternalError") + )>>('jsThrowInternalError') .asFunction(); Pointer jsThrowInternalError(Pointer ctx, String message) { @@ -89,12 +89,12 @@ Pointer jsThrowInternalError(Pointer ctx, String message) { /// JSValue *jsEXCEPTION() final Pointer Function() jsEXCEPTION = _qjsLib - .lookup>("jsEXCEPTION") + .lookup>('jsEXCEPTION') .asFunction(); /// JSValue *jsUNDEFINED() final Pointer Function() jsUNDEFINED = _qjsLib - .lookup>("jsUNDEFINED") + .lookup>('jsUNDEFINED') .asFunction(); typedef JSChannel = Pointer Function(Pointer ctx, int method, Pointer argv); @@ -109,7 +109,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsNewRuntime") + )>>('jsNewRuntime') .asFunction(); class RuntimeOpaque { @@ -147,7 +147,7 @@ final void Function( Void Function( Pointer, IntPtr, - )>>("jsSetMaxStackSize") + )>>('jsSetMaxStackSize') .asFunction(); /// void jsFreeRuntime(JSRuntime *rt) @@ -158,7 +158,7 @@ final void Function( NativeFunction< Void Function( Pointer, - )>>("jsFreeRuntime") + )>>('jsFreeRuntime') .asFunction(); void jsFreeRuntime( @@ -181,7 +181,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsNewCFunction") + )>>('jsNewCFunction') .asFunction(); /// JSContext *jsNewContext(JSRuntime *rt) @@ -192,14 +192,14 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsNewContext") + )>>('jsNewContext') .asFunction(); Pointer jsNewContext(Pointer rt) { var ctx = _jsNewContext(rt); final runtimeOpaque = runtimeOpaques[rt]; - if (runtimeOpaque == null) throw Exception("Runtime has been released!"); - runtimeOpaque.dartObjectClassId = jsNewClass(ctx, "DartObject"); + if (runtimeOpaque == null) throw Exception('Runtime has been released!'); + runtimeOpaque.dartObjectClassId = jsNewClass(ctx, 'DartObject'); return ctx; } @@ -211,7 +211,7 @@ final void Function( NativeFunction< Void Function( Pointer, - )>>("jsFreeContext") + )>>('jsFreeContext') .asFunction(); /// JSRuntime *jsGetRuntime(JSContext *ctx) @@ -222,7 +222,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsGetRuntime") + )>>('jsGetRuntime') .asFunction(); /// JSValue *jsEval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int eval_flags) @@ -241,7 +241,7 @@ final Pointer Function( IntPtr, Pointer, Int32, - )>>("jsEval") + )>>('jsEval') .asFunction(); Pointer jsEval( @@ -273,7 +273,7 @@ final int Function( NativeFunction< Int32 Function( Pointer, - )>>("jsValueGetTag") + )>>('jsValueGetTag') .asFunction(); /// void *jsValueGetPtr(JSValue *val) @@ -284,7 +284,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsValueGetPtr") + )>>('jsValueGetPtr') .asFunction(); /// DLLEXPORT bool jsTagIsFloat64(int32_t tag) @@ -295,7 +295,7 @@ final int Function( NativeFunction< Int32 Function( Int32, - )>>("jsTagIsFloat64") + )>>('jsTagIsFloat64') .asFunction(); /// JSValue *jsNewBool(JSContext *ctx, int val) @@ -308,7 +308,7 @@ final Pointer Function( Pointer Function( Pointer, Int32, - )>>("jsNewBool") + )>>('jsNewBool') .asFunction(); /// JSValue *jsNewInt64(JSContext *ctx, int64_t val) @@ -321,7 +321,7 @@ final Pointer Function( Pointer Function( Pointer, Int64, - )>>("jsNewInt64") + )>>('jsNewInt64') .asFunction(); /// JSValue *jsNewFloat64(JSContext *ctx, double val) @@ -334,7 +334,7 @@ final Pointer Function( Pointer Function( Pointer, Double, - )>>("jsNewFloat64") + )>>('jsNewFloat64') .asFunction(); /// JSValue *jsNewString(JSContext *ctx, const char *str) @@ -347,7 +347,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsNewString") + )>>('jsNewString') .asFunction(); Pointer jsNewString( @@ -370,7 +370,7 @@ final Pointer Function( Pointer, Pointer, IntPtr, - )>>("jsNewArrayBufferCopy") + )>>('jsNewArrayBufferCopy') .asFunction(); /// JSValue *jsNewArray(JSContext *ctx) @@ -381,7 +381,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsNewArray") + )>>('jsNewArray') .asFunction(); /// JSValue *jsNewObject(JSContext *ctx) @@ -392,7 +392,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsNewObject") + )>>('jsNewObject') .asFunction(); /// void jsFreeValue(JSContext *ctx, JSValue *val, int32_t free) @@ -407,7 +407,7 @@ final void Function( Pointer, Pointer, Int32, - )>>("jsFreeValue") + )>>('jsFreeValue') .asFunction(); void jsFreeValue( @@ -430,7 +430,7 @@ final void Function( Pointer, Pointer, Int32, - )>>("jsFreeValueRT") + )>>('jsFreeValueRT') .asFunction(); void jsFreeValueRT( @@ -451,7 +451,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsDupValue") + )>>('jsDupValue') .asFunction(); /// JSValue *jsDupValueRT(JSRuntime *rt, JSValue *v) @@ -464,7 +464,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsDupValueRT") + )>>('jsDupValueRT') .asFunction(); /// int32_t jsToBool(JSContext *ctx, JSValueConst *val) @@ -477,7 +477,7 @@ final int Function( Int32 Function( Pointer, Pointer, - )>>("jsToBool") + )>>('jsToBool') .asFunction(); /// int64_t jsToFloat64(JSContext *ctx, JSValueConst *val) @@ -490,7 +490,7 @@ final int Function( Int64 Function( Pointer, Pointer, - )>>("jsToInt64") + )>>('jsToInt64') .asFunction(); /// double jsToFloat64(JSContext *ctx, JSValueConst *val) @@ -503,7 +503,7 @@ final double Function( Double Function( Pointer, Pointer, - )>>("jsToFloat64") + )>>('jsToFloat64') .asFunction(); /// const char *jsToCString(JSContext *ctx, JSValue *val) @@ -516,7 +516,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsToCString") + )>>('jsToCString') .asFunction(); /// void jsFreeCString(JSContext *ctx, const char *ptr) @@ -529,7 +529,7 @@ final void Function( Void Function( Pointer, Pointer, - )>>("jsFreeCString") + )>>('jsFreeCString') .asFunction(); String jsToCString( @@ -537,7 +537,7 @@ String jsToCString( Pointer val, ) { var ptr = _jsToCString(ctx, val); - if (ptr.address == 0) throw Exception("JSValue cannot convert to string"); + if (ptr.address == 0) throw Exception('JSValue cannot convert to string'); var str = Utf8.fromUtf8(ptr); jsFreeCString(ctx, ptr); return str; @@ -553,7 +553,7 @@ final int Function( Uint32 Function( Pointer, Pointer, - )>>("jsNewClass") + )>>('jsNewClass') .asFunction(); int jsNewClass( @@ -581,7 +581,7 @@ final Pointer Function( Pointer, Uint32, IntPtr, - )>>("jsNewObjectClass") + )>>('jsNewObjectClass') .asFunction(); /// DLLEXPORT void *jsGetObjectOpaque(JSValue *obj, uint32_t classid) @@ -594,7 +594,7 @@ final int Function( IntPtr Function( Pointer, Uint32, - )>>("jsGetObjectOpaque") + )>>('jsGetObjectOpaque') .asFunction(); /// uint8_t *jsGetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst *obj) @@ -609,7 +609,7 @@ final Pointer Function( Pointer, Pointer, Pointer, - )>>("jsGetArrayBuffer") + )>>('jsGetArrayBuffer') .asFunction(); /// int32_t jsIsFunction(JSContext *ctx, JSValueConst *val) @@ -622,7 +622,7 @@ final int Function( Int32 Function( Pointer, Pointer, - )>>("jsIsFunction") + )>>('jsIsFunction') .asFunction(); /// int32_t jsIsPromise(JSContext *ctx, JSValueConst *val) @@ -635,7 +635,7 @@ final int Function( Int32 Function( Pointer, Pointer, - )>>("jsIsPromise") + )>>('jsIsPromise') .asFunction(); /// int32_t jsIsArray(JSContext *ctx, JSValueConst *val) @@ -648,7 +648,7 @@ final int Function( Int32 Function( Pointer, Pointer, - )>>("jsIsArray") + )>>('jsIsArray') .asFunction(); /// JSValue *jsGetProperty(JSContext *ctx, JSValueConst *this_obj, @@ -664,7 +664,7 @@ final Pointer Function( Pointer, Pointer, Uint32, - )>>("jsGetProperty") + )>>('jsGetProperty') .asFunction(); /// int jsDefinePropertyValue(JSContext *ctx, JSValueConst *this_obj, @@ -684,7 +684,7 @@ final int Function( Uint32, Pointer, Int32, - )>>("jsDefinePropertyValue") + )>>('jsDefinePropertyValue') .asFunction(); /// void jsFreeAtom(JSContext *ctx, JSAtom v) @@ -697,7 +697,7 @@ final Pointer Function( Pointer Function( Pointer, Uint32, - )>>("jsFreeAtom") + )>>('jsFreeAtom') .asFunction(); /// JSAtom jsValueToAtom(JSContext *ctx, JSValueConst *val) @@ -710,7 +710,7 @@ final int Function( Uint32 Function( Pointer, Pointer, - )>>("jsValueToAtom") + )>>('jsValueToAtom') .asFunction(); /// JSValue *jsAtomToValue(JSContext *ctx, JSAtom val) @@ -723,7 +723,7 @@ final Pointer Function( Pointer Function( Pointer, Uint32, - )>>("jsAtomToValue") + )>>('jsAtomToValue') .asFunction(); /// int jsGetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, @@ -743,7 +743,7 @@ final int Function( Pointer, Pointer, Int32, - )>>("jsGetOwnPropertyNames") + )>>('jsGetOwnPropertyNames') .asFunction(); /// JSAtom jsPropertyEnumGetAtom(JSPropertyEnum *ptab, int i) @@ -756,12 +756,12 @@ final int Function( Uint32 Function( Pointer, Int32, - )>>("jsPropertyEnumGetAtom") + )>>('jsPropertyEnumGetAtom') .asFunction(); /// uint32_t sizeOfJSValue() final int Function() _sizeOfJSValue = _qjsLib - .lookup>("sizeOfJSValue") + .lookup>('sizeOfJSValue') .asFunction(); final sizeOfJSValue = _sizeOfJSValue(); @@ -778,7 +778,7 @@ final void Function( Pointer, Uint32, Pointer, - )>>("setJSValueList") + )>>('setJSValueList') .asFunction(); /// JSValue *jsCall(JSContext *ctx, JSValueConst *func_obj, JSValueConst *this_obj, @@ -798,7 +798,7 @@ final Pointer Function( Pointer, Int32, Pointer, - )>>("jsCall") + )>>('jsCall') .asFunction(); Pointer jsCall( @@ -834,7 +834,7 @@ final int Function( NativeFunction< Int32 Function( Pointer, - )>>("jsIsException") + )>>('jsIsException') .asFunction(); /// JSValue *jsGetException(JSContext *ctx) @@ -845,7 +845,7 @@ final Pointer Function( NativeFunction< Pointer Function( Pointer, - )>>("jsGetException") + )>>('jsGetException') .asFunction(); /// int jsExecutePendingJob(JSRuntime *rt) @@ -856,7 +856,7 @@ final int Function( NativeFunction< Int32 Function( Pointer, - )>>("jsExecutePendingJob") + )>>('jsExecutePendingJob') .asFunction(); /// JSValue *jsNewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs) @@ -869,7 +869,7 @@ final Pointer Function( Pointer Function( Pointer, Pointer, - )>>("jsNewPromiseCapability") + )>>('jsNewPromiseCapability') .asFunction(); /// void jsFree(JSContext *ctx, void *ptab) @@ -882,5 +882,5 @@ final void Function( Void Function( Pointer, Pointer, - )>>("jsFree") + )>>('jsFree') .asFunction(); diff --git a/lib/flutter_qjs.dart b/lib/flutter_qjs.dart index e02deb8..07f3db4 100644 --- a/lib/flutter_qjs.dart +++ b/lib/flutter_qjs.dart @@ -50,20 +50,25 @@ class FlutterQjs { case JSChannelType.METHON: final pdata = ptr.cast(); final argc = pdata.elementAt(1).value.cast().value; - List args = []; + List pargs = []; for (var i = 0; i < argc; i++) { - args.add(jsToDart( - ctx, - Pointer.fromAddress( - pdata.elementAt(2).value.address + sizeOfJSValue * i, - ))); + pargs.add(Pointer.fromAddress( + pdata.elementAt(2).value.address + sizeOfJSValue * i, + )); } - final thisVal = jsToDart(ctx, pdata.elementAt(0).value); + final pThis = pdata.elementAt(0).value; JSInvokable func = jsToDart(ctx, pdata.elementAt(3).value); - final ret = func.invoke(args, thisVal); - return dartToJs(ctx, ret); + if (func is NativeJSInvokable) { + return dartToJs(ctx, func.invokeNative(ctx, pThis, pargs)); + } + return dartToJs( + ctx, + func.invoke( + pargs.map((e) => jsToDart(ctx, e)).toList(), + jsToDart(ctx, pThis), + )); case JSChannelType.MODULE: - if (moduleHandler == null) throw Exception("No ModuleHandler"); + if (moduleHandler == null) throw Exception('No ModuleHandler'); var ret = Utf8.toUtf8(moduleHandler( Utf8.fromUtf8(ptr.cast()), )); @@ -72,11 +77,11 @@ class FlutterQjs { }); return ret; case JSChannelType.PROMISE_TRACK: - final errStr = parseJSException(ctx, perr: ptr); + final errStr = parseJSException(ctx, ptr); if (hostPromiseRejectionHandler != null) { hostPromiseRejectionHandler(errStr); } else { - print("unhandled promise rejection: $errStr"); + print('unhandled promise rejection: $errStr'); } return Pointer.fromAddress(0); case JSChannelType.FREE_OBJECT: @@ -86,15 +91,15 @@ class FlutterQjs { runtimeOpaques[rt]?.ref?.remove(obj); return Pointer.fromAddress(0); } - throw Exception("call channel with wrong type"); + throw Exception('call channel with wrong type'); } catch (e, stack) { - final errStr = e.toString() + "\n" + stack.toString(); + final errStr = e.toString() + '\n' + stack.toString(); if (type == JSChannelType.FREE_OBJECT) { - print("DartObject release error: " + errStr); + print('DartObject release error: ' + errStr); return Pointer.fromAddress(0); } if (type == JSChannelType.MODULE) { - print("host Promise Rejection Handler error: " + errStr); + print('host Promise Rejection Handler error: ' + errStr); return Pointer.fromAddress(0); } var err = jsThrowInternalError( @@ -143,12 +148,12 @@ class FlutterQjs { var jsval = jsEval( _ctx, command, - name ?? "", + name ?? '', evalFlags ?? JSEvalFlag.GLOBAL, ); if (jsIsException(jsval) != 0) { jsFreeValue(_ctx, jsval); - throw Exception(parseJSException(_ctx)); + throw parseJSException(_ctx); } var result = jsToDart(_ctx, jsval); jsFreeValue(_ctx, jsval); diff --git a/lib/isolate.dart b/lib/isolate.dart index 0180216..15dfc62 100644 --- a/lib/isolate.dart +++ b/lib/isolate.dart @@ -35,7 +35,7 @@ void _runJsIsolate(Map spawnMessage) async { 'ptr': ptr.address, }); while (ptr.value.address == 0) sleep(Duration.zero); - if (ptr.value.address == -1) throw Exception("Module Not found"); + if (ptr.value.address == -1) throw Exception('Module Not found'); var ret = Utf8.fromUtf8(ptr.value); sendPort.send({ 'type': 'release', @@ -58,7 +58,7 @@ void _runJsIsolate(Map spawnMessage) async { ); break; case 'call': - data = JSFunction.fromAddress( + data = await JSFunction.fromAddress( Pointer.fromAddress(msg['ctx']), Pointer.fromAddress(msg['val']), ).invoke( @@ -79,7 +79,7 @@ void _runJsIsolate(Map spawnMessage) async { } catch (e, stack) { if (msgPort != null) msgPort.send({ - 'error': e.toString() + "\n" + stack.toString(), + 'error': e.toString() + '\n' + stack.toString(), }); } }); @@ -135,12 +135,12 @@ class IsolateQjs { if (hostPromiseRejectionHandler != null) { hostPromiseRejectionHandler(errStr); } else { - print("unhandled promise rejection: $errStr"); + print('unhandled promise rejection: $errStr'); } } catch (e, stack) { - print("host Promise Rejection Handler error: " + + print('host Promise Rejection Handler error: ' + e.toString() + - "\n" + + '\n' + stack.toString()); } break; diff --git a/lib/wrapper.dart b/lib/wrapper.dart index 51563cb..fb4f52f 100644 --- a/lib/wrapper.dart +++ b/lib/wrapper.dart @@ -32,6 +32,20 @@ abstract class JSInvokable { } } +class NativeJSInvokable extends JSInvokable { + dynamic Function(Pointer ctx, Pointer thisVal, List args) _func; + NativeJSInvokable(this._func); + + @override + dynamic invoke(List args, [dynamic thisVal]) { + throw UnimplementedError('use invokeNative instead.'); + } + + invokeNative(Pointer ctx, Pointer thisVal, List args) { + _func(ctx, thisVal, args); + } +} + class _DartFunction extends JSInvokable { Function _func; _DartFunction(this._func); @@ -40,7 +54,7 @@ class _DartFunction extends JSInvokable { invoke(List args, [thisVal]) { /// wrap this into function final passThis = - RegExp("{.*thisVal.*}").hasMatch(_func.runtimeType.toString()); + RegExp('{.*thisVal.*}').hasMatch(_func.runtimeType.toString()); return Function.apply(_func, args, passThis ? {#thisVal: thisVal} : null); } } @@ -112,7 +126,7 @@ class JSFunction extends JSObject implements JSInvokable { bool isException = jsIsException(jsRet) != 0; if (isException) { jsFreeValue(_ctx, jsRet); - throw Exception(parseJSException(_ctx)); + throw parseJSException(_ctx); } var ret = jsToDart(_ctx, jsRet); jsFreeValue(_ctx, jsRet); @@ -180,7 +194,7 @@ class IsolateFunction extends JSInvokable implements DartReleasable { final JSInvokable invokable = JSInvokable.wrap(func); final funcPort = ReceivePort(); funcPort.listen((msg) async { - if (msg == "close") return funcPort.close(); + if (msg == 'close') return funcPort.close(); var data; SendPort msgPort = msg['port']; try { @@ -194,7 +208,7 @@ class IsolateFunction extends JSInvokable implements DartReleasable { } catch (e, stack) { if (msgPort != null) msgPort.send({ - 'error': e.toString() + "\n" + stack.toString(), + 'error': e.toString() + '\n' + stack.toString(), }); } }); @@ -221,7 +235,7 @@ class IsolateFunction extends JSInvokable implements DartReleasable { @override void release() { if (func == null) return; - func.send("close"); + func.send('close'); func = null; } } @@ -275,7 +289,7 @@ dynamic encodeData(dynamic data, {Map cache}) { futurePort.first.then((port) { futurePort.close(); (port as SendPort) - .send({'error': e.toString() + "\n" + stack.toString()}); + .send({'error': e.toString() + '\n' + stack.toString()}); }); }); return { @@ -344,12 +358,12 @@ dynamic decodeData(dynamic data, SendPort port, {Map cache}) { return data; } -String parseJSException(Pointer ctx, {Pointer perr}) { +String parseJSException(Pointer ctx, [Pointer perr]) { final e = perr ?? jsGetException(ctx); var err = jsToCString(ctx, e); if (jsValueGetTag(e) == JSTag.OBJECT) { - Pointer stack = jsGetPropertyValue(ctx, e, "stack"); + Pointer stack = jsGetPropertyValue(ctx, e, 'stack'); if (jsToBool(ctx, stack) != 0) { err += '\n' + jsToCString(ctx, stack); } @@ -409,7 +423,7 @@ Pointer dartToJs(Pointer ctx, dynamic val, {Map cache}) { val.then((value) { res(value); }, onError: (e, stack) { - rej(e.toString() + "\n" + stack.toString()); + rej(e.toString() + '\n' + stack.toString()); }); return ret; } @@ -498,7 +512,7 @@ dynamic jsToDart(Pointer ctx, Pointer val, {Map cache}) { if (jsIsFunction(ctx, val) != 0) { return JSFunction(ctx, val); } else if (jsIsPromise(ctx, val) != 0) { - Pointer jsPromiseThen = jsGetPropertyValue(ctx, val, "then"); + Pointer jsPromiseThen = jsGetPropertyValue(ctx, val, 'then'); JSFunction promiseThen = jsToDart(ctx, jsPromiseThen, cache: cache); jsFreeValue(ctx, jsPromiseThen); var completer = Completer(); @@ -507,16 +521,18 @@ dynamic jsToDart(Pointer ctx, Pointer val, {Map cache}) { (v) { if (!completer.isCompleted) completer.complete(v); }, - (e) { - if (!completer.isCompleted) completer.completeError(e); - }, + NativeJSInvokable((ctx, thisVal, args) { + if (!completer.isCompleted) + completer + .completeError(parseJSException(ctx, args[0])); + }), ], JSObject.fromAddress(ctx, val)); bool isException = jsIsException(jsRet) != 0; jsFreeValue(ctx, jsRet); - if (isException) throw Exception(parseJSException(ctx)); + if (isException) throw parseJSException(ctx); return completer.future; } else if (jsIsArray(ctx, val) != 0) { - Pointer jslength = jsGetPropertyValue(ctx, val, "length"); + Pointer jslength = jsGetPropertyValue(ctx, val, 'length'); int length = jsToInt64(ctx, jslength); List ret = []; cache[valptr] = ret; diff --git a/pubspec.yaml b/pubspec.yaml index 6c6deaa..c882ae1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_qjs description: This plugin is a simple js engine for flutter using the `quickjs` project. Plugin currently supports all the platforms except web! -version: 0.3.1 +version: 0.3.2 homepage: https://github.com/ekibun/flutter_qjs environment: diff --git a/test/flutter_qjs_test.dart b/test/flutter_qjs_test.dart index 923a6a3..7438833 100644 --- a/test/flutter_qjs_test.dart +++ b/test/flutter_qjs_test.dart @@ -158,7 +158,7 @@ void main() async { qjs.evaluate("a=()=>a();a();", name: ""); } catch (e) { expect( - e.toString(), startsWith('Exception: InternalError: stack overflow'), + e.toString(), startsWith('InternalError: stack overflow'), reason: "throw stack overflow"); } qjs.close();