"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fnCache = {};
function stringToFunction(str, expression, errors, logs) {
    if (expression === void 0) { expression = true; }
    if (!str || !str.trim()) {
        return function () { return undefined; };
    }
    var cacheKey = str + ':' + expression;
    if (fnCache[cacheKey]) {
        return fnCache[cacheKey];
    }
    // FIXME: gross hack
    var useReturn = (expression &&
        !(str.includes(';') || str.includes(' return ') || str.trim().startsWith('return '))) ||
        str.trim().startsWith('builder.run');
    var fn = function () {
        /* intentionally empty */
    };
    try {
        // tslint:disable-next-line:no-function-constructor-with-string-args
        // TODO: use strict and eval
        fn = new Function('state', 'event', 'block', 'builder', 'Device', 'update', 
        // TODO: block reference...
        // TODO: or just remove with (rootState) in general
        "\n          var rootState = state;\n          if (typeof Proxy !== 'undefined') {\n            rootState = new Proxy(rootState, {\n              set: function () {\n                return false;\n              }\n            });\n          }\n          with (rootState) {\n            " + (useReturn ? "return (" + str + ");" : str) + ";\n          }\n        ");
    }
    catch (error) {
        if (errors) {
            errors.push(error);
        }
        var message = error && error.message;
        if (message && typeof message === 'string') {
            if (logs && logs.indexOf(message) === -1) {
                logs.push(message);
            }
        }
        console.warn("Function compile error in " + str, error);
    }
    var final = (fnCache[cacheKey] = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        try {
            return fn.apply(void 0, args);
        }
        catch (error) {
            console.warn('Builder custom code error:', error.message, error.stack);
            if (errors) {
                errors.push(error);
            }
        }
    });
    return final;
}
exports.stringToFunction = stringToFunction;
//# sourceMappingURL=string-to-function.js.map