@next-core/cook 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +3 -0
- package/dist/cjs/AnalysisContext.js +42 -0
- package/dist/cjs/AnalysisContext.js.map +1 -0
- package/dist/cjs/ExecutionContext.js +161 -0
- package/dist/cjs/ExecutionContext.js.map +1 -0
- package/dist/cjs/context-free.js +262 -0
- package/dist/cjs/context-free.js.map +1 -0
- package/dist/cjs/cook.js +1587 -0
- package/dist/cjs/cook.js.map +1 -0
- package/dist/cjs/hasOwnProperty.js +11 -0
- package/dist/cjs/hasOwnProperty.js.map +1 -0
- package/dist/cjs/index.js +58 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/interfaces.js +6 -0
- package/dist/cjs/interfaces.js.map +1 -0
- package/dist/cjs/lint.js +176 -0
- package/dist/cjs/lint.js.map +1 -0
- package/dist/cjs/parse.js +51 -0
- package/dist/cjs/parse.js.map +1 -0
- package/dist/cjs/precook.js +432 -0
- package/dist/cjs/precook.js.map +1 -0
- package/dist/cjs/precookFunction.js +25 -0
- package/dist/cjs/precookFunction.js.map +1 -0
- package/dist/cjs/preevaluate.js +35 -0
- package/dist/cjs/preevaluate.js.map +1 -0
- package/dist/cjs/sanitize.js +59 -0
- package/dist/cjs/sanitize.js.map +1 -0
- package/dist/cjs/traverse.js +168 -0
- package/dist/cjs/traverse.js.map +1 -0
- package/dist/esm/AnalysisContext.js +30 -0
- package/dist/esm/AnalysisContext.js.map +1 -0
- package/dist/esm/ExecutionContext.js +135 -0
- package/dist/esm/ExecutionContext.js.map +1 -0
- package/dist/esm/context-free.js +221 -0
- package/dist/esm/context-free.js.map +1 -0
- package/dist/esm/cook.js +1607 -0
- package/dist/esm/cook.js.map +1 -0
- package/dist/esm/hasOwnProperty.js +4 -0
- package/dist/esm/hasOwnProperty.js.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interfaces.js +2 -0
- package/dist/esm/interfaces.js.map +1 -0
- package/dist/esm/lint.js +168 -0
- package/dist/esm/lint.js.map +1 -0
- package/dist/esm/parse.js +41 -0
- package/dist/esm/parse.js.map +1 -0
- package/dist/esm/precook.js +435 -0
- package/dist/esm/precook.js.map +1 -0
- package/dist/esm/precookFunction.js +20 -0
- package/dist/esm/precookFunction.js.map +1 -0
- package/dist/esm/preevaluate.js +23 -0
- package/dist/esm/preevaluate.js.map +1 -0
- package/dist/esm/sanitize.js +48 -0
- package/dist/esm/sanitize.js.map +1 -0
- package/dist/esm/traverse.js +157 -0
- package/dist/esm/traverse.js.map +1 -0
- package/dist/types/AnalysisContext.d.ts +17 -0
- package/dist/types/ExecutionContext.d.ts +79 -0
- package/dist/types/context-free.d.ts +19 -0
- package/dist/types/cook.d.ts +12 -0
- package/dist/types/cook.spec.d.ts +1 -0
- package/dist/types/hasOwnProperty.d.ts +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/interfaces.d.ts +33 -0
- package/dist/types/lint.d.ts +13 -0
- package/dist/types/lint.spec.d.ts +1 -0
- package/dist/types/parse.d.ts +6 -0
- package/dist/types/precook.d.ts +14 -0
- package/dist/types/precook.spec.d.ts +1 -0
- package/dist/types/precookFunction.d.ts +10 -0
- package/dist/types/precookFunction.spec.d.ts +1 -0
- package/dist/types/preevaluate.d.ts +13 -0
- package/dist/types/preevaluate.spec.d.ts +1 -0
- package/dist/types/sanitize.d.ts +2 -0
- package/dist/types/traverse.d.ts +11 -0
- package/package.json +40 -0
package/dist/cjs/cook.js
ADDED
|
@@ -0,0 +1,1587 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.cook = cook;
|
|
7
|
+
|
|
8
|
+
var _contextFree = require("./context-free");
|
|
9
|
+
|
|
10
|
+
var _ExecutionContext = require("./ExecutionContext");
|
|
11
|
+
|
|
12
|
+
var _sanitize = require("./sanitize");
|
|
13
|
+
|
|
14
|
+
var _traverse = require("./traverse");
|
|
15
|
+
|
|
16
|
+
/** For next-core internal usage only. */
|
|
17
|
+
function cook(rootAst, codeSource, {
|
|
18
|
+
rules,
|
|
19
|
+
globalVariables = {}
|
|
20
|
+
} = {}) {
|
|
21
|
+
const expressionOnly = rootAst.type !== "FunctionDeclaration";
|
|
22
|
+
const rootEnv = new _ExecutionContext.DeclarativeEnvironment(null);
|
|
23
|
+
const rootContext = new _ExecutionContext.ExecutionContext();
|
|
24
|
+
rootContext.VariableEnvironment = rootEnv;
|
|
25
|
+
rootContext.LexicalEnvironment = rootEnv;
|
|
26
|
+
const executionContextStack = [rootContext];
|
|
27
|
+
|
|
28
|
+
for (const [key, value] of Object.entries(globalVariables)) {
|
|
29
|
+
rootEnv.CreateImmutableBinding(key, true);
|
|
30
|
+
rootEnv.InitializeBinding(key, value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const TemplateMap = new WeakMap(); // https://tc39.es/ecma262/#sec-gettemplateobject
|
|
34
|
+
|
|
35
|
+
function GetTemplateObject(templateLiteral) {
|
|
36
|
+
const memo = TemplateMap.get(templateLiteral);
|
|
37
|
+
|
|
38
|
+
if (memo) {
|
|
39
|
+
return memo;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const rawObj = templateLiteral.quasis.map(quasi => quasi.value.raw);
|
|
43
|
+
const template = templateLiteral.quasis.map(quasi => quasi.value.cooked);
|
|
44
|
+
Object.freeze(rawObj);
|
|
45
|
+
Object.defineProperty(template, "raw", {
|
|
46
|
+
value: rawObj,
|
|
47
|
+
writable: false,
|
|
48
|
+
enumerable: false,
|
|
49
|
+
configurable: false
|
|
50
|
+
});
|
|
51
|
+
Object.freeze(template);
|
|
52
|
+
TemplateMap.set(templateLiteral, template);
|
|
53
|
+
return template;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function Evaluate(node, optionalChainRef) {
|
|
57
|
+
// Expressions:
|
|
58
|
+
switch (node.type) {
|
|
59
|
+
case "ArrayExpression":
|
|
60
|
+
{
|
|
61
|
+
// https://tc39.es/ecma262/#sec-array-initializer
|
|
62
|
+
const array = [];
|
|
63
|
+
|
|
64
|
+
for (const element of node.elements) {
|
|
65
|
+
if (!element) {
|
|
66
|
+
array.length += 1;
|
|
67
|
+
} else if (element.type === "SpreadElement") {
|
|
68
|
+
const spreadValues = (0, _contextFree.GetValue)(Evaluate(element.argument));
|
|
69
|
+
array.push(...spreadValues);
|
|
70
|
+
} else {
|
|
71
|
+
array.push((0, _contextFree.GetValue)(Evaluate(element)));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (0, _ExecutionContext.NormalCompletion)(array);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case "ArrowFunctionExpression":
|
|
79
|
+
{
|
|
80
|
+
// https://tc39.es/ecma262/#sec-arrow-function-definitions
|
|
81
|
+
ThrowIfFunctionIsInvalid(node);
|
|
82
|
+
const closure = InstantiateArrowFunctionExpression(node);
|
|
83
|
+
return (0, _ExecutionContext.NormalCompletion)(closure);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
case "BinaryExpression":
|
|
87
|
+
{
|
|
88
|
+
const leftRef = Evaluate(node.left);
|
|
89
|
+
const leftValue = (0, _contextFree.GetValue)(leftRef);
|
|
90
|
+
const rightRef = Evaluate(node.right).Value;
|
|
91
|
+
const rightValue = (0, _contextFree.GetValue)(rightRef);
|
|
92
|
+
|
|
93
|
+
if (expressionOnly && node.operator === "|>") {
|
|
94
|
+
// Minimal pipeline operator is supported only in expression-only mode.
|
|
95
|
+
// See https://tc39.es/proposal-pipeline-operator
|
|
96
|
+
// and https://github.com/tc39/proposal-pipeline-operator
|
|
97
|
+
if (typeof rightValue !== "function") {
|
|
98
|
+
const funcName = codeSource.substring(node.right.start, node.right.end);
|
|
99
|
+
throw new TypeError(`${funcName} is not a function`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let thisValue;
|
|
103
|
+
|
|
104
|
+
if (rightRef instanceof _ExecutionContext.ReferenceRecord) {
|
|
105
|
+
if ((0, _contextFree.IsPropertyReference)(rightRef)) {
|
|
106
|
+
thisValue = rightRef.Base;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (0, _ExecutionContext.NormalCompletion)(rightValue.call(thisValue, leftValue));
|
|
111
|
+
} // https://tc39.es/ecma262/#sec-additive-operators
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const result = (0, _contextFree.ApplyStringOrNumericBinaryOperator)(leftValue, node.operator, rightValue);
|
|
115
|
+
return (0, _ExecutionContext.NormalCompletion)(result);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
case "CallExpression":
|
|
119
|
+
{
|
|
120
|
+
// https://tc39.es/ecma262/#sec-function-calls
|
|
121
|
+
const ref = Evaluate(node.callee, optionalChainRef).Value;
|
|
122
|
+
const func = (0, _contextFree.GetValue)(ref);
|
|
123
|
+
|
|
124
|
+
if ((func === undefined || func === null) && (node.optional || optionalChainRef !== null && optionalChainRef !== void 0 && optionalChainRef.skipped)) {
|
|
125
|
+
optionalChainRef.skipped = true;
|
|
126
|
+
return (0, _ExecutionContext.NormalCompletion)(undefined);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
(0, _sanitize.sanitize)(func);
|
|
130
|
+
return EvaluateCall(func, ref, node.arguments, node.callee);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
case "ChainExpression":
|
|
134
|
+
// https://tc39.es/ecma262/#sec-optional-chains
|
|
135
|
+
return Evaluate(node.expression, {});
|
|
136
|
+
|
|
137
|
+
case "ConditionalExpression":
|
|
138
|
+
// https://tc39.es/ecma262/#sec-conditional-operator
|
|
139
|
+
return (0, _ExecutionContext.NormalCompletion)((0, _contextFree.GetValue)(Evaluate((0, _contextFree.GetValue)(Evaluate(node.test)) ? node.consequent : node.alternate)));
|
|
140
|
+
|
|
141
|
+
case "Identifier":
|
|
142
|
+
// https://tc39.es/ecma262/#sec-identifiers
|
|
143
|
+
return (0, _ExecutionContext.NormalCompletion)(ResolveBinding(node.name));
|
|
144
|
+
|
|
145
|
+
case "Literal":
|
|
146
|
+
{
|
|
147
|
+
// https://tc39.es/ecma262/#sec-primary-expression-literals
|
|
148
|
+
if (node.regex) {
|
|
149
|
+
if (node.value === null) {
|
|
150
|
+
// Invalid regular expression fails silently in @babel/parser.
|
|
151
|
+
throw new SyntaxError(`Invalid regular expression: ${node.raw}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (node.regex.flags.includes("u")) {
|
|
155
|
+
// Currently unicode flag is not fully supported across major browsers.
|
|
156
|
+
throw new SyntaxError(`Unsupported unicode flag in regular expression: ${node.raw}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return (0, _ExecutionContext.NormalCompletion)(node.value);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
case "LogicalExpression":
|
|
164
|
+
{
|
|
165
|
+
// https://tc39.es/ecma262/#sec-binary-logical-operators
|
|
166
|
+
const leftValue = (0, _contextFree.GetValue)(Evaluate(node.left));
|
|
167
|
+
|
|
168
|
+
switch (node.operator) {
|
|
169
|
+
case "&&":
|
|
170
|
+
return (0, _ExecutionContext.NormalCompletion)(leftValue && (0, _contextFree.GetValue)(Evaluate(node.right)));
|
|
171
|
+
|
|
172
|
+
case "||":
|
|
173
|
+
return (0, _ExecutionContext.NormalCompletion)(leftValue || (0, _contextFree.GetValue)(Evaluate(node.right)));
|
|
174
|
+
|
|
175
|
+
case "??":
|
|
176
|
+
return (0, _ExecutionContext.NormalCompletion)(leftValue !== null && leftValue !== void 0 ? leftValue : (0, _contextFree.GetValue)(Evaluate(node.right)));
|
|
177
|
+
// istanbul ignore next
|
|
178
|
+
|
|
179
|
+
default:
|
|
180
|
+
throw new SyntaxError( // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
181
|
+
// @ts-ignore never reach here.
|
|
182
|
+
`Unsupported logical operator '${node.operator}'`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
case "MemberExpression":
|
|
187
|
+
{
|
|
188
|
+
// https://tc39.es/ecma262/#sec-property-accessors
|
|
189
|
+
const baseReference = Evaluate(node.object, optionalChainRef).Value;
|
|
190
|
+
const baseValue = (0, _contextFree.GetValue)(baseReference);
|
|
191
|
+
|
|
192
|
+
if ((baseValue === undefined || baseValue === null) && (node.optional || optionalChainRef !== null && optionalChainRef !== void 0 && optionalChainRef.skipped)) {
|
|
193
|
+
optionalChainRef.skipped = true;
|
|
194
|
+
return (0, _ExecutionContext.NormalCompletion)(undefined);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
(0, _sanitize.sanitize)(baseValue);
|
|
198
|
+
const result = node.computed ? EvaluatePropertyAccessWithExpressionKey(baseValue, node.property, true) : EvaluatePropertyAccessWithIdentifierKey(baseValue, node.property, true);
|
|
199
|
+
(0, _sanitize.sanitize)(result);
|
|
200
|
+
return (0, _ExecutionContext.NormalCompletion)(result);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
case "NewExpression":
|
|
204
|
+
// https://tc39.es/ecma262/#sec-new-operator
|
|
205
|
+
return EvaluateNew(node.callee, node.arguments);
|
|
206
|
+
|
|
207
|
+
case "ObjectExpression":
|
|
208
|
+
{
|
|
209
|
+
// https://tc39.es/ecma262/#sec-object-initializer
|
|
210
|
+
const object = {};
|
|
211
|
+
|
|
212
|
+
for (const prop of node.properties) {
|
|
213
|
+
if (prop.type === "SpreadElement") {
|
|
214
|
+
const fromValue = (0, _contextFree.GetValue)(Evaluate(prop.argument));
|
|
215
|
+
(0, _contextFree.CopyDataProperties)(object, fromValue, new Set());
|
|
216
|
+
} else {
|
|
217
|
+
if (prop.kind !== "init") {
|
|
218
|
+
throw new SyntaxError("Unsupported object getter/setter");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const propName = !prop.computed && prop.key.type === "Identifier" ? prop.key.name : EvaluateComputedPropertyName(prop.key);
|
|
222
|
+
|
|
223
|
+
if (propName === "__proto__") {
|
|
224
|
+
throw new TypeError("Setting '__proto__' property is not allowed");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
object[propName] = (0, _contextFree.GetValue)(Evaluate(prop.value));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return (0, _ExecutionContext.NormalCompletion)(object);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
case "SequenceExpression":
|
|
235
|
+
{
|
|
236
|
+
// https://tc39.es/ecma262/#sec-comma-operator
|
|
237
|
+
let result;
|
|
238
|
+
|
|
239
|
+
for (const expr of node.expressions) {
|
|
240
|
+
result = (0, _ExecutionContext.NormalCompletion)((0, _contextFree.GetValue)(Evaluate(expr)));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
case "TemplateLiteral":
|
|
247
|
+
{
|
|
248
|
+
// https://tc39.es/ecma262/#sec-template-literals
|
|
249
|
+
const chunks = [node.quasis[0].value.cooked];
|
|
250
|
+
let index = 0;
|
|
251
|
+
|
|
252
|
+
for (const expr of node.expressions) {
|
|
253
|
+
const val = (0, _contextFree.GetValue)(Evaluate(expr));
|
|
254
|
+
chunks.push(String(val));
|
|
255
|
+
chunks.push(node.quasis[index += 1].value.cooked);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return (0, _ExecutionContext.NormalCompletion)(chunks.join(""));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
case "TaggedTemplateExpression":
|
|
262
|
+
{
|
|
263
|
+
// https://tc39.es/ecma262/#sec-tagged-templates
|
|
264
|
+
const tagRef = Evaluate(node.tag).Value;
|
|
265
|
+
const tagFunc = (0, _contextFree.GetValue)(tagRef);
|
|
266
|
+
(0, _sanitize.sanitize)(tagFunc);
|
|
267
|
+
return EvaluateCall(tagFunc, tagRef, node.quasi, node.tag);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
case "UnaryExpression":
|
|
271
|
+
{
|
|
272
|
+
// https://tc39.es/ecma262/#sec-unary-operators
|
|
273
|
+
const ref = Evaluate(node.argument).Value;
|
|
274
|
+
|
|
275
|
+
if (!expressionOnly && node.operator === "delete") {
|
|
276
|
+
// Delete operator is supported only in function mode.
|
|
277
|
+
if (!(ref instanceof _ExecutionContext.ReferenceRecord)) {
|
|
278
|
+
return (0, _ExecutionContext.NormalCompletion)(true);
|
|
279
|
+
} // istanbul ignore else
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
if ((0, _contextFree.IsPropertyReference)(ref)) {
|
|
283
|
+
const deleteStatus = delete ref.Base[ref.ReferenceName];
|
|
284
|
+
return (0, _ExecutionContext.NormalCompletion)(deleteStatus);
|
|
285
|
+
} // Should never reach here in strict mode.
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (node.operator === "typeof") {
|
|
290
|
+
if (ref instanceof _ExecutionContext.ReferenceRecord && ref.Base === "unresolvable") {
|
|
291
|
+
return (0, _ExecutionContext.NormalCompletion)("undefined");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return (0, _ExecutionContext.NormalCompletion)(typeof (0, _contextFree.GetValue)(ref));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return (0, _ExecutionContext.NormalCompletion)((0, _contextFree.ApplyUnaryOperator)((0, _contextFree.GetValue)(ref), node.operator));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!expressionOnly) {
|
|
302
|
+
// Statements and assignments:
|
|
303
|
+
switch (node.type) {
|
|
304
|
+
case "AssignmentExpression":
|
|
305
|
+
{
|
|
306
|
+
// https://tc39.es/ecma262/#sec-assignment-operators
|
|
307
|
+
if (node.operator === "=") {
|
|
308
|
+
if (!(node.left.type === "ArrayPattern" || node.left.type === "ObjectPattern")) {
|
|
309
|
+
const lref = Evaluate(node.left).Value; // Todo: IsAnonymousFunctionDefinition(lref)
|
|
310
|
+
|
|
311
|
+
const rref = Evaluate(node.right);
|
|
312
|
+
const rval = (0, _contextFree.GetValue)(rref);
|
|
313
|
+
(0, _contextFree.PutValue)(lref, rval);
|
|
314
|
+
return (0, _ExecutionContext.NormalCompletion)(rval);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const rref = Evaluate(node.right);
|
|
318
|
+
const rval = (0, _contextFree.GetValue)(rref);
|
|
319
|
+
DestructuringAssignmentEvaluation(node.left, rval);
|
|
320
|
+
return (0, _ExecutionContext.NormalCompletion)(rval);
|
|
321
|
+
} // Operators other than `=`.
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
const lref = Evaluate(node.left).Value;
|
|
325
|
+
const lval = (0, _contextFree.GetValue)(lref);
|
|
326
|
+
const rref = Evaluate(node.right);
|
|
327
|
+
const rval = (0, _contextFree.GetValue)(rref);
|
|
328
|
+
const r = (0, _contextFree.ApplyStringOrNumericAssignment)(lval, node.operator, rval);
|
|
329
|
+
(0, _contextFree.PutValue)(lref, r);
|
|
330
|
+
return (0, _ExecutionContext.NormalCompletion)(r);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
case "BlockStatement":
|
|
334
|
+
{
|
|
335
|
+
// https://tc39.es/ecma262/#sec-block
|
|
336
|
+
if (!node.body.length) {
|
|
337
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
341
|
+
const blockEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
342
|
+
BlockDeclarationInstantiation(node.body, blockEnv);
|
|
343
|
+
getRunningContext().LexicalEnvironment = blockEnv;
|
|
344
|
+
const blockValue = EvaluateStatementList(node.body);
|
|
345
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
346
|
+
return blockValue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
case "BreakStatement":
|
|
350
|
+
// https://tc39.es/ecma262/#sec-break-statement
|
|
351
|
+
return new _ExecutionContext.CompletionRecord("break", _ExecutionContext.Empty);
|
|
352
|
+
|
|
353
|
+
case "ContinueStatement":
|
|
354
|
+
// https://tc39.es/ecma262/#sec-continue-statement
|
|
355
|
+
return new _ExecutionContext.CompletionRecord("continue", _ExecutionContext.Empty);
|
|
356
|
+
|
|
357
|
+
case "EmptyStatement":
|
|
358
|
+
// https://tc39.es/ecma262/#sec-empty-statement
|
|
359
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
360
|
+
|
|
361
|
+
case "DoWhileStatement":
|
|
362
|
+
// https://tc39.es/ecma262/#sec-do-while-statement
|
|
363
|
+
return EvaluateBreakableStatement(DoWhileLoopEvaluation(node));
|
|
364
|
+
|
|
365
|
+
case "ExpressionStatement":
|
|
366
|
+
case "TSAsExpression":
|
|
367
|
+
// https://tc39.es/ecma262/#sec-expression-statement
|
|
368
|
+
return Evaluate(node.expression);
|
|
369
|
+
|
|
370
|
+
case "ForInStatement":
|
|
371
|
+
case "ForOfStatement":
|
|
372
|
+
// https://tc39.es/ecma262/#sec-for-in-and-for-of-statements
|
|
373
|
+
return EvaluateBreakableStatement(ForInOfLoopEvaluation(node));
|
|
374
|
+
|
|
375
|
+
case "ForStatement":
|
|
376
|
+
// https://tc39.es/ecma262/#sec-for-statement
|
|
377
|
+
return EvaluateBreakableStatement(ForLoopEvaluation(node));
|
|
378
|
+
|
|
379
|
+
case "FunctionDeclaration":
|
|
380
|
+
// https://tc39.es/ecma262/#sec-function-definitions
|
|
381
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
382
|
+
|
|
383
|
+
case "FunctionExpression":
|
|
384
|
+
// https://tc39.es/ecma262/#sec-function-defining-expressions
|
|
385
|
+
ThrowIfFunctionIsInvalid(node);
|
|
386
|
+
return (0, _ExecutionContext.NormalCompletion)(InstantiateOrdinaryFunctionExpression(node));
|
|
387
|
+
|
|
388
|
+
case "IfStatement":
|
|
389
|
+
// https://tc39.es/ecma262/#sec-if-statement
|
|
390
|
+
return (0, _contextFree.GetValue)(Evaluate(node.test)) ? (0, _contextFree.UpdateEmpty)(Evaluate(node.consequent), undefined) : node.alternate ? (0, _contextFree.UpdateEmpty)(Evaluate(node.alternate), undefined) : (0, _ExecutionContext.NormalCompletion)(undefined);
|
|
391
|
+
|
|
392
|
+
case "ReturnStatement":
|
|
393
|
+
{
|
|
394
|
+
// https://tc39.es/ecma262/#sec-return-statement
|
|
395
|
+
let v;
|
|
396
|
+
|
|
397
|
+
if (node.argument) {
|
|
398
|
+
const exprRef = Evaluate(node.argument);
|
|
399
|
+
v = (0, _contextFree.GetValue)(exprRef);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return new _ExecutionContext.CompletionRecord("return", v);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
case "ThrowStatement":
|
|
406
|
+
// https://tc39.es/ecma262/#sec-throw-statement
|
|
407
|
+
throw (0, _contextFree.GetValue)(Evaluate(node.argument));
|
|
408
|
+
|
|
409
|
+
case "UpdateExpression":
|
|
410
|
+
{
|
|
411
|
+
// https://tc39.es/ecma262/#sec-update-expressions
|
|
412
|
+
const lhs = Evaluate(node.argument).Value;
|
|
413
|
+
const oldValue = Number((0, _contextFree.GetValue)(lhs));
|
|
414
|
+
const newValue = node.operator === "++" ? oldValue + 1 : oldValue - 1;
|
|
415
|
+
(0, _contextFree.PutValue)(lhs, newValue);
|
|
416
|
+
return (0, _ExecutionContext.NormalCompletion)(node.prefix ? newValue : oldValue);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
case "SwitchCase":
|
|
420
|
+
return EvaluateStatementList(node.consequent);
|
|
421
|
+
|
|
422
|
+
case "SwitchStatement":
|
|
423
|
+
{
|
|
424
|
+
// https://tc39.es/ecma262/#sec-switch-statement
|
|
425
|
+
const exprRef = Evaluate(node.discriminant);
|
|
426
|
+
const switchValue = (0, _contextFree.GetValue)(exprRef);
|
|
427
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
428
|
+
const blockEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
429
|
+
BlockDeclarationInstantiation(node.cases, blockEnv);
|
|
430
|
+
getRunningContext().LexicalEnvironment = blockEnv;
|
|
431
|
+
const R = CaseBlockEvaluation(node.cases, switchValue);
|
|
432
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
433
|
+
return EvaluateBreakableStatement(R);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
case "TryStatement":
|
|
437
|
+
{
|
|
438
|
+
// https://tc39.es/ecma262/#sec-try-statement
|
|
439
|
+
let R;
|
|
440
|
+
|
|
441
|
+
try {
|
|
442
|
+
R = Evaluate(node.block);
|
|
443
|
+
} catch (error) {
|
|
444
|
+
if (node.handler) {
|
|
445
|
+
R = CatchClauseEvaluation(node.handler, error);
|
|
446
|
+
} else {
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
} finally {
|
|
450
|
+
if (node.finalizer) {
|
|
451
|
+
const F = Evaluate(node.finalizer);
|
|
452
|
+
|
|
453
|
+
if (F.Type !== "normal") {
|
|
454
|
+
R = F;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return R;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
case "VariableDeclaration":
|
|
463
|
+
{
|
|
464
|
+
// https://tc39.es/ecma262/#sec-declarations-and-the-variable-statement
|
|
465
|
+
let result;
|
|
466
|
+
|
|
467
|
+
for (const declarator of node.declarations) {
|
|
468
|
+
if (!declarator.init) {
|
|
469
|
+
// Assert: a declarator without init is always an identifier.
|
|
470
|
+
if (node.kind === "var") {
|
|
471
|
+
result = (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
472
|
+
} else {
|
|
473
|
+
const lhs = ResolveBinding(declarator.id.name);
|
|
474
|
+
result = (0, _contextFree.InitializeReferencedBinding)(lhs, undefined);
|
|
475
|
+
}
|
|
476
|
+
} else if (declarator.id.type === "Identifier") {
|
|
477
|
+
const bindingId = declarator.id.name;
|
|
478
|
+
const lhs = ResolveBinding(bindingId); // Todo: IsAnonymousFunctionDefinition(Initializer)
|
|
479
|
+
|
|
480
|
+
const rhs = Evaluate(declarator.init);
|
|
481
|
+
const value = (0, _contextFree.GetValue)(rhs);
|
|
482
|
+
result = node.kind === "var" ? (0, _contextFree.PutValue)(lhs, value) : (0, _contextFree.InitializeReferencedBinding)(lhs, value);
|
|
483
|
+
} else {
|
|
484
|
+
const rhs = Evaluate(declarator.init);
|
|
485
|
+
const rval = (0, _contextFree.GetValue)(rhs);
|
|
486
|
+
result = BindingInitialization(declarator.id, rval, node.kind === "var" ? undefined : getRunningContext().LexicalEnvironment);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return result;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
case "WhileStatement":
|
|
494
|
+
// https://tc39.es/ecma262/#sec-while-statement
|
|
495
|
+
return EvaluateBreakableStatement(WhileLoopEvaluation(node));
|
|
496
|
+
}
|
|
497
|
+
} // eslint-disable-next-line no-console
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
throw new SyntaxError(`Unsupported node type \`${node.type}\``);
|
|
501
|
+
} // https://tc39.es/ecma262/#sec-execution-contexts
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
function getRunningContext() {
|
|
505
|
+
return executionContextStack[executionContextStack.length - 1];
|
|
506
|
+
} // https://tc39.es/ecma262/#sec-resolvebinding
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
function ResolveBinding(name, env) {
|
|
510
|
+
if (!env) {
|
|
511
|
+
env = getRunningContext().LexicalEnvironment;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return (0, _contextFree.GetIdentifierReference)(env, name, true);
|
|
515
|
+
} // Try statements.
|
|
516
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-catchclauseevaluation
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
function CatchClauseEvaluation(node, thrownValue) {
|
|
520
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
521
|
+
const catchEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
522
|
+
|
|
523
|
+
for (const argName of (0, _traverse.collectBoundNames)(node.param)) {
|
|
524
|
+
catchEnv.CreateMutableBinding(argName, false);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
getRunningContext().LexicalEnvironment = catchEnv;
|
|
528
|
+
BindingInitialization(node.param, thrownValue, catchEnv);
|
|
529
|
+
const B = Evaluate(node.body);
|
|
530
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
531
|
+
return B;
|
|
532
|
+
} // Iteration statements and switch statements.
|
|
533
|
+
// https://tc39.es/ecma262/#prod-BreakableStatement
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
function EvaluateBreakableStatement(stmtResult) {
|
|
537
|
+
return stmtResult.Type === "break" ? stmtResult.Value === _ExecutionContext.Empty ? (0, _ExecutionContext.NormalCompletion)(undefined) : (0, _ExecutionContext.NormalCompletion)(stmtResult.Value) : stmtResult;
|
|
538
|
+
} // Switch statements.
|
|
539
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-caseblockevaluation
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
function CaseBlockEvaluation(cases, input) {
|
|
543
|
+
let V;
|
|
544
|
+
const defaultCaseIndex = cases.findIndex(switchCase => !switchCase.test);
|
|
545
|
+
const hasDefaultCase = defaultCaseIndex >= 0;
|
|
546
|
+
const A = hasDefaultCase ? cases.slice(0, defaultCaseIndex) : cases;
|
|
547
|
+
let found = false;
|
|
548
|
+
|
|
549
|
+
for (const C of A) {
|
|
550
|
+
if (!found) {
|
|
551
|
+
found = CaseClauseIsSelected(C, input);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (found) {
|
|
555
|
+
const R = Evaluate(C);
|
|
556
|
+
|
|
557
|
+
if (R.Value !== _ExecutionContext.Empty) {
|
|
558
|
+
V = R.Value;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (R.Type !== "normal") {
|
|
562
|
+
return (0, _contextFree.UpdateEmpty)(R, V);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (!hasDefaultCase) {
|
|
568
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
let foundInB = false;
|
|
572
|
+
const B = cases.slice(defaultCaseIndex + 1);
|
|
573
|
+
|
|
574
|
+
if (!found) {
|
|
575
|
+
for (const C of B) {
|
|
576
|
+
if (!foundInB) {
|
|
577
|
+
foundInB = CaseClauseIsSelected(C, input);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (foundInB) {
|
|
581
|
+
const R = Evaluate(C);
|
|
582
|
+
|
|
583
|
+
if (R.Value !== _ExecutionContext.Empty) {
|
|
584
|
+
V = R.Value;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (R.Type !== "normal") {
|
|
588
|
+
return (0, _contextFree.UpdateEmpty)(R, V);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (foundInB) {
|
|
595
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const R = Evaluate(cases[defaultCaseIndex]);
|
|
599
|
+
|
|
600
|
+
if (R.Value !== _ExecutionContext.Empty) {
|
|
601
|
+
V = R.Value;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (R.Type !== "normal") {
|
|
605
|
+
return (0, _contextFree.UpdateEmpty)(R, V);
|
|
606
|
+
} // NOTE: The following is another complete iteration of the second CaseClauses.
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
for (const C of B) {
|
|
610
|
+
const R = Evaluate(C);
|
|
611
|
+
|
|
612
|
+
if (R.Value !== _ExecutionContext.Empty) {
|
|
613
|
+
V = R.Value;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (R.Type !== "normal") {
|
|
617
|
+
return (0, _contextFree.UpdateEmpty)(R, V);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
622
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-caseclauseisselected
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
function CaseClauseIsSelected(C, input) {
|
|
626
|
+
const clauseSelector = (0, _contextFree.GetValue)(Evaluate(C.test));
|
|
627
|
+
return input === clauseSelector;
|
|
628
|
+
} // While statements.
|
|
629
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-whileloopevaluation
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
function WhileLoopEvaluation(node) {
|
|
633
|
+
let V; // eslint-disable-next-line no-constant-condition
|
|
634
|
+
|
|
635
|
+
while (true) {
|
|
636
|
+
const exprValue = (0, _contextFree.GetValue)(Evaluate(node.test));
|
|
637
|
+
|
|
638
|
+
if (!exprValue) {
|
|
639
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const stmtResult = Evaluate(node.body);
|
|
643
|
+
|
|
644
|
+
if (!(0, _contextFree.LoopContinues)(stmtResult)) {
|
|
645
|
+
return (0, _contextFree.UpdateEmpty)(stmtResult, V);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (stmtResult.Value !== _ExecutionContext.Empty) {
|
|
649
|
+
V = stmtResult.Value;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
} // Do-while Statements.
|
|
653
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-dowhileloopevaluation
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
function DoWhileLoopEvaluation(node) {
|
|
657
|
+
let V; // eslint-disable-next-line no-constant-condition
|
|
658
|
+
|
|
659
|
+
while (true) {
|
|
660
|
+
const stmtResult = Evaluate(node.body);
|
|
661
|
+
|
|
662
|
+
if (!(0, _contextFree.LoopContinues)(stmtResult)) {
|
|
663
|
+
return (0, _contextFree.UpdateEmpty)(stmtResult, V);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (stmtResult.Value !== _ExecutionContext.Empty) {
|
|
667
|
+
V = stmtResult.Value;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const exprValue = (0, _contextFree.GetValue)(Evaluate(node.test));
|
|
671
|
+
|
|
672
|
+
if (!exprValue) {
|
|
673
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
} // For in/of statements.
|
|
677
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-forinofloopevaluation
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
function ForInOfLoopEvaluation(node) {
|
|
681
|
+
const lhs = node.left;
|
|
682
|
+
const isVariableDeclaration = lhs.type === "VariableDeclaration";
|
|
683
|
+
const lhsKind = isVariableDeclaration ? lhs.kind === "var" ? "varBinding" : "lexicalBinding" : "assignment";
|
|
684
|
+
const uninitializedBoundNames = lhsKind === "lexicalBinding" ? (0, _traverse.collectBoundNames)(lhs) : [];
|
|
685
|
+
const iterationKind = node.type === "ForInStatement" ? "enumerate" : "iterate";
|
|
686
|
+
const keyResult = ForInOfHeadEvaluation(uninitializedBoundNames, node.right, iterationKind);
|
|
687
|
+
|
|
688
|
+
if (keyResult.Type !== "normal") {
|
|
689
|
+
// When enumerate, if the target is nil, a break completion will be returned.
|
|
690
|
+
return keyResult;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return ForInOfBodyEvaluation(lhs, node.body, keyResult.Value, iterationKind, lhsKind);
|
|
694
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-forinofheadevaluation
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
function ForInOfHeadEvaluation(uninitializedBoundNames, expr, iterationKind) {
|
|
698
|
+
const runningContext = getRunningContext();
|
|
699
|
+
const oldEnv = runningContext.LexicalEnvironment;
|
|
700
|
+
|
|
701
|
+
if (uninitializedBoundNames.length > 0) {
|
|
702
|
+
const newEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
703
|
+
|
|
704
|
+
for (const name of uninitializedBoundNames) {
|
|
705
|
+
newEnv.CreateMutableBinding(name, false);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
runningContext.LexicalEnvironment = newEnv;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
const exprRef = Evaluate(expr);
|
|
712
|
+
runningContext.LexicalEnvironment = oldEnv;
|
|
713
|
+
const exprValue = (0, _contextFree.GetValue)(exprRef);
|
|
714
|
+
|
|
715
|
+
if (iterationKind === "enumerate") {
|
|
716
|
+
if (exprValue === null || exprValue === undefined) {
|
|
717
|
+
return new _ExecutionContext.CompletionRecord("break", _ExecutionContext.Empty);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const iterator = EnumerateObjectProperties(exprValue);
|
|
721
|
+
return (0, _ExecutionContext.NormalCompletion)(iterator);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const iterator = (0, _contextFree.CreateListIteratorRecord)(exprValue);
|
|
725
|
+
return (0, _ExecutionContext.NormalCompletion)(iterator);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
function ForInOfBodyEvaluation(node, stmt, iteratorRecord, iterationKind, lhsKind) {
|
|
729
|
+
const lhs = lhsKind === "assignment" ? node : node.declarations[0].id;
|
|
730
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
731
|
+
let V; // When `destructuring` is false,
|
|
732
|
+
// For `node` whose `kind` is assignment:
|
|
733
|
+
// `lhs` is an `Identifier` or a `MemberExpression`,
|
|
734
|
+
// Otherwise:
|
|
735
|
+
// `lhs` is an `Identifier`.
|
|
736
|
+
|
|
737
|
+
const destructuring = lhs.type === "ObjectPattern" || lhs.type === "ArrayPattern"; // eslint-disable-next-line no-constant-condition
|
|
738
|
+
|
|
739
|
+
while (true) {
|
|
740
|
+
const {
|
|
741
|
+
done,
|
|
742
|
+
value: nextValue
|
|
743
|
+
} = iteratorRecord.next();
|
|
744
|
+
|
|
745
|
+
if (done) {
|
|
746
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
let lhsRef;
|
|
750
|
+
let iterationEnv;
|
|
751
|
+
|
|
752
|
+
if (lhsKind === "lexicalBinding") {
|
|
753
|
+
iterationEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
754
|
+
(0, _contextFree.ForDeclarationBindingInstantiation)(node, iterationEnv);
|
|
755
|
+
getRunningContext().LexicalEnvironment = iterationEnv;
|
|
756
|
+
|
|
757
|
+
if (!destructuring) {
|
|
758
|
+
const [lhsName] = (0, _traverse.collectBoundNames)(lhs);
|
|
759
|
+
lhsRef = ResolveBinding(lhsName);
|
|
760
|
+
}
|
|
761
|
+
} else if (!destructuring) {
|
|
762
|
+
lhsRef = Evaluate(lhs).Value;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
destructuring ? lhsKind === "assignment" ? DestructuringAssignmentEvaluation(lhs, nextValue) : lhsKind === "varBinding" ? BindingInitialization(lhs, nextValue, undefined) : BindingInitialization(lhs, nextValue, iterationEnv) : lhsKind === "lexicalBinding" ? (0, _contextFree.InitializeReferencedBinding)(lhsRef, nextValue) : (0, _contextFree.PutValue)(lhsRef, nextValue);
|
|
766
|
+
const result = Evaluate(stmt);
|
|
767
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
768
|
+
|
|
769
|
+
if (!(0, _contextFree.LoopContinues)(result)) {
|
|
770
|
+
return (0, _contextFree.UpdateEmpty)(result, V);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (result.Value !== _ExecutionContext.Empty) {
|
|
774
|
+
V = result.Value;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
} // https://tc39.es/ecma262/#sec-enumerate-object-properties
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
function* EnumerateObjectProperties(value) {
|
|
781
|
+
for (const key in value) {
|
|
782
|
+
yield key;
|
|
783
|
+
}
|
|
784
|
+
} // For statements.
|
|
785
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-forloopevaluation
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
function ForLoopEvaluation(node) {
|
|
789
|
+
var _node$init;
|
|
790
|
+
|
|
791
|
+
if (((_node$init = node.init) === null || _node$init === void 0 ? void 0 : _node$init.type) === "VariableDeclaration") {
|
|
792
|
+
// `for (var … ; … ; … ) …`
|
|
793
|
+
if (node.init.kind === "var") {
|
|
794
|
+
Evaluate(node.init);
|
|
795
|
+
return ForBodyEvaluation(node.test, node.update, node.body, []);
|
|
796
|
+
} // `for (let/const … ; … ; … ) …`
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
800
|
+
const loopEnv = new _ExecutionContext.DeclarativeEnvironment(oldEnv);
|
|
801
|
+
const isConst = node.init.kind === "const";
|
|
802
|
+
const boundNames = (0, _traverse.collectBoundNames)(node.init);
|
|
803
|
+
|
|
804
|
+
for (const dn of boundNames) {
|
|
805
|
+
if (isConst) {
|
|
806
|
+
loopEnv.CreateImmutableBinding(dn, true);
|
|
807
|
+
} else {
|
|
808
|
+
loopEnv.CreateMutableBinding(dn, false);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
getRunningContext().LexicalEnvironment = loopEnv;
|
|
813
|
+
Evaluate(node.init);
|
|
814
|
+
const perIterationLets = isConst ? [] : Array.from(boundNames);
|
|
815
|
+
const bodyResult = ForBodyEvaluation(node.test, node.update, node.body, perIterationLets);
|
|
816
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
817
|
+
return bodyResult;
|
|
818
|
+
} // `for ( … ; … ; … ) …`
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
if (node.init) {
|
|
822
|
+
const exprRef = Evaluate(node.init);
|
|
823
|
+
(0, _contextFree.GetValue)(exprRef);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
return ForBodyEvaluation(node.test, node.update, node.body, []);
|
|
827
|
+
} // https://tc39.es/ecma262/#sec-forbodyevaluation
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
function ForBodyEvaluation(test, increment, stmt, perIterationBindings) {
|
|
831
|
+
CreatePerIterationEnvironment(perIterationBindings);
|
|
832
|
+
let V; // eslint-disable-next-line no-constant-condition
|
|
833
|
+
|
|
834
|
+
while (true) {
|
|
835
|
+
if (test) {
|
|
836
|
+
const testRef = Evaluate(test);
|
|
837
|
+
const testValue = (0, _contextFree.GetValue)(testRef);
|
|
838
|
+
|
|
839
|
+
if (!testValue) {
|
|
840
|
+
return (0, _ExecutionContext.NormalCompletion)(V);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
const result = Evaluate(stmt);
|
|
845
|
+
|
|
846
|
+
if (!(0, _contextFree.LoopContinues)(result)) {
|
|
847
|
+
return (0, _contextFree.UpdateEmpty)(result, V);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
if (result.Value) {
|
|
851
|
+
V = result.Value;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
CreatePerIterationEnvironment(perIterationBindings);
|
|
855
|
+
|
|
856
|
+
if (increment) {
|
|
857
|
+
const incRef = Evaluate(increment);
|
|
858
|
+
(0, _contextFree.GetValue)(incRef);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
} // https://tc39.es/ecma262/#sec-createperiterationenvironment
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
function CreatePerIterationEnvironment(perIterationBindings) {
|
|
865
|
+
if (perIterationBindings.length === 0) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const lastIterationEnv = getRunningContext().LexicalEnvironment;
|
|
870
|
+
const outer = lastIterationEnv.OuterEnv;
|
|
871
|
+
const thisIterationEnv = new _ExecutionContext.DeclarativeEnvironment(outer);
|
|
872
|
+
|
|
873
|
+
for (const bn of perIterationBindings) {
|
|
874
|
+
thisIterationEnv.CreateMutableBinding(bn, false);
|
|
875
|
+
const lastValue = lastIterationEnv.GetBindingValue(bn, false);
|
|
876
|
+
thisIterationEnv.InitializeBinding(bn, lastValue);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
getRunningContext().LexicalEnvironment = thisIterationEnv;
|
|
880
|
+
} // Destructuring assignments.
|
|
881
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
function DestructuringAssignmentEvaluation(pattern, value) {
|
|
885
|
+
if (pattern.type === "ObjectPattern") {
|
|
886
|
+
(0, _contextFree.RequireObjectCoercible)(value);
|
|
887
|
+
|
|
888
|
+
if (pattern.properties.length > 0) {
|
|
889
|
+
PropertyDestructuringAssignmentEvaluation(pattern.properties, value);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const iteratorRecord = (0, _contextFree.CreateListIteratorRecord)(value);
|
|
896
|
+
return IteratorDestructuringAssignmentEvaluation(pattern.elements, iteratorRecord);
|
|
897
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-propertydestructuringassignmentevaluation
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
function PropertyDestructuringAssignmentEvaluation(properties, value) {
|
|
901
|
+
const excludedNames = new Set();
|
|
902
|
+
|
|
903
|
+
for (const prop of properties) {
|
|
904
|
+
if (prop.type === "Property") {
|
|
905
|
+
const propName = !prop.computed && prop.key.type === "Identifier" ? prop.key.name : EvaluateComputedPropertyName(prop.key);
|
|
906
|
+
const valueTarget = prop.value.type === "AssignmentPattern" ? prop.value.left : prop.value;
|
|
907
|
+
|
|
908
|
+
if (valueTarget.type === "Identifier") {
|
|
909
|
+
const lref = ResolveBinding(valueTarget.name);
|
|
910
|
+
let v = (0, _contextFree.GetV)(value, propName);
|
|
911
|
+
|
|
912
|
+
if (prop.value.type === "AssignmentPattern" && v === undefined) {
|
|
913
|
+
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
914
|
+
const defaultValue = Evaluate(prop.value.right);
|
|
915
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
(0, _contextFree.PutValue)(lref, v);
|
|
919
|
+
excludedNames.add(propName);
|
|
920
|
+
} else {
|
|
921
|
+
KeyedDestructuringAssignmentEvaluation(prop.value, value, propName);
|
|
922
|
+
excludedNames.add(propName);
|
|
923
|
+
}
|
|
924
|
+
} else {
|
|
925
|
+
RestDestructuringAssignmentEvaluation(prop, value, excludedNames);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-keyeddestructuringassignmentevaluation
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
function KeyedDestructuringAssignmentEvaluation(node, value, propertyName) {
|
|
932
|
+
const assignmentTarget = node.type === "AssignmentPattern" ? node.left : node;
|
|
933
|
+
const isObjectOrArray = assignmentTarget.type === "ArrayPattern" || assignmentTarget.type === "ObjectPattern";
|
|
934
|
+
let lref;
|
|
935
|
+
|
|
936
|
+
if (!isObjectOrArray) {
|
|
937
|
+
lref = Evaluate(assignmentTarget).Value;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const v = (0, _contextFree.GetV)(value, propertyName);
|
|
941
|
+
let rhsValue;
|
|
942
|
+
|
|
943
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
944
|
+
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
945
|
+
const defaultValue = Evaluate(node.right);
|
|
946
|
+
rhsValue = (0, _contextFree.GetValue)(defaultValue);
|
|
947
|
+
} else {
|
|
948
|
+
rhsValue = v;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
if (isObjectOrArray) {
|
|
952
|
+
return DestructuringAssignmentEvaluation(assignmentTarget, rhsValue);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
return (0, _contextFree.PutValue)(lref, rhsValue);
|
|
956
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-restdestructuringassignmentevaluation
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
function RestDestructuringAssignmentEvaluation(restProperty, value, excludedNames) {
|
|
960
|
+
const lref = Evaluate(restProperty.argument).Value;
|
|
961
|
+
const restObj = (0, _contextFree.CopyDataProperties)({}, value, excludedNames);
|
|
962
|
+
return (0, _contextFree.PutValue)(lref, restObj);
|
|
963
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-iteratordestructuringassignmentevaluation
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
function IteratorDestructuringAssignmentEvaluation(elements, iteratorRecord) {
|
|
967
|
+
let status = (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
968
|
+
|
|
969
|
+
for (const element of elements) {
|
|
970
|
+
if (!element) {
|
|
971
|
+
iteratorRecord.next();
|
|
972
|
+
status = (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const assignmentTarget = element.type === "RestElement" ? element.argument : element.type === "AssignmentPattern" ? element.left : element;
|
|
977
|
+
const isObjectOrArray = assignmentTarget.type === "ArrayPattern" || assignmentTarget.type === "ObjectPattern";
|
|
978
|
+
let lref;
|
|
979
|
+
|
|
980
|
+
if (!isObjectOrArray) {
|
|
981
|
+
lref = Evaluate(assignmentTarget).Value;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
let v;
|
|
985
|
+
|
|
986
|
+
if (element.type !== "RestElement") {
|
|
987
|
+
const {
|
|
988
|
+
done,
|
|
989
|
+
value: nextValue
|
|
990
|
+
} = iteratorRecord.next();
|
|
991
|
+
const value = done ? undefined : nextValue;
|
|
992
|
+
|
|
993
|
+
if (element.type === "AssignmentPattern" && value === undefined) {
|
|
994
|
+
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
995
|
+
const defaultValue = Evaluate(element.right);
|
|
996
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
997
|
+
} else {
|
|
998
|
+
v = value;
|
|
999
|
+
}
|
|
1000
|
+
} else {
|
|
1001
|
+
// RestElement
|
|
1002
|
+
v = [];
|
|
1003
|
+
let n = 0; // eslint-disable-next-line no-constant-condition
|
|
1004
|
+
|
|
1005
|
+
while (true) {
|
|
1006
|
+
const {
|
|
1007
|
+
done,
|
|
1008
|
+
value: nextValue
|
|
1009
|
+
} = iteratorRecord.next();
|
|
1010
|
+
|
|
1011
|
+
if (done) {
|
|
1012
|
+
break;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
v[n] = nextValue;
|
|
1016
|
+
n++;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
if (isObjectOrArray) {
|
|
1021
|
+
status = DestructuringAssignmentEvaluation(assignmentTarget, v);
|
|
1022
|
+
} else {
|
|
1023
|
+
status = (0, _contextFree.PutValue)(lref, v);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
return status;
|
|
1028
|
+
} // Object expressions.
|
|
1029
|
+
// https://tc39.es/ecma262/#sec-evaluate-property-access-with-expression-key
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
function EvaluatePropertyAccessWithExpressionKey(baseValue, expression, strict) {
|
|
1033
|
+
const propertyNameReference = Evaluate(expression);
|
|
1034
|
+
const propertyNameValue = (0, _contextFree.GetValue)(propertyNameReference);
|
|
1035
|
+
const propertyKey = (0, _contextFree.ToPropertyKey)(propertyNameValue);
|
|
1036
|
+
return new _ExecutionContext.ReferenceRecord(baseValue, propertyKey, strict);
|
|
1037
|
+
} // https://tc39.es/ecma262/#sec-evaluate-property-access-with-identifier-key
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
function EvaluatePropertyAccessWithIdentifierKey(baseValue, identifier, strict) {
|
|
1041
|
+
const propertyNameString = identifier.name;
|
|
1042
|
+
return new _ExecutionContext.ReferenceRecord(baseValue, propertyNameString, strict);
|
|
1043
|
+
} // Block statements.
|
|
1044
|
+
// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
function BlockDeclarationInstantiation(code, env) {
|
|
1048
|
+
const declarations = (0, _traverse.collectScopedDeclarations)(code, {
|
|
1049
|
+
var: false,
|
|
1050
|
+
topLevel: false
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
for (const d of declarations) {
|
|
1054
|
+
const IsConstantDeclaration = d.type === "VariableDeclaration" && d.kind === "const";
|
|
1055
|
+
|
|
1056
|
+
for (const dn of (0, _traverse.collectBoundNames)(d)) {
|
|
1057
|
+
if (IsConstantDeclaration) {
|
|
1058
|
+
env.CreateImmutableBinding(dn, true);
|
|
1059
|
+
} else {
|
|
1060
|
+
env.CreateMutableBinding(dn, false);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (d.type === "FunctionDeclaration") {
|
|
1065
|
+
const [fn] = (0, _traverse.collectBoundNames)(d);
|
|
1066
|
+
const fo = InstantiateFunctionObject(d, env);
|
|
1067
|
+
env.InitializeBinding(fn, fo);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
} // Function declarations and expressions.
|
|
1071
|
+
// https://tc39.es/ecma262/#sec-evaluatecall
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
function EvaluateCall(func, ref, args, callee) {
|
|
1075
|
+
let thisValue;
|
|
1076
|
+
|
|
1077
|
+
if (ref instanceof _ExecutionContext.ReferenceRecord) {
|
|
1078
|
+
if ((0, _contextFree.IsPropertyReference)(ref)) {
|
|
1079
|
+
thisValue = ref.Base;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
const argList = ArgumentListEvaluation(args);
|
|
1084
|
+
|
|
1085
|
+
if (typeof func !== "function") {
|
|
1086
|
+
const funcName = codeSource.substring(callee.start, callee.end);
|
|
1087
|
+
throw new TypeError(`${funcName} is not a function`);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
const result = func.apply(thisValue, argList);
|
|
1091
|
+
(0, _sanitize.sanitize)(result);
|
|
1092
|
+
return (0, _ExecutionContext.NormalCompletion)(result);
|
|
1093
|
+
} // https://tc39.es/ecma262/#sec-evaluatenew
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
function EvaluateNew(constructExpr, args) {
|
|
1097
|
+
const ref = Evaluate(constructExpr);
|
|
1098
|
+
const constructor = (0, _contextFree.GetValue)(ref);
|
|
1099
|
+
const argList = ArgumentListEvaluation(args);
|
|
1100
|
+
|
|
1101
|
+
if (typeof constructor !== "function" || constructor[_ExecutionContext.IsConstructor] === false) {
|
|
1102
|
+
const constructorName = codeSource.substring(constructExpr.start, constructExpr.end);
|
|
1103
|
+
throw new TypeError(`${constructorName} is not a constructor`);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
if (!(0, _sanitize.isAllowedConstructor)(constructor)) {
|
|
1107
|
+
const constructorName = codeSource.substring(constructExpr.start, constructExpr.end);
|
|
1108
|
+
throw new TypeError(`${constructorName} is not an allowed constructor`);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
return (0, _ExecutionContext.NormalCompletion)(new constructor(...argList));
|
|
1112
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
function ArgumentListEvaluation(args) {
|
|
1116
|
+
const array = [];
|
|
1117
|
+
|
|
1118
|
+
if (Array.isArray(args)) {
|
|
1119
|
+
for (const arg of args) {
|
|
1120
|
+
if (arg.type === "SpreadElement") {
|
|
1121
|
+
const spreadValues = (0, _contextFree.GetValue)(Evaluate(arg.argument));
|
|
1122
|
+
array.push(...spreadValues);
|
|
1123
|
+
} else {
|
|
1124
|
+
array.push((0, _contextFree.GetValue)(Evaluate(arg)));
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
} else {
|
|
1128
|
+
array.push(GetTemplateObject(args));
|
|
1129
|
+
|
|
1130
|
+
for (const expr of args.expressions) {
|
|
1131
|
+
array.push((0, _contextFree.GetValue)(Evaluate(expr)));
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
return array;
|
|
1136
|
+
} // https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
function CallFunction(closure, args) {
|
|
1140
|
+
PrepareForOrdinaryCall(closure);
|
|
1141
|
+
const result = OrdinaryCallEvaluateBody(closure, args);
|
|
1142
|
+
executionContextStack.pop();
|
|
1143
|
+
|
|
1144
|
+
if (result.Type === "return") {
|
|
1145
|
+
return result.Value;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
return undefined;
|
|
1149
|
+
} // https://tc39.es/ecma262/#sec-prepareforordinarycall
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
function PrepareForOrdinaryCall(F) {
|
|
1153
|
+
const calleeContext = new _ExecutionContext.ExecutionContext();
|
|
1154
|
+
calleeContext.Function = F;
|
|
1155
|
+
const localEnv = new _ExecutionContext.FunctionEnvironment(F[_ExecutionContext.Environment]);
|
|
1156
|
+
calleeContext.VariableEnvironment = localEnv;
|
|
1157
|
+
calleeContext.LexicalEnvironment = localEnv;
|
|
1158
|
+
executionContextStack.push(calleeContext);
|
|
1159
|
+
return calleeContext;
|
|
1160
|
+
} // https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
function OrdinaryCallEvaluateBody(F, args) {
|
|
1164
|
+
return EvaluateFunctionBody(F[_ExecutionContext.ECMAScriptCode], F, args);
|
|
1165
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-evaluatefunctionbody
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
function EvaluateFunctionBody(body, F, args) {
|
|
1169
|
+
FunctionDeclarationInstantiation(F, args);
|
|
1170
|
+
|
|
1171
|
+
if (Array.isArray(body)) {
|
|
1172
|
+
return EvaluateStatementList(body);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
return new _ExecutionContext.CompletionRecord("return", (0, _contextFree.GetValue)(Evaluate(body)));
|
|
1176
|
+
} // https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
function EvaluateStatementList(statements) {
|
|
1180
|
+
let result = (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
1181
|
+
|
|
1182
|
+
for (const stmt of statements) {
|
|
1183
|
+
const s = Evaluate(stmt);
|
|
1184
|
+
|
|
1185
|
+
if (s.Type !== "normal") {
|
|
1186
|
+
return s;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
result = (0, _contextFree.UpdateEmpty)(result, s.Value);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
return result;
|
|
1193
|
+
} // https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
function FunctionDeclarationInstantiation(func, args) {
|
|
1197
|
+
const calleeContext = getRunningContext();
|
|
1198
|
+
const code = func[_ExecutionContext.ECMAScriptCode];
|
|
1199
|
+
const formals = func[_ExecutionContext.FormalParameters];
|
|
1200
|
+
const parameterNames = (0, _traverse.collectBoundNames)(formals);
|
|
1201
|
+
const hasParameterExpressions = (0, _traverse.containsExpression)(formals);
|
|
1202
|
+
const varDeclarations = (0, _traverse.collectScopedDeclarations)(code, {
|
|
1203
|
+
var: true,
|
|
1204
|
+
topLevel: true
|
|
1205
|
+
});
|
|
1206
|
+
const varNames = (0, _traverse.collectBoundNames)(varDeclarations); // `functionNames` ∈ `varNames`
|
|
1207
|
+
// `functionsToInitialize` ≈ `functionNames`
|
|
1208
|
+
|
|
1209
|
+
const functionNames = [];
|
|
1210
|
+
const functionsToInitialize = [];
|
|
1211
|
+
|
|
1212
|
+
for (let i = varDeclarations.length - 1; i >= 0; i--) {
|
|
1213
|
+
const d = varDeclarations[i];
|
|
1214
|
+
|
|
1215
|
+
if (d.type === "FunctionDeclaration") {
|
|
1216
|
+
ThrowIfFunctionIsInvalid(d);
|
|
1217
|
+
const [fn] = (0, _traverse.collectBoundNames)(d);
|
|
1218
|
+
|
|
1219
|
+
if (!functionNames.includes(fn)) {
|
|
1220
|
+
functionNames.unshift(fn);
|
|
1221
|
+
functionsToInitialize.unshift(d);
|
|
1222
|
+
}
|
|
1223
|
+
} else if (rules !== null && rules !== void 0 && rules.noVar) {
|
|
1224
|
+
throw new SyntaxError("Var declaration is not recommended, use `let` or `const` instead");
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
const env = calleeContext.LexicalEnvironment;
|
|
1229
|
+
|
|
1230
|
+
for (const paramName of parameterNames) {
|
|
1231
|
+
// In strict mode, it's guaranteed no duplicate params exist.
|
|
1232
|
+
env.CreateMutableBinding(paramName, false);
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
const iteratorRecord = (0, _contextFree.CreateListIteratorRecord)(args);
|
|
1236
|
+
IteratorBindingInitialization(formals, iteratorRecord, env);
|
|
1237
|
+
let varEnv;
|
|
1238
|
+
|
|
1239
|
+
if (!hasParameterExpressions) {
|
|
1240
|
+
// NOTE: Only a single Environment Record is needed for the parameters
|
|
1241
|
+
// and top-level vars.
|
|
1242
|
+
// `varNames` are unique.
|
|
1243
|
+
for (const n of varNames) {
|
|
1244
|
+
if (!parameterNames.includes(n)) {
|
|
1245
|
+
env.CreateMutableBinding(n, false);
|
|
1246
|
+
env.InitializeBinding(n, undefined);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
varEnv = env;
|
|
1251
|
+
} else {
|
|
1252
|
+
// NOTE: A separate Environment Record is needed to ensure that closures
|
|
1253
|
+
// created by expressions in the formal parameter list do not have
|
|
1254
|
+
// visibility of declarations in the function body.
|
|
1255
|
+
varEnv = new _ExecutionContext.DeclarativeEnvironment(env);
|
|
1256
|
+
calleeContext.VariableEnvironment = varEnv; // `varNames` are unique.
|
|
1257
|
+
|
|
1258
|
+
for (const n of varNames) {
|
|
1259
|
+
varEnv.CreateMutableBinding(n, false);
|
|
1260
|
+
let initialValue;
|
|
1261
|
+
|
|
1262
|
+
if (parameterNames.includes(n) && !functionNames.includes(n)) {
|
|
1263
|
+
initialValue = env.GetBindingValue(n, false);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
varEnv.InitializeBinding(n, initialValue); // NOTE: A var with the same name as a formal parameter initially has
|
|
1267
|
+
// the same value as the corresponding initialized parameter.
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
const lexEnv = varEnv;
|
|
1272
|
+
calleeContext.LexicalEnvironment = lexEnv;
|
|
1273
|
+
const lexDeclarations = (0, _traverse.collectScopedDeclarations)(code, {
|
|
1274
|
+
var: false,
|
|
1275
|
+
topLevel: true
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
for (const d of lexDeclarations) {
|
|
1279
|
+
for (const dn of (0, _traverse.collectBoundNames)(d)) {
|
|
1280
|
+
// Only lexical VariableDeclaration here in top-level.
|
|
1281
|
+
if (d.kind === "const") {
|
|
1282
|
+
lexEnv.CreateImmutableBinding(dn, true);
|
|
1283
|
+
} else {
|
|
1284
|
+
lexEnv.CreateMutableBinding(dn, false);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
for (const f of functionsToInitialize) {
|
|
1290
|
+
const [fn] = (0, _traverse.collectBoundNames)(f);
|
|
1291
|
+
const fo = InstantiateFunctionObject(f, lexEnv);
|
|
1292
|
+
varEnv.SetMutableBinding(fn, fo, false);
|
|
1293
|
+
}
|
|
1294
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
function InstantiateFunctionObject(func, scope) {
|
|
1298
|
+
return OrdinaryFunctionCreate(func.params, func.body, scope, true);
|
|
1299
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
function InstantiateOrdinaryFunctionExpression(functionExpression) {
|
|
1303
|
+
const scope = getRunningContext().LexicalEnvironment;
|
|
1304
|
+
|
|
1305
|
+
if (functionExpression.id) {
|
|
1306
|
+
const name = functionExpression.id.name;
|
|
1307
|
+
const funcEnv = new _ExecutionContext.DeclarativeEnvironment(scope);
|
|
1308
|
+
funcEnv.CreateImmutableBinding(name, false);
|
|
1309
|
+
const closure = OrdinaryFunctionCreate(functionExpression.params, functionExpression.body, funcEnv, true);
|
|
1310
|
+
funcEnv.InitializeBinding(name, closure);
|
|
1311
|
+
return closure;
|
|
1312
|
+
} else {
|
|
1313
|
+
const closure = OrdinaryFunctionCreate(functionExpression.params, functionExpression.body, scope, true);
|
|
1314
|
+
return closure;
|
|
1315
|
+
}
|
|
1316
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-instantiatearrowfunctionexpression
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
function InstantiateArrowFunctionExpression(arrowFunction) {
|
|
1320
|
+
const scope = getRunningContext().LexicalEnvironment;
|
|
1321
|
+
const closure = OrdinaryFunctionCreate(arrowFunction.params, arrowFunction.body, scope, false);
|
|
1322
|
+
return closure;
|
|
1323
|
+
} // https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
function OrdinaryFunctionCreate(parameterList, body, scope, isConstructor) {
|
|
1327
|
+
const F = function () {
|
|
1328
|
+
// eslint-disable-next-line prefer-rest-params
|
|
1329
|
+
return CallFunction(F, arguments);
|
|
1330
|
+
};
|
|
1331
|
+
|
|
1332
|
+
Object.defineProperties(F, {
|
|
1333
|
+
[_ExecutionContext.FormalParameters]: {
|
|
1334
|
+
enumerable: false,
|
|
1335
|
+
writable: false,
|
|
1336
|
+
value: parameterList
|
|
1337
|
+
},
|
|
1338
|
+
[_ExecutionContext.ECMAScriptCode]: {
|
|
1339
|
+
enumerable: false,
|
|
1340
|
+
writable: false,
|
|
1341
|
+
value: body.type === "BlockStatement" ? body.body : body
|
|
1342
|
+
},
|
|
1343
|
+
[_ExecutionContext.Environment]: {
|
|
1344
|
+
enumerable: false,
|
|
1345
|
+
writable: false,
|
|
1346
|
+
value: scope
|
|
1347
|
+
},
|
|
1348
|
+
[_ExecutionContext.IsConstructor]: {
|
|
1349
|
+
enumerable: false,
|
|
1350
|
+
writable: false,
|
|
1351
|
+
value: isConstructor
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
return F;
|
|
1355
|
+
} // Patterns initialization.
|
|
1356
|
+
// https://tc39.es/ecma262/#sec-runtime-semantics-bindinginitialization
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
function BindingInitialization(node, value, environment) {
|
|
1360
|
+
switch (node.type) {
|
|
1361
|
+
case "Identifier":
|
|
1362
|
+
return InitializeBoundName(node.name, value, environment);
|
|
1363
|
+
|
|
1364
|
+
case "ObjectPattern":
|
|
1365
|
+
(0, _contextFree.RequireObjectCoercible)(value);
|
|
1366
|
+
return PropertyBindingInitialization(node.properties, value, environment);
|
|
1367
|
+
|
|
1368
|
+
case "ArrayPattern":
|
|
1369
|
+
{
|
|
1370
|
+
const iteratorRecord = (0, _contextFree.CreateListIteratorRecord)(value);
|
|
1371
|
+
return IteratorBindingInitialization(node.elements, iteratorRecord, environment);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
} // https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
function PropertyBindingInitialization(properties, value, environment) {
|
|
1378
|
+
const excludedNames = new Set();
|
|
1379
|
+
|
|
1380
|
+
for (const prop of properties) {
|
|
1381
|
+
if (prop.type === "RestElement") {
|
|
1382
|
+
return RestBindingInitialization(prop, value, environment, excludedNames);
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
if (!prop.computed && prop.key.type === "Identifier") {
|
|
1386
|
+
KeyedBindingInitialization(prop.value, value, environment, prop.key.name);
|
|
1387
|
+
excludedNames.add(prop.key.name);
|
|
1388
|
+
} else {
|
|
1389
|
+
const P = EvaluateComputedPropertyName(prop.key);
|
|
1390
|
+
KeyedBindingInitialization(prop.value, value, environment, P);
|
|
1391
|
+
excludedNames.add(P);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
1396
|
+
} // https://tc39.es/ecma262/#prod-ComputedPropertyName
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
function EvaluateComputedPropertyName(node) {
|
|
1400
|
+
const propName = (0, _contextFree.GetValue)(Evaluate(node));
|
|
1401
|
+
return (0, _contextFree.ToPropertyKey)(propName);
|
|
1402
|
+
} // https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-restbindinginitialization
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
function RestBindingInitialization(restProperty, value, environment, excludedNames) {
|
|
1406
|
+
const lhs = ResolveBinding(restProperty.argument.name, environment);
|
|
1407
|
+
const restObj = (0, _contextFree.CopyDataProperties)({}, value, excludedNames);
|
|
1408
|
+
|
|
1409
|
+
if (!environment) {
|
|
1410
|
+
return (0, _contextFree.PutValue)(lhs, restObj);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
return (0, _contextFree.InitializeReferencedBinding)(lhs, restObj);
|
|
1414
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-iteratorbindinginitialization
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
function IteratorBindingInitialization(elements, iteratorRecord, environment) {
|
|
1418
|
+
if (elements.length === 0) {
|
|
1419
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
let result;
|
|
1423
|
+
|
|
1424
|
+
for (const node of elements) {
|
|
1425
|
+
if (!node) {
|
|
1426
|
+
// Elision element.
|
|
1427
|
+
iteratorRecord.next();
|
|
1428
|
+
result = (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
1429
|
+
} else if (node.type === "RestElement") {
|
|
1430
|
+
// Rest element.
|
|
1431
|
+
if (node.argument.type === "Identifier") {
|
|
1432
|
+
const lhs = ResolveBinding(node.argument.name, environment);
|
|
1433
|
+
const A = [];
|
|
1434
|
+
let n = 0; // eslint-disable-next-line no-constant-condition
|
|
1435
|
+
|
|
1436
|
+
while (true) {
|
|
1437
|
+
const {
|
|
1438
|
+
done,
|
|
1439
|
+
value
|
|
1440
|
+
} = iteratorRecord.next();
|
|
1441
|
+
|
|
1442
|
+
if (done) {
|
|
1443
|
+
result = environment ? (0, _contextFree.InitializeReferencedBinding)(lhs, A) : (0, _contextFree.PutValue)(lhs, A);
|
|
1444
|
+
break;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
A[n] = value;
|
|
1448
|
+
n++;
|
|
1449
|
+
}
|
|
1450
|
+
} else {
|
|
1451
|
+
const A = [];
|
|
1452
|
+
let n = 0; // eslint-disable-next-line no-constant-condition
|
|
1453
|
+
|
|
1454
|
+
while (true) {
|
|
1455
|
+
const {
|
|
1456
|
+
done,
|
|
1457
|
+
value
|
|
1458
|
+
} = iteratorRecord.next();
|
|
1459
|
+
|
|
1460
|
+
if (done) {
|
|
1461
|
+
result = BindingInitialization(node.argument, A, environment);
|
|
1462
|
+
break;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
A[n] = value;
|
|
1466
|
+
n++;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
} else {
|
|
1470
|
+
// Normal element.
|
|
1471
|
+
const bindingElement = node.type === "AssignmentPattern" ? node.left : node;
|
|
1472
|
+
|
|
1473
|
+
switch (bindingElement.type) {
|
|
1474
|
+
case "ObjectPattern":
|
|
1475
|
+
case "ArrayPattern":
|
|
1476
|
+
{
|
|
1477
|
+
let v;
|
|
1478
|
+
const {
|
|
1479
|
+
done,
|
|
1480
|
+
value
|
|
1481
|
+
} = iteratorRecord.next();
|
|
1482
|
+
|
|
1483
|
+
if (!done) {
|
|
1484
|
+
v = value;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1488
|
+
const defaultValue = Evaluate(node.right);
|
|
1489
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
result = BindingInitialization(bindingElement, v, environment);
|
|
1493
|
+
break;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
case "Identifier":
|
|
1497
|
+
{
|
|
1498
|
+
const bindingId = bindingElement.name;
|
|
1499
|
+
const lhs = ResolveBinding(bindingId, environment);
|
|
1500
|
+
let v;
|
|
1501
|
+
const {
|
|
1502
|
+
done,
|
|
1503
|
+
value
|
|
1504
|
+
} = iteratorRecord.next();
|
|
1505
|
+
|
|
1506
|
+
if (!done) {
|
|
1507
|
+
v = value;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1511
|
+
// IsAnonymousFunctionDefinition(Initializer)
|
|
1512
|
+
const defaultValue = Evaluate(node.right);
|
|
1513
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
result = environment ? (0, _contextFree.InitializeReferencedBinding)(lhs, v) : (0, _contextFree.PutValue)(lhs, v);
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
return result;
|
|
1524
|
+
} // https://tc39.es/ecma262/#sec-runtime-semantics-keyedbindinginitialization
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
function KeyedBindingInitialization(node, value, environment, propertyName) {
|
|
1528
|
+
const isIdentifier = node.type === "Identifier" || node.type === "AssignmentPattern" && node.left.type === "Identifier";
|
|
1529
|
+
|
|
1530
|
+
if (isIdentifier) {
|
|
1531
|
+
const bindingId = node.type === "Identifier" ? node.name : node.left.name;
|
|
1532
|
+
const lhs = ResolveBinding(bindingId, environment);
|
|
1533
|
+
let v = (0, _contextFree.GetV)(value, propertyName);
|
|
1534
|
+
|
|
1535
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1536
|
+
// If IsAnonymousFunctionDefinition(Initializer)
|
|
1537
|
+
const defaultValue = Evaluate(node.right);
|
|
1538
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
if (!environment) {
|
|
1542
|
+
return (0, _contextFree.PutValue)(lhs, v);
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
return (0, _contextFree.InitializeReferencedBinding)(lhs, v);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
let v = (0, _contextFree.GetV)(value, propertyName);
|
|
1549
|
+
|
|
1550
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1551
|
+
const defaultValue = Evaluate(node.right);
|
|
1552
|
+
v = (0, _contextFree.GetValue)(defaultValue);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
return BindingInitialization(node.type === "AssignmentPattern" ? node.left : node, v, environment);
|
|
1556
|
+
} // https://tc39.es/ecma262/#sec-initializeboundname
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
function InitializeBoundName(name, value, environment) {
|
|
1560
|
+
// Assert: environment is always present.
|
|
1561
|
+
environment.InitializeBinding(name, value);
|
|
1562
|
+
return (0, _ExecutionContext.NormalCompletion)(_ExecutionContext.Empty);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
function ThrowIfFunctionIsInvalid(func) {
|
|
1566
|
+
if (func.async || func.generator) {
|
|
1567
|
+
throw new SyntaxError(`${func.async ? "Async" : "Generator"} function is not allowed`);
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
if (expressionOnly && !func.expression) {
|
|
1571
|
+
throw new SyntaxError("Only an `Expression` is allowed in `ArrowFunctionExpression`'s body");
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
if (expressionOnly) {
|
|
1576
|
+
return (0, _contextFree.GetValue)(Evaluate(rootAst));
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
ThrowIfFunctionIsInvalid(rootAst);
|
|
1580
|
+
const [fn] = (0, _traverse.collectBoundNames)(rootAst); // Create an immutable binding for the root function.
|
|
1581
|
+
|
|
1582
|
+
rootEnv.CreateImmutableBinding(fn, true);
|
|
1583
|
+
const fo = InstantiateFunctionObject(rootAst, rootEnv);
|
|
1584
|
+
rootEnv.InitializeBinding(fn, fo);
|
|
1585
|
+
return fo;
|
|
1586
|
+
}
|
|
1587
|
+
//# sourceMappingURL=cook.js.map
|