module-asyncify.js 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.QuickJSAsyncWASMModule = void 0;
  4. const errors_1 = require("./errors");
  5. const lifetime_1 = require("./lifetime");
  6. const module_1 = require("./module");
  7. const runtime_asyncify_1 = require("./runtime-asyncify");
  8. /**
  9. * Asyncified version of [[QuickJSWASMModule]].
  10. *
  11. * Due to limitations of Emscripten's ASYNCIFY process, only a single async
  12. * function call can happen at a time across the entire WebAssembly module.
  13. *
  14. * That means that all runtimes, contexts, functions, etc created inside this
  15. * WebAssembly are limited to a single concurrent async action.
  16. * **Multiple concurrent async actions is an error.**
  17. *
  18. * To allow for multiple concurrent async actions, you must create multiple WebAssembly
  19. * modules.
  20. */
  21. class QuickJSAsyncWASMModule extends module_1.QuickJSWASMModule {
  22. /** @private */
  23. constructor(module, ffi) {
  24. super(module, ffi);
  25. this.ffi = ffi;
  26. this.module = module;
  27. }
  28. /**
  29. * Create a new async runtime inside this WebAssembly module. All runtimes inside a
  30. * module are limited to a single async call at a time. For multiple
  31. * concurrent async actions, create multiple WebAssembly modules.
  32. */
  33. newRuntime(options = {}) {
  34. const rt = new lifetime_1.Lifetime(this.ffi.QTS_NewRuntime(), undefined, (rt_ptr) => {
  35. this.callbacks.deleteRuntime(rt_ptr);
  36. this.ffi.QTS_FreeRuntime(rt_ptr);
  37. });
  38. const runtime = new runtime_asyncify_1.QuickJSAsyncRuntime({
  39. module: this.module,
  40. ffi: this.ffi,
  41. rt,
  42. callbacks: this.callbacks,
  43. });
  44. (0, module_1.applyBaseRuntimeOptions)(runtime, options);
  45. if (options.moduleLoader) {
  46. runtime.setModuleLoader(options.moduleLoader);
  47. }
  48. return runtime;
  49. }
  50. /**
  51. * A simplified API to create a new [[QuickJSRuntime]] and a
  52. * [[QuickJSContext]] inside that runtime at the same time. The runtime will
  53. * be disposed when the context is disposed.
  54. */
  55. newContext(options = {}) {
  56. const runtime = this.newRuntime();
  57. const lifetimes = options.ownedLifetimes ? options.ownedLifetimes.concat([runtime]) : [runtime];
  58. const context = runtime.newContext({ ...options, ownedLifetimes: lifetimes });
  59. runtime.context = context;
  60. return context;
  61. }
  62. /** Synchronous evalCode is not supported. */
  63. evalCode() {
  64. throw new errors_1.QuickJSNotImplemented("QuickJSWASMModuleAsyncify.evalCode: use evalCodeAsync instead");
  65. }
  66. /**
  67. * One-off evaluate code without needing to create a [[QuickJSRuntimeAsync]] or
  68. * [[QuickJSContextSync]] explicitly.
  69. *
  70. * This version allows for asynchronous Ecmascript module loading.
  71. *
  72. * Note that only a single async action can occur at a time inside the entire WebAssembly module.
  73. * **Multiple concurrent async actions is an error.**
  74. *
  75. * See the documentation for [[QuickJSWASMModule.evalCode]] for more details.
  76. */
  77. evalCodeAsync(code, options) {
  78. // TODO: we should really figure out generator for the Promise monad...
  79. return lifetime_1.Scope.withScopeAsync(async (scope) => {
  80. const vm = scope.manage(this.newContext());
  81. (0, module_1.applyModuleEvalRuntimeOptions)(vm.runtime, options);
  82. const result = await vm.evalCodeAsync(code, "eval.js");
  83. if (options.memoryLimitBytes !== undefined) {
  84. // Remove memory limit so we can dump the result without exceeding it.
  85. vm.runtime.setMemoryLimit(-1);
  86. }
  87. if (result.error) {
  88. const error = vm.dump(scope.manage(result.error));
  89. throw error;
  90. }
  91. const value = vm.dump(scope.manage(result.value));
  92. return value;
  93. });
  94. }
  95. }
  96. exports.QuickJSAsyncWASMModule = QuickJSAsyncWASMModule;
  97. //# sourceMappingURL=module-asyncify.js.map