diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59bf684..acf702a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@
* @LastEditTime: 2020-12-02 11:36:40
-->
+## 0.2.1
+
+* code cleanup.
+
## 0.2.0
* breakdown change with new constructor.
diff --git a/README.md b/README.md
index 81ea6b9..390e373 100644
--- a/README.md
+++ b/README.md
@@ -7,17 +7,38 @@
-->
# flutter_qjs
-A quickjs engine for flutter.
-
-## Feature
-
This plugin is a simple js engine for flutter using the `quickjs` project with `dart:ffi`. Plugin currently supports all the platforms except web!
-Event loop of `FlutterQjs` should be implemented by calling `FlutterQjs.dispatch()`.
+## Getting Started
-ES6 module with `import` function is supported and can be managed in dart with `setModuleHandler`.
+### Basic usage
-A global function `channel` is presented to invoke dart function. Data conversion between dart and js are implemented as follow:
+Firstly, create a `FlutterQjs` object, then call `dispatch` to dispatch event loop:
+
+```dart
+final engine = FlutterQjs()
+engine.dispatch();
+```
+
+Use `evaluate` method to run js script, now you can use it synchronously, or use await to resolve `Promise`:
+
+```dart
+try {
+ print(engine.evaluate(code ?? ''));
+} catch (e) {
+ print(e.toString());
+}
+```
+
+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.
+
+```dart
+engine.port.close(); // stop dispatch loop
+engine.close(); // close engine
+engine = null;
+```
+
+Data conversion between dart and js are implemented as follow:
| dart | js |
| --------------------------------------------------- | ------------------ |
@@ -31,13 +52,13 @@ A global function `channel` is presented to invoke dart function. Data conversio
| JSFunction(...args)
IsolateJSFunction(...args) | function(....args) |
| Future | Promise |
-**notice:** `function` can only be sent from js to dart. `IsolateJSFunction` always returns asynchronously.
+**notice:** `function` can only be sent from js to dart.
-## Getting Started
+### Invoke dart function
-### Run on main thread
+A global JavaScript function `channel` is presented to invoke dart function.
-1. Create a `FlutterQjs` object, pass handlers to implement js-dart interaction and resolving modules. For example, you can use `Dio` to implement http in js:
+In constructor, pass handler function to manage JavaScript call. For example, you can use `Dio` to implement http in JavaScript:
```dart
final engine = FlutterQjs(
@@ -49,6 +70,21 @@ final engine = FlutterQjs(
throw Exception("No such method");
}
},
+);
+```
+
+then, in java script you can use channel function to invoke `methodHandler`, make sure the second parameter is a list:
+
+```javascript
+channel("http", ["http://example.com/"]);
+```
+
+### Use modules
+
+ES6 module with `import` function is supported and can be managed in dart with `moduleHandler`:
+
+```dart
+final engine = FlutterQjs(
moduleHandler: (String module) {
if(module == "hello")
return "export default (name) => `hello \${name}!`;";
@@ -57,41 +93,19 @@ final engine = FlutterQjs(
);
```
-in javascript, `channel` function is equiped to invoke `methodHandler`, make sure the second parameter is a list:
-
-```javascript
-channel("http", ["http://example.com/"]);
-```
-
-`import` function is used to get modules:
+then in JavaScript, `import` function is used to get modules:
```javascript
import("hello").then(({default: greet}) => greet("world"));
```
-**notice:** To use async function in module handler, try [Run on isolate thread](#Run-on-isolate-thread)
+**notice:** Module handler should be called only once for each module name. To reset the module cache, call `FlutterQjs.close` then `evaluate` again.
-2. Then call `dispatch` to dispatch event loop.
-
-```dart
-engine.dispatch();
-```
-
-1. Use `evaluate` to run js script, now you can use it synchronously, or use await to resolve `Promise`:
-
-```dart
-try {
- print(engine.evaluate(code ?? ''));
-} catch (e) {
- print(e.toString());
-}
-```
-
-1. Method `close` can destroy quickjs runtime that can be recreated again if you call `evaluate`.
+To use async function in module handler, try [Run on isolate thread](#Run-on-isolate-thread)
### Run on isolate thread
-1. 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 module:
+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:
```dart
dynamic methodHandler(String method, List arg) {
@@ -112,7 +126,7 @@ final engine = IsolateQjs(
// not need engine.dispatch();
```
-2. 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:
+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
try {
@@ -122,11 +136,11 @@ try {
}
```
-3. Method `close` can destroy quickjs runtime that can be recreated again if you call `evaluate`.
+Method `close` can destroy quickjs runtime that can be recreated again if you call `evaluate`.
[This example](example/lib/main.dart) contains a complete demonstration on how to use this plugin.
-## For Mac & IOS developer
+## For macOS & iOS developer
I am new to Xcode and iOS developing, and I cannot find a better way to support both simulators and real devices without combining the binary frameworks. To reduce build size, change the `s.vendored_frameworks` in `ios/flutter_qjs.podspec` to the specific framework.
@@ -146,4 +160,4 @@ Two additional notes:
1. quickjs built with `release` config has bug in resolving `Promise`. Please let me know if you know the solution.
-2. `ios/make.sh` limit the build architectures to avoid combine conflicts. Change the `make.sh` to support another architectures.
\ No newline at end of file
+2. `ios/make.sh` limits the build architectures to avoid combining conflicts. Change the `make.sh` to support another architectures.
\ No newline at end of file
diff --git a/example/pubspec.lock b/example/pubspec.lock
index fc2018c..ba43bba 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -82,7 +82,7 @@ packages:
path: ".."
relative: true
source: path
- version: "0.2.0"
+ version: "0.2.1"
flutter_test:
dependency: "direct dev"
description: flutter
diff --git a/lib/flutter_qjs.dart b/lib/flutter_qjs.dart
index 2d79227..7c30f5c 100644
--- a/lib/flutter_qjs.dart
+++ b/lib/flutter_qjs.dart
@@ -13,23 +13,28 @@ import 'package:ffi/ffi.dart';
import 'package:flutter_qjs/ffi.dart';
import 'package:flutter_qjs/wrapper.dart';
-/// Handle function to manage js call with `dart(method, ...args)` function.
+/// Handler function to manage js call.
typedef JsMethodHandler = dynamic Function(String method, List args);
-/// Handle function to manage js module.
+/// Handler function to manage js module.
typedef JsModuleHandler = String Function(String name);
class FlutterQjs {
Pointer _rt;
Pointer _ctx;
+
+ /// Message Port for event loop. Close it to stop dispatching event loop.
ReceivePort port = ReceivePort();
- /// Set a handler to manage js call with `channel(method, args)` function.
+ /// Handler function to manage js call with `channel(method, [...args])` function.
JsMethodHandler methodHandler;
- /// Set a handler to manage js module.
+ /// Handler function to manage js module.
JsModuleHandler moduleHandler;
+ /// Quickjs engine for flutter.
+ ///
+ /// Pass handlers to implement js-dart interaction and resolving modules.
FlutterQjs({this.methodHandler, this.moduleHandler});
_ensureEngine() {
@@ -77,7 +82,7 @@ class FlutterQjs {
_ctx = null;
}
- /// DispatchMessage
+ /// Dispatch JavaScript Event loop.
Future dispatch() async {
await for (var _ in port) {
if (_rt == null) continue;
diff --git a/lib/isolate.dart b/lib/isolate.dart
index 7b4b8aa..9b69150 100644
--- a/lib/isolate.dart
+++ b/lib/isolate.dart
@@ -211,13 +211,17 @@ typedef JsIsolateSpawn = void Function(SendPort sendPort);
class IsolateQjs {
Future _sendPort;
- /// Set a handler to manage js call with `channel(method, args)` function.
- /// The function must be a top-level function or a static method
+ /// Handler to manage js call with `channel(method, [...args])` function.
+ /// The function must be a top-level function or a static method.
JsMethodHandler methodHandler;
- /// Set a handler to manage js module.
+ /// Asynchronously handler to manage js module.
JsAsyncModuleHandler moduleHandler;
+ /// Quickjs engine runing on isolate thread.
+ ///
+ /// 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});
_ensureEngine() {
@@ -257,6 +261,7 @@ class IsolateQjs {
_sendPort = completer.future;
}
+ /// Free Runtime and close isolate thread that can be recreate when evaluate again.
close() {
if (_sendPort == null) return;
_sendPort.then((sendPort) {
@@ -267,6 +272,7 @@ class IsolateQjs {
_sendPort = null;
}
+ /// Evaluate js script.
Future evaluate(String command, {String name, int evalFlags}) async {
_ensureEngine();
var evaluatePort = ReceivePort();
@@ -279,10 +285,9 @@ class IsolateQjs {
'port': evaluatePort.sendPort,
});
var result = await evaluatePort.first;
- if (result['error'] == null){
+ if (result['error'] == null) {
return _decodeData(result['data'], sendPort);
- }
- else
+ } else
throw result['error'];
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index ec291fe..57152e2 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.2.0
+version: 0.2.1
homepage: https://github.com/ekibun/flutter_qjs
environment: