diff --git a/README.md b/README.md
index a03d9af..c45eef5 100644
--- a/README.md
+++ b/README.md
@@ -45,44 +45,36 @@ engine = null;
Data conversion between dart and js are implemented as follow:
-| dart | js |
-| --------------------------------------------------- | ------------------ |
-| Bool | boolean |
-| Int | number |
-| Double | number |
-| String | string |
-| Uint8List | ArrayBuffer |
-| List | Array |
-| Map | Object |
-| JSFunction(...args)
IsolateJSFunction(...args) | function(....args) |
-| Future | Promise |
-| Object | DartObject |
+| dart | js |
+| --------- | ------------------ |
+| Bool | boolean |
+| Int | number |
+| Double | number |
+| String | string |
+| Uint8List | ArrayBuffer |
+| List | Array |
+| Map | Object |
+| Function | function(....args) |
+| Future | Promise |
+| Object | DartObject |
-**notice:** `function` can only be sent from js to dart. `DartObject` can only be used in `moduleHandler`.
+**notice:** Dart function parameter `thisVal` is used to store `this` in js.
-### Invoke dart function
+### Set into global object
-A global JavaScript function `channel` is presented to invoke dart function.
-
-In constructor, pass handler function to manage JavaScript call. For example, you can use `Dio` to implement http in JavaScript:
+Method `setToGlobalObject` is presented to set dart object into global object.
+For example, you can pass a function implement http in JavaScript with `Dio`:
```dart
-final engine = FlutterQjs(
- methodHandler: (String method, List arg) {
- switch (method) {
- case "http":
- return Dio().get(arg[0]).then((response) => response.data);
- default:
- throw Exception("No such method");
- }
- },
-);
+engine.setToGlobalObject("http", (String url) {
+ return Dio().get(url).then((response) => response.data);
+});
```
-then, in java script you can use channel function to invoke `methodHandler`, make sure the second parameter is a list:
+then, in java script you can use `http` function to invoke dart function:
```javascript
-channel("http", ["http://example.com/"]);
+http("http://example.com/");
```
### Use modules
@@ -111,7 +103,9 @@ To use async function in module handler, try [Run on isolate thread](#Run-on-iso
### Run on isolate thread
-Create a `IsolateQjs` object, pass handlers to implement js-dart interaction and resolving modules. The `methodHandler` is used in isolate, so **the handler function must be a top-level function or a static method**. Async function such as `rootBundle.loadString` can be used now to get modules:
+Create a `IsolateQjs` object, pass handlers to resolving modules. Async function such as `rootBundle.loadString` can be used now to get modules:
+
+The `methodHandler` is used in isolate, so **the handler function must be a top-level function or a static method**.
```dart
dynamic methodHandler(String method, List arg) {
@@ -132,6 +126,16 @@ final engine = IsolateQjs(
// not need engine.dispatch();
```
+Method `setToGlobalObject` is still here to set dart object into global object. Use `await` to make sure it is finished.
+**Make sure the object that can pass through isolate**, For example, a top level function:
+
+```dart
+dynamic http(String url) {
+ return Dio().get(url).then((response) => response.data);
+}
+await engine.setToGlobalObject("http", http);
+```
+
Same as run on main thread, use `evaluate` to run js script. In this way, `Promise` return by `evaluate` will be automatically tracked and return the resolved data:
```dart
diff --git a/cxx/ffi.cpp b/cxx/ffi.cpp
index 573bf33..baefdb5 100644
--- a/cxx/ffi.cpp
+++ b/cxx/ffi.cpp
@@ -39,7 +39,7 @@ extern "C"
{
JSRuntime *rt = JS_GetRuntime(ctx);
JSChannel *channel = (JSChannel *)JS_GetRuntimeOpaque(rt);
- const char *str = (char *)channel(ctx, module_name, nullptr);
+ const char *str = (char *)channel(ctx, JSChannelType_MODULE, (void *)module_name);
if (str == 0)
return NULL;
JSValue func_val = JS_Eval(ctx, str, strlen(str), module_name, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
@@ -51,16 +51,16 @@ extern "C"
return m;
}
- JSValue js_channel(JSContext *ctx, JSValueConst this_val, int32_t argc, JSValueConst *argv)
+ JSValue js_channel(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data)
{
JSRuntime *rt = JS_GetRuntime(ctx);
JSChannel *channel = (JSChannel *)JS_GetRuntimeOpaque(rt);
- const char *str = JS_ToCString(ctx, argv[0]);
- JS_DupValue(ctx, *(argv + 1));
- JSValue ret = *(JSValue *)channel(ctx, str, argv + 1);
- JS_FreeValue(ctx, *(argv + 1));
- JS_FreeCString(ctx, str);
- return ret;
+ void *data[4];
+ data[0] = &this_val;
+ data[1] = &argc;
+ data[2] = argv;
+ data[3] = func_data;
+ return *(JSValue *)channel(ctx, JSChannelType_METHON, data);
}
void js_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
@@ -71,7 +71,7 @@ extern "C"
return;
JSRuntime *rt = JS_GetRuntime(ctx);
JSChannel *channel = (JSChannel *)JS_GetRuntimeOpaque(rt);
- channel(ctx, (char *)ctx, &reason);
+ channel(ctx, JSChannelType_PROMISE_TRACK, &reason);
}
DLLEXPORT JSRuntime *jsNewRuntime(JSChannel channel)
@@ -97,7 +97,9 @@ extern "C"
JSClassID classid = JS_GetClassID(obj);
void *opaque = JS_GetOpaque(obj, classid);
JSChannel *channel = (JSChannel *)JS_GetRuntimeOpaque(rt);
- channel((JSContext *)rt, nullptr, opaque);
+ if (channel == nullptr)
+ return;
+ channel((JSContext *)rt, JSChannelType_FREE_OBJECT, opaque);
}};
int e = JS_NewClass(rt, QJSClassId, &def);
if (e < 0)
@@ -134,14 +136,19 @@ extern "C"
JS_FreeRuntime(rt);
}
+ DLLEXPORT JSValue *jsNewCFunction(JSContext *ctx, JSValue *funcData)
+ {
+ return new JSValue(JS_NewCFunctionData(ctx, js_channel, 0, 0, 1, funcData));
+ }
+
+ DLLEXPORT JSValue *jsGetGlobalObject(JSContext *ctx)
+ {
+ return new JSValue(JS_GetGlobalObject(ctx));
+ }
+
DLLEXPORT JSContext *jsNewContext(JSRuntime *rt)
{
JSContext *ctx = JS_NewContext(rt);
- JSAtom atom = JS_NewAtom(ctx, "channel");
- JSValue globalObject = JS_GetGlobalObject(ctx);
- JS_SetProperty(ctx, globalObject, atom, JS_NewCFunction(ctx, js_channel, "channel", 2));
- JS_FreeValue(ctx, globalObject);
- JS_FreeAtom(ctx, atom);
return ctx;
}
diff --git a/cxx/ffi.h b/cxx/ffi.h
index 47981e8..a1ca636 100644
--- a/cxx/ffi.h
+++ b/cxx/ffi.h
@@ -8,7 +8,14 @@
extern "C"
{
- typedef void *JSChannel(JSContext *ctx, const char *method, void *argv);
+ enum JSChannelType {
+ JSChannelType_METHON = 0,
+ JSChannelType_MODULE = 1,
+ JSChannelType_PROMISE_TRACK = 2,
+ JSChannelType_FREE_OBJECT = 3,
+ };
+
+ typedef void *JSChannel(JSContext *ctx, size_t type, void *argv);
DLLEXPORT JSValue *jsThrowInternalError(JSContext *ctx, char *message);
@@ -30,6 +37,10 @@ extern "C"
DLLEXPORT void jsFreeRuntime(JSRuntime *rt);
+ DLLEXPORT JSValue *jsNewCFunction(JSContext *ctx, JSValue *funcData);
+
+ DLLEXPORT JSValue *jsGetGlobalObject(JSContext *ctx);
+
DLLEXPORT JSContext *jsNewContext(JSRuntime *rt);
DLLEXPORT void jsFreeContext(JSContext *ctx);
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 269c9af..b4d51a3 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -76,13 +76,13 @@ class _TestPageState extends State {
_ensureEngine() {
if (engine != null) return;
engine = IsolateQjs(
- methodHandler: methodHandler,
moduleHandler: (String module) async {
if (module == "test") return "export default '${new DateTime.now()}'";
return await rootBundle.loadString(
"js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js");
},
);
+ engine.setToGlobalObject("channel", methodHandler);
}
@override
diff --git a/lib/ffi.dart b/lib/ffi.dart
index 18ac833..15d8773 100644
--- a/lib/ffi.dart
+++ b/lib/ffi.dart
@@ -21,6 +21,13 @@ class JSEvalFlag {
static const MODULE = 1 << 0;
}
+class JSChannelType {
+ static const METHON = 0;
+ static const MODULE = 1;
+ static const PROMISE_TRACK = 2;
+ static const FREE_OBJECT = 3;
+}
+
class JSProp {
static const CONFIGURABLE = (1 << 0);
static const WRITABLE = (1 << 1);
@@ -91,11 +98,13 @@ final Pointer Function() jsUNDEFINED = qjsLib
.lookup>("jsUNDEFINED")
.asFunction();
+typedef JSChannel = Pointer Function(Pointer ctx, int method, Pointer argv);
+typedef JSChannelNative = Pointer Function(
+ Pointer ctx, IntPtr method, Pointer argv);
+
/// JSRuntime *jsNewRuntime(JSChannel channel)
final Pointer Function(
- Pointer<
- NativeFunction<
- Pointer Function(Pointer ctx, Pointer method, Pointer argv)>>,
+ Pointer>,
) _jsNewRuntime = qjsLib
.lookup<
NativeFunction<
@@ -104,8 +113,6 @@ final Pointer Function(
)>>("jsNewRuntime")
.asFunction();
-typedef JSChannel = Pointer Function(Pointer ctx, Pointer method, Pointer argv);
-
class RuntimeOpaque {
JSChannel channel;
List ref = [];
@@ -116,9 +123,9 @@ class RuntimeOpaque {
final Map runtimeOpaques = Map();
-Pointer channelDispacher(Pointer ctx, Pointer method, Pointer argv) {
- Pointer rt = method.address == 0 ? ctx : jsGetRuntime(ctx);
- return runtimeOpaques[rt]?.channel(ctx, method, argv);
+Pointer channelDispacher(Pointer ctx, int type, Pointer argv) {
+ Pointer rt = type == JSChannelType.FREE_OBJECT ? ctx : jsGetRuntime(ctx);
+ return runtimeOpaques[rt]?.channel(ctx, type, argv);
}
Pointer jsNewRuntime(
@@ -166,6 +173,30 @@ void jsFreeRuntime(
_jsFreeRuntime(rt);
}
+/// JSValue *jsNewCFunction(JSContext *ctx, JSValue *funcData)
+final Pointer Function(
+ Pointer ctx,
+ Pointer funcData,
+) jsNewCFunction = qjsLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(
+ Pointer,
+ Pointer,
+ )>>("jsNewCFunction")
+ .asFunction();
+
+/// JSValue *jsGetGlobalObject(JSContext *ctx)
+final Pointer Function(
+ Pointer ctx,
+) jsGetGlobalObject = qjsLib
+ .lookup<
+ NativeFunction<
+ Pointer Function(
+ Pointer,
+ )>>("jsGetGlobalObject")
+ .asFunction();
+
/// JSContext *jsNewContext(JSRuntime *rt)
final Pointer Function(
Pointer rt,
diff --git a/lib/flutter_qjs.dart b/lib/flutter_qjs.dart
index e8e27d9..2eb86f3 100644
--- a/lib/flutter_qjs.dart
+++ b/lib/flutter_qjs.dart
@@ -13,9 +13,6 @@ import 'package:ffi/ffi.dart';
import 'package:flutter_qjs/ffi.dart';
import 'package:flutter_qjs/wrapper.dart';
-/// Handler function to manage js call.
-typedef JsMethodHandler = dynamic Function(String method, List args);
-
/// Handler function to manage js module.
typedef JsModuleHandler = String Function(String name);
@@ -32,9 +29,6 @@ class FlutterQjs {
/// Message Port for event loop. Close it to stop dispatching event loop.
ReceivePort port = ReceivePort();
- /// Handler function to manage js call with `channel(method, [...args])` function.
- JsMethodHandler methodHandler;
-
/// Handler function to manage js module.
JsModuleHandler moduleHandler;
@@ -44,55 +38,75 @@ class FlutterQjs {
/// Quickjs engine for flutter.
///
/// Pass handlers to implement js-dart interaction and resolving modules.
- FlutterQjs(
- {this.methodHandler,
- this.moduleHandler,
- this.stackSize,
- this.hostPromiseRejectionHandler});
+ FlutterQjs({
+ this.moduleHandler,
+ this.stackSize,
+ this.hostPromiseRejectionHandler,
+ });
+
+ setToGlobalObject(dynamic key, dynamic val) {
+ _ensureEngine();
+ final globalObject = jsGetGlobalObject(_ctx);
+ definePropertyValue(_ctx, globalObject, key, val);
+ jsFreeValue(_ctx, globalObject);
+ }
_ensureEngine() {
if (_rt != null) return;
- _rt = jsNewRuntime((ctx, method, argv) {
+ _rt = jsNewRuntime((ctx, type, ptr) {
try {
- if (method.address == 0) {
- Pointer rt = ctx;
- DartObject obj = DartObject.fromAddress(rt, argv.address);
- obj?.release();
- runtimeOpaques[rt]?.ref?.remove(obj);
- return Pointer.fromAddress(0);
- }
- if (argv.address != 0) {
- if (method.address == ctx.address) {
- final errStr = parseJSException(ctx, perr: argv);
+ switch (type) {
+ case JSChannelType.METHON:
+ final pdata = ptr.cast();
+ final argc = pdata.elementAt(1).value.cast().value;
+ List args = [];
+ for (var i = 0; i < argc; i++) {
+ args.add(jsToDart(
+ ctx,
+ Pointer.fromAddress(
+ pdata.elementAt(2).value.address + sizeOfJSValue * i,
+ )));
+ }
+ final thisVal = jsToDart(ctx, pdata.elementAt(0).value);
+ Function func = jsToDart(ctx, pdata.elementAt(3).value);
+ final passThis =
+ RegExp("{.*thisVal.*}").hasMatch(func.runtimeType.toString());
+ return dartToJs(
+ ctx,
+ Function.apply(func, args, passThis ? {#thisVal: thisVal} : null),
+ );
+ case JSChannelType.MODULE:
+ if (moduleHandler == null) throw Exception("No ModuleHandler");
+ var ret = Utf8.toUtf8(moduleHandler(
+ Utf8.fromUtf8(ptr.cast()),
+ ));
+ Future.microtask(() {
+ free(ret);
+ });
+ return ret;
+ case JSChannelType.PROMISE_TRACK:
+ final errStr = parseJSException(ctx, perr: ptr);
if (hostPromiseRejectionHandler != null) {
hostPromiseRejectionHandler(errStr);
} else {
print("unhandled promise rejection: $errStr");
}
return Pointer.fromAddress(0);
- }
- if (methodHandler == null) throw Exception("No MethodHandler");
- return dartToJs(
- ctx,
- methodHandler(
- Utf8.fromUtf8(method.cast()),
- jsToDart(ctx, argv),
- ));
+ case JSChannelType.FREE_OBJECT:
+ Pointer rt = ctx;
+ DartObject obj = DartObject.fromAddress(rt, ptr.address);
+ obj?.release();
+ runtimeOpaques[rt]?.ref?.remove(obj);
+ return Pointer.fromAddress(0);
}
- if (moduleHandler == null) throw Exception("No ModuleHandler");
- var ret =
- Utf8.toUtf8(moduleHandler(Utf8.fromUtf8(method.cast())));
- Future.microtask(() {
- free(ret);
- });
- return ret;
+ throw Exception("call channel with wrong type");
} catch (e, stack) {
final errStr = e.toString() + "\n" + stack.toString();
- if (method.address == 0) {
+ if (type == JSChannelType.FREE_OBJECT) {
print("DartObject release error: " + errStr);
return Pointer.fromAddress(0);
}
- if (method.address == ctx.address) {
+ if (type == JSChannelType.MODULE) {
print("host Promise Rejection Handler error: " + errStr);
return Pointer.fromAddress(0);
}
@@ -100,7 +114,7 @@ class FlutterQjs {
ctx,
errStr,
);
- if (argv.address == 0) {
+ if (type == JSChannelType.MODULE) {
jsFreeValue(ctx, err);
return Pointer.fromAddress(0);
}
diff --git a/lib/isolate.dart b/lib/isolate.dart
index 53ffa29..978b187 100644
--- a/lib/isolate.dart
+++ b/lib/isolate.dart
@@ -153,7 +153,6 @@ void _runJsIsolate(Map spawnMessage) async {
'reason': reason,
});
},
- methodHandler: spawnMessage['handler'],
moduleHandler: (name) {
var ptr = allocate>();
ptr.value = Pointer.fromAddress(0);
@@ -192,6 +191,9 @@ void _runJsIsolate(Map spawnMessage) async {
msg['val'],
).invoke(_decodeData(msg['args'], null));
break;
+ case 'setToGlobalObject':
+ qjs.setToGlobalObject(msg['key'], msg['val']);
+ break;
case 'close':
qjs.port.close();
qjs.close();
@@ -220,10 +222,6 @@ class IsolateQjs {
/// Max stack size for quickjs.
final int stackSize;
- /// Handler to manage js call with `channel(method, [...args])` function.
- /// The function must be a top-level function or a static method.
- JsMethodHandler methodHandler;
-
/// Asynchronously handler to manage js module.
JsAsyncModuleHandler moduleHandler;
@@ -235,7 +233,6 @@ class IsolateQjs {
/// Pass handlers to implement js-dart interaction and resolving modules. The `methodHandler` is
/// used in isolate, so **the handler function must be a top-level function or a static method**.
IsolateQjs({
- this.methodHandler,
this.moduleHandler,
this.stackSize,
this.hostPromiseRejectionHandler,
@@ -248,7 +245,6 @@ class IsolateQjs {
_runJsIsolate,
{
'port': port.sendPort,
- 'handler': methodHandler,
'stackSize': stackSize,
},
errorsAreFatal: true,
@@ -305,6 +301,23 @@ class IsolateQjs {
_sendPort = null;
}
+ setToGlobalObject(dynamic key, dynamic val) async {
+ _ensureEngine();
+ var evaluatePort = ReceivePort();
+ var sendPort = await _sendPort;
+ sendPort.send({
+ 'type': 'setToGlobalObject',
+ 'key': key,
+ 'val': val,
+ 'port': evaluatePort.sendPort,
+ });
+ var result = await evaluatePort.first;
+ if (result['error'] == null) {
+ return;
+ } else
+ throw result['error'];
+ }
+
/// Evaluate js script.
Future evaluate(String command, {String name, int evalFlags}) async {
_ensureEngine();
diff --git a/lib/wrapper.dart b/lib/wrapper.dart
index 5a58295..0cceac2 100644
--- a/lib/wrapper.dart
+++ b/lib/wrapper.dart
@@ -146,6 +146,26 @@ String parseJSException(Pointer ctx, {Pointer perr}) {
return err;
}
+void definePropertyValue(
+ Pointer ctx,
+ Pointer obj,
+ dynamic key,
+ dynamic val, {
+ Map cache,
+}) {
+ var jsAtomVal = dartToJs(ctx, key, cache: cache);
+ var jsAtom = jsValueToAtom(ctx, jsAtomVal);
+ jsDefinePropertyValue(
+ ctx,
+ obj,
+ jsAtom,
+ dartToJs(ctx, val, cache: cache),
+ JSProp.C_W_E,
+ );
+ jsFreeAtom(ctx, jsAtom);
+ jsFreeValue(ctx, jsAtomVal);
+}
+
Pointer dartToJs(Pointer ctx, dynamic val, {Map cache}) {
if (val == null) return jsUNDEFINED();
if (val is Future) {
@@ -188,17 +208,7 @@ Pointer dartToJs(Pointer ctx, dynamic val, {Map cache}) {
Pointer ret = jsNewArray(ctx);
cache[val] = ret;
for (int i = 0; i < val.length; ++i) {
- var jsAtomVal = jsNewInt64(ctx, i);
- var jsAtom = jsValueToAtom(ctx, jsAtomVal);
- jsDefinePropertyValue(
- ctx,
- ret,
- jsAtom,
- dartToJs(ctx, val[i], cache: cache),
- JSProp.C_W_E,
- );
- jsFreeAtom(ctx, jsAtom);
- jsFreeValue(ctx, jsAtomVal);
+ definePropertyValue(ctx, ret, i, val[i], cache: cache);
}
return ret;
}
@@ -206,28 +216,24 @@ Pointer dartToJs(Pointer ctx, dynamic val, {Map cache}) {
Pointer ret = jsNewObject(ctx);
cache[val] = ret;
for (MapEntry entry in val.entries) {
- var jsAtomVal = dartToJs(ctx, entry.key, cache: cache);
- var jsAtom = jsValueToAtom(ctx, jsAtomVal);
- jsDefinePropertyValue(
- ctx,
- ret,
- jsAtom,
- dartToJs(ctx, entry.value, cache: cache),
- JSProp.C_W_E,
- );
- jsFreeAtom(ctx, jsAtom);
- jsFreeValue(ctx, jsAtomVal);
+ definePropertyValue(ctx, ret, entry.key, entry.value, cache: cache);
}
return ret;
}
int dartObjectClassId =
runtimeOpaques[jsGetRuntime(ctx)]?.dartObjectClassId ?? 0;
if (dartObjectClassId == 0) return jsUNDEFINED();
- return jsNewObjectClass(
+ var dartObject = jsNewObjectClass(
ctx,
dartObjectClassId,
identityHashCode(DartObject(ctx, val)),
);
+ if (val is Function) {
+ final ret = jsNewCFunction(ctx, dartObject);
+ jsFreeValue(ctx, dartObject);
+ return ret;
+ }
+ return dartObject;
}
dynamic jsToDart(Pointer ctx, Pointer val, {Map cache}) {
diff --git a/test/flutter_qjs_test.dart b/test/flutter_qjs_test.dart
index 0ddc8ad..bd62b18 100644
--- a/test/flutter_qjs_test.dart
+++ b/test/flutter_qjs_test.dart
@@ -14,31 +14,32 @@ import 'package:flutter_qjs/flutter_qjs.dart';
import 'package:flutter_qjs/isolate.dart';
import 'package:flutter_test/flutter_test.dart';
-dynamic myMethodHandler(method, args) {
- return args;
+dynamic myMethodHandler(List args, {String thisVal}) {
+ return [thisVal, ...args];
}
Future testEvaluate(qjs) async {
- var value = await qjs.evaluate("""
+ final value = await qjs.evaluate("""
const a = {};
a.a = a;
- import('test').then((module) => channel('channel', [
+ import('test').then((module) => channel.call('this', [
(...args)=>`hello \${args}!`, a,
Promise.reject('test Promise.reject'), Promise.resolve('test Promise.resolve'),
0.1, true, false, 1, "world", module
]));
""", name: "");
- expect(await value[0]('world'), 'hello world!', reason: "js function call");
- expect(value[1]['a'], value[1], reason: "recursive object");
- expect(value[2], isInstanceOf(), reason: "promise object");
+ expect(value[0], 'this', reason: "js function this");
+ expect(await value[1]('world'), 'hello world!', reason: "js function call");
+ expect(value[2]['a'], value[2], reason: "recursive object");
+ expect(value[3], isInstanceOf(), reason: "promise object");
try {
- await value[2];
+ await value[3];
throw 'Future not reject';
} catch (e) {
expect(e, startsWith('test Promise.reject\n'),
reason: "promise object reject");
}
- expect(await value[3], 'test Promise.resolve',
+ expect(await value[4], 'test Promise.resolve',
reason: "promise object resolve");
}
@@ -96,12 +97,12 @@ void main() async {
});
test('jsToDart', () async {
final qjs = FlutterQjs(
- methodHandler: myMethodHandler,
moduleHandler: (name) {
return "export default '${new DateTime.now()}'";
},
hostPromiseRejectionHandler: (_) {},
);
+ qjs.setToGlobalObject("channel", myMethodHandler);
qjs.dispatch();
await testEvaluate(qjs);
qjs.close();
@@ -109,12 +110,12 @@ void main() async {
test('isolate', () async {
await runZonedGuarded(() async {
final qjs = IsolateQjs(
- methodHandler: myMethodHandler,
moduleHandler: (name) async {
return "export default '${new DateTime.now()}'";
},
hostPromiseRejectionHandler: (_) {},
);
+ await qjs.setToGlobalObject("channel", myMethodHandler);
await testEvaluate(qjs);
qjs.close();
}, (e, stack) {
@@ -122,13 +123,12 @@ void main() async {
});
});
test('dart object', () async {
- final qjs = FlutterQjs(
- methodHandler: (method, args) {
- return FlutterQjs();
- },
- );
+ final qjs = FlutterQjs();
+ qjs.setToGlobalObject("channel", () {
+ return FlutterQjs();
+ });
qjs.dispatch();
- var value = await qjs.evaluate("channel('channel', [])", name: "");
+ var value = await qjs.evaluate("channel()", name: "");
expect(value, isInstanceOf(), reason: "dart object");
qjs.close();
});