@next-core/cook 2.2.16 → 2.2.18
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/dist/cjs/ExecutionContext.js.map +1 -1
- package/dist/cjs/context-free.js.map +1 -1
- package/dist/cjs/cook.js +1 -1
- package/dist/cjs/cook.js.map +1 -1
- package/dist/cjs/lint.js.map +1 -1
- package/dist/cjs/parse.js.map +1 -1
- package/dist/cjs/precook.js.map +1 -1
- package/dist/esm/ExecutionContext.js +12 -12
- package/dist/esm/ExecutionContext.js.map +1 -1
- package/dist/esm/context-free.js +13 -13
- package/dist/esm/context-free.js.map +1 -1
- package/dist/esm/cook.js +367 -366
- package/dist/esm/cook.js.map +1 -1
- package/dist/esm/lint.js +16 -16
- package/dist/esm/lint.js.map +1 -1
- package/dist/esm/parse.js +7 -7
- package/dist/esm/parse.js.map +1 -1
- package/dist/esm/parseForAnalysis.js +1 -1
- package/dist/esm/precook.js +70 -70
- package/dist/esm/precook.js.map +1 -1
- package/dist/esm/precookFunction.js +6 -9
- package/dist/esm/precookFunction.js.map +1 -1
- package/dist/esm/preevaluate.js +6 -6
- package/dist/esm/preevaluate.js.map +1 -1
- package/dist/esm/sanitize.js +2 -2
- package/dist/esm/sanitize.js.map +1 -1
- package/dist/esm/traverse.js +8 -8
- package/dist/esm/traverse.js.map +1 -1
- package/package.json +8 -7
package/dist/esm/cook.js
CHANGED
|
@@ -5,31 +5,31 @@ import { collectBoundNames, collectScopedDeclarations, containsExpression } from
|
|
|
5
5
|
/** For next-core internal usage only. */
|
|
6
6
|
export function cook(rootAst, codeSource) {
|
|
7
7
|
var _hooks$beforeEvaluate3;
|
|
8
|
-
|
|
8
|
+
let {
|
|
9
9
|
rules,
|
|
10
10
|
globalVariables = {},
|
|
11
11
|
hooks = {}
|
|
12
12
|
} = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const expressionOnly = rootAst.type !== "FunctionDeclaration";
|
|
14
|
+
const rootEnv = new DeclarativeEnvironment(null);
|
|
15
|
+
const rootContext = new ExecutionContext();
|
|
16
16
|
rootContext.VariableEnvironment = rootEnv;
|
|
17
17
|
rootContext.LexicalEnvironment = rootEnv;
|
|
18
|
-
|
|
19
|
-
for (
|
|
18
|
+
const executionContextStack = [rootContext];
|
|
19
|
+
for (const [key, value] of Object.entries(globalVariables)) {
|
|
20
20
|
rootEnv.CreateImmutableBinding(key, true);
|
|
21
21
|
rootEnv.InitializeBinding(key, value);
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
const TemplateMap = new WeakMap();
|
|
24
24
|
|
|
25
25
|
// https://tc39.es/ecma262/#sec-gettemplateobject
|
|
26
26
|
function GetTemplateObject(templateLiteral) {
|
|
27
|
-
|
|
27
|
+
const memo = TemplateMap.get(templateLiteral);
|
|
28
28
|
if (memo) {
|
|
29
29
|
return memo;
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const rawObj = templateLiteral.quasis.map(quasi => quasi.value.raw);
|
|
32
|
+
const template = templateLiteral.quasis.map(quasi => quasi.value.cooked);
|
|
33
33
|
Object.freeze(rawObj);
|
|
34
34
|
Object.defineProperty(template, "raw", {
|
|
35
35
|
value: rawObj,
|
|
@@ -49,12 +49,12 @@ export function cook(rootAst, codeSource) {
|
|
|
49
49
|
case "ArrayExpression":
|
|
50
50
|
{
|
|
51
51
|
// https://tc39.es/ecma262/#sec-array-initializer
|
|
52
|
-
|
|
53
|
-
for (
|
|
52
|
+
const array = [];
|
|
53
|
+
for (const element of node.elements) {
|
|
54
54
|
if (!element) {
|
|
55
55
|
array.length += 1;
|
|
56
56
|
} else if (element.type === "SpreadElement") {
|
|
57
|
-
|
|
57
|
+
const spreadValues = GetValue(Evaluate(element.argument));
|
|
58
58
|
array.push(...spreadValues);
|
|
59
59
|
} else {
|
|
60
60
|
array.push(GetValue(Evaluate(element)));
|
|
@@ -66,24 +66,24 @@ export function cook(rootAst, codeSource) {
|
|
|
66
66
|
{
|
|
67
67
|
// https://tc39.es/ecma262/#sec-arrow-function-definitions
|
|
68
68
|
ThrowIfFunctionIsInvalid(node);
|
|
69
|
-
|
|
69
|
+
const closure = InstantiateArrowFunctionExpression(node);
|
|
70
70
|
return NormalCompletion(closure);
|
|
71
71
|
}
|
|
72
72
|
case "BinaryExpression":
|
|
73
73
|
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
const leftRef = Evaluate(node.left);
|
|
75
|
+
const leftValue = GetValue(leftRef);
|
|
76
|
+
const rightRef = Evaluate(node.right).Value;
|
|
77
|
+
const rightValue = GetValue(rightRef);
|
|
78
78
|
if (expressionOnly && node.operator === "|>") {
|
|
79
79
|
// Minimal pipeline operator is supported only in expression-only mode.
|
|
80
80
|
// See https://tc39.es/proposal-pipeline-operator
|
|
81
81
|
// and https://github.com/tc39/proposal-pipeline-operator
|
|
82
82
|
if (typeof rightValue !== "function") {
|
|
83
|
-
|
|
84
|
-
throw new TypeError(
|
|
83
|
+
const funcName = codeSource.substring(node.right.start, node.right.end);
|
|
84
|
+
throw new TypeError(`${funcName} is not a function`);
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
let thisValue;
|
|
87
87
|
if (rightRef instanceof ReferenceRecord) {
|
|
88
88
|
if (IsPropertyReference(rightRef)) {
|
|
89
89
|
thisValue = rightRef.Base;
|
|
@@ -92,14 +92,14 @@ export function cook(rootAst, codeSource) {
|
|
|
92
92
|
return NormalCompletion(rightValue.call(thisValue, leftValue));
|
|
93
93
|
}
|
|
94
94
|
// https://tc39.es/ecma262/#sec-additive-operators
|
|
95
|
-
|
|
95
|
+
const result = ApplyStringOrNumericBinaryOperator(leftValue, node.operator, rightValue);
|
|
96
96
|
return NormalCompletion(result);
|
|
97
97
|
}
|
|
98
98
|
case "CallExpression":
|
|
99
99
|
{
|
|
100
100
|
// https://tc39.es/ecma262/#sec-function-calls
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
const ref = Evaluate(node.callee, optionalChainRef).Value;
|
|
102
|
+
const func = GetValue(ref);
|
|
103
103
|
if ((func === undefined || func === null) && (node.optional || optionalChainRef !== null && optionalChainRef !== void 0 && optionalChainRef.skipped)) {
|
|
104
104
|
optionalChainRef.skipped = true;
|
|
105
105
|
return NormalCompletion(undefined);
|
|
@@ -122,11 +122,11 @@ export function cook(rootAst, codeSource) {
|
|
|
122
122
|
if (node.regex) {
|
|
123
123
|
if (node.value === null) {
|
|
124
124
|
// Invalid regular expression fails silently in @babel/parser.
|
|
125
|
-
throw new SyntaxError(
|
|
125
|
+
throw new SyntaxError(`Invalid regular expression: ${node.raw}`);
|
|
126
126
|
}
|
|
127
127
|
if (node.regex.flags.includes("u")) {
|
|
128
128
|
// Currently unicode flag is not fully supported across major browsers.
|
|
129
|
-
throw new SyntaxError(
|
|
129
|
+
throw new SyntaxError(`Unsupported unicode flag in regular expression: ${node.raw}`);
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
return NormalCompletion(node.value);
|
|
@@ -134,34 +134,35 @@ export function cook(rootAst, codeSource) {
|
|
|
134
134
|
case "LogicalExpression":
|
|
135
135
|
{
|
|
136
136
|
// https://tc39.es/ecma262/#sec-binary-logical-operators
|
|
137
|
-
|
|
137
|
+
const leftValue = GetValue(Evaluate(node.left));
|
|
138
138
|
switch (node.operator) {
|
|
139
139
|
case "&&":
|
|
140
|
-
return NormalCompletion(
|
|
140
|
+
return NormalCompletion(leftValue && GetValue(Evaluate(node.right)));
|
|
141
141
|
case "||":
|
|
142
|
-
return NormalCompletion(
|
|
142
|
+
return NormalCompletion(leftValue || GetValue(Evaluate(node.right)));
|
|
143
143
|
case "??":
|
|
144
|
-
return NormalCompletion(
|
|
144
|
+
return NormalCompletion(leftValue ?? GetValue(Evaluate(node.right)));
|
|
145
145
|
// istanbul ignore next
|
|
146
146
|
default:
|
|
147
|
-
throw new SyntaxError(
|
|
147
|
+
throw new SyntaxError(
|
|
148
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
148
149
|
// @ts-ignore never reach here.
|
|
149
|
-
|
|
150
|
+
`Unsupported logical operator '${node.operator}'`);
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
case "MemberExpression":
|
|
153
154
|
{
|
|
154
155
|
// https://tc39.es/ecma262/#sec-property-accessors
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
const baseReference = Evaluate(node.object, optionalChainRef).Value;
|
|
157
|
+
const baseValue = GetValue(baseReference);
|
|
157
158
|
if ((baseValue === undefined || baseValue === null) && (node.optional || optionalChainRef !== null && optionalChainRef !== void 0 && optionalChainRef.skipped)) {
|
|
158
159
|
optionalChainRef.skipped = true;
|
|
159
160
|
return NormalCompletion(undefined);
|
|
160
161
|
}
|
|
161
162
|
sanitize(baseValue);
|
|
162
|
-
|
|
163
|
-
sanitize(
|
|
164
|
-
return NormalCompletion(
|
|
163
|
+
const result = node.computed ? EvaluatePropertyAccessWithExpressionKey(baseValue, node.property, true) : EvaluatePropertyAccessWithIdentifierKey(baseValue, node.property, true);
|
|
164
|
+
sanitize(result);
|
|
165
|
+
return NormalCompletion(result);
|
|
165
166
|
}
|
|
166
167
|
case "NewExpression":
|
|
167
168
|
// https://tc39.es/ecma262/#sec-new-operator
|
|
@@ -169,16 +170,16 @@ export function cook(rootAst, codeSource) {
|
|
|
169
170
|
case "ObjectExpression":
|
|
170
171
|
{
|
|
171
172
|
// https://tc39.es/ecma262/#sec-object-initializer
|
|
172
|
-
|
|
173
|
-
for (
|
|
173
|
+
const object = {};
|
|
174
|
+
for (const prop of node.properties) {
|
|
174
175
|
if (prop.type === "SpreadElement") {
|
|
175
|
-
|
|
176
|
+
const fromValue = GetValue(Evaluate(prop.argument));
|
|
176
177
|
CopyDataProperties(object, fromValue, new Set());
|
|
177
178
|
} else {
|
|
178
179
|
if (prop.kind !== "init") {
|
|
179
180
|
throw new SyntaxError("Unsupported object getter/setter");
|
|
180
181
|
}
|
|
181
|
-
|
|
182
|
+
const propName = !prop.computed && prop.key.type === "Identifier" ? prop.key.name : EvaluateComputedPropertyName(prop.key);
|
|
182
183
|
if (propName === "__proto__") {
|
|
183
184
|
throw new TypeError("Setting '__proto__' property is not allowed");
|
|
184
185
|
}
|
|
@@ -190,19 +191,19 @@ export function cook(rootAst, codeSource) {
|
|
|
190
191
|
case "SequenceExpression":
|
|
191
192
|
{
|
|
192
193
|
// https://tc39.es/ecma262/#sec-comma-operator
|
|
193
|
-
|
|
194
|
-
for (
|
|
195
|
-
|
|
194
|
+
let result;
|
|
195
|
+
for (const expr of node.expressions) {
|
|
196
|
+
result = NormalCompletion(GetValue(Evaluate(expr)));
|
|
196
197
|
}
|
|
197
|
-
return
|
|
198
|
+
return result;
|
|
198
199
|
}
|
|
199
200
|
case "TemplateLiteral":
|
|
200
201
|
{
|
|
201
202
|
// https://tc39.es/ecma262/#sec-template-literals
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
for (
|
|
205
|
-
|
|
203
|
+
const chunks = [node.quasis[0].value.cooked];
|
|
204
|
+
let index = 0;
|
|
205
|
+
for (const expr of node.expressions) {
|
|
206
|
+
const val = GetValue(Evaluate(expr));
|
|
206
207
|
chunks.push(String(val));
|
|
207
208
|
chunks.push(node.quasis[index += 1].value.cooked);
|
|
208
209
|
}
|
|
@@ -211,34 +212,34 @@ export function cook(rootAst, codeSource) {
|
|
|
211
212
|
case "TaggedTemplateExpression":
|
|
212
213
|
{
|
|
213
214
|
// https://tc39.es/ecma262/#sec-tagged-templates
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
const tagRef = Evaluate(node.tag).Value;
|
|
216
|
+
const tagFunc = GetValue(tagRef);
|
|
216
217
|
sanitize(tagFunc);
|
|
217
218
|
return EvaluateCall(tagFunc, tagRef, node.quasi, node.tag);
|
|
218
219
|
}
|
|
219
220
|
case "UnaryExpression":
|
|
220
221
|
{
|
|
221
222
|
// https://tc39.es/ecma262/#sec-unary-operators
|
|
222
|
-
|
|
223
|
+
const ref = Evaluate(node.argument).Value;
|
|
223
224
|
if (!expressionOnly && node.operator === "delete") {
|
|
224
225
|
// Delete operator is supported only in function mode.
|
|
225
|
-
if (!(
|
|
226
|
+
if (!(ref instanceof ReferenceRecord)) {
|
|
226
227
|
return NormalCompletion(true);
|
|
227
228
|
}
|
|
228
229
|
// istanbul ignore else
|
|
229
|
-
if (IsPropertyReference(
|
|
230
|
-
|
|
230
|
+
if (IsPropertyReference(ref)) {
|
|
231
|
+
const deleteStatus = delete ref.Base[ref.ReferenceName];
|
|
231
232
|
return NormalCompletion(deleteStatus);
|
|
232
233
|
}
|
|
233
234
|
// Should never reach here in strict mode.
|
|
234
235
|
}
|
|
235
236
|
if (node.operator === "typeof") {
|
|
236
|
-
if (
|
|
237
|
+
if (ref instanceof ReferenceRecord && ref.Base === "unresolvable") {
|
|
237
238
|
return NormalCompletion("undefined");
|
|
238
239
|
}
|
|
239
|
-
return NormalCompletion(typeof GetValue(
|
|
240
|
+
return NormalCompletion(typeof GetValue(ref));
|
|
240
241
|
}
|
|
241
|
-
return NormalCompletion(ApplyUnaryOperator(GetValue(
|
|
242
|
+
return NormalCompletion(ApplyUnaryOperator(GetValue(ref), node.operator));
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
if (!expressionOnly) {
|
|
@@ -249,24 +250,24 @@ export function cook(rootAst, codeSource) {
|
|
|
249
250
|
// https://tc39.es/ecma262/#sec-assignment-operators
|
|
250
251
|
if (node.operator === "=") {
|
|
251
252
|
if (!(node.left.type === "ArrayPattern" || node.left.type === "ObjectPattern")) {
|
|
252
|
-
|
|
253
|
+
const lref = Evaluate(node.left).Value;
|
|
253
254
|
// Todo: IsAnonymousFunctionDefinition(lref)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
PutValue(
|
|
257
|
-
return NormalCompletion(
|
|
255
|
+
const rref = Evaluate(node.right);
|
|
256
|
+
const rval = GetValue(rref);
|
|
257
|
+
PutValue(lref, rval);
|
|
258
|
+
return NormalCompletion(rval);
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
DestructuringAssignmentEvaluation(node.left,
|
|
262
|
-
return NormalCompletion(
|
|
260
|
+
const rref = Evaluate(node.right);
|
|
261
|
+
const rval = GetValue(rref);
|
|
262
|
+
DestructuringAssignmentEvaluation(node.left, rval);
|
|
263
|
+
return NormalCompletion(rval);
|
|
263
264
|
}
|
|
264
265
|
// Operators other than `=`.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
266
|
+
const lref = Evaluate(node.left).Value;
|
|
267
|
+
const lval = GetValue(lref);
|
|
268
|
+
const rref = Evaluate(node.right);
|
|
269
|
+
const rval = GetValue(rref);
|
|
270
|
+
const r = ApplyStringOrNumericAssignment(lval, node.operator, rval);
|
|
270
271
|
PutValue(lref, r);
|
|
271
272
|
return NormalCompletion(r);
|
|
272
273
|
}
|
|
@@ -276,11 +277,11 @@ export function cook(rootAst, codeSource) {
|
|
|
276
277
|
if (!node.body.length) {
|
|
277
278
|
return NormalCompletion(Empty);
|
|
278
279
|
}
|
|
279
|
-
|
|
280
|
-
|
|
280
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
281
|
+
const blockEnv = new DeclarativeEnvironment(oldEnv);
|
|
281
282
|
BlockDeclarationInstantiation(node.body, blockEnv);
|
|
282
283
|
getRunningContext().LexicalEnvironment = blockEnv;
|
|
283
|
-
|
|
284
|
+
const blockValue = EvaluateStatementList(node.body);
|
|
284
285
|
getRunningContext().LexicalEnvironment = oldEnv;
|
|
285
286
|
return blockValue;
|
|
286
287
|
}
|
|
@@ -320,9 +321,9 @@ export function cook(rootAst, codeSource) {
|
|
|
320
321
|
case "ReturnStatement":
|
|
321
322
|
{
|
|
322
323
|
// https://tc39.es/ecma262/#sec-return-statement
|
|
323
|
-
|
|
324
|
+
let v;
|
|
324
325
|
if (node.argument) {
|
|
325
|
-
|
|
326
|
+
const exprRef = Evaluate(node.argument);
|
|
326
327
|
v = GetValue(exprRef);
|
|
327
328
|
}
|
|
328
329
|
return new CompletionRecord("return", v);
|
|
@@ -333,9 +334,9 @@ export function cook(rootAst, codeSource) {
|
|
|
333
334
|
case "UpdateExpression":
|
|
334
335
|
{
|
|
335
336
|
// https://tc39.es/ecma262/#sec-update-expressions
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
337
|
+
const lhs = Evaluate(node.argument).Value;
|
|
338
|
+
const oldValue = Number(GetValue(lhs));
|
|
339
|
+
const newValue = node.operator === "++" ? oldValue + 1 : oldValue - 1;
|
|
339
340
|
PutValue(lhs, newValue);
|
|
340
341
|
return NormalCompletion(node.prefix ? newValue : oldValue);
|
|
341
342
|
}
|
|
@@ -344,67 +345,67 @@ export function cook(rootAst, codeSource) {
|
|
|
344
345
|
case "SwitchStatement":
|
|
345
346
|
{
|
|
346
347
|
// https://tc39.es/ecma262/#sec-switch-statement
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
BlockDeclarationInstantiation(node.cases,
|
|
352
|
-
getRunningContext().LexicalEnvironment =
|
|
353
|
-
|
|
354
|
-
getRunningContext().LexicalEnvironment =
|
|
348
|
+
const exprRef = Evaluate(node.discriminant);
|
|
349
|
+
const switchValue = GetValue(exprRef);
|
|
350
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
351
|
+
const blockEnv = new DeclarativeEnvironment(oldEnv);
|
|
352
|
+
BlockDeclarationInstantiation(node.cases, blockEnv);
|
|
353
|
+
getRunningContext().LexicalEnvironment = blockEnv;
|
|
354
|
+
const R = CaseBlockEvaluation(node.cases, switchValue);
|
|
355
|
+
getRunningContext().LexicalEnvironment = oldEnv;
|
|
355
356
|
return EvaluateBreakableStatement(R);
|
|
356
357
|
}
|
|
357
358
|
case "TryStatement":
|
|
358
359
|
{
|
|
359
360
|
// https://tc39.es/ecma262/#sec-try-statement
|
|
360
|
-
|
|
361
|
+
let R;
|
|
361
362
|
try {
|
|
362
|
-
|
|
363
|
+
R = Evaluate(node.block);
|
|
363
364
|
} catch (error) {
|
|
364
365
|
if (node.handler) {
|
|
365
366
|
var _hooks$beforeEvaluate2;
|
|
366
367
|
(_hooks$beforeEvaluate2 = hooks.beforeEvaluate) === null || _hooks$beforeEvaluate2 === void 0 || _hooks$beforeEvaluate2.call(hooks, node.handler);
|
|
367
|
-
|
|
368
|
+
R = CatchClauseEvaluation(node.handler, error);
|
|
368
369
|
} else {
|
|
369
370
|
throw error;
|
|
370
371
|
}
|
|
371
372
|
} finally {
|
|
372
373
|
if (node.finalizer) {
|
|
373
|
-
|
|
374
|
+
const F = Evaluate(node.finalizer);
|
|
374
375
|
if (F.Type !== "normal") {
|
|
375
|
-
|
|
376
|
+
R = F;
|
|
376
377
|
}
|
|
377
378
|
}
|
|
378
379
|
}
|
|
379
|
-
return
|
|
380
|
+
return R;
|
|
380
381
|
}
|
|
381
382
|
case "VariableDeclaration":
|
|
382
383
|
{
|
|
383
384
|
// https://tc39.es/ecma262/#sec-declarations-and-the-variable-statement
|
|
384
|
-
|
|
385
|
-
for (
|
|
385
|
+
let result;
|
|
386
|
+
for (const declarator of node.declarations) {
|
|
386
387
|
if (!declarator.init) {
|
|
387
388
|
// Assert: a declarator without init is always an identifier.
|
|
388
389
|
if (node.kind === "var") {
|
|
389
|
-
|
|
390
|
+
result = NormalCompletion(Empty);
|
|
390
391
|
} else {
|
|
391
|
-
|
|
392
|
-
|
|
392
|
+
const lhs = ResolveBinding(declarator.id.name);
|
|
393
|
+
result = InitializeReferencedBinding(lhs, undefined);
|
|
393
394
|
}
|
|
394
395
|
} else if (declarator.id.type === "Identifier") {
|
|
395
|
-
|
|
396
|
-
|
|
396
|
+
const bindingId = declarator.id.name;
|
|
397
|
+
const lhs = ResolveBinding(bindingId);
|
|
397
398
|
// Todo: IsAnonymousFunctionDefinition(Initializer)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
399
|
+
const rhs = Evaluate(declarator.init);
|
|
400
|
+
const value = GetValue(rhs);
|
|
401
|
+
result = node.kind === "var" ? PutValue(lhs, value) : InitializeReferencedBinding(lhs, value);
|
|
401
402
|
} else {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
403
|
+
const rhs = Evaluate(declarator.init);
|
|
404
|
+
const rval = GetValue(rhs);
|
|
405
|
+
result = BindingInitialization(declarator.id, rval, node.kind === "var" ? undefined : getRunningContext().LexicalEnvironment);
|
|
405
406
|
}
|
|
406
407
|
}
|
|
407
|
-
return
|
|
408
|
+
return result;
|
|
408
409
|
}
|
|
409
410
|
case "WhileStatement":
|
|
410
411
|
// https://tc39.es/ecma262/#sec-while-statement
|
|
@@ -412,7 +413,7 @@ export function cook(rootAst, codeSource) {
|
|
|
412
413
|
}
|
|
413
414
|
}
|
|
414
415
|
// eslint-disable-next-line no-console
|
|
415
|
-
throw new SyntaxError(
|
|
416
|
+
throw new SyntaxError(`Unsupported node type \`${node.type}\``);
|
|
416
417
|
}
|
|
417
418
|
|
|
418
419
|
// https://tc39.es/ecma262/#sec-execution-contexts
|
|
@@ -434,14 +435,14 @@ export function cook(rootAst, codeSource) {
|
|
|
434
435
|
if (!node.param) {
|
|
435
436
|
return Evaluate(node.body);
|
|
436
437
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
for (
|
|
438
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
439
|
+
const catchEnv = new DeclarativeEnvironment(oldEnv);
|
|
440
|
+
for (const argName of collectBoundNames(node.param)) {
|
|
440
441
|
catchEnv.CreateMutableBinding(argName, false);
|
|
441
442
|
}
|
|
442
443
|
getRunningContext().LexicalEnvironment = catchEnv;
|
|
443
444
|
BindingInitialization(node.param, thrownValue, catchEnv);
|
|
444
|
-
|
|
445
|
+
const B = Evaluate(node.body);
|
|
445
446
|
getRunningContext().LexicalEnvironment = oldEnv;
|
|
446
447
|
return B;
|
|
447
448
|
}
|
|
@@ -455,42 +456,42 @@ export function cook(rootAst, codeSource) {
|
|
|
455
456
|
// Switch statements.
|
|
456
457
|
// https://tc39.es/ecma262/#sec-runtime-semantics-caseblockevaluation
|
|
457
458
|
function CaseBlockEvaluation(cases, input) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
for (
|
|
459
|
+
let V;
|
|
460
|
+
const defaultCaseIndex = cases.findIndex(switchCase => !switchCase.test);
|
|
461
|
+
const hasDefaultCase = defaultCaseIndex >= 0;
|
|
462
|
+
const A = hasDefaultCase ? cases.slice(0, defaultCaseIndex) : cases;
|
|
463
|
+
let found = false;
|
|
464
|
+
for (const C of A) {
|
|
464
465
|
if (!found) {
|
|
465
466
|
found = CaseClauseIsSelected(C, input);
|
|
466
467
|
}
|
|
467
468
|
if (found) {
|
|
468
|
-
|
|
469
|
-
if (
|
|
470
|
-
V =
|
|
469
|
+
const R = Evaluate(C);
|
|
470
|
+
if (R.Value !== Empty) {
|
|
471
|
+
V = R.Value;
|
|
471
472
|
}
|
|
472
|
-
if (
|
|
473
|
-
return UpdateEmpty(
|
|
473
|
+
if (R.Type !== "normal") {
|
|
474
|
+
return UpdateEmpty(R, V);
|
|
474
475
|
}
|
|
475
476
|
}
|
|
476
477
|
}
|
|
477
478
|
if (!hasDefaultCase) {
|
|
478
479
|
return NormalCompletion(V);
|
|
479
480
|
}
|
|
480
|
-
|
|
481
|
-
|
|
481
|
+
let foundInB = false;
|
|
482
|
+
const B = cases.slice(defaultCaseIndex + 1);
|
|
482
483
|
if (!found) {
|
|
483
|
-
for (
|
|
484
|
+
for (const C of B) {
|
|
484
485
|
if (!foundInB) {
|
|
485
|
-
foundInB = CaseClauseIsSelected(
|
|
486
|
+
foundInB = CaseClauseIsSelected(C, input);
|
|
486
487
|
}
|
|
487
488
|
if (foundInB) {
|
|
488
|
-
|
|
489
|
-
if (
|
|
490
|
-
V =
|
|
489
|
+
const R = Evaluate(C);
|
|
490
|
+
if (R.Value !== Empty) {
|
|
491
|
+
V = R.Value;
|
|
491
492
|
}
|
|
492
|
-
if (
|
|
493
|
-
return UpdateEmpty(
|
|
493
|
+
if (R.Type !== "normal") {
|
|
494
|
+
return UpdateEmpty(R, V);
|
|
494
495
|
}
|
|
495
496
|
}
|
|
496
497
|
}
|
|
@@ -498,7 +499,7 @@ export function cook(rootAst, codeSource) {
|
|
|
498
499
|
if (foundInB) {
|
|
499
500
|
return NormalCompletion(V);
|
|
500
501
|
}
|
|
501
|
-
|
|
502
|
+
const R = Evaluate(cases[defaultCaseIndex]);
|
|
502
503
|
if (R.Value !== Empty) {
|
|
503
504
|
V = R.Value;
|
|
504
505
|
}
|
|
@@ -507,13 +508,13 @@ export function cook(rootAst, codeSource) {
|
|
|
507
508
|
}
|
|
508
509
|
|
|
509
510
|
// NOTE: The following is another complete iteration of the second CaseClauses.
|
|
510
|
-
for (
|
|
511
|
-
|
|
512
|
-
if (
|
|
513
|
-
V =
|
|
511
|
+
for (const C of B) {
|
|
512
|
+
const R = Evaluate(C);
|
|
513
|
+
if (R.Value !== Empty) {
|
|
514
|
+
V = R.Value;
|
|
514
515
|
}
|
|
515
|
-
if (
|
|
516
|
-
return UpdateEmpty(
|
|
516
|
+
if (R.Type !== "normal") {
|
|
517
|
+
return UpdateEmpty(R, V);
|
|
517
518
|
}
|
|
518
519
|
}
|
|
519
520
|
return NormalCompletion(V);
|
|
@@ -521,21 +522,21 @@ export function cook(rootAst, codeSource) {
|
|
|
521
522
|
|
|
522
523
|
// https://tc39.es/ecma262/#sec-runtime-semantics-caseclauseisselected
|
|
523
524
|
function CaseClauseIsSelected(C, input) {
|
|
524
|
-
|
|
525
|
+
const clauseSelector = GetValue(Evaluate(C.test));
|
|
525
526
|
return input === clauseSelector;
|
|
526
527
|
}
|
|
527
528
|
|
|
528
529
|
// While statements.
|
|
529
530
|
// https://tc39.es/ecma262/#sec-runtime-semantics-whileloopevaluation
|
|
530
531
|
function WhileLoopEvaluation(node) {
|
|
531
|
-
|
|
532
|
+
let V;
|
|
532
533
|
// eslint-disable-next-line no-constant-condition
|
|
533
534
|
while (true) {
|
|
534
|
-
|
|
535
|
+
const exprValue = GetValue(Evaluate(node.test));
|
|
535
536
|
if (!exprValue) {
|
|
536
537
|
return NormalCompletion(V);
|
|
537
538
|
}
|
|
538
|
-
|
|
539
|
+
const stmtResult = Evaluate(node.body);
|
|
539
540
|
if (!LoopContinues(stmtResult)) {
|
|
540
541
|
return UpdateEmpty(stmtResult, V);
|
|
541
542
|
}
|
|
@@ -548,17 +549,17 @@ export function cook(rootAst, codeSource) {
|
|
|
548
549
|
// Do-while Statements.
|
|
549
550
|
// https://tc39.es/ecma262/#sec-runtime-semantics-dowhileloopevaluation
|
|
550
551
|
function DoWhileLoopEvaluation(node) {
|
|
551
|
-
|
|
552
|
+
let V;
|
|
552
553
|
// eslint-disable-next-line no-constant-condition
|
|
553
554
|
while (true) {
|
|
554
|
-
|
|
555
|
+
const stmtResult = Evaluate(node.body);
|
|
555
556
|
if (!LoopContinues(stmtResult)) {
|
|
556
557
|
return UpdateEmpty(stmtResult, V);
|
|
557
558
|
}
|
|
558
559
|
if (stmtResult.Value !== Empty) {
|
|
559
560
|
V = stmtResult.Value;
|
|
560
561
|
}
|
|
561
|
-
|
|
562
|
+
const exprValue = GetValue(Evaluate(node.test));
|
|
562
563
|
if (!exprValue) {
|
|
563
564
|
return NormalCompletion(V);
|
|
564
565
|
}
|
|
@@ -568,12 +569,12 @@ export function cook(rootAst, codeSource) {
|
|
|
568
569
|
// For in/of statements.
|
|
569
570
|
// https://tc39.es/ecma262/#sec-runtime-semantics-forinofloopevaluation
|
|
570
571
|
function ForInOfLoopEvaluation(node) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
572
|
+
const lhs = node.left;
|
|
573
|
+
const isVariableDeclaration = lhs.type === "VariableDeclaration";
|
|
574
|
+
const lhsKind = isVariableDeclaration ? lhs.kind === "var" ? "varBinding" : "lexicalBinding" : "assignment";
|
|
575
|
+
const uninitializedBoundNames = lhsKind === "lexicalBinding" ? collectBoundNames(lhs) : [];
|
|
576
|
+
const iterationKind = node.type === "ForInStatement" ? "enumerate" : "iterate";
|
|
577
|
+
const keyResult = ForInOfHeadEvaluation(uninitializedBoundNames, node.right, iterationKind);
|
|
577
578
|
if (keyResult.Type !== "normal") {
|
|
578
579
|
// When enumerate, if the target is nil, a break completion will be returned.
|
|
579
580
|
return keyResult;
|
|
@@ -583,71 +584,71 @@ export function cook(rootAst, codeSource) {
|
|
|
583
584
|
|
|
584
585
|
// https://tc39.es/ecma262/#sec-runtime-semantics-forinofheadevaluation
|
|
585
586
|
function ForInOfHeadEvaluation(uninitializedBoundNames, expr, iterationKind) {
|
|
586
|
-
|
|
587
|
-
|
|
587
|
+
const runningContext = getRunningContext();
|
|
588
|
+
const oldEnv = runningContext.LexicalEnvironment;
|
|
588
589
|
if (uninitializedBoundNames.length > 0) {
|
|
589
|
-
|
|
590
|
-
for (
|
|
590
|
+
const newEnv = new DeclarativeEnvironment(oldEnv);
|
|
591
|
+
for (const name of uninitializedBoundNames) {
|
|
591
592
|
newEnv.CreateMutableBinding(name, false);
|
|
592
593
|
}
|
|
593
594
|
runningContext.LexicalEnvironment = newEnv;
|
|
594
595
|
}
|
|
595
|
-
|
|
596
|
+
const exprRef = Evaluate(expr);
|
|
596
597
|
runningContext.LexicalEnvironment = oldEnv;
|
|
597
|
-
|
|
598
|
+
const exprValue = GetValue(exprRef);
|
|
598
599
|
if (iterationKind === "enumerate") {
|
|
599
600
|
if (exprValue === null || exprValue === undefined) {
|
|
600
601
|
return new CompletionRecord("break", Empty);
|
|
601
602
|
}
|
|
602
|
-
|
|
603
|
-
return NormalCompletion(
|
|
603
|
+
const iterator = EnumerateObjectProperties(exprValue);
|
|
604
|
+
return NormalCompletion(iterator);
|
|
604
605
|
}
|
|
605
|
-
|
|
606
|
+
const iterator = CreateListIteratorRecord(exprValue);
|
|
606
607
|
return NormalCompletion(iterator);
|
|
607
608
|
}
|
|
608
609
|
function ForInOfBodyEvaluation(node, stmt, iteratorRecord, iterationKind, lhsKind) {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
610
|
+
const lhs = lhsKind === "assignment" ? node : node.declarations[0].id;
|
|
611
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
612
|
+
let V;
|
|
612
613
|
// When `destructuring` is false,
|
|
613
614
|
// For `node` whose `kind` is assignment:
|
|
614
615
|
// `lhs` is an `Identifier` or a `MemberExpression`,
|
|
615
616
|
// Otherwise:
|
|
616
617
|
// `lhs` is an `Identifier`.
|
|
617
|
-
|
|
618
|
+
const destructuring = lhs.type === "ObjectPattern" || lhs.type === "ArrayPattern";
|
|
618
619
|
// eslint-disable-next-line no-constant-condition
|
|
619
620
|
while (true) {
|
|
620
|
-
|
|
621
|
+
const {
|
|
621
622
|
done,
|
|
622
623
|
value: nextValue
|
|
623
624
|
} = iteratorRecord.next();
|
|
624
625
|
if (done) {
|
|
625
626
|
return NormalCompletion(V);
|
|
626
627
|
}
|
|
627
|
-
|
|
628
|
-
|
|
628
|
+
let lhsRef;
|
|
629
|
+
let iterationEnv;
|
|
629
630
|
if (lhsKind === "lexicalBinding") {
|
|
630
631
|
iterationEnv = new DeclarativeEnvironment(oldEnv);
|
|
631
632
|
ForDeclarationBindingInstantiation(node, iterationEnv);
|
|
632
633
|
getRunningContext().LexicalEnvironment = iterationEnv;
|
|
633
634
|
if (!destructuring) {
|
|
634
|
-
|
|
635
|
+
const [lhsName] = collectBoundNames(lhs);
|
|
635
636
|
lhsRef = ResolveBinding(lhsName);
|
|
636
637
|
}
|
|
637
638
|
} else if (!destructuring) {
|
|
638
639
|
lhsRef = Evaluate(lhs).Value;
|
|
639
640
|
}
|
|
640
641
|
destructuring ? lhsKind === "assignment" ? DestructuringAssignmentEvaluation(lhs, nextValue) : lhsKind === "varBinding" ? BindingInitialization(lhs, nextValue, undefined) : BindingInitialization(lhs, nextValue, iterationEnv) : lhsKind === "lexicalBinding" ? InitializeReferencedBinding(lhsRef, nextValue) : PutValue(lhsRef, nextValue);
|
|
641
|
-
|
|
642
|
+
const result = Evaluate(stmt);
|
|
642
643
|
getRunningContext().LexicalEnvironment = oldEnv;
|
|
643
644
|
if (!LoopContinues(result)) {
|
|
644
|
-
|
|
645
|
+
const status = UpdateEmpty(result, V);
|
|
645
646
|
if (!(iterationKind === "enumerate" || iteratorRecord.return === undefined)) {
|
|
646
647
|
// Perform *IteratorClose*
|
|
647
648
|
// https://tc39.es/ecma262/#sec-iteratorclose
|
|
648
|
-
|
|
649
|
+
const innerResult = iteratorRecord.return();
|
|
649
650
|
if (!innerResult || !["object", "function"].includes(typeof innerResult)) {
|
|
650
|
-
throw new TypeError(
|
|
651
|
+
throw new TypeError(`Iterator result is not an object`);
|
|
651
652
|
}
|
|
652
653
|
}
|
|
653
654
|
return status;
|
|
@@ -660,8 +661,8 @@ export function cook(rootAst, codeSource) {
|
|
|
660
661
|
|
|
661
662
|
// https://tc39.es/ecma262/#sec-enumerate-object-properties
|
|
662
663
|
function* EnumerateObjectProperties(value) {
|
|
663
|
-
for (
|
|
664
|
-
yield
|
|
664
|
+
for (const key in value) {
|
|
665
|
+
yield key;
|
|
665
666
|
}
|
|
666
667
|
}
|
|
667
668
|
|
|
@@ -676,11 +677,11 @@ export function cook(rootAst, codeSource) {
|
|
|
676
677
|
return ForBodyEvaluation(node.test, node.update, node.body, []);
|
|
677
678
|
}
|
|
678
679
|
// `for (let/const … ; … ; … ) …`
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
for (
|
|
680
|
+
const oldEnv = getRunningContext().LexicalEnvironment;
|
|
681
|
+
const loopEnv = new DeclarativeEnvironment(oldEnv);
|
|
682
|
+
const isConst = node.init.kind === "const";
|
|
683
|
+
const boundNames = collectBoundNames(node.init);
|
|
684
|
+
for (const dn of boundNames) {
|
|
684
685
|
if (isConst) {
|
|
685
686
|
loopEnv.CreateImmutableBinding(dn, true);
|
|
686
687
|
} else {
|
|
@@ -689,14 +690,14 @@ export function cook(rootAst, codeSource) {
|
|
|
689
690
|
}
|
|
690
691
|
getRunningContext().LexicalEnvironment = loopEnv;
|
|
691
692
|
Evaluate(node.init);
|
|
692
|
-
|
|
693
|
-
|
|
693
|
+
const perIterationLets = isConst ? [] : Array.from(boundNames);
|
|
694
|
+
const bodyResult = ForBodyEvaluation(node.test, node.update, node.body, perIterationLets);
|
|
694
695
|
getRunningContext().LexicalEnvironment = oldEnv;
|
|
695
696
|
return bodyResult;
|
|
696
697
|
}
|
|
697
698
|
// `for ( … ; … ; … ) …`
|
|
698
699
|
if (node.init) {
|
|
699
|
-
|
|
700
|
+
const exprRef = Evaluate(node.init);
|
|
700
701
|
GetValue(exprRef);
|
|
701
702
|
}
|
|
702
703
|
return ForBodyEvaluation(node.test, node.update, node.body, []);
|
|
@@ -705,17 +706,17 @@ export function cook(rootAst, codeSource) {
|
|
|
705
706
|
// https://tc39.es/ecma262/#sec-forbodyevaluation
|
|
706
707
|
function ForBodyEvaluation(test, increment, stmt, perIterationBindings) {
|
|
707
708
|
CreatePerIterationEnvironment(perIterationBindings);
|
|
708
|
-
|
|
709
|
+
let V;
|
|
709
710
|
// eslint-disable-next-line no-constant-condition
|
|
710
711
|
while (true) {
|
|
711
712
|
if (test) {
|
|
712
|
-
|
|
713
|
-
|
|
713
|
+
const testRef = Evaluate(test);
|
|
714
|
+
const testValue = GetValue(testRef);
|
|
714
715
|
if (!testValue) {
|
|
715
716
|
return NormalCompletion(V);
|
|
716
717
|
}
|
|
717
718
|
}
|
|
718
|
-
|
|
719
|
+
const result = Evaluate(stmt);
|
|
719
720
|
if (!LoopContinues(result)) {
|
|
720
721
|
return UpdateEmpty(result, V);
|
|
721
722
|
}
|
|
@@ -724,7 +725,7 @@ export function cook(rootAst, codeSource) {
|
|
|
724
725
|
}
|
|
725
726
|
CreatePerIterationEnvironment(perIterationBindings);
|
|
726
727
|
if (increment) {
|
|
727
|
-
|
|
728
|
+
const incRef = Evaluate(increment);
|
|
728
729
|
GetValue(incRef);
|
|
729
730
|
}
|
|
730
731
|
}
|
|
@@ -735,12 +736,12 @@ export function cook(rootAst, codeSource) {
|
|
|
735
736
|
if (perIterationBindings.length === 0) {
|
|
736
737
|
return;
|
|
737
738
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
for (
|
|
739
|
+
const lastIterationEnv = getRunningContext().LexicalEnvironment;
|
|
740
|
+
const outer = lastIterationEnv.OuterEnv;
|
|
741
|
+
const thisIterationEnv = new DeclarativeEnvironment(outer);
|
|
742
|
+
for (const bn of perIterationBindings) {
|
|
742
743
|
thisIterationEnv.CreateMutableBinding(bn, false);
|
|
743
|
-
|
|
744
|
+
const lastValue = lastIterationEnv.GetBindingValue(bn, false);
|
|
744
745
|
thisIterationEnv.InitializeBinding(bn, lastValue);
|
|
745
746
|
}
|
|
746
747
|
getRunningContext().LexicalEnvironment = thisIterationEnv;
|
|
@@ -756,23 +757,23 @@ export function cook(rootAst, codeSource) {
|
|
|
756
757
|
}
|
|
757
758
|
return NormalCompletion(Empty);
|
|
758
759
|
}
|
|
759
|
-
|
|
760
|
+
const iteratorRecord = CreateListIteratorRecord(value);
|
|
760
761
|
return IteratorDestructuringAssignmentEvaluation(pattern.elements, iteratorRecord);
|
|
761
762
|
}
|
|
762
763
|
|
|
763
764
|
// https://tc39.es/ecma262/#sec-runtime-semantics-propertydestructuringassignmentevaluation
|
|
764
765
|
function PropertyDestructuringAssignmentEvaluation(properties, value) {
|
|
765
|
-
|
|
766
|
-
for (
|
|
766
|
+
const excludedNames = new Set();
|
|
767
|
+
for (const prop of properties) {
|
|
767
768
|
if (prop.type === "Property") {
|
|
768
|
-
|
|
769
|
-
|
|
769
|
+
const propName = !prop.computed && prop.key.type === "Identifier" ? prop.key.name : EvaluateComputedPropertyName(prop.key);
|
|
770
|
+
const valueTarget = prop.value.type === "AssignmentPattern" ? prop.value.left : prop.value;
|
|
770
771
|
if (valueTarget.type === "Identifier") {
|
|
771
|
-
|
|
772
|
-
|
|
772
|
+
const lref = ResolveBinding(valueTarget.name);
|
|
773
|
+
let v = GetV(value, propName);
|
|
773
774
|
if (prop.value.type === "AssignmentPattern" && v === undefined) {
|
|
774
775
|
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
775
|
-
|
|
776
|
+
const defaultValue = Evaluate(prop.value.right);
|
|
776
777
|
v = GetValue(defaultValue);
|
|
777
778
|
}
|
|
778
779
|
PutValue(lref, v);
|
|
@@ -789,17 +790,17 @@ export function cook(rootAst, codeSource) {
|
|
|
789
790
|
|
|
790
791
|
// https://tc39.es/ecma262/#sec-runtime-semantics-keyeddestructuringassignmentevaluation
|
|
791
792
|
function KeyedDestructuringAssignmentEvaluation(node, value, propertyName) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
793
|
+
const assignmentTarget = node.type === "AssignmentPattern" ? node.left : node;
|
|
794
|
+
const isObjectOrArray = assignmentTarget.type === "ArrayPattern" || assignmentTarget.type === "ObjectPattern";
|
|
795
|
+
let lref;
|
|
795
796
|
if (!isObjectOrArray) {
|
|
796
797
|
lref = Evaluate(assignmentTarget).Value;
|
|
797
798
|
}
|
|
798
|
-
|
|
799
|
-
|
|
799
|
+
const v = GetV(value, propertyName);
|
|
800
|
+
let rhsValue;
|
|
800
801
|
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
801
802
|
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
802
|
-
|
|
803
|
+
const defaultValue = Evaluate(node.right);
|
|
803
804
|
rhsValue = GetValue(defaultValue);
|
|
804
805
|
} else {
|
|
805
806
|
rhsValue = v;
|
|
@@ -812,54 +813,54 @@ export function cook(rootAst, codeSource) {
|
|
|
812
813
|
|
|
813
814
|
// https://tc39.es/ecma262/#sec-runtime-semantics-restdestructuringassignmentevaluation
|
|
814
815
|
function RestDestructuringAssignmentEvaluation(restProperty, value, excludedNames) {
|
|
815
|
-
|
|
816
|
-
|
|
816
|
+
const lref = Evaluate(restProperty.argument).Value;
|
|
817
|
+
const restObj = CopyDataProperties({}, value, excludedNames);
|
|
817
818
|
return PutValue(lref, restObj);
|
|
818
819
|
}
|
|
819
820
|
|
|
820
821
|
// https://tc39.es/ecma262/#sec-runtime-semantics-iteratordestructuringassignmentevaluation
|
|
821
822
|
function IteratorDestructuringAssignmentEvaluation(elements, iteratorRecord) {
|
|
822
|
-
|
|
823
|
-
for (
|
|
823
|
+
let status = NormalCompletion(Empty);
|
|
824
|
+
for (const element of elements) {
|
|
824
825
|
if (!element) {
|
|
825
826
|
iteratorRecord.next();
|
|
826
827
|
status = NormalCompletion(Empty);
|
|
827
828
|
continue;
|
|
828
829
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
830
|
+
const assignmentTarget = element.type === "RestElement" ? element.argument : element.type === "AssignmentPattern" ? element.left : element;
|
|
831
|
+
const isObjectOrArray = assignmentTarget.type === "ArrayPattern" || assignmentTarget.type === "ObjectPattern";
|
|
832
|
+
let lref;
|
|
832
833
|
if (!isObjectOrArray) {
|
|
833
834
|
lref = Evaluate(assignmentTarget).Value;
|
|
834
835
|
}
|
|
835
|
-
|
|
836
|
+
let v;
|
|
836
837
|
if (element.type !== "RestElement") {
|
|
837
|
-
|
|
838
|
+
const {
|
|
838
839
|
done,
|
|
839
840
|
value: nextValue
|
|
840
841
|
} = iteratorRecord.next();
|
|
841
|
-
|
|
842
|
-
if (element.type === "AssignmentPattern" &&
|
|
842
|
+
const value = done ? undefined : nextValue;
|
|
843
|
+
if (element.type === "AssignmentPattern" && value === undefined) {
|
|
843
844
|
// Todo(steve): check IsAnonymousFunctionDefinition(Initializer)
|
|
844
|
-
|
|
845
|
+
const defaultValue = Evaluate(element.right);
|
|
845
846
|
v = GetValue(defaultValue);
|
|
846
847
|
} else {
|
|
847
|
-
v =
|
|
848
|
+
v = value;
|
|
848
849
|
}
|
|
849
850
|
} else {
|
|
850
851
|
// RestElement
|
|
851
852
|
v = [];
|
|
852
|
-
|
|
853
|
+
let n = 0;
|
|
853
854
|
// eslint-disable-next-line no-constant-condition
|
|
854
855
|
while (true) {
|
|
855
|
-
|
|
856
|
-
done
|
|
857
|
-
value:
|
|
856
|
+
const {
|
|
857
|
+
done,
|
|
858
|
+
value: nextValue
|
|
858
859
|
} = iteratorRecord.next();
|
|
859
|
-
if (
|
|
860
|
+
if (done) {
|
|
860
861
|
break;
|
|
861
862
|
}
|
|
862
|
-
v[n] =
|
|
863
|
+
v[n] = nextValue;
|
|
863
864
|
n++;
|
|
864
865
|
}
|
|
865
866
|
}
|
|
@@ -875,28 +876,28 @@ export function cook(rootAst, codeSource) {
|
|
|
875
876
|
// Object expressions.
|
|
876
877
|
// https://tc39.es/ecma262/#sec-evaluate-property-access-with-expression-key
|
|
877
878
|
function EvaluatePropertyAccessWithExpressionKey(baseValue, expression, strict) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
879
|
+
const propertyNameReference = Evaluate(expression);
|
|
880
|
+
const propertyNameValue = GetValue(propertyNameReference);
|
|
881
|
+
const propertyKey = ToPropertyKey(propertyNameValue);
|
|
881
882
|
return new ReferenceRecord(baseValue, propertyKey, strict);
|
|
882
883
|
}
|
|
883
884
|
|
|
884
885
|
// https://tc39.es/ecma262/#sec-evaluate-property-access-with-identifier-key
|
|
885
886
|
function EvaluatePropertyAccessWithIdentifierKey(baseValue, identifier, strict) {
|
|
886
|
-
|
|
887
|
+
const propertyNameString = identifier.name;
|
|
887
888
|
return new ReferenceRecord(baseValue, propertyNameString, strict);
|
|
888
889
|
}
|
|
889
890
|
|
|
890
891
|
// Block statements.
|
|
891
892
|
// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
|
|
892
893
|
function BlockDeclarationInstantiation(code, env) {
|
|
893
|
-
|
|
894
|
+
const declarations = collectScopedDeclarations(code, {
|
|
894
895
|
var: false,
|
|
895
896
|
topLevel: false
|
|
896
897
|
});
|
|
897
|
-
for (
|
|
898
|
-
|
|
899
|
-
for (
|
|
898
|
+
for (const d of declarations) {
|
|
899
|
+
const IsConstantDeclaration = d.type === "VariableDeclaration" && d.kind === "const";
|
|
900
|
+
for (const dn of collectBoundNames(d)) {
|
|
900
901
|
if (IsConstantDeclaration) {
|
|
901
902
|
env.CreateImmutableBinding(dn, true);
|
|
902
903
|
} else {
|
|
@@ -904,9 +905,9 @@ export function cook(rootAst, codeSource) {
|
|
|
904
905
|
}
|
|
905
906
|
}
|
|
906
907
|
if (d.type === "FunctionDeclaration") {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
env.InitializeBinding(
|
|
908
|
+
const [fn] = collectBoundNames(d);
|
|
909
|
+
const fo = InstantiateFunctionObject(d, env);
|
|
910
|
+
env.InitializeBinding(fn, fo);
|
|
910
911
|
}
|
|
911
912
|
}
|
|
912
913
|
}
|
|
@@ -914,45 +915,45 @@ export function cook(rootAst, codeSource) {
|
|
|
914
915
|
// Function declarations and expressions.
|
|
915
916
|
// https://tc39.es/ecma262/#sec-evaluatecall
|
|
916
917
|
function EvaluateCall(func, ref, args, callee) {
|
|
917
|
-
|
|
918
|
+
let thisValue;
|
|
918
919
|
if (ref instanceof ReferenceRecord) {
|
|
919
920
|
if (IsPropertyReference(ref)) {
|
|
920
921
|
thisValue = ref.Base;
|
|
921
922
|
}
|
|
922
923
|
}
|
|
923
|
-
|
|
924
|
+
const argList = ArgumentListEvaluation(args);
|
|
924
925
|
if (typeof func !== "function") {
|
|
925
|
-
|
|
926
|
-
throw new TypeError(
|
|
926
|
+
const funcName = codeSource.substring(callee.start, callee.end);
|
|
927
|
+
throw new TypeError(`${funcName} is not a function`);
|
|
927
928
|
}
|
|
928
|
-
|
|
929
|
+
const result = func.apply(thisValue, argList);
|
|
929
930
|
sanitize(result);
|
|
930
931
|
return NormalCompletion(result);
|
|
931
932
|
}
|
|
932
933
|
|
|
933
934
|
// https://tc39.es/ecma262/#sec-evaluatenew
|
|
934
935
|
function EvaluateNew(constructExpr, args) {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
936
|
+
const ref = Evaluate(constructExpr);
|
|
937
|
+
const constructor = GetValue(ref);
|
|
938
|
+
const argList = ArgumentListEvaluation(args);
|
|
938
939
|
if (typeof constructor !== "function" || constructor[IsConstructor] === false) {
|
|
939
|
-
|
|
940
|
-
throw new TypeError(
|
|
940
|
+
const constructorName = codeSource.substring(constructExpr.start, constructExpr.end);
|
|
941
|
+
throw new TypeError(`${constructorName} is not a constructor`);
|
|
941
942
|
}
|
|
942
943
|
if (!isAllowedConstructor(constructor)) {
|
|
943
|
-
|
|
944
|
-
throw new TypeError(
|
|
944
|
+
const constructorName = codeSource.substring(constructExpr.start, constructExpr.end);
|
|
945
|
+
throw new TypeError(`${constructorName} is not an allowed constructor`);
|
|
945
946
|
}
|
|
946
947
|
return NormalCompletion(new constructor(...argList));
|
|
947
948
|
}
|
|
948
949
|
|
|
949
950
|
// https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation
|
|
950
951
|
function ArgumentListEvaluation(args) {
|
|
951
|
-
|
|
952
|
+
const array = [];
|
|
952
953
|
if (Array.isArray(args)) {
|
|
953
|
-
for (
|
|
954
|
+
for (const arg of args) {
|
|
954
955
|
if (arg.type === "SpreadElement") {
|
|
955
|
-
|
|
956
|
+
const spreadValues = GetValue(Evaluate(arg.argument));
|
|
956
957
|
array.push(...spreadValues);
|
|
957
958
|
} else {
|
|
958
959
|
array.push(GetValue(Evaluate(arg)));
|
|
@@ -960,7 +961,7 @@ export function cook(rootAst, codeSource) {
|
|
|
960
961
|
}
|
|
961
962
|
} else {
|
|
962
963
|
array.push(GetTemplateObject(args));
|
|
963
|
-
for (
|
|
964
|
+
for (const expr of args.expressions) {
|
|
964
965
|
array.push(GetValue(Evaluate(expr)));
|
|
965
966
|
}
|
|
966
967
|
}
|
|
@@ -972,7 +973,7 @@ export function cook(rootAst, codeSource) {
|
|
|
972
973
|
var _hooks$beforeCall;
|
|
973
974
|
(_hooks$beforeCall = hooks.beforeCall) === null || _hooks$beforeCall === void 0 || _hooks$beforeCall.call(hooks, closure[SourceNode]);
|
|
974
975
|
PrepareForOrdinaryCall(closure);
|
|
975
|
-
|
|
976
|
+
const result = OrdinaryCallEvaluateBody(closure, args);
|
|
976
977
|
executionContextStack.pop();
|
|
977
978
|
if (result.Type === "return") {
|
|
978
979
|
return result.Value;
|
|
@@ -982,9 +983,9 @@ export function cook(rootAst, codeSource) {
|
|
|
982
983
|
|
|
983
984
|
// https://tc39.es/ecma262/#sec-prepareforordinarycall
|
|
984
985
|
function PrepareForOrdinaryCall(F) {
|
|
985
|
-
|
|
986
|
+
const calleeContext = new ExecutionContext();
|
|
986
987
|
calleeContext.Function = F;
|
|
987
|
-
|
|
988
|
+
const localEnv = new FunctionEnvironment(F[Environment]);
|
|
988
989
|
calleeContext.VariableEnvironment = localEnv;
|
|
989
990
|
calleeContext.LexicalEnvironment = localEnv;
|
|
990
991
|
executionContextStack.push(calleeContext);
|
|
@@ -1007,9 +1008,9 @@ export function cook(rootAst, codeSource) {
|
|
|
1007
1008
|
|
|
1008
1009
|
// https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
|
|
1009
1010
|
function EvaluateStatementList(statements) {
|
|
1010
|
-
|
|
1011
|
-
for (
|
|
1012
|
-
|
|
1011
|
+
let result = NormalCompletion(Empty);
|
|
1012
|
+
for (const stmt of statements) {
|
|
1013
|
+
const s = Evaluate(stmt);
|
|
1013
1014
|
if (s.Type !== "normal") {
|
|
1014
1015
|
return s;
|
|
1015
1016
|
}
|
|
@@ -1020,47 +1021,47 @@ export function cook(rootAst, codeSource) {
|
|
|
1020
1021
|
|
|
1021
1022
|
// https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
|
|
1022
1023
|
function FunctionDeclarationInstantiation(func, args) {
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1024
|
+
const calleeContext = getRunningContext();
|
|
1025
|
+
const code = func[ECMAScriptCode];
|
|
1026
|
+
const formals = func[FormalParameters];
|
|
1027
|
+
const parameterNames = collectBoundNames(formals);
|
|
1028
|
+
const hasParameterExpressions = containsExpression(formals);
|
|
1029
|
+
const varDeclarations = collectScopedDeclarations(code, {
|
|
1029
1030
|
var: true,
|
|
1030
1031
|
topLevel: true
|
|
1031
1032
|
});
|
|
1032
|
-
|
|
1033
|
+
const varNames = collectBoundNames(varDeclarations);
|
|
1033
1034
|
|
|
1034
1035
|
// `functionNames` ∈ `varNames`
|
|
1035
1036
|
// `functionsToInitialize` ≈ `functionNames`
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
for (
|
|
1039
|
-
|
|
1037
|
+
const functionNames = [];
|
|
1038
|
+
const functionsToInitialize = [];
|
|
1039
|
+
for (let i = varDeclarations.length - 1; i >= 0; i--) {
|
|
1040
|
+
const d = varDeclarations[i];
|
|
1040
1041
|
if (d.type === "FunctionDeclaration") {
|
|
1041
1042
|
ThrowIfFunctionIsInvalid(d);
|
|
1042
|
-
|
|
1043
|
-
if (!functionNames.includes(
|
|
1044
|
-
functionNames.unshift(
|
|
1043
|
+
const [fn] = collectBoundNames(d);
|
|
1044
|
+
if (!functionNames.includes(fn)) {
|
|
1045
|
+
functionNames.unshift(fn);
|
|
1045
1046
|
functionsToInitialize.unshift(d);
|
|
1046
1047
|
}
|
|
1047
1048
|
} else if (rules !== null && rules !== void 0 && rules.noVar) {
|
|
1048
1049
|
throw new SyntaxError("Var declaration is not recommended, use `let` or `const` instead");
|
|
1049
1050
|
}
|
|
1050
1051
|
}
|
|
1051
|
-
|
|
1052
|
-
for (
|
|
1052
|
+
const env = calleeContext.LexicalEnvironment;
|
|
1053
|
+
for (const paramName of parameterNames) {
|
|
1053
1054
|
// In strict mode, it's guaranteed no duplicate params exist.
|
|
1054
1055
|
env.CreateMutableBinding(paramName, false);
|
|
1055
1056
|
}
|
|
1056
|
-
|
|
1057
|
+
const iteratorRecord = CreateListIteratorRecord(args);
|
|
1057
1058
|
IteratorBindingInitialization(formals, iteratorRecord, env);
|
|
1058
|
-
|
|
1059
|
+
let varEnv;
|
|
1059
1060
|
if (!hasParameterExpressions) {
|
|
1060
1061
|
// NOTE: Only a single Environment Record is needed for the parameters
|
|
1061
1062
|
// and top-level vars.
|
|
1062
1063
|
// `varNames` are unique.
|
|
1063
|
-
for (
|
|
1064
|
+
for (const n of varNames) {
|
|
1064
1065
|
if (!parameterNames.includes(n)) {
|
|
1065
1066
|
env.CreateMutableBinding(n, false);
|
|
1066
1067
|
env.InitializeBinding(n, undefined);
|
|
@@ -1074,37 +1075,37 @@ export function cook(rootAst, codeSource) {
|
|
|
1074
1075
|
varEnv = new DeclarativeEnvironment(env);
|
|
1075
1076
|
calleeContext.VariableEnvironment = varEnv;
|
|
1076
1077
|
// `varNames` are unique.
|
|
1077
|
-
for (
|
|
1078
|
-
varEnv.CreateMutableBinding(
|
|
1079
|
-
|
|
1080
|
-
if (parameterNames.includes(
|
|
1081
|
-
initialValue = env.GetBindingValue(
|
|
1078
|
+
for (const n of varNames) {
|
|
1079
|
+
varEnv.CreateMutableBinding(n, false);
|
|
1080
|
+
let initialValue;
|
|
1081
|
+
if (parameterNames.includes(n) && !functionNames.includes(n)) {
|
|
1082
|
+
initialValue = env.GetBindingValue(n, false);
|
|
1082
1083
|
}
|
|
1083
|
-
varEnv.InitializeBinding(
|
|
1084
|
+
varEnv.InitializeBinding(n, initialValue);
|
|
1084
1085
|
// NOTE: A var with the same name as a formal parameter initially has
|
|
1085
1086
|
// the same value as the corresponding initialized parameter.
|
|
1086
1087
|
}
|
|
1087
1088
|
}
|
|
1088
|
-
|
|
1089
|
+
const lexEnv = varEnv;
|
|
1089
1090
|
calleeContext.LexicalEnvironment = lexEnv;
|
|
1090
|
-
|
|
1091
|
+
const lexDeclarations = collectScopedDeclarations(code, {
|
|
1091
1092
|
var: false,
|
|
1092
1093
|
topLevel: true
|
|
1093
1094
|
});
|
|
1094
|
-
for (
|
|
1095
|
-
for (
|
|
1095
|
+
for (const d of lexDeclarations) {
|
|
1096
|
+
for (const dn of collectBoundNames(d)) {
|
|
1096
1097
|
// Only lexical VariableDeclaration here in top-level.
|
|
1097
|
-
if (
|
|
1098
|
+
if (d.kind === "const") {
|
|
1098
1099
|
lexEnv.CreateImmutableBinding(dn, true);
|
|
1099
1100
|
} else {
|
|
1100
1101
|
lexEnv.CreateMutableBinding(dn, false);
|
|
1101
1102
|
}
|
|
1102
1103
|
}
|
|
1103
1104
|
}
|
|
1104
|
-
for (
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
varEnv.SetMutableBinding(
|
|
1105
|
+
for (const f of functionsToInitialize) {
|
|
1106
|
+
const [fn] = collectBoundNames(f);
|
|
1107
|
+
const fo = InstantiateFunctionObject(f, lexEnv);
|
|
1108
|
+
varEnv.SetMutableBinding(fn, fo, false);
|
|
1108
1109
|
}
|
|
1109
1110
|
}
|
|
1110
1111
|
|
|
@@ -1115,30 +1116,30 @@ export function cook(rootAst, codeSource) {
|
|
|
1115
1116
|
|
|
1116
1117
|
// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
|
|
1117
1118
|
function InstantiateOrdinaryFunctionExpression(functionExpression) {
|
|
1118
|
-
|
|
1119
|
+
const scope = getRunningContext().LexicalEnvironment;
|
|
1119
1120
|
if (functionExpression.id) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1121
|
+
const name = functionExpression.id.name;
|
|
1122
|
+
const funcEnv = new DeclarativeEnvironment(scope);
|
|
1122
1123
|
funcEnv.CreateImmutableBinding(name, false);
|
|
1123
|
-
|
|
1124
|
+
const closure = OrdinaryFunctionCreate(functionExpression, funcEnv, true);
|
|
1124
1125
|
funcEnv.InitializeBinding(name, closure);
|
|
1125
1126
|
return closure;
|
|
1126
1127
|
} else {
|
|
1127
|
-
|
|
1128
|
-
return
|
|
1128
|
+
const closure = OrdinaryFunctionCreate(functionExpression, scope, true);
|
|
1129
|
+
return closure;
|
|
1129
1130
|
}
|
|
1130
1131
|
}
|
|
1131
1132
|
|
|
1132
1133
|
// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatearrowfunctionexpression
|
|
1133
1134
|
function InstantiateArrowFunctionExpression(arrowFunction) {
|
|
1134
|
-
|
|
1135
|
-
|
|
1135
|
+
const scope = getRunningContext().LexicalEnvironment;
|
|
1136
|
+
const closure = OrdinaryFunctionCreate(arrowFunction, scope, false);
|
|
1136
1137
|
return closure;
|
|
1137
1138
|
}
|
|
1138
1139
|
|
|
1139
1140
|
// https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
|
|
1140
1141
|
function OrdinaryFunctionCreate(sourceNode, scope, isConstructor) {
|
|
1141
|
-
|
|
1142
|
+
const F = function () {
|
|
1142
1143
|
// eslint-disable-next-line prefer-rest-params
|
|
1143
1144
|
return CallFunction(F, arguments);
|
|
1144
1145
|
};
|
|
@@ -1173,7 +1174,7 @@ export function cook(rootAst, codeSource) {
|
|
|
1173
1174
|
return PropertyBindingInitialization(node.properties, value, environment);
|
|
1174
1175
|
case "ArrayPattern":
|
|
1175
1176
|
{
|
|
1176
|
-
|
|
1177
|
+
const iteratorRecord = CreateListIteratorRecord(value);
|
|
1177
1178
|
return IteratorBindingInitialization(node.elements, iteratorRecord, environment);
|
|
1178
1179
|
}
|
|
1179
1180
|
}
|
|
@@ -1181,8 +1182,8 @@ export function cook(rootAst, codeSource) {
|
|
|
1181
1182
|
|
|
1182
1183
|
// https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization
|
|
1183
1184
|
function PropertyBindingInitialization(properties, value, environment) {
|
|
1184
|
-
|
|
1185
|
-
for (
|
|
1185
|
+
const excludedNames = new Set();
|
|
1186
|
+
for (const prop of properties) {
|
|
1186
1187
|
if (prop.type === "RestElement") {
|
|
1187
1188
|
return RestBindingInitialization(prop, value, environment, excludedNames);
|
|
1188
1189
|
}
|
|
@@ -1190,7 +1191,7 @@ export function cook(rootAst, codeSource) {
|
|
|
1190
1191
|
KeyedBindingInitialization(prop.value, value, environment, prop.key.name);
|
|
1191
1192
|
excludedNames.add(prop.key.name);
|
|
1192
1193
|
} else {
|
|
1193
|
-
|
|
1194
|
+
const P = EvaluateComputedPropertyName(prop.key);
|
|
1194
1195
|
KeyedBindingInitialization(prop.value, value, environment, P);
|
|
1195
1196
|
excludedNames.add(P);
|
|
1196
1197
|
}
|
|
@@ -1200,14 +1201,14 @@ export function cook(rootAst, codeSource) {
|
|
|
1200
1201
|
|
|
1201
1202
|
// https://tc39.es/ecma262/#prod-ComputedPropertyName
|
|
1202
1203
|
function EvaluateComputedPropertyName(node) {
|
|
1203
|
-
|
|
1204
|
+
const propName = GetValue(Evaluate(node));
|
|
1204
1205
|
return ToPropertyKey(propName);
|
|
1205
1206
|
}
|
|
1206
1207
|
|
|
1207
1208
|
// https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-restbindinginitialization
|
|
1208
1209
|
function RestBindingInitialization(restProperty, value, environment, excludedNames) {
|
|
1209
|
-
|
|
1210
|
-
|
|
1210
|
+
const lhs = ResolveBinding(restProperty.argument.name, environment);
|
|
1211
|
+
const restObj = CopyDataProperties({}, value, excludedNames);
|
|
1211
1212
|
if (!environment) {
|
|
1212
1213
|
return PutValue(lhs, restObj);
|
|
1213
1214
|
}
|
|
@@ -1219,65 +1220,65 @@ export function cook(rootAst, codeSource) {
|
|
|
1219
1220
|
if (elements.length === 0) {
|
|
1220
1221
|
return NormalCompletion(Empty);
|
|
1221
1222
|
}
|
|
1222
|
-
|
|
1223
|
-
for (
|
|
1224
|
-
if (!
|
|
1223
|
+
let result;
|
|
1224
|
+
for (const node of elements) {
|
|
1225
|
+
if (!node) {
|
|
1225
1226
|
// Elision element.
|
|
1226
1227
|
iteratorRecord.next();
|
|
1227
1228
|
result = NormalCompletion(Empty);
|
|
1228
|
-
} else if (
|
|
1229
|
+
} else if (node.type === "RestElement") {
|
|
1229
1230
|
// Rest element.
|
|
1230
|
-
if (
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1231
|
+
if (node.argument.type === "Identifier") {
|
|
1232
|
+
const lhs = ResolveBinding(node.argument.name, environment);
|
|
1233
|
+
const A = [];
|
|
1234
|
+
let n = 0;
|
|
1234
1235
|
// eslint-disable-next-line no-constant-condition
|
|
1235
1236
|
while (true) {
|
|
1236
|
-
|
|
1237
|
+
const {
|
|
1237
1238
|
done,
|
|
1238
|
-
value
|
|
1239
|
+
value
|
|
1239
1240
|
} = iteratorRecord.next();
|
|
1240
1241
|
if (done) {
|
|
1241
1242
|
result = environment ? InitializeReferencedBinding(lhs, A) : PutValue(lhs, A);
|
|
1242
1243
|
break;
|
|
1243
1244
|
}
|
|
1244
|
-
A[n] =
|
|
1245
|
+
A[n] = value;
|
|
1245
1246
|
n++;
|
|
1246
1247
|
}
|
|
1247
1248
|
} else {
|
|
1248
|
-
|
|
1249
|
-
|
|
1249
|
+
const A = [];
|
|
1250
|
+
let n = 0;
|
|
1250
1251
|
// eslint-disable-next-line no-constant-condition
|
|
1251
1252
|
while (true) {
|
|
1252
|
-
|
|
1253
|
-
done
|
|
1254
|
-
value
|
|
1253
|
+
const {
|
|
1254
|
+
done,
|
|
1255
|
+
value
|
|
1255
1256
|
} = iteratorRecord.next();
|
|
1256
|
-
if (
|
|
1257
|
-
result = BindingInitialization(
|
|
1257
|
+
if (done) {
|
|
1258
|
+
result = BindingInitialization(node.argument, A, environment);
|
|
1258
1259
|
break;
|
|
1259
1260
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1261
|
+
A[n] = value;
|
|
1262
|
+
n++;
|
|
1262
1263
|
}
|
|
1263
1264
|
}
|
|
1264
1265
|
} else {
|
|
1265
1266
|
// Normal element.
|
|
1266
|
-
|
|
1267
|
+
const bindingElement = node.type === "AssignmentPattern" ? node.left : node;
|
|
1267
1268
|
switch (bindingElement.type) {
|
|
1268
1269
|
case "ObjectPattern":
|
|
1269
1270
|
case "ArrayPattern":
|
|
1270
1271
|
{
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
done
|
|
1274
|
-
value
|
|
1272
|
+
let v;
|
|
1273
|
+
const {
|
|
1274
|
+
done,
|
|
1275
|
+
value
|
|
1275
1276
|
} = iteratorRecord.next();
|
|
1276
|
-
if (!
|
|
1277
|
-
v =
|
|
1277
|
+
if (!done) {
|
|
1278
|
+
v = value;
|
|
1278
1279
|
}
|
|
1279
|
-
if (
|
|
1280
|
-
|
|
1280
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1281
|
+
const defaultValue = Evaluate(node.right);
|
|
1281
1282
|
v = GetValue(defaultValue);
|
|
1282
1283
|
}
|
|
1283
1284
|
result = BindingInitialization(bindingElement, v, environment);
|
|
@@ -1285,22 +1286,22 @@ export function cook(rootAst, codeSource) {
|
|
|
1285
1286
|
}
|
|
1286
1287
|
case "Identifier":
|
|
1287
1288
|
{
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
done
|
|
1293
|
-
value
|
|
1289
|
+
const bindingId = bindingElement.name;
|
|
1290
|
+
const lhs = ResolveBinding(bindingId, environment);
|
|
1291
|
+
let v;
|
|
1292
|
+
const {
|
|
1293
|
+
done,
|
|
1294
|
+
value
|
|
1294
1295
|
} = iteratorRecord.next();
|
|
1295
|
-
if (!
|
|
1296
|
-
|
|
1296
|
+
if (!done) {
|
|
1297
|
+
v = value;
|
|
1297
1298
|
}
|
|
1298
|
-
if (
|
|
1299
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1299
1300
|
// IsAnonymousFunctionDefinition(Initializer)
|
|
1300
|
-
|
|
1301
|
-
|
|
1301
|
+
const defaultValue = Evaluate(node.right);
|
|
1302
|
+
v = GetValue(defaultValue);
|
|
1302
1303
|
}
|
|
1303
|
-
result = environment ? InitializeReferencedBinding(
|
|
1304
|
+
result = environment ? InitializeReferencedBinding(lhs, v) : PutValue(lhs, v);
|
|
1304
1305
|
break;
|
|
1305
1306
|
}
|
|
1306
1307
|
}
|
|
@@ -1311,25 +1312,25 @@ export function cook(rootAst, codeSource) {
|
|
|
1311
1312
|
|
|
1312
1313
|
// https://tc39.es/ecma262/#sec-runtime-semantics-keyedbindinginitialization
|
|
1313
1314
|
function KeyedBindingInitialization(node, value, environment, propertyName) {
|
|
1314
|
-
|
|
1315
|
+
const isIdentifier = node.type === "Identifier" || node.type === "AssignmentPattern" && node.left.type === "Identifier";
|
|
1315
1316
|
if (isIdentifier) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
if (node.type === "AssignmentPattern" &&
|
|
1317
|
+
const bindingId = node.type === "Identifier" ? node.name : node.left.name;
|
|
1318
|
+
const lhs = ResolveBinding(bindingId, environment);
|
|
1319
|
+
let v = GetV(value, propertyName);
|
|
1320
|
+
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1320
1321
|
// If IsAnonymousFunctionDefinition(Initializer)
|
|
1321
|
-
|
|
1322
|
-
|
|
1322
|
+
const defaultValue = Evaluate(node.right);
|
|
1323
|
+
v = GetValue(defaultValue);
|
|
1323
1324
|
}
|
|
1324
1325
|
if (!environment) {
|
|
1325
|
-
return PutValue(lhs,
|
|
1326
|
+
return PutValue(lhs, v);
|
|
1326
1327
|
}
|
|
1327
|
-
return InitializeReferencedBinding(lhs,
|
|
1328
|
+
return InitializeReferencedBinding(lhs, v);
|
|
1328
1329
|
}
|
|
1329
|
-
|
|
1330
|
+
let v = GetV(value, propertyName);
|
|
1330
1331
|
if (node.type === "AssignmentPattern" && v === undefined) {
|
|
1331
|
-
|
|
1332
|
-
v = GetValue(
|
|
1332
|
+
const defaultValue = Evaluate(node.right);
|
|
1333
|
+
v = GetValue(defaultValue);
|
|
1333
1334
|
}
|
|
1334
1335
|
return BindingInitialization(node.type === "AssignmentPattern" ? node.left : node, v, environment);
|
|
1335
1336
|
}
|
|
@@ -1342,7 +1343,7 @@ export function cook(rootAst, codeSource) {
|
|
|
1342
1343
|
}
|
|
1343
1344
|
function ThrowIfFunctionIsInvalid(func) {
|
|
1344
1345
|
if (func.async || func.generator) {
|
|
1345
|
-
throw new SyntaxError(
|
|
1346
|
+
throw new SyntaxError(`${func.async ? "Async" : "Generator"} function is not allowed`);
|
|
1346
1347
|
}
|
|
1347
1348
|
if (expressionOnly && !func.expression) {
|
|
1348
1349
|
throw new SyntaxError("Only an `Expression` is allowed in `ArrowFunctionExpression`'s body");
|
|
@@ -1353,10 +1354,10 @@ export function cook(rootAst, codeSource) {
|
|
|
1353
1354
|
}
|
|
1354
1355
|
(_hooks$beforeEvaluate3 = hooks.beforeEvaluate) === null || _hooks$beforeEvaluate3 === void 0 || _hooks$beforeEvaluate3.call(hooks, rootAst);
|
|
1355
1356
|
ThrowIfFunctionIsInvalid(rootAst);
|
|
1356
|
-
|
|
1357
|
+
const [fn] = collectBoundNames(rootAst);
|
|
1357
1358
|
// Create an immutable binding for the root function.
|
|
1358
1359
|
rootEnv.CreateImmutableBinding(fn, true);
|
|
1359
|
-
|
|
1360
|
+
const fo = InstantiateFunctionObject(rootAst, rootEnv);
|
|
1360
1361
|
rootEnv.InitializeBinding(fn, fo);
|
|
1361
1362
|
return fo;
|
|
1362
1363
|
}
|