UNPKG

@sebastianwessel/quickjs

Version:

A typescript package to execute JavaScript and TypeScript code in a WebAssembly QuickJS sandbox

79 lines (78 loc) 4.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadAsyncQuickJs = void 0; const quickjs_emscripten_core_1 = require("quickjs-emscripten-core"); const getTypescriptSupport_js_1 = require("./getTypescriptSupport.js"); const executeAsyncSandboxFunction_js_1 = require("./sandbox/asyncVersion/executeAsyncSandboxFunction.js"); const getAsyncModuleLoader_js_1 = require("./sandbox/asyncVersion/getAsyncModuleLoader.js"); const modulePathNormalizerAsync_js_1 = require("./sandbox/asyncVersion/modulePathNormalizerAsync.js"); const prepareAsyncNodeCompatibility_js_1 = require("./sandbox/asyncVersion/prepareAsyncNodeCompatibility.js"); const prepareAsyncSandbox_js_1 = require("./sandbox/asyncVersion/prepareAsyncSandbox.js"); const pendingHostPromises_js_1 = require("./sandbox/expose/pendingHostPromises.js"); const setupFileSystem_js_1 = require("./sandbox/setupFileSystem.js"); /** * Loads the QuickJS async module and returns a sandbox execution function. * @param variant - Options for loading the QuickJS module. Defaults to '@jitl/quickjs-ng-wasmfile-release-asyncify'. * @returns An object containing the runSandboxed function and the loaded module. */ const loadAsyncQuickJs = async (variant) => { const module = await (0, quickjs_emscripten_core_1.newQuickJSAsyncWASMModuleFromVariant)(variant); /** * Provides a new sandbox and executes the given function. * When the function has been finished, the sandbox gets disposed and can longer be used. * * @param sandboxedFunction * @param sandboxOptions * @returns */ const runSandboxed = async (sandboxedFunction, sandboxOptions = {}) => { const scope = new quickjs_emscripten_core_1.Scope(); let ctx; try { ctx = scope.manage(module.newContext()); if (sandboxOptions.maxStackSize) { ctx.runtime.setMaxStackSize(sandboxOptions.maxStackSize); } if (sandboxOptions.memoryLimit) { ctx.runtime.setMemoryLimit(sandboxOptions.memoryLimit); } // Virtual File System, const fs = (0, setupFileSystem_js_1.setupFileSystem)(sandboxOptions); // TypeScript Support: const { transpileVirtualFs, transpileFile } = await (0, getTypescriptSupport_js_1.getTypescriptSupport)(sandboxOptions.transformTypescript, sandboxOptions.typescriptImportFile, sandboxOptions.transformCompilerOptions); // if typescript support is enabled, transpile all ts files in file system transpileVirtualFs(fs); // JS Module Loader const moduleLoader = sandboxOptions.getModuleLoader ? sandboxOptions.getModuleLoader(fs, sandboxOptions) : (0, getAsyncModuleLoader_js_1.getAsyncModuleLoader)(fs, sandboxOptions); ctx.runtime.setModuleLoader(moduleLoader, sandboxOptions.modulePathNormalizer ?? modulePathNormalizerAsync_js_1.modulePathNormalizerAsync); // Register Globals to be more Node.js compatible await (0, prepareAsyncNodeCompatibility_js_1.prepareAsyncNodeCompatibility)(ctx, sandboxOptions); // Prepare the Sandbox // Expose Data and Functions to Client (0, prepareAsyncSandbox_js_1.prepareAsyncSandbox)(ctx, scope, sandboxOptions, fs); if (sandboxOptions.executionTimeout) { ctx.runtime.setInterruptHandler((0, quickjs_emscripten_core_1.shouldInterruptAfterDeadline)(Date.now() + sandboxOptions.executionTimeout)); } // Run the given Function const result = await (0, executeAsyncSandboxFunction_js_1.executeAsyncSandboxFunction)({ ctx, fs, scope, sandboxOptions, sandboxedFunction, transpileFile, }); return result; } finally { if (ctx) { await (0, pendingHostPromises_js_1.rejectAndFlushPendingHostPromises)(ctx); } scope.dispose(); } }; return { runSandboxed, module }; }; exports.loadAsyncQuickJs = loadAsyncQuickJs;