Comparing version 1.4.7 to 1.4.8
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var vm_1 = require("./vm"); | ||
exports.default = (function (code, ctx, options) { | ||
return (0, vm_1.runInContext)(code, ctx, options); | ||
}); | ||
exports.default = void 0; | ||
var _vm = require("./vm"); | ||
var _default = function _default(code, ctx, options) { | ||
return (0, _vm.runInContext)(code, ctx, options); | ||
}; | ||
exports.default = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = _default; | ||
var _vm = require("./vm"); | ||
function _default() { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var code = args.pop(); | ||
return (0, _vm.compileFunction)(code || "", args); | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var vm_1 = require("./vm"); | ||
function default_1() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var code = args.pop(); | ||
return (0, vm_1.compileFunction)(code || "", args); | ||
} | ||
exports.default = default_1; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
Object.defineProperty(exports, "Interpreter", { | ||
enumerable: true, | ||
get: function get() { | ||
return _main.Interpreter; | ||
} | ||
}); | ||
Object.defineProperty(exports, "evaluate", { | ||
enumerable: true, | ||
get: function get() { | ||
return _evaluate.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "Function", { | ||
enumerable: true, | ||
get: function get() { | ||
return _Function.default; | ||
} | ||
}); | ||
exports.vm = exports.default = void 0; | ||
var _main = require("./interpreter/main"); | ||
var vm = _interopRequireWildcard(require("./vm")); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Function = exports.evaluate = exports.vm = exports.Interpreter = void 0; | ||
var main_1 = require("./interpreter/main"); | ||
Object.defineProperty(exports, "Interpreter", { enumerable: true, get: function () { return main_1.Interpreter; } }); | ||
var vm = require("./vm"); | ||
exports.vm = vm; | ||
var _evaluate = _interopRequireDefault(require("./evaluate")); | ||
var _Function = _interopRequireDefault(require("./Function")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var _default = _evaluate.default; | ||
exports.default = _default; | ||
var evaluate_1 = require("./evaluate"); | ||
exports.evaluate = evaluate_1.default; | ||
var Function_1 = require("./Function"); | ||
exports.Function = Function_1.default; | ||
exports.default = evaluate_1.default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Messages = exports.InterruptThrowReferenceError = exports.InterruptThrowSyntaxError = exports.InterruptThrowError = exports.ThrowTypeError = exports.ThrowReferenceError = exports.ThrowSyntaxError = exports.ThrowError = void 0; | ||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } | ||
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } | ||
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | ||
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } | ||
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
var ThrowError = | ||
/*#__PURE__*/ | ||
function (_Error) { | ||
_inheritsLoose(ThrowError, _Error); | ||
function ThrowError() { | ||
return _Error.apply(this, arguments) || this; | ||
} | ||
return ThrowError; | ||
}(_wrapNativeSuper(Error)); | ||
var ThrowError = /** @class */ (function (_super) { | ||
__extends(ThrowError, _super); | ||
function ThrowError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ThrowError; | ||
}(Error)); | ||
exports.ThrowError = ThrowError; | ||
var ThrowSyntaxError = | ||
/*#__PURE__*/ | ||
function (_SyntaxError) { | ||
_inheritsLoose(ThrowSyntaxError, _SyntaxError); | ||
function ThrowSyntaxError() { | ||
return _SyntaxError.apply(this, arguments) || this; | ||
} | ||
return ThrowSyntaxError; | ||
}(_wrapNativeSuper(SyntaxError)); | ||
var ThrowSyntaxError = /** @class */ (function (_super) { | ||
__extends(ThrowSyntaxError, _super); | ||
function ThrowSyntaxError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ThrowSyntaxError; | ||
}(SyntaxError)); | ||
exports.ThrowSyntaxError = ThrowSyntaxError; | ||
var ThrowReferenceError = | ||
/*#__PURE__*/ | ||
function (_ReferenceError) { | ||
_inheritsLoose(ThrowReferenceError, _ReferenceError); | ||
function ThrowReferenceError() { | ||
return _ReferenceError.apply(this, arguments) || this; | ||
} | ||
return ThrowReferenceError; | ||
}(_wrapNativeSuper(ReferenceError)); | ||
var ThrowReferenceError = /** @class */ (function (_super) { | ||
__extends(ThrowReferenceError, _super); | ||
function ThrowReferenceError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ThrowReferenceError; | ||
}(ReferenceError)); | ||
exports.ThrowReferenceError = ThrowReferenceError; | ||
var ThrowTypeError = | ||
/*#__PURE__*/ | ||
function (_TypeError) { | ||
_inheritsLoose(ThrowTypeError, _TypeError); | ||
function ThrowTypeError() { | ||
return _TypeError.apply(this, arguments) || this; | ||
} | ||
return ThrowTypeError; | ||
}(_wrapNativeSuper(TypeError)); | ||
var ThrowTypeError = /** @class */ (function (_super) { | ||
__extends(ThrowTypeError, _super); | ||
function ThrowTypeError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ThrowTypeError; | ||
}(TypeError)); | ||
exports.ThrowTypeError = ThrowTypeError; | ||
var InterruptThrowError = | ||
/*#__PURE__*/ | ||
function (_ThrowError) { | ||
_inheritsLoose(InterruptThrowError, _ThrowError); | ||
function InterruptThrowError() { | ||
return _ThrowError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowError; | ||
}(ThrowError); | ||
var InterruptThrowError = /** @class */ (function (_super) { | ||
__extends(InterruptThrowError, _super); | ||
function InterruptThrowError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowError; | ||
}(ThrowError)); | ||
exports.InterruptThrowError = InterruptThrowError; | ||
var InterruptThrowSyntaxError = | ||
/*#__PURE__*/ | ||
function (_ThrowSyntaxError) { | ||
_inheritsLoose(InterruptThrowSyntaxError, _ThrowSyntaxError); | ||
function InterruptThrowSyntaxError() { | ||
return _ThrowSyntaxError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowSyntaxError; | ||
}(ThrowSyntaxError); | ||
var InterruptThrowSyntaxError = /** @class */ (function (_super) { | ||
__extends(InterruptThrowSyntaxError, _super); | ||
function InterruptThrowSyntaxError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowSyntaxError; | ||
}(ThrowSyntaxError)); | ||
exports.InterruptThrowSyntaxError = InterruptThrowSyntaxError; | ||
var InterruptThrowReferenceError = | ||
/*#__PURE__*/ | ||
function (_ThrowReferenceError) { | ||
_inheritsLoose(InterruptThrowReferenceError, _ThrowReferenceError); | ||
function InterruptThrowReferenceError() { | ||
return _ThrowReferenceError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowReferenceError; | ||
}(ThrowReferenceError); | ||
var InterruptThrowReferenceError = /** @class */ (function (_super) { | ||
__extends(InterruptThrowReferenceError, _super); | ||
function InterruptThrowReferenceError() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowReferenceError; | ||
}(ThrowReferenceError)); | ||
exports.InterruptThrowReferenceError = InterruptThrowReferenceError; | ||
var Messages = { | ||
UnknownError: [3001, "%0", InterruptThrowError], | ||
ExecutionTimeOutError: [3002, "Script execution timed out after %0ms", InterruptThrowError], | ||
NodeTypeSyntaxError: [1001, "Unknown node type: %0", InterruptThrowReferenceError], | ||
BinaryOperatorSyntaxError: [1002, "Unknown binary operator: %0", InterruptThrowReferenceError], | ||
LogicalOperatorSyntaxError: [1003, "Unknown logical operator: %0", InterruptThrowReferenceError], | ||
UnaryOperatorSyntaxError: [1004, "Unknown unary operator: %0", InterruptThrowReferenceError], | ||
UpdateOperatorSyntaxError: [1005, "Unknown update operator: %0", InterruptThrowReferenceError], | ||
ObjectStructureSyntaxError: [1006, "Unknown object structure: %0", InterruptThrowReferenceError], | ||
AssignmentExpressionSyntaxError: [1007, "Unknown assignment expression: %0", InterruptThrowReferenceError], | ||
VariableTypeSyntaxError: [1008, "Unknown variable type: %0", InterruptThrowReferenceError], | ||
ParamTypeSyntaxError: [1009, "Unknown param type: %0", InterruptThrowReferenceError], | ||
AssignmentTypeSyntaxError: [1010, "Unknown assignment type: %0", InterruptThrowReferenceError], | ||
FunctionUndefinedReferenceError: [2001, "%0 is not a function", ThrowReferenceError], | ||
VariableUndefinedReferenceError: [2002, "%0 is not defined", ThrowReferenceError], | ||
IsNotConstructor: [2003, "%0 is not a constructor", ThrowTypeError] | ||
exports.Messages = { | ||
UnknownError: [3001, "%0", InterruptThrowError], | ||
ExecutionTimeOutError: [3002, "Script execution timed out after %0ms", InterruptThrowError], | ||
NodeTypeSyntaxError: [1001, "Unknown node type: %0", InterruptThrowReferenceError], | ||
BinaryOperatorSyntaxError: [1002, "Unknown binary operator: %0", InterruptThrowReferenceError], | ||
LogicalOperatorSyntaxError: [ | ||
1003, | ||
"Unknown logical operator: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
UnaryOperatorSyntaxError: [1004, "Unknown unary operator: %0", InterruptThrowReferenceError], | ||
UpdateOperatorSyntaxError: [1005, "Unknown update operator: %0", InterruptThrowReferenceError], | ||
ObjectStructureSyntaxError: [ | ||
1006, | ||
"Unknown object structure: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
AssignmentExpressionSyntaxError: [ | ||
1007, | ||
"Unknown assignment expression: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
VariableTypeSyntaxError: [1008, "Unknown variable type: %0", InterruptThrowReferenceError], | ||
ParamTypeSyntaxError: [1009, "Unknown param type: %0", InterruptThrowReferenceError], | ||
AssignmentTypeSyntaxError: [1010, "Unknown assignment type: %0", InterruptThrowReferenceError], | ||
FunctionUndefinedReferenceError: [2001, "%0 is not a function", ThrowReferenceError], | ||
VariableUndefinedReferenceError: [2002, "%0 is not defined", ThrowReferenceError], | ||
IsNotConstructor: [2003, "%0 is not a constructor", ThrowTypeError], | ||
}; | ||
exports.Messages = Messages; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ESTree = void 0; | ||
var ESTree = _interopRequireWildcard(require("estree")); | ||
var ESTree = require("estree"); | ||
exports.ESTree = ESTree; | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } |
@@ -1,1 +0,2 @@ | ||
"use strict"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.createContext = createContext; | ||
exports.compileFunction = compileFunction; | ||
exports.runInContext = _runInContext; | ||
exports.Script = exports.runInNewContext = void 0; | ||
var _main = require("./interpreter/main"); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Script = exports.runInNewContext = exports.runInContext = exports.compileFunction = exports.createContext = void 0; | ||
var main_1 = require("./interpreter/main"); | ||
// TODO: | ||
// add tests | ||
function createContext(ctx) { | ||
if (ctx === void 0) { | ||
ctx = Object.create(null); | ||
} | ||
return ctx; | ||
if (ctx === void 0) { ctx = Object.create(null); } | ||
return ctx; | ||
} | ||
exports.createContext = createContext; | ||
function compileFunction(code, params, options) { | ||
if (params === void 0) { | ||
params = []; | ||
} | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var ctx = options.parsingContext; | ||
var timeout = options.timeout === undefined ? 0 : options.timeout; | ||
var wrapCode = "\n (function anonymous(" + params.join(",") + "){\n " + code + "\n });\n "; | ||
var interpreter = new _main.Interpreter(ctx, { | ||
ecmaVersion: options.ecmaVersion, | ||
timeout: timeout, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction | ||
}); | ||
return interpreter.evaluate(wrapCode); | ||
if (params === void 0) { params = []; } | ||
if (options === void 0) { options = {}; } | ||
var ctx = options.parsingContext; | ||
var timeout = options.timeout === undefined ? 0 : options.timeout; | ||
var wrapCode = "\n (function anonymous(".concat(params.join(","), "){\n ").concat(code, "\n });\n "); | ||
var interpreter = new main_1.Interpreter(ctx, { | ||
ecmaVersion: options.ecmaVersion, | ||
timeout: timeout, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction, | ||
}); | ||
return interpreter.evaluate(wrapCode); | ||
} | ||
function _runInContext(code, ctx, options) { | ||
var interpreter = new _main.Interpreter(ctx, options); | ||
return interpreter.evaluate(code); | ||
exports.compileFunction = compileFunction; | ||
function runInContext(code, ctx, options) { | ||
var interpreter = new main_1.Interpreter(ctx, options); | ||
return interpreter.evaluate(code); | ||
} | ||
var runInNewContext = _runInContext; | ||
exports.runInNewContext = runInNewContext; | ||
var Script = | ||
/*#__PURE__*/ | ||
function () { | ||
function Script(code) { | ||
this._code = code; | ||
} | ||
var _proto = Script.prototype; | ||
_proto.runInContext = function runInContext(ctx) { | ||
return _runInContext(this._code, ctx); | ||
}; | ||
_proto.runInNewContext = function runInNewContext(ctx) { | ||
return _runInContext(this._code, ctx); | ||
}; | ||
return Script; | ||
}(); | ||
exports.Script = Script; | ||
exports.runInContext = runInContext; | ||
exports.runInNewContext = runInContext; | ||
var Script = /** @class */ (function () { | ||
function Script(code) { | ||
this._code = code; | ||
} | ||
Script.prototype.runInContext = function (ctx) { | ||
return runInContext(this._code, ctx); | ||
}; | ||
Script.prototype.runInNewContext = function (ctx) { | ||
return runInContext(this._code, ctx); | ||
}; | ||
return Script; | ||
}()); | ||
exports.Script = Script; |
import { runInContext } from "./vm"; | ||
export default (function (code, ctx, options) { | ||
return runInContext(code, ctx, options); | ||
}); | ||
export default (code, ctx, options) => { | ||
return runInContext(code, ctx, options); | ||
}; |
import { compileFunction } from "./vm"; | ||
export default function () { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var code = args.pop(); | ||
return compileFunction(code || "", args); | ||
} | ||
export default function (...args) { | ||
const code = args.pop(); | ||
return compileFunction(code || "", args); | ||
} |
@@ -6,2 +6,2 @@ import { Interpreter } from "./interpreter/main"; | ||
export { Interpreter, vm, evaluate, Function }; | ||
export default evaluate; | ||
export default evaluate; |
@@ -1,143 +0,115 @@ | ||
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | ||
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
import { parse } from "acorn"; | ||
import { Messages, InterruptThrowError, InterruptThrowReferenceError, InterruptThrowSyntaxError } from "./messages"; | ||
var version = "1.4.7"; | ||
import { Messages, InterruptThrowError, InterruptThrowReferenceError, InterruptThrowSyntaxError, } from "./messages"; | ||
const version = "1.4.8"; | ||
function defineFunctionName(func, name) { | ||
Object.defineProperty(func, "name", { | ||
value: name, | ||
writable: false, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(func, "name", { | ||
value: name, | ||
writable: false, | ||
enumerable: false, | ||
configurable: true, | ||
}); | ||
} | ||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
var Break = Symbol("Break"); | ||
var Continue = Symbol("Continue"); | ||
var DefaultCase = Symbol("DefaultCase"); | ||
var EmptyStatementReturn = Symbol("EmptyStatementReturn"); | ||
var WithScopeName = Symbol("WithScopeName"); | ||
var SuperScopeName = Symbol("SuperScopeName"); | ||
var RootScopeName = Symbol("RootScopeName"); | ||
var GlobalScopeName = Symbol("GlobalScopeName"); | ||
const hasOwnProperty = Object.prototype.hasOwnProperty; | ||
const Break = Symbol("Break"); | ||
const Continue = Symbol("Continue"); | ||
const DefaultCase = Symbol("DefaultCase"); | ||
const EmptyStatementReturn = Symbol("EmptyStatementReturn"); | ||
const WithScopeName = Symbol("WithScopeName"); | ||
const SuperScopeName = Symbol("SuperScopeName"); | ||
const RootScopeName = Symbol("RootScopeName"); | ||
const GlobalScopeName = Symbol("GlobalScopeName"); | ||
function isFunction(func) { | ||
return typeof func === "function"; | ||
return typeof func === "function"; | ||
} | ||
var InternalInterpreterReflection = | ||
/*#__PURE__*/ | ||
function () { | ||
function InternalInterpreterReflection(interpreter) { | ||
this.interpreter = interpreter; | ||
} | ||
var _proto = InternalInterpreterReflection.prototype; | ||
_proto.generator = function generator() { | ||
var interpreter = this.interpreter; | ||
function getCurrentScope() { | ||
return this.getCurrentScope(); | ||
class InternalInterpreterReflection { | ||
constructor(interpreter) { | ||
this.interpreter = interpreter; | ||
} | ||
function getGlobalScope() { | ||
return this.getGlobalScope(); | ||
generator() { | ||
const interpreter = this.interpreter; | ||
function getCurrentScope() { | ||
return this.getCurrentScope(); | ||
} | ||
function getGlobalScope() { | ||
return this.getGlobalScope(); | ||
} | ||
function getCurrentContext() { | ||
return this.getCurrentContext(); | ||
} | ||
return { | ||
getOptions: interpreter.getOptions.bind(interpreter), | ||
getCurrentScope: getCurrentScope.bind(interpreter), | ||
getGlobalScope: getGlobalScope.bind(interpreter), | ||
getCurrentContext: getCurrentContext.bind(interpreter), | ||
getExecStartTime: interpreter.getExecStartTime.bind(interpreter), | ||
}; | ||
} | ||
function getCurrentContext() { | ||
return this.getCurrentContext(); | ||
} | ||
function internalEval(reflection, code, useGlobalScope = true) { | ||
if (!(reflection instanceof InternalInterpreterReflection)) { | ||
throw new Error("Illegal call"); | ||
} | ||
return { | ||
getOptions: interpreter.getOptions.bind(interpreter), | ||
getCurrentScope: getCurrentScope.bind(interpreter), | ||
getGlobalScope: getGlobalScope.bind(interpreter), | ||
getCurrentContext: getCurrentContext.bind(interpreter), | ||
getExecStartTime: interpreter.getExecStartTime.bind(interpreter) | ||
if (typeof code !== "string") | ||
return code; | ||
if (!code) | ||
return void 0; | ||
const instance = reflection.generator(); | ||
const opts = instance.getOptions(); | ||
const options = { | ||
timeout: opts.timeout, | ||
_initEnv: function () { | ||
// set caller context | ||
if (!useGlobalScope) { | ||
this.setCurrentContext(instance.getCurrentContext()); | ||
} | ||
// share timeout | ||
this.execStartTime = instance.getExecStartTime(); | ||
this.execEndTime = this.execStartTime; | ||
}, | ||
}; | ||
}; | ||
return InternalInterpreterReflection; | ||
}(); | ||
function internalEval(reflection, code, useGlobalScope) { | ||
if (useGlobalScope === void 0) { | ||
useGlobalScope = true; | ||
} | ||
if (!(reflection instanceof InternalInterpreterReflection)) { | ||
throw new Error("Illegal call"); | ||
} | ||
if (typeof code !== "string") return code; | ||
if (!code) return void 0; | ||
var instance = reflection.generator(); | ||
var opts = instance.getOptions(); | ||
var options = { | ||
timeout: opts.timeout, | ||
_initEnv: function _initEnv() { | ||
// set caller context | ||
if (!useGlobalScope) { | ||
this.setCurrentContext(instance.getCurrentContext()); | ||
} // share timeout | ||
this.execStartTime = instance.getExecStartTime(); | ||
this.execEndTime = this.execStartTime; | ||
} | ||
}; | ||
var currentScope = useGlobalScope ? instance.getGlobalScope() : instance.getCurrentScope(); | ||
var interpreter = new Interpreter(currentScope, options); | ||
return interpreter.evaluate(code); | ||
const currentScope = useGlobalScope ? instance.getGlobalScope() : instance.getCurrentScope(); | ||
const interpreter = new Interpreter(currentScope, options); | ||
return interpreter.evaluate(code); | ||
} | ||
Object.defineProperty(internalEval, "__IS_EVAL_FUNC", { | ||
value: true, | ||
writable: false, | ||
enumerable: false, | ||
configurable: false | ||
value: true, | ||
writable: false, | ||
enumerable: false, | ||
configurable: false, | ||
}); | ||
function internalFunction(reflection) { | ||
if (!(reflection instanceof InternalInterpreterReflection)) { | ||
throw new Error("Illegal call"); | ||
} | ||
var instance = reflection.generator(); | ||
for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
params[_key - 1] = arguments[_key]; | ||
} | ||
var code = params.pop(); | ||
var interpreter = new Interpreter(instance.getGlobalScope(), instance.getOptions()); | ||
var wrapCode = "\n\t\t (function anonymous(" + params.join(",") + "){\n\t\t " + code + "\n\t\t });\n\t\t "; | ||
return interpreter.evaluate(wrapCode); | ||
function internalFunction(reflection, ...params) { | ||
if (!(reflection instanceof InternalInterpreterReflection)) { | ||
throw new Error("Illegal call"); | ||
} | ||
const instance = reflection.generator(); | ||
const code = params.pop(); | ||
const interpreter = new Interpreter(instance.getGlobalScope(), instance.getOptions()); | ||
const wrapCode = ` | ||
(function anonymous(${params.join(",")}){ | ||
${code} | ||
}); | ||
`; | ||
return interpreter.evaluate(wrapCode); | ||
} | ||
Object.defineProperty(internalFunction, "__IS_FUNCTION_FUNC", { | ||
value: true, | ||
writable: false, | ||
enumerable: false, | ||
configurable: false | ||
value: true, | ||
writable: false, | ||
enumerable: false, | ||
configurable: false, | ||
}); | ||
var Return = function Return(value) { | ||
this.value = value; | ||
}; | ||
var BreakLabel = function BreakLabel(value) { | ||
this.value = value; | ||
}; | ||
var ContinueLabel = function ContinueLabel(value) { | ||
this.value = value; | ||
}; | ||
class Return { | ||
constructor(value) { | ||
this.value = value; | ||
} | ||
} | ||
class BreakLabel { | ||
constructor(value) { | ||
this.value = value; | ||
} | ||
} | ||
class ContinueLabel { | ||
constructor(value) { | ||
this.value = value; | ||
} | ||
} | ||
/** | ||
@@ -155,1916 +127,1492 @@ * scope chain | ||
*/ | ||
var Scope = function Scope(data, parent, name) { | ||
if (parent === void 0) { | ||
parent = null; | ||
} | ||
this.name = name; | ||
this.parent = parent; | ||
this.data = data; | ||
this.labelStack = []; | ||
}; | ||
function noop() {} | ||
function createScope(parent, name) { | ||
if (parent === void 0) { | ||
parent = null; | ||
} | ||
return new Scope(Object.create(null), parent, name); | ||
class Scope { | ||
constructor(data, parent = null, name) { | ||
this.name = name; | ||
this.parent = parent; | ||
this.data = data; | ||
this.labelStack = []; | ||
} | ||
} | ||
function noop() { } | ||
function createScope(parent = null, name) { | ||
return new Scope(Object.create(null), parent, name); | ||
} | ||
function createRootContext(data) { | ||
return Object.create(data); | ||
return Object.create(data); | ||
} | ||
var BuildInObjects = { | ||
NaN: NaN, | ||
Infinity: Infinity, | ||
undefined: undefined, | ||
// null, | ||
Object: Object, | ||
Array: Array, | ||
String: String, | ||
Boolean: Boolean, | ||
Number: Number, | ||
Date: Date, | ||
RegExp: RegExp, | ||
Error: Error, | ||
URIError: URIError, | ||
TypeError: TypeError, | ||
RangeError: RangeError, | ||
SyntaxError: SyntaxError, | ||
ReferenceError: ReferenceError, | ||
Math: Math, | ||
parseInt: parseInt, | ||
parseFloat: parseFloat, | ||
isNaN: isNaN, | ||
isFinite: isFinite, | ||
decodeURI: decodeURI, | ||
decodeURIComponent: decodeURIComponent, | ||
encodeURI: encodeURI, | ||
encodeURIComponent: encodeURIComponent, | ||
escape: escape, | ||
unescape: unescape, | ||
eval: internalEval, | ||
Function: internalFunction | ||
}; // ES5 Object | ||
const BuildInObjects = { | ||
NaN, | ||
Infinity, | ||
undefined, | ||
// null, | ||
Object, | ||
Array, | ||
String, | ||
Boolean, | ||
Number, | ||
Date, | ||
RegExp, | ||
Error, | ||
URIError, | ||
TypeError, | ||
RangeError, | ||
SyntaxError, | ||
ReferenceError, | ||
Math, | ||
parseInt, | ||
parseFloat, | ||
isNaN, | ||
isFinite, | ||
decodeURI, | ||
decodeURIComponent, | ||
encodeURI, | ||
encodeURIComponent, | ||
escape, | ||
unescape, | ||
eval: internalEval, | ||
Function: internalFunction, | ||
}; | ||
// ES5 Object | ||
if (typeof JSON !== "undefined") { | ||
BuildInObjects.JSON = JSON; | ||
} //ES6 Object | ||
BuildInObjects.JSON = JSON; | ||
} | ||
//ES6 Object | ||
if (typeof Promise !== "undefined") { | ||
BuildInObjects.Promise = Promise; | ||
BuildInObjects.Promise = Promise; | ||
} | ||
if (typeof Set !== "undefined") { | ||
BuildInObjects.Set = Set; | ||
BuildInObjects.Set = Set; | ||
} | ||
if (typeof Map !== "undefined") { | ||
BuildInObjects.Map = Map; | ||
BuildInObjects.Map = Map; | ||
} | ||
if (typeof Symbol !== "undefined") { | ||
BuildInObjects.Symbol = Symbol; | ||
BuildInObjects.Symbol = Symbol; | ||
} | ||
if (typeof Proxy !== "undefined") { | ||
BuildInObjects.Proxy = Proxy; | ||
BuildInObjects.Proxy = Proxy; | ||
} | ||
if (typeof WeakMap !== "undefined") { | ||
BuildInObjects.WeakMap = WeakMap; | ||
BuildInObjects.WeakMap = WeakMap; | ||
} | ||
if (typeof WeakSet !== "undefined") { | ||
BuildInObjects.WeakSet = WeakSet; | ||
BuildInObjects.WeakSet = WeakSet; | ||
} | ||
if (typeof Reflect !== "undefined") { | ||
BuildInObjects.Reflect = Reflect; | ||
BuildInObjects.Reflect = Reflect; | ||
} | ||
export var Interpreter = | ||
/*#__PURE__*/ | ||
function () { | ||
function Interpreter(context, options) { | ||
if (context === void 0) { | ||
context = Interpreter.global; | ||
export class Interpreter { | ||
constructor(context = Interpreter.global, options = {}) { | ||
this.sourceList = []; | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
this.isVarDeclMode = false; | ||
this.lastExecNode = null; | ||
this.isRunning = false; | ||
this.options = { | ||
ecmaVersion: options.ecmaVersion || Interpreter.ecmaVersion, | ||
timeout: options.timeout || 0, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction === undefined | ||
? Interpreter.globalContextInFunction | ||
: options.globalContextInFunction, | ||
_initEnv: options._initEnv, | ||
}; | ||
this.context = context || Object.create(null); | ||
this.callStack = []; | ||
this.initEnvironment(this.context); | ||
} | ||
if (options === void 0) { | ||
options = {}; | ||
initEnvironment(ctx) { | ||
let scope; | ||
//init global scope | ||
if (ctx instanceof Scope) { | ||
scope = ctx; | ||
} | ||
else { | ||
let rootScope = null; | ||
const superScope = this.createSuperScope(ctx); | ||
if (this.options.rootContext) { | ||
rootScope = new Scope(createRootContext(this.options.rootContext), superScope, RootScopeName); | ||
} | ||
scope = new Scope(ctx, rootScope || superScope, GlobalScopeName); | ||
} | ||
this.globalScope = scope; | ||
this.currentScope = this.globalScope; | ||
//init global context to this | ||
this.globalContext = scope.data; | ||
this.currentContext = scope.data; | ||
// collect var/function declare | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
this.execStartTime = Date.now(); | ||
this.execEndTime = this.execStartTime; | ||
const _initEnv = this.options._initEnv; | ||
if (_initEnv) { | ||
_initEnv.call(this); | ||
} | ||
} | ||
this.sourceList = []; | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
this.isVarDeclMode = false; | ||
this.lastExecNode = null; | ||
this.isRunning = false; | ||
this.options = { | ||
ecmaVersion: options.ecmaVersion || Interpreter.ecmaVersion, | ||
timeout: options.timeout || 0, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction === undefined ? Interpreter.globalContextInFunction : options.globalContextInFunction, | ||
_initEnv: options._initEnv | ||
}; | ||
this.context = context || Object.create(null); | ||
this.callStack = []; | ||
this.initEnvironment(this.context); | ||
} | ||
var _proto2 = Interpreter.prototype; | ||
_proto2.initEnvironment = function initEnvironment(ctx) { | ||
var scope; //init global scope | ||
if (ctx instanceof Scope) { | ||
scope = ctx; | ||
} else { | ||
var rootScope = null; | ||
var superScope = this.createSuperScope(ctx); | ||
if (this.options.rootContext) { | ||
rootScope = new Scope(createRootContext(this.options.rootContext), superScope, RootScopeName); | ||
} | ||
scope = new Scope(ctx, rootScope || superScope, GlobalScopeName); | ||
getExecStartTime() { | ||
return this.execStartTime; | ||
} | ||
this.globalScope = scope; | ||
this.currentScope = this.globalScope; //init global context to this | ||
this.globalContext = scope.data; | ||
this.currentContext = scope.data; // collect var/function declare | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
this.execStartTime = Date.now(); | ||
this.execEndTime = this.execStartTime; | ||
var _initEnv = this.options._initEnv; | ||
if (_initEnv) { | ||
_initEnv.call(this); | ||
getExecutionTime() { | ||
return this.execEndTime - this.execStartTime; | ||
} | ||
}; | ||
_proto2.getExecStartTime = function getExecStartTime() { | ||
return this.execStartTime; | ||
}; | ||
_proto2.getExecutionTime = function getExecutionTime() { | ||
return this.execEndTime - this.execStartTime; | ||
}; | ||
_proto2.setExecTimeout = function setExecTimeout(timeout) { | ||
if (timeout === void 0) { | ||
timeout = 0; | ||
setExecTimeout(timeout = 0) { | ||
this.options.timeout = timeout; | ||
} | ||
this.options.timeout = timeout; | ||
}; | ||
_proto2.getOptions = function getOptions() { | ||
return this.options; | ||
}; | ||
_proto2.getGlobalScope = function getGlobalScope() { | ||
return this.globalScope; | ||
}; | ||
_proto2.getCurrentScope = function getCurrentScope() { | ||
return this.currentScope; | ||
}; | ||
_proto2.getCurrentContext = function getCurrentContext() { | ||
return this.currentContext; | ||
}; | ||
_proto2.isInterruptThrow = function isInterruptThrow(err) { | ||
return err instanceof InterruptThrowError || err instanceof InterruptThrowReferenceError || err instanceof InterruptThrowSyntaxError; | ||
}; | ||
_proto2.createSuperScope = function createSuperScope(ctx) { | ||
var data = Object.assign({}, BuildInObjects); | ||
var buildInObjectKeys = Object.keys(data); | ||
buildInObjectKeys.forEach(function (key) { | ||
if (key in ctx) { | ||
delete data[key]; | ||
} | ||
}); | ||
return new Scope(data, null, SuperScopeName); | ||
}; | ||
_proto2.setCurrentContext = function setCurrentContext(ctx) { | ||
this.currentContext = ctx; | ||
}; | ||
_proto2.setCurrentScope = function setCurrentScope(scope) { | ||
this.currentScope = scope; | ||
}; | ||
_proto2.evaluate = function evaluate(code) { | ||
if (code === void 0) { | ||
code = ""; | ||
getOptions() { | ||
return this.options; | ||
} | ||
var node; | ||
if (!code) return; | ||
node = parse(code, { | ||
ranges: true, | ||
locations: true, | ||
ecmaVersion: this.options.ecmaVersion || Interpreter.ecmaVersion | ||
}); | ||
return this.evaluateNode(node, code); | ||
}; | ||
_proto2.appendCode = function appendCode(code) { | ||
return this.evaluate(code); | ||
}; | ||
_proto2.evaluateNode = function evaluateNode(node, source) { | ||
var _this = this; | ||
if (source === void 0) { | ||
source = ""; | ||
getGlobalScope() { | ||
return this.globalScope; | ||
} | ||
this.value = undefined; | ||
this.source = source; | ||
this.sourceList.push(source); | ||
this.isRunning = true; //reset timeout | ||
this.execStartTime = Date.now(); | ||
this.execEndTime = this.execStartTime; // reset | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
var currentScope = this.getCurrentScope(); | ||
var currentContext = this.getCurrentContext(); | ||
var labelStack = currentScope.labelStack.concat([]); | ||
var callStack = this.callStack.concat([]); | ||
var reset = function reset() { | ||
_this.setCurrentScope(currentScope); //reset scope | ||
_this.setCurrentContext(currentContext); //reset context | ||
currentScope.labelStack = labelStack; //reset label stack | ||
_this.callStack = callStack; //reset call stack | ||
}; // start run | ||
try { | ||
var bodyClosure = this.createClosure(node); // add declares to data | ||
this.addDeclarationsToScope(this.collectDeclVars, this.collectDeclFuncs, this.getCurrentScope()); | ||
bodyClosure(); | ||
} catch (e) { | ||
throw e; | ||
} finally { | ||
reset(); | ||
this.execEndTime = Date.now(); | ||
getCurrentScope() { | ||
return this.currentScope; | ||
} | ||
this.isRunning = false; | ||
return this.getValue(); | ||
}; | ||
_proto2.createErrorMessage = function createErrorMessage(msg, value, node) { | ||
var message = msg[1].replace("%0", String(value)); | ||
if (node !== null) { | ||
message += this.getNodePosition(node || this.lastExecNode); | ||
getCurrentContext() { | ||
return this.currentContext; | ||
} | ||
return message; | ||
}; | ||
_proto2.createError = function createError(message, error) { | ||
return new error(message); | ||
}; | ||
_proto2.createThrowError = function createThrowError(message, error) { | ||
return this.createError(message, error); | ||
}; | ||
_proto2.createInternalThrowError = function createInternalThrowError(msg, value, node) { | ||
return this.createError(this.createErrorMessage(msg, value, node), msg[2]); | ||
}; | ||
_proto2.checkTimeout = function checkTimeout() { | ||
if (!this.isRunning) return false; | ||
var timeout = this.options.timeout || 0; | ||
var now = Date.now(); | ||
if (now - this.execStartTime > timeout) { | ||
return true; | ||
isInterruptThrow(err) { | ||
return (err instanceof InterruptThrowError || | ||
err instanceof InterruptThrowReferenceError || | ||
err instanceof InterruptThrowSyntaxError); | ||
} | ||
return false; | ||
}; | ||
_proto2.getNodePosition = function getNodePosition(node) { | ||
if (node) { | ||
var errorCode = ""; //this.source.slice(node.start, node.end); | ||
return node.loc ? " [" + node.loc.start.line + ":" + node.loc.start.column + "]" + errorCode : ""; | ||
createSuperScope(ctx) { | ||
let data = Object.assign({}, BuildInObjects); | ||
const buildInObjectKeys = Object.keys(data); | ||
buildInObjectKeys.forEach(key => { | ||
if (key in ctx) { | ||
delete data[key]; | ||
} | ||
}); | ||
return new Scope(data, null, SuperScopeName); | ||
} | ||
return ""; | ||
}; | ||
_proto2.createClosure = function createClosure(node) { | ||
var _this2 = this; | ||
var closure; | ||
switch (node.type) { | ||
case "BinaryExpression": | ||
closure = this.binaryExpressionHandler(node); | ||
break; | ||
case "LogicalExpression": | ||
closure = this.logicalExpressionHandler(node); | ||
break; | ||
case "UnaryExpression": | ||
closure = this.unaryExpressionHandler(node); | ||
break; | ||
case "UpdateExpression": | ||
closure = this.updateExpressionHandler(node); | ||
break; | ||
case "ObjectExpression": | ||
closure = this.objectExpressionHandler(node); | ||
break; | ||
case "ArrayExpression": | ||
closure = this.arrayExpressionHandler(node); | ||
break; | ||
case "CallExpression": | ||
closure = this.callExpressionHandler(node); | ||
break; | ||
case "NewExpression": | ||
closure = this.newExpressionHandler(node); | ||
break; | ||
case "MemberExpression": | ||
closure = this.memberExpressionHandler(node); | ||
break; | ||
case "ThisExpression": | ||
closure = this.thisExpressionHandler(node); | ||
break; | ||
case "SequenceExpression": | ||
closure = this.sequenceExpressionHandler(node); | ||
break; | ||
case "Literal": | ||
closure = this.literalHandler(node); | ||
break; | ||
case "Identifier": | ||
closure = this.identifierHandler(node); | ||
break; | ||
case "AssignmentExpression": | ||
closure = this.assignmentExpressionHandler(node); | ||
break; | ||
case "FunctionDeclaration": | ||
closure = this.functionDeclarationHandler(node); | ||
break; | ||
case "VariableDeclaration": | ||
closure = this.variableDeclarationHandler(node); | ||
break; | ||
case "BlockStatement": | ||
case "Program": | ||
closure = this.programHandler(node); | ||
break; | ||
case "ExpressionStatement": | ||
closure = this.expressionStatementHandler(node); | ||
break; | ||
case "EmptyStatement": | ||
closure = this.emptyStatementHandler(node); | ||
break; | ||
case "ReturnStatement": | ||
closure = this.returnStatementHandler(node); | ||
break; | ||
case "FunctionExpression": | ||
closure = this.functionExpressionHandler(node); | ||
break; | ||
case "IfStatement": | ||
closure = this.ifStatementHandler(node); | ||
break; | ||
case "ConditionalExpression": | ||
closure = this.conditionalExpressionHandler(node); | ||
break; | ||
case "ForStatement": | ||
closure = this.forStatementHandler(node); | ||
break; | ||
case "WhileStatement": | ||
closure = this.whileStatementHandler(node); | ||
break; | ||
case "DoWhileStatement": | ||
closure = this.doWhileStatementHandler(node); | ||
break; | ||
case "ForInStatement": | ||
closure = this.forInStatementHandler(node); | ||
break; | ||
case "WithStatement": | ||
closure = this.withStatementHandler(node); | ||
break; | ||
case "ThrowStatement": | ||
closure = this.throwStatementHandler(node); | ||
break; | ||
case "TryStatement": | ||
closure = this.tryStatementHandler(node); | ||
break; | ||
case "ContinueStatement": | ||
closure = this.continueStatementHandler(node); | ||
break; | ||
case "BreakStatement": | ||
closure = this.breakStatementHandler(node); | ||
break; | ||
case "SwitchStatement": | ||
closure = this.switchStatementHandler(node); | ||
break; | ||
case "LabeledStatement": | ||
closure = this.labeledStatementHandler(node); | ||
break; | ||
case "DebuggerStatement": | ||
closure = this.debuggerStatementHandler(node); | ||
break; | ||
default: | ||
throw this.createInternalThrowError(Messages.NodeTypeSyntaxError, node.type, node); | ||
setCurrentContext(ctx) { | ||
this.currentContext = ctx; | ||
} | ||
return function () { | ||
var timeout = _this2.options.timeout; | ||
if (timeout && timeout > 0 && _this2.checkTimeout()) { | ||
throw _this2.createInternalThrowError(Messages.ExecutionTimeOutError, timeout, null); | ||
} | ||
_this2.lastExecNode = node; | ||
return closure.apply(void 0, arguments); | ||
}; | ||
} // a==b a/b | ||
; | ||
_proto2.binaryExpressionHandler = function binaryExpressionHandler(node) { | ||
var _this3 = this; | ||
var leftExpression = this.createClosure(node.left); | ||
var rightExpression = this.createClosure(node.right); | ||
return function () { | ||
var leftValue = leftExpression(); | ||
var rightValue = rightExpression(); | ||
switch (node.operator) { | ||
case "==": | ||
return leftValue == rightValue; | ||
case "!=": | ||
return leftValue != rightValue; | ||
case "===": | ||
return leftValue === rightValue; | ||
case "!==": | ||
return leftValue !== rightValue; | ||
case "<": | ||
return leftValue < rightValue; | ||
case "<=": | ||
return leftValue <= rightValue; | ||
case ">": | ||
return leftValue > rightValue; | ||
case ">=": | ||
return leftValue >= rightValue; | ||
case "<<": | ||
return leftValue << rightValue; | ||
case ">>": | ||
return leftValue >> rightValue; | ||
case ">>>": | ||
return leftValue >>> rightValue; | ||
case "+": | ||
return leftValue + rightValue; | ||
case "-": | ||
return leftValue - rightValue; | ||
case "*": | ||
return leftValue * rightValue; | ||
case "**": | ||
return Math.pow(leftValue, rightValue); | ||
case "/": | ||
return leftValue / rightValue; | ||
case "%": | ||
return leftValue % rightValue; | ||
case "|": | ||
return leftValue | rightValue; | ||
case "^": | ||
return leftValue ^ rightValue; | ||
case "&": | ||
return leftValue & rightValue; | ||
case "in": | ||
return leftValue in rightValue; | ||
case "instanceof": | ||
return leftValue instanceof rightValue; | ||
default: | ||
throw _this3.createInternalThrowError(Messages.BinaryOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} // a && b | ||
; | ||
_proto2.logicalExpressionHandler = function logicalExpressionHandler(node) { | ||
var _this4 = this; | ||
var leftExpression = this.createClosure(node.left); | ||
var rightExpression = this.createClosure(node.right); | ||
return function () { | ||
switch (node.operator) { | ||
case "||": | ||
return leftExpression() || rightExpression(); | ||
case "&&": | ||
return leftExpression() && rightExpression(); | ||
default: | ||
throw _this4.createInternalThrowError(Messages.LogicalOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} // protected isRootScope(node: ESTree.Expression | ESTree.Pattern): boolean { | ||
// if (node.type === "Identifier") { | ||
// const scope = this.getScopeFromName(node.name, this.getCurrentScope()); | ||
// return scope.name === "rootScope"; | ||
// } | ||
// return false; | ||
// } | ||
// typeof a !a() | ||
; | ||
_proto2.unaryExpressionHandler = function unaryExpressionHandler(node) { | ||
var _this5 = this; | ||
switch (node.operator) { | ||
case "delete": | ||
var objectGetter = this.createObjectGetter(node.argument); | ||
var nameGetter = this.createNameGetter(node.argument); | ||
return function () { | ||
// not allowed to delete root scope property | ||
// rootContext has move to prototype chai, so no judgment required | ||
// if (this.isRootScope(node.argument)) { | ||
// return false; | ||
// } | ||
var obj = objectGetter(); | ||
var name = nameGetter(); | ||
return delete obj[name]; | ||
setCurrentScope(scope) { | ||
this.currentScope = scope; | ||
} | ||
evaluate(code = "") { | ||
let node; | ||
if (!code) | ||
return; | ||
node = parse(code, { | ||
ranges: true, | ||
locations: true, | ||
ecmaVersion: this.options.ecmaVersion || Interpreter.ecmaVersion, | ||
}); | ||
return this.evaluateNode(node, code); | ||
} | ||
appendCode(code) { | ||
return this.evaluate(code); | ||
} | ||
evaluateNode(node, source = "") { | ||
this.value = undefined; | ||
this.source = source; | ||
this.sourceList.push(source); | ||
this.isRunning = true; | ||
//reset timeout | ||
this.execStartTime = Date.now(); | ||
this.execEndTime = this.execStartTime; | ||
// reset | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
const currentScope = this.getCurrentScope(); | ||
const currentContext = this.getCurrentContext(); | ||
const labelStack = currentScope.labelStack.concat([]); | ||
const callStack = this.callStack.concat([]); | ||
const reset = () => { | ||
this.setCurrentScope(currentScope); //reset scope | ||
this.setCurrentContext(currentContext); //reset context | ||
currentScope.labelStack = labelStack; //reset label stack | ||
this.callStack = callStack; //reset call stack | ||
}; | ||
default: | ||
var expression; // for typeof undefined var | ||
// typeof adf9ad | ||
if (node.operator === "typeof" && node.argument.type === "Identifier") { | ||
var _objectGetter = this.createObjectGetter(node.argument); | ||
var _nameGetter = this.createNameGetter(node.argument); | ||
expression = function expression() { | ||
return _objectGetter()[_nameGetter()]; | ||
}; | ||
} else { | ||
expression = this.createClosure(node.argument); | ||
// start run | ||
try { | ||
const bodyClosure = this.createClosure(node); | ||
// add declares to data | ||
this.addDeclarationsToScope(this.collectDeclVars, this.collectDeclFuncs, this.getCurrentScope()); | ||
bodyClosure(); | ||
} | ||
return function () { | ||
var value = expression(); | ||
switch (node.operator) { | ||
case "-": | ||
return -value; | ||
case "+": | ||
return +value; | ||
case "!": | ||
return !value; | ||
case "~": | ||
return ~value; | ||
case "void": | ||
return void value; | ||
case "typeof": | ||
return typeof value; | ||
catch (e) { | ||
throw e; | ||
} | ||
finally { | ||
reset(); | ||
this.execEndTime = Date.now(); | ||
} | ||
this.isRunning = false; | ||
return this.getValue(); | ||
} | ||
createErrorMessage(msg, value, node) { | ||
let message = msg[1].replace("%0", String(value)); | ||
if (node !== null) { | ||
message += this.getNodePosition(node || this.lastExecNode); | ||
} | ||
return message; | ||
} | ||
createError(message, error) { | ||
return new error(message); | ||
} | ||
createThrowError(message, error) { | ||
return this.createError(message, error); | ||
} | ||
createInternalThrowError(msg, value, node) { | ||
return this.createError(this.createErrorMessage(msg, value, node), msg[2]); | ||
} | ||
checkTimeout() { | ||
if (!this.isRunning) | ||
return false; | ||
const timeout = this.options.timeout || 0; | ||
const now = Date.now(); | ||
if (now - this.execStartTime > timeout) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
getNodePosition(node) { | ||
if (node) { | ||
const errorCode = ""; //this.source.slice(node.start, node.end); | ||
return node.loc ? ` [${node.loc.start.line}:${node.loc.start.column}]${errorCode}` : ""; | ||
} | ||
return ""; | ||
} | ||
createClosure(node) { | ||
let closure; | ||
switch (node.type) { | ||
case "BinaryExpression": | ||
closure = this.binaryExpressionHandler(node); | ||
break; | ||
case "LogicalExpression": | ||
closure = this.logicalExpressionHandler(node); | ||
break; | ||
case "UnaryExpression": | ||
closure = this.unaryExpressionHandler(node); | ||
break; | ||
case "UpdateExpression": | ||
closure = this.updateExpressionHandler(node); | ||
break; | ||
case "ObjectExpression": | ||
closure = this.objectExpressionHandler(node); | ||
break; | ||
case "ArrayExpression": | ||
closure = this.arrayExpressionHandler(node); | ||
break; | ||
case "CallExpression": | ||
closure = this.callExpressionHandler(node); | ||
break; | ||
case "NewExpression": | ||
closure = this.newExpressionHandler(node); | ||
break; | ||
case "MemberExpression": | ||
closure = this.memberExpressionHandler(node); | ||
break; | ||
case "ThisExpression": | ||
closure = this.thisExpressionHandler(node); | ||
break; | ||
case "SequenceExpression": | ||
closure = this.sequenceExpressionHandler(node); | ||
break; | ||
case "Literal": | ||
closure = this.literalHandler(node); | ||
break; | ||
case "Identifier": | ||
closure = this.identifierHandler(node); | ||
break; | ||
case "AssignmentExpression": | ||
closure = this.assignmentExpressionHandler(node); | ||
break; | ||
case "FunctionDeclaration": | ||
closure = this.functionDeclarationHandler(node); | ||
break; | ||
case "VariableDeclaration": | ||
closure = this.variableDeclarationHandler(node); | ||
break; | ||
case "BlockStatement": | ||
case "Program": | ||
closure = this.programHandler(node); | ||
break; | ||
case "ExpressionStatement": | ||
closure = this.expressionStatementHandler(node); | ||
break; | ||
case "EmptyStatement": | ||
closure = this.emptyStatementHandler(node); | ||
break; | ||
case "ReturnStatement": | ||
closure = this.returnStatementHandler(node); | ||
break; | ||
case "FunctionExpression": | ||
closure = this.functionExpressionHandler(node); | ||
break; | ||
case "IfStatement": | ||
closure = this.ifStatementHandler(node); | ||
break; | ||
case "ConditionalExpression": | ||
closure = this.conditionalExpressionHandler(node); | ||
break; | ||
case "ForStatement": | ||
closure = this.forStatementHandler(node); | ||
break; | ||
case "WhileStatement": | ||
closure = this.whileStatementHandler(node); | ||
break; | ||
case "DoWhileStatement": | ||
closure = this.doWhileStatementHandler(node); | ||
break; | ||
case "ForInStatement": | ||
closure = this.forInStatementHandler(node); | ||
break; | ||
case "WithStatement": | ||
closure = this.withStatementHandler(node); | ||
break; | ||
case "ThrowStatement": | ||
closure = this.throwStatementHandler(node); | ||
break; | ||
case "TryStatement": | ||
closure = this.tryStatementHandler(node); | ||
break; | ||
case "ContinueStatement": | ||
closure = this.continueStatementHandler(node); | ||
break; | ||
case "BreakStatement": | ||
closure = this.breakStatementHandler(node); | ||
break; | ||
case "SwitchStatement": | ||
closure = this.switchStatementHandler(node); | ||
break; | ||
case "LabeledStatement": | ||
closure = this.labeledStatementHandler(node); | ||
break; | ||
case "DebuggerStatement": | ||
closure = this.debuggerStatementHandler(node); | ||
break; | ||
default: | ||
throw _this5.createInternalThrowError(Messages.UnaryOperatorSyntaxError, node.operator, node); | ||
} | ||
throw this.createInternalThrowError(Messages.NodeTypeSyntaxError, node.type, node); | ||
} | ||
return (...args) => { | ||
const timeout = this.options.timeout; | ||
if (timeout && timeout > 0 && this.checkTimeout()) { | ||
throw this.createInternalThrowError(Messages.ExecutionTimeOutError, timeout, null); | ||
} | ||
this.lastExecNode = node; | ||
return closure(...args); | ||
}; | ||
} | ||
} // ++a --a | ||
; | ||
_proto2.updateExpressionHandler = function updateExpressionHandler(node) { | ||
var _this6 = this; | ||
var objectGetter = this.createObjectGetter(node.argument); | ||
var nameGetter = this.createNameGetter(node.argument); | ||
return function () { | ||
var obj = objectGetter(); | ||
var name = nameGetter(); | ||
_this6.assertVariable(obj, name, node); | ||
switch (node.operator) { | ||
case "++": | ||
return node.prefix ? ++obj[name] : obj[name]++; | ||
case "--": | ||
return node.prefix ? --obj[name] : obj[name]--; | ||
default: | ||
throw _this6.createInternalThrowError(Messages.UpdateOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} // var o = {a: 1, b: 's', get name(){}, set name(){} ...} | ||
; | ||
_proto2.objectExpressionHandler = function objectExpressionHandler(node) { | ||
var _this7 = this; | ||
var items = []; | ||
function getKey(keyNode) { | ||
if (keyNode.type === "Identifier") { | ||
// var o = {a:1} | ||
return keyNode.name; | ||
} else if (keyNode.type === "Literal") { | ||
// var o = {"a":1} | ||
return keyNode.value; | ||
} else { | ||
return this.throwError(Messages.ObjectStructureSyntaxError, keyNode.type, keyNode); | ||
} | ||
} // collect value, getter, and/or setter. | ||
var properties = Object.create(null); | ||
node.properties.forEach(function (property) { | ||
var kind = property.kind; | ||
var key = getKey(property.key); | ||
if (!properties[key] || kind === "init") { | ||
properties[key] = {}; | ||
} | ||
properties[key][kind] = _this7.createClosure(property.value); | ||
items.push({ | ||
key: key, | ||
property: property | ||
}); | ||
}); | ||
return function () { | ||
var result = {}; | ||
var len = items.length; | ||
for (var i = 0; i < len; i++) { | ||
var item = items[i]; | ||
var key = item.key; | ||
var kinds = properties[key]; | ||
var value = kinds.init ? kinds.init() : undefined; | ||
var getter = kinds.get ? kinds.get() : function () {}; | ||
var setter = kinds.set ? kinds.set() : function (a) {}; | ||
if ("set" in kinds || "get" in kinds) { | ||
var descriptor = { | ||
configurable: true, | ||
enumerable: true, | ||
get: getter, | ||
set: setter | ||
}; | ||
Object.defineProperty(result, key, descriptor); | ||
} else { | ||
var property = item.property; | ||
var kind = property.kind; // set function.name | ||
// var d = { test(){} } | ||
// var d = { test: function(){} } | ||
if (property.key.type === "Identifier" && property.value.type === "FunctionExpression" && kind === "init" && !property.value.id) { | ||
defineFunctionName(value, property.key.name); | ||
} | ||
result[key] = value; | ||
// a==b a/b | ||
binaryExpressionHandler(node) { | ||
const leftExpression = this.createClosure(node.left); | ||
const rightExpression = this.createClosure(node.right); | ||
return () => { | ||
const leftValue = leftExpression(); | ||
const rightValue = rightExpression(); | ||
switch (node.operator) { | ||
case "==": | ||
return leftValue == rightValue; | ||
case "!=": | ||
return leftValue != rightValue; | ||
case "===": | ||
return leftValue === rightValue; | ||
case "!==": | ||
return leftValue !== rightValue; | ||
case "<": | ||
return leftValue < rightValue; | ||
case "<=": | ||
return leftValue <= rightValue; | ||
case ">": | ||
return leftValue > rightValue; | ||
case ">=": | ||
return leftValue >= rightValue; | ||
case "<<": | ||
return leftValue << rightValue; | ||
case ">>": | ||
return leftValue >> rightValue; | ||
case ">>>": | ||
return leftValue >>> rightValue; | ||
case "+": | ||
return leftValue + rightValue; | ||
case "-": | ||
return leftValue - rightValue; | ||
case "*": | ||
return leftValue * rightValue; | ||
case "**": | ||
return Math.pow(leftValue, rightValue); | ||
case "/": | ||
return leftValue / rightValue; | ||
case "%": | ||
return leftValue % rightValue; | ||
case "|": | ||
return leftValue | rightValue; | ||
case "^": | ||
return leftValue ^ rightValue; | ||
case "&": | ||
return leftValue & rightValue; | ||
case "in": | ||
return leftValue in rightValue; | ||
case "instanceof": | ||
return leftValue instanceof rightValue; | ||
default: | ||
throw this.createInternalThrowError(Messages.BinaryOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} | ||
// a && b | ||
logicalExpressionHandler(node) { | ||
const leftExpression = this.createClosure(node.left); | ||
const rightExpression = this.createClosure(node.right); | ||
return () => { | ||
switch (node.operator) { | ||
case "||": | ||
return leftExpression() || rightExpression(); | ||
case "&&": | ||
return leftExpression() && rightExpression(); | ||
default: | ||
throw this.createInternalThrowError(Messages.LogicalOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} | ||
// protected isRootScope(node: ESTree.Expression | ESTree.Pattern): boolean { | ||
// if (node.type === "Identifier") { | ||
// const scope = this.getScopeFromName(node.name, this.getCurrentScope()); | ||
// return scope.name === "rootScope"; | ||
// } | ||
// return false; | ||
// } | ||
// typeof a !a() | ||
unaryExpressionHandler(node) { | ||
switch (node.operator) { | ||
case "delete": | ||
const objectGetter = this.createObjectGetter(node.argument); | ||
const nameGetter = this.createNameGetter(node.argument); | ||
return () => { | ||
// not allowed to delete root scope property | ||
// rootContext has move to prototype chai, so no judgment required | ||
// if (this.isRootScope(node.argument)) { | ||
// return false; | ||
// } | ||
let obj = objectGetter(); | ||
const name = nameGetter(); | ||
return delete obj[name]; | ||
}; | ||
default: | ||
let expression; | ||
// for typeof undefined var | ||
// typeof adf9ad | ||
if (node.operator === "typeof" && node.argument.type === "Identifier") { | ||
const objectGetter = this.createObjectGetter(node.argument); | ||
const nameGetter = this.createNameGetter(node.argument); | ||
expression = () => objectGetter()[nameGetter()]; | ||
} | ||
else { | ||
expression = this.createClosure(node.argument); | ||
} | ||
return () => { | ||
const value = expression(); | ||
switch (node.operator) { | ||
case "-": | ||
return -value; | ||
case "+": | ||
return +value; | ||
case "!": | ||
return !value; | ||
case "~": | ||
return ~value; | ||
case "void": | ||
return void value; | ||
case "typeof": | ||
return typeof value; | ||
default: | ||
throw this.createInternalThrowError(Messages.UnaryOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} | ||
} | ||
return result; | ||
}; | ||
} // [1,2,3] | ||
; | ||
_proto2.arrayExpressionHandler = function arrayExpressionHandler(node) { | ||
var _this8 = this; | ||
//fix: [,,,1,2] | ||
var items = node.elements.map(function (element) { | ||
return element ? _this8.createClosure(element) : element; | ||
}); | ||
return function () { | ||
var len = items.length; | ||
var result = Array(len); | ||
for (var i = 0; i < len; i++) { | ||
var item = items[i]; | ||
if (item) { | ||
result[i] = item(); | ||
} | ||
// ++a --a | ||
updateExpressionHandler(node) { | ||
const objectGetter = this.createObjectGetter(node.argument); | ||
const nameGetter = this.createNameGetter(node.argument); | ||
return () => { | ||
const obj = objectGetter(); | ||
const name = nameGetter(); | ||
this.assertVariable(obj, name, node); | ||
switch (node.operator) { | ||
case "++": | ||
return node.prefix ? ++obj[name] : obj[name]++; | ||
case "--": | ||
return node.prefix ? --obj[name] : obj[name]--; | ||
default: | ||
throw this.createInternalThrowError(Messages.UpdateOperatorSyntaxError, node.operator, node); | ||
} | ||
}; | ||
} | ||
// var o = {a: 1, b: 's', get name(){}, set name(){} ...} | ||
objectExpressionHandler(node) { | ||
const items = []; | ||
function getKey(keyNode) { | ||
if (keyNode.type === "Identifier") { | ||
// var o = {a:1} | ||
return keyNode.name; | ||
} | ||
else if (keyNode.type === "Literal") { | ||
// var o = {"a":1} | ||
return keyNode.value; | ||
} | ||
else { | ||
return this.throwError(Messages.ObjectStructureSyntaxError, keyNode.type, keyNode); | ||
} | ||
} | ||
} | ||
return result; | ||
}; | ||
}; | ||
_proto2.safeObjectGet = function safeObjectGet(obj, key, node) { | ||
return obj[key]; | ||
}; | ||
_proto2.createCallFunctionGetter = function createCallFunctionGetter(node) { | ||
var _this9 = this; | ||
switch (node.type) { | ||
case "MemberExpression": | ||
var objectGetter = this.createClosure(node.object); | ||
var keyGetter = this.createMemberKeyGetter(node); | ||
var source = this.source; | ||
return function () { | ||
var obj = objectGetter(); | ||
var key = keyGetter(); | ||
var func = _this9.safeObjectGet(obj, key, node); | ||
if (!func || !isFunction(func)) { | ||
var name = source.slice(node.start, node.end); | ||
throw _this9.createInternalThrowError(Messages.FunctionUndefinedReferenceError, name, node); | ||
} // obj.eval = eval | ||
// obj.eval(...) | ||
if (func.__IS_EVAL_FUNC) { | ||
return function (code) { | ||
return func(new InternalInterpreterReflection(_this9), code, true); | ||
// collect value, getter, and/or setter. | ||
const properties = Object.create(null); | ||
node.properties.forEach(property => { | ||
const kind = property.kind; | ||
const key = getKey(property.key); | ||
if (!properties[key] || kind === "init") { | ||
properties[key] = {}; | ||
} | ||
properties[key][kind] = this.createClosure(property.value); | ||
items.push({ | ||
key, | ||
property, | ||
}); | ||
}); | ||
return () => { | ||
const result = {}; | ||
const len = items.length; | ||
for (let i = 0; i < len; i++) { | ||
const item = items[i]; | ||
const key = item.key; | ||
const kinds = properties[key]; | ||
const value = kinds.init ? kinds.init() : undefined; | ||
const getter = kinds.get ? kinds.get() : function () { }; | ||
const setter = kinds.set ? kinds.set() : function (a) { }; | ||
if ("set" in kinds || "get" in kinds) { | ||
const descriptor = { | ||
configurable: true, | ||
enumerable: true, | ||
get: getter, | ||
set: setter, | ||
}; | ||
Object.defineProperty(result, key, descriptor); | ||
} | ||
else { | ||
const property = item.property; | ||
const kind = property.kind; | ||
// set function.name | ||
// var d = { test(){} } | ||
// var d = { test: function(){} } | ||
if (property.key.type === "Identifier" && | ||
property.value.type === "FunctionExpression" && | ||
kind === "init" && | ||
!property.value.id) { | ||
defineFunctionName(value, property.key.name); | ||
} | ||
result[key] = value; | ||
} | ||
} | ||
return result; | ||
}; | ||
} | ||
// [1,2,3] | ||
arrayExpressionHandler(node) { | ||
//fix: [,,,1,2] | ||
const items = node.elements.map(element => element ? this.createClosure(element) : element); | ||
return () => { | ||
const len = items.length; | ||
const result = Array(len); | ||
for (let i = 0; i < len; i++) { | ||
const item = items[i]; | ||
if (item) { | ||
result[i] = item(); | ||
} | ||
} | ||
return result; | ||
}; | ||
} | ||
safeObjectGet(obj, key, node) { | ||
return obj[key]; | ||
} | ||
createCallFunctionGetter(node) { | ||
switch (node.type) { | ||
case "MemberExpression": | ||
const objectGetter = this.createClosure(node.object); | ||
const keyGetter = this.createMemberKeyGetter(node); | ||
const source = this.source; | ||
return () => { | ||
const obj = objectGetter(); | ||
const key = keyGetter(); | ||
const func = this.safeObjectGet(obj, key, node); | ||
if (!func || !isFunction(func)) { | ||
const name = source.slice(node.start, node.end); | ||
throw this.createInternalThrowError(Messages.FunctionUndefinedReferenceError, name, node); | ||
} | ||
// obj.eval = eval | ||
// obj.eval(...) | ||
if (func.__IS_EVAL_FUNC) { | ||
return (code) => { | ||
return func(new InternalInterpreterReflection(this), code, true); | ||
}; | ||
} | ||
// obj.func = Function | ||
// obj.func(...) | ||
if (func.__IS_FUNCTION_FUNC) { | ||
return (...args) => { | ||
return func(new InternalInterpreterReflection(this), ...args); | ||
}; | ||
} | ||
// method call | ||
// eg:obj.say(...) | ||
// eg: obj.say.call(...) | ||
// eg: obj.say.apply(...) | ||
// ====================== | ||
// obj.func(...) | ||
// func = func.bind(obj) | ||
// tips: | ||
// func(...) -> func.bind(obj)(...) | ||
// func.call(...) -> obj.func.call.bind(obj.func)(...) | ||
// func.apply(...) -> obj.func.apply.bind(obj.func)(...) | ||
// ...others | ||
return func.bind(obj); | ||
}; | ||
default: | ||
// test() or (0,test)() or a[1]() ... | ||
const closure = this.createClosure(node); | ||
return () => { | ||
let name = ""; | ||
if (node.type === "Identifier") { | ||
name = node.name; | ||
} | ||
// const name: string = (<ESTree.Identifier>node).name; | ||
const func = closure(); | ||
if (!func || !isFunction(func)) { | ||
throw this.createInternalThrowError(Messages.FunctionUndefinedReferenceError, name, node); | ||
} | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval | ||
// var eval = eval; | ||
// function test(){ | ||
// eval(...); //note: use local scope in eval5,but in Browser is use global scope | ||
// } | ||
if (node.type === "Identifier" && func.__IS_EVAL_FUNC && name === "eval") { | ||
return (code) => { | ||
const scope = this.getScopeFromName(name, this.getCurrentScope()); | ||
const useGlobalScope = scope.name === SuperScopeName || | ||
// !scope.parent || // super scope | ||
scope.name === GlobalScopeName || | ||
// this.globalScope === scope || | ||
scope.name === RootScopeName; | ||
// use local scope if calling eval in super scope | ||
return func(new InternalInterpreterReflection(this), code, !useGlobalScope); | ||
}; | ||
} | ||
// use global scope | ||
// var g_eval = eval; | ||
// g_eval("a+1"); | ||
//(0,eval)(...) ...eval alias | ||
if (func.__IS_EVAL_FUNC) { | ||
return (code) => { | ||
return func(new InternalInterpreterReflection(this), code, true); | ||
}; | ||
} | ||
// Function('a', 'b', 'return a+b') | ||
if (func.__IS_FUNCTION_FUNC) { | ||
return (...args) => { | ||
return func(new InternalInterpreterReflection(this), ...args); | ||
}; | ||
} | ||
let ctx = this.options.globalContextInFunction; | ||
// with(obj) { | ||
// test() // test.call(obj, ...) | ||
// } | ||
if (node.type === "Identifier") { | ||
const scope = this.getIdentifierScope(node); | ||
if (scope.name === WithScopeName) { | ||
ctx = scope.data; | ||
} | ||
} | ||
// function call | ||
// this = undefined | ||
// tips: | ||
// test(...) === test.call(undefined, ...) | ||
// fix: alert.call({}, ...) Illegal invocation | ||
return func.bind(ctx); | ||
}; | ||
} | ||
} | ||
// func() | ||
callExpressionHandler(node) { | ||
const funcGetter = this.createCallFunctionGetter(node.callee); | ||
const argsGetter = node.arguments.map(arg => this.createClosure(arg)); | ||
return () => { | ||
return funcGetter()(...argsGetter.map(arg => arg())); | ||
}; | ||
} | ||
// var f = function() {...} | ||
functionExpressionHandler(node) { | ||
const self = this; | ||
const source = this.source; | ||
const oldDeclVars = this.collectDeclVars; | ||
const oldDeclFuncs = this.collectDeclFuncs; | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
const name = node.id ? node.id.name : ""; /**anonymous*/ | ||
const paramLength = node.params.length; | ||
const paramsGetter = node.params.map(param => this.createParamNameGetter(param)); | ||
// set scope | ||
const bodyClosure = this.createClosure(node.body); | ||
const declVars = this.collectDeclVars; | ||
const declFuncs = this.collectDeclFuncs; | ||
this.collectDeclVars = oldDeclVars; | ||
this.collectDeclFuncs = oldDeclFuncs; | ||
return () => { | ||
// bind current scope | ||
const runtimeScope = self.getCurrentScope(); | ||
const func = function (...args) { | ||
self.callStack.push(`${name}`); | ||
const prevScope = self.getCurrentScope(); | ||
const currentScope = createScope(runtimeScope, `FunctionScope(${name})`); | ||
self.setCurrentScope(currentScope); | ||
self.addDeclarationsToScope(declVars, declFuncs, currentScope); | ||
// var t = function(){ typeof t } // function | ||
// t = function(){ typeof t } // function | ||
// z = function tx(){ typeof tx } // function | ||
// but | ||
// d = { say: function(){ typeof say } } // undefined | ||
if (name) { | ||
currentScope.data[name] = func; | ||
} | ||
// init arguments var | ||
currentScope.data["arguments"] = arguments; | ||
paramsGetter.forEach((getter, i) => { | ||
currentScope.data[getter()] = args[i]; | ||
}); | ||
// init this | ||
const prevContext = self.getCurrentContext(); | ||
//for ThisExpression | ||
self.setCurrentContext(this); | ||
const result = bodyClosure(); | ||
//reset | ||
self.setCurrentContext(prevContext); | ||
self.setCurrentScope(prevScope); | ||
self.callStack.pop(); | ||
if (result instanceof Return) { | ||
return result.value; | ||
} | ||
}; | ||
} // obj.func = Function | ||
// obj.func(...) | ||
if (func.__IS_FUNCTION_FUNC) { | ||
return function () { | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
return func.apply(void 0, [new InternalInterpreterReflection(_this9)].concat(args)); | ||
}; | ||
} // method call | ||
// eg:obj.say(...) | ||
// eg: obj.say.call(...) | ||
// eg: obj.say.apply(...) | ||
// ====================== | ||
// obj.func(...) | ||
// func = func.bind(obj) | ||
// tips: | ||
// func(...) -> func.bind(obj)(...) | ||
// func.call(...) -> obj.func.call.bind(obj.func)(...) | ||
// func.apply(...) -> obj.func.apply.bind(obj.func)(...) | ||
// ...others | ||
return func.bind(obj); | ||
defineFunctionName(func, name); | ||
Object.defineProperty(func, "length", { | ||
value: paramLength, | ||
writable: false, | ||
enumerable: false, | ||
configurable: true, | ||
}); | ||
Object.defineProperty(func, "toString", { | ||
value: () => { | ||
return source.slice(node.start, node.end); | ||
}, | ||
writable: true, | ||
configurable: true, | ||
enumerable: false, | ||
}); | ||
Object.defineProperty(func, "valueOf", { | ||
value: () => { | ||
return source.slice(node.start, node.end); | ||
}, | ||
writable: true, | ||
configurable: true, | ||
enumerable: false, | ||
}); | ||
return func; | ||
}; | ||
default: | ||
// test() or (0,test)() or a[1]() ... | ||
var closure = this.createClosure(node); | ||
return function () { | ||
var name = ""; | ||
if (node.type === "Identifier") { | ||
name = node.name; | ||
} // const name: string = (<ESTree.Identifier>node).name; | ||
var func = closure(); | ||
if (!func || !isFunction(func)) { | ||
throw _this9.createInternalThrowError(Messages.FunctionUndefinedReferenceError, name, node); | ||
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval | ||
// var eval = eval; | ||
// function test(){ | ||
// eval(...); //note: use local scope in eval5,but in Browser is use global scope | ||
// } | ||
if (node.type === "Identifier" && func.__IS_EVAL_FUNC && name === "eval") { | ||
return function (code) { | ||
var scope = _this9.getScopeFromName(name, _this9.getCurrentScope()); | ||
var useGlobalScope = scope.name === SuperScopeName || // !scope.parent || // super scope | ||
scope.name === GlobalScopeName || // this.globalScope === scope || | ||
scope.name === RootScopeName; // use local scope if calling eval in super scope | ||
return func(new InternalInterpreterReflection(_this9), code, !useGlobalScope); | ||
} | ||
// new Ctrl() | ||
newExpressionHandler(node) { | ||
const source = this.source; | ||
const expression = this.createClosure(node.callee); | ||
const args = node.arguments.map(arg => this.createClosure(arg)); | ||
return () => { | ||
const construct = expression(); | ||
if (!isFunction(construct) || construct.__IS_EVAL_FUNC) { | ||
const callee = node.callee; | ||
const name = source.slice(callee.start, callee.end); | ||
throw this.createInternalThrowError(Messages.IsNotConstructor, name, node); | ||
} | ||
// new Function(...) | ||
if (construct.__IS_FUNCTION_FUNC) { | ||
return construct(new InternalInterpreterReflection(this), ...args.map(arg => arg())); | ||
} | ||
return new construct(...args.map(arg => arg())); | ||
}; | ||
} | ||
// a.b a['b'] | ||
memberExpressionHandler(node) { | ||
const objectGetter = this.createClosure(node.object); | ||
const keyGetter = this.createMemberKeyGetter(node); | ||
return () => { | ||
const obj = objectGetter(); | ||
let key = keyGetter(); | ||
return obj[key]; | ||
}; | ||
} | ||
//this | ||
thisExpressionHandler(node) { | ||
return () => this.getCurrentContext(); | ||
} | ||
// var1,var2,... | ||
sequenceExpressionHandler(node) { | ||
const expressions = node.expressions.map(item => this.createClosure(item)); | ||
return () => { | ||
let result; | ||
const len = expressions.length; | ||
for (let i = 0; i < len; i++) { | ||
const expression = expressions[i]; | ||
result = expression(); | ||
} | ||
return result; | ||
}; | ||
} | ||
// 1 'name' | ||
literalHandler(node) { | ||
return () => { | ||
if (node.regex) { | ||
return new RegExp(node.regex.pattern, node.regex.flags); | ||
} | ||
return node.value; | ||
}; | ||
} | ||
// var1 ... | ||
identifierHandler(node) { | ||
return () => { | ||
const currentScope = this.getCurrentScope(); | ||
const data = this.getScopeDataFromName(node.name, currentScope); | ||
this.assertVariable(data, node.name, node); | ||
return data[node.name]; | ||
}; | ||
} | ||
getIdentifierScope(node) { | ||
const currentScope = this.getCurrentScope(); | ||
const scope = this.getScopeFromName(node.name, currentScope); | ||
return scope; | ||
} | ||
// a=1 a+=2 | ||
assignmentExpressionHandler(node) { | ||
// var s = function(){} | ||
// s.name === s | ||
if (node.left.type === "Identifier" && | ||
node.right.type === "FunctionExpression" && | ||
!node.right.id) { | ||
node.right.id = { | ||
type: "Identifier", | ||
name: node.left.name, | ||
}; | ||
} // use global scope | ||
// var g_eval = eval; | ||
// g_eval("a+1"); | ||
//(0,eval)(...) ...eval alias | ||
if (func.__IS_EVAL_FUNC) { | ||
return function (code) { | ||
return func(new InternalInterpreterReflection(_this9), code, true); | ||
}; | ||
} // Function('a', 'b', 'return a+b') | ||
if (func.__IS_FUNCTION_FUNC) { | ||
return function () { | ||
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
return func.apply(void 0, [new InternalInterpreterReflection(_this9)].concat(args)); | ||
}; | ||
} | ||
var ctx = _this9.options.globalContextInFunction; // with(obj) { | ||
// test() // test.call(obj, ...) | ||
// } | ||
if (node.type === "Identifier") { | ||
var scope = _this9.getIdentifierScope(node); | ||
if (scope.name === WithScopeName) { | ||
ctx = scope.data; | ||
} | ||
const dataGetter = this.createObjectGetter(node.left); | ||
const nameGetter = this.createNameGetter(node.left); | ||
const rightValueGetter = this.createClosure(node.right); | ||
return () => { | ||
const data = dataGetter(); | ||
const name = nameGetter(); | ||
const rightValue = rightValueGetter(); | ||
if (node.operator !== "=") { | ||
// if a is undefined | ||
// a += 1 | ||
this.assertVariable(data, name, node); | ||
} | ||
} // function call | ||
// this = undefined | ||
// tips: | ||
// test(...) === test.call(undefined, ...) | ||
// fix: alert.call({}, ...) Illegal invocation | ||
return func.bind(ctx); | ||
switch (node.operator) { | ||
case "=": | ||
return (data[name] = rightValue); | ||
case "+=": | ||
return (data[name] += rightValue); | ||
case "-=": | ||
return (data[name] -= rightValue); | ||
case "*=": | ||
return (data[name] *= rightValue); | ||
case "**=": | ||
return (data[name] = Math.pow(data[name], rightValue)); | ||
case "/=": | ||
return (data[name] /= rightValue); | ||
case "%=": | ||
return (data[name] %= rightValue); | ||
case "<<=": | ||
return (data[name] <<= rightValue); | ||
case ">>=": | ||
return (data[name] >>= rightValue); | ||
case ">>>=": | ||
return (data[name] >>>= rightValue); | ||
case "&=": | ||
return (data[name] &= rightValue); | ||
case "^=": | ||
return (data[name] ^= rightValue); | ||
case "|=": | ||
return (data[name] |= rightValue); | ||
default: | ||
throw this.createInternalThrowError(Messages.AssignmentExpressionSyntaxError, node.type, node); | ||
} | ||
}; | ||
} | ||
} // func() | ||
; | ||
_proto2.callExpressionHandler = function callExpressionHandler(node) { | ||
var _this10 = this; | ||
var funcGetter = this.createCallFunctionGetter(node.callee); | ||
var argsGetter = node.arguments.map(function (arg) { | ||
return _this10.createClosure(arg); | ||
}); | ||
return function () { | ||
return funcGetter().apply(void 0, argsGetter.map(function (arg) { | ||
return arg(); | ||
})); | ||
}; | ||
} // var f = function() {...} | ||
; | ||
_proto2.functionExpressionHandler = function functionExpressionHandler(node) { | ||
var _this11 = this; | ||
var self = this; | ||
var source = this.source; | ||
var oldDeclVars = this.collectDeclVars; | ||
var oldDeclFuncs = this.collectDeclFuncs; | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
var name = node.id ? node.id.name : ""; | ||
/**anonymous*/ | ||
var paramLength = node.params.length; | ||
var paramsGetter = node.params.map(function (param) { | ||
return _this11.createParamNameGetter(param); | ||
}); // set scope | ||
var bodyClosure = this.createClosure(node.body); | ||
var declVars = this.collectDeclVars; | ||
var declFuncs = this.collectDeclFuncs; | ||
this.collectDeclVars = oldDeclVars; | ||
this.collectDeclFuncs = oldDeclFuncs; | ||
return function () { | ||
// bind current scope | ||
var runtimeScope = self.getCurrentScope(); | ||
var func = function func() { | ||
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { | ||
args[_key4] = arguments[_key4]; | ||
// function test(){} | ||
functionDeclarationHandler(node) { | ||
if (node.id) { | ||
const functionClosure = this.functionExpressionHandler(node); | ||
Object.defineProperty(functionClosure, "isFunctionDeclareClosure", { | ||
value: true, | ||
writable: false, | ||
configurable: false, | ||
enumerable: false, | ||
}); | ||
this.funcDeclaration(node.id.name, functionClosure); | ||
} | ||
self.callStack.push("" + name); | ||
var prevScope = self.getCurrentScope(); | ||
var currentScope = createScope(runtimeScope, "FunctionScope(" + name + ")"); | ||
self.setCurrentScope(currentScope); | ||
self.addDeclarationsToScope(declVars, declFuncs, currentScope); // var t = function(){ typeof t } // function | ||
// t = function(){ typeof t } // function | ||
// z = function tx(){ typeof tx } // function | ||
// but | ||
// d = { say: function(){ typeof say } } // undefined | ||
if (name) { | ||
currentScope.data[name] = func; | ||
} // init arguments var | ||
currentScope.data["arguments"] = arguments; | ||
paramsGetter.forEach(function (getter, i) { | ||
currentScope.data[getter()] = args[i]; | ||
}); // init this | ||
var prevContext = self.getCurrentContext(); //for ThisExpression | ||
self.setCurrentContext(this); | ||
var result = bodyClosure(); //reset | ||
self.setCurrentContext(prevContext); | ||
self.setCurrentScope(prevScope); | ||
self.callStack.pop(); | ||
if (result instanceof Return) { | ||
return result.value; | ||
return () => { | ||
return EmptyStatementReturn; | ||
}; | ||
} | ||
getVariableName(node) { | ||
if (node.type === "Identifier") { | ||
return node.name; | ||
} | ||
}; | ||
defineFunctionName(func, name); | ||
Object.defineProperty(func, "length", { | ||
value: paramLength, | ||
writable: false, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Object.defineProperty(func, "toString", { | ||
value: function value() { | ||
return source.slice(node.start, node.end); | ||
}, | ||
writable: true, | ||
configurable: true, | ||
enumerable: false | ||
}); | ||
Object.defineProperty(func, "valueOf", { | ||
value: function value() { | ||
return source.slice(node.start, node.end); | ||
}, | ||
writable: true, | ||
configurable: true, | ||
enumerable: false | ||
}); | ||
return func; | ||
}; | ||
} // new Ctrl() | ||
; | ||
_proto2.newExpressionHandler = function newExpressionHandler(node) { | ||
var _this12 = this; | ||
var source = this.source; | ||
var expression = this.createClosure(node.callee); | ||
var args = node.arguments.map(function (arg) { | ||
return _this12.createClosure(arg); | ||
}); | ||
return function () { | ||
var construct = expression(); | ||
if (!isFunction(construct) || construct.__IS_EVAL_FUNC) { | ||
var callee = node.callee; | ||
var name = source.slice(callee.start, callee.end); | ||
throw _this12.createInternalThrowError(Messages.IsNotConstructor, name, node); | ||
} // new Function(...) | ||
if (construct.__IS_FUNCTION_FUNC) { | ||
return construct.apply(void 0, [new InternalInterpreterReflection(_this12)].concat(args.map(function (arg) { | ||
return arg(); | ||
}))); | ||
} | ||
return _construct(construct, args.map(function (arg) { | ||
return arg(); | ||
})); | ||
}; | ||
} // a.b a['b'] | ||
; | ||
_proto2.memberExpressionHandler = function memberExpressionHandler(node) { | ||
var objectGetter = this.createClosure(node.object); | ||
var keyGetter = this.createMemberKeyGetter(node); | ||
return function () { | ||
var obj = objectGetter(); | ||
var key = keyGetter(); | ||
return obj[key]; | ||
}; | ||
} //this | ||
; | ||
_proto2.thisExpressionHandler = function thisExpressionHandler(node) { | ||
var _this13 = this; | ||
return function () { | ||
return _this13.getCurrentContext(); | ||
}; | ||
} // var1,var2,... | ||
; | ||
_proto2.sequenceExpressionHandler = function sequenceExpressionHandler(node) { | ||
var _this14 = this; | ||
var expressions = node.expressions.map(function (item) { | ||
return _this14.createClosure(item); | ||
}); | ||
return function () { | ||
var result; | ||
var len = expressions.length; | ||
for (var i = 0; i < len; i++) { | ||
var expression = expressions[i]; | ||
result = expression(); | ||
} | ||
return result; | ||
}; | ||
} // 1 'name' | ||
; | ||
_proto2.literalHandler = function literalHandler(node) { | ||
return function () { | ||
if (node.regex) { | ||
return new RegExp(node.regex.pattern, node.regex.flags); | ||
} | ||
return node.value; | ||
}; | ||
} // var1 ... | ||
; | ||
_proto2.identifierHandler = function identifierHandler(node) { | ||
var _this15 = this; | ||
return function () { | ||
var currentScope = _this15.getCurrentScope(); | ||
var data = _this15.getScopeDataFromName(node.name, currentScope); | ||
_this15.assertVariable(data, node.name, node); | ||
return data[node.name]; | ||
}; | ||
}; | ||
_proto2.getIdentifierScope = function getIdentifierScope(node) { | ||
var currentScope = this.getCurrentScope(); | ||
var scope = this.getScopeFromName(node.name, currentScope); | ||
return scope; | ||
} // a=1 a+=2 | ||
; | ||
_proto2.assignmentExpressionHandler = function assignmentExpressionHandler(node) { | ||
var _this16 = this; | ||
// var s = function(){} | ||
// s.name === s | ||
if (node.left.type === "Identifier" && node.right.type === "FunctionExpression" && !node.right.id) { | ||
node.right.id = { | ||
type: "Identifier", | ||
name: node.left.name | ||
}; | ||
else { | ||
throw this.createInternalThrowError(Messages.VariableTypeSyntaxError, node.type, node); | ||
} | ||
} | ||
var dataGetter = this.createObjectGetter(node.left); | ||
var nameGetter = this.createNameGetter(node.left); | ||
var rightValueGetter = this.createClosure(node.right); | ||
return function () { | ||
var data = dataGetter(); | ||
var name = nameGetter(); | ||
var rightValue = rightValueGetter(); | ||
if (node.operator !== "=") { | ||
// if a is undefined | ||
// a += 1 | ||
_this16.assertVariable(data, name, node); | ||
} | ||
switch (node.operator) { | ||
case "=": | ||
return data[name] = rightValue; | ||
case "+=": | ||
return data[name] += rightValue; | ||
case "-=": | ||
return data[name] -= rightValue; | ||
case "*=": | ||
return data[name] *= rightValue; | ||
case "**=": | ||
return data[name] = Math.pow(data[name], rightValue); | ||
case "/=": | ||
return data[name] /= rightValue; | ||
case "%=": | ||
return data[name] %= rightValue; | ||
case "<<=": | ||
return data[name] <<= rightValue; | ||
case ">>=": | ||
return data[name] >>= rightValue; | ||
case ">>>=": | ||
return data[name] >>>= rightValue; | ||
case "&=": | ||
return data[name] &= rightValue; | ||
case "^=": | ||
return data[name] ^= rightValue; | ||
case "|=": | ||
return data[name] |= rightValue; | ||
default: | ||
throw _this16.createInternalThrowError(Messages.AssignmentExpressionSyntaxError, node.type, node); | ||
} | ||
}; | ||
} // function test(){} | ||
; | ||
_proto2.functionDeclarationHandler = function functionDeclarationHandler(node) { | ||
if (node.id) { | ||
var functionClosure = this.functionExpressionHandler(node); | ||
Object.defineProperty(functionClosure, "isFunctionDeclareClosure", { | ||
value: true, | ||
writable: false, | ||
configurable: false, | ||
enumerable: false | ||
}); | ||
this.funcDeclaration(node.id.name, functionClosure); | ||
// var i; | ||
// var i=1; | ||
variableDeclarationHandler(node) { | ||
let assignmentsClosure; | ||
const assignments = []; | ||
for (let i = 0; i < node.declarations.length; i++) { | ||
const decl = node.declarations[i]; | ||
this.varDeclaration(this.getVariableName(decl.id)); | ||
if (decl.init) { | ||
assignments.push({ | ||
type: "AssignmentExpression", | ||
operator: "=", | ||
left: decl.id, | ||
right: decl.init, | ||
}); | ||
} | ||
} | ||
if (assignments.length) { | ||
assignmentsClosure = this.createClosure({ | ||
type: "BlockStatement", | ||
body: assignments, | ||
}); | ||
} | ||
return () => { | ||
if (assignmentsClosure) { | ||
const oldValue = this.isVarDeclMode; | ||
this.isVarDeclMode = true; | ||
assignmentsClosure(); | ||
this.isVarDeclMode = oldValue; | ||
} | ||
return EmptyStatementReturn; | ||
}; | ||
} | ||
return function () { | ||
return EmptyStatementReturn; | ||
}; | ||
}; | ||
_proto2.getVariableName = function getVariableName(node) { | ||
if (node.type === "Identifier") { | ||
return node.name; | ||
} else { | ||
throw this.createInternalThrowError(Messages.VariableTypeSyntaxError, node.type, node); | ||
assertVariable(data, name, node) { | ||
if (data === this.globalScope.data && !(name in data)) { | ||
throw this.createInternalThrowError(Messages.VariableUndefinedReferenceError, name, node); | ||
} | ||
} | ||
} // var i; | ||
// var i=1; | ||
; | ||
_proto2.variableDeclarationHandler = function variableDeclarationHandler(node) { | ||
var _this17 = this; | ||
var assignmentsClosure; | ||
var assignments = []; | ||
for (var i = 0; i < node.declarations.length; i++) { | ||
var decl = node.declarations[i]; | ||
this.varDeclaration(this.getVariableName(decl.id)); | ||
if (decl.init) { | ||
assignments.push({ | ||
type: "AssignmentExpression", | ||
operator: "=", | ||
left: decl.id, | ||
right: decl.init | ||
// {...} | ||
programHandler(node) { | ||
// const currentScope = this.getCurrentScope(); | ||
const stmtClosures = node.body.map((stmt) => { | ||
// if (stmt.type === "EmptyStatement") return null; | ||
return this.createClosure(stmt); | ||
}); | ||
} | ||
return () => { | ||
let result = EmptyStatementReturn; | ||
for (let i = 0; i < stmtClosures.length; i++) { | ||
const stmtClosure = stmtClosures[i]; | ||
// save last value | ||
const ret = this.setValue(stmtClosure()); | ||
// if (!stmtClosure) continue; | ||
// EmptyStatement | ||
if (ret === EmptyStatementReturn) | ||
continue; | ||
result = ret; | ||
// BlockStatement: break label; continue label; for(){ break ... } | ||
// ReturnStatement: return xx; | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel || | ||
result === Break || | ||
result === Continue) { | ||
break; | ||
} | ||
} | ||
// save last value | ||
return result; | ||
}; | ||
} | ||
if (assignments.length) { | ||
assignmentsClosure = this.createClosure({ | ||
type: "BlockStatement", | ||
body: assignments | ||
}); | ||
// all expression: a+1 a&&b a() a.b ... | ||
expressionStatementHandler(node) { | ||
return this.createClosure(node.expression); | ||
} | ||
return function () { | ||
if (assignmentsClosure) { | ||
var oldValue = _this17.isVarDeclMode; | ||
_this17.isVarDeclMode = true; | ||
assignmentsClosure(); | ||
_this17.isVarDeclMode = oldValue; | ||
} | ||
return EmptyStatementReturn; | ||
}; | ||
}; | ||
_proto2.assertVariable = function assertVariable(data, name, node) { | ||
if (data === this.globalScope.data && !(name in data)) { | ||
throw this.createInternalThrowError(Messages.VariableUndefinedReferenceError, name, node); | ||
emptyStatementHandler(node) { | ||
return () => EmptyStatementReturn; | ||
} | ||
} // {...} | ||
; | ||
_proto2.programHandler = function programHandler(node) { | ||
var _this18 = this; | ||
// const currentScope = this.getCurrentScope(); | ||
var stmtClosures = node.body.map(function (stmt) { | ||
// if (stmt.type === "EmptyStatement") return null; | ||
return _this18.createClosure(stmt); | ||
}); | ||
return function () { | ||
var result = EmptyStatementReturn; | ||
for (var i = 0; i < stmtClosures.length; i++) { | ||
var stmtClosure = stmtClosures[i]; // save last value | ||
var ret = _this18.setValue(stmtClosure()); // if (!stmtClosure) continue; | ||
// EmptyStatement | ||
if (ret === EmptyStatementReturn) continue; | ||
result = ret; // BlockStatement: break label; continue label; for(){ break ... } | ||
// ReturnStatement: return xx; | ||
if (result instanceof Return || result instanceof BreakLabel || result instanceof ContinueLabel || result === Break || result === Continue) { | ||
break; | ||
// return xx; | ||
returnStatementHandler(node) { | ||
const argumentClosure = node.argument ? this.createClosure(node.argument) : noop; | ||
return () => new Return(argumentClosure()); | ||
} | ||
// if else | ||
ifStatementHandler(node) { | ||
const testClosure = this.createClosure(node.test); | ||
const consequentClosure = this.createClosure(node.consequent); | ||
const alternateClosure = node.alternate | ||
? this.createClosure(node.alternate) | ||
: /*!important*/ () => EmptyStatementReturn; | ||
return () => { | ||
return testClosure() ? consequentClosure() : alternateClosure(); | ||
}; | ||
} | ||
// test() ? true : false | ||
conditionalExpressionHandler(node) { | ||
return this.ifStatementHandler(node); | ||
} | ||
// for(var i = 0; i < 10; i++) {...} | ||
forStatementHandler(node) { | ||
let initClosure = noop; | ||
let testClosure = node.test ? this.createClosure(node.test) : () => true; | ||
let updateClosure = noop; | ||
const bodyClosure = this.createClosure(node.body); | ||
if (node.type === "ForStatement") { | ||
initClosure = node.init ? this.createClosure(node.init) : initClosure; | ||
updateClosure = node.update ? this.createClosure(node.update) : noop; | ||
} | ||
} // save last value | ||
return result; | ||
}; | ||
} // all expression: a+1 a&&b a() a.b ... | ||
; | ||
_proto2.expressionStatementHandler = function expressionStatementHandler(node) { | ||
return this.createClosure(node.expression); | ||
}; | ||
_proto2.emptyStatementHandler = function emptyStatementHandler(node) { | ||
return function () { | ||
return EmptyStatementReturn; | ||
}; | ||
} // return xx; | ||
; | ||
_proto2.returnStatementHandler = function returnStatementHandler(node) { | ||
var argumentClosure = node.argument ? this.createClosure(node.argument) : noop; | ||
return function () { | ||
return new Return(argumentClosure()); | ||
}; | ||
} // if else | ||
; | ||
_proto2.ifStatementHandler = function ifStatementHandler(node) { | ||
var testClosure = this.createClosure(node.test); | ||
var consequentClosure = this.createClosure(node.consequent); | ||
var alternateClosure = node.alternate ? this.createClosure(node.alternate) : | ||
/*!important*/ | ||
function () { | ||
return EmptyStatementReturn; | ||
}; | ||
return function () { | ||
return testClosure() ? consequentClosure() : alternateClosure(); | ||
}; | ||
} // test() ? true : false | ||
; | ||
_proto2.conditionalExpressionHandler = function conditionalExpressionHandler(node) { | ||
return this.ifStatementHandler(node); | ||
} // for(var i = 0; i < 10; i++) {...} | ||
; | ||
_proto2.forStatementHandler = function forStatementHandler(node) { | ||
var _this19 = this; | ||
var initClosure = noop; | ||
var testClosure = node.test ? this.createClosure(node.test) : function () { | ||
return true; | ||
}; | ||
var updateClosure = noop; | ||
var bodyClosure = this.createClosure(node.body); | ||
if (node.type === "ForStatement") { | ||
initClosure = node.init ? this.createClosure(node.init) : initClosure; | ||
updateClosure = node.update ? this.createClosure(node.update) : noop; | ||
return pNode => { | ||
let labelName; | ||
let result = EmptyStatementReturn; | ||
let shouldInitExec = node.type === "DoWhileStatement"; | ||
if (pNode && pNode.type === "LabeledStatement") { | ||
labelName = pNode.label.name; | ||
} | ||
for (initClosure(); shouldInitExec || testClosure(); updateClosure()) { | ||
shouldInitExec = false; | ||
// save last value | ||
const ret = this.setValue(bodyClosure()); | ||
// notice: never return Break or Continue! | ||
if (ret === EmptyStatementReturn || ret === Continue) | ||
continue; | ||
if (ret === Break) { | ||
break; | ||
} | ||
result = ret; | ||
// stop continue label | ||
if (result instanceof ContinueLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
continue; | ||
} | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel) { | ||
break; | ||
} | ||
} | ||
return result; | ||
}; | ||
} | ||
return function (pNode) { | ||
var labelName; | ||
var result = EmptyStatementReturn; | ||
var shouldInitExec = node.type === "DoWhileStatement"; | ||
if (pNode && pNode.type === "LabeledStatement") { | ||
labelName = pNode.label.name; | ||
} | ||
for (initClosure(); shouldInitExec || testClosure(); updateClosure()) { | ||
shouldInitExec = false; // save last value | ||
var ret = _this19.setValue(bodyClosure()); // notice: never return Break or Continue! | ||
if (ret === EmptyStatementReturn || ret === Continue) continue; | ||
if (ret === Break) { | ||
break; | ||
// while(1) {...} | ||
whileStatementHandler(node) { | ||
return this.forStatementHandler(node); | ||
} | ||
doWhileStatementHandler(node) { | ||
return this.forStatementHandler(node); | ||
} | ||
forInStatementHandler(node) { | ||
// for( k in obj) or for(o.k in obj) ... | ||
let left = node.left; | ||
const rightClosure = this.createClosure(node.right); | ||
const bodyClosure = this.createClosure(node.body); | ||
// for(var k in obj) {...} | ||
if (node.left.type === "VariableDeclaration") { | ||
// init var k | ||
this.createClosure(node.left)(); | ||
// reset left | ||
// for( k in obj) | ||
left = node.left.declarations[0].id; | ||
} | ||
result = ret; // stop continue label | ||
if (result instanceof ContinueLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
continue; | ||
return pNode => { | ||
let labelName; | ||
let result = EmptyStatementReturn; | ||
let x; | ||
if (pNode && pNode.type === "LabeledStatement") { | ||
labelName = pNode.label.name; | ||
} | ||
const data = rightClosure(); | ||
for (x in data) { | ||
// assign left to scope | ||
// k = x | ||
// o.k = x | ||
this.assignmentExpressionHandler({ | ||
type: "AssignmentExpression", | ||
operator: "=", | ||
left: left, | ||
right: { | ||
type: "Literal", | ||
value: x, | ||
}, | ||
})(); | ||
// save last value | ||
const ret = this.setValue(bodyClosure()); | ||
// notice: never return Break or Continue! | ||
if (ret === EmptyStatementReturn || ret === Continue) | ||
continue; | ||
if (ret === Break) { | ||
break; | ||
} | ||
result = ret; | ||
// stop continue label | ||
if (result instanceof ContinueLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
continue; | ||
} | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel) { | ||
break; | ||
} | ||
} | ||
return result; | ||
}; | ||
} | ||
withStatementHandler(node) { | ||
const objectClosure = this.createClosure(node.object); | ||
const bodyClosure = this.createClosure(node.body); | ||
return () => { | ||
const data = objectClosure(); | ||
const currentScope = this.getCurrentScope(); | ||
const newScope = new Scope(data, currentScope, WithScopeName); | ||
// const data = objectClosure(); | ||
// copy all properties | ||
// for (let k in data) { | ||
// newScope.data[k] = data[k]; | ||
// } | ||
this.setCurrentScope(newScope); | ||
// save last value | ||
const result = this.setValue(bodyClosure()); | ||
this.setCurrentScope(currentScope); | ||
return result; | ||
}; | ||
} | ||
throwStatementHandler(node) { | ||
const argumentClosure = this.createClosure(node.argument); | ||
return () => { | ||
this.setValue(undefined); | ||
throw argumentClosure(); | ||
}; | ||
} | ||
// try{...}catch(e){...}finally{} | ||
tryStatementHandler(node) { | ||
const blockClosure = this.createClosure(node.block); | ||
const handlerClosure = node.handler ? this.catchClauseHandler(node.handler) : null; | ||
const finalizerClosure = node.finalizer ? this.createClosure(node.finalizer) : null; | ||
return () => { | ||
const currentScope = this.getCurrentScope(); | ||
const currentContext = this.getCurrentContext(); | ||
const labelStack = currentScope.labelStack.concat([]); | ||
const callStack = this.callStack.concat([]); | ||
let result = EmptyStatementReturn; | ||
let finalReturn; | ||
let throwError; | ||
const reset = () => { | ||
this.setCurrentScope(currentScope); //reset scope | ||
this.setCurrentContext(currentContext); //reset context | ||
currentScope.labelStack = labelStack; //reset label stack | ||
this.callStack = callStack; //reset call stack | ||
}; | ||
/** | ||
* try{...}catch(e){...}finally{...} execution sequence: | ||
* try stmt | ||
* try throw | ||
* catch stmt (if) | ||
* finally stmt | ||
* | ||
* finally throw or finally return | ||
* catch throw or catch return | ||
* try return | ||
*/ | ||
try { | ||
result = this.setValue(blockClosure()); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
} | ||
} | ||
catch (err) { | ||
reset(); | ||
if (this.isInterruptThrow(err)) { | ||
throw err; | ||
} | ||
if (handlerClosure) { | ||
try { | ||
result = this.setValue(handlerClosure(err)); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
} | ||
} | ||
catch (err) { | ||
reset(); | ||
if (this.isInterruptThrow(err)) { | ||
throw err; | ||
} | ||
// save catch throw error | ||
throwError = err; | ||
} | ||
} | ||
} | ||
// finally { | ||
if (finalizerClosure) { | ||
try { | ||
//do not save finally result | ||
result = finalizerClosure(); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
} | ||
// finalReturn = finalizerClosure(); | ||
} | ||
catch (err) { | ||
reset(); | ||
if (this.isInterruptThrow(err)) { | ||
throw err; | ||
} | ||
// save finally throw error | ||
throwError = err; | ||
} | ||
// if (finalReturn instanceof Return) { | ||
// result = finalReturn; | ||
// } | ||
} | ||
// } | ||
if (throwError) | ||
throw throwError; | ||
if (finalReturn) { | ||
return finalReturn; | ||
} | ||
return result; | ||
}; | ||
} | ||
// ... catch(e){...} | ||
catchClauseHandler(node) { | ||
const paramNameGetter = this.createParamNameGetter(node.param); | ||
const bodyClosure = this.createClosure(node.body); | ||
return (e) => { | ||
let result; | ||
const currentScope = this.getCurrentScope(); | ||
const scopeData = currentScope.data; | ||
// get param name "e" | ||
const paramName = paramNameGetter(); | ||
const isInScope = hasOwnProperty.call(scopeData, paramName); //paramName in scopeData; | ||
// save "e" | ||
const oldValue = scopeData[paramName]; | ||
// add "e" to scope | ||
scopeData[paramName] = e; | ||
// run | ||
result = bodyClosure(); | ||
// reset "e" | ||
if (isInScope) { | ||
scopeData[paramName] = oldValue; | ||
} | ||
else { | ||
//unset | ||
delete scopeData[paramName]; | ||
} | ||
return result; | ||
}; | ||
} | ||
continueStatementHandler(node) { | ||
return () => (node.label ? new ContinueLabel(node.label.name) : Continue); | ||
} | ||
breakStatementHandler(node) { | ||
return () => (node.label ? new BreakLabel(node.label.name) : Break); | ||
} | ||
switchStatementHandler(node) { | ||
const discriminantClosure = this.createClosure(node.discriminant); | ||
const caseClosures = node.cases.map(item => this.switchCaseHandler(item)); | ||
return () => { | ||
const value = discriminantClosure(); | ||
let match = false; | ||
let result; | ||
let ret, start = 0, hasDefaultCase = false; | ||
for (let j = 0; j < 2; j++) { | ||
for (let i = start; i < caseClosures.length; i++) { | ||
const item = caseClosures[i](); | ||
const test = item.testClosure(); | ||
if (!hasDefaultCase && test === DefaultCase) { | ||
hasDefaultCase = true; | ||
start = i; | ||
} | ||
if (match || test === value) { | ||
match = true; | ||
ret = this.setValue(item.bodyClosure()); | ||
// notice: never return Break! | ||
if (ret === EmptyStatementReturn) | ||
continue; | ||
if (ret === Break) { | ||
break; | ||
} | ||
result = ret; | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel || | ||
result === Continue) { | ||
break; | ||
} | ||
} | ||
} | ||
if (!match && hasDefaultCase) { | ||
match = true; | ||
} | ||
else { | ||
break; | ||
} | ||
} | ||
return result; | ||
}; | ||
} | ||
switchCaseHandler(node) { | ||
const testClosure = node.test ? this.createClosure(node.test) : () => DefaultCase; | ||
const bodyClosure = this.createClosure({ | ||
type: "BlockStatement", | ||
body: node.consequent, | ||
}); | ||
return () => ({ | ||
testClosure, | ||
bodyClosure, | ||
}); | ||
} | ||
// label: xxx | ||
labeledStatementHandler(node) { | ||
const labelName = node.label.name; | ||
const bodyClosure = this.createClosure(node.body); | ||
return () => { | ||
let result; | ||
const currentScope = this.getCurrentScope(); | ||
currentScope.labelStack.push(labelName); | ||
result = bodyClosure(node); | ||
// stop break label | ||
if (result instanceof BreakLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
} | ||
currentScope.labelStack.pop(); | ||
return result; | ||
}; | ||
} | ||
debuggerStatementHandler(node) { | ||
return () => { | ||
debugger; | ||
return EmptyStatementReturn; | ||
}; | ||
} | ||
// get es3/5 param name | ||
createParamNameGetter(node) { | ||
if (node.type === "Identifier") { | ||
return () => node.name; | ||
} | ||
if (result instanceof Return || result instanceof BreakLabel || result instanceof ContinueLabel) { | ||
break; | ||
else { | ||
throw this.createInternalThrowError(Messages.ParamTypeSyntaxError, node.type, node); | ||
} | ||
} | ||
return result; | ||
}; | ||
} // while(1) {...} | ||
; | ||
_proto2.whileStatementHandler = function whileStatementHandler(node) { | ||
return this.forStatementHandler(node); | ||
}; | ||
_proto2.doWhileStatementHandler = function doWhileStatementHandler(node) { | ||
return this.forStatementHandler(node); | ||
}; | ||
_proto2.forInStatementHandler = function forInStatementHandler(node) { | ||
var _this20 = this; | ||
// for( k in obj) or for(o.k in obj) ... | ||
var left = node.left; | ||
var rightClosure = this.createClosure(node.right); | ||
var bodyClosure = this.createClosure(node.body); // for(var k in obj) {...} | ||
if (node.left.type === "VariableDeclaration") { | ||
// init var k | ||
this.createClosure(node.left)(); // reset left | ||
// for( k in obj) | ||
left = node.left.declarations[0].id; | ||
} | ||
return function (pNode) { | ||
var labelName; | ||
var result = EmptyStatementReturn; | ||
var x; | ||
if (pNode && pNode.type === "LabeledStatement") { | ||
labelName = pNode.label.name; | ||
} | ||
var data = rightClosure(); | ||
for (x in data) { | ||
// assign left to scope | ||
// k = x | ||
// o.k = x | ||
_this20.assignmentExpressionHandler({ | ||
type: "AssignmentExpression", | ||
operator: "=", | ||
left: left, | ||
right: { | ||
type: "Literal", | ||
value: x | ||
} | ||
})(); // save last value | ||
var ret = _this20.setValue(bodyClosure()); // notice: never return Break or Continue! | ||
if (ret === EmptyStatementReturn || ret === Continue) continue; | ||
if (ret === Break) { | ||
break; | ||
createObjectKeyGetter(node) { | ||
let getter; | ||
// var obj = { title: "" } | ||
if (node.type === "Identifier") { | ||
getter = () => node.name; | ||
} | ||
result = ret; // stop continue label | ||
if (result instanceof ContinueLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
continue; | ||
else { | ||
// Literal or ... | ||
// var obj = { "title": "" } or others... | ||
getter = this.createClosure(node); | ||
} | ||
if (result instanceof Return || result instanceof BreakLabel || result instanceof ContinueLabel) { | ||
break; | ||
return function () { | ||
return getter(); | ||
}; | ||
} | ||
createMemberKeyGetter(node) { | ||
// s['a']; node.computed = true | ||
// s.foo; node.computed = false | ||
return node.computed | ||
? this.createClosure(node.property) | ||
: this.createObjectKeyGetter(node.property); | ||
} | ||
// for UnaryExpression UpdateExpression AssignmentExpression | ||
createObjectGetter(node) { | ||
switch (node.type) { | ||
case "Identifier": | ||
return () => this.getScopeDataFromName(node.name, this.getCurrentScope()); | ||
case "MemberExpression": | ||
return this.createClosure(node.object); | ||
default: | ||
throw this.createInternalThrowError(Messages.AssignmentTypeSyntaxError, node.type, node); | ||
} | ||
} | ||
return result; | ||
}; | ||
}; | ||
_proto2.withStatementHandler = function withStatementHandler(node) { | ||
var _this21 = this; | ||
var objectClosure = this.createClosure(node.object); | ||
var bodyClosure = this.createClosure(node.body); | ||
return function () { | ||
var data = objectClosure(); | ||
var currentScope = _this21.getCurrentScope(); | ||
var newScope = new Scope(data, currentScope, WithScopeName); // const data = objectClosure(); | ||
// copy all properties | ||
// for (let k in data) { | ||
// newScope.data[k] = data[k]; | ||
// } | ||
_this21.setCurrentScope(newScope); // save last value | ||
var result = _this21.setValue(bodyClosure()); | ||
_this21.setCurrentScope(currentScope); | ||
return result; | ||
}; | ||
}; | ||
_proto2.throwStatementHandler = function throwStatementHandler(node) { | ||
var _this22 = this; | ||
var argumentClosure = this.createClosure(node.argument); | ||
return function () { | ||
_this22.setValue(undefined); | ||
throw argumentClosure(); | ||
}; | ||
} // try{...}catch(e){...}finally{} | ||
; | ||
_proto2.tryStatementHandler = function tryStatementHandler(node) { | ||
var _this23 = this; | ||
var blockClosure = this.createClosure(node.block); | ||
var handlerClosure = node.handler ? this.catchClauseHandler(node.handler) : null; | ||
var finalizerClosure = node.finalizer ? this.createClosure(node.finalizer) : null; | ||
return function () { | ||
var currentScope = _this23.getCurrentScope(); | ||
var currentContext = _this23.getCurrentContext(); | ||
var labelStack = currentScope.labelStack.concat([]); | ||
var callStack = _this23.callStack.concat([]); | ||
var result = EmptyStatementReturn; | ||
var finalReturn; | ||
var throwError; | ||
var reset = function reset() { | ||
_this23.setCurrentScope(currentScope); //reset scope | ||
_this23.setCurrentContext(currentContext); //reset context | ||
currentScope.labelStack = labelStack; //reset label stack | ||
_this23.callStack = callStack; //reset call stack | ||
}; | ||
/** | ||
* try{...}catch(e){...}finally{...} execution sequence: | ||
* try stmt | ||
* try throw | ||
* catch stmt (if) | ||
* finally stmt | ||
* | ||
* finally throw or finally return | ||
* catch throw or catch return | ||
* try return | ||
*/ | ||
try { | ||
result = _this23.setValue(blockClosure()); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
} | ||
// for UnaryExpression UpdateExpression AssignmentExpression | ||
createNameGetter(node) { | ||
switch (node.type) { | ||
case "Identifier": | ||
return () => node.name; | ||
case "MemberExpression": | ||
return this.createMemberKeyGetter(node); | ||
default: | ||
throw this.createInternalThrowError(Messages.AssignmentTypeSyntaxError, node.type, node); | ||
} | ||
} catch (err) { | ||
reset(); | ||
if (_this23.isInterruptThrow(err)) { | ||
throw err; | ||
} | ||
varDeclaration(name) { | ||
const context = this.collectDeclVars; | ||
context[name] = undefined; | ||
} | ||
funcDeclaration(name, func) { | ||
const context = this.collectDeclFuncs; | ||
context[name] = func; | ||
} | ||
addDeclarationsToScope(declVars, declFuncs, scope) { | ||
const scopeData = scope.data; | ||
for (let key in declFuncs) { | ||
const value = declFuncs[key]; | ||
scopeData[key] = value ? value() : value; | ||
} | ||
if (handlerClosure) { | ||
try { | ||
result = _this23.setValue(handlerClosure(err)); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
for (let key in declVars) { | ||
if (!(key in scopeData)) { | ||
scopeData[key] = void 0; | ||
} | ||
} catch (err) { | ||
reset(); | ||
if (_this23.isInterruptThrow(err)) { | ||
throw err; | ||
} // save catch throw error | ||
throwError = err; | ||
} | ||
} | ||
} // finally { | ||
if (finalizerClosure) { | ||
try { | ||
//do not save finally result | ||
result = finalizerClosure(); | ||
if (result instanceof Return) { | ||
finalReturn = result; | ||
} // finalReturn = finalizerClosure(); | ||
} catch (err) { | ||
reset(); | ||
if (_this23.isInterruptThrow(err)) { | ||
throw err; | ||
} // save finally throw error | ||
throwError = err; | ||
} // if (finalReturn instanceof Return) { | ||
// result = finalReturn; | ||
// } | ||
} // } | ||
if (throwError) throw throwError; | ||
if (finalReturn) { | ||
return finalReturn; | ||
} | ||
return result; | ||
}; | ||
} // ... catch(e){...} | ||
; | ||
_proto2.catchClauseHandler = function catchClauseHandler(node) { | ||
var _this24 = this; | ||
var paramNameGetter = this.createParamNameGetter(node.param); | ||
var bodyClosure = this.createClosure(node.body); | ||
return function (e) { | ||
var result; | ||
var currentScope = _this24.getCurrentScope(); | ||
var scopeData = currentScope.data; // get param name "e" | ||
var paramName = paramNameGetter(); | ||
var isInScope = hasOwnProperty.call(scopeData, paramName); //paramName in scopeData; | ||
// save "e" | ||
var oldValue = scopeData[paramName]; // add "e" to scope | ||
scopeData[paramName] = e; // run | ||
result = bodyClosure(); // reset "e" | ||
if (isInScope) { | ||
scopeData[paramName] = oldValue; | ||
} else { | ||
//unset | ||
delete scopeData[paramName]; | ||
} | ||
return result; | ||
}; | ||
}; | ||
_proto2.continueStatementHandler = function continueStatementHandler(node) { | ||
return function () { | ||
return node.label ? new ContinueLabel(node.label.name) : Continue; | ||
}; | ||
}; | ||
_proto2.breakStatementHandler = function breakStatementHandler(node) { | ||
return function () { | ||
return node.label ? new BreakLabel(node.label.name) : Break; | ||
}; | ||
}; | ||
_proto2.switchStatementHandler = function switchStatementHandler(node) { | ||
var _this25 = this; | ||
var discriminantClosure = this.createClosure(node.discriminant); | ||
var caseClosures = node.cases.map(function (item) { | ||
return _this25.switchCaseHandler(item); | ||
}); | ||
return function () { | ||
var value = discriminantClosure(); | ||
var match = false; | ||
var result; | ||
var ret, defaultCase; | ||
for (var i = 0; i < caseClosures.length; i++) { | ||
var item = caseClosures[i](); | ||
var test = item.testClosure(); | ||
if (test === DefaultCase) { | ||
defaultCase = item; | ||
continue; | ||
} | ||
if (match || test === value) { | ||
match = true; | ||
ret = _this25.setValue(item.bodyClosure()); // notice: never return Break! | ||
if (ret === EmptyStatementReturn) continue; | ||
if (ret === Break) { | ||
break; | ||
} | ||
result = ret; | ||
if (result instanceof Return || result instanceof BreakLabel || result instanceof ContinueLabel || result === Continue) { | ||
break; | ||
} | ||
} | ||
} | ||
if (!match && defaultCase) { | ||
ret = _this25.setValue(defaultCase.bodyClosure()); | ||
var isEBC = ret === EmptyStatementReturn || ret === Break; // notice: never return Break or Continue! | ||
if (!isEBC) { | ||
result = ret; | ||
} | ||
} | ||
return result; | ||
}; | ||
}; | ||
_proto2.switchCaseHandler = function switchCaseHandler(node) { | ||
var testClosure = node.test ? this.createClosure(node.test) : function () { | ||
return DefaultCase; | ||
}; | ||
var bodyClosure = this.createClosure({ | ||
type: "BlockStatement", | ||
body: node.consequent | ||
}); | ||
return function () { | ||
return { | ||
testClosure: testClosure, | ||
bodyClosure: bodyClosure | ||
}; | ||
}; | ||
} // label: xxx | ||
; | ||
_proto2.labeledStatementHandler = function labeledStatementHandler(node) { | ||
var _this26 = this; | ||
var labelName = node.label.name; | ||
var bodyClosure = this.createClosure(node.body); | ||
return function () { | ||
var result; | ||
var currentScope = _this26.getCurrentScope(); | ||
currentScope.labelStack.push(labelName); | ||
result = bodyClosure(node); // stop break label | ||
if (result instanceof BreakLabel && result.value === labelName) { | ||
result = EmptyStatementReturn; | ||
} | ||
currentScope.labelStack.pop(); | ||
return result; | ||
}; | ||
}; | ||
_proto2.debuggerStatementHandler = function debuggerStatementHandler(node) { | ||
return function () { | ||
debugger; | ||
return EmptyStatementReturn; | ||
}; | ||
} // get es3/5 param name | ||
; | ||
_proto2.createParamNameGetter = function createParamNameGetter(node) { | ||
if (node.type === "Identifier") { | ||
return function () { | ||
return node.name; | ||
}; | ||
} else { | ||
throw this.createInternalThrowError(Messages.ParamTypeSyntaxError, node.type, node); | ||
} | ||
}; | ||
_proto2.createObjectKeyGetter = function createObjectKeyGetter(node) { | ||
var getter; // var obj = { title: "" } | ||
if (node.type === "Identifier") { | ||
getter = function getter() { | ||
return node.name; | ||
}; | ||
} else { | ||
// Literal or ... | ||
// var obj = { "title": "" } or others... | ||
getter = this.createClosure(node); | ||
getScopeValue(name, startScope) { | ||
const scope = this.getScopeFromName(name, startScope); | ||
return scope.data[name]; | ||
} | ||
return function () { | ||
return getter(); | ||
}; | ||
}; | ||
_proto2.createMemberKeyGetter = function createMemberKeyGetter(node) { | ||
// s['a']; node.computed = true | ||
// s.foo; node.computed = false | ||
return node.computed ? this.createClosure(node.property) : this.createObjectKeyGetter(node.property); | ||
} // for UnaryExpression UpdateExpression AssignmentExpression | ||
; | ||
_proto2.createObjectGetter = function createObjectGetter(node) { | ||
var _this27 = this; | ||
switch (node.type) { | ||
case "Identifier": | ||
return function () { | ||
return _this27.getScopeDataFromName(node.name, _this27.getCurrentScope()); | ||
}; | ||
case "MemberExpression": | ||
return this.createClosure(node.object); | ||
default: | ||
throw this.createInternalThrowError(Messages.AssignmentTypeSyntaxError, node.type, node); | ||
getScopeDataFromName(name, startScope) { | ||
return this.getScopeFromName(name, startScope).data; | ||
} | ||
} // for UnaryExpression UpdateExpression AssignmentExpression | ||
; | ||
_proto2.createNameGetter = function createNameGetter(node) { | ||
switch (node.type) { | ||
case "Identifier": | ||
return function () { | ||
return node.name; | ||
}; | ||
case "MemberExpression": | ||
return this.createMemberKeyGetter(node); | ||
default: | ||
throw this.createInternalThrowError(Messages.AssignmentTypeSyntaxError, node.type, node); | ||
getScopeFromName(name, startScope) { | ||
let scope = startScope; | ||
do { | ||
if (name in scope.data) { | ||
//if (hasOwnProperty.call(scope.data, name)) { | ||
return scope; | ||
} | ||
} while ((scope = scope.parent)); | ||
return this.globalScope; | ||
} | ||
}; | ||
_proto2.varDeclaration = function varDeclaration(name) { | ||
var context = this.collectDeclVars; | ||
context[name] = undefined; | ||
}; | ||
_proto2.funcDeclaration = function funcDeclaration(name, func) { | ||
var context = this.collectDeclFuncs; | ||
context[name] = func; | ||
}; | ||
_proto2.addDeclarationsToScope = function addDeclarationsToScope(declVars, declFuncs, scope) { | ||
var scopeData = scope.data; | ||
for (var key in declFuncs) { | ||
var value = declFuncs[key]; | ||
scopeData[key] = value ? value() : value; | ||
setValue(value) { | ||
const isFunctionCall = this.callStack.length; | ||
if (this.isVarDeclMode || | ||
isFunctionCall || | ||
value === EmptyStatementReturn || | ||
value === Break || | ||
value === Continue || | ||
value instanceof BreakLabel || | ||
value instanceof ContinueLabel) { | ||
return value; | ||
} | ||
this.value = value instanceof Return ? value.value : value; | ||
return value; | ||
} | ||
for (var _key5 in declVars) { | ||
if (!(_key5 in scopeData)) { | ||
scopeData[_key5] = void 0; | ||
} | ||
getValue() { | ||
return this.value; | ||
} | ||
}; | ||
_proto2.getScopeValue = function getScopeValue(name, startScope) { | ||
var scope = this.getScopeFromName(name, startScope); | ||
return scope.data[name]; | ||
}; | ||
_proto2.getScopeDataFromName = function getScopeDataFromName(name, startScope) { | ||
return this.getScopeFromName(name, startScope).data; | ||
}; | ||
_proto2.getScopeFromName = function getScopeFromName(name, startScope) { | ||
var scope = startScope; | ||
do { | ||
if (name in scope.data) { | ||
//if (hasOwnProperty.call(scope.data, name)) { | ||
return scope; | ||
} | ||
} while (scope = scope.parent); | ||
return this.globalScope; | ||
}; | ||
_proto2.setValue = function setValue(value) { | ||
var isFunctionCall = this.callStack.length; | ||
if (this.isVarDeclMode || isFunctionCall || value === EmptyStatementReturn || value === Break || value === Continue || value instanceof BreakLabel || value instanceof ContinueLabel) { | ||
return value; | ||
} | ||
this.value = value instanceof Return ? value.value : value; | ||
return value; | ||
}; | ||
_proto2.getValue = function getValue() { | ||
return this.value; | ||
}; | ||
return Interpreter; | ||
}(); | ||
} | ||
Interpreter.version = version; | ||
Interpreter.eval = internalEval; | ||
Interpreter.Function = internalFunction; | ||
Interpreter.ecmaVersion = 5; // alert.call(globalContextInFunction, 1); | ||
Interpreter.ecmaVersion = 5; | ||
// alert.call(globalContextInFunction, 1); | ||
// fix: alert.call({}, 1); // Illegal invocation | ||
@@ -2075,4 +1623,3 @@ // function func(){ | ||
// func() | ||
Interpreter.globalContextInFunction = void 0; | ||
Interpreter.global = Object.create(null); | ||
Interpreter.global = Object.create(null); |
@@ -1,108 +0,43 @@ | ||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } | ||
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } | ||
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | ||
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } | ||
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
export var ThrowError = | ||
/*#__PURE__*/ | ||
function (_Error) { | ||
_inheritsLoose(ThrowError, _Error); | ||
function ThrowError() { | ||
return _Error.apply(this, arguments) || this; | ||
} | ||
return ThrowError; | ||
}(_wrapNativeSuper(Error)); | ||
export var ThrowSyntaxError = | ||
/*#__PURE__*/ | ||
function (_SyntaxError) { | ||
_inheritsLoose(ThrowSyntaxError, _SyntaxError); | ||
function ThrowSyntaxError() { | ||
return _SyntaxError.apply(this, arguments) || this; | ||
} | ||
return ThrowSyntaxError; | ||
}(_wrapNativeSuper(SyntaxError)); | ||
export var ThrowReferenceError = | ||
/*#__PURE__*/ | ||
function (_ReferenceError) { | ||
_inheritsLoose(ThrowReferenceError, _ReferenceError); | ||
function ThrowReferenceError() { | ||
return _ReferenceError.apply(this, arguments) || this; | ||
} | ||
return ThrowReferenceError; | ||
}(_wrapNativeSuper(ReferenceError)); | ||
export var ThrowTypeError = | ||
/*#__PURE__*/ | ||
function (_TypeError) { | ||
_inheritsLoose(ThrowTypeError, _TypeError); | ||
function ThrowTypeError() { | ||
return _TypeError.apply(this, arguments) || this; | ||
} | ||
return ThrowTypeError; | ||
}(_wrapNativeSuper(TypeError)); | ||
export var InterruptThrowError = | ||
/*#__PURE__*/ | ||
function (_ThrowError) { | ||
_inheritsLoose(InterruptThrowError, _ThrowError); | ||
function InterruptThrowError() { | ||
return _ThrowError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowError; | ||
}(ThrowError); | ||
export var InterruptThrowSyntaxError = | ||
/*#__PURE__*/ | ||
function (_ThrowSyntaxError) { | ||
_inheritsLoose(InterruptThrowSyntaxError, _ThrowSyntaxError); | ||
function InterruptThrowSyntaxError() { | ||
return _ThrowSyntaxError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowSyntaxError; | ||
}(ThrowSyntaxError); | ||
export var InterruptThrowReferenceError = | ||
/*#__PURE__*/ | ||
function (_ThrowReferenceError) { | ||
_inheritsLoose(InterruptThrowReferenceError, _ThrowReferenceError); | ||
function InterruptThrowReferenceError() { | ||
return _ThrowReferenceError.apply(this, arguments) || this; | ||
} | ||
return InterruptThrowReferenceError; | ||
}(ThrowReferenceError); | ||
export var Messages = { | ||
UnknownError: [3001, "%0", InterruptThrowError], | ||
ExecutionTimeOutError: [3002, "Script execution timed out after %0ms", InterruptThrowError], | ||
NodeTypeSyntaxError: [1001, "Unknown node type: %0", InterruptThrowReferenceError], | ||
BinaryOperatorSyntaxError: [1002, "Unknown binary operator: %0", InterruptThrowReferenceError], | ||
LogicalOperatorSyntaxError: [1003, "Unknown logical operator: %0", InterruptThrowReferenceError], | ||
UnaryOperatorSyntaxError: [1004, "Unknown unary operator: %0", InterruptThrowReferenceError], | ||
UpdateOperatorSyntaxError: [1005, "Unknown update operator: %0", InterruptThrowReferenceError], | ||
ObjectStructureSyntaxError: [1006, "Unknown object structure: %0", InterruptThrowReferenceError], | ||
AssignmentExpressionSyntaxError: [1007, "Unknown assignment expression: %0", InterruptThrowReferenceError], | ||
VariableTypeSyntaxError: [1008, "Unknown variable type: %0", InterruptThrowReferenceError], | ||
ParamTypeSyntaxError: [1009, "Unknown param type: %0", InterruptThrowReferenceError], | ||
AssignmentTypeSyntaxError: [1010, "Unknown assignment type: %0", InterruptThrowReferenceError], | ||
FunctionUndefinedReferenceError: [2001, "%0 is not a function", ThrowReferenceError], | ||
VariableUndefinedReferenceError: [2002, "%0 is not defined", ThrowReferenceError], | ||
IsNotConstructor: [2003, "%0 is not a constructor", ThrowTypeError] | ||
}; | ||
export class ThrowError extends Error { | ||
} | ||
export class ThrowSyntaxError extends SyntaxError { | ||
} | ||
export class ThrowReferenceError extends ReferenceError { | ||
} | ||
export class ThrowTypeError extends TypeError { | ||
} | ||
export class InterruptThrowError extends ThrowError { | ||
} | ||
export class InterruptThrowSyntaxError extends ThrowSyntaxError { | ||
} | ||
export class InterruptThrowReferenceError extends ThrowReferenceError { | ||
} | ||
export const Messages = { | ||
UnknownError: [3001, "%0", InterruptThrowError], | ||
ExecutionTimeOutError: [3002, "Script execution timed out after %0ms", InterruptThrowError], | ||
NodeTypeSyntaxError: [1001, "Unknown node type: %0", InterruptThrowReferenceError], | ||
BinaryOperatorSyntaxError: [1002, "Unknown binary operator: %0", InterruptThrowReferenceError], | ||
LogicalOperatorSyntaxError: [ | ||
1003, | ||
"Unknown logical operator: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
UnaryOperatorSyntaxError: [1004, "Unknown unary operator: %0", InterruptThrowReferenceError], | ||
UpdateOperatorSyntaxError: [1005, "Unknown update operator: %0", InterruptThrowReferenceError], | ||
ObjectStructureSyntaxError: [ | ||
1006, | ||
"Unknown object structure: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
AssignmentExpressionSyntaxError: [ | ||
1007, | ||
"Unknown assignment expression: %0", | ||
InterruptThrowReferenceError, | ||
], | ||
VariableTypeSyntaxError: [1008, "Unknown variable type: %0", InterruptThrowReferenceError], | ||
ParamTypeSyntaxError: [1009, "Unknown param type: %0", InterruptThrowReferenceError], | ||
AssignmentTypeSyntaxError: [1010, "Unknown assignment type: %0", InterruptThrowReferenceError], | ||
FunctionUndefinedReferenceError: [2001, "%0 is not a function", ThrowReferenceError], | ||
VariableUndefinedReferenceError: [2002, "%0 is not defined", ThrowReferenceError], | ||
IsNotConstructor: [2003, "%0 is not a constructor", ThrowTypeError], | ||
}; |
import * as ESTree from "estree"; | ||
export { ESTree }; | ||
export { ESTree }; |
@@ -1,57 +0,38 @@ | ||
import { Interpreter } from "./interpreter/main"; // TODO: | ||
import { Interpreter } from "./interpreter/main"; | ||
// TODO: | ||
// add tests | ||
export function createContext(ctx) { | ||
if (ctx === void 0) { | ||
ctx = Object.create(null); | ||
} | ||
return ctx; | ||
export function createContext(ctx = Object.create(null)) { | ||
return ctx; | ||
} | ||
export function compileFunction(code, params, options) { | ||
if (params === void 0) { | ||
params = []; | ||
} | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var ctx = options.parsingContext; | ||
var timeout = options.timeout === undefined ? 0 : options.timeout; | ||
var wrapCode = "\n (function anonymous(" + params.join(",") + "){\n " + code + "\n });\n "; | ||
var interpreter = new Interpreter(ctx, { | ||
ecmaVersion: options.ecmaVersion, | ||
timeout: timeout, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction | ||
}); | ||
return interpreter.evaluate(wrapCode); | ||
export function compileFunction(code, params = [], options = {}) { | ||
const ctx = options.parsingContext; | ||
const timeout = options.timeout === undefined ? 0 : options.timeout; | ||
const wrapCode = ` | ||
(function anonymous(${params.join(",")}){ | ||
${code} | ||
}); | ||
`; | ||
const interpreter = new Interpreter(ctx, { | ||
ecmaVersion: options.ecmaVersion, | ||
timeout, | ||
rootContext: options.rootContext, | ||
globalContextInFunction: options.globalContextInFunction, | ||
}); | ||
return interpreter.evaluate(wrapCode); | ||
} | ||
function _runInContext(code, ctx, options) { | ||
var interpreter = new Interpreter(ctx, options); | ||
return interpreter.evaluate(code); | ||
export function runInContext(code, ctx, options) { | ||
const interpreter = new Interpreter(ctx, options); | ||
return interpreter.evaluate(code); | ||
} | ||
export { _runInContext as runInContext }; | ||
export var runInNewContext = _runInContext; | ||
export var Script = | ||
/*#__PURE__*/ | ||
function () { | ||
function Script(code) { | ||
this._code = code; | ||
} | ||
var _proto = Script.prototype; | ||
_proto.runInContext = function runInContext(ctx) { | ||
return _runInContext(this._code, ctx); | ||
}; | ||
_proto.runInNewContext = function runInNewContext(ctx) { | ||
return _runInContext(this._code, ctx); | ||
}; | ||
return Script; | ||
}(); | ||
export const runInNewContext = runInContext; | ||
export class Script { | ||
constructor(code) { | ||
this._code = code; | ||
} | ||
runInContext(ctx) { | ||
return runInContext(this._code, ctx); | ||
} | ||
runInNewContext(ctx) { | ||
return runInContext(this._code, ctx); | ||
} | ||
} |
import { VMContext, ScriptOptions } from "./types"; | ||
declare const _default: (code: string, ctx?: VMContext | undefined, options?: ScriptOptions | undefined) => any; | ||
declare const _default: (code: string, ctx?: VMContext, options?: ScriptOptions) => any; | ||
export default _default; |
@@ -0,0 +0,0 @@ import { runInContext } from "./vm"; |
export default function (...args: string[]): (...args: string[]) => any; |
@@ -0,0 +0,0 @@ import { compileFunction } from "./vm"; |
@@ -0,0 +0,0 @@ import { Interpreter } from "./interpreter/main"; |
@@ -0,0 +0,0 @@ import { Interpreter } from "./interpreter/main"; |
import { MessageItem } from "./messages"; | ||
import { Node, ESTree } from "./nodes"; | ||
declare type Getter = () => any; | ||
type Getter = () => any; | ||
interface BaseClosure { | ||
@@ -8,9 +8,9 @@ (pNode?: Node): any; | ||
} | ||
declare type CaseItem = { | ||
type CaseItem = { | ||
testClosure: BaseClosure; | ||
bodyClosure: BaseClosure; | ||
}; | ||
declare type SwitchCaseClosure = () => CaseItem; | ||
declare type ReturnStringClosure = () => string; | ||
declare type ECMA_VERSION = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020; | ||
type SwitchCaseClosure = () => CaseItem; | ||
type ReturnStringClosure = () => string; | ||
type ECMA_VERSION = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020; | ||
interface Options { | ||
@@ -26,7 +26,7 @@ ecmaVersion?: ECMA_VERSION; | ||
} | ||
declare type ScopeData = { | ||
type ScopeData = { | ||
[prop: string]: any; | ||
[prop: number]: any; | ||
}; | ||
declare type Context = { | ||
type Context = { | ||
[prop: string]: any; | ||
@@ -33,0 +33,0 @@ [prop: number]: any; |
@@ -25,2 +25,3 @@ import { parse } from "acorn"; | ||
class InternalInterpreterReflection { | ||
interpreter; | ||
constructor(interpreter) { | ||
@@ -102,2 +103,3 @@ this.interpreter = interpreter; | ||
class Return { | ||
value; | ||
constructor(value) { | ||
@@ -108,2 +110,3 @@ this.value = value; | ||
class BreakLabel { | ||
value; | ||
constructor(value) { | ||
@@ -114,2 +117,3 @@ this.value = value; | ||
class ContinueLabel { | ||
value; | ||
constructor(value) { | ||
@@ -132,2 +136,6 @@ this.value = value; | ||
class Scope { | ||
name; | ||
parent; | ||
data; | ||
labelStack; | ||
constructor(data, parent = null, name) { | ||
@@ -209,9 +217,33 @@ this.name = name; | ||
export class Interpreter { | ||
static version = version; | ||
static eval = internalEval; | ||
static Function = internalFunction; | ||
static ecmaVersion = 5; | ||
// alert.call(globalContextInFunction, 1); | ||
// fix: alert.call({}, 1); // Illegal invocation | ||
// function func(){ | ||
// this;// Interpreter.globalContextInFunction | ||
// } | ||
// func() | ||
static globalContextInFunction = void 0; | ||
static global = Object.create(null); | ||
// last expression value | ||
value; | ||
context; | ||
globalContext; | ||
source; | ||
sourceList = []; | ||
currentScope; | ||
globalScope; | ||
currentContext; | ||
options; | ||
callStack; | ||
collectDeclVars = Object.create(null); | ||
collectDeclFuncs = Object.create(null); | ||
isVarDeclMode = false; | ||
lastExecNode = null; | ||
isRunning = false; | ||
execStartTime; | ||
execEndTime; | ||
constructor(context = Interpreter.global, options = {}) { | ||
this.sourceList = []; | ||
this.collectDeclVars = Object.create(null); | ||
this.collectDeclFuncs = Object.create(null); | ||
this.isVarDeclMode = false; | ||
this.lastExecNode = null; | ||
this.isRunning = false; | ||
this.options = { | ||
@@ -1441,35 +1473,35 @@ ecmaVersion: options.ecmaVersion || Interpreter.ecmaVersion, | ||
let result; | ||
let ret, defaultCase; | ||
for (let i = 0; i < caseClosures.length; i++) { | ||
const item = caseClosures[i](); | ||
const test = item.testClosure(); | ||
if (test === DefaultCase) { | ||
defaultCase = item; | ||
continue; | ||
} | ||
if (match || test === value) { | ||
match = true; | ||
ret = this.setValue(item.bodyClosure()); | ||
// notice: never return Break! | ||
if (ret === EmptyStatementReturn) | ||
continue; | ||
if (ret === Break) { | ||
break; | ||
let ret, start = 0, hasDefaultCase = false; | ||
for (let j = 0; j < 2; j++) { | ||
for (let i = start; i < caseClosures.length; i++) { | ||
const item = caseClosures[i](); | ||
const test = item.testClosure(); | ||
if (!hasDefaultCase && test === DefaultCase) { | ||
hasDefaultCase = true; | ||
start = i; | ||
} | ||
result = ret; | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel || | ||
result === Continue) { | ||
break; | ||
if (match || test === value) { | ||
match = true; | ||
ret = this.setValue(item.bodyClosure()); | ||
// notice: never return Break! | ||
if (ret === EmptyStatementReturn) | ||
continue; | ||
if (ret === Break) { | ||
break; | ||
} | ||
result = ret; | ||
if (result instanceof Return || | ||
result instanceof BreakLabel || | ||
result instanceof ContinueLabel || | ||
result === Continue) { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
if (!match && defaultCase) { | ||
ret = this.setValue(defaultCase.bodyClosure()); | ||
const isEBC = ret === EmptyStatementReturn || ret === Break; | ||
// notice: never return Break or Continue! | ||
if (!isEBC) { | ||
result = ret; | ||
if (!match && hasDefaultCase) { | ||
match = true; | ||
} | ||
else { | ||
break; | ||
} | ||
} | ||
@@ -1621,13 +1653,1 @@ return result; | ||
} | ||
Interpreter.version = version; | ||
Interpreter.eval = internalEval; | ||
Interpreter.Function = internalFunction; | ||
Interpreter.ecmaVersion = 5; | ||
// alert.call(globalContextInFunction, 1); | ||
// fix: alert.call({}, 1); // Illegal invocation | ||
// function func(){ | ||
// this;// Interpreter.globalContextInFunction | ||
// } | ||
// func() | ||
Interpreter.globalContextInFunction = void 0; | ||
Interpreter.global = Object.create(null); |
@@ -18,4 +18,8 @@ export declare class ThrowError extends Error { | ||
} | ||
export declare type MessageItem = [number, string, new (message: string) => Error]; | ||
export type MessageItem = [ | ||
number, | ||
string, | ||
new (message: string) => Error | ||
]; | ||
export declare const Messages: Messages; | ||
export {}; |
@@ -0,0 +0,0 @@ export class ThrowError extends Error { |
import * as ESTree from "estree"; | ||
export { ESTree }; | ||
export declare type Node = ESTree.Node | ESTree.BinaryExpression | ESTree.LogicalExpression | ESTree.UnaryExpression | ESTree.UpdateExpression | ESTree.ObjectExpression | ESTree.ArrayExpression | ESTree.CallExpression | ESTree.NewExpression | ESTree.MemberExpression | ESTree.ThisExpression | ESTree.SequenceExpression | ESTree.Literal | ESTree.Identifier | ESTree.AssignmentExpression | ESTree.FunctionDeclaration | ESTree.VariableDeclaration | ESTree.BlockStatement | ESTree.Program | ESTree.ExpressionStatement | ESTree.EmptyStatement | ESTree.ReturnStatement | ESTree.FunctionExpression | ESTree.IfStatement | ESTree.ConditionalExpression | ESTree.ForStatement | ESTree.WhileStatement | ESTree.DoWhileStatement | ESTree.ForInStatement | ESTree.WithStatement | ESTree.ThrowStatement | ESTree.TryStatement | ESTree.ContinueStatement | ESTree.BreakStatement | ESTree.SwitchStatement | ESTree.SwitchCase | ESTree.LabeledStatement | ESTree.DebuggerStatement; | ||
export type Node = ESTree.Node | ESTree.BinaryExpression | ESTree.LogicalExpression | ESTree.UnaryExpression | ESTree.UpdateExpression | ESTree.ObjectExpression | ESTree.ArrayExpression | ESTree.CallExpression | ESTree.NewExpression | ESTree.MemberExpression | ESTree.ThisExpression | ESTree.SequenceExpression | ESTree.Literal | ESTree.Identifier | ESTree.AssignmentExpression | ESTree.FunctionDeclaration | ESTree.VariableDeclaration | ESTree.BlockStatement | ESTree.Program | ESTree.ExpressionStatement | ESTree.EmptyStatement | ESTree.ReturnStatement | ESTree.FunctionExpression | ESTree.IfStatement | ESTree.ConditionalExpression | ESTree.ForStatement | ESTree.WhileStatement | ESTree.DoWhileStatement | ESTree.ForInStatement | ESTree.WithStatement | ESTree.ThrowStatement | ESTree.TryStatement | ESTree.ContinueStatement | ESTree.BreakStatement | ESTree.SwitchStatement | ESTree.SwitchCase | ESTree.LabeledStatement | ESTree.DebuggerStatement; |
import * as ESTree from "estree"; | ||
export { ESTree }; |
@@ -1,2 +0,2 @@ | ||
export declare type VMContext = { | ||
export type VMContext = { | ||
[x: string]: any; | ||
@@ -3,0 +3,0 @@ [x: number]: any; |
@@ -0,0 +0,0 @@ import { VMContext, CompileOptions, ScriptOptions } from "./types"; |
@@ -29,2 +29,3 @@ import { Interpreter } from "./interpreter/main"; | ||
export class Script { | ||
_code; | ||
constructor(code) { | ||
@@ -31,0 +32,0 @@ this._code = code; |
{ | ||
"name": "eval5", | ||
"version": "1.4.7", | ||
"version": "1.4.8", | ||
"description": "A JavaScript interpreter written in JavaScript", | ||
@@ -10,10 +10,11 @@ "main": "./dist/cjs/index.js", | ||
"start": "tsc -w", | ||
"build": "run-s clear build:* bundle:dev bundle:prod bundle:banner", | ||
"build": "run-s clear build:* bundle:dev bundle:version bundle:prod bundle:banner", | ||
"build:lib": "tsc", | ||
"build:cjs": "babel lib --config-file=./babel.config.js --out-dir dist/cjs", | ||
"build:esm": "babel lib --config-file=./babel.config.esm.js --out-dir dist/esm", | ||
"build:cjs": "tsc --module commonjs --target ES5 --outDir dist/cjs --declaration false", | ||
"build:esm": "tsc --module esnext --target ES6 --outDir dist/esm --declaration false", | ||
"clear": "rimraf lib dist umd", | ||
"bundle:dev": "packez bundle ./src/index.ts -d umd -c", | ||
"bundle:prod": "packez bundle ./src/index.ts -d umd --state prod", | ||
"bundle:dev": "rollup -c", | ||
"bundle:prod": "rollup -c rollup.config.min.mjs", | ||
"bundle:banner": "node scripts/banner.js", | ||
"bundle:version": "node scripts/version.js", | ||
"prepublishOnly": "run-s test build", | ||
@@ -48,2 +49,6 @@ "test": "jest" | ||
"@babel/cli": "^7.8.4", | ||
"@rollup/plugin-commonjs": "^26.0.1", | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"@rollup/plugin-typescript": "^11.1.6", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"@types/fs-extra": "^8.1.0", | ||
@@ -56,3 +61,3 @@ "@types/jest": "^24.0.25", | ||
"npm-run-all": "^4.1.5", | ||
"packez": "^3.1.0", | ||
"rollup": "^4.20.0", | ||
"rimraf": "^3.0.0" | ||
@@ -59,0 +64,0 @@ }, |
@@ -0,0 +0,0 @@ # eval5 |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42
628309
14
12657