Last updated:
0 purchases
flutter qjs
flutter_qjs #
English | 中文
This plugin is a simple js engine for flutter using the quickjs project with dart:ffi. Plugin currently supports all the platforms except web!
Getting Started #
Basic usage #
Firstly, create a FlutterQjs object, then call dispatch to establish event loop:
final engine = FlutterQjs(
stackSize: 1024 * 1024, // change stack size here.
);
engine.dispatch();
copied to clipboard
Use evaluate method to run js script, it runs synchronously, you can use await to resolve Promise:
try {
print(engine.evaluate(code ?? ''));
} catch (e) {
print(e.toString());
}
copied to clipboard
Method close can destroy quickjs runtime that can be recreated again if you call evaluate. Parameter port should be close to stop dispatch loop when you do not need it. Reference leak exception will be thrown since v0.3.3
try {
engine.port.close(); // stop dispatch loop
engine.close(); // close engine
} on JSError catch(e) {
print(e); // catch reference leak exception
}
engine = null;
copied to clipboard
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
Function(arg1, arg2, ..., {thisVal})JSInvokable.invoke([arg1, arg2, ...], thisVal)
function.call(thisVal, arg1, arg2, ...)
Future
Promise
JSError
Error
Object
DartObject
Use Modules #
ES6 module with import function is supported and can be managed in dart with moduleHandler:
final engine = FlutterQjs(
moduleHandler: (String module) {
if(module == "hello")
return "export default (name) => `hello \${name}!`;";
throw Exception("Module Not found");
},
);
copied to clipboard
then in JavaScript, import function is used to get modules:
import("hello").then(({default: greet}) => greet("world"));
copied to clipboard
notice: Module handler should be called only once for each module name. To reset the module cache, call FlutterQjs.close then evaluate again.
To use async function in module handler, try run on isolate thread
Run on Isolate Thread #
Create a IsolateQjs object, pass handlers to resolving modules. Async function such as rootBundle.loadString can be used now to get modules:
final engine = IsolateQjs(
moduleHandler: (String module) async {
return await rootBundle.loadString(
"js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js");
},
);
// not need engine.dispatch();
copied to clipboard
Same as run on main thread, use evaluate to run js script. In isolate, everything returns asynchronously, use await to get the result:
try {
print(await engine.evaluate(code ?? ''));
} catch (e) {
print(e.toString());
}
copied to clipboard
Method close can destroy isolate thread that will be recreated again if you call evaluate.
Use Dart Function (Breaking change in v0.3.0) #
Js script returning function will be converted to JSInvokable. It does not extend Function, use invoke method to invoke it:
(func as JSInvokable).invoke([arg1, arg2], thisVal);
copied to clipboard
notice: evaluation returning JSInvokable may cause reference leak.
You should manually call free to release JS reference.
(obj as JSRef).free();
// or JSRef.freeRecursive(obj);
copied to clipboard
Arguments passed into JSInvokable will be freed automatically. Use dup to keep the reference.
(obj as JSRef).dup();
// or JSRef.dupRecursive(obj);
copied to clipboard
Since v0.3.0, you can pass a function to JSInvokable arguments, and channel function is no longer included by default. You can use js function to set dart object globally.
For example, use Dio to implement http in qjs:
final setToGlobalObject = await engine.evaluate("(key, val) => { this[key] = val; }");
await setToGlobalObject.invoke(["http", (String url) {
return Dio().get(url).then((response) => response.data);
}]);
setToGlobalObject.free();
copied to clipboard
In isolate, top level function passed in JSInvokable will be invoked in isolate thread. Use IsolateFunction to pass a instant function:
await setToGlobalObject.invoke([
"http",
IsolateFunction((String url) {
return Dio().get(url).then((response) => response.data);
}),
]);
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.