@opencode/codemode 0.0.0-dev-19484 → 0.0.0-dev-19485
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/data.d.ts +4 -6
- package/dist/data.js +41 -18
- package/dist/interpreter/errors.js +3 -4
- package/dist/interpreter/methods.js +53 -55
- package/dist/interpreter/model.d.ts +2 -2
- package/dist/interpreter/objects.d.ts +25 -0
- package/dist/interpreter/objects.js +122 -0
- package/dist/interpreter/promises.js +7 -9
- package/dist/interpreter/references.d.ts +0 -1
- package/dist/interpreter/references.js +7 -17
- package/dist/interpreter/runner.js +7 -4
- package/dist/interpreter/runtime.js +71 -120
- package/dist/stdlib/array.js +12 -14
- package/dist/stdlib/collections.js +10 -9
- package/dist/stdlib/console.js +16 -14
- package/dist/stdlib/json.js +21 -36
- package/dist/stdlib/object.d.ts +2 -1
- package/dist/stdlib/object.js +21 -42
- package/dist/stdlib/regexp.d.ts +2 -1
- package/dist/stdlib/regexp.js +14 -20
- package/dist/stdlib/url.js +3 -3
- package/dist/stdlib/value.d.ts +3 -3
- package/dist/stdlib/value.js +25 -26
- package/dist/tool-runtime.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Cause, Deferred, Effect, Exit, Fiber, Scope } from "effect";
|
|
2
2
|
import { CodeModeFunction, InterpreterRuntimeError, ProgramThrow, PromiseInstanceMethodReference, } from "./model.js";
|
|
3
|
+
import { get, ProgramArray, ProgramObject, record } from "./objects.js";
|
|
3
4
|
import { HostFunction, requiresNew, sync } from "./host.js";
|
|
4
5
|
import { caughtErrorValue, normalizeError } from "./errors.js";
|
|
5
6
|
import { typeofValue } from "./references.js";
|
|
@@ -88,9 +89,9 @@ export const resolvePromiseValue = (runner, value, node, own) => {
|
|
|
88
89
|
return Effect.fail(selfResolutionError(node));
|
|
89
90
|
if (value instanceof Values.Promise)
|
|
90
91
|
return runner.settlePromise(value);
|
|
91
|
-
if (
|
|
92
|
+
if (!(value instanceof ProgramObject))
|
|
92
93
|
return Effect.succeed(value);
|
|
93
|
-
const then = value
|
|
94
|
+
const then = get(value, "then");
|
|
94
95
|
if (typeofValue(then) !== "function")
|
|
95
96
|
return Effect.succeed(value);
|
|
96
97
|
return Effect.gen(function* () {
|
|
@@ -136,25 +137,22 @@ const invokePromiseMethod = (runner, promises, name, args, node) => {
|
|
|
136
137
|
items.push(item);
|
|
137
138
|
}
|
|
138
139
|
if (name === "all") {
|
|
139
|
-
return yield* settleAfterTurn(Effect.all(items.map((item) => Effect.flatten(promises.await(item))), { concurrency: "unbounded" }));
|
|
140
|
+
return new ProgramArray(yield* settleAfterTurn(Effect.all(items.map((item) => Effect.flatten(promises.await(item))), { concurrency: "unbounded" })));
|
|
140
141
|
}
|
|
141
142
|
if (name === "allSettled") {
|
|
142
143
|
const outcomes = [];
|
|
143
144
|
for (const item of items) {
|
|
144
145
|
const exit = yield* promises.await(item);
|
|
145
146
|
if (Exit.isSuccess(exit)) {
|
|
146
|
-
outcomes.push(
|
|
147
|
+
outcomes.push(record({ status: "fulfilled", value: exit.value }));
|
|
147
148
|
continue;
|
|
148
149
|
}
|
|
149
150
|
if (Cause.hasInterruptsOnly(exit.cause))
|
|
150
151
|
return yield* Effect.failCause(exit.cause);
|
|
151
|
-
outcomes.push(
|
|
152
|
-
status: "rejected",
|
|
153
|
-
reason: caughtErrorValue(Cause.squash(exit.cause)),
|
|
154
|
-
}));
|
|
152
|
+
outcomes.push(record({ status: "rejected", reason: caughtErrorValue(Cause.squash(exit.cause)) }));
|
|
155
153
|
}
|
|
156
154
|
yield* Effect.yieldNow;
|
|
157
|
-
return outcomes;
|
|
155
|
+
return new ProgramArray(outcomes);
|
|
158
156
|
}
|
|
159
157
|
if (name === "race") {
|
|
160
158
|
if (items.length === 0) {
|
|
@@ -5,4 +5,3 @@ export declare const containsOpaqueReference: (value: unknown) => boolean;
|
|
|
5
5
|
export declare const rejectCircularInsertion: (container: object, value: unknown, label: string, node: AstNode, seen?: Set<object>) => void;
|
|
6
6
|
export declare const describeValue: (value: unknown) => string;
|
|
7
7
|
export declare const typeofValue: (value: unknown) => string;
|
|
8
|
-
export declare const parseArrayIndex: (key: string | number) => number | undefined;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ToolReference } from "../tool-runtime.js";
|
|
2
2
|
import { Values } from "../values.js";
|
|
3
3
|
import { HostFunction, HostNamespace } from "./host.js";
|
|
4
|
-
import {
|
|
4
|
+
import { CodeModeFunction, CodeModeGenerator, GeneratorMethodReference, InterpreterRuntimeError, IntrinsicReference, PromiseInstanceMethodReference, } from "./model.js";
|
|
5
|
+
import { getOwn, ownKeys, ProgramArray, ProgramObject } from "./objects.js";
|
|
5
6
|
export const isRuntimeReference = (value) => value instanceof HostFunction ||
|
|
6
7
|
value instanceof HostNamespace ||
|
|
7
8
|
value instanceof CodeModeFunction ||
|
|
@@ -13,13 +14,10 @@ export const isRuntimeReference = (value) => value instanceof HostFunction ||
|
|
|
13
14
|
value instanceof Values.Promise ||
|
|
14
15
|
Values.isValue(value);
|
|
15
16
|
function* childValues(value) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
continue;
|
|
21
|
-
yield Reflect.get(value, key);
|
|
22
|
-
}
|
|
17
|
+
if (!(value instanceof ProgramObject))
|
|
18
|
+
return;
|
|
19
|
+
for (const key of ownKeys(value))
|
|
20
|
+
yield getOwn(value, key);
|
|
23
21
|
}
|
|
24
22
|
// Depth-first search over a value tree. `match` stops the walk; `skip` prunes a subtree without matching it.
|
|
25
23
|
const find = (value, match, skip, seen) => {
|
|
@@ -53,7 +51,7 @@ export const rejectCircularInsertion = (container, value, label, node, seen = ne
|
|
|
53
51
|
export const describeValue = (value) => {
|
|
54
52
|
if (value === null)
|
|
55
53
|
return "null";
|
|
56
|
-
if (
|
|
54
|
+
if (value instanceof ProgramArray)
|
|
57
55
|
return "an array";
|
|
58
56
|
if (value instanceof Values.Promise)
|
|
59
57
|
return "an un-awaited Promise";
|
|
@@ -93,11 +91,3 @@ export const typeofValue = (value) => {
|
|
|
93
91
|
return value.path.length > 0 ? "function" : "object";
|
|
94
92
|
return typeof value;
|
|
95
93
|
};
|
|
96
|
-
const MAX_ARRAY_LENGTH = 4_294_967_295;
|
|
97
|
-
export const parseArrayIndex = (key) => {
|
|
98
|
-
const property = String(key);
|
|
99
|
-
if (!/^(0|[1-9]\d*)$/.test(property))
|
|
100
|
-
return undefined;
|
|
101
|
-
const index = Number(property);
|
|
102
|
-
return index < MAX_ARRAY_LENGTH ? index : undefined;
|
|
103
|
-
};
|
|
@@ -3,6 +3,7 @@ import { Values } from "../values.js";
|
|
|
3
3
|
import { coerceToString } from "../stdlib/value.js";
|
|
4
4
|
import { HostFunction } from "./host.js";
|
|
5
5
|
import { CodeModeFunction, InterpreterRuntimeError, IntrinsicReference } from "./model.js";
|
|
6
|
+
import { get, has, ProgramObject } from "./objects.js";
|
|
6
7
|
import { typeofValue } from "./references.js";
|
|
7
8
|
export const preserveConsumerError = (cursor, effect) => Effect.flatMap(Effect.exit(effect), (exit) => Exit.isSuccess(exit)
|
|
8
9
|
? Effect.succeed(exit.value)
|
|
@@ -13,15 +14,17 @@ export const toPrimitive = (runner, value, hint, node) => {
|
|
|
13
14
|
if (Values.isValue(value)) {
|
|
14
15
|
return Effect.succeed(value instanceof Values.Date && hint === "number" ? value.time : coerceToString(value));
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
if (!(value instanceof ProgramObject))
|
|
18
|
+
return Effect.succeed(value);
|
|
17
19
|
const order = hint === "number" ? ["valueOf", "toString"] : ["toString", "valueOf"];
|
|
18
20
|
return Effect.gen(function* () {
|
|
19
21
|
for (const method of order) {
|
|
20
|
-
if (method === "toString" && !
|
|
22
|
+
if (method === "toString" && !has(value, "toString"))
|
|
21
23
|
return coerceToString(value);
|
|
22
|
-
|
|
24
|
+
const callable = get(value, method);
|
|
25
|
+
if (typeofValue(callable) !== "function")
|
|
23
26
|
continue;
|
|
24
|
-
const result = yield* runner.invokeCallable(
|
|
27
|
+
const result = yield* runner.invokeCallable(callable, [], node);
|
|
25
28
|
if (result === null || (typeof result !== "object" && typeof result !== "function"))
|
|
26
29
|
return result;
|
|
27
30
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Cause, Deferred, Effect, Exit } from "effect";
|
|
2
2
|
import { ToolRuntimeError, toProgram } from "../data.js";
|
|
3
3
|
import { ToolReference } from "../tool-runtime.js";
|
|
4
|
-
import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, ComputedValue, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError,
|
|
4
|
+
import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, ComputedValue, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError, IteratorSymbol, OptionalShortCircuit, PromiseInstanceMethodReference, ProgramThrow, unsupportedSyntax, } from "./model.js";
|
|
5
5
|
import { caughtErrorValue } from "./errors.js";
|
|
6
6
|
import { globals } from "./globals.js";
|
|
7
7
|
import { HostFunction, HostNamespace } from "./host.js";
|
|
8
8
|
import { invokeIntrinsic } from "./methods.js";
|
|
9
|
+
import { assign, get, has, ownKeys, parseArrayIndex, ProgramArray, ProgramObject, record, remove, set, } from "./objects.js";
|
|
9
10
|
import { preserveConsumerError } from "./runner.js";
|
|
10
11
|
import { invokePromiseInstanceMethod, PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
|
|
11
|
-
import { containsOpaqueReference, describeValue, isRuntimeReference,
|
|
12
|
+
import { containsOpaqueReference, describeValue, isRuntimeReference, rejectCircularInsertion, typeofValue, } from "./references.js";
|
|
12
13
|
import { ScopeStack } from "./scope.js";
|
|
13
14
|
import { arrayMethods, mapMethods, setMethods } from "../stdlib/collections.js";
|
|
14
15
|
import { dateMethods } from "../stdlib/date.js";
|
|
@@ -49,7 +50,6 @@ const calleeDescription = (callee) => {
|
|
|
49
50
|
}
|
|
50
51
|
return "The called value";
|
|
51
52
|
};
|
|
52
|
-
const hasOwn = (value, key) => value !== null && typeof value === "object" && Object.hasOwn(value, key);
|
|
53
53
|
const constructorName = (value) => {
|
|
54
54
|
if (typeof value === "string")
|
|
55
55
|
return "String";
|
|
@@ -57,7 +57,7 @@ const constructorName = (value) => {
|
|
|
57
57
|
return "Number";
|
|
58
58
|
if (typeof value === "boolean")
|
|
59
59
|
return "Boolean";
|
|
60
|
-
if (
|
|
60
|
+
if (value instanceof ProgramArray)
|
|
61
61
|
return "Array";
|
|
62
62
|
if (value instanceof Values.Date)
|
|
63
63
|
return "Date";
|
|
@@ -73,7 +73,7 @@ const constructorName = (value) => {
|
|
|
73
73
|
return "URLSearchParams";
|
|
74
74
|
if (value instanceof Values.Promise)
|
|
75
75
|
return "Promise";
|
|
76
|
-
if (value
|
|
76
|
+
if (!(value instanceof ProgramObject))
|
|
77
77
|
return undefined;
|
|
78
78
|
return errorBrandName(value) ?? "Object";
|
|
79
79
|
};
|
|
@@ -174,12 +174,6 @@ const isOpaqueMemberReference = (value) => value instanceof ToolReference ||
|
|
|
174
174
|
value instanceof PromiseInstanceMethodReference ||
|
|
175
175
|
value instanceof IntrinsicReference ||
|
|
176
176
|
value instanceof GeneratorMethodReference;
|
|
177
|
-
const copyIteratorSymbols = (source, target, consumed) => {
|
|
178
|
-
for (const symbol of IteratorSymbols) {
|
|
179
|
-
if (!consumed?.has(symbol) && Object.hasOwn(source, symbol))
|
|
180
|
-
Reflect.set(target, symbol, Reflect.get(source, symbol));
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
177
|
const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
|
|
184
178
|
/** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
|
|
185
179
|
export class Runtime {
|
|
@@ -574,8 +568,8 @@ class Frame {
|
|
|
574
568
|
});
|
|
575
569
|
}
|
|
576
570
|
syncIterator(value, node) {
|
|
577
|
-
const iterator =
|
|
578
|
-
? value[Symbol.iterator]()
|
|
571
|
+
const iterator = value instanceof ProgramArray
|
|
572
|
+
? value.items[Symbol.iterator]()
|
|
579
573
|
: typeof value === "string"
|
|
580
574
|
? value[Symbol.iterator]()
|
|
581
575
|
: value instanceof Values.Map
|
|
@@ -589,7 +583,10 @@ class Frame {
|
|
|
589
583
|
return Effect.succeed({
|
|
590
584
|
next: Effect.sync(() => {
|
|
591
585
|
const step = iterator.next();
|
|
592
|
-
return {
|
|
586
|
+
return {
|
|
587
|
+
done: Boolean(step.done),
|
|
588
|
+
value: Array.isArray(step.value) ? new ProgramArray(step.value) : step.value,
|
|
589
|
+
};
|
|
593
590
|
}),
|
|
594
591
|
close: Effect.void,
|
|
595
592
|
});
|
|
@@ -612,10 +609,10 @@ class Frame {
|
|
|
612
609
|
asynchronous: value.asynchronous,
|
|
613
610
|
});
|
|
614
611
|
}
|
|
615
|
-
if (!
|
|
612
|
+
if (!(value instanceof ProgramObject))
|
|
616
613
|
return Effect.undefined;
|
|
617
|
-
const asyncMethod = allowAsync ?
|
|
618
|
-
const method = asyncMethod ??
|
|
614
|
+
const asyncMethod = allowAsync ? get(value, AsyncIteratorSymbol) : undefined;
|
|
615
|
+
const method = asyncMethod ?? get(value, IteratorSymbol);
|
|
619
616
|
if (method === undefined || method === null)
|
|
620
617
|
return Effect.undefined;
|
|
621
618
|
const self = this;
|
|
@@ -625,7 +622,7 @@ class Frame {
|
|
|
625
622
|
iterator: object,
|
|
626
623
|
next: object instanceof CodeModeGenerator
|
|
627
624
|
? new GeneratorMethodReference(object, "next")
|
|
628
|
-
: self.requireIteratorMethod(object
|
|
625
|
+
: self.requireIteratorMethod(get(object, "next"), "Iterator next", node),
|
|
629
626
|
asynchronous: asyncMethod !== undefined && asyncMethod !== null,
|
|
630
627
|
};
|
|
631
628
|
});
|
|
@@ -635,7 +632,7 @@ class Frame {
|
|
|
635
632
|
return Effect.gen(function* () {
|
|
636
633
|
if (iterator.asynchronous) {
|
|
637
634
|
const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(iterator.next, [], node)), "Iterator next() result", node);
|
|
638
|
-
return { done: Boolean(object
|
|
635
|
+
return { done: Boolean(get(object, "done")), value: get(object, "value") };
|
|
639
636
|
}
|
|
640
637
|
const called = yield* Effect.exit(self.invokeCallable(iterator.next, [], node));
|
|
641
638
|
if (!Exit.isSuccess(called)) {
|
|
@@ -645,7 +642,7 @@ class Frame {
|
|
|
645
642
|
}
|
|
646
643
|
const captured = yield* Effect.exit(Effect.sync(() => {
|
|
647
644
|
const object = self.requireIteratorObject(called.value, "Iterator next() result", node);
|
|
648
|
-
return { done: Boolean(object
|
|
645
|
+
return { done: Boolean(get(object, "done")), value: get(object, "value") };
|
|
649
646
|
}));
|
|
650
647
|
if (!Exit.isSuccess(captured)) {
|
|
651
648
|
if (awaiting)
|
|
@@ -663,7 +660,7 @@ class Frame {
|
|
|
663
660
|
closeIterator(iterator, node, awaiting = true) {
|
|
664
661
|
const close = iterator.iterator instanceof CodeModeGenerator
|
|
665
662
|
? new GeneratorMethodReference(iterator.iterator, "return")
|
|
666
|
-
: iterator.iterator
|
|
663
|
+
: get(iterator.iterator, "return");
|
|
667
664
|
if (close === undefined || close === null)
|
|
668
665
|
return iterator.asynchronous || !awaiting ? Effect.void : Effect.yieldNow;
|
|
669
666
|
const self = this;
|
|
@@ -679,7 +676,7 @@ class Frame {
|
|
|
679
676
|
yield* Effect.yieldNow;
|
|
680
677
|
return yield* Effect.failCause(called.cause);
|
|
681
678
|
}
|
|
682
|
-
const captured = yield* Effect.exit(Effect.sync(() => self.requireIteratorObject(called.value, "Iterator return() result", node)
|
|
679
|
+
const captured = yield* Effect.exit(Effect.sync(() => get(self.requireIteratorObject(called.value, "Iterator return() result", node), "value")));
|
|
683
680
|
if (!Exit.isSuccess(captured)) {
|
|
684
681
|
if (awaiting)
|
|
685
682
|
yield* Effect.yieldNow;
|
|
@@ -690,7 +687,7 @@ class Frame {
|
|
|
690
687
|
});
|
|
691
688
|
}
|
|
692
689
|
requireIteratorObject(value, context, node) {
|
|
693
|
-
if (
|
|
690
|
+
if (value instanceof ProgramObject)
|
|
694
691
|
return value;
|
|
695
692
|
throw new InterpreterRuntimeError(`${context} must be an object.`, node).as("TypeError");
|
|
696
693
|
}
|
|
@@ -710,7 +707,7 @@ class Frame {
|
|
|
710
707
|
return [...this.runtime.toolKeys(value.path)];
|
|
711
708
|
if (value === null || value === undefined)
|
|
712
709
|
return [];
|
|
713
|
-
return
|
|
710
|
+
return ownKeys(enumerableSource("for...in", value, node)).filter((key) => typeof key === "string");
|
|
714
711
|
}
|
|
715
712
|
evaluateForInStatement(node, labels) {
|
|
716
713
|
const left = node.left;
|
|
@@ -856,18 +853,14 @@ class Frame {
|
|
|
856
853
|
return;
|
|
857
854
|
}
|
|
858
855
|
if (pattern.type === "ObjectPattern") {
|
|
859
|
-
if (value
|
|
856
|
+
if (!(value instanceof ProgramObject)) {
|
|
860
857
|
throw new InterpreterRuntimeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern, "InvalidDataValue");
|
|
861
858
|
}
|
|
862
859
|
const consumed = new Set();
|
|
863
860
|
for (const property of pattern.properties) {
|
|
864
861
|
if (property.type === "RestElement") {
|
|
865
|
-
const rest =
|
|
866
|
-
|
|
867
|
-
if (!consumed.has(key))
|
|
868
|
-
rest[key] = item;
|
|
869
|
-
}
|
|
870
|
-
copyIteratorSymbols(value, rest, consumed);
|
|
862
|
+
const rest = new ProgramObject();
|
|
863
|
+
assign(rest, value, consumed);
|
|
871
864
|
yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
|
|
872
865
|
continue;
|
|
873
866
|
}
|
|
@@ -900,25 +893,20 @@ class Frame {
|
|
|
900
893
|
return;
|
|
901
894
|
}
|
|
902
895
|
if (pattern.type === "ObjectPattern") {
|
|
903
|
-
if (value
|
|
896
|
+
if (!(value instanceof ProgramObject)) {
|
|
904
897
|
throw new InterpreterRuntimeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern, "InvalidDataValue");
|
|
905
898
|
}
|
|
906
|
-
const source = value;
|
|
907
899
|
const consumed = new Set();
|
|
908
900
|
for (const property of pattern.properties) {
|
|
909
901
|
if (property.type === "RestElement") {
|
|
910
|
-
const rest =
|
|
911
|
-
|
|
912
|
-
if (!consumed.has(key))
|
|
913
|
-
rest[key] = item;
|
|
914
|
-
}
|
|
915
|
-
copyIteratorSymbols(source, rest, consumed);
|
|
902
|
+
const rest = new ProgramObject();
|
|
903
|
+
assign(rest, value, consumed);
|
|
916
904
|
yield* self.assignPattern(property.argument, rest, property);
|
|
917
905
|
continue;
|
|
918
906
|
}
|
|
919
907
|
const key = yield* self.destructuringPropertyKey(property);
|
|
920
908
|
consumed.add(typeof key === "symbol" ? key : String(key));
|
|
921
|
-
yield* self.assignPattern(property.value, self.destructuringPropertyValue(
|
|
909
|
+
yield* self.assignPattern(property.value, self.destructuringPropertyValue(value, key), property);
|
|
922
910
|
}
|
|
923
911
|
return;
|
|
924
912
|
}
|
|
@@ -940,7 +928,7 @@ class Frame {
|
|
|
940
928
|
if (done) {
|
|
941
929
|
if (element === null)
|
|
942
930
|
continue;
|
|
943
|
-
yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ?
|
|
931
|
+
yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new ProgramArray() : undefined, element);
|
|
944
932
|
if (element.type === "RestElement")
|
|
945
933
|
return;
|
|
946
934
|
continue;
|
|
@@ -959,7 +947,7 @@ class Frame {
|
|
|
959
947
|
if (!done)
|
|
960
948
|
rest.push(next.value);
|
|
961
949
|
}
|
|
962
|
-
yield* consume(element.argument, rest, element);
|
|
950
|
+
yield* consume(element.argument, new ProgramArray(rest), element);
|
|
963
951
|
return;
|
|
964
952
|
}
|
|
965
953
|
const consumed = consume(element, step.done ? undefined : step.value, pattern);
|
|
@@ -984,14 +972,10 @@ class Frame {
|
|
|
984
972
|
throw unsupportedSyntax(keyNode.type, keyNode);
|
|
985
973
|
}
|
|
986
974
|
destructuringPropertyValue(source, key) {
|
|
987
|
-
if (!
|
|
988
|
-
return
|
|
989
|
-
if (key
|
|
990
|
-
return source
|
|
991
|
-
if (typeof key === "number")
|
|
992
|
-
return source[key];
|
|
993
|
-
if (Object.hasOwn(source, key))
|
|
994
|
-
return Reflect.get(source, key);
|
|
975
|
+
if (!(source instanceof ProgramArray))
|
|
976
|
+
return get(source, key);
|
|
977
|
+
if (has(source, key))
|
|
978
|
+
return get(source, key);
|
|
995
979
|
if (typeof key === "string" && arrayMethods.has(key))
|
|
996
980
|
return new IntrinsicReference(source, key);
|
|
997
981
|
return undefined;
|
|
@@ -1148,11 +1132,10 @@ class Frame {
|
|
|
1148
1132
|
case ">>>":
|
|
1149
1133
|
return l >>> r;
|
|
1150
1134
|
case "in":
|
|
1151
|
-
if (rhs
|
|
1135
|
+
if (!(rhs instanceof ProgramObject)) {
|
|
1152
1136
|
throw new InterpreterRuntimeError("The 'in' operator requires a data object on the right-hand side.", node);
|
|
1153
1137
|
}
|
|
1154
|
-
|
|
1155
|
-
return Object.hasOwn(rhs, coerceOperand(lhs));
|
|
1138
|
+
return has(rhs, coerceOperand(lhs));
|
|
1156
1139
|
default:
|
|
1157
1140
|
throw new InterpreterRuntimeError(`Unsupported binary operator '${operator}'.`, node);
|
|
1158
1141
|
}
|
|
@@ -1387,7 +1370,7 @@ class Frame {
|
|
|
1387
1370
|
}
|
|
1388
1371
|
for (const [index, parameter] of fn.parameters.entries()) {
|
|
1389
1372
|
if (parameter.type === "RestElement") {
|
|
1390
|
-
yield* invocation.declarePattern(parameter.argument, args.slice(index), true, parameter, true);
|
|
1373
|
+
yield* invocation.declarePattern(parameter.argument, new ProgramArray(args.slice(index)), true, parameter, true);
|
|
1391
1374
|
break;
|
|
1392
1375
|
}
|
|
1393
1376
|
yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
|
|
@@ -1429,13 +1412,13 @@ class Frame {
|
|
|
1429
1412
|
if (state.completed) {
|
|
1430
1413
|
if (kind === "throw")
|
|
1431
1414
|
return Effect.fail(new ProgramThrow(value));
|
|
1432
|
-
return Effect.succeed({ value: kind === "return" ? value : undefined, done: true });
|
|
1415
|
+
return Effect.succeed(record({ value: kind === "return" ? value : undefined, done: true }));
|
|
1433
1416
|
}
|
|
1434
1417
|
if (!state.started && kind !== "next") {
|
|
1435
1418
|
state.completed = true;
|
|
1436
1419
|
if (kind === "throw")
|
|
1437
1420
|
return Effect.fail(new ProgramThrow(value));
|
|
1438
|
-
return Effect.succeed({ value, done: true });
|
|
1421
|
+
return Effect.succeed(record({ value, done: true }));
|
|
1439
1422
|
}
|
|
1440
1423
|
state.pending.push(request);
|
|
1441
1424
|
if (state.available) {
|
|
@@ -1455,7 +1438,7 @@ class Frame {
|
|
|
1455
1438
|
const active = state.active;
|
|
1456
1439
|
state.active = undefined;
|
|
1457
1440
|
if (active) {
|
|
1458
|
-
Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed({ value: exit.value, done: true }) : exit);
|
|
1441
|
+
Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed(record({ value: exit.value, done: true })) : exit);
|
|
1459
1442
|
}
|
|
1460
1443
|
yield* invocation.completeGeneratorRequests(state, asynchronous);
|
|
1461
1444
|
state.completed = true;
|
|
@@ -1479,10 +1462,10 @@ class Frame {
|
|
|
1479
1462
|
}
|
|
1480
1463
|
if (asynchronous && pending.kind === "return") {
|
|
1481
1464
|
const resolved = yield* Effect.exit(self.awaitValue(pending.value));
|
|
1482
|
-
Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed({ value: resolved.value, done: true }) : resolved);
|
|
1465
|
+
Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed(record({ value: resolved.value, done: true })) : resolved);
|
|
1483
1466
|
continue;
|
|
1484
1467
|
}
|
|
1485
|
-
Deferred.doneUnsafe(pending.response, Exit.succeed({ value: pending.kind === "return" ? pending.value : undefined, done: true }));
|
|
1468
|
+
Deferred.doneUnsafe(pending.response, Exit.succeed(record({ value: pending.kind === "return" ? pending.value : undefined, done: true })));
|
|
1486
1469
|
}
|
|
1487
1470
|
});
|
|
1488
1471
|
}
|
|
@@ -1523,7 +1506,7 @@ class Frame {
|
|
|
1523
1506
|
const state = this.generatorState;
|
|
1524
1507
|
if (!state?.active)
|
|
1525
1508
|
throw new InterpreterRuntimeError("Generator has no active request.", node);
|
|
1526
|
-
Deferred.doneUnsafe(state.active.response, Exit.succeed({ value, done: false }));
|
|
1509
|
+
Deferred.doneUnsafe(state.active.response, Exit.succeed(record({ value, done: false })));
|
|
1527
1510
|
state.active = undefined;
|
|
1528
1511
|
return Effect.flatMap(this.takeGeneratorRequest(state), (request) => {
|
|
1529
1512
|
state.active = request;
|
|
@@ -1539,7 +1522,7 @@ class Frame {
|
|
|
1539
1522
|
delegateYield(value, node) {
|
|
1540
1523
|
const self = this;
|
|
1541
1524
|
return Effect.gen(function* () {
|
|
1542
|
-
if (
|
|
1525
|
+
if (value instanceof ProgramArray ||
|
|
1543
1526
|
typeof value === "string" ||
|
|
1544
1527
|
value instanceof Values.Map ||
|
|
1545
1528
|
value instanceof Values.Set ||
|
|
@@ -1576,7 +1559,7 @@ class Frame {
|
|
|
1576
1559
|
? iterator.next
|
|
1577
1560
|
: iterator.iterator instanceof CodeModeGenerator
|
|
1578
1561
|
? new GeneratorMethodReference(iterator.iterator, kind)
|
|
1579
|
-
: iterator.iterator
|
|
1562
|
+
: get(iterator.iterator, kind);
|
|
1580
1563
|
if (method === undefined || method === null) {
|
|
1581
1564
|
if (kind === "return")
|
|
1582
1565
|
return yield* Effect.fail(new GeneratorReturn(input));
|
|
@@ -1585,10 +1568,10 @@ class Frame {
|
|
|
1585
1568
|
}
|
|
1586
1569
|
const called = yield* self.invokeCallable(self.requireIteratorMethod(method, `Iterator ${kind}`, node), [input], node);
|
|
1587
1570
|
const result = self.requireIteratorObject(iterator.asynchronous ? yield* self.awaitValue(called) : called, `Iterator ${kind}() result`, node);
|
|
1588
|
-
const done = Boolean(result
|
|
1571
|
+
const done = Boolean(get(result, "done"));
|
|
1589
1572
|
const resultValue = self.generatorAsync && !iterator.asynchronous
|
|
1590
|
-
? yield* self.awaitAsyncFromSyncValue(iterator, result
|
|
1591
|
-
: result
|
|
1573
|
+
? yield* self.awaitAsyncFromSyncValue(iterator, get(result, "value"), node, kind !== "return" && !done)
|
|
1574
|
+
: get(result, "value");
|
|
1592
1575
|
if (done) {
|
|
1593
1576
|
if (kind === "return")
|
|
1594
1577
|
return yield* Effect.fail(new GeneratorReturn(resultValue));
|
|
@@ -1610,7 +1593,7 @@ class Frame {
|
|
|
1610
1593
|
});
|
|
1611
1594
|
}
|
|
1612
1595
|
evaluateObjectExpression(node) {
|
|
1613
|
-
const objectValue =
|
|
1596
|
+
const objectValue = new ProgramObject();
|
|
1614
1597
|
const self = this;
|
|
1615
1598
|
return Effect.gen(function* () {
|
|
1616
1599
|
for (const property of node.properties) {
|
|
@@ -1618,11 +1601,7 @@ class Frame {
|
|
|
1618
1601
|
const spread = yield* self.evaluateExpression(property.argument);
|
|
1619
1602
|
if (spread === null || spread === undefined)
|
|
1620
1603
|
continue;
|
|
1621
|
-
|
|
1622
|
-
for (const [key, value] of Object.entries(from))
|
|
1623
|
-
objectValue[key] = value;
|
|
1624
|
-
if (typeof from === "object")
|
|
1625
|
-
copyIteratorSymbols(from, objectValue);
|
|
1604
|
+
assign(objectValue, enumerableSource("Object spread", spread, property));
|
|
1626
1605
|
continue;
|
|
1627
1606
|
}
|
|
1628
1607
|
if (property.kind !== "init") {
|
|
@@ -1642,7 +1621,7 @@ class Frame {
|
|
|
1642
1621
|
else {
|
|
1643
1622
|
throw new InterpreterRuntimeError("Unsupported object property key shape.", keyNode);
|
|
1644
1623
|
}
|
|
1645
|
-
|
|
1624
|
+
set(objectValue, key, yield* self.evaluateExpression(property.value));
|
|
1646
1625
|
}
|
|
1647
1626
|
return objectValue;
|
|
1648
1627
|
});
|
|
@@ -1673,7 +1652,7 @@ class Frame {
|
|
|
1673
1652
|
values.push(yield* self.evaluateExpression(element));
|
|
1674
1653
|
}
|
|
1675
1654
|
}
|
|
1676
|
-
return values;
|
|
1655
|
+
return new ProgramArray(values);
|
|
1677
1656
|
});
|
|
1678
1657
|
}
|
|
1679
1658
|
evaluateTemplateLiteral(node) {
|
|
@@ -1736,7 +1715,9 @@ class Frame {
|
|
|
1736
1715
|
return new ComputedValue(objectValue.member(key, propertyNode));
|
|
1737
1716
|
}
|
|
1738
1717
|
// Values have no prototype chain, so `.constructor` resolves to the owning built-in directly.
|
|
1739
|
-
if (operation === "read" &&
|
|
1718
|
+
if (operation === "read" &&
|
|
1719
|
+
key === "constructor" &&
|
|
1720
|
+
!(objectValue instanceof ProgramObject && has(objectValue, key))) {
|
|
1740
1721
|
const name = constructorName(objectValue);
|
|
1741
1722
|
if (name !== undefined)
|
|
1742
1723
|
return new ComputedValue(self.runtime.builtins.get(name));
|
|
@@ -1823,25 +1804,14 @@ class Frame {
|
|
|
1823
1804
|
if (isRuntimeReference(objectValue)) {
|
|
1824
1805
|
throw new InterpreterRuntimeError(`Cannot read properties of ${describeValue(objectValue)}; only data values expose properties.`, objectNode, "InvalidDataValue");
|
|
1825
1806
|
}
|
|
1826
|
-
if (
|
|
1807
|
+
if (!(objectValue instanceof ProgramObject)) {
|
|
1827
1808
|
throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode);
|
|
1828
1809
|
}
|
|
1829
|
-
if (Array.isArray(objectValue)) {
|
|
1830
|
-
if (operation === "delete")
|
|
1831
|
-
return { target: objectValue, key };
|
|
1832
|
-
const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
|
|
1833
|
-
if (key !== "length" && !(typeof key === "string" && arrayMethods.has(key)) && index === undefined) {
|
|
1834
|
-
if (typeof key === "string" && Object.hasOwn(objectValue, key)) {
|
|
1835
|
-
return new ComputedValue(objectValue[key]);
|
|
1836
|
-
}
|
|
1837
|
-
return new ComputedValue(undefined);
|
|
1838
|
-
}
|
|
1839
|
-
return { target: objectValue, key: index ?? key };
|
|
1840
|
-
}
|
|
1841
1810
|
return { target: objectValue, key };
|
|
1842
1811
|
});
|
|
1843
1812
|
}
|
|
1844
1813
|
readMember(node) {
|
|
1814
|
+
const self = this;
|
|
1845
1815
|
return Effect.map(this.getMemberReference(node), (reference) => {
|
|
1846
1816
|
if (reference === OptionalShortCircuit)
|
|
1847
1817
|
return OptionalShortCircuit;
|
|
@@ -1849,19 +1819,15 @@ class Frame {
|
|
|
1849
1819
|
return reference.value;
|
|
1850
1820
|
if (reference === undefined || isOpaqueMemberReference(reference))
|
|
1851
1821
|
return reference;
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
if (reference.target instanceof Values.URL) {
|
|
1862
|
-
return Reflect.get(reference.target.url, reference.key);
|
|
1863
|
-
}
|
|
1864
|
-
return Reflect.get(reference.target, reference.key);
|
|
1822
|
+
const value = self.readReferenceValue(reference, reference.key);
|
|
1823
|
+
if (value === undefined &&
|
|
1824
|
+
reference.target instanceof ProgramArray &&
|
|
1825
|
+
typeof reference.key === "string" &&
|
|
1826
|
+
arrayMethods.has(reference.key) &&
|
|
1827
|
+
!has(reference.target, reference.key)) {
|
|
1828
|
+
return new IntrinsicReference(reference.target, reference.key);
|
|
1829
|
+
}
|
|
1830
|
+
return value;
|
|
1865
1831
|
});
|
|
1866
1832
|
}
|
|
1867
1833
|
writeMember(node, value) {
|
|
@@ -1884,7 +1850,7 @@ class Frame {
|
|
|
1884
1850
|
if (reference.target instanceof Values.RegExp) {
|
|
1885
1851
|
return Reflect.deleteProperty(reference.target.regex, reference.key);
|
|
1886
1852
|
}
|
|
1887
|
-
return
|
|
1853
|
+
return remove(reference.target, reference.key);
|
|
1888
1854
|
});
|
|
1889
1855
|
}
|
|
1890
1856
|
// Resolve side-effecting object and key expressions exactly once.
|
|
@@ -1898,13 +1864,6 @@ class Frame {
|
|
|
1898
1864
|
isOpaqueMemberReference(reference)) {
|
|
1899
1865
|
throw new InterpreterRuntimeError("Only data fields may be assigned.", node);
|
|
1900
1866
|
}
|
|
1901
|
-
if (Array.isArray(reference.target)) {
|
|
1902
|
-
if (reference.key === "length")
|
|
1903
|
-
throw new InterpreterRuntimeError("Array length cannot be assigned.", node);
|
|
1904
|
-
if (typeof reference.key === "string" && arrayMethods.has(reference.key)) {
|
|
1905
|
-
throw new InterpreterRuntimeError("Array methods cannot be assigned.", node);
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
1867
|
const key = reference.key;
|
|
1909
1868
|
const { write, next, result } = yield* compute(self.readReferenceValue(reference, key));
|
|
1910
1869
|
if (write)
|
|
@@ -1918,18 +1877,9 @@ class Frame {
|
|
|
1918
1877
|
}
|
|
1919
1878
|
if (reference.target instanceof Values.RegExp)
|
|
1920
1879
|
return reference.target.lastIndex;
|
|
1921
|
-
return
|
|
1880
|
+
return get(reference.target, key);
|
|
1922
1881
|
}
|
|
1923
1882
|
assignToReference(reference, key, next, node) {
|
|
1924
|
-
if (Array.isArray(reference.target)) {
|
|
1925
|
-
const target = reference.target;
|
|
1926
|
-
if (typeof key !== "number" || parseArrayIndex(key) === undefined) {
|
|
1927
|
-
throw new InterpreterRuntimeError("Array assignment index must be a valid array index.", node, "InvalidDataValue");
|
|
1928
|
-
}
|
|
1929
|
-
rejectCircularInsertion(target, next, "Array assignment result", node);
|
|
1930
|
-
target[key] = next;
|
|
1931
|
-
return;
|
|
1932
|
-
}
|
|
1933
1883
|
if (reference.target instanceof Values.URL) {
|
|
1934
1884
|
const property = key;
|
|
1935
1885
|
if (!urlWritableProperties.has(property)) {
|
|
@@ -1951,8 +1901,9 @@ class Frame {
|
|
|
1951
1901
|
return;
|
|
1952
1902
|
}
|
|
1953
1903
|
const target = reference.target;
|
|
1954
|
-
rejectCircularInsertion(target, next, "Object assignment result", node);
|
|
1955
|
-
|
|
1904
|
+
rejectCircularInsertion(target, next, target instanceof ProgramArray ? "Array assignment result" : "Object assignment result", node);
|
|
1905
|
+
if (!set(target, key, next))
|
|
1906
|
+
throw new InterpreterRuntimeError("Invalid array length", node).as("RangeError");
|
|
1956
1907
|
}
|
|
1957
1908
|
toPropertyKey(value, node) {
|
|
1958
1909
|
if (typeof value === "string" || typeof value === "number") {
|