var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import axios from "axios";
import crypto from "crypto";
import http from "http";
import https from "https";
import ivm from "isolated-vm";
import CaptureSpan from "../Telemetry/CaptureSpan";
import vm from "vm";
/**
 * Symbol used to retrieve the real (unwrapped) target from a sandbox proxy.
 * Hidden from user code via ownKeys / has traps.
 */
const PROXY_TARGET_SYMBOL = Symbol("sandboxProxyTarget");
/**
 * Hardening prelude injected before user code in `runCodeInNodeVM`.
 *
 * Node's `vm` module is not a security boundary. The published PoC for
 * GHSA-g9cp-35m2-fjv6 forces a stack-overflow `RangeError`, walks
 * `e.__proto__.__proto__.__proto__` to `Object.prototype`, then reads
 * `.toString.constructor` to obtain a `Function` constructor that compiles
 * code in a realm where `process.binding('spawn_sync')` is reachable.
 *
 * This prelude closes that path by:
 *  - severing `Error.prototype`'s link to `Object.prototype` so the 3-level
 *    walk lands on `null` instead of `Object.prototype`;
 *  - deleting `.constructor` from every built-in prototype, so even a
 *    different walk (e.g. `(0).constructor.constructor`) cannot resolve to a
 *    function constructor;
 *  - clearing `Function` / `eval` from the sandbox global;
 *  - freezing the affected prototypes so user code cannot reattach them.
 *
 * This is a hotfix for the public PoC. The durable fix is to drop
 * `runCodeInNodeVM` in favor of running synthetic monitor scripts in an
 * out-of-process sandbox (tracked on the `probe-runner` branch).
 */
const VM_HARDENING_PRELUDE = `(() => {
  const _ctors = [
    Object, Function, Array, String, Number, Boolean, RegExp,
    Error, RangeError, TypeError, SyntaxError, ReferenceError, EvalError, URIError,
    Symbol, Date, Map, Set, WeakMap, WeakSet, Promise, Proxy,
    ArrayBuffer, DataView,
    Int8Array, Uint8Array, Uint8ClampedArray,
    Int16Array, Uint16Array, Int32Array, Uint32Array,
    Float32Array, Float64Array,
  ];
  if (typeof BigInt !== 'undefined') _ctors.push(BigInt);

  for (const C of _ctors) {
    try { if (C && C.prototype) delete C.prototype.constructor; } catch (_) {}
  }

  // Generator / async-function prototypes have no named global — reach via syntax.
  try { delete Object.getPrototypeOf(function*(){}).constructor; } catch (_) {}
  try { delete Object.getPrototypeOf(async function(){}).constructor; } catch (_) {}
  try { delete Object.getPrototypeOf(async function*(){}).constructor; } catch (_) {}

  try { Object.setPrototypeOf(Error.prototype, null); } catch (_) {}

  try {
    Object.defineProperty(globalThis, 'Function', {
      value: undefined, writable: false, configurable: false,
    });
  } catch (_) {}
  try {
    Object.defineProperty(globalThis, 'eval', {
      value: undefined, writable: false, configurable: false,
    });
  } catch (_) {}

  for (const C of _ctors) {
    try { if (C && C.prototype) Object.freeze(C.prototype); } catch (_) {}
  }
})();`;
/** Properties blocked on every host-realm object exposed to the sandbox. */
const BLOCKED_SANDBOX_PROPERTIES = new Set([
    "constructor",
    "__proto__",
    "prototype",
    "mainModule",
    /*
     * Block Playwright methods that can spawn processes or access internals.
     * Prevents RCE via browser.browserType().launch({executablePath:"/bin/sh"})
     * and traversal via page.context().browser().browserType().launch(...)
     */
    "browserType", // Browser → BrowserType (which has launch/connect)
    "_browserType", // Internal alias for browserType — same escape vector
    "launch", // BrowserType.launch() spawns a child process
    "launchServer", // BrowserType.launchServer() spawns a browser server process
    "launchPersistentContext", // BrowserType.launchPersistentContext() spawns a child process
    "connectOverCDP", // BrowserType.connectOverCDP() connects via Chrome DevTools Protocol
    "connect", // BrowserType.connect() connects to a remote browser
    "newCDPSession", // BrowserContext/Page.newCDPSession() opens raw CDP sessions
]);
/**
 * Wraps a host-realm value in a Proxy that blocks prototype-chain traversal.
 * Primitives and null/undefined pass through unchanged.
 * Object proxies are cached to preserve identity; function proxies are created
 * per-access so they bind to the correct `this` (parent object).
 */
function createSandboxProxy(value, cache, parentObj) {
    if (value === null || value === undefined) {
        return value;
    }
    const valueType = typeof value;
    if (valueType !== "object" && valueType !== "function") {
        return value;
    }
    const target = value;
    if (valueType === "function") {
        /*
         * Function proxies are NOT cached because the same function may be a method
         * on different parent objects and needs a different `this` binding each time.
         */
        const fnProxy = new Proxy(target, {
            get(fnTarget, prop) {
                if (prop === PROXY_TARGET_SYMBOL) {
                    return fnTarget;
                }
                if (typeof prop === "string" &&
                    BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                    return undefined;
                }
                const val = Reflect.get(fnTarget, prop, fnTarget);
                return createSandboxProxy(val, cache, fnTarget);
            },
            getPrototypeOf() {
                return null;
            },
            apply(fnTarget, _thisArg, args) {
                const thisObj = (parentObj ||
                    fnTarget);
                try {
                    const result = Reflect.apply(fnTarget, thisObj, args);
                    if (result instanceof Promise) {
                        return result.then((v) => {
                            return createSandboxProxy(v, cache);
                        }, (err) => {
                            throw createSandboxProxy(err, cache);
                        });
                    }
                    return createSandboxProxy(result, cache);
                }
                catch (err) {
                    throw createSandboxProxy(err, cache);
                }
            },
            has(fnTarget, prop) {
                if (typeof prop === "string" &&
                    BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                    return false;
                }
                return Reflect.has(fnTarget, prop);
            },
            ownKeys(fnTarget) {
                return Reflect.ownKeys(fnTarget).filter((k) => {
                    return !(typeof k === "string" && BLOCKED_SANDBOX_PROPERTIES.has(k));
                });
            },
            getOwnPropertyDescriptor(fnTarget, prop) {
                if (typeof prop === "string" &&
                    BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                    return undefined;
                }
                const desc = Reflect.getOwnPropertyDescriptor(fnTarget, prop);
                if (desc && "value" in desc) {
                    desc.value = createSandboxProxy(desc.value, cache, fnTarget);
                }
                return desc;
            },
        });
        return fnProxy;
    }
    // Object — use cache to preserve identity and handle circular references
    if (cache.has(target)) {
        return cache.get(target);
    }
    const objProxy = new Proxy(target, {
        get(objTarget, prop) {
            if (prop === PROXY_TARGET_SYMBOL) {
                return objTarget;
            }
            if (typeof prop === "string" && BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                return undefined;
            }
            const val = Reflect.get(objTarget, prop, objTarget);
            return createSandboxProxy(val, cache, objTarget);
        },
        getPrototypeOf() {
            return null;
        },
        set(objTarget, prop, newValue) {
            return Reflect.set(objTarget, prop, newValue);
        },
        has(objTarget, prop) {
            if (typeof prop === "string" && BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                return false;
            }
            return Reflect.has(objTarget, prop);
        },
        ownKeys(objTarget) {
            return Reflect.ownKeys(objTarget).filter((k) => {
                return !(typeof k === "string" && BLOCKED_SANDBOX_PROPERTIES.has(k));
            });
        },
        getOwnPropertyDescriptor(objTarget, prop) {
            if (typeof prop === "string" && BLOCKED_SANDBOX_PROPERTIES.has(prop)) {
                return undefined;
            }
            const desc = Reflect.getOwnPropertyDescriptor(objTarget, prop);
            if (desc && "value" in desc) {
                desc.value = createSandboxProxy(desc.value, cache, objTarget);
            }
            return desc;
        },
    });
    cache.set(target, objProxy);
    return objProxy;
}
/**
 * Recursively unwraps sandbox proxies in a return value so the host code
 * receives original objects (e.g. Buffers that pass `instanceof` checks).
 */
export function deepUnwrapProxies(value, visited) {
    if (value === null || value === undefined) {
        return value;
    }
    const valueType = typeof value;
    if (valueType !== "object" && valueType !== "function") {
        return value;
    }
    const obj = value;
    // If it's one of our proxies, unwrap to the original target
    try {
        const underlying = obj[PROXY_TARGET_SYMBOL];
        if (underlying !== undefined) {
            return underlying;
        }
    }
    catch (_a) {
        // Not a proxy or symbol access failed — treat as a plain value
    }
    if (!visited) {
        visited = new WeakSet();
    }
    if (visited.has(obj)) {
        return obj;
    }
    visited.add(obj);
    if (Array.isArray(obj)) {
        for (let i = 0; i < obj.length; i++) {
            obj[i] = deepUnwrapProxies(obj[i], visited);
        }
    }
    else if (valueType === "object") {
        for (const key of Object.keys(obj)) {
            obj[key] = deepUnwrapProxies(obj[key], visited);
        }
    }
    return obj;
}
/**
 * Unwraps a single value if it is a sandbox proxy, otherwise returns it as-is.
 */
function unwrapProxy(value) {
    if (value && typeof value === "object") {
        const underlying = value[PROXY_TARGET_SYMBOL];
        if (underlying !== undefined) {
            return underlying;
        }
    }
    return value;
}
export default class VMRunner {
    static async runCodeInNodeVM(data) {
        const { code, options } = data;
        const timeout = options.timeout || 5000;
        const logMessages = [];
        const MAX_LOG_BYTES = 1000000; // 1MB cap
        let totalLogBytes = 0;
        const capturedMetrics = [];
        const MAX_METRICS = 100;
        const pendingTimeouts = [];
        const pendingIntervals = [];
        const wrappedSetTimeout = (fn, ms, ...rest) => {
            const handle = setTimeout(fn, ms, ...rest);
            pendingTimeouts.push(handle);
            return handle;
        };
        const wrappedClearTimeout = (handle) => {
            const actual = unwrapProxy(handle);
            clearTimeout(actual);
            const idx = pendingTimeouts.indexOf(actual);
            if (idx !== -1) {
                pendingTimeouts.splice(idx, 1);
            }
        };
        const wrappedSetInterval = (fn, ms, ...rest) => {
            const handle = setInterval(fn, ms, ...rest);
            pendingIntervals.push(handle);
            return handle;
        };
        const wrappedClearInterval = (handle) => {
            const actual = unwrapProxy(handle);
            clearInterval(actual);
            const idx = pendingIntervals.indexOf(actual);
            if (idx !== -1) {
                pendingIntervals.splice(idx, 1);
            }
        };
        // Proxy cache shared across all wrapped host objects in this execution
        const proxyCache = new WeakMap();
        // Use null-prototype object to break this.constructor chain on the global
        const sandbox = Object.create(null);
        sandbox["process"] = Object.freeze(Object.create(null));
        sandbox["console"] = createSandboxProxy({
            log: (...args) => {
                const msg = args.join(" ");
                totalLogBytes += msg.length;
                if (totalLogBytes <= MAX_LOG_BYTES) {
                    logMessages.push(msg);
                }
            },
        }, proxyCache);
        sandbox["http"] = createSandboxProxy(http, proxyCache);
        sandbox["https"] = createSandboxProxy(https, proxyCache);
        sandbox["axios"] = createSandboxProxy(axios, proxyCache);
        sandbox["crypto"] = createSandboxProxy(crypto, proxyCache);
        sandbox["setTimeout"] = createSandboxProxy(wrappedSetTimeout, proxyCache);
        sandbox["clearTimeout"] = createSandboxProxy(wrappedClearTimeout, proxyCache);
        sandbox["setInterval"] = createSandboxProxy(wrappedSetInterval, proxyCache);
        sandbox["clearInterval"] = createSandboxProxy(wrappedClearInterval, proxyCache);
        sandbox["oneuptime"] = createSandboxProxy({
            captureMetric: (name, value, attributes) => {
                if (typeof name !== "string" || name.length === 0) {
                    return;
                }
                if (typeof value !== "number" || isNaN(value)) {
                    return;
                }
                if (capturedMetrics.length >= MAX_METRICS) {
                    return;
                }
                const metric = {
                    name: name.substring(0, 200),
                    value: value,
                };
                if (attributes && typeof attributes === "object") {
                    const safeAttrs = {};
                    for (const [k, v] of Object.entries(attributes)) {
                        if (typeof v === "string" ||
                            typeof v === "number" ||
                            typeof v === "boolean") {
                            safeAttrs[k] = String(v);
                        }
                    }
                    metric.attributes = safeAttrs;
                }
                capturedMetrics.push(metric);
            },
        }, proxyCache);
        // Wrap any additional context (e.g. Playwright browser/page objects)
        if (options.context) {
            for (const key of Object.keys(options.context)) {
                const val = options.context[key];
                sandbox[key] =
                    typeof val === "string" ? val : createSandboxProxy(val, proxyCache);
            }
        }
        if (options.args) {
            // args is plain JSON data — no host functions to protect against
            sandbox["args"] = options.args;
        }
        vm.createContext(sandbox, {
            codeGeneration: {
                strings: false,
                wasm: false,
            },
        });
        const script = `(async()=>{
        ${VM_HARDENING_PRELUDE}
        ${code}
      })()`;
        try {
            let returnVal;
            let scriptError;
            try {
                /*
                 * vm timeout only covers synchronous CPU time, so wrap with
                 * Promise.race to also cover async operations (network, timers, etc.)
                 */
                const vmPromise = vm.runInContext(script, sandbox, {
                    timeout: timeout,
                });
                const overallTimeout = new Promise((_resolve, reject) => {
                    const handle = global.setTimeout(() => {
                        reject(new Error("Script execution timed out"));
                    }, timeout + 5000);
                    // Don't let this timer keep the process alive
                    handle.unref();
                });
                returnVal = await Promise.race([vmPromise, overallTimeout]);
            }
            catch (err) {
                /*
                 * Capture user-thrown errors (including timeouts) so the caller can
                 * still access side-channel data collected before the throw — e.g.
                 * screenshots assigned to a host-realm object passed via `context`.
                 * Rethrowing here would discard those partial results.
                 */
                scriptError =
                    err instanceof Error
                        ? err
                        : new Error(typeof err === "string" ? err : String(err));
            }
            return {
                returnValue: deepUnwrapProxies(returnVal),
                logMessages,
                capturedMetrics,
                scriptError,
            };
        }
        finally {
            // Clean up any lingering timers to prevent resource leaks
            for (const handle of pendingTimeouts) {
                clearTimeout(handle);
            }
            for (const handle of pendingIntervals) {
                clearInterval(handle);
            }
        }
    }
    static async runCodeInSandbox(data) {
        const { code, options } = data;
        const timeout = options.timeout || 5000;
        const logMessages = [];
        const capturedMetrics = [];
        const MAX_METRICS = 100;
        const isolate = new ivm.Isolate({ memoryLimit: 128 });
        try {
            const context = await isolate.createContext();
            const jail = context.global;
            // Set up global object
            await jail.set("global", jail.derefInto());
            // console.log - fire-and-forget callback
            await jail.set("_log", new ivm.Callback((...args) => {
                logMessages.push(args.join(" "));
            }));
            await context.eval(`
        const console = { log: (...a) => _log(...a.map(v => {
          try { return typeof v === 'object' ? JSON.stringify(v) : String(v); }
          catch(_) { return String(v); }
        }))};
      `);
            // oneuptime.captureMetric - fire-and-forget callback
            await jail.set("_captureMetric", new ivm.Callback((name, value, attributesJson) => {
                if (capturedMetrics.length >= MAX_METRICS) {
                    return;
                }
                const numValue = Number(value);
                if (isNaN(numValue)) {
                    return;
                }
                const metric = {
                    name: String(name).substring(0, 200),
                    value: numValue,
                };
                if (attributesJson) {
                    try {
                        metric.attributes = JSON.parse(attributesJson);
                    }
                    catch (_a) {
                        // ignore invalid JSON
                    }
                }
                capturedMetrics.push(metric);
            }));
            await context.eval(`
        const oneuptime = {
          captureMetric: (name, value, attributes) => {
            if (typeof name !== 'string' || name.length === 0) return;
            if (typeof value !== 'number' || isNaN(value)) return;
            const attrJson = attributes ? JSON.stringify(attributes) : undefined;
            _captureMetric(String(name), String(value), attrJson);
          }
        };
      `);
            // args - deep copy into isolate
            if (options.args) {
                await jail.set("_args", new ivm.ExternalCopy(options.args).copyInto());
                await context.eval("const args = _args;");
            }
            else {
                await context.eval("const args = {};");
            }
            /*
             * http / https - provide Agent constructors that serialize across the boundary.
             * The sandbox Agent is a plain object with a marker; the host-side axios bridge
             * reconstructs the real Node.js Agent before making the request.
             */
            await context.eval(`
        const https = {
          Agent: class Agent {
            constructor(options) {
              this.__agentType = '__https_agent__';
              this.options = options || {};
            }
          }
        };
        const http = {
          Agent: class Agent {
            constructor(options) {
              this.__agentType = '__http_agent__';
              this.options = options || {};
            }
          }
        };
      `);
            /*
             * axios (get, head, options, post, put, patch, delete, request)
             * bridged via applySyncPromise.
             *
             * For GET/HEAD/OPTIONS/DELETE: args = [method, url, configJson?]
             * For POST/PUT/PATCH:         args = [method, url, bodyJson?, configJson?]
             * For REQUEST:                args = ['request', '', configJson]
             */
            const axiosRef = new ivm.Reference(async (method, url, arg1, arg2) => {
                const methodsWithBody = ["post", "put", "patch"];
                const hasBody = methodsWithBody.includes(method);
                /*
                 * For POST/PUT/PATCH: arg1=body, arg2=config
                 * For GET/HEAD/OPTIONS/DELETE/REQUEST: arg1=config
                 */
                const body = hasBody && arg1 ? JSON.parse(arg1) : undefined;
                const configStr = hasBody ? arg2 : arg1;
                const config = configStr
                    ? JSON.parse(configStr)
                    : undefined;
                // Reconstruct real http/https Agents from serialized markers
                if (config) {
                    const httpsAgentConfig = config["httpsAgent"];
                    if (httpsAgentConfig &&
                        httpsAgentConfig["__agentType"] === "__https_agent__") {
                        config["httpsAgent"] = new https.Agent(httpsAgentConfig["options"]);
                    }
                    const httpAgentConfig = config["httpAgent"];
                    if (httpAgentConfig &&
                        httpAgentConfig["__agentType"] === "__http_agent__") {
                        config["httpAgent"] = new http.Agent(httpAgentConfig["options"]);
                    }
                }
                /**
                 * Helper: convert AxiosHeaders (or any header-like object) to a
                 * plain record so it can be safely JSON-serialised.
                 */
                const toPlainHeaders = (headers) => {
                    const plain = {};
                    if (headers) {
                        for (const hKey of Object.keys(headers)) {
                            plain[hKey] = headers[hKey];
                        }
                    }
                    return plain;
                };
                try {
                    let response;
                    switch (method) {
                        case "get":
                            response = await axios.get(url, config);
                            break;
                        case "head":
                            response = await axios.head(url, config);
                            break;
                        case "options":
                            response = await axios.options(url, config);
                            break;
                        case "post":
                            response = await axios.post(url, body, config);
                            break;
                        case "put":
                            response = await axios.put(url, body, config);
                            break;
                        case "patch":
                            response = await axios.patch(url, body, config);
                            break;
                        case "delete":
                            response = await axios.delete(url, config);
                            break;
                        case "request":
                            response = await axios.request(config);
                            break;
                        default:
                            throw new Error(`Unsupported HTTP method: ${method}`);
                    }
                    /*
                     * Convert AxiosHeaders to a plain object before serializing.
                     * JSON.stringify calls AxiosHeaders.toJSON(key) with a truthy key,
                     * which makes it join array headers (like set-cookie) with commas.
                     * This produces invalid Cookie headers when user code forwards them.
                     */
                    return JSON.stringify({
                        status: response.status,
                        headers: toPlainHeaders(response.headers),
                        data: response.data,
                    });
                }
                catch (err) {
                    /*
                     * If this is an axios error with a response (4xx, 5xx, etc.),
                     * return the error details as JSON so the sandbox-side axios
                     * wrapper can reconstruct error.response for user code.
                     */
                    const axiosErr = err;
                    if (axiosErr.isAxiosError && axiosErr.response) {
                        return JSON.stringify({
                            __isAxiosError: true,
                            message: axiosErr.message || "Request failed",
                            status: axiosErr.response.status,
                            statusText: axiosErr.response.statusText,
                            headers: toPlainHeaders(axiosErr.response.headers),
                            data: axiosErr.response.data,
                        });
                    }
                    throw err;
                }
            });
            await jail.set("_axiosRef", axiosRef);
            await context.eval(`
        function _assertNoFunctions(obj, path) {
          if (!obj || typeof obj !== 'object') return;
          if (Array.isArray(obj)) {
            for (let i = 0; i < obj.length; i++) {
              const fullPath = path + '[' + i + ']';
              if (typeof obj[i] === 'function') {
                throw new Error(
                  'Functions are not supported in axios config because of security. ' +
                  'Found a function at "' + fullPath + '". Please remove it or replace it with a plain value.'
                );
              }
              if (obj[i] && typeof obj[i] === 'object') {
                _assertNoFunctions(obj[i], fullPath);
              }
            }
            return;
          }
          for (const key of Object.keys(obj)) {
            const fullPath = path ? path + '.' + key : key;
            if (typeof obj[key] === 'function') {
              throw new Error(
                'Functions are not supported in axios config because of security. ' +
                'Found a function at "' + fullPath + '". Please remove it or replace it with a plain value.'
              );
            }
            if (obj[key] && typeof obj[key] === 'object') {
              _assertNoFunctions(obj[key], fullPath);
            }
          }
        }

        function _parseAxiosResult(r) {
          const parsed = JSON.parse(r);
          if (parsed && parsed.__isAxiosError) {
            const err = new Error(parsed.message);
            err.response = {
              status: parsed.status,
              statusText: parsed.statusText,
              headers: parsed.headers,
              data: parsed.data,
            };
            err.isAxiosError = true;
            err.status = parsed.status;
            throw err;
          }
          return parsed;
        }

        function _makeAxiosInstance(defaults) {
          function mergeConfig(overrides) {
            if (!defaults && !overrides) return undefined;
            if (!defaults) return overrides;
            if (!overrides) return Object.assign({}, defaults);
            const merged = Object.assign({}, defaults, overrides);
            if (defaults.headers && overrides.headers) {
              merged.headers = Object.assign({}, defaults.headers, overrides.headers);
            }
            return merged;
          }

          async function _request(config) {
            const merged = mergeConfig(config);
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['request', '', merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          }

          // Make instance callable: axios(config) or axios(url, config)
          const instance = async function(urlOrConfig, config) {
            if (typeof urlOrConfig === 'object') {
              return _request(urlOrConfig);
            }
            return _request(Object.assign({}, config || {}, { url: urlOrConfig }));
          };

          instance.request = _request;
          instance.get = async (url, config) => {
            const merged = mergeConfig(config);
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['get', url, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.head = async (url, config) => {
            const merged = mergeConfig(config);
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['head', url, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.options = async (url, config) => {
            const merged = mergeConfig(config);
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['options', url, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.post = async (url, data, config) => {
            const merged = mergeConfig(config);
            if (data) _assertNoFunctions(data, 'data');
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['post', url, data ? JSON.stringify(data) : undefined, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.put = async (url, data, config) => {
            const merged = mergeConfig(config);
            if (data) _assertNoFunctions(data, 'data');
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['put', url, data ? JSON.stringify(data) : undefined, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.patch = async (url, data, config) => {
            const merged = mergeConfig(config);
            if (data) _assertNoFunctions(data, 'data');
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['patch', url, data ? JSON.stringify(data) : undefined, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.delete = async (url, config) => {
            const merged = mergeConfig(config);
            if (merged) _assertNoFunctions(merged, 'config');
            const r = await _axiosRef.applySyncPromise(undefined, ['delete', url, merged ? JSON.stringify(merged) : undefined]);
            return _parseAxiosResult(r);
          };
          instance.create = (instanceDefaults) => {
            if (instanceDefaults) _assertNoFunctions(instanceDefaults, 'defaults');
            const combinedDefaults = mergeConfig(instanceDefaults);
            return _makeAxiosInstance(combinedDefaults);
          };

          return instance;
        }

        const axios = _makeAxiosInstance(null);
      `);
            // crypto (createHash, createHmac, randomBytes, randomUUID, randomInt) - bridged via applySync
            const cryptoRef = new ivm.Reference((op, ...args) => {
                switch (op) {
                    case "createHash": {
                        const [algorithm, inputData, encoding] = args;
                        return crypto
                            .createHash(algorithm)
                            .update(inputData)
                            .digest(encoding || "hex");
                    }
                    case "createHmac": {
                        const [algorithm, key, inputData, encoding] = args;
                        return crypto
                            .createHmac(algorithm, key)
                            .update(inputData)
                            .digest(encoding || "hex");
                    }
                    case "randomBytes": {
                        const [size] = args;
                        return crypto.randomBytes(parseInt(size)).toString("hex");
                    }
                    case "randomUUID": {
                        return crypto.randomUUID();
                    }
                    case "randomInt": {
                        const [min, max] = args;
                        return String(crypto.randomInt(parseInt(min), parseInt(max)));
                    }
                    default:
                        throw new Error(`Unsupported crypto operation: ${op}`);
                }
            });
            await jail.set("_cryptoRef", cryptoRef);
            await context.eval(`
        const crypto = {
          createHash: (algorithm) => ({
            _alg: algorithm, _data: '',
            update(d) { this._data = d; return this; },
            digest(enc) { return _cryptoRef.applySync(undefined, ['createHash', this._alg, this._data, enc || 'hex']); }
          }),
          createHmac: (algorithm, key) => ({
            _alg: algorithm, _key: key, _data: '',
            update(d) { this._data = d; return this; },
            digest(enc) { return _cryptoRef.applySync(undefined, ['createHmac', this._alg, this._key, this._data, enc || 'hex']); }
          }),
          randomBytes: (size) => ({
            toString(enc) { return _cryptoRef.applySync(undefined, ['randomBytes', String(size)]); }
          }),
          randomUUID: () => {
            return _cryptoRef.applySync(undefined, ['randomUUID']);
          },
          randomInt: (minOrMax, max) => {
            if (max === undefined) { max = minOrMax; minOrMax = 0; }
            return Number(_cryptoRef.applySync(undefined, ['randomInt', String(minOrMax), String(max)]));
          },
        };
      `);
            // setTimeout / sleep - bridged via applySyncPromise
            const sleepRef = new ivm.Reference((ms) => {
                return new Promise((resolve) => {
                    global.setTimeout(resolve, Math.min(ms, timeout));
                });
            });
            await jail.set("_sleepRef", sleepRef);
            await context.eval(`
        function setTimeout(fn, ms) {
          _sleepRef.applySyncPromise(undefined, [ms || 0]);
          if (typeof fn === 'function') fn();
        }
        async function sleep(ms) {
          await _sleepRef.applySyncPromise(undefined, [ms || 0]);
        }
      `);
            /*
             * Wrap user code in async IIFE. JSON.stringify the return value inside
             * the isolate so only a plain string crosses the boundary — this avoids
             * "A non-transferable value was passed" errors when user code returns
             * objects containing functions, class instances, or other non-cloneable types.
             */
            const wrappedCode = `(async () => {
        const __result = await (async () => {
          ${code}
        })();
        try { return JSON.stringify(__result); }
        catch(_) { return undefined; }
      })()`;
            // Run with overall timeout covering both CPU and I/O wait
            const resultPromise = context.eval(wrappedCode, {
                promise: true,
                timeout: timeout,
            });
            const overallTimeout = new Promise((_resolve, reject) => {
                global.setTimeout(() => {
                    reject(new Error("Script execution timed out"));
                }, timeout + 5000); // 5s grace period beyond isolate timeout
            });
            const result = await Promise.race([
                resultPromise,
                overallTimeout,
            ]);
            // Parse the JSON string returned from inside the isolate
            let returnValue;
            if (typeof result === "string") {
                try {
                    returnValue = JSON.parse(result);
                }
                catch (_a) {
                    returnValue = result;
                }
            }
            else {
                returnValue = result;
            }
            return {
                returnValue,
                logMessages,
                capturedMetrics,
            };
        }
        finally {
            if (!isolate.isDisposed) {
                isolate.dispose();
            }
        }
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], VMRunner, "runCodeInNodeVM", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], VMRunner, "runCodeInSandbox", null);
//# sourceMappingURL=VMRunner.js.map