{"id":13550836,"url":"https://github.com/ekibun/flutter_qjs","last_synced_at":"2025-04-09T11:12:57.647Z","repository":{"id":54383583,"uuid":"286017292","full_name":"ekibun/flutter_qjs","owner":"ekibun","description":"A quickjs engine for flutter.","archived":false,"fork":false,"pushed_at":"2024-06-26T12:51:22.000Z","size":6462,"stargazers_count":155,"open_issues_count":20,"forks_count":30,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T03:44:07.202Z","etag":null,"topics":["flutter","quickjs"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_qjs","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekibun.png","metadata":{"files":{"readme":"README-CN.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-08T09:57:28.000Z","updated_at":"2025-03-02T14:26:58.000Z","dependencies_parsed_at":"2024-08-01T12:18:34.145Z","dependency_job_id":"1387f521-3428-4087-99a1-0ef56a6b1731","html_url":"https://github.com/ekibun/flutter_qjs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekibun%2Fflutter_qjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekibun%2Fflutter_qjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekibun%2Fflutter_qjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekibun%2Fflutter_qjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekibun","download_url":"https://codeload.github.com/ekibun/flutter_qjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248027411,"owners_count":21035594,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flutter","quickjs"],"created_at":"2024-08-01T12:01:38.299Z","updated_at":"2025-04-09T11:12:57.615Z","avatar_url":"https://github.com/ekibun.png","language":"Dart","readme":"\u003c!--\n * @Description: \n * @Author: ekibun\n * @Date: 2020-08-08 08:16:50\n * @LastEditors: ekibun\n * @LastEditTime: 2020-10-03 00:44:41\n--\u003e\n# flutter_qjs\n\n![Pub](https://img.shields.io/pub/v/flutter_qjs.svg)\n![Test](https://github.com/ekibun/flutter_qjs/workflows/Test/badge.svg)\n\n[English](README.md) | [中文](README-CN.md)\n\n一个为flutter开发的 `quickjs` 引擎。插件基于 `dart:ffi`，支持除Web以外的所有平台！\n\n## 基本使用\n\n首先，创建 `FlutterQjs` 对象。调用 `dispatch` 建立事件循环：\n\n```dart\nfinal engine = FlutterQjs(\n  stackSize: 1024 * 1024, // change stack size here.\n);\nengine.dispatch();\n```\n\n使用 `evaluate` 方法运行js脚本，方法同步执行，使用 `await` 来获得 `Promise` 结果：\n\n```dart\ntry {\n  print(engine.evaluate(code ?? ''));\n} catch (e) {\n  print(e.toString());\n}\n```\n\n使用 `close` 方法销毁 quickjs 实例，其在再次调用 `evaluate` 时将会重建。当不再需要 `FlutterQjs` 对象时，关闭 `port` 参数来结束事件循环。**在 v0.3.3 后增加了引用检查，可能会抛出异常**。\n\n```dart\ntry {\n  engine.port.close(); // stop dispatch loop\n  engine.close();      // close engine\n} on JSError catch(e) { \n  print(e);            // catch reference leak exception\n}\nengine = null;\n```\n\ndart 与 js 间数据以如下规则转换：\n\n| dart                         | js         |\n| ---------------------------- | ---------- |\n| Bool                         | boolean    |\n| Int                          | number     |\n| Double                       | number     |\n| String                       | string     |\n| Uint8List                    | ArrayBuffer|\n| List                         | Array      |\n| Map                          | Object     |\n| Function(arg1, arg2, ..., {thisVal})\u003cbr\u003eJSInvokable.invoke(\\[arg1, arg2, ...\\], thisVal) | function.call(thisVal, arg1, arg2, ...) |\n| Future                       | Promise    |\n| JSError                      | Error      |\n| Object                       | DartObject |\n\n## 使用模块\n\n插件支持 ES6 模块方法 `import`。使用 `moduleHandler` 来处理模块请求：\n\n```dart\nfinal engine = FlutterQjs(\n  moduleHandler: (String module) {\n    if(module == \"hello\")\n      return \"export default (name) =\u003e `hello \\${name}!`;\";\n    throw Exception(\"Module Not found\");\n  },\n);\n```\n\n在JavaScript中，`import` 方法用以获取模块：\n\n```javascript\nimport(\"hello\").then(({default: greet}) =\u003e greet(\"world\"));\n```\n\n**注：** 模块将只被编译一次. 调用 `FlutterQjs.close` 再 `evaluate` 来重置模块缓存。\n\n若要使用异步方法来处理模块请求，请参见 [在 isolate 中运行](#在-isolate-中运行)。\n\n## 在 isolate 中运行\n\n创建 `IsolateQjs` 对象，设置 `moduleHandler` 来处理模块请求。 现在可以使用异步函数来获得模块字符串，如 `rootBundle.loadString`：\n\n```dart\nfinal engine = IsolateQjs(\n  moduleHandler: (String module) async {\n    return await rootBundle.loadString(\n        \"js/\" + module.replaceFirst(new RegExp(r\".js$\"), \"\") + \".js\");\n  },\n);\n// not need engine.dispatch();\n```\n\n与在主线程运行一样，使用 `evaluate` 方法运行js脚本。在isolate中，所有结果都将异步返回，使用 `await` 来获取结果：\n\n```dart\ntry {\n  print(await engine.evaluate(code ?? ''));\n} catch (e) {\n  print(e.toString());\n}\n```\n\n使用 `close` 方法销毁 isolate 线程，其在再次调用 `evaluate` 时将会重建。\n\n## 调用 Dart 函数\n\nJs脚本返回函数将被转换为 `JSInvokable`。 **它不能像 `Function` 一样调用，请使用 `invoke` 方法来调用**：\n\n```dart\n(func as JSInvokable).invoke([arg1, arg2], thisVal);\n```\n\n**注：** 返回 `JSInvokable` 可能造成引用泄漏，需要手动调用 `free` 来释放引用：\n\n```dart\n(obj as JSRef).free();\n// or JSRef.freeRecursive(obj);\n```\n\n传递给 `JSInvokable` 的参数将自动释放. 使用 `dup` 来保持引用：\n\n```dart\n(obj as JSRef).dup();\n// or JSRef.dupRecursive(obj);\n```\n\n自 v0.3.0 起，dart 函数可以作为参数传递给 `JSInvokable`，且 `channel` 函数不再默认内置。可以使用如下方法将 dart 函数赋值给全局，例如，使用 `Dio` 来为 qjs 提供 http 支持：\n\n```dart\nfinal setToGlobalObject = await engine.evaluate(\"(key, val) =\u003e { this[key] = val; }\");\nawait setToGlobalObject.invoke([\"http\", (String url) {\n  return Dio().get(url).then((response) =\u003e response.data);\n}]);\nsetToGlobalObject.free();\n```\n\n在 isolate 模式下，只有顶层和静态函数能作为参数传给 `JSInvokable`，函数将在 isolate 线程中调用。 使用 `IsolateFunction` 来传递局部函数（将在主线程中调用）：\n\n```dart\nawait setToGlobalObject.invoke([\n  \"http\",\n  IsolateFunction((String url) {\n    return Dio().get(url).then((response) =\u003e response.data);\n  }),\n]);\n```","funding_links":[],"categories":["Dart"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekibun%2Fflutter_qjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekibun%2Fflutter_qjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekibun%2Fflutter_qjs/lists"}