add hw2
This commit is contained in:
302
node_modules/@tootallnate/quickjs-emscripten/dist/module.js
generated
vendored
Normal file
302
node_modules/@tootallnate/quickjs-emscripten/dist/module.js
generated
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.QuickJSWASMModule = exports.applyModuleEvalRuntimeOptions = exports.applyBaseRuntimeOptions = exports.QuickJSModuleCallbacks = void 0;
|
||||
const debug_1 = require("./debug");
|
||||
const errors_1 = require("./errors");
|
||||
const lifetime_1 = require("./lifetime");
|
||||
const runtime_1 = require("./runtime");
|
||||
const types_1 = require("./types");
|
||||
class QuickJSEmscriptenModuleCallbacks {
|
||||
constructor(args) {
|
||||
this.callFunction = args.callFunction;
|
||||
this.shouldInterrupt = args.shouldInterrupt;
|
||||
this.loadModuleSource = args.loadModuleSource;
|
||||
this.normalizeModule = args.normalizeModule;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* We use static functions per module to dispatch runtime or context calls from
|
||||
* C to the host. This class manages the indirection from a specific runtime or
|
||||
* context pointer to the appropriate callback handler.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
class QuickJSModuleCallbacks {
|
||||
constructor(module) {
|
||||
this.contextCallbacks = new Map();
|
||||
this.runtimeCallbacks = new Map();
|
||||
this.suspendedCount = 0;
|
||||
this.cToHostCallbacks = new QuickJSEmscriptenModuleCallbacks({
|
||||
callFunction: (asyncify, ctx, this_ptr, argc, argv, fn_id) => this.handleAsyncify(asyncify, () => {
|
||||
try {
|
||||
const vm = this.contextCallbacks.get(ctx);
|
||||
if (!vm) {
|
||||
throw new Error(`QuickJSContext(ctx = ${ctx}) not found for C function call "${fn_id}"`);
|
||||
}
|
||||
return vm.callFunction(ctx, this_ptr, argc, argv, fn_id);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[C to host error: returning null]", error);
|
||||
return 0;
|
||||
}
|
||||
}),
|
||||
shouldInterrupt: (asyncify, rt) => this.handleAsyncify(asyncify, () => {
|
||||
try {
|
||||
const vm = this.runtimeCallbacks.get(rt);
|
||||
if (!vm) {
|
||||
throw new Error(`QuickJSRuntime(rt = ${rt}) not found for C interrupt`);
|
||||
}
|
||||
return vm.shouldInterrupt(rt);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[C to host interrupt: returning error]", error);
|
||||
return 1;
|
||||
}
|
||||
}),
|
||||
loadModuleSource: (asyncify, rt, ctx, moduleName) => this.handleAsyncify(asyncify, () => {
|
||||
try {
|
||||
const runtimeCallbacks = this.runtimeCallbacks.get(rt);
|
||||
if (!runtimeCallbacks) {
|
||||
throw new Error(`QuickJSRuntime(rt = ${rt}) not found for C module loader`);
|
||||
}
|
||||
const loadModule = runtimeCallbacks.loadModuleSource;
|
||||
if (!loadModule) {
|
||||
throw new Error(`QuickJSRuntime(rt = ${rt}) does not support module loading`);
|
||||
}
|
||||
return loadModule(rt, ctx, moduleName);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[C to host module loader error: returning null]", error);
|
||||
return 0;
|
||||
}
|
||||
}),
|
||||
normalizeModule: (asyncify, rt, ctx, moduleBaseName, moduleName) => this.handleAsyncify(asyncify, () => {
|
||||
try {
|
||||
const runtimeCallbacks = this.runtimeCallbacks.get(rt);
|
||||
if (!runtimeCallbacks) {
|
||||
throw new Error(`QuickJSRuntime(rt = ${rt}) not found for C module loader`);
|
||||
}
|
||||
const normalizeModule = runtimeCallbacks.normalizeModule;
|
||||
if (!normalizeModule) {
|
||||
throw new Error(`QuickJSRuntime(rt = ${rt}) does not support module loading`);
|
||||
}
|
||||
return normalizeModule(rt, ctx, moduleBaseName, moduleName);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[C to host module loader error: returning null]", error);
|
||||
return 0;
|
||||
}
|
||||
}),
|
||||
});
|
||||
this.module = module;
|
||||
this.module.callbacks = this.cToHostCallbacks;
|
||||
}
|
||||
setRuntimeCallbacks(rt, callbacks) {
|
||||
this.runtimeCallbacks.set(rt, callbacks);
|
||||
}
|
||||
deleteRuntime(rt) {
|
||||
this.runtimeCallbacks.delete(rt);
|
||||
}
|
||||
setContextCallbacks(ctx, callbacks) {
|
||||
this.contextCallbacks.set(ctx, callbacks);
|
||||
}
|
||||
deleteContext(ctx) {
|
||||
this.contextCallbacks.delete(ctx);
|
||||
}
|
||||
handleAsyncify(asyncify, fn) {
|
||||
if (asyncify) {
|
||||
// We must always call asyncify.handleSync around our function.
|
||||
// This allows asyncify to resume suspended execution on the second call.
|
||||
// Asyncify internally can detect sync behavior, and avoid suspending.
|
||||
return asyncify.handleSleep((done) => {
|
||||
try {
|
||||
const result = fn();
|
||||
if (!(result instanceof Promise)) {
|
||||
(0, debug_1.debugLog)("asyncify.handleSleep: not suspending:", result);
|
||||
done(result);
|
||||
return;
|
||||
}
|
||||
// Is promise, we intend to suspend.
|
||||
if (this.suspended) {
|
||||
throw new errors_1.QuickJSAsyncifyError(`Already suspended at: ${this.suspended.stack}\nAttempted to suspend at:`);
|
||||
}
|
||||
else {
|
||||
this.suspended = new errors_1.QuickJSAsyncifySuspended(`(${this.suspendedCount++})`);
|
||||
(0, debug_1.debugLog)("asyncify.handleSleep: suspending:", this.suspended);
|
||||
}
|
||||
result.then((resolvedResult) => {
|
||||
this.suspended = undefined;
|
||||
(0, debug_1.debugLog)("asyncify.handleSleep: resolved:", resolvedResult);
|
||||
done(resolvedResult);
|
||||
}, (error) => {
|
||||
(0, debug_1.debugLog)("asyncify.handleSleep: rejected:", error);
|
||||
console.error("QuickJS: cannot handle error in suspended function", error);
|
||||
this.suspended = undefined;
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
(0, debug_1.debugLog)("asyncify.handleSleep: error:", error);
|
||||
this.suspended = undefined;
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
// No asyncify - we should never return a promise.
|
||||
const value = fn();
|
||||
if (value instanceof Promise) {
|
||||
throw new Error("Promise return value not supported in non-asyncify context.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
exports.QuickJSModuleCallbacks = QuickJSModuleCallbacks;
|
||||
/**
|
||||
* Process RuntimeOptions and apply them to a QuickJSRuntime.
|
||||
* @private
|
||||
*/
|
||||
function applyBaseRuntimeOptions(runtime, options) {
|
||||
if (options.interruptHandler) {
|
||||
runtime.setInterruptHandler(options.interruptHandler);
|
||||
}
|
||||
if (options.maxStackSizeBytes !== undefined) {
|
||||
runtime.setMaxStackSize(options.maxStackSizeBytes);
|
||||
}
|
||||
if (options.memoryLimitBytes !== undefined) {
|
||||
runtime.setMemoryLimit(options.memoryLimitBytes);
|
||||
}
|
||||
}
|
||||
exports.applyBaseRuntimeOptions = applyBaseRuntimeOptions;
|
||||
/**
|
||||
* Process ModuleEvalOptions and apply them to a QuickJSRuntime.
|
||||
* @private
|
||||
*/
|
||||
function applyModuleEvalRuntimeOptions(runtime, options) {
|
||||
if (options.moduleLoader) {
|
||||
runtime.setModuleLoader(options.moduleLoader);
|
||||
}
|
||||
if (options.shouldInterrupt) {
|
||||
runtime.setInterruptHandler(options.shouldInterrupt);
|
||||
}
|
||||
if (options.memoryLimitBytes !== undefined) {
|
||||
runtime.setMemoryLimit(options.memoryLimitBytes);
|
||||
}
|
||||
if (options.maxStackSizeBytes !== undefined) {
|
||||
runtime.setMaxStackSize(options.maxStackSizeBytes);
|
||||
}
|
||||
}
|
||||
exports.applyModuleEvalRuntimeOptions = applyModuleEvalRuntimeOptions;
|
||||
/**
|
||||
* This class presents a Javascript interface to QuickJS, a Javascript interpreter
|
||||
* that supports EcmaScript 2020 (ES2020).
|
||||
*
|
||||
* It wraps a single WebAssembly module containing the QuickJS library and
|
||||
* associated helper C code. WebAssembly modules are completely isolated from
|
||||
* each other by the host's WebAssembly runtime. Separate WebAssembly modules
|
||||
* have the most isolation guarantees possible with this library.
|
||||
*
|
||||
* The simplest way to start running code is {@link evalCode}. This shortcut
|
||||
* method will evaluate Javascript safely and return the result as a native
|
||||
* Javascript value.
|
||||
*
|
||||
* For more control over the execution environment, or to interact with values
|
||||
* inside QuickJS, create a context with {@link newContext} or a runtime with
|
||||
* {@link newRuntime}.
|
||||
*/
|
||||
class QuickJSWASMModule {
|
||||
/** @private */
|
||||
constructor(module, ffi) {
|
||||
this.module = module;
|
||||
this.ffi = ffi;
|
||||
this.callbacks = new QuickJSModuleCallbacks(module);
|
||||
}
|
||||
/**
|
||||
* Create a runtime.
|
||||
* Use the runtime to set limits on CPU and memory usage and configure module
|
||||
* loading for one or more [[QuickJSContext]]s inside the runtime.
|
||||
*/
|
||||
newRuntime(options = {}) {
|
||||
const rt = new lifetime_1.Lifetime(this.ffi.QTS_NewRuntime(), undefined, (rt_ptr) => {
|
||||
this.callbacks.deleteRuntime(rt_ptr);
|
||||
this.ffi.QTS_FreeRuntime(rt_ptr);
|
||||
});
|
||||
const runtime = new runtime_1.QuickJSRuntime({
|
||||
module: this.module,
|
||||
callbacks: this.callbacks,
|
||||
ffi: this.ffi,
|
||||
rt,
|
||||
});
|
||||
applyBaseRuntimeOptions(runtime, options);
|
||||
if (options.moduleLoader) {
|
||||
runtime.setModuleLoader(options.moduleLoader);
|
||||
}
|
||||
return runtime;
|
||||
}
|
||||
/**
|
||||
* A simplified API to create a new [[QuickJSRuntime]] and a
|
||||
* [[QuickJSContext]] inside that runtime at the same time. The runtime will
|
||||
* be disposed when the context is disposed.
|
||||
*/
|
||||
newContext(options = {}) {
|
||||
const runtime = this.newRuntime();
|
||||
const context = runtime.newContext({
|
||||
...options,
|
||||
ownedLifetimes: (0, types_1.concat)(runtime, options.ownedLifetimes),
|
||||
});
|
||||
runtime.context = context;
|
||||
return context;
|
||||
}
|
||||
/**
|
||||
* One-off evaluate code without needing to create a [[QuickJSRuntime]] or
|
||||
* [[QuickJSContext]] explicitly.
|
||||
*
|
||||
* To protect against infinite loops, use the `shouldInterrupt` option. The
|
||||
* [[shouldInterruptAfterDeadline]] function will create a time-based deadline.
|
||||
*
|
||||
* If you need more control over how the code executes, create a
|
||||
* [[QuickJSRuntime]] (with [[newRuntime]]) or a [[QuickJSContext]] (with
|
||||
* [[newContext]] or [[QuickJSRuntime.newContext]]), and use its
|
||||
* [[QuickJSContext.evalCode]] method.
|
||||
*
|
||||
* Asynchronous callbacks may not run during the first call to `evalCode`. If
|
||||
* you need to work with async code inside QuickJS, create a runtime and use
|
||||
* [[QuickJSRuntime.executePendingJobs]].
|
||||
*
|
||||
* @returns The result is coerced to a native Javascript value using JSON
|
||||
* serialization, so properties and values unsupported by JSON will be dropped.
|
||||
*
|
||||
* @throws If `code` throws during evaluation, the exception will be
|
||||
* converted into a native Javascript value and thrown.
|
||||
*
|
||||
* @throws if `options.shouldInterrupt` interrupted execution, will throw a Error
|
||||
* with name `"InternalError"` and message `"interrupted"`.
|
||||
*/
|
||||
evalCode(code, options = {}) {
|
||||
return lifetime_1.Scope.withScope((scope) => {
|
||||
const vm = scope.manage(this.newContext());
|
||||
applyModuleEvalRuntimeOptions(vm.runtime, options);
|
||||
const result = vm.evalCode(code, "eval.js");
|
||||
if (options.memoryLimitBytes !== undefined) {
|
||||
// Remove memory limit so we can dump the result without exceeding it.
|
||||
vm.runtime.setMemoryLimit(-1);
|
||||
}
|
||||
if (result.error) {
|
||||
const error = vm.dump(scope.manage(result.error));
|
||||
throw error;
|
||||
}
|
||||
const value = vm.dump(scope.manage(result.value));
|
||||
return value;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get a low-level interface to the QuickJS functions in this WebAssembly
|
||||
* module.
|
||||
* @experimental
|
||||
* @unstable No warranty is provided with this API. It could change at any time.
|
||||
* @private
|
||||
*/
|
||||
getFFI() {
|
||||
return this.ffi;
|
||||
}
|
||||
}
|
||||
exports.QuickJSWASMModule = QuickJSWASMModule;
|
||||
//# sourceMappingURL=module.js.map
|
||||
Reference in New Issue
Block a user