runtime.d.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { QuickJSContext } from "./context";
  2. import { EitherModule } from "./emscripten-types";
  3. import { JSContextPointer, JSRuntimePointer } from "./types-ffi";
  4. import { Disposable, Lifetime, Scope } from "./lifetime";
  5. import { ModuleMemory } from "./memory";
  6. import { QuickJSModuleCallbacks } from "./module";
  7. import { ContextOptions, EitherFFI, JSModuleLoader, JSModuleNormalizer, QuickJSHandle } from "./types";
  8. import { SuccessOrFail } from "./vm-interface";
  9. /**
  10. * Callback called regularly while the VM executes code.
  11. * Determines if a VM's execution should be interrupted.
  12. *
  13. * @returns `true` to interrupt JS execution inside the VM.
  14. * @returns `false` or `undefined` to continue JS execution inside the VM.
  15. */
  16. export type InterruptHandler = (runtime: QuickJSRuntime) => boolean | undefined;
  17. /**
  18. * Used as an optional for the results of executing pendingJobs.
  19. * On success, `value` contains the number of async jobs executed
  20. * by the runtime.
  21. * @source
  22. */
  23. export type ExecutePendingJobsResult = SuccessOrFail<
  24. /** Number of jobs successfully executed. */
  25. number,
  26. /** The error that occurred. */
  27. QuickJSHandle & {
  28. /** The context where the error occurred. */
  29. context: QuickJSContext;
  30. }>;
  31. /**
  32. * A runtime represents a Javascript runtime corresponding to an object heap.
  33. * Several runtimes can exist at the same time but they cannot exchange objects.
  34. * Inside a given runtime, no multi-threading is supported.
  35. *
  36. * You can think of separate runtimes like different domains in a browser, and
  37. * the contexts within a runtime like the different windows open to the same
  38. * domain.
  39. *
  40. * Create a runtime via {@link QuickJSWASMModule.newRuntime}.
  41. *
  42. * You should create separate runtime instances for untrusted code from
  43. * different sources for isolation. However, stronger isolation is also
  44. * available (at the cost of memory usage), by creating separate WebAssembly
  45. * modules to further isolate untrusted code.
  46. * See {@link newQuickJSWASMModule}.
  47. *
  48. * Implement memory and CPU constraints with [[setInterruptHandler]]
  49. * (called regularly while the interpreter runs), [[setMemoryLimit]], and
  50. * [[setMaxStackSize]].
  51. * Use [[computeMemoryUsage]] or [[dumpMemoryUsage]] to guide memory limit
  52. * tuning.
  53. *
  54. * Configure ES module loading with [[setModuleLoader]].
  55. */
  56. export declare class QuickJSRuntime implements Disposable {
  57. /**
  58. * If this runtime was created as as part of a context, points to the context
  59. * associated with the runtime.
  60. *
  61. * If this runtime was created stand-alone, this may or may not contain a context.
  62. * A context here may be allocated if one is needed by the runtime, eg for [[computeMemoryUsage]].
  63. */
  64. context: QuickJSContext | undefined;
  65. /** @private */
  66. protected module: EitherModule;
  67. /** @private */
  68. protected memory: ModuleMemory;
  69. /** @private */
  70. protected ffi: EitherFFI;
  71. /** @private */
  72. protected rt: Lifetime<JSRuntimePointer>;
  73. /** @private */
  74. protected callbacks: QuickJSModuleCallbacks;
  75. /** @private */
  76. protected scope: Scope;
  77. /** @private */
  78. protected contextMap: Map<JSContextPointer, QuickJSContext>;
  79. /** @private */
  80. protected moduleLoader: JSModuleLoader | undefined;
  81. /** @private */
  82. protected moduleNormalizer: JSModuleNormalizer | undefined;
  83. /** @private */
  84. constructor(args: {
  85. module: EitherModule;
  86. ffi: EitherFFI;
  87. rt: Lifetime<JSRuntimePointer>;
  88. callbacks: QuickJSModuleCallbacks;
  89. ownedLifetimes?: Disposable[];
  90. });
  91. get alive(): boolean;
  92. dispose(): void;
  93. newContext(options?: ContextOptions): QuickJSContext;
  94. /**
  95. * Set the loader for EcmaScript modules requested by any context in this
  96. * runtime.
  97. *
  98. * The loader can be removed with [[removeModuleLoader]].
  99. */
  100. setModuleLoader(moduleLoader: JSModuleLoader, moduleNormalizer?: JSModuleNormalizer): void;
  101. /**
  102. * Remove the the loader set by [[setModuleLoader]]. This disables module loading.
  103. */
  104. removeModuleLoader(): void;
  105. /**
  106. * In QuickJS, promises and async functions create pendingJobs. These do not execute
  107. * immediately and need to be run by calling [[executePendingJobs]].
  108. *
  109. * @return true if there is at least one pendingJob queued up.
  110. */
  111. hasPendingJob(): boolean;
  112. private interruptHandler;
  113. /**
  114. * Set a callback which is regularly called by the QuickJS engine when it is
  115. * executing code. This callback can be used to implement an execution
  116. * timeout.
  117. *
  118. * The interrupt handler can be removed with [[removeInterruptHandler]].
  119. */
  120. setInterruptHandler(cb: InterruptHandler): void;
  121. /**
  122. * Remove the interrupt handler, if any.
  123. * See [[setInterruptHandler]].
  124. */
  125. removeInterruptHandler(): void;
  126. /**
  127. * Execute pendingJobs on the runtime until `maxJobsToExecute` jobs are
  128. * executed (default all pendingJobs), the queue is exhausted, or the runtime
  129. * encounters an exception.
  130. *
  131. * In QuickJS, promises and async functions *inside the runtime* create
  132. * pendingJobs. These do not execute immediately and need to triggered to run.
  133. *
  134. * @param maxJobsToExecute - When negative, run all pending jobs. Otherwise execute
  135. * at most `maxJobsToExecute` before returning.
  136. *
  137. * @return On success, the number of executed jobs. On error, the exception
  138. * that stopped execution, and the context it occurred in. Note that
  139. * executePendingJobs will not normally return errors thrown inside async
  140. * functions or rejected promises. Those errors are available by calling
  141. * [[resolvePromise]] on the promise handle returned by the async function.
  142. */
  143. executePendingJobs(maxJobsToExecute?: number | void): ExecutePendingJobsResult;
  144. /**
  145. * Set the max memory this runtime can allocate.
  146. * To remove the limit, set to `-1`.
  147. */
  148. setMemoryLimit(limitBytes: number): void;
  149. /**
  150. * Compute memory usage for this runtime. Returns the result as a handle to a
  151. * JSValue object. Use [[QuickJSContext.dump]] to convert to a native object.
  152. * Calling this method will allocate more memory inside the runtime. The information
  153. * is accurate as of just before the call to `computeMemoryUsage`.
  154. * For a human-digestible representation, see [[dumpMemoryUsage]].
  155. */
  156. computeMemoryUsage(): QuickJSHandle;
  157. /**
  158. * @returns a human-readable description of memory usage in this runtime.
  159. * For programmatic access to this information, see [[computeMemoryUsage]].
  160. */
  161. dumpMemoryUsage(): string;
  162. /**
  163. * Set the max stack size for this runtime, in bytes.
  164. * To remove the limit, set to `0`.
  165. */
  166. setMaxStackSize(stackSize: number): void;
  167. /**
  168. * Assert that `handle` is owned by this runtime.
  169. * @throws QuickJSWrongOwner if owned by a different runtime.
  170. */
  171. assertOwned(handle: QuickJSHandle): void;
  172. private getSystemContext;
  173. private cToHostCallbacks;
  174. }