@opencode/codemode 0.0.0-beta-19289 → 0.0.0-beta-19365
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/README.md +6 -0
- package/dist/codemode.d.ts +8 -11
- package/dist/codemode.js +4 -8
- package/dist/data.d.ts +28 -0
- package/dist/data.js +130 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interpreter/errors.d.ts +1 -1
- package/dist/interpreter/errors.js +2 -2
- package/dist/interpreter/execute.d.ts +3 -3
- package/dist/interpreter/execute.js +9 -15
- package/dist/interpreter/methods.d.ts +9 -2
- package/dist/interpreter/methods.js +54 -76
- package/dist/interpreter/model.d.ts +12 -32
- package/dist/interpreter/model.js +0 -31
- package/dist/interpreter/promises.d.ts +8 -8
- package/dist/interpreter/promises.js +4 -4
- package/dist/interpreter/references.js +12 -42
- package/dist/interpreter/runtime.d.ts +2 -3
- package/dist/interpreter/runtime.js +255 -311
- package/dist/openapi/spec.js +1 -1
- package/dist/stdlib/console.js +14 -14
- package/dist/stdlib/date.d.ts +2 -2
- package/dist/stdlib/date.js +1 -1
- package/dist/stdlib/json.js +17 -26
- package/dist/stdlib/number.d.ts +1 -1
- package/dist/stdlib/number.js +4 -3
- package/dist/stdlib/object.js +11 -10
- package/dist/stdlib/regexp.d.ts +2 -2
- package/dist/stdlib/regexp.js +3 -3
- package/dist/stdlib/string.d.ts +1 -1
- package/dist/stdlib/string.js +1 -1
- package/dist/stdlib/url.d.ts +3 -3
- package/dist/stdlib/url.js +7 -6
- package/dist/stdlib/value.d.ts +2 -3
- package/dist/stdlib/value.js +14 -15
- package/dist/tool-runtime.d.ts +16 -15
- package/dist/tool-runtime.js +13 -150
- package/dist/values.d.ts +22 -16
- package/dist/values.js +23 -17
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Cause, Deferred, Effect, Exit } from "effect";
|
|
2
|
-
import { isBlockedMember,
|
|
3
|
-
import {
|
|
2
|
+
import { isBlockedMember, ToolRuntimeError, toProgram } from "../data.js";
|
|
3
|
+
import { ToolReference } from "../tool-runtime.js";
|
|
4
|
+
import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, CoercionFunction, ComputedValue, ErrorConstructorReference, GlobalMethodReference, GlobalNamespace, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError, isRecord, IteratorSymbol, IteratorSymbols, JsonMethodReference, OptionalShortCircuit, PromiseCapabilityFunction, PromiseInstanceMethodReference, PromiseMethodReference, PromiseNamespace, ProgramThrow, SearchFunction, SymbolNamespace, unsupportedSyntax, UriFunction, } from "./model.js";
|
|
4
5
|
import { caughtErrorValue, constructAggregateErrorValue, constructErrorValue } from "./errors.js";
|
|
5
|
-
import { arrayStatics, invokeArrayFrom, invokeGlobalMethod, invokeGroupBy, invokeIntrinsic, } from "./methods.js";
|
|
6
|
+
import { arrayStatics, invokeArrayFrom, invokeGlobalMethod, invokeGroupBy, invokeIntrinsic, toPrimitive, } from "./methods.js";
|
|
6
7
|
import { preserveConsumerError } from "./iterator.js";
|
|
7
8
|
import { constructPromise, invokePromiseInstanceMethod, invokePromiseMethod, PromiseRuntime, resolvePromise, resolvePromiseValue, } from "./promises.js";
|
|
8
9
|
import { containsOpaqueReference, isRuntimeReference, rejectCircularInsertion, typeofValue } from "./references.js";
|
|
@@ -18,8 +19,8 @@ import { promiseStatics } from "../stdlib/promise.js";
|
|
|
18
19
|
import { escapeRegexHint, regexpMethods, regexpProperties, regexpStatics, regexFailureReason, } from "../stdlib/regexp.js";
|
|
19
20
|
import { stringMethods, stringStatics } from "../stdlib/string.js";
|
|
20
21
|
import { urlMethods, urlProperties, urlSearchParamsMethods, urlStatics, urlWritableProperties, invokeUriFunction, uriArgument, urlArgument, } from "../stdlib/url.js";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
22
|
+
import { coerceToNumber, coerceToString, compoundOperators, errorBrandName, errorConstructors, invokeCoercion, valueConstructors, } from "../stdlib/value.js";
|
|
23
|
+
import { Values } from "../values.js";
|
|
23
24
|
const globalStaticMembers = {
|
|
24
25
|
Object: objectStatics,
|
|
25
26
|
Math: mathMethods,
|
|
@@ -39,18 +40,18 @@ const parseArrayIndex = (key) => {
|
|
|
39
40
|
return index < MAX_ARRAY_LENGTH ? index : undefined;
|
|
40
41
|
};
|
|
41
42
|
const calleeDescription = (callee) => {
|
|
42
|
-
if (callee
|
|
43
|
-
return
|
|
44
|
-
if (callee
|
|
45
|
-
const object =
|
|
46
|
-
const property =
|
|
47
|
-
const key = callee.computed
|
|
48
|
-
?
|
|
43
|
+
if (callee?.type === "Identifier")
|
|
44
|
+
return callee.name;
|
|
45
|
+
if (callee?.type === "MemberExpression") {
|
|
46
|
+
const object = callee.object;
|
|
47
|
+
const property = callee.property;
|
|
48
|
+
const key = !callee.computed && property.type === "Identifier"
|
|
49
|
+
? property.name
|
|
49
50
|
: property.type === "Literal" && typeof property.value === "string"
|
|
50
51
|
? property.value
|
|
51
52
|
: undefined;
|
|
52
53
|
if (object.type === "Identifier" && key !== undefined)
|
|
53
|
-
return `${
|
|
54
|
+
return `${object.name}.${key}`;
|
|
54
55
|
}
|
|
55
56
|
return "The called value";
|
|
56
57
|
};
|
|
@@ -62,17 +63,17 @@ const instanceofValue = (lhs, rhs, node) => {
|
|
|
62
63
|
if (rhs instanceof GlobalNamespace) {
|
|
63
64
|
switch (rhs.name) {
|
|
64
65
|
case "Date":
|
|
65
|
-
return lhs instanceof
|
|
66
|
+
return lhs instanceof Values.Date;
|
|
66
67
|
case "RegExp":
|
|
67
|
-
return lhs instanceof
|
|
68
|
+
return lhs instanceof Values.RegExp;
|
|
68
69
|
case "Map":
|
|
69
|
-
return lhs instanceof
|
|
70
|
+
return lhs instanceof Values.Map;
|
|
70
71
|
case "Set":
|
|
71
|
-
return lhs instanceof
|
|
72
|
+
return lhs instanceof Values.Set;
|
|
72
73
|
case "URL":
|
|
73
|
-
return lhs instanceof
|
|
74
|
+
return lhs instanceof Values.URL;
|
|
74
75
|
case "URLSearchParams":
|
|
75
|
-
return lhs instanceof
|
|
76
|
+
return lhs instanceof Values.URLSearchParams;
|
|
76
77
|
case "Array":
|
|
77
78
|
return Array.isArray(lhs);
|
|
78
79
|
case "Object":
|
|
@@ -80,7 +81,7 @@ const instanceofValue = (lhs, rhs, node) => {
|
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
if (rhs instanceof PromiseNamespace)
|
|
83
|
-
return lhs instanceof
|
|
84
|
+
return lhs instanceof Values.Promise;
|
|
84
85
|
if (rhs instanceof CoercionFunction && (rhs.name === "Number" || rhs.name === "String" || rhs.name === "Boolean")) {
|
|
85
86
|
return false;
|
|
86
87
|
}
|
|
@@ -89,24 +90,23 @@ const instanceofValue = (lhs, rhs, node) => {
|
|
|
89
90
|
const collectPatternNames = (pattern, out = []) => {
|
|
90
91
|
switch (pattern.type) {
|
|
91
92
|
case "Identifier":
|
|
92
|
-
out.push(
|
|
93
|
+
out.push(pattern.name);
|
|
93
94
|
break;
|
|
94
95
|
case "AssignmentPattern":
|
|
95
|
-
collectPatternNames(
|
|
96
|
+
collectPatternNames(pattern.left, out);
|
|
96
97
|
break;
|
|
97
98
|
case "RestElement":
|
|
98
|
-
collectPatternNames(
|
|
99
|
+
collectPatternNames(pattern.argument, out);
|
|
99
100
|
break;
|
|
100
101
|
case "ArrayPattern":
|
|
101
|
-
for (const element of
|
|
102
|
+
for (const element of pattern.elements) {
|
|
102
103
|
if (element !== null)
|
|
103
|
-
collectPatternNames(
|
|
104
|
+
collectPatternNames(element, out);
|
|
104
105
|
}
|
|
105
106
|
break;
|
|
106
107
|
case "ObjectPattern":
|
|
107
|
-
for (const
|
|
108
|
-
|
|
109
|
-
collectPatternNames(prop.type === "RestElement" ? getNode(prop, "argument") : getNode(prop, "value"), out);
|
|
108
|
+
for (const prop of pattern.properties) {
|
|
109
|
+
collectPatternNames(prop.type === "RestElement" ? prop.argument : prop.value, out);
|
|
110
110
|
}
|
|
111
111
|
break;
|
|
112
112
|
}
|
|
@@ -115,13 +115,13 @@ const collectPatternNames = (pattern, out = []) => {
|
|
|
115
115
|
const loopDeclaration = (left, statement) => {
|
|
116
116
|
if (left.type !== "VariableDeclaration")
|
|
117
117
|
return undefined;
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
118
|
+
const declaration = left.declarations.length === 1 ? left.declarations[0] : undefined;
|
|
119
|
+
if (declaration === undefined) {
|
|
120
120
|
throw new InterpreterRuntimeError(`${statement} supports one declared binding.`, left);
|
|
121
121
|
}
|
|
122
|
-
const kind =
|
|
122
|
+
const kind = left.kind;
|
|
123
123
|
return {
|
|
124
|
-
pattern:
|
|
124
|
+
pattern: declaration.id,
|
|
125
125
|
mutable: kind !== "const",
|
|
126
126
|
lexical: kind !== "var",
|
|
127
127
|
};
|
|
@@ -139,7 +139,7 @@ const copyIteratorSymbols = (source, target, consumed) => {
|
|
|
139
139
|
Reflect.set(target, symbol, Reflect.get(source, symbol));
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
-
const promiseResolutionNode = { type: "PromiseResolution" };
|
|
142
|
+
const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
|
|
143
143
|
export class Interpreter {
|
|
144
144
|
scopes;
|
|
145
145
|
executeTool;
|
|
@@ -206,7 +206,7 @@ export class Interpreter {
|
|
|
206
206
|
let value = undefined;
|
|
207
207
|
for (const [index, statement] of program.body.entries()) {
|
|
208
208
|
if (index === program.body.length - 1 && statement.type === "ExpressionStatement") {
|
|
209
|
-
value = yield* self.evaluateExpression(
|
|
209
|
+
value = yield* self.evaluateExpression(statement.expression);
|
|
210
210
|
break;
|
|
211
211
|
}
|
|
212
212
|
const result = yield* self.evaluateStatement(statement);
|
|
@@ -241,11 +241,11 @@ export class Interpreter {
|
|
|
241
241
|
evaluateStatement(node) {
|
|
242
242
|
switch (node.type) {
|
|
243
243
|
case "ExpressionStatement":
|
|
244
|
-
return Effect.as(this.evaluateExpression(
|
|
244
|
+
return Effect.as(this.evaluateExpression(node.expression), { kind: "none" });
|
|
245
245
|
case "VariableDeclaration":
|
|
246
246
|
return Effect.map(this.evaluateVariableDeclaration(node), () => ({ kind: "none" }));
|
|
247
247
|
case "ReturnStatement": {
|
|
248
|
-
const argumentNode =
|
|
248
|
+
const argumentNode = node.argument;
|
|
249
249
|
return argumentNode
|
|
250
250
|
? Effect.map(this.evaluateExpression(argumentNode), (value) => ({ kind: "return", value }))
|
|
251
251
|
: Effect.succeed({ kind: "return", value: undefined });
|
|
@@ -288,11 +288,10 @@ export class Interpreter {
|
|
|
288
288
|
this.scopes.push();
|
|
289
289
|
const self = this;
|
|
290
290
|
return Effect.gen(function* () {
|
|
291
|
-
const body =
|
|
291
|
+
const body = node.body;
|
|
292
292
|
self.predeclareLexical(body);
|
|
293
293
|
self.hoistFunctions(body);
|
|
294
|
-
for (const
|
|
295
|
-
const statement = asNode(statementValue, "body");
|
|
294
|
+
for (const statement of body) {
|
|
296
295
|
const result = yield* self.evaluateStatement(statement);
|
|
297
296
|
if (result.kind !== "none") {
|
|
298
297
|
return result;
|
|
@@ -302,27 +301,24 @@ export class Interpreter {
|
|
|
302
301
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
303
302
|
}
|
|
304
303
|
createFunction(node) {
|
|
305
|
-
return new CodeModeFunction(
|
|
304
|
+
return new CodeModeFunction(node.params, node.body, this.scopes.capture(), node.async, node.generator);
|
|
306
305
|
}
|
|
307
306
|
hoistFunctions(statements) {
|
|
308
|
-
for (const
|
|
309
|
-
if (
|
|
307
|
+
for (const node of statements) {
|
|
308
|
+
if (node.type !== "FunctionDeclaration")
|
|
310
309
|
continue;
|
|
311
|
-
|
|
312
|
-
this.scopes.declare(getString(getNode(node, "id"), "name"), this.createFunction(node), true, node);
|
|
310
|
+
this.scopes.declare(node.id.name, this.createFunction(node), true, node);
|
|
313
311
|
}
|
|
314
312
|
}
|
|
315
313
|
predeclareLexical(statements) {
|
|
316
|
-
for (const
|
|
317
|
-
if (
|
|
314
|
+
for (const statement of statements) {
|
|
315
|
+
if (statement.type !== "VariableDeclaration")
|
|
318
316
|
continue;
|
|
319
|
-
const
|
|
320
|
-
const kind = getString(statement, "kind");
|
|
317
|
+
const kind = statement.kind;
|
|
321
318
|
if (kind === "var")
|
|
322
319
|
continue;
|
|
323
|
-
for (const
|
|
324
|
-
const
|
|
325
|
-
for (const name of collectPatternNames(getNode(declaration, "id"))) {
|
|
320
|
+
for (const declaration of statement.declarations) {
|
|
321
|
+
for (const name of collectPatternNames(declaration.id)) {
|
|
326
322
|
this.scopes.reserve(name, kind !== "const", declaration);
|
|
327
323
|
}
|
|
328
324
|
}
|
|
@@ -333,30 +329,27 @@ export class Interpreter {
|
|
|
333
329
|
this.scopes.reserve(name, mutable, node);
|
|
334
330
|
}
|
|
335
331
|
evaluateIfStatement(node) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
? this.evaluateStatement(consequentNode)
|
|
341
|
-
: alternateNode
|
|
342
|
-
? this.evaluateStatement(alternateNode)
|
|
332
|
+
return Effect.flatMap(this.evaluateExpression(node.test), (test) => test
|
|
333
|
+
? this.evaluateStatement(node.consequent)
|
|
334
|
+
: node.alternate
|
|
335
|
+
? this.evaluateStatement(node.alternate)
|
|
343
336
|
: Effect.succeed({ kind: "none" }));
|
|
344
337
|
}
|
|
345
338
|
evaluateSwitchStatement(node) {
|
|
346
339
|
const self = this;
|
|
347
340
|
return Effect.gen(function* () {
|
|
348
|
-
const discriminant = yield* self.evaluateExpression(
|
|
341
|
+
const discriminant = yield* self.evaluateExpression(node.discriminant);
|
|
349
342
|
if (containsOpaqueReference(discriminant)) {
|
|
350
343
|
throw new InterpreterRuntimeError("Switch discriminants must be data values.", node, "InvalidDataValue");
|
|
351
344
|
}
|
|
352
345
|
self.scopes.push();
|
|
353
346
|
return yield* Effect.gen(function* () {
|
|
354
|
-
const cases =
|
|
355
|
-
self.predeclareLexical(cases.flatMap((branch) =>
|
|
347
|
+
const cases = node.cases;
|
|
348
|
+
self.predeclareLexical(cases.flatMap((branch) => branch.consequent));
|
|
356
349
|
let defaultIndex;
|
|
357
350
|
let selected;
|
|
358
351
|
for (const [index, branch] of cases.entries()) {
|
|
359
|
-
const test =
|
|
352
|
+
const test = branch.test;
|
|
360
353
|
if (!test) {
|
|
361
354
|
defaultIndex = index;
|
|
362
355
|
continue;
|
|
@@ -374,8 +367,8 @@ export class Interpreter {
|
|
|
374
367
|
if (start === undefined)
|
|
375
368
|
return { kind: "none" };
|
|
376
369
|
for (let index = start; index < cases.length; index += 1) {
|
|
377
|
-
for (const
|
|
378
|
-
const result = yield* self.evaluateStatement(
|
|
370
|
+
for (const statement of cases[index].consequent) {
|
|
371
|
+
const result = yield* self.evaluateStatement(statement);
|
|
379
372
|
if (result.kind === "break") {
|
|
380
373
|
if (result.label === undefined)
|
|
381
374
|
return { kind: "none" };
|
|
@@ -390,12 +383,10 @@ export class Interpreter {
|
|
|
390
383
|
});
|
|
391
384
|
}
|
|
392
385
|
evaluateWhileStatement(node, labels) {
|
|
393
|
-
const testNode = getNode(node, "test");
|
|
394
|
-
const bodyNode = getNode(node, "body");
|
|
395
386
|
const self = this;
|
|
396
387
|
return Effect.gen(function* () {
|
|
397
|
-
while (yield* self.evaluateExpression(
|
|
398
|
-
const result = yield* self.evaluateStatement(
|
|
388
|
+
while (yield* self.evaluateExpression(node.test)) {
|
|
389
|
+
const result = yield* self.evaluateStatement(node.body);
|
|
399
390
|
if (result.kind === "continue") {
|
|
400
391
|
if (result.label !== undefined && !labels?.has(result.label))
|
|
401
392
|
return result;
|
|
@@ -414,12 +405,10 @@ export class Interpreter {
|
|
|
414
405
|
});
|
|
415
406
|
}
|
|
416
407
|
evaluateDoWhileStatement(node, labels) {
|
|
417
|
-
const bodyNode = getNode(node, "body");
|
|
418
|
-
const testNode = getNode(node, "test");
|
|
419
408
|
const self = this;
|
|
420
409
|
return Effect.gen(function* () {
|
|
421
410
|
do {
|
|
422
|
-
const result = yield* self.evaluateStatement(
|
|
411
|
+
const result = yield* self.evaluateStatement(node.body);
|
|
423
412
|
if (result.kind === "continue") {
|
|
424
413
|
if (result.label !== undefined && !labels?.has(result.label))
|
|
425
414
|
return result;
|
|
@@ -433,7 +422,7 @@ export class Interpreter {
|
|
|
433
422
|
if (result.kind === "return") {
|
|
434
423
|
return result;
|
|
435
424
|
}
|
|
436
|
-
} while (yield* self.evaluateExpression(
|
|
425
|
+
} while (yield* self.evaluateExpression(node.test));
|
|
437
426
|
return { kind: "none" };
|
|
438
427
|
});
|
|
439
428
|
}
|
|
@@ -441,11 +430,10 @@ export class Interpreter {
|
|
|
441
430
|
this.scopes.push();
|
|
442
431
|
const self = this;
|
|
443
432
|
return Effect.gen(function* () {
|
|
444
|
-
const initNode =
|
|
445
|
-
const testNode =
|
|
446
|
-
const updateNode =
|
|
447
|
-
|
|
448
|
-
if (initNode?.type === "VariableDeclaration" && getString(initNode, "kind") !== "var") {
|
|
433
|
+
const initNode = node.init;
|
|
434
|
+
const testNode = node.test;
|
|
435
|
+
const updateNode = node.update;
|
|
436
|
+
if (initNode?.type === "VariableDeclaration" && initNode.kind !== "var") {
|
|
449
437
|
self.predeclareLexical([initNode]);
|
|
450
438
|
}
|
|
451
439
|
if (initNode) {
|
|
@@ -456,7 +444,7 @@ export class Interpreter {
|
|
|
456
444
|
yield* self.evaluateExpression(initNode);
|
|
457
445
|
}
|
|
458
446
|
}
|
|
459
|
-
const perIterationBindings = initNode?.type === "VariableDeclaration" &&
|
|
447
|
+
const perIterationBindings = initNode?.type === "VariableDeclaration" && initNode.kind !== "var"
|
|
460
448
|
? Array.from(self.scopes.current().keys())
|
|
461
449
|
: [];
|
|
462
450
|
const nextIteration = () => {
|
|
@@ -468,7 +456,7 @@ export class Interpreter {
|
|
|
468
456
|
};
|
|
469
457
|
nextIteration();
|
|
470
458
|
while (testNode ? yield* self.evaluateExpression(testNode) : true) {
|
|
471
|
-
const result = yield* self.evaluateStatement(
|
|
459
|
+
const result = yield* self.evaluateStatement(node.body);
|
|
472
460
|
if (result.kind === "return") {
|
|
473
461
|
return result;
|
|
474
462
|
}
|
|
@@ -491,8 +479,8 @@ export class Interpreter {
|
|
|
491
479
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
492
480
|
}
|
|
493
481
|
evaluateForOfStatement(node, labels) {
|
|
494
|
-
const awaiting =
|
|
495
|
-
const left =
|
|
482
|
+
const awaiting = node.await;
|
|
483
|
+
const left = node.left;
|
|
496
484
|
const declared = loopDeclaration(left, "for...of");
|
|
497
485
|
if (declared?.lexical)
|
|
498
486
|
this.scopes.push();
|
|
@@ -500,8 +488,7 @@ export class Interpreter {
|
|
|
500
488
|
return Effect.gen(function* () {
|
|
501
489
|
if (declared?.lexical)
|
|
502
490
|
self.predeclarePattern(declared.pattern, declared.mutable, left);
|
|
503
|
-
const right = yield* self.evaluateExpression(
|
|
504
|
-
const body = getNode(node, "body");
|
|
491
|
+
const right = yield* self.evaluateExpression(node.right);
|
|
505
492
|
const iterator = yield* self.customIterator(right, node, awaiting);
|
|
506
493
|
const cursor = iterator === undefined ? yield* self.syncIterator(right, node) : undefined;
|
|
507
494
|
if (iterator === undefined && cursor === undefined) {
|
|
@@ -512,17 +499,10 @@ export class Interpreter {
|
|
|
512
499
|
: awaiting
|
|
513
500
|
? Effect.andThen(cursor?.close ?? Effect.void, Effect.yieldNow)
|
|
514
501
|
: (cursor?.close ?? Effect.void);
|
|
515
|
-
|
|
516
|
-
if (left.type !== "VariableDeclaration" &&
|
|
517
|
-
(left.type === "Identifier" ||
|
|
518
|
-
left.type === "MemberExpression" ||
|
|
519
|
-
left.type === "ArrayPattern" ||
|
|
520
|
-
left.type === "ObjectPattern")) {
|
|
521
|
-
assignment = left;
|
|
522
|
-
}
|
|
523
|
-
else if (left.type !== "VariableDeclaration") {
|
|
502
|
+
if (left.type === "RestElement" || left.type === "AssignmentPattern") {
|
|
524
503
|
throw new InterpreterRuntimeError("Unsupported for...of binding.", left);
|
|
525
504
|
}
|
|
505
|
+
const assignment = left.type === "VariableDeclaration" ? undefined : left;
|
|
526
506
|
const evaluateBody = (value) => Effect.gen(function* () {
|
|
527
507
|
if (declared) {
|
|
528
508
|
self.scopes.push();
|
|
@@ -533,7 +513,7 @@ export class Interpreter {
|
|
|
533
513
|
else if (assignment) {
|
|
534
514
|
yield* self.assignPattern(assignment, value, left);
|
|
535
515
|
}
|
|
536
|
-
return yield* self.evaluateStatement(body);
|
|
516
|
+
return yield* self.evaluateStatement(node.body);
|
|
537
517
|
}).pipe(Effect.ensuring(Effect.sync(() => {
|
|
538
518
|
if (declared)
|
|
539
519
|
self.scopes.pop();
|
|
@@ -594,11 +574,11 @@ export class Interpreter {
|
|
|
594
574
|
? value[Symbol.iterator]()
|
|
595
575
|
: typeof value === "string"
|
|
596
576
|
? value[Symbol.iterator]()
|
|
597
|
-
: value instanceof
|
|
577
|
+
: value instanceof Values.Map
|
|
598
578
|
? value.map.entries()
|
|
599
|
-
: value instanceof
|
|
579
|
+
: value instanceof Values.Set
|
|
600
580
|
? value.set.values()
|
|
601
|
-
: value instanceof
|
|
581
|
+
: value instanceof Values.URLSearchParams
|
|
602
582
|
? value.params.entries()
|
|
603
583
|
: undefined;
|
|
604
584
|
if (iterator !== undefined) {
|
|
@@ -733,7 +713,7 @@ export class Interpreter {
|
|
|
733
713
|
return undefined;
|
|
734
714
|
}
|
|
735
715
|
evaluateForInStatement(node, labels) {
|
|
736
|
-
const left =
|
|
716
|
+
const left = node.left;
|
|
737
717
|
const declared = loopDeclaration(left, "for...in");
|
|
738
718
|
if (declared?.lexical)
|
|
739
719
|
this.scopes.push();
|
|
@@ -741,19 +721,15 @@ export class Interpreter {
|
|
|
741
721
|
return Effect.gen(function* () {
|
|
742
722
|
if (declared?.lexical)
|
|
743
723
|
self.predeclarePattern(declared.pattern, declared.mutable, left);
|
|
744
|
-
const right = yield* self.evaluateExpression(
|
|
745
|
-
const body = getNode(node, "body");
|
|
724
|
+
const right = yield* self.evaluateExpression(node.right);
|
|
746
725
|
const keys = self.enumerableKeys(right);
|
|
747
726
|
if (keys === undefined) {
|
|
748
727
|
throw new InterpreterRuntimeError("for...in requires a plain object, array, or tools reference. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", node);
|
|
749
728
|
}
|
|
750
|
-
|
|
751
|
-
if (left.type === "Identifier") {
|
|
752
|
-
assignmentName = getString(left, "name");
|
|
753
|
-
}
|
|
754
|
-
else if (left.type !== "VariableDeclaration") {
|
|
729
|
+
if (left.type !== "Identifier" && left.type !== "VariableDeclaration") {
|
|
755
730
|
throw new InterpreterRuntimeError("Unsupported for...in binding.", left);
|
|
756
731
|
}
|
|
732
|
+
const assignmentName = left.type === "Identifier" ? left.name : undefined;
|
|
757
733
|
for (const key of keys) {
|
|
758
734
|
const result = yield* Effect.gen(function* () {
|
|
759
735
|
if (declared) {
|
|
@@ -765,7 +741,7 @@ export class Interpreter {
|
|
|
765
741
|
else if (assignmentName) {
|
|
766
742
|
self.scopes.set(assignmentName, key, left);
|
|
767
743
|
}
|
|
768
|
-
return yield* self.evaluateStatement(body);
|
|
744
|
+
return yield* self.evaluateStatement(node.body);
|
|
769
745
|
}).pipe(Effect.ensuring(Effect.sync(() => {
|
|
770
746
|
if (declared)
|
|
771
747
|
self.scopes.pop();
|
|
@@ -791,19 +767,17 @@ export class Interpreter {
|
|
|
791
767
|
})));
|
|
792
768
|
}
|
|
793
769
|
evaluateBreakStatement(node) {
|
|
794
|
-
|
|
795
|
-
return labelNode ? { kind: "break", label: getString(labelNode, "name") } : { kind: "break" };
|
|
770
|
+
return node.label ? { kind: "break", label: node.label.name } : { kind: "break" };
|
|
796
771
|
}
|
|
797
772
|
evaluateContinueStatement(node) {
|
|
798
|
-
|
|
799
|
-
return labelNode ? { kind: "continue", label: getString(labelNode, "name") } : { kind: "continue" };
|
|
773
|
+
return node.label ? { kind: "continue", label: node.label.name } : { kind: "continue" };
|
|
800
774
|
}
|
|
801
775
|
evaluateLabeledStatement(node) {
|
|
802
776
|
const labels = new Set();
|
|
803
777
|
let body = node;
|
|
804
778
|
while (body.type === "LabeledStatement") {
|
|
805
|
-
labels.add(
|
|
806
|
-
body =
|
|
779
|
+
labels.add(body.label.name);
|
|
780
|
+
body = body.body;
|
|
807
781
|
}
|
|
808
782
|
const evaluated = (() => {
|
|
809
783
|
if (body.type === "WhileStatement")
|
|
@@ -823,13 +797,12 @@ export class Interpreter {
|
|
|
823
797
|
: result);
|
|
824
798
|
}
|
|
825
799
|
evaluateThrowStatement(node) {
|
|
826
|
-
|
|
827
|
-
return Effect.flatMap(this.evaluateExpression(argument), (value) => Effect.fail(new ProgramThrow(value)));
|
|
800
|
+
return Effect.flatMap(this.evaluateExpression(node.argument), (value) => Effect.fail(new ProgramThrow(value)));
|
|
828
801
|
}
|
|
829
802
|
evaluateTryStatement(node) {
|
|
830
|
-
const body =
|
|
831
|
-
const handler =
|
|
832
|
-
const finalizer =
|
|
803
|
+
const body = node.block;
|
|
804
|
+
const handler = node.handler;
|
|
805
|
+
const finalizer = node.finalizer;
|
|
833
806
|
const self = this;
|
|
834
807
|
const attempted = Effect.matchCauseEffect(this.evaluateStatement(body), {
|
|
835
808
|
onFailure: (cause) => {
|
|
@@ -837,12 +810,12 @@ export class Interpreter {
|
|
|
837
810
|
return Effect.failCause(cause);
|
|
838
811
|
}
|
|
839
812
|
const caught = caughtErrorValue(Cause.squash(cause));
|
|
840
|
-
const parameter =
|
|
813
|
+
const parameter = handler.param;
|
|
841
814
|
self.scopes.push();
|
|
842
815
|
return Effect.gen(function* () {
|
|
843
816
|
if (parameter)
|
|
844
817
|
yield* self.declarePattern(parameter, caught, true, handler);
|
|
845
|
-
return yield* self.evaluateStatement(
|
|
818
|
+
return yield* self.evaluateStatement(handler.body);
|
|
846
819
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
847
820
|
},
|
|
848
821
|
onSuccess: Effect.succeed,
|
|
@@ -858,18 +831,16 @@ export class Interpreter {
|
|
|
858
831
|
});
|
|
859
832
|
}
|
|
860
833
|
evaluateVariableDeclaration(node) {
|
|
861
|
-
const kind =
|
|
862
|
-
const declarations = getArray(node, "declarations");
|
|
834
|
+
const kind = node.kind;
|
|
863
835
|
const self = this;
|
|
864
836
|
return Effect.gen(function* () {
|
|
865
|
-
for (const
|
|
866
|
-
const declaration = asNode(declarationValue, "declarations");
|
|
837
|
+
for (const declaration of node.declarations) {
|
|
867
838
|
if (declaration.type !== "VariableDeclarator") {
|
|
868
839
|
throw new InterpreterRuntimeError("Unsupported variable declaration shape.", declaration);
|
|
869
840
|
}
|
|
870
|
-
const init =
|
|
841
|
+
const init = declaration.init;
|
|
871
842
|
const value = init ? yield* self.evaluateExpression(init) : undefined;
|
|
872
|
-
yield* self.declarePattern(
|
|
843
|
+
yield* self.declarePattern(declaration.id, value, kind !== "const", declaration, kind !== "var");
|
|
873
844
|
}
|
|
874
845
|
});
|
|
875
846
|
}
|
|
@@ -877,7 +848,7 @@ export class Interpreter {
|
|
|
877
848
|
const self = this;
|
|
878
849
|
return Effect.gen(function* () {
|
|
879
850
|
if (pattern.type === "Identifier") {
|
|
880
|
-
const name =
|
|
851
|
+
const name = pattern.name;
|
|
881
852
|
if (initialize)
|
|
882
853
|
self.scopes.initialize(name, value, node);
|
|
883
854
|
else
|
|
@@ -885,8 +856,8 @@ export class Interpreter {
|
|
|
885
856
|
return;
|
|
886
857
|
}
|
|
887
858
|
if (pattern.type === "AssignmentPattern") {
|
|
888
|
-
const resolved = value === undefined ? yield* self.evaluateExpression(
|
|
889
|
-
yield* self.declarePattern(
|
|
859
|
+
const resolved = value === undefined ? yield* self.evaluateExpression(pattern.right) : value;
|
|
860
|
+
yield* self.declarePattern(pattern.left, resolved, mutable, node, initialize);
|
|
890
861
|
return;
|
|
891
862
|
}
|
|
892
863
|
if (pattern.type === "ObjectPattern") {
|
|
@@ -894,8 +865,7 @@ export class Interpreter {
|
|
|
894
865
|
throw new InterpreterRuntimeError("Object destructuring requires a data object or array value.", pattern, "InvalidDataValue");
|
|
895
866
|
}
|
|
896
867
|
const consumed = new Set();
|
|
897
|
-
for (const
|
|
898
|
-
const property = asNode(propertyValue, "properties");
|
|
868
|
+
for (const property of pattern.properties) {
|
|
899
869
|
if (property.type === "RestElement") {
|
|
900
870
|
const rest = Object.create(null);
|
|
901
871
|
for (const [key, item] of Object.entries(value)) {
|
|
@@ -903,7 +873,7 @@ export class Interpreter {
|
|
|
903
873
|
rest[key] = item;
|
|
904
874
|
}
|
|
905
875
|
copyIteratorSymbols(value, rest, consumed);
|
|
906
|
-
yield* self.declarePattern(
|
|
876
|
+
yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
|
|
907
877
|
continue;
|
|
908
878
|
}
|
|
909
879
|
const key = yield* self.destructuringPropertyKey(property);
|
|
@@ -911,7 +881,7 @@ export class Interpreter {
|
|
|
911
881
|
throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, property);
|
|
912
882
|
}
|
|
913
883
|
consumed.add(typeof key === "symbol" ? key : String(key));
|
|
914
|
-
yield* self.declarePattern(
|
|
884
|
+
yield* self.declarePattern(property.value, self.destructuringPropertyValue(value, key), mutable, property, initialize);
|
|
915
885
|
}
|
|
916
886
|
return;
|
|
917
887
|
}
|
|
@@ -925,7 +895,7 @@ export class Interpreter {
|
|
|
925
895
|
const self = this;
|
|
926
896
|
return Effect.gen(function* () {
|
|
927
897
|
if (pattern.type === "Identifier") {
|
|
928
|
-
self.scopes.set(
|
|
898
|
+
self.scopes.set(pattern.name, value, pattern);
|
|
929
899
|
return;
|
|
930
900
|
}
|
|
931
901
|
if (pattern.type === "MemberExpression") {
|
|
@@ -933,8 +903,8 @@ export class Interpreter {
|
|
|
933
903
|
return;
|
|
934
904
|
}
|
|
935
905
|
if (pattern.type === "AssignmentPattern") {
|
|
936
|
-
const resolved = value === undefined ? yield* self.evaluateExpression(
|
|
937
|
-
yield* self.assignPattern(
|
|
906
|
+
const resolved = value === undefined ? yield* self.evaluateExpression(pattern.right) : value;
|
|
907
|
+
yield* self.assignPattern(pattern.left, resolved, node);
|
|
938
908
|
return;
|
|
939
909
|
}
|
|
940
910
|
if (pattern.type === "ObjectPattern") {
|
|
@@ -943,8 +913,7 @@ export class Interpreter {
|
|
|
943
913
|
}
|
|
944
914
|
const source = value;
|
|
945
915
|
const consumed = new Set();
|
|
946
|
-
for (const
|
|
947
|
-
const property = asNode(propertyValue, "properties");
|
|
916
|
+
for (const property of pattern.properties) {
|
|
948
917
|
if (property.type === "RestElement") {
|
|
949
918
|
const rest = Object.create(null);
|
|
950
919
|
for (const [key, item] of Object.entries(source)) {
|
|
@@ -952,7 +921,7 @@ export class Interpreter {
|
|
|
952
921
|
rest[key] = item;
|
|
953
922
|
}
|
|
954
923
|
copyIteratorSymbols(source, rest, consumed);
|
|
955
|
-
yield* self.assignPattern(
|
|
924
|
+
yield* self.assignPattern(property.argument, rest, property);
|
|
956
925
|
continue;
|
|
957
926
|
}
|
|
958
927
|
const key = yield* self.destructuringPropertyKey(property);
|
|
@@ -960,7 +929,7 @@ export class Interpreter {
|
|
|
960
929
|
throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, property);
|
|
961
930
|
}
|
|
962
931
|
consumed.add(typeof key === "symbol" ? key : String(key));
|
|
963
|
-
yield* self.assignPattern(
|
|
932
|
+
yield* self.assignPattern(property.value, self.destructuringPropertyValue(source, key), property);
|
|
964
933
|
}
|
|
965
934
|
return;
|
|
966
935
|
}
|
|
@@ -978,21 +947,19 @@ export class Interpreter {
|
|
|
978
947
|
throw new InterpreterRuntimeError("Array destructuring requires a supported iterable value.", pattern).as("TypeError");
|
|
979
948
|
}
|
|
980
949
|
let done = false;
|
|
981
|
-
for (const
|
|
950
|
+
for (const element of pattern.elements) {
|
|
982
951
|
if (done) {
|
|
983
|
-
if (
|
|
952
|
+
if (element === null)
|
|
984
953
|
continue;
|
|
985
|
-
|
|
986
|
-
yield* consume(element.type === "RestElement" ? getNode(element, "argument") : element, element.type === "RestElement" ? [] : undefined, element);
|
|
954
|
+
yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? [] : undefined, element);
|
|
987
955
|
if (element.type === "RestElement")
|
|
988
956
|
return;
|
|
989
957
|
continue;
|
|
990
958
|
}
|
|
991
959
|
const step = yield* cursor.next;
|
|
992
960
|
done = step.done;
|
|
993
|
-
if (
|
|
961
|
+
if (element === null)
|
|
994
962
|
continue;
|
|
995
|
-
const element = asNode(item, `elements[${index}]`);
|
|
996
963
|
if (element.type === "RestElement") {
|
|
997
964
|
const rest = [];
|
|
998
965
|
if (!step.done)
|
|
@@ -1003,7 +970,7 @@ export class Interpreter {
|
|
|
1003
970
|
if (!done)
|
|
1004
971
|
rest.push(next.value);
|
|
1005
972
|
}
|
|
1006
|
-
yield* consume(
|
|
973
|
+
yield* consume(element.argument, rest, element);
|
|
1007
974
|
return;
|
|
1008
975
|
}
|
|
1009
976
|
const consumed = consume(element, step.done ? undefined : step.value, pattern);
|
|
@@ -1014,14 +981,18 @@ export class Interpreter {
|
|
|
1014
981
|
});
|
|
1015
982
|
}
|
|
1016
983
|
destructuringPropertyKey(property) {
|
|
1017
|
-
if (property.type !== "Property" ||
|
|
984
|
+
if (property.type !== "Property" || property.kind !== "init") {
|
|
1018
985
|
throw new InterpreterRuntimeError("Unsupported object destructuring property.", property);
|
|
1019
986
|
}
|
|
1020
|
-
const keyNode =
|
|
1021
|
-
if (
|
|
987
|
+
const keyNode = property.key;
|
|
988
|
+
if (property.computed) {
|
|
1022
989
|
return Effect.map(this.evaluateExpression(keyNode), (value) => this.toPropertyKey(value, keyNode));
|
|
1023
990
|
}
|
|
1024
|
-
|
|
991
|
+
if (keyNode.type === "Identifier")
|
|
992
|
+
return Effect.succeed(keyNode.name);
|
|
993
|
+
if (keyNode.type === "Literal")
|
|
994
|
+
return Effect.succeed(String(keyNode.value));
|
|
995
|
+
throw unsupportedSyntax(keyNode.type, keyNode);
|
|
1025
996
|
}
|
|
1026
997
|
destructuringPropertyValue(source, key) {
|
|
1027
998
|
if (!Array.isArray(source))
|
|
@@ -1040,13 +1011,12 @@ export class Interpreter {
|
|
|
1040
1011
|
switch (node.type) {
|
|
1041
1012
|
case "Literal": {
|
|
1042
1013
|
const regex = node.regex;
|
|
1043
|
-
if (
|
|
1044
|
-
return Effect.sync(() => this.constructRegExp([regex.pattern,
|
|
1045
|
-
|
|
1046
|
-
return Effect.sync(() => boundedData(node.value, "Literal"));
|
|
1014
|
+
if (regex)
|
|
1015
|
+
return Effect.sync(() => this.constructRegExp([regex.pattern, regex.flags], node));
|
|
1016
|
+
return Effect.sync(() => toProgram(node.value, "Literal"));
|
|
1047
1017
|
}
|
|
1048
1018
|
case "Identifier":
|
|
1049
|
-
return Effect.sync(() => this.scopes.get(
|
|
1019
|
+
return Effect.sync(() => this.scopes.get(node.name, node));
|
|
1050
1020
|
case "BinaryExpression":
|
|
1051
1021
|
return this.evaluateBinaryExpression(node);
|
|
1052
1022
|
case "LogicalExpression":
|
|
@@ -1059,8 +1029,8 @@ export class Interpreter {
|
|
|
1059
1029
|
const self = this;
|
|
1060
1030
|
return Effect.gen(function* () {
|
|
1061
1031
|
let result;
|
|
1062
|
-
for (const expression of
|
|
1063
|
-
result = yield* self.evaluateExpression(
|
|
1032
|
+
for (const expression of node.expressions) {
|
|
1033
|
+
result = yield* self.evaluateExpression(expression);
|
|
1064
1034
|
}
|
|
1065
1035
|
return result;
|
|
1066
1036
|
});
|
|
@@ -1073,7 +1043,7 @@ export class Interpreter {
|
|
|
1073
1043
|
case "MemberExpression":
|
|
1074
1044
|
return this.readMember(node);
|
|
1075
1045
|
case "ChainExpression":
|
|
1076
|
-
return Effect.map(this.evaluateExpression(
|
|
1046
|
+
return Effect.map(this.evaluateExpression(node.expression), (value) => value === OptionalShortCircuit ? undefined : value);
|
|
1077
1047
|
case "ObjectExpression":
|
|
1078
1048
|
return this.evaluateObjectExpression(node);
|
|
1079
1049
|
case "ArrayExpression":
|
|
@@ -1086,7 +1056,7 @@ export class Interpreter {
|
|
|
1086
1056
|
return this.evaluateUpdateExpression(node);
|
|
1087
1057
|
case "AwaitExpression": {
|
|
1088
1058
|
// Await always suspends, including for plain values.
|
|
1089
|
-
return Effect.flatMap(this.evaluateExpression(
|
|
1059
|
+
return Effect.flatMap(this.evaluateExpression(node.argument), (value) => this.awaitValue(value, node));
|
|
1090
1060
|
}
|
|
1091
1061
|
case "YieldExpression":
|
|
1092
1062
|
return this.evaluateYieldExpression(node);
|
|
@@ -1097,12 +1067,12 @@ export class Interpreter {
|
|
|
1097
1067
|
}
|
|
1098
1068
|
}
|
|
1099
1069
|
evaluateNewExpression(node) {
|
|
1100
|
-
const callee =
|
|
1070
|
+
const callee = node.callee;
|
|
1101
1071
|
if (callee.type !== "Identifier") {
|
|
1102
1072
|
throw unsupportedSyntax("NewExpression", node);
|
|
1103
1073
|
}
|
|
1104
|
-
const name =
|
|
1105
|
-
const argNodes =
|
|
1074
|
+
const name = callee.name;
|
|
1075
|
+
const argNodes = node.arguments;
|
|
1106
1076
|
const self = this;
|
|
1107
1077
|
if (name === "Promise") {
|
|
1108
1078
|
return Effect.flatMap(this.evaluateCallArguments(argNodes), (args) => constructPromise(self.runner, self.promises, args[0], node));
|
|
@@ -1162,49 +1132,28 @@ export class Interpreter {
|
|
|
1162
1132
|
}
|
|
1163
1133
|
constructDate(args, node) {
|
|
1164
1134
|
if (args.length === 0)
|
|
1165
|
-
return Effect.succeed(new
|
|
1135
|
+
return Effect.succeed(new Values.Date(Date.now()));
|
|
1166
1136
|
if (args.length === 1) {
|
|
1167
1137
|
const arg = args[0];
|
|
1168
|
-
if (arg instanceof
|
|
1169
|
-
return Effect.succeed(new
|
|
1170
|
-
return Effect.map(this.
|
|
1171
|
-
? new
|
|
1172
|
-
: new
|
|
1138
|
+
if (arg instanceof Values.Date)
|
|
1139
|
+
return Effect.succeed(new Values.Date(arg.time));
|
|
1140
|
+
return Effect.map(toPrimitive(this.runner, arg, "number", node), (value) => typeof value === "string"
|
|
1141
|
+
? new Values.Date(Date.parse(value))
|
|
1142
|
+
: new Values.Date(new Date(coerceToNumber(value)).getTime()));
|
|
1173
1143
|
}
|
|
1174
1144
|
const parts = args.map((arg) => coerceToNumber(arg));
|
|
1175
|
-
return Effect.succeed(new
|
|
1176
|
-
}
|
|
1177
|
-
toDatePrimitive(value, node) {
|
|
1178
|
-
if (value === null || (typeof value !== "object" && typeof value !== "function"))
|
|
1179
|
-
return Effect.succeed(value);
|
|
1180
|
-
const object = value;
|
|
1181
|
-
const self = this;
|
|
1182
|
-
return Effect.gen(function* () {
|
|
1183
|
-
if (Object.hasOwn(object, "valueOf") && typeofValue(object.valueOf) === "function") {
|
|
1184
|
-
const result = yield* self.runner.invokeCallable(object.valueOf, [], node);
|
|
1185
|
-
if (result === null || (typeof result !== "object" && typeof result !== "function"))
|
|
1186
|
-
return result;
|
|
1187
|
-
}
|
|
1188
|
-
if (!Object.hasOwn(object, "toString"))
|
|
1189
|
-
return coerceToString(value);
|
|
1190
|
-
if (typeofValue(object.toString) === "function") {
|
|
1191
|
-
const result = yield* self.runner.invokeCallable(object.toString, [], node);
|
|
1192
|
-
if (result === null || (typeof result !== "object" && typeof result !== "function"))
|
|
1193
|
-
return result;
|
|
1194
|
-
}
|
|
1195
|
-
throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node).as("TypeError");
|
|
1196
|
-
});
|
|
1145
|
+
return Effect.succeed(new Values.Date(new Date(...parts).getTime()));
|
|
1197
1146
|
}
|
|
1198
1147
|
constructRegExp(args, node) {
|
|
1199
1148
|
const first = args[0];
|
|
1200
|
-
const pattern = first instanceof
|
|
1149
|
+
const pattern = first instanceof Values.RegExp ? first.regex.source : first === undefined ? "" : coerceToString(first);
|
|
1201
1150
|
const flagsArg = args[1];
|
|
1202
1151
|
if (flagsArg !== undefined && typeof flagsArg !== "string") {
|
|
1203
1152
|
throw new InterpreterRuntimeError(`RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`, node).as("SyntaxError");
|
|
1204
1153
|
}
|
|
1205
|
-
const flags = flagsArg ?? (first instanceof
|
|
1154
|
+
const flags = flagsArg ?? (first instanceof Values.RegExp ? first.regex.flags : "");
|
|
1206
1155
|
try {
|
|
1207
|
-
return new
|
|
1156
|
+
return new Values.RegExp(pattern, flags);
|
|
1208
1157
|
}
|
|
1209
1158
|
catch (error) {
|
|
1210
1159
|
const reason = regexFailureReason(error);
|
|
@@ -1214,7 +1163,7 @@ export class Interpreter {
|
|
|
1214
1163
|
}
|
|
1215
1164
|
}
|
|
1216
1165
|
constructMap(init, node) {
|
|
1217
|
-
const target = new
|
|
1166
|
+
const target = new Values.Map();
|
|
1218
1167
|
if (init === undefined || init === null)
|
|
1219
1168
|
return Effect.succeed(target);
|
|
1220
1169
|
const self = this;
|
|
@@ -1237,7 +1186,7 @@ export class Interpreter {
|
|
|
1237
1186
|
});
|
|
1238
1187
|
}
|
|
1239
1188
|
constructSet(init, node) {
|
|
1240
|
-
const target = new
|
|
1189
|
+
const target = new Values.Set();
|
|
1241
1190
|
if (init === undefined || init === null)
|
|
1242
1191
|
return Effect.succeed(target);
|
|
1243
1192
|
const self = this;
|
|
@@ -1261,7 +1210,7 @@ export class Interpreter {
|
|
|
1261
1210
|
const input = urlArgument(args[0], "new URL input");
|
|
1262
1211
|
const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base");
|
|
1263
1212
|
try {
|
|
1264
|
-
return new
|
|
1213
|
+
return new Values.URL(new URL(input, base));
|
|
1265
1214
|
}
|
|
1266
1215
|
catch {
|
|
1267
1216
|
throw new InterpreterRuntimeError(`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, node).as("TypeError");
|
|
@@ -1269,14 +1218,14 @@ export class Interpreter {
|
|
|
1269
1218
|
}
|
|
1270
1219
|
constructURLSearchParams(init, node) {
|
|
1271
1220
|
if (init === undefined)
|
|
1272
|
-
return Effect.succeed(new
|
|
1273
|
-
if (init instanceof
|
|
1274
|
-
return Effect.succeed(new
|
|
1221
|
+
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams()));
|
|
1222
|
+
if (init instanceof Values.URLSearchParams) {
|
|
1223
|
+
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(init.params)));
|
|
1275
1224
|
}
|
|
1276
1225
|
if (typeof init === "string")
|
|
1277
|
-
return Effect.succeed(new
|
|
1226
|
+
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(init)));
|
|
1278
1227
|
if (init === null || typeof init === "number" || typeof init === "boolean") {
|
|
1279
|
-
return Effect.succeed(new
|
|
1228
|
+
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(coerceToString(init))));
|
|
1280
1229
|
}
|
|
1281
1230
|
const self = this;
|
|
1282
1231
|
return Effect.gen(function* () {
|
|
@@ -1289,7 +1238,7 @@ export class Interpreter {
|
|
|
1289
1238
|
if (entries.some((entry) => entry.length !== 2)) {
|
|
1290
1239
|
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as("TypeError");
|
|
1291
1240
|
}
|
|
1292
|
-
return new
|
|
1241
|
+
return new Values.URLSearchParams(new URLSearchParams(entries.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
|
|
1293
1242
|
}
|
|
1294
1243
|
entries.push(yield* preserveConsumerError(cursor, self.readURLSearchParamsPair(step.value, node)));
|
|
1295
1244
|
}
|
|
@@ -1297,13 +1246,13 @@ export class Interpreter {
|
|
|
1297
1246
|
if (isRuntimeReference(init)) {
|
|
1298
1247
|
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.", node).as("TypeError");
|
|
1299
1248
|
}
|
|
1300
|
-
if (
|
|
1301
|
-
return new
|
|
1302
|
-
const data =
|
|
1249
|
+
if (Values.isValue(init))
|
|
1250
|
+
return new Values.URLSearchParams(new URLSearchParams());
|
|
1251
|
+
const data = toProgram(init, "new URLSearchParams input");
|
|
1303
1252
|
if (data === null || typeof data !== "object") {
|
|
1304
1253
|
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.", node).as("TypeError");
|
|
1305
1254
|
}
|
|
1306
|
-
return new
|
|
1255
|
+
return new Values.URLSearchParams(new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))));
|
|
1307
1256
|
});
|
|
1308
1257
|
}
|
|
1309
1258
|
readURLSearchParamsPair(value, node) {
|
|
@@ -1323,14 +1272,17 @@ export class Interpreter {
|
|
|
1323
1272
|
});
|
|
1324
1273
|
}
|
|
1325
1274
|
evaluateBinaryExpression(node) {
|
|
1326
|
-
const operator =
|
|
1275
|
+
const operator = node.operator;
|
|
1276
|
+
const left = node.left;
|
|
1277
|
+
if (left.type === "PrivateIdentifier")
|
|
1278
|
+
throw unsupportedSyntax(left.type, left);
|
|
1327
1279
|
const self = this;
|
|
1328
1280
|
return Effect.gen(function* () {
|
|
1329
|
-
const lhs = yield* self.evaluateExpression(
|
|
1330
|
-
const rhs = yield* self.evaluateExpression(
|
|
1281
|
+
const lhs = yield* self.evaluateExpression(left);
|
|
1282
|
+
const rhs = yield* self.evaluateExpression(node.right);
|
|
1331
1283
|
if (operator === "instanceof")
|
|
1332
1284
|
return instanceofValue(lhs, rhs, node);
|
|
1333
|
-
return
|
|
1285
|
+
return toProgram(self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
|
|
1334
1286
|
});
|
|
1335
1287
|
}
|
|
1336
1288
|
applyBinaryOperator(operator, lhs, rhs, node) {
|
|
@@ -1344,7 +1296,7 @@ export class Interpreter {
|
|
|
1344
1296
|
// Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
|
|
1345
1297
|
// Dates use their default string hint for addition and loose equality, and epoch time elsewhere.
|
|
1346
1298
|
const coerceOperand = (operand) => {
|
|
1347
|
-
if (operand instanceof
|
|
1299
|
+
if (operand instanceof Values.Date) {
|
|
1348
1300
|
return operator === "+" || operator === "==" || operator === "!=" ? coerceToString(operand) : operand.time;
|
|
1349
1301
|
}
|
|
1350
1302
|
return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand;
|
|
@@ -1400,26 +1352,24 @@ export class Interpreter {
|
|
|
1400
1352
|
}
|
|
1401
1353
|
}
|
|
1402
1354
|
evaluateLogicalExpression(node) {
|
|
1403
|
-
const operator =
|
|
1404
|
-
return Effect.flatMap(this.evaluateExpression(
|
|
1355
|
+
const operator = node.operator;
|
|
1356
|
+
return Effect.flatMap(this.evaluateExpression(node.left), (left) => {
|
|
1405
1357
|
if (operator === "&&")
|
|
1406
|
-
return left ? this.evaluateExpression(
|
|
1358
|
+
return left ? this.evaluateExpression(node.right) : Effect.succeed(left);
|
|
1407
1359
|
if (operator === "||")
|
|
1408
|
-
return left ? Effect.succeed(left) : this.evaluateExpression(
|
|
1360
|
+
return left ? Effect.succeed(left) : this.evaluateExpression(node.right);
|
|
1409
1361
|
if (operator === "??")
|
|
1410
|
-
return left !== null && left !== undefined
|
|
1411
|
-
? Effect.succeed(left)
|
|
1412
|
-
: this.evaluateExpression(getNode(node, "right"));
|
|
1362
|
+
return left !== null && left !== undefined ? Effect.succeed(left) : this.evaluateExpression(node.right);
|
|
1413
1363
|
throw new InterpreterRuntimeError(`Unsupported logical operator '${operator}'.`, node);
|
|
1414
1364
|
});
|
|
1415
1365
|
}
|
|
1416
1366
|
evaluateUnaryExpression(node) {
|
|
1417
|
-
const operator =
|
|
1418
|
-
const argument =
|
|
1367
|
+
const operator = node.operator;
|
|
1368
|
+
const argument = node.argument;
|
|
1419
1369
|
if (operator === "delete")
|
|
1420
1370
|
return this.evaluateDeleteExpression(argument);
|
|
1421
1371
|
// Undeclared names short-circuit, but declared TDZ bindings must still throw.
|
|
1422
|
-
if (operator === "typeof" && argument.type === "Identifier" && !this.scopes.resolve(
|
|
1372
|
+
if (operator === "typeof" && argument.type === "Identifier" && !this.scopes.resolve(argument.name)) {
|
|
1423
1373
|
return Effect.succeed("undefined");
|
|
1424
1374
|
}
|
|
1425
1375
|
return Effect.map(this.evaluateExpression(argument), (value) => {
|
|
@@ -1432,7 +1382,7 @@ export class Interpreter {
|
|
|
1432
1382
|
if (containsOpaqueReference(value)) {
|
|
1433
1383
|
throw new InterpreterRuntimeError("Unary operators require data values.", node, "InvalidDataValue");
|
|
1434
1384
|
}
|
|
1435
|
-
const operand = value instanceof
|
|
1385
|
+
const operand = value instanceof Values.Date
|
|
1436
1386
|
? value.time
|
|
1437
1387
|
: value !== null && typeof value === "object"
|
|
1438
1388
|
? coerceToString(value)
|
|
@@ -1451,38 +1401,38 @@ export class Interpreter {
|
|
|
1451
1401
|
default:
|
|
1452
1402
|
throw new InterpreterRuntimeError(`Unsupported unary operator '${operator}'.`, node);
|
|
1453
1403
|
}
|
|
1454
|
-
return
|
|
1404
|
+
return toProgram(result, "Unary expression result");
|
|
1455
1405
|
});
|
|
1456
1406
|
}
|
|
1457
1407
|
evaluateAssignmentExpression(node) {
|
|
1458
|
-
const left =
|
|
1459
|
-
const operator =
|
|
1408
|
+
const left = node.left;
|
|
1409
|
+
const operator = node.operator;
|
|
1460
1410
|
const self = this;
|
|
1461
1411
|
return Effect.gen(function* () {
|
|
1462
1412
|
if (operator === "??=" || operator === "||=" || operator === "&&=") {
|
|
1463
1413
|
return yield* self.evaluateLogicalAssignment(node, left, operator);
|
|
1464
1414
|
}
|
|
1465
1415
|
if (operator === "=" && (left.type === "ObjectPattern" || left.type === "ArrayPattern")) {
|
|
1466
|
-
const rightValue = yield* self.evaluateExpression(
|
|
1416
|
+
const rightValue = yield* self.evaluateExpression(node.right);
|
|
1467
1417
|
yield* self.assignPattern(left, rightValue, node);
|
|
1468
1418
|
return rightValue;
|
|
1469
1419
|
}
|
|
1470
1420
|
if (left.type === "Identifier") {
|
|
1471
|
-
const name =
|
|
1421
|
+
const name = left.name;
|
|
1472
1422
|
if (operator !== "=") {
|
|
1473
1423
|
const current = self.scopes.get(name, left);
|
|
1474
|
-
const rightValue = yield* self.evaluateExpression(
|
|
1475
|
-
const next =
|
|
1424
|
+
const rightValue = yield* self.evaluateExpression(node.right);
|
|
1425
|
+
const next = toProgram(self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
|
|
1476
1426
|
return self.scopes.set(name, next, left);
|
|
1477
1427
|
}
|
|
1478
|
-
const rightValue = yield* self.evaluateExpression(
|
|
1428
|
+
const rightValue = yield* self.evaluateExpression(node.right);
|
|
1479
1429
|
return self.scopes.set(name, rightValue, left);
|
|
1480
1430
|
}
|
|
1481
1431
|
if (left.type === "MemberExpression") {
|
|
1482
|
-
return yield* self.modifyMember(left, (current) => Effect.map(self.evaluateExpression(
|
|
1432
|
+
return yield* self.modifyMember(left, (current) => Effect.map(self.evaluateExpression(node.right), (rightValue) => {
|
|
1483
1433
|
if (operator === "=")
|
|
1484
1434
|
return { write: true, next: rightValue, result: rightValue };
|
|
1485
|
-
const next =
|
|
1435
|
+
const next = toProgram(self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
|
|
1486
1436
|
return { write: true, next, result: next };
|
|
1487
1437
|
}));
|
|
1488
1438
|
}
|
|
@@ -1493,18 +1443,18 @@ export class Interpreter {
|
|
|
1493
1443
|
const self = this;
|
|
1494
1444
|
const shouldAssign = (current) => operator === "??=" ? current === null || current === undefined : operator === "||=" ? !current : Boolean(current);
|
|
1495
1445
|
if (left.type === "Identifier") {
|
|
1496
|
-
const name =
|
|
1446
|
+
const name = left.name;
|
|
1497
1447
|
return Effect.gen(function* () {
|
|
1498
1448
|
const current = self.scopes.get(name, left);
|
|
1499
1449
|
if (!shouldAssign(current))
|
|
1500
1450
|
return current;
|
|
1501
|
-
const rightValue = yield* self.evaluateExpression(
|
|
1451
|
+
const rightValue = yield* self.evaluateExpression(node.right);
|
|
1502
1452
|
return self.scopes.set(name, rightValue, left);
|
|
1503
1453
|
});
|
|
1504
1454
|
}
|
|
1505
1455
|
if (left.type === "MemberExpression") {
|
|
1506
1456
|
return self.modifyMember(left, (current) => shouldAssign(current)
|
|
1507
|
-
? Effect.map(self.evaluateExpression(
|
|
1457
|
+
? Effect.map(self.evaluateExpression(node.right), (rightValue) => ({
|
|
1508
1458
|
write: true,
|
|
1509
1459
|
next: rightValue,
|
|
1510
1460
|
result: rightValue,
|
|
@@ -1514,9 +1464,9 @@ export class Interpreter {
|
|
|
1514
1464
|
throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left);
|
|
1515
1465
|
}
|
|
1516
1466
|
evaluateUpdateExpression(node) {
|
|
1517
|
-
const operator =
|
|
1518
|
-
const argument =
|
|
1519
|
-
const prefix =
|
|
1467
|
+
const operator = node.operator;
|
|
1468
|
+
const argument = node.argument;
|
|
1469
|
+
const prefix = node.prefix;
|
|
1520
1470
|
const increment = operator === "++" ? 1 : operator === "--" ? -1 : undefined;
|
|
1521
1471
|
if (increment === undefined) {
|
|
1522
1472
|
throw new InterpreterRuntimeError(`Unsupported update operator '${operator}'.`, node);
|
|
@@ -1531,7 +1481,7 @@ export class Interpreter {
|
|
|
1531
1481
|
};
|
|
1532
1482
|
if (argument.type === "Identifier") {
|
|
1533
1483
|
return Effect.sync(() => {
|
|
1534
|
-
const name =
|
|
1484
|
+
const name = argument.name;
|
|
1535
1485
|
const current = operand(this.scopes.get(name, argument));
|
|
1536
1486
|
const next = current + increment;
|
|
1537
1487
|
this.scopes.set(name, next, argument);
|
|
@@ -1548,26 +1498,28 @@ export class Interpreter {
|
|
|
1548
1498
|
throw new InterpreterRuntimeError("Update target must be an Identifier or MemberExpression.", argument);
|
|
1549
1499
|
}
|
|
1550
1500
|
evaluateCallExpression(node) {
|
|
1551
|
-
const callee =
|
|
1552
|
-
const argNodes = getArray(node, "arguments");
|
|
1501
|
+
const callee = node.callee;
|
|
1553
1502
|
const self = this;
|
|
1554
1503
|
return Effect.gen(function* () {
|
|
1504
|
+
if (callee.type === "Super")
|
|
1505
|
+
throw unsupportedSyntax(callee.type, callee);
|
|
1555
1506
|
const callable = yield* self.evaluateExpression(callee);
|
|
1556
1507
|
if (callable === OptionalShortCircuit)
|
|
1557
1508
|
return OptionalShortCircuit;
|
|
1558
|
-
if ((callable === null || callable === undefined) && node.optional
|
|
1509
|
+
if ((callable === null || callable === undefined) && node.optional)
|
|
1559
1510
|
return OptionalShortCircuit;
|
|
1560
|
-
const args = yield* self.evaluateCallArguments(
|
|
1511
|
+
const args = yield* self.evaluateCallArguments(node.arguments);
|
|
1561
1512
|
return yield* self.invokeCallable(callable, args, node, callee);
|
|
1562
1513
|
});
|
|
1563
1514
|
}
|
|
1564
1515
|
// The single dispatch for every invocation: call expressions and callbacks share it.
|
|
1565
|
-
invokeCallable(callable, args, node, callee
|
|
1516
|
+
invokeCallable(callable, args, node, callee) {
|
|
1566
1517
|
const self = this;
|
|
1567
1518
|
return Effect.gen(function* () {
|
|
1568
1519
|
if (callable instanceof ToolReference) {
|
|
1569
|
-
if (callable.path.length === 0)
|
|
1570
|
-
throw new InterpreterRuntimeError("The tools root is not callable.", callee);
|
|
1520
|
+
if (callable.path.length === 0) {
|
|
1521
|
+
throw new InterpreterRuntimeError("The tools root is not callable.", callee ?? node);
|
|
1522
|
+
}
|
|
1571
1523
|
return yield* self.createToolCallPromise(callable.path, args);
|
|
1572
1524
|
}
|
|
1573
1525
|
if (callable instanceof PromiseMethodReference) {
|
|
@@ -1611,13 +1563,13 @@ export class Interpreter {
|
|
|
1611
1563
|
if (callable.namespace === "Array" && callable.name === "of") {
|
|
1612
1564
|
return invokeGlobalMethod(callable, args, node);
|
|
1613
1565
|
}
|
|
1614
|
-
return
|
|
1566
|
+
return toProgram(invokeGlobalMethod(callable, args, node), `${callable.namespace}.${callable.name} result`);
|
|
1615
1567
|
}
|
|
1616
1568
|
if (callable instanceof JsonMethodReference) {
|
|
1617
1569
|
return yield* invokeJsonMethod(self.runner, callable.name, args, node);
|
|
1618
1570
|
}
|
|
1619
1571
|
if (callable instanceof CoercionFunction) {
|
|
1620
|
-
return
|
|
1572
|
+
return toProgram(invokeCoercion(callable, args, node), `${callable.name} result`);
|
|
1621
1573
|
}
|
|
1622
1574
|
if (callable instanceof UriFunction) {
|
|
1623
1575
|
return invokeUriFunction(callable, args, node);
|
|
@@ -1658,14 +1610,14 @@ export class Interpreter {
|
|
|
1658
1610
|
return undefined;
|
|
1659
1611
|
}
|
|
1660
1612
|
if (callable === undefined || callable === null) {
|
|
1661
|
-
throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee).as("TypeError");
|
|
1613
|
+
throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node).as("TypeError");
|
|
1662
1614
|
}
|
|
1663
|
-
throw new InterpreterRuntimeError("Only tools are callable here.", callee);
|
|
1615
|
+
throw new InterpreterRuntimeError("Only tools are callable here.", callee ?? node);
|
|
1664
1616
|
});
|
|
1665
1617
|
}
|
|
1666
1618
|
invokeObjectMethodOnTools(name, ref, node) {
|
|
1667
1619
|
if (name === "keys") {
|
|
1668
|
-
return
|
|
1620
|
+
return toProgram(this.enumerableKeys(ref), "Object.keys result");
|
|
1669
1621
|
}
|
|
1670
1622
|
throw new InterpreterRuntimeError(`Object.${name}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or search({ query }) for signatures.`, node, "InvalidDataValue");
|
|
1671
1623
|
}
|
|
@@ -1679,10 +1631,9 @@ export class Interpreter {
|
|
|
1679
1631
|
const self = this;
|
|
1680
1632
|
return Effect.gen(function* () {
|
|
1681
1633
|
const args = [];
|
|
1682
|
-
for (const
|
|
1683
|
-
const argNode = asNode(arg, `arguments[${index}]`);
|
|
1634
|
+
for (const argNode of argNodes) {
|
|
1684
1635
|
if (argNode.type === "SpreadElement") {
|
|
1685
|
-
const spread = yield* self.evaluateExpression(
|
|
1636
|
+
const spread = yield* self.evaluateExpression(argNode.argument);
|
|
1686
1637
|
const cursor = yield* self.syncIterator(spread, argNode);
|
|
1687
1638
|
if (cursor === undefined)
|
|
1688
1639
|
throw new InterpreterRuntimeError("Spread arguments require a synchronous iterable.", argNode).as("TypeError");
|
|
@@ -1713,7 +1664,7 @@ export class Interpreter {
|
|
|
1713
1664
|
}
|
|
1714
1665
|
for (const [index, parameter] of fn.parameters.entries()) {
|
|
1715
1666
|
if (parameter.type === "RestElement") {
|
|
1716
|
-
yield* invocation.declarePattern(
|
|
1667
|
+
yield* invocation.declarePattern(parameter.argument, args.slice(index), true, parameter, true);
|
|
1717
1668
|
break;
|
|
1718
1669
|
}
|
|
1719
1670
|
yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
|
|
@@ -1834,12 +1785,12 @@ export class Interpreter {
|
|
|
1834
1785
|
return request;
|
|
1835
1786
|
}
|
|
1836
1787
|
evaluateYieldExpression(node) {
|
|
1837
|
-
const argument =
|
|
1788
|
+
const argument = node.argument;
|
|
1838
1789
|
const self = this;
|
|
1839
1790
|
return Effect.gen(function* () {
|
|
1840
1791
|
if (!self.generatorState)
|
|
1841
1792
|
throw new InterpreterRuntimeError("yield is only valid inside a generator.", node);
|
|
1842
|
-
if (node.delegate
|
|
1793
|
+
if (node.delegate) {
|
|
1843
1794
|
const value = argument ? yield* self.evaluateExpression(argument) : undefined;
|
|
1844
1795
|
return yield* self.delegateYield(value, node);
|
|
1845
1796
|
}
|
|
@@ -1870,9 +1821,9 @@ export class Interpreter {
|
|
|
1870
1821
|
return Effect.gen(function* () {
|
|
1871
1822
|
if (Array.isArray(value) ||
|
|
1872
1823
|
typeof value === "string" ||
|
|
1873
|
-
value instanceof
|
|
1874
|
-
value instanceof
|
|
1875
|
-
value instanceof
|
|
1824
|
+
value instanceof Values.Map ||
|
|
1825
|
+
value instanceof Values.Set ||
|
|
1826
|
+
value instanceof Values.URLSearchParams) {
|
|
1876
1827
|
const cursor = yield* self.syncIterator(value, node);
|
|
1877
1828
|
if (!cursor)
|
|
1878
1829
|
throw new InterpreterRuntimeError("Built-in iterator is unavailable.", node);
|
|
@@ -1940,14 +1891,12 @@ export class Interpreter {
|
|
|
1940
1891
|
}
|
|
1941
1892
|
evaluateObjectExpression(node) {
|
|
1942
1893
|
const objectValue = Object.create(null);
|
|
1943
|
-
const properties = getArray(node, "properties");
|
|
1944
1894
|
const self = this;
|
|
1945
1895
|
return Effect.gen(function* () {
|
|
1946
|
-
for (const
|
|
1947
|
-
const property = asNode(propertyValue, "properties");
|
|
1896
|
+
for (const property of node.properties) {
|
|
1948
1897
|
if (property.type === "SpreadElement") {
|
|
1949
|
-
const spread = yield* self.evaluateExpression(
|
|
1950
|
-
if (spread === null || spread === undefined ||
|
|
1898
|
+
const spread = yield* self.evaluateExpression(property.argument);
|
|
1899
|
+
if (spread === null || spread === undefined || Values.isValue(spread))
|
|
1951
1900
|
continue;
|
|
1952
1901
|
if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) {
|
|
1953
1902
|
throw new InterpreterRuntimeError("Object spread requires a data object.", property, "InvalidDataValue");
|
|
@@ -1960,21 +1909,16 @@ export class Interpreter {
|
|
|
1960
1909
|
copyIteratorSymbols(spread, objectValue);
|
|
1961
1910
|
continue;
|
|
1962
1911
|
}
|
|
1963
|
-
if (property.
|
|
1964
|
-
throw new InterpreterRuntimeError("Only standard object properties are supported.", property);
|
|
1965
|
-
}
|
|
1966
|
-
if (getString(property, "kind") !== "init") {
|
|
1912
|
+
if (property.kind !== "init") {
|
|
1967
1913
|
throw new InterpreterRuntimeError("Only init object properties are supported.", property);
|
|
1968
1914
|
}
|
|
1969
|
-
const keyNode =
|
|
1970
|
-
const valueNode = getNode(property, "value");
|
|
1971
|
-
const computed = getBoolean(property, "computed");
|
|
1915
|
+
const keyNode = property.key;
|
|
1972
1916
|
let key;
|
|
1973
|
-
if (computed) {
|
|
1917
|
+
if (property.computed) {
|
|
1974
1918
|
key = self.toPropertyKey(yield* self.evaluateExpression(keyNode), keyNode);
|
|
1975
1919
|
}
|
|
1976
1920
|
else if (keyNode.type === "Identifier") {
|
|
1977
|
-
key =
|
|
1921
|
+
key = keyNode.name;
|
|
1978
1922
|
}
|
|
1979
1923
|
else if (keyNode.type === "Literal") {
|
|
1980
1924
|
key = self.toPropertyKey(keyNode.value, keyNode);
|
|
@@ -1985,25 +1929,23 @@ export class Interpreter {
|
|
|
1985
1929
|
if (isBlockedMember(String(key))) {
|
|
1986
1930
|
throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, keyNode);
|
|
1987
1931
|
}
|
|
1988
|
-
Reflect.set(objectValue, key, yield* self.evaluateExpression(
|
|
1932
|
+
Reflect.set(objectValue, key, yield* self.evaluateExpression(property.value));
|
|
1989
1933
|
}
|
|
1990
1934
|
return objectValue;
|
|
1991
1935
|
});
|
|
1992
1936
|
}
|
|
1993
1937
|
evaluateArrayExpression(node) {
|
|
1994
|
-
const elements = getArray(node, "elements");
|
|
1995
1938
|
const values = [];
|
|
1996
1939
|
const self = this;
|
|
1997
1940
|
return Effect.gen(function* () {
|
|
1998
|
-
for (const
|
|
1999
|
-
if (
|
|
1941
|
+
for (const element of node.elements) {
|
|
1942
|
+
if (element === null) {
|
|
2000
1943
|
// A literal elision is a real hole, like JS: extend length without an own index.
|
|
2001
1944
|
values.length += 1;
|
|
2002
1945
|
continue;
|
|
2003
1946
|
}
|
|
2004
|
-
const element = asNode(elementValue, "elements");
|
|
2005
1947
|
if (element.type === "SpreadElement") {
|
|
2006
|
-
const spread = yield* self.evaluateExpression(
|
|
1948
|
+
const spread = yield* self.evaluateExpression(element.argument);
|
|
2007
1949
|
const cursor = yield* self.syncIterator(spread, element);
|
|
2008
1950
|
if (cursor === undefined)
|
|
2009
1951
|
throw new InterpreterRuntimeError("Array spread requires a synchronous iterable.", element).as("TypeError");
|
|
@@ -2022,28 +1964,28 @@ export class Interpreter {
|
|
|
2022
1964
|
});
|
|
2023
1965
|
}
|
|
2024
1966
|
evaluateTemplateLiteral(node) {
|
|
2025
|
-
const quasis =
|
|
2026
|
-
const expressions =
|
|
1967
|
+
const quasis = node.quasis;
|
|
1968
|
+
const expressions = node.expressions;
|
|
2027
1969
|
let output = "";
|
|
2028
1970
|
const self = this;
|
|
2029
1971
|
return Effect.gen(function* () {
|
|
2030
1972
|
for (let index = 0; index < quasis.length; index += 1) {
|
|
2031
|
-
const quasi =
|
|
2032
|
-
|
|
2033
|
-
if (
|
|
1973
|
+
const quasi = quasis[index];
|
|
1974
|
+
// acorn only omits `cooked` for invalid escapes in tagged templates, which are unsupported.
|
|
1975
|
+
if (typeof quasi.value.cooked !== "string") {
|
|
2034
1976
|
throw new InterpreterRuntimeError("Invalid template literal quasi.", quasi);
|
|
2035
1977
|
}
|
|
2036
|
-
output +=
|
|
1978
|
+
output += quasi.value.cooked;
|
|
2037
1979
|
if (index < expressions.length) {
|
|
2038
|
-
const raw = yield* self.evaluateExpression(
|
|
2039
|
-
output += coerceToString(
|
|
1980
|
+
const raw = yield* self.evaluateExpression(expressions[index]);
|
|
1981
|
+
output += coerceToString(toProgram(raw, "Template interpolation"));
|
|
2040
1982
|
}
|
|
2041
1983
|
}
|
|
2042
1984
|
return output;
|
|
2043
1985
|
});
|
|
2044
1986
|
}
|
|
2045
1987
|
evaluateConditionalExpression(node) {
|
|
2046
|
-
return Effect.flatMap(this.evaluateExpression(
|
|
1988
|
+
return Effect.flatMap(this.evaluateExpression(node.test), (test) => this.evaluateExpression(test ? node.consequent : node.alternate));
|
|
2047
1989
|
}
|
|
2048
1990
|
applyCompoundAssignment(operator, current, incoming, node) {
|
|
2049
1991
|
if (!compoundOperators.has(operator)) {
|
|
@@ -2052,21 +1994,23 @@ export class Interpreter {
|
|
|
2052
1994
|
return this.applyBinaryOperator(operator.slice(0, -1), current, incoming, node);
|
|
2053
1995
|
}
|
|
2054
1996
|
getMemberReference(node, operation = "read") {
|
|
2055
|
-
const objectNode =
|
|
2056
|
-
const propertyNode =
|
|
2057
|
-
|
|
2058
|
-
|
|
1997
|
+
const objectNode = node.object;
|
|
1998
|
+
const propertyNode = node.property;
|
|
1999
|
+
if (objectNode.type === "Super")
|
|
2000
|
+
throw unsupportedSyntax(objectNode.type, objectNode);
|
|
2001
|
+
if (propertyNode.type === "PrivateIdentifier")
|
|
2002
|
+
throw unsupportedSyntax(propertyNode.type, propertyNode);
|
|
2059
2003
|
const self = this;
|
|
2060
2004
|
return Effect.gen(function* () {
|
|
2061
2005
|
const objectValue = yield* self.evaluateExpression(objectNode);
|
|
2062
2006
|
if (objectValue === OptionalShortCircuit)
|
|
2063
2007
|
return OptionalShortCircuit;
|
|
2064
|
-
if ((objectValue === null || objectValue === undefined) && optional)
|
|
2008
|
+
if ((objectValue === null || objectValue === undefined) && node.optional)
|
|
2065
2009
|
return OptionalShortCircuit;
|
|
2066
|
-
const key = computed
|
|
2010
|
+
const key = node.computed
|
|
2067
2011
|
? self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode)
|
|
2068
2012
|
: propertyNode.type === "Identifier"
|
|
2069
|
-
?
|
|
2013
|
+
? propertyNode.name
|
|
2070
2014
|
: self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode);
|
|
2071
2015
|
if (objectValue instanceof ToolReference) {
|
|
2072
2016
|
if (typeof key !== "string") {
|
|
@@ -2139,12 +2083,12 @@ export class Interpreter {
|
|
|
2139
2083
|
}
|
|
2140
2084
|
return new ComputedValue(undefined);
|
|
2141
2085
|
}
|
|
2142
|
-
if (objectValue instanceof
|
|
2086
|
+
if (objectValue instanceof Values.Date) {
|
|
2143
2087
|
if (typeof key === "string" && dateMethods.has(key))
|
|
2144
2088
|
return new IntrinsicReference(objectValue, key);
|
|
2145
2089
|
return new ComputedValue(undefined);
|
|
2146
2090
|
}
|
|
2147
|
-
if (objectValue instanceof
|
|
2091
|
+
if (objectValue instanceof Values.RegExp) {
|
|
2148
2092
|
if (key === "lastIndex")
|
|
2149
2093
|
return { target: objectValue, key };
|
|
2150
2094
|
if (typeof key === "string" && regexpProperties.has(key)) {
|
|
@@ -2154,21 +2098,21 @@ export class Interpreter {
|
|
|
2154
2098
|
return new IntrinsicReference(objectValue, key);
|
|
2155
2099
|
return new ComputedValue(undefined);
|
|
2156
2100
|
}
|
|
2157
|
-
if (objectValue instanceof
|
|
2101
|
+
if (objectValue instanceof Values.Map) {
|
|
2158
2102
|
if (key === "size")
|
|
2159
2103
|
return new ComputedValue(objectValue.map.size);
|
|
2160
2104
|
if (typeof key === "string" && mapMethods.has(key))
|
|
2161
2105
|
return new IntrinsicReference(objectValue, key);
|
|
2162
2106
|
return new ComputedValue(undefined);
|
|
2163
2107
|
}
|
|
2164
|
-
if (objectValue instanceof
|
|
2108
|
+
if (objectValue instanceof Values.Set) {
|
|
2165
2109
|
if (key === "size")
|
|
2166
2110
|
return new ComputedValue(objectValue.set.size);
|
|
2167
2111
|
if (typeof key === "string" && setMethods.has(key))
|
|
2168
2112
|
return new IntrinsicReference(objectValue, key);
|
|
2169
2113
|
return new ComputedValue(undefined);
|
|
2170
2114
|
}
|
|
2171
|
-
if (objectValue instanceof
|
|
2115
|
+
if (objectValue instanceof Values.URL) {
|
|
2172
2116
|
if (key === "searchParams") {
|
|
2173
2117
|
return new ComputedValue(objectValue.searchParams);
|
|
2174
2118
|
}
|
|
@@ -2178,7 +2122,7 @@ export class Interpreter {
|
|
|
2178
2122
|
return { target: objectValue, key };
|
|
2179
2123
|
return new ComputedValue(undefined);
|
|
2180
2124
|
}
|
|
2181
|
-
if (objectValue instanceof
|
|
2125
|
+
if (objectValue instanceof Values.URLSearchParams) {
|
|
2182
2126
|
if (key === "size")
|
|
2183
2127
|
return new ComputedValue(objectValue.params.size);
|
|
2184
2128
|
if (typeof key === "string" && urlSearchParamsMethods.has(key)) {
|
|
@@ -2187,7 +2131,7 @@ export class Interpreter {
|
|
|
2187
2131
|
return new ComputedValue(undefined);
|
|
2188
2132
|
}
|
|
2189
2133
|
// Reject unknown promise properties so a missing await cannot hide.
|
|
2190
|
-
if (objectValue instanceof
|
|
2134
|
+
if (objectValue instanceof Values.Promise) {
|
|
2191
2135
|
if (key === "then" || key === "catch" || key === "finally") {
|
|
2192
2136
|
return new PromiseInstanceMethodReference(objectValue, key);
|
|
2193
2137
|
}
|
|
@@ -2242,9 +2186,9 @@ export class Interpreter {
|
|
|
2242
2186
|
return new IntrinsicReference(reference.target, reference.key);
|
|
2243
2187
|
return Reflect.get(reference.target, reference.key);
|
|
2244
2188
|
}
|
|
2245
|
-
if (reference.target instanceof
|
|
2189
|
+
if (reference.target instanceof Values.RegExp)
|
|
2246
2190
|
return reference.target.lastIndex;
|
|
2247
|
-
if (reference.target instanceof
|
|
2191
|
+
if (reference.target instanceof Values.URL) {
|
|
2248
2192
|
return Reflect.get(reference.target.url, reference.key);
|
|
2249
2193
|
}
|
|
2250
2194
|
return Reflect.get(reference.target, reference.key);
|
|
@@ -2254,7 +2198,7 @@ export class Interpreter {
|
|
|
2254
2198
|
return this.modifyMember(node, () => Effect.succeed({ write: true, next: value, result: value }));
|
|
2255
2199
|
}
|
|
2256
2200
|
evaluateDeleteExpression(argument) {
|
|
2257
|
-
const target = argument.type === "ChainExpression" ?
|
|
2201
|
+
const target = argument.type === "ChainExpression" ? argument.expression : argument;
|
|
2258
2202
|
if (target.type !== "MemberExpression") {
|
|
2259
2203
|
throw new InterpreterRuntimeError("Only data fields may be deleted.", argument);
|
|
2260
2204
|
}
|
|
@@ -2264,10 +2208,10 @@ export class Interpreter {
|
|
|
2264
2208
|
if (reference instanceof ComputedValue ||
|
|
2265
2209
|
reference === undefined ||
|
|
2266
2210
|
isOpaqueMemberReference(reference) ||
|
|
2267
|
-
reference.target instanceof
|
|
2211
|
+
reference.target instanceof Values.URL) {
|
|
2268
2212
|
throw new InterpreterRuntimeError("Only data fields may be deleted.", target, "InvalidDataValue");
|
|
2269
2213
|
}
|
|
2270
|
-
if (reference.target instanceof
|
|
2214
|
+
if (reference.target instanceof Values.RegExp) {
|
|
2271
2215
|
return Reflect.deleteProperty(reference.target.regex, reference.key);
|
|
2272
2216
|
}
|
|
2273
2217
|
return Reflect.deleteProperty(reference.target, reference.key);
|
|
@@ -2299,10 +2243,10 @@ export class Interpreter {
|
|
|
2299
2243
|
});
|
|
2300
2244
|
}
|
|
2301
2245
|
readReferenceValue(reference, key) {
|
|
2302
|
-
if (reference.target instanceof
|
|
2246
|
+
if (reference.target instanceof Values.URL) {
|
|
2303
2247
|
return Reflect.get(reference.target.url, key);
|
|
2304
2248
|
}
|
|
2305
|
-
if (reference.target instanceof
|
|
2249
|
+
if (reference.target instanceof Values.RegExp)
|
|
2306
2250
|
return reference.target.lastIndex;
|
|
2307
2251
|
return Reflect.get(reference.target, key);
|
|
2308
2252
|
}
|
|
@@ -2316,7 +2260,7 @@ export class Interpreter {
|
|
|
2316
2260
|
target[key] = next;
|
|
2317
2261
|
return;
|
|
2318
2262
|
}
|
|
2319
|
-
if (reference.target instanceof
|
|
2263
|
+
if (reference.target instanceof Values.URL) {
|
|
2320
2264
|
const property = key;
|
|
2321
2265
|
if (!urlWritableProperties.has(property)) {
|
|
2322
2266
|
throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError");
|
|
@@ -2332,7 +2276,7 @@ export class Interpreter {
|
|
|
2332
2276
|
throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError");
|
|
2333
2277
|
}
|
|
2334
2278
|
}
|
|
2335
|
-
if (reference.target instanceof
|
|
2279
|
+
if (reference.target instanceof Values.RegExp) {
|
|
2336
2280
|
reference.target.lastIndex = next;
|
|
2337
2281
|
return;
|
|
2338
2282
|
}
|