"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.exec = void 0;
const interceptor_1 = require("../interceptor");
function has(target, key) {
    return true;
}
function get(target, key) {
    if (key === Symbol.unscopables)
        return undefined;
    return target[key];
}
const exec = (source, options) => {
    var _a;
    const interceptedSource = (0, interceptor_1.runInterceptors)({
        source: source,
        interceptors: options === null || options === void 0 ? void 0 : options.interceptors,
    });
    const globalValues = (_a = options === null || options === void 0 ? void 0 : options.globalValues) !== null && _a !== void 0 ? _a : {};
    const proxiesCache = new WeakMap();
    const sourceWithSand = `with (sandbox) { ${interceptedSource} }`;
    const executableCode = new Function("sandbox", sourceWithSand);
    return function (sandbox) {
        const sandboxWithGlobals = Object.assign(Object.assign({}, sandbox), globalValues);
        if (!proxiesCache.has(sandboxWithGlobals)) {
            const sandboxProxy = new Proxy(sandboxWithGlobals, { has, get });
            proxiesCache.set(sandboxWithGlobals, sandboxProxy);
        }
        try {
            executableCode(proxiesCache.get(sandboxWithGlobals));
            if (options === null || options === void 0 ? void 0 : options.onSuccess) {
                return options.onSuccess();
            }
        }
        catch (e) {
            if (options === null || options === void 0 ? void 0 : options.onError) {
                return options.onError(e);
            }
            throw new Error(e);
        }
    };
};
exports.exec = exec;
