sval
Version:
A javascript interpreter written in javascript
1,405 lines (1,390 loc) • 144 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('acorn')) :
typeof define === 'function' && define.amd ? define(['acorn'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Sval = factory(global.acorn));
})(this, (function (acorn) { 'use strict';
var statement$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
get ExpressionStatement () { return ExpressionStatement$1; },
get BlockStatement () { return BlockStatement$1; },
get EmptyStatement () { return EmptyStatement$1; },
get DebuggerStatement () { return DebuggerStatement$1; },
get ReturnStatement () { return ReturnStatement$1; },
get BreakStatement () { return BreakStatement$1; },
get ContinueStatement () { return ContinueStatement$1; },
get LabeledStatement () { return LabeledStatement$1; },
get WithStatement () { return WithStatement$1; },
get IfStatement () { return IfStatement$1; },
get SwitchStatement () { return SwitchStatement$1; },
get SwitchCase () { return SwitchCase$1; },
get ThrowStatement () { return ThrowStatement$1; },
get TryStatement () { return TryStatement$1; },
get CatchClause () { return CatchClause$1; },
get WhileStatement () { return WhileStatement$1; },
get DoWhileStatement () { return DoWhileStatement$1; },
get ForStatement () { return ForStatement$1; },
get ForInStatement () { return ForInStatement$1; },
get ForOfStatement () { return ForOfStatement$1; }
});
var declaration$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
get FunctionDeclaration () { return FunctionDeclaration$1; },
get VariableDeclaration () { return VariableDeclaration$1; },
get VariableDeclarator () { return VariableDeclarator$1; },
get ClassDeclaration () { return ClassDeclaration$1; },
get ClassBody () { return ClassBody$1; },
get MethodDefinition () { return MethodDefinition$1; },
get PropertyDefinition () { return PropertyDefinition$1; },
get StaticBlock () { return StaticBlock$1; },
get ImportDeclaration () { return ImportDeclaration$1; },
get ExportDefaultDeclaration () { return ExportDefaultDeclaration$1; },
get ExportNamedDeclaration () { return ExportNamedDeclaration$1; },
get ExportAllDeclaration () { return ExportAllDeclaration$1; }
});
var statement = /*#__PURE__*/Object.freeze({
__proto__: null,
get ExpressionStatement () { return ExpressionStatement; },
get BlockStatement () { return BlockStatement; },
get EmptyStatement () { return EmptyStatement; },
get DebuggerStatement () { return DebuggerStatement; },
get ReturnStatement () { return ReturnStatement; },
get BreakStatement () { return BreakStatement; },
get ContinueStatement () { return ContinueStatement; },
get LabeledStatement () { return LabeledStatement; },
get WithStatement () { return WithStatement; },
get IfStatement () { return IfStatement; },
get SwitchStatement () { return SwitchStatement; },
get SwitchCase () { return SwitchCase; },
get ThrowStatement () { return ThrowStatement; },
get TryStatement () { return TryStatement; },
get CatchClause () { return CatchClause; },
get WhileStatement () { return WhileStatement; },
get DoWhileStatement () { return DoWhileStatement; },
get ForStatement () { return ForStatement; },
get ForInStatement () { return ForInStatement; },
get ForOfStatement () { return ForOfStatement; }
});
var declaration = /*#__PURE__*/Object.freeze({
__proto__: null,
get FunctionDeclaration () { return FunctionDeclaration; },
get VariableDeclaration () { return VariableDeclaration; },
get VariableDeclarator () { return VariableDeclarator; },
get ClassDeclaration () { return ClassDeclaration; },
get ClassBody () { return ClassBody; },
get MethodDefinition () { return MethodDefinition; },
get PropertyDefinition () { return PropertyDefinition; },
get StaticBlock () { return StaticBlock; },
get ImportDeclaration () { return ImportDeclaration; },
get ExportDefaultDeclaration () { return ExportDefaultDeclaration; },
get ExportNamedDeclaration () { return ExportNamedDeclaration; },
get ExportAllDeclaration () { return ExportAllDeclaration; }
});
const freeze = Object.freeze;
const define = Object.defineProperty;
const getDptor = Object.getOwnPropertyDescriptor;
const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
return hasOwnProperty.call(obj, key);
}
const getOwnNames = Object.getOwnPropertyNames;
const setPrototypeOf = Object.setPrototypeOf;
function setProto(obj, proto) {
setPrototypeOf ? setPrototypeOf(obj, proto) : obj.__proto__ = proto;
}
const getPrototypeOf = Object.getPrototypeOf;
function getProto(obj) {
return getPrototypeOf ? getPrototypeOf(obj) : obj.__proto__;
}
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
function getGetterOrSetter(method, obj, key) {
while (obj) {
const descriptor = getOwnPropertyDescriptor(obj, key);
const value = typeof descriptor !== 'undefined'
&& typeof descriptor.writable === 'undefined'
&& typeof descriptor[method] === 'function'
&& descriptor[method];
if (value) {
return value;
}
else {
obj = getProto(obj);
}
}
}
function getGetter(obj, key) {
return getGetterOrSetter('get', obj, key);
}
function getSetter(obj, key) {
return getGetterOrSetter('set', obj, key);
}
const create = Object.create;
function inherits(subClass, superClass) {
setProto(subClass, superClass);
subClass.prototype = create(superClass.prototype, {
constructor: {
value: subClass,
writable: true,
}
});
}
function _assign(target) {
for (let i = 1; i < arguments.length; ++i) {
const source = arguments[i];
for (const key in source) {
if (hasOwn(source, key)) {
target[key] = source[key];
}
}
}
return target;
}
const assign = Object.assign || _assign;
let names = [];
let globalObj = create(null);
const setGlobalObj = (g) => {
if (!g.Object)
throw 0;
names = getOwnNames(globalObj = g).filter(n => ['webkitStorageInfo', 'GLOBAL', 'root'].indexOf(n) === -1);
};
try {
setGlobalObj(window);
}
catch (err) {
try {
setGlobalObj(self);
}
catch (err) {
try {
setGlobalObj(global);
}
catch (err) {
try {
setGlobalObj(globalThis);
}
catch (err) {
try {
globalObj.Object = Object;
}
catch (err) { }
try {
globalObj.Function = Function;
}
catch (err) { }
try {
globalObj.Array = Array;
}
catch (err) { }
try {
globalObj.Number = Number;
}
catch (err) { }
try {
globalObj.parseFloat = parseFloat;
}
catch (err) { }
try {
globalObj.parseInt = parseInt;
}
catch (err) { }
try {
globalObj.Infinity = Infinity;
}
catch (err) { }
try {
globalObj.NaN = NaN;
}
catch (err) { }
try {
globalObj.undefined = undefined;
}
catch (err) { }
try {
globalObj.Boolean = Boolean;
}
catch (err) { }
try {
globalObj.String = String;
}
catch (err) { }
try {
globalObj.Symbol = Symbol;
}
catch (err) { }
try {
globalObj.Date = Date;
}
catch (err) { }
try {
globalObj.Promise = Promise;
}
catch (err) { }
try {
globalObj.RegExp = RegExp;
}
catch (err) { }
try {
globalObj.Error = Error;
}
catch (err) { }
try {
globalObj.EvalError = EvalError;
}
catch (err) { }
try {
globalObj.RangeError = RangeError;
}
catch (err) { }
try {
globalObj.ReferenceError = ReferenceError;
}
catch (err) { }
try {
globalObj.SyntaxError = SyntaxError;
}
catch (err) { }
try {
globalObj.TypeError = TypeError;
}
catch (err) { }
try {
globalObj.URIError = URIError;
}
catch (err) { }
try {
globalObj.JSON = JSON;
}
catch (err) { }
try {
globalObj.Math = Math;
}
catch (err) { }
try {
globalObj.console = console;
}
catch (err) { }
try {
globalObj.Intl = Intl;
}
catch (err) { }
try {
globalObj.ArrayBuffer = ArrayBuffer;
}
catch (err) { }
try {
globalObj.Uint8Array = Uint8Array;
}
catch (err) { }
try {
globalObj.Int8Array = Int8Array;
}
catch (err) { }
try {
globalObj.Uint16Array = Uint16Array;
}
catch (err) { }
try {
globalObj.Int16Array = Int16Array;
}
catch (err) { }
try {
globalObj.Uint32Array = Uint32Array;
}
catch (err) { }
try {
globalObj.Int32Array = Int32Array;
}
catch (err) { }
try {
globalObj.Float32Array = Float32Array;
}
catch (err) { }
try {
globalObj.Float64Array = Float64Array;
}
catch (err) { }
try {
globalObj.Uint8ClampedArray = Uint8ClampedArray;
}
catch (err) { }
try {
globalObj.DataView = DataView;
}
catch (err) { }
try {
globalObj.Map = Map;
}
catch (err) { }
try {
globalObj.Set = Set;
}
catch (err) { }
try {
globalObj.WeakMap = WeakMap;
}
catch (err) { }
try {
globalObj.WeakSet = WeakSet;
}
catch (err) { }
try {
globalObj.Proxy = Proxy;
}
catch (err) { }
try {
globalObj.Reflect = Reflect;
}
catch (err) { }
try {
globalObj.BigInt = BigInt;
}
catch (err) { }
try {
globalObj.decodeURI = decodeURI;
}
catch (err) { }
try {
globalObj.decodeURIComponent = decodeURIComponent;
}
catch (err) { }
try {
globalObj.encodeURI = encodeURI;
}
catch (err) { }
try {
globalObj.encodeURIComponent = encodeURIComponent;
}
catch (err) { }
try {
globalObj.escape = escape;
}
catch (err) { }
try {
globalObj.unescape = unescape;
}
catch (err) { }
try {
globalObj.eval = eval;
}
catch (err) { }
try {
globalObj.isFinite = isFinite;
}
catch (err) { }
try {
globalObj.isNaN = isNaN;
}
catch (err) { }
try {
globalObj.SharedArrayBuffer = SharedArrayBuffer;
}
catch (err) { }
try {
globalObj.Atomics = Atomics;
}
catch (err) { }
try {
globalObj.WebAssembly = WebAssembly;
}
catch (err) { }
try {
globalObj.clearInterval = clearInterval;
}
catch (err) { }
try {
globalObj.clearTimeout = clearTimeout;
}
catch (err) { }
try {
globalObj.setInterval = setInterval;
}
catch (err) { }
try {
globalObj.setTimeout = setTimeout;
}
catch (err) { }
try {
globalObj.crypto = crypto;
}
catch (err) { }
try {
globalObj.URL = URL;
}
catch (err) { }
names = getOwnNames(globalObj);
}
}
}
}
if (globalObj.Symbol) {
!globalObj.Symbol.iterator && (globalObj.Symbol.iterator = createSymbol('iterator'));
!globalObj.Symbol.asyncIterator && (globalObj.Symbol.asyncIterator = createSymbol('asynciterator'));
}
const win = create({});
for (let i = 0; i < names.length; i++) {
const name = names[i];
try {
win[name] = globalObj[name];
}
catch (err) { }
}
const WINDOW = createSymbol('window');
function createSandBox() {
return assign(create({ [WINDOW]: globalObj }), win);
}
function createSymbol(key) {
return key + Math.random().toString(36).substring(2);
}
function getAsyncIterator(obj) {
let iterator;
if (typeof Symbol === 'function') {
iterator = obj[Symbol.asyncIterator];
!iterator && (iterator = obj[Symbol.iterator]);
}
if (iterator) {
return iterator.call(obj);
}
else if (typeof obj.next === 'function') {
return obj;
}
else {
let i = 0;
return {
next() {
if (obj && i >= obj.length)
obj = undefined;
return { value: obj && obj[i++], done: !obj };
}
};
}
}
const AWAIT = { RES: undefined };
const RETURN = { RES: undefined };
const CONTINUE = { LABEL: undefined };
const BREAK = { LABEL: undefined };
const SUPER = createSymbol('super');
const SUPERCALL = createSymbol('supercall');
const NOCTOR = createSymbol('noctor');
const CLSCTOR = createSymbol('clsctor');
const NEWTARGET = createSymbol('newtarget');
const PRIVATE = createSymbol('private');
const NOINIT = createSymbol('noinit');
const DEADZONE = createSymbol('deadzone');
const IMPORT = createSymbol('import');
const EXPORTS = createSymbol('exports');
var version = "0.6.1";
class Var {
constructor(kind, value) {
this.kind = kind;
this.value = value;
}
get() {
return this.value;
}
set(value) {
if (this.kind === 'const') {
throw new TypeError('Assignment to constant variable');
}
else {
return this.value = value;
}
}
}
class Prop {
constructor(object, property) {
this.object = object;
this.property = property;
}
get() {
return this.object[this.property];
}
set(value) {
this.object[this.property] = value;
return true;
}
del() {
return delete this.object[this.property];
}
}
class Scope {
constructor(parent = null, isolated = false) {
this.context = create(null);
this.withContext = create(null);
this.parent = parent;
this.isolated = isolated;
}
global() {
let scope = this;
while (scope.parent) {
scope = scope.parent;
}
return scope;
}
find(name) {
if (this.context[name]) {
return this.context[name];
}
else if (name in this.withContext) {
return new Prop(this.withContext, name);
}
else if (this.parent) {
return this.parent.find(name);
}
else {
const win = this.global().find('window').get();
if (name in win) {
return new Prop(win, name);
}
else {
return null;
}
}
}
var(name, value) {
let scope = this;
while (scope.parent && !scope.isolated) {
scope = scope.parent;
}
const variable = scope.context[name];
if (!variable) {
scope.context[name] = new Var('var', value === NOINIT ? undefined : value);
}
else {
if (variable.kind === 'var') {
if (value !== NOINIT) {
variable.set(value);
}
}
else {
throw new SyntaxError(`Identifier '${name}' has already been declared`);
}
}
if (!scope.parent) {
const win = scope.find('window').get();
if (value !== NOINIT) {
define(win, name, { value, writable: true, enumerable: true });
}
}
}
let(name, value) {
const variable = this.context[name];
if (!variable || variable.get() === DEADZONE) {
this.context[name] = new Var('let', value);
}
else {
throw new SyntaxError(`Identifier '${name}' has already been declared`);
}
}
const(name, value) {
const variable = this.context[name];
if (!variable || variable.get() === DEADZONE) {
this.context[name] = new Var('const', value);
}
else {
throw new SyntaxError(`Identifier '${name}' has already been declared`);
}
}
func(name, value) {
const variable = this.context[name];
if (!variable || variable.kind === 'var') {
this.context[name] = new Var('var', value);
}
else {
throw new SyntaxError(`Identifier '${name}' has already been declared`);
}
}
with(value) {
if (Object.keys(value)) {
this.withContext = value;
}
}
}
function runAsync(iterator, options = {}) {
const { res, err, ret, fullRet } = options;
return new Promise((resolve, reject) => {
if ('ret' in options) {
return resolve(iterator.return(ret));
}
if ('err' in options) {
onRejected(err);
}
else {
onFulfilled(res);
}
function onFulfilled(res) {
let ret;
try {
ret = iterator.next(res);
}
catch (e) {
return reject(e);
}
next(ret);
return null;
}
function onRejected(err) {
let ret;
try {
ret = iterator.throw(err);
}
catch (e) {
return reject(e);
}
next(ret);
}
function next(ret) {
if (ret.done)
return resolve(fullRet ? ret : ret.value);
if (ret.value !== AWAIT)
return resolve(ret);
const awaitValue = ret.value.RES;
const value = awaitValue && awaitValue.then === 'function'
? awaitValue : Promise.resolve(awaitValue);
return value.then(onFulfilled, onRejected);
}
});
}
function* Identifier$1(node, scope, options = {}) {
const { getVar = false, throwErr = true } = options;
if (node.name === 'undefined') {
return undefined;
}
const variable = scope.find(node.name);
if (variable) {
if (getVar) {
return variable;
}
else {
const value = variable.get();
if (value === DEADZONE) {
throw new ReferenceError(`${node.name} is not defined`);
}
else {
return value;
}
}
}
else if (throwErr) {
throw new ReferenceError(`${node.name} is not defined`);
}
else {
return undefined;
}
}
var identifier$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
Identifier: Identifier$1
});
function* Literal$1(node, scope) {
return node.value;
}
var literal$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
Literal: Literal$1
});
function* ThisExpression$1(node, scope) {
const superCall = scope.find(SUPERCALL);
if (superCall && !superCall.get()) {
throw new ReferenceError('Must call super constructor in derived class '
+ 'before accessing \'this\' or returning from derived constructor');
}
else {
return scope.find('this').get();
}
}
function* ArrayExpression$1(node, scope) {
let results = [];
for (let i = 0; i < node.elements.length; i++) {
const item = node.elements[i];
if (item.type === 'SpreadElement') {
results = results.concat(yield* SpreadElement$1(item, scope));
}
else {
results.push(yield* evaluate$1(item, scope));
}
}
return results;
}
function* ObjectExpression$1(node, scope) {
const object = {};
for (let i = 0; i < node.properties.length; i++) {
const property = node.properties[i];
if (property.type === 'SpreadElement') {
assign(object, yield* SpreadElement$1(property, scope, { spreadProps: true }));
}
else {
let key;
const propKey = property.key;
if (property.computed) {
key = yield* evaluate$1(propKey, scope);
}
else {
if (propKey.type === 'Identifier') {
key = propKey.name;
}
else {
key = '' + (yield* Literal$1(propKey));
}
}
const value = yield* evaluate$1(property.value, scope);
const propKind = property.kind;
if (propKind === 'init') {
object[key] = value;
}
else if (propKind === 'get') {
const oriDptor = getDptor(object, key);
define(object, key, {
get: value,
set: oriDptor && oriDptor.set,
enumerable: true,
configurable: true
});
}
else {
const oriDptor = getDptor(object, key);
define(object, key, {
get: oriDptor && oriDptor.get,
set: value,
enumerable: true,
configurable: true
});
}
}
}
return object;
}
function* FunctionExpression$1(node, scope) {
if (node.id && node.id.name) {
const tmpScope = new Scope(scope);
const func = createFunc(node, tmpScope);
tmpScope.const(node.id.name, func);
return func;
}
else {
return createFunc(node, scope);
}
}
function* UnaryExpression$1(node, scope) {
const arg = node.argument;
switch (node.operator) {
case '+': return +(yield* evaluate$1(arg, scope));
case '-': return -(yield* evaluate$1(arg, scope));
case '!': return !(yield* evaluate$1(arg, scope));
case '~': return ~(yield* evaluate$1(arg, scope));
case 'void': return void (yield* evaluate$1(arg, scope));
case 'typeof':
if (arg.type === 'Identifier') {
return typeof (yield* Identifier$1(arg, scope, { throwErr: false }));
}
else {
return typeof (yield* evaluate$1(arg, scope));
}
case 'delete':
if (arg.type === 'MemberExpression') {
const variable = yield* MemberExpression$1(arg, scope, { getVar: true });
return variable.del();
}
else if (arg.type === 'Identifier') {
throw new SyntaxError('Delete of an unqualified identifier in strict mode');
}
else {
yield* evaluate$1(arg, scope);
return true;
}
default: throw new SyntaxError(`Unexpected token ${node.operator}`);
}
}
function* UpdateExpression$1(node, scope) {
const arg = node.argument;
let variable;
if (arg.type === 'Identifier') {
variable = yield* Identifier$1(arg, scope, { getVar: true });
}
else if (arg.type === 'MemberExpression') {
variable = yield* MemberExpression$1(arg, scope, { getVar: true });
}
else {
throw new SyntaxError('Unexpected token');
}
const value = variable.get();
if (node.operator === '++') {
variable.set(value + 1);
return node.prefix ? variable.get() : value;
}
else if (node.operator === '--') {
variable.set(value - 1);
return node.prefix ? variable.get() : value;
}
else {
throw new SyntaxError(`Unexpected token ${node.operator}`);
}
}
function* BinaryExpression$1(node, scope) {
let left;
let right;
if (node.left.type === 'PrivateIdentifier') {
left = node.left.name;
right = yield* evaluate$1(node.right, scope);
right = right[PRIVATE] || {};
}
else {
left = yield* evaluate$1(node.left, scope);
right = yield* evaluate$1(node.right, scope);
}
switch (node.operator) {
case '==': return left == right;
case '!=': return left != right;
case '===': return left === right;
case '!==': return left !== right;
case '<': return left < right;
case '<=': return left <= right;
case '>': return left > right;
case '>=': return left >= right;
case '<<': return left << right;
case '>>': return left >> right;
case '>>>': return left >>> right;
case '+': return left + right;
case '-': return left - right;
case '*': return left * right;
case '**': return Math.pow(left, right);
case '/': return left / right;
case '%': return left % right;
case '|': return left | right;
case '^': return left ^ right;
case '&': return left & right;
case 'in': return left in right;
case 'instanceof': return left instanceof right;
default: throw new SyntaxError(`Unexpected token ${node.operator}`);
}
}
function* AssignmentExpression$1(node, scope) {
var _a;
const left = node.left;
let variable;
if (left.type === 'Identifier') {
variable = yield* Identifier$1(left, scope, { getVar: true, throwErr: false });
if (!variable) {
const win = scope.global().find('window').get();
variable = new Prop(win, left.name);
}
}
else if (left.type === 'MemberExpression') {
variable = yield* MemberExpression$1(left, scope, { getVar: true });
}
else {
const value = yield* evaluate$1(node.right, scope);
return yield* pattern(left, scope, { feed: value });
}
const value = yield* evaluate$1(node.right, scope);
switch (node.operator) {
case '=':
variable.set(value);
return variable.get();
case '+=':
variable.set(variable.get() + value);
return variable.get();
case '-=':
variable.set(variable.get() - value);
return variable.get();
case '*=':
variable.set(variable.get() * value);
return variable.get();
case '/=':
variable.set(variable.get() / value);
return variable.get();
case '%=':
variable.set(variable.get() % value);
return variable.get();
case '**=':
variable.set(Math.pow(variable.get(), value));
return variable.get();
case '<<=':
variable.set(variable.get() << value);
return variable.get();
case '>>=':
variable.set(variable.get() >> value);
return variable.get();
case '>>>=':
variable.set(variable.get() >>> value);
return variable.get();
case '|=':
variable.set(variable.get() | value);
return variable.get();
case '^=':
variable.set(variable.get() ^ value);
return variable.get();
case '&=':
variable.set(variable.get() & value);
return variable.get();
case '??=':
variable.set((_a = variable.get()) !== null && _a !== void 0 ? _a : value);
return variable.get();
case '&&=':
variable.set(variable.get() && value);
return variable.get();
case '||=':
variable.set(variable.get() || value);
return variable.get();
default: throw new SyntaxError(`Unexpected token ${node.operator}`);
}
}
function* LogicalExpression$1(node, scope) {
var _a;
switch (node.operator) {
case '||':
return (yield* evaluate$1(node.left, scope)) || (yield* evaluate$1(node.right, scope));
case '&&':
return (yield* evaluate$1(node.left, scope)) && (yield* evaluate$1(node.right, scope));
case '??':
return (_a = (yield* evaluate$1(node.left, scope))) !== null && _a !== void 0 ? _a : (yield* evaluate$1(node.right, scope));
default:
throw new SyntaxError(`Unexpected token ${node.operator}`);
}
}
function* MemberExpression$1(node, scope, options = {}) {
const { getObj = false, getVar = false } = options;
let object;
if (node.object.type === 'Super') {
object = yield* Super$1(node.object, scope, { getProto: true });
}
else {
object = yield* evaluate$1(node.object, scope);
}
if (getObj)
return object;
let key;
let priv = false;
if (node.computed) {
key = yield* evaluate$1(node.property, scope);
}
else if (node.property.type === 'PrivateIdentifier') {
key = node.property.name;
priv = true;
}
else {
key = node.property.name;
}
if (priv) {
object = object[PRIVATE];
}
if (getVar) {
const setter = getSetter(object, key);
if (node.object.type === 'Super' && setter) {
const thisObject = scope.find('this').get();
const privateKey = createSymbol(key);
define(thisObject, privateKey, { set: setter });
return new Prop(thisObject, privateKey);
}
else {
return new Prop(object, key);
}
}
else {
const getter = getGetter(object, key);
if (node.object.type === 'Super' && getter) {
const thisObject = scope.find('this').get();
if (node.optional && thisObject == null) {
return undefined;
}
return getter.call(thisObject);
}
else {
if (node.optional && object == null) {
return undefined;
}
return object[key];
}
}
}
function* ConditionalExpression$1(node, scope) {
return (yield* evaluate$1(node.test, scope))
? (yield* evaluate$1(node.consequent, scope))
: (yield* evaluate$1(node.alternate, scope));
}
function* CallExpression$1(node, scope) {
let func;
let object;
if (node.callee.type === 'MemberExpression') {
object = yield* MemberExpression$1(node.callee, scope, { getObj: true });
if (node.callee.optional && object == null) {
return undefined;
}
let key;
let priv = false;
if (node.callee.computed) {
key = yield* evaluate$1(node.callee.property, scope);
}
else if (node.callee.property.type === 'PrivateIdentifier') {
key = node.callee.property.name;
priv = true;
}
else {
key = node.callee.property.name;
}
let obj = object;
if (priv) {
obj = obj[PRIVATE];
}
if (node.callee.object.type === 'Super') {
const thisObject = scope.find('this').get();
func = obj[key].bind(thisObject);
}
else {
func = obj[key];
}
if (node.optional && func == null) {
return undefined;
}
if (typeof func !== 'function') {
throw new TypeError(`${key} is not a function`);
}
else if (func[CLSCTOR]) {
throw new TypeError(`Class constructor ${key} cannot be invoked without 'new'`);
}
}
else {
object = scope.find('this').get();
func = yield* evaluate$1(node.callee, scope);
if (node.optional && func == null) {
return undefined;
}
if (typeof func !== 'function' || node.callee.type !== 'Super' && func[CLSCTOR]) {
let name;
if (node.callee.type === 'Identifier') {
name = node.callee.name;
}
else {
try {
name = JSON.stringify(func);
}
catch (err) {
name = '' + func;
}
}
if (typeof func !== 'function') {
throw new TypeError(`${name} is not a function`);
}
else {
throw new TypeError(`Class constructor ${name} cannot be invoked without 'new'`);
}
}
}
let args = [];
for (let i = 0; i < node.arguments.length; i++) {
const arg = node.arguments[i];
if (arg.type === 'SpreadElement') {
args = args.concat(yield* SpreadElement$1(arg, scope));
}
else {
args.push(yield* evaluate$1(arg, scope));
}
}
if (node.callee.type === 'Super') {
const superCall = scope.find(SUPERCALL);
if (superCall.get()) {
throw new ReferenceError('Super constructor may only be called once');
}
else {
scope.find(SUPERCALL).set(true);
}
}
try {
return func.apply(object, args);
}
catch (err) {
if (err instanceof TypeError && err.message === 'Illegal invocation'
&& func.toString().indexOf('[native code]') !== -1) {
const win = scope.global().find('window').get();
if (win && win[WINDOW]) {
return func.apply(win[WINDOW], args);
}
}
throw err;
}
}
function* NewExpression$1(node, scope) {
const constructor = yield* evaluate$1(node.callee, scope);
if (typeof constructor !== 'function') {
let name;
if (node.callee.type === 'Identifier') {
name = node.callee.name;
}
else {
try {
name = JSON.stringify(constructor);
}
catch (err) {
name = '' + constructor;
}
}
throw new TypeError(`${name} is not a constructor`);
}
else if (constructor[NOCTOR]) {
throw new TypeError(`${constructor.name || '(intermediate value)'} is not a constructor`);
}
let args = [];
for (let i = 0; i < node.arguments.length; i++) {
const arg = node.arguments[i];
if (arg.type === 'SpreadElement') {
args = args.concat(yield* SpreadElement$1(arg, scope));
}
else {
args.push(yield* evaluate$1(arg, scope));
}
}
return new constructor(...args);
}
function* MetaProperty$1(node, scope) {
if (node.meta.name === 'new' && node.property.name === 'target') {
return scope.find(NEWTARGET).get();
}
else if (node.meta.name === 'import' && node.property.name === 'meta') {
return { url: '' };
}
}
function* SequenceExpression$1(node, scope) {
let result;
for (let i = 0; i < node.expressions.length; i++) {
result = yield* evaluate$1(node.expressions[i], scope);
}
return result;
}
function* ArrowFunctionExpression$1(node, scope) {
return createFunc(node, scope);
}
function* TemplateLiteral$1(node, scope) {
const quasis = node.quasis.slice();
const expressions = node.expressions.slice();
let result = '';
let temEl;
let expr;
while (temEl = quasis.shift()) {
result += yield* TemplateElement$1(temEl);
expr = expressions.shift();
if (expr) {
result += yield* evaluate$1(expr, scope);
}
}
return result;
}
function* TaggedTemplateExpression$1(node, scope) {
const tagFunc = yield* evaluate$1(node.tag, scope);
const quasis = node.quasi.quasis;
const str = quasis.map(v => v.value.cooked);
const raw = quasis.map(v => v.value.raw);
define(str, 'raw', {
value: freeze(raw)
});
const expressions = node.quasi.expressions;
const args = [];
if (expressions) {
for (let i = 0; i < expressions.length; i++) {
args.push(yield* evaluate$1(expressions[i], scope));
}
}
return tagFunc(freeze(str), ...args);
}
function* TemplateElement$1(node, scope) {
return node.value.raw;
}
function* ClassExpression$1(node, scope) {
if (node.id && node.id.name) {
const tmpScope = new Scope(scope);
const klass = yield* createClass(node, tmpScope);
tmpScope.const(node.id.name, klass);
return klass;
}
else {
return yield* createClass(node, scope);
}
}
function* Super$1(node, scope, options = {}) {
const { getProto = false } = options;
const superClass = scope.find(SUPER).get();
return getProto ? superClass.prototype : superClass;
}
function* SpreadElement$1(node, scope, options = {}) {
const result = yield* evaluate$1(node.argument, scope);
if (options.spreadProps) {
return result;
}
if (typeof Symbol === 'function' && typeof result[Symbol.iterator] !== 'function') {
throw new TypeError('Spread syntax requires ...iterable[Symbol.iterator] to be a function');
}
return [...result];
}
function* ChainExpression$1(node, scope) {
return yield* evaluate$1(node.expression, scope);
}
function* ImportExpression$1(node, scope) {
const globalScope = scope.global();
const source = yield* evaluate$1(node.source, scope);
const module = globalScope.find(IMPORT + source);
let value;
if (module) {
const result = module.get();
if (result) {
if (typeof result === 'function') {
value = result();
}
else if (typeof result === 'object') {
value = result;
}
}
}
if (!value || typeof value !== 'object') {
return Promise.reject(new TypeError(`Failed to resolve module specifier "${source}"`));
}
return Promise.resolve(value);
}
function* YieldExpression(node, scope) {
const res = yield* evaluate$1(node.argument, scope);
return node.delegate ? yield* res : yield res;
}
function* AwaitExpression(node, scope) {
AWAIT.RES = yield* evaluate$1(node.argument, scope);
return yield AWAIT;
}
var expression$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
ThisExpression: ThisExpression$1,
ArrayExpression: ArrayExpression$1,
ObjectExpression: ObjectExpression$1,
FunctionExpression: FunctionExpression$1,
UnaryExpression: UnaryExpression$1,
UpdateExpression: UpdateExpression$1,
BinaryExpression: BinaryExpression$1,
AssignmentExpression: AssignmentExpression$1,
LogicalExpression: LogicalExpression$1,
MemberExpression: MemberExpression$1,
ConditionalExpression: ConditionalExpression$1,
CallExpression: CallExpression$1,
NewExpression: NewExpression$1,
MetaProperty: MetaProperty$1,
SequenceExpression: SequenceExpression$1,
ArrowFunctionExpression: ArrowFunctionExpression$1,
TemplateLiteral: TemplateLiteral$1,
TaggedTemplateExpression: TaggedTemplateExpression$1,
TemplateElement: TemplateElement$1,
ClassExpression: ClassExpression$1,
Super: Super$1,
SpreadElement: SpreadElement$1,
ChainExpression: ChainExpression$1,
ImportExpression: ImportExpression$1,
YieldExpression: YieldExpression,
AwaitExpression: AwaitExpression
});
function* ObjectPattern$1(node, scope, options = {}) {
const { kind = 'var', hoist = false, onlyBlock = false, feed = {} } = options;
const fedKeys = [];
for (let i = 0; i < node.properties.length; i++) {
const property = node.properties[i];
if (hoist) {
if (onlyBlock || kind === 'var') {
if (property.type === 'Property') {
const value = property.value;
if (value.type === 'Identifier') {
scope[kind](value.name, onlyBlock ? DEADZONE : kind === 'var' ? NOINIT : undefined);
}
else {
yield* pattern(value, scope, { kind, hoist, onlyBlock });
}
}
else {
yield* RestElement$1(property, scope, { kind, hoist, onlyBlock });
}
}
}
else if (property.type === 'Property') {
let key;
if (property.computed) {
key = yield* evaluate$1(property.key, scope);
}
else {
key = property.key.name;
}
fedKeys.push(key);
const value = property.value;
if (value.type === 'Identifier') {
scope[kind](value.name, feed[key]);
}
else {
yield* pattern(value, scope, { kind, feed: feed[key] });
}
}
else {
const rest = assign({}, feed);
for (let i = 0; i < fedKeys.length; i++)
delete rest[fedKeys[i]];
yield* RestElement$1(property, scope, { kind, feed: rest });
}
}
}
function* ArrayPattern$1(node, scope, options = {}) {
const { kind, hoist = false, onlyBlock = false, feed = [] } = options;
const result = [];
for (let i = 0; i < node.elements.length; i++) {
const element = node.elements[i];
if (!element)
continue;
if (hoist) {
if (onlyBlock || kind === 'var') {
if (element.type === 'Identifier') {
scope[kind](element.name, onlyBlock ? DEADZONE : kind === 'var' ? NOINIT : undefined);
}
else {
yield* pattern(element, scope, { kind, hoist, onlyBlock });
}
}
}
else if (element.type === 'Identifier') {
if (kind) {
scope[kind](element.name, feed[i]);
}
else {
const variable = yield* Identifier$1(element, scope, { getVar: true });
variable.set(feed[i]);
result.push(variable.get());
}
}
else if (element.type === 'RestElement') {
yield* RestElement$1(element, scope, { kind, feed: feed.slice(i) });
}
else {
yield* pattern(element, scope, { kind, feed: feed[i] });
}
}
if (result.length) {
return result;
}
}
function* RestElement$1(node, scope, options = {}) {
const { kind, hoist = false, onlyBlock = false, feed = [] } = options;
const arg = node.argument;
if (hoist) {
if (onlyBlock || kind === 'var') {
if (arg.type === 'Identifier') {
scope[kind](arg.name, onlyBlock ? DEADZONE : kind === 'var' ? NOINIT : undefined);
}
else {
yield* pattern(arg, scope, { kind, hoist, onlyBlock });
}
}
}
else if (arg.type === 'Identifier') {
if (kind) {
scope[kind](arg.name, feed);
}
else {
const variable = yield* Identifier$1(arg, scope, { getVar: true });
variable.set(feed);
}
}
else {
yield* pattern(arg, scope, { kind, feed });
}
}
function* AssignmentPattern$1(node, scope, options = {}) {
const { kind = 'var', hoist = false, onlyBlock = false, feed = yield* evaluate$1(node.right, scope) } = options;
const left = node.left;
if (hoist) {
if (onlyBlock || kind === 'var') {