Git Product home page Git Product logo

flutter_qjs's Introduction

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().

ES6 module with import function is supported and can be managed in dart with setModuleHandler.

A global function channel is presented to invoke dart function. 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 function(....args)
Future Promise

notice: function can only be sent from js to dart. Promise return by evaluate will be automatically tracked and return the resolved data.

Getting Started

Run on main thread

  1. Create a FlutterQjs object. Call dispatch to dispatch event loop.
final engine = FlutterQjs();
await engine.dispatch();
  1. Call setMethodHandler to implement js-dart interaction. For example, you can use Dio to implement http in js:
await engine.setMethodHandler((String method, List arg) {
  switch (method) {
    case "http":
      return Dio().get(arg[0]).then((response) => response.data);
    default:
      throw Exception("No such method");
  }
});

and in javascript, call channel function to get data, make sure the second parameter is a list:

channel("http", ["http://example.com/"]);
  1. Call setModuleHandler to resolve the js module.

I cannot find a way to convert the sync ffi callback into an async function. So the assets files received by async function rootBundle.loadString cannot be used in this version. I will appreciate it if you can provide me a solution to make ModuleHandler async.

To use async function in module handler, try Run on isolate thread

await engine.setModuleHandler((String module) {
  if(module == "hello") return "export default (name) => `hello \${name}!`;";
  throw Exception("Module Not found");
});

and in javascript, call import function to get module:

import("hello").then(({default: greet}) => greet("world"));
  1. Use evaluate to run js script:
try {
  print(await engine.evaluate(code ?? '', "<eval>"));
} catch (e) {
  print(e.toString());
}
  1. Method recreate can destroy quickjs runtime that can be recreated again if you call evaluate, recreat can be used to reset the module cache. Call close to stop dispatch when you do not need it.

Run on isolate thread

  1. Create a IsolateQjs object, pass a handler to implement js-dart interaction. The handler is used in isolate, so the function must be a top-level function or a static method.
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);
// not need engine.dispatch();

and in javascript, call channel function to get data, make sure the second parameter is a list:

channel("http", ["http://example.com/"]);
  1. Call setModuleHandler to resolve the js module. Async function such as rootBundle.loadString can be used now to get module. The handler is called in main thread.
await engine.setModuleHandler((String module) async {
  return await rootBundle.loadString(
      "js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js");
});

and in javascript, call import function to get module:

import("hello").then(({default: greet}) => greet("world"));
  1. Same as run on main thread, use evaluate to run js script:
try {
  print(await engine.evaluate(code ?? '', "<eval>"));
} catch (e) {
  print(e.toString());
}
  1. Method close (same as recreate in main thread) can destroy quickjs runtime that can be recreated again if you call evaluate.

This example contains a complete demonstration on how to use this plugin.

For Mac & 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.

For simulator, use:

s.vendored_frameworks = `build/Debug-iphonesimulator/ffiquickjs.framework`

For real device, use:

s.vendored_frameworks = `build/Debug-iphoneos/ffiquickjs.framework`

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.

flutter_qjs's People

Contributors

ekibun avatar mabdc avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.