UNPKG

@sebastianwessel/quickjs

Version:

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

59 lines (58 loc) 2.47 kB
import { createTimeInterval } from '../../createTimeInterval.js'; import { getMaxIntervalAmount } from '../getMaxIntervalAmount.js'; import { getMaxTimeoutAmount } from '../getMaxTimeoutAmount.js'; import { handleEvalError } from '../handleEvalError.js'; import { handleToNative } from '../handleToNative/handleToNative.js'; import { provideTimingFunctions } from '../provide/provideTimingFunctions.js'; export const createAsyncEvalCodeFunction = (input, scope) => { const { ctx, sandboxOptions, transpileFile } = input; return async (code, filename = '/src/index.js', evalOptions) => { const eventLoopinterval = createTimeInterval(() => ctx.runtime.executePendingJobs(), 0); let timeoutId; const { dispose: disposeTimer } = provideTimingFunctions(ctx, { maxTimeoutCount: getMaxTimeoutAmount(sandboxOptions), maxIntervalCount: getMaxIntervalAmount(sandboxOptions), }); const disposeStep = () => { if (timeoutId) { clearTimeout(timeoutId); } eventLoopinterval?.clear(); disposeTimer(); }; try { const jsCode = transpileFile(code); const evalResult = await ctx.evalCodeAsync(jsCode, filename, { strict: true, strip: false, backtraceBarrier: true, ...evalOptions, type: 'module', }); const handle = scope.manage(ctx.unwrapResult(evalResult)); const native = handleToNative(ctx, handle, scope); const result = await Promise.race([ (async () => { const res = await native; return res.default; })(), new Promise((_resolve, reject) => { if (sandboxOptions.executionTimeout) { timeoutId = setTimeout(() => { const err = new Error('The script execution has exceeded the maximum allowed time limit.'); err.name = 'ExecutionTimeout'; reject(err); }, sandboxOptions.executionTimeout); } }), ]); return { ok: true, data: result }; } catch (err) { return handleEvalError(err); } finally { disposeStep(); } }; };