UNPKG

@mariozechner/jailjs

Version:

Lightweight JavaScript interpreter for isolated execution. For plugins, user scripts, and browser extensions. Not for adversarial code - use SandboxJS or isolated-vm for that.

87 lines 3.11 kB
import * as Babel from "@babel/standalone"; /** * Transform modern JavaScript (ES6+) to ES5 AST for interpreter execution * * This function uses Babel to transform modern JavaScript syntax to ES5, * then parses it into an AST. The resulting AST can be executed by the interpreter. * * @param code - Modern JavaScript code (ES6+, TypeScript, JSX, etc.) * @param options - Babel transformation options * @returns ES5 AST Program node * * @example * ```typescript * import { Interpreter } from '@mariozechner/jailjs'; * import { transformToES5 } from '@mariozechner/jailjs/transform'; * * const modernCode = ` * const double = (x) => x * 2; * const numbers = [1, 2, 3]; * numbers.map(double); * `; * * const ast = transformToES5(modernCode); * const interpreter = new Interpreter(); * const result = interpreter.evaluate(ast); * console.log(result); // [2, 4, 6] * ``` */ export function transformToES5(code, options = {}) { const presets = [ [ "env", { targets: options.targets || { ie: 9 }, // IE9 = pure ES5, no Symbol // Don't add polyfills, just transform syntax useBuiltIns: false, // Force all transforms, no native ES6+ features forceAllTransforms: true, // Use loose mode for simpler ES5 output without Object.defineProperty loose: true, }, ], ]; if (options.typescript) { presets.push("typescript"); } if (options.jsx) { presets.push("react"); } try { const result = Babel.transform(code, { presets, filename: "script.js", ast: true, code: true, // Need code output to patch helpers // Babel assumptions for pure ES5 output assumptions: { noDocumentAll: true, noClassCalls: true, iterableIsArray: true, objectRestNoSymbols: true, setSpreadProperties: true, skipForOfIteratorClosing: true, }, }); if (!result?.code) { throw new Error("Babel transformation failed to produce code"); } // Patch Babel's _unsupportedIterableToArray to handle NodeList-like objects let patchedCode = result.code; patchedCode = patchedCode.replace(/(function _unsupportedIterableToArray\([^)]+\)\s*\{\s*if\s*\([^)]+\)\s*\{\s*if\s*\([^)]+typeof[^)]+\)\s*return[^;]+;)/, '$1 if ("object" == typeof r && "length" in r) return _arrayLikeToArray(r, a);'); // Parse patched code back to AST const finalResult = Babel.transform(patchedCode, { filename: "script.js", ast: true, code: false, }); if (!finalResult?.ast?.program) { throw new Error("Failed to parse patched code"); } return finalResult.ast.program; } catch (error) { throw new Error(`Failed to transform code: ${error.message}`); } } //# sourceMappingURL=transform.js.map