lemon_js 0.3.0 copy "lemon_js: ^0.3.0" to clipboard
lemon_js: ^0.3.0 copied to clipboard

QuickJS JavaScript engine for Flutter — cross-platform FFI and WebAssembly.

lemon_js #

公开 API 的命名和方向语义以 API 命名语义 为准。

lemon_js 是面向 Flutter 的 QuickJS JavaScript 运行时。原生平台使用 FFI 和随包编译的 QuickJS,Flutter Web 使用 WASM 与 Web Worker。它提供异步执行、ES Module、插件、宿主 能力注入、结构化值转换、网络、KV、Web Crypto 和运行时隔离。

支持 Android、iOS、macOS、Linux、Windows 和 Web。OpenHarmony 基础 FFI 目前仅作为面向 未来 CPF Flutter 与 HarmonyOS SDK 的实验适配,不承诺现有 HarmonyOS 6.1.1(API 24) 环境可用于生产。

安装 #

dependencies:
  lemon_js: ^0.2.1
import 'package:lemon_js/lemon_js.dart';

Apple 宿主推荐使用 Flutter 的 Swift Package Manager 配置;仓库虽然保留 CocoaPods 清单, 但 CocoaPods 模式不属于当前发布验证范围。发布前还需设置应用版本和最低系统版本。完整配置见 宿主平台配置

OpenHarmony 需要使用 CPF Flutter OHOS 分支及 DevEco/OpenHarmony SDK,不能使用官方 Flutter SDK 直接构建。当前只提供 lemon_js 的 QuickJS FFI 实验接入;CPF Flutter 3.44 的自动填充实现与 API 24 SDK 不兼容,x64 模拟器还存在第三方视频 Surface 黑屏等问题。 完整示例中的视频和其他平台插件必须在目标真机逐项确认,详见 宿主平台配置

基本使用 #

Future<void> runJavaScript() async {
  final engine = await JsEngine.create();
  try {
    final result = await engine.eval('''
      const items = [1, 2, 3];
      ({ total: items.reduce((sum, value) => sum + value, 0) });
    ''');
    print(result); // {total: 6}
  } finally {
    await engine.dispose();
  }
}

eval() 返回 Dart 结构化值。需要底层字符串结果时使用 evalRaw()。 每个 JsEngine 实例拥有独立 runtime;不用时应调用 dispose()

Dart 与 JavaScript 互调 #

final engine = await JsEngine.create();
await engine.injectFunction('addFromDart', (arguments) {
  return (arguments[0] as num) + (arguments[1] as num);
});

final result = await engine.run('''
  return await addFromDart(20, 22);
''');
print(result); // 42

injectFunction() 临时注入的 Dart 函数在 JS 中返回 Promise;同名注入会替换旧回调, restart() 后不会恢复。需要随引擎重建恢复的正式宿主能力应通过创建参数 methods 配置。 参数和结果支持 JSON 值以及 Uint8List/Uint8Array

ES Module #

final engine = await JsEngine.create(
  moduleLoader: (name) => <String, String>{
      'math.mjs': 'export const answer = 42;',
    }[name],
);

await engine.runModule('''
  import { answer } from './math.mjs';
  globalThis.result = answer;
''', name: 'main.mjs');

print(await engine.eval('globalThis.result')); // 42

Flutter asset 模块可使用 assetModuleLoader()。npm 依赖建议先通过 esbuild、 Rollup 或 webpack 打包,不提供完整 Node.js resolver。

宿主能力 #

宿主能力通过 JsFeatures 注入。常用内置能力包括:

  • FetchFeatures:Fetch、XHR、FormData、Blob 等网络 API;
  • StorageFeatures:按 namespace 隔离的异步 KV;
  • WebCryptoFeatures:随机数、摘要和 HMAC;
  • WebSocketFeatures:原生平台 WebSocket;当前 Flutter Web 不支持此能力;
  • AxiosFeatures:向 JS 提供 Axios;
  • EssentialFeatures()NodeFeatures():常用环境兼容能力。
final engine = await JsEngine.create(
  features: <JsFeatures>[
    FetchFeatures(
      allowedOrigins: <String>{'https://api.example.com'},
    ),
    StorageFeatures(namespace: 'site.example'),
  ],
);

生产环境建议限制网络 origin。Web 请求仍受浏览器 CORS、Cookie 和安全策略限制。

JS 插件 #

final plugin = JsPlugin.sources(
  manifest: const JsPluginManifest(
    id: 'site.example',
    version: '1.0.0',
    entry: 'site.example/main.mjs',
    exports: <String>['getHome'],
  ),
  modules: const <String, String>{
    'site.example/main.mjs':
        'export function getHome() { return {items: []}; }',
  },
);

final engine = await JsEngine.create();
final result = await engine.callPluginExport(plugin, 'getHome', const []);

插件 ID 同时作为模块命名空间。多文件插件和 ZIP 插件也使用相同的 manifest、导出校验与 调用模型。

运行限制与错误 #

JsOptions 可配置内存、原生栈和执行队列上限。框架错误可通过 JsException.kind 或具体异常类型区分超时、取消、队列已满、runtime 关闭、崩溃、 内存不足和栈溢出。

长同步 JavaScript 不会阻塞 Flutter UI isolate,但会阻塞同一 QuickJS runtime 的后续 任务。restart() 会重建底层 runtime,因此 JS 全局变量和模块临时状态会丢失。

示例与文档 #

完整示例保留在 GitHub 仓库,pub 包 README 只覆盖最小接入和主要能力。

0
likes
160
points
254
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

QuickJS JavaScript engine for Flutter — cross-platform FFI and WebAssembly.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

archive, crypto, ffi, flutter, flutter_web_plugins, http, shared_preferences, web

More

Packages that depend on lemon_js

Packages that implement lemon_js