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