@opencode/codemode 0.0.0-beta-19365 → 0.0.0-beta-19381
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/interpreter/errors.d.ts +4 -6
- package/dist/interpreter/errors.js +20 -4
- package/dist/interpreter/execute.js +2 -3
- package/dist/interpreter/globals.d.ts +13 -0
- package/dist/interpreter/globals.js +59 -0
- package/dist/interpreter/host.d.ts +41 -0
- package/dist/interpreter/host.js +44 -0
- package/dist/interpreter/methods.d.ts +3 -23
- package/dist/interpreter/methods.js +8 -183
- package/dist/interpreter/model.d.ts +0 -41
- package/dist/interpreter/model.js +0 -56
- package/dist/interpreter/promises.d.ts +7 -8
- package/dist/interpreter/promises.js +45 -22
- package/dist/interpreter/references.js +11 -28
- package/dist/interpreter/runner.d.ts +23 -0
- package/dist/interpreter/runner.js +42 -0
- package/dist/interpreter/runtime.d.ts +11 -92
- package/dist/interpreter/runtime.js +75 -452
- package/dist/stdlib/array.d.ts +3 -0
- package/dist/stdlib/array.js +73 -0
- package/dist/stdlib/collections.d.ts +6 -1
- package/dist/stdlib/collections.js +120 -1
- package/dist/stdlib/console.d.ts +3 -2
- package/dist/stdlib/console.js +11 -2
- package/dist/stdlib/date.d.ts +3 -2
- package/dist/stdlib/date.js +27 -11
- package/dist/stdlib/json.d.ts +4 -4
- package/dist/stdlib/json.js +6 -2
- package/dist/stdlib/math.d.ts +3 -7
- package/dist/stdlib/math.js +85 -153
- package/dist/stdlib/number.d.ts +1 -3
- package/dist/stdlib/number.js +28 -36
- package/dist/stdlib/object.d.ts +4 -6
- package/dist/stdlib/object.js +101 -71
- package/dist/stdlib/regexp.d.ts +2 -4
- package/dist/stdlib/regexp.js +32 -9
- package/dist/stdlib/string.d.ts +1 -3
- package/dist/stdlib/string.js +14 -16
- package/dist/stdlib/url.d.ts +8 -4
- package/dist/stdlib/url.js +97 -21
- package/dist/stdlib/value.d.ts +5 -3
- package/dist/stdlib/value.js +21 -19
- package/package.json +1 -1
- package/dist/interpreter/iterator.d.ts +0 -13
- package/dist/interpreter/iterator.js +0 -4
- package/dist/stdlib/promise.d.ts +0 -2
- package/dist/stdlib/promise.js +0 -1
|
@@ -1,36 +1,23 @@
|
|
|
1
1
|
import { Cause, Deferred, Effect, Exit } from "effect";
|
|
2
2
|
import { isBlockedMember, ToolRuntimeError, toProgram } from "../data.js";
|
|
3
3
|
import { ToolReference } from "../tool-runtime.js";
|
|
4
|
-
import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator,
|
|
5
|
-
import { caughtErrorValue
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
4
|
+
import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, ComputedValue, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError, isRecord, IteratorSymbol, IteratorSymbols, OptionalShortCircuit, PromiseInstanceMethodReference, ProgramThrow, unsupportedSyntax, } from "./model.js";
|
|
5
|
+
import { caughtErrorValue } from "./errors.js";
|
|
6
|
+
import { globals } from "./globals.js";
|
|
7
|
+
import { HostFunction, HostNamespace } from "./host.js";
|
|
8
|
+
import { invokeIntrinsic } from "./methods.js";
|
|
9
|
+
import { preserveConsumerError } from "./runner.js";
|
|
10
|
+
import { invokePromiseInstanceMethod, PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
|
|
9
11
|
import { containsOpaqueReference, isRuntimeReference, rejectCircularInsertion, typeofValue } from "./references.js";
|
|
10
12
|
import { ScopeStack } from "./scope.js";
|
|
11
|
-
import { arrayMethods, mapMethods,
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { promiseStatics } from "../stdlib/promise.js";
|
|
19
|
-
import { escapeRegexHint, regexpMethods, regexpProperties, regexpStatics, regexFailureReason, } from "../stdlib/regexp.js";
|
|
20
|
-
import { stringMethods, stringStatics } from "../stdlib/string.js";
|
|
21
|
-
import { urlMethods, urlProperties, urlSearchParamsMethods, urlStatics, urlWritableProperties, invokeUriFunction, uriArgument, urlArgument, } from "../stdlib/url.js";
|
|
22
|
-
import { coerceToNumber, coerceToString, compoundOperators, errorBrandName, errorConstructors, invokeCoercion, valueConstructors, } from "../stdlib/value.js";
|
|
13
|
+
import { arrayMethods, mapMethods, setMethods } from "../stdlib/collections.js";
|
|
14
|
+
import { dateMethods } from "../stdlib/date.js";
|
|
15
|
+
import { numberMethods } from "../stdlib/number.js";
|
|
16
|
+
import { constructRegExp, regexpMethods, regexpProperties } from "../stdlib/regexp.js";
|
|
17
|
+
import { stringMethods } from "../stdlib/string.js";
|
|
18
|
+
import { uriArgument, urlMethods, urlProperties, urlSearchParamsMethods, urlWritableProperties } from "../stdlib/url.js";
|
|
19
|
+
import { coerceToNumber, coerceToString, compoundOperators } from "../stdlib/value.js";
|
|
23
20
|
import { Values } from "../values.js";
|
|
24
|
-
const globalStaticMembers = {
|
|
25
|
-
Object: objectStatics,
|
|
26
|
-
Math: mathMethods,
|
|
27
|
-
Array: arrayStatics,
|
|
28
|
-
console: consoleMethods,
|
|
29
|
-
Date: dateStatics,
|
|
30
|
-
RegExp: regexpStatics,
|
|
31
|
-
Map: mapStatics,
|
|
32
|
-
URL: urlStatics,
|
|
33
|
-
};
|
|
34
21
|
const MAX_ARRAY_LENGTH = 4_294_967_295;
|
|
35
22
|
const parseArrayIndex = (key) => {
|
|
36
23
|
const property = String(key);
|
|
@@ -56,35 +43,8 @@ const calleeDescription = (callee) => {
|
|
|
56
43
|
return "The called value";
|
|
57
44
|
};
|
|
58
45
|
const instanceofValue = (lhs, rhs, node) => {
|
|
59
|
-
if (rhs instanceof
|
|
60
|
-
|
|
61
|
-
return brand !== undefined && (rhs.name === "Error" || brand === rhs.name);
|
|
62
|
-
}
|
|
63
|
-
if (rhs instanceof GlobalNamespace) {
|
|
64
|
-
switch (rhs.name) {
|
|
65
|
-
case "Date":
|
|
66
|
-
return lhs instanceof Values.Date;
|
|
67
|
-
case "RegExp":
|
|
68
|
-
return lhs instanceof Values.RegExp;
|
|
69
|
-
case "Map":
|
|
70
|
-
return lhs instanceof Values.Map;
|
|
71
|
-
case "Set":
|
|
72
|
-
return lhs instanceof Values.Set;
|
|
73
|
-
case "URL":
|
|
74
|
-
return lhs instanceof Values.URL;
|
|
75
|
-
case "URLSearchParams":
|
|
76
|
-
return lhs instanceof Values.URLSearchParams;
|
|
77
|
-
case "Array":
|
|
78
|
-
return Array.isArray(lhs);
|
|
79
|
-
case "Object":
|
|
80
|
-
return lhs !== null && (typeof lhs === "object" || typeofValue(lhs) === "function");
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (rhs instanceof PromiseNamespace)
|
|
84
|
-
return lhs instanceof Values.Promise;
|
|
85
|
-
if (rhs instanceof CoercionFunction && (rhs.name === "Number" || rhs.name === "String" || rhs.name === "Boolean")) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
46
|
+
if (rhs instanceof HostFunction && rhs.instanceOf !== undefined)
|
|
47
|
+
return rhs.instanceOf(lhs);
|
|
88
48
|
throw new InterpreterRuntimeError("The right-hand side of 'instanceof' must be a supported constructor: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", node);
|
|
89
49
|
};
|
|
90
50
|
const collectPatternNames = (pattern, out = []) => {
|
|
@@ -127,11 +87,8 @@ const loopDeclaration = (left, statement) => {
|
|
|
127
87
|
};
|
|
128
88
|
};
|
|
129
89
|
const isOpaqueMemberReference = (value) => value instanceof ToolReference ||
|
|
130
|
-
value instanceof PromiseMethodReference ||
|
|
131
90
|
value instanceof PromiseInstanceMethodReference ||
|
|
132
91
|
value instanceof IntrinsicReference ||
|
|
133
|
-
value instanceof GlobalMethodReference ||
|
|
134
|
-
value instanceof JsonMethodReference ||
|
|
135
92
|
value instanceof GeneratorMethodReference;
|
|
136
93
|
const copyIteratorSymbols = (source, target, consumed) => {
|
|
137
94
|
for (const symbol of IteratorSymbols) {
|
|
@@ -140,61 +97,46 @@ const copyIteratorSymbols = (source, target, consumed) => {
|
|
|
140
97
|
}
|
|
141
98
|
};
|
|
142
99
|
const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
|
|
143
|
-
|
|
144
|
-
|
|
100
|
+
/** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
|
|
101
|
+
export class Runtime {
|
|
145
102
|
executeTool;
|
|
146
|
-
|
|
103
|
+
search;
|
|
147
104
|
toolKeys;
|
|
148
|
-
logs;
|
|
149
105
|
promises;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
invokeCallable: (callable, args, node) => this.invokeCallable(callable, args, node),
|
|
155
|
-
settlePromise: (promise) => this.settlePromise(promise),
|
|
156
|
-
syncIterator: (value, node) => this.syncIterator(value, node),
|
|
157
|
-
};
|
|
158
|
-
constructor(executeTool, invokeSearch, toolKeys, promises, logs = []) {
|
|
159
|
-
const globalScope = new Map();
|
|
160
|
-
this.scopes = new ScopeStack([globalScope]);
|
|
106
|
+
logs;
|
|
107
|
+
runner;
|
|
108
|
+
root;
|
|
109
|
+
constructor(executeTool, search, toolKeys, promises, logs = []) {
|
|
161
110
|
this.executeTool = executeTool;
|
|
162
|
-
this.
|
|
111
|
+
this.search = search;
|
|
163
112
|
this.toolKeys = toolKeys;
|
|
164
|
-
this.logs = logs;
|
|
165
113
|
this.promises = promises;
|
|
166
|
-
|
|
167
|
-
globalScope
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
globalScope.set("decodeURIComponent", { mutable: false, value: new UriFunction("decodeURIComponent") });
|
|
193
|
-
for (const name of errorConstructors) {
|
|
194
|
-
globalScope.set(name, { mutable: false, value: new ErrorConstructorReference(name) });
|
|
195
|
-
}
|
|
196
|
-
globalScope.set("NaN", { mutable: false, value: NaN });
|
|
197
|
-
globalScope.set("Infinity", { mutable: false, value: Infinity });
|
|
114
|
+
this.logs = logs;
|
|
115
|
+
const globalScope = new Map();
|
|
116
|
+
// Calling back into the program never reads frame state, so any frame serves; the root is always alive.
|
|
117
|
+
this.root = new Frame(this, new ScopeStack([globalScope]));
|
|
118
|
+
this.runner = {
|
|
119
|
+
invokeFunction: (fn, args) => this.root.invokeFunction(fn, args),
|
|
120
|
+
invokeCallable: (callable, args, node) => this.root.invokeCallable(callable, args, node),
|
|
121
|
+
settlePromise: (promise) => this.root.settlePromise(promise),
|
|
122
|
+
syncIterator: (value, node) => this.root.syncIterator(value, node),
|
|
123
|
+
};
|
|
124
|
+
for (const [name, value] of globals(this))
|
|
125
|
+
globalScope.set(name, { mutable: false, value });
|
|
126
|
+
}
|
|
127
|
+
run(program) {
|
|
128
|
+
return this.root.run(program);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** One activation: the top-level program or a single function call, evaluating against its own scope chain. */
|
|
132
|
+
class Frame {
|
|
133
|
+
runtime;
|
|
134
|
+
scopes;
|
|
135
|
+
generatorState;
|
|
136
|
+
generatorAsync = false;
|
|
137
|
+
constructor(runtime, scopes) {
|
|
138
|
+
this.runtime = runtime;
|
|
139
|
+
this.scopes = scopes;
|
|
198
140
|
}
|
|
199
141
|
run(program) {
|
|
200
142
|
const self = this;
|
|
@@ -219,20 +161,20 @@ export class Interpreter {
|
|
|
219
161
|
}
|
|
220
162
|
}
|
|
221
163
|
// The implicit async body adopts returned promises before copy-out.
|
|
222
|
-
value = yield* resolvePromiseValue(self.runner, value, program);
|
|
164
|
+
value = yield* resolvePromiseValue(self.runtime.runner, value, program);
|
|
223
165
|
return value;
|
|
224
166
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
225
167
|
}
|
|
226
168
|
// Fork at the call site so admission and hooks occur when the call is made.
|
|
227
169
|
createToolCallPromise(path, args) {
|
|
228
|
-
return this.createPromise(Effect.suspend(() => this.executeTool(path, args)));
|
|
170
|
+
return this.createPromise(Effect.suspend(() => this.runtime.executeTool(path, args)));
|
|
229
171
|
}
|
|
230
172
|
createPromise(effect) {
|
|
231
|
-
return this.promises.create(effect);
|
|
173
|
+
return this.runtime.promises.create(effect);
|
|
232
174
|
}
|
|
233
175
|
// Fiber exits make settlement idempotent; yielding prevents inline continuation.
|
|
234
176
|
settlePromise(promise) {
|
|
235
|
-
const promises = this.promises;
|
|
177
|
+
const promises = this.runtime.promises;
|
|
236
178
|
return Effect.suspend(() => {
|
|
237
179
|
promises.markObserved(promise);
|
|
238
180
|
return Effect.flatMap(promises.await(promise), (exit) => Effect.andThen(Effect.yieldNow, exit));
|
|
@@ -555,7 +497,7 @@ export class Interpreter {
|
|
|
555
497
|
})));
|
|
556
498
|
}
|
|
557
499
|
awaitValue(value, node = promiseResolutionNode) {
|
|
558
|
-
return Effect.flatMap(resolvePromise(this.runner, this.promises, value, node), (promise) => this.settlePromise(promise));
|
|
500
|
+
return Effect.flatMap(resolvePromise(this.runtime.runner, this.runtime.promises, value, node), (promise) => this.settlePromise(promise));
|
|
559
501
|
}
|
|
560
502
|
awaitAsyncFromSyncValue(iterator, value, node, closeOnRejection) {
|
|
561
503
|
const self = this;
|
|
@@ -702,7 +644,7 @@ export class Interpreter {
|
|
|
702
644
|
}
|
|
703
645
|
enumerableKeys(value) {
|
|
704
646
|
if (value instanceof ToolReference) {
|
|
705
|
-
return [...this.toolKeys(value.path)];
|
|
647
|
+
return [...this.runtime.toolKeys(value.path)];
|
|
706
648
|
}
|
|
707
649
|
if (Array.isArray(value)) {
|
|
708
650
|
return Object.keys(value);
|
|
@@ -1012,7 +954,7 @@ export class Interpreter {
|
|
|
1012
954
|
case "Literal": {
|
|
1013
955
|
const regex = node.regex;
|
|
1014
956
|
if (regex)
|
|
1015
|
-
return Effect.sync(() =>
|
|
957
|
+
return Effect.sync(() => constructRegExp([regex.pattern, regex.flags], node));
|
|
1016
958
|
return Effect.sync(() => toProgram(node.value, "Literal"));
|
|
1017
959
|
}
|
|
1018
960
|
case "Identifier":
|
|
@@ -1067,208 +1009,15 @@ export class Interpreter {
|
|
|
1067
1009
|
}
|
|
1068
1010
|
}
|
|
1069
1011
|
evaluateNewExpression(node) {
|
|
1070
|
-
const callee = node.callee;
|
|
1071
|
-
if (callee.type !== "Identifier") {
|
|
1072
|
-
throw unsupportedSyntax("NewExpression", node);
|
|
1073
|
-
}
|
|
1074
|
-
const name = callee.name;
|
|
1075
|
-
const argNodes = node.arguments;
|
|
1076
|
-
const self = this;
|
|
1077
|
-
if (name === "Promise") {
|
|
1078
|
-
return Effect.flatMap(this.evaluateCallArguments(argNodes), (args) => constructPromise(self.runner, self.promises, args[0], node));
|
|
1079
|
-
}
|
|
1080
|
-
if (errorConstructors.has(name)) {
|
|
1081
|
-
return Effect.flatMap(this.evaluateCallArguments(argNodes), (args) => name === "AggregateError"
|
|
1082
|
-
? constructAggregateErrorValue(self.runner, args, node)
|
|
1083
|
-
: Effect.succeed(constructErrorValue(name, args)));
|
|
1084
|
-
}
|
|
1085
|
-
// Array and Object construct identically with or without new, like JS.
|
|
1086
|
-
if (name === "Array") {
|
|
1087
|
-
return Effect.map(this.evaluateCallArguments(argNodes), (args) => self.constructArray(args, node));
|
|
1088
|
-
}
|
|
1089
|
-
if (name === "Object") {
|
|
1090
|
-
return Effect.map(this.evaluateCallArguments(argNodes), (args) => self.constructObject(args, node));
|
|
1091
|
-
}
|
|
1092
|
-
if (valueConstructors.has(name)) {
|
|
1093
|
-
return Effect.gen(function* () {
|
|
1094
|
-
const args = yield* self.evaluateCallArguments(argNodes);
|
|
1095
|
-
switch (name) {
|
|
1096
|
-
case "Date":
|
|
1097
|
-
return yield* self.constructDate(args, node);
|
|
1098
|
-
case "RegExp":
|
|
1099
|
-
return self.constructRegExp(args, node);
|
|
1100
|
-
case "Map":
|
|
1101
|
-
return yield* self.constructMap(args[0], node);
|
|
1102
|
-
case "Set":
|
|
1103
|
-
return yield* self.constructSet(args[0], node);
|
|
1104
|
-
case "URL":
|
|
1105
|
-
return self.constructURL(args, node);
|
|
1106
|
-
default:
|
|
1107
|
-
return yield* self.constructURLSearchParams(args[0], node);
|
|
1108
|
-
}
|
|
1109
|
-
});
|
|
1110
|
-
}
|
|
1111
|
-
throw unsupportedSyntax("NewExpression", node);
|
|
1112
|
-
}
|
|
1113
|
-
constructArray(args, node) {
|
|
1114
|
-
if (args.length !== 1)
|
|
1115
|
-
return [...args];
|
|
1116
|
-
const first = args[0];
|
|
1117
|
-
if (typeof first !== "number")
|
|
1118
|
-
return [first];
|
|
1119
|
-
if (!Number.isInteger(first) || first < 0 || first > 4294967295) {
|
|
1120
|
-
throw new InterpreterRuntimeError("Invalid array length.", node).as("RangeError");
|
|
1121
|
-
}
|
|
1122
|
-
// Sparse like JS: Array(3) has holes, and combinator loops already skip them.
|
|
1123
|
-
return new Array(first);
|
|
1124
|
-
}
|
|
1125
|
-
constructObject(args, node) {
|
|
1126
|
-
const first = args[0];
|
|
1127
|
-
if (first === null || first === undefined)
|
|
1128
|
-
return {};
|
|
1129
|
-
if (typeof first === "object")
|
|
1130
|
-
return first;
|
|
1131
|
-
throw new InterpreterRuntimeError(`Object(${typeof first}) wrapper objects are not supported; use the primitive value directly.`, node);
|
|
1132
|
-
}
|
|
1133
|
-
constructDate(args, node) {
|
|
1134
|
-
if (args.length === 0)
|
|
1135
|
-
return Effect.succeed(new Values.Date(Date.now()));
|
|
1136
|
-
if (args.length === 1) {
|
|
1137
|
-
const arg = args[0];
|
|
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()));
|
|
1143
|
-
}
|
|
1144
|
-
const parts = args.map((arg) => coerceToNumber(arg));
|
|
1145
|
-
return Effect.succeed(new Values.Date(new Date(...parts).getTime()));
|
|
1146
|
-
}
|
|
1147
|
-
constructRegExp(args, node) {
|
|
1148
|
-
const first = args[0];
|
|
1149
|
-
const pattern = first instanceof Values.RegExp ? first.regex.source : first === undefined ? "" : coerceToString(first);
|
|
1150
|
-
const flagsArg = args[1];
|
|
1151
|
-
if (flagsArg !== undefined && typeof flagsArg !== "string") {
|
|
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");
|
|
1153
|
-
}
|
|
1154
|
-
const flags = flagsArg ?? (first instanceof Values.RegExp ? first.regex.flags : "");
|
|
1155
|
-
try {
|
|
1156
|
-
return new Values.RegExp(pattern, flags);
|
|
1157
|
-
}
|
|
1158
|
-
catch (error) {
|
|
1159
|
-
const reason = regexFailureReason(error);
|
|
1160
|
-
throw new InterpreterRuntimeError(/flag/i.test(reason)
|
|
1161
|
-
? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.`
|
|
1162
|
-
: `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`, node).as("SyntaxError");
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
constructMap(init, node) {
|
|
1166
|
-
const target = new Values.Map();
|
|
1167
|
-
if (init === undefined || init === null)
|
|
1168
|
-
return Effect.succeed(target);
|
|
1169
1012
|
const self = this;
|
|
1170
1013
|
return Effect.gen(function* () {
|
|
1171
|
-
const
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
return target;
|
|
1179
|
-
yield* preserveConsumerError(cursor, Effect.sync(() => {
|
|
1180
|
-
if (!isRecord(step.value) || isRuntimeReference(step.value)) {
|
|
1181
|
-
throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node).as("TypeError");
|
|
1182
|
-
}
|
|
1183
|
-
target.map.set(step.value[0], step.value[1]);
|
|
1184
|
-
}));
|
|
1185
|
-
}
|
|
1186
|
-
});
|
|
1187
|
-
}
|
|
1188
|
-
constructSet(init, node) {
|
|
1189
|
-
const target = new Values.Set();
|
|
1190
|
-
if (init === undefined || init === null)
|
|
1191
|
-
return Effect.succeed(target);
|
|
1192
|
-
const self = this;
|
|
1193
|
-
return Effect.gen(function* () {
|
|
1194
|
-
const cursor = yield* self.syncIterator(init, node);
|
|
1195
|
-
if (cursor === undefined) {
|
|
1196
|
-
throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node).as("TypeError");
|
|
1197
|
-
}
|
|
1198
|
-
while (true) {
|
|
1199
|
-
const step = yield* cursor.next;
|
|
1200
|
-
if (step.done)
|
|
1201
|
-
return target;
|
|
1202
|
-
target.set.add(step.value);
|
|
1203
|
-
}
|
|
1204
|
-
});
|
|
1205
|
-
}
|
|
1206
|
-
constructURL(args, node) {
|
|
1207
|
-
if (args.length === 0) {
|
|
1208
|
-
throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as("TypeError");
|
|
1209
|
-
}
|
|
1210
|
-
const input = urlArgument(args[0], "new URL input");
|
|
1211
|
-
const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base");
|
|
1212
|
-
try {
|
|
1213
|
-
return new Values.URL(new URL(input, base));
|
|
1214
|
-
}
|
|
1215
|
-
catch {
|
|
1216
|
-
throw new InterpreterRuntimeError(`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, node).as("TypeError");
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
constructURLSearchParams(init, node) {
|
|
1220
|
-
if (init === undefined)
|
|
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)));
|
|
1224
|
-
}
|
|
1225
|
-
if (typeof init === "string")
|
|
1226
|
-
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(init)));
|
|
1227
|
-
if (init === null || typeof init === "number" || typeof init === "boolean") {
|
|
1228
|
-
return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(coerceToString(init))));
|
|
1229
|
-
}
|
|
1230
|
-
const self = this;
|
|
1231
|
-
return Effect.gen(function* () {
|
|
1232
|
-
const cursor = yield* self.syncIterator(init, node);
|
|
1233
|
-
if (cursor !== undefined) {
|
|
1234
|
-
const entries = [];
|
|
1235
|
-
while (true) {
|
|
1236
|
-
const step = yield* cursor.next;
|
|
1237
|
-
if (step.done) {
|
|
1238
|
-
if (entries.some((entry) => entry.length !== 2)) {
|
|
1239
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as("TypeError");
|
|
1240
|
-
}
|
|
1241
|
-
return new Values.URLSearchParams(new URLSearchParams(entries.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
|
|
1242
|
-
}
|
|
1243
|
-
entries.push(yield* preserveConsumerError(cursor, self.readURLSearchParamsPair(step.value, node)));
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
if (isRuntimeReference(init)) {
|
|
1247
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.", node).as("TypeError");
|
|
1248
|
-
}
|
|
1249
|
-
if (Values.isValue(init))
|
|
1250
|
-
return new Values.URLSearchParams(new URLSearchParams());
|
|
1251
|
-
const data = toProgram(init, "new URLSearchParams input");
|
|
1252
|
-
if (data === null || typeof data !== "object") {
|
|
1253
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.", node).as("TypeError");
|
|
1254
|
-
}
|
|
1255
|
-
return new Values.URLSearchParams(new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))));
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
readURLSearchParamsPair(value, node) {
|
|
1259
|
-
const self = this;
|
|
1260
|
-
return Effect.gen(function* () {
|
|
1261
|
-
const cursor = yield* self.syncIterator(value, node);
|
|
1262
|
-
if (cursor === undefined) {
|
|
1263
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as("TypeError");
|
|
1264
|
-
}
|
|
1265
|
-
const items = [];
|
|
1266
|
-
while (true) {
|
|
1267
|
-
const step = yield* cursor.next;
|
|
1268
|
-
if (step.done)
|
|
1269
|
-
return items;
|
|
1270
|
-
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => uriArgument(step.value, "URLSearchParams pair value"))));
|
|
1271
|
-
}
|
|
1014
|
+
const callee = yield* self.evaluateExpression(node.callee);
|
|
1015
|
+
// Globals are built with this interpreter's R; `instanceof` cannot recover the type argument.
|
|
1016
|
+
const construct = callee instanceof HostFunction ? callee.construct : undefined;
|
|
1017
|
+
if (construct === undefined)
|
|
1018
|
+
throw unsupportedSyntax("NewExpression", node);
|
|
1019
|
+
const args = yield* self.evaluateCallArguments(node.arguments);
|
|
1020
|
+
return yield* construct(args, node);
|
|
1272
1021
|
});
|
|
1273
1022
|
}
|
|
1274
1023
|
evaluateBinaryExpression(node) {
|
|
@@ -1522,12 +1271,6 @@ export class Interpreter {
|
|
|
1522
1271
|
}
|
|
1523
1272
|
return yield* self.createToolCallPromise(callable.path, args);
|
|
1524
1273
|
}
|
|
1525
|
-
if (callable instanceof PromiseMethodReference) {
|
|
1526
|
-
return yield* invokePromiseMethod(self.runner, self.promises, callable, args, node);
|
|
1527
|
-
}
|
|
1528
|
-
if (callable instanceof PromiseInstanceMethodReference) {
|
|
1529
|
-
return yield* invokePromiseInstanceMethod(self.runner, self.promises, callable, args, node);
|
|
1530
|
-
}
|
|
1531
1274
|
if (callable instanceof CodeModeFunction) {
|
|
1532
1275
|
return yield* self.invokeFunction(callable, args);
|
|
1533
1276
|
}
|
|
@@ -1538,95 +1281,19 @@ export class Interpreter {
|
|
|
1538
1281
|
return callable.generator.asynchronous ? yield* self.createPromise(requested) : yield* requested;
|
|
1539
1282
|
}
|
|
1540
1283
|
if (callable instanceof IntrinsicReference) {
|
|
1541
|
-
return yield* invokeIntrinsic(self.runner, callable, args, node);
|
|
1542
|
-
}
|
|
1543
|
-
if (callable instanceof GlobalMethodReference) {
|
|
1544
|
-
if (callable.namespace === "console")
|
|
1545
|
-
return self.invokeConsole(callable.name, args, node);
|
|
1546
|
-
if (callable.namespace === "Object" && args[0] instanceof ToolReference) {
|
|
1547
|
-
return self.invokeObjectMethodOnTools(callable.name, args[0], node);
|
|
1548
|
-
}
|
|
1549
|
-
if (callable.namespace === "Object" && objectMethodsPreservingIdentity.has(callable.name)) {
|
|
1550
|
-
if (callable.name === "fromEntries")
|
|
1551
|
-
return yield* invokeObjectFromEntries(self.runner, args[0], node);
|
|
1552
|
-
return invokeGlobalMethod(callable, args, node);
|
|
1553
|
-
}
|
|
1554
|
-
if (callable.namespace === "Array" && callable.name === "from") {
|
|
1555
|
-
return yield* invokeArrayFrom(self.runner, args, node);
|
|
1556
|
-
}
|
|
1557
|
-
if ((callable.namespace === "Object" || callable.namespace === "Map") && callable.name === "groupBy") {
|
|
1558
|
-
return yield* invokeGroupBy(self.runner, callable.namespace, args, node);
|
|
1559
|
-
}
|
|
1560
|
-
if (callable.namespace === "Math" && callable.name === "sumPrecise") {
|
|
1561
|
-
return yield* invokeMathSumPrecise(self.runner, args[0], node);
|
|
1562
|
-
}
|
|
1563
|
-
if (callable.namespace === "Array" && callable.name === "of") {
|
|
1564
|
-
return invokeGlobalMethod(callable, args, node);
|
|
1565
|
-
}
|
|
1566
|
-
return toProgram(invokeGlobalMethod(callable, args, node), `${callable.namespace}.${callable.name} result`);
|
|
1567
|
-
}
|
|
1568
|
-
if (callable instanceof JsonMethodReference) {
|
|
1569
|
-
return yield* invokeJsonMethod(self.runner, callable.name, args, node);
|
|
1570
|
-
}
|
|
1571
|
-
if (callable instanceof CoercionFunction) {
|
|
1572
|
-
return toProgram(invokeCoercion(callable, args, node), `${callable.name} result`);
|
|
1284
|
+
return yield* invokeIntrinsic(self.runtime.runner, callable, args, node);
|
|
1573
1285
|
}
|
|
1574
|
-
if (callable instanceof
|
|
1575
|
-
return
|
|
1576
|
-
}
|
|
1577
|
-
if (callable instanceof SearchFunction) {
|
|
1578
|
-
return yield* self.invokeSearch(args);
|
|
1579
|
-
}
|
|
1580
|
-
if (callable instanceof ErrorConstructorReference) {
|
|
1581
|
-
if (callable.name === "AggregateError")
|
|
1582
|
-
return yield* constructAggregateErrorValue(self.runner, args, node);
|
|
1583
|
-
return constructErrorValue(callable.name, args);
|
|
1584
|
-
}
|
|
1585
|
-
if (callable instanceof GlobalNamespace) {
|
|
1586
|
-
// Real JS permits calling Array, Object, Date, and RegExp without new.
|
|
1587
|
-
if (callable.name === "Array")
|
|
1588
|
-
return self.constructArray(args, node);
|
|
1589
|
-
if (callable.name === "Object")
|
|
1590
|
-
return self.constructObject(args, node);
|
|
1591
|
-
// ISO instead of the host's locale string: CodeMode date strings are
|
|
1592
|
-
// deterministic and must not leak the host timezone.
|
|
1593
|
-
if (callable.name === "Date")
|
|
1594
|
-
return new Date().toISOString();
|
|
1595
|
-
if (callable.name === "RegExp")
|
|
1596
|
-
return self.constructRegExp(args, node);
|
|
1597
|
-
if (typeofValue(callable) === "function") {
|
|
1598
|
-
throw new InterpreterRuntimeError(`Constructor ${callable.name} requires 'new'.`, node).as("TypeError");
|
|
1599
|
-
}
|
|
1600
|
-
throw new InterpreterRuntimeError(`${callable.name} is not a function.`, node).as("TypeError");
|
|
1601
|
-
}
|
|
1602
|
-
if (callable instanceof PromiseNamespace) {
|
|
1603
|
-
throw new InterpreterRuntimeError("Constructor Promise requires 'new'.", node).as("TypeError");
|
|
1604
|
-
}
|
|
1605
|
-
if (callable instanceof SymbolNamespace) {
|
|
1606
|
-
throw new InterpreterRuntimeError("Symbol is not callable; only Symbol.asyncIterator and Symbol.iterator are available.", node).as("TypeError");
|
|
1607
|
-
}
|
|
1608
|
-
if (callable instanceof PromiseCapabilityFunction) {
|
|
1609
|
-
callable.settle(args[0]);
|
|
1610
|
-
return undefined;
|
|
1286
|
+
if (callable instanceof PromiseInstanceMethodReference) {
|
|
1287
|
+
return yield* invokePromiseInstanceMethod(self.runtime.runner, self.runtime.promises, callable, args, node);
|
|
1611
1288
|
}
|
|
1289
|
+
if (callable instanceof HostFunction)
|
|
1290
|
+
return yield* callable.call(args, node);
|
|
1612
1291
|
if (callable === undefined || callable === null) {
|
|
1613
1292
|
throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node).as("TypeError");
|
|
1614
1293
|
}
|
|
1615
1294
|
throw new InterpreterRuntimeError("Only tools are callable here.", callee ?? node);
|
|
1616
1295
|
});
|
|
1617
1296
|
}
|
|
1618
|
-
invokeObjectMethodOnTools(name, ref, node) {
|
|
1619
|
-
if (name === "keys") {
|
|
1620
|
-
return toProgram(this.enumerableKeys(ref), "Object.keys result");
|
|
1621
|
-
}
|
|
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");
|
|
1623
|
-
}
|
|
1624
|
-
invokeConsole(name, args, node) {
|
|
1625
|
-
if (!consoleMethods.has(name))
|
|
1626
|
-
throw new InterpreterRuntimeError(`console.${name} is not available.`, node);
|
|
1627
|
-
this.logs.push(formatConsoleMessage(name, args));
|
|
1628
|
-
return undefined;
|
|
1629
|
-
}
|
|
1630
1297
|
evaluateCallArguments(argNodes) {
|
|
1631
1298
|
const self = this;
|
|
1632
1299
|
return Effect.gen(function* () {
|
|
@@ -1652,8 +1319,7 @@ export class Interpreter {
|
|
|
1652
1319
|
});
|
|
1653
1320
|
}
|
|
1654
1321
|
invokeFunction(fn, args) {
|
|
1655
|
-
const invocation = new
|
|
1656
|
-
invocation.scopes = new ScopeStack([...fn.capturedScopes, new Map()]);
|
|
1322
|
+
const invocation = new Frame(this.runtime, new ScopeStack([...fn.capturedScopes, new Map()]));
|
|
1657
1323
|
const run = Effect.gen(function* () {
|
|
1658
1324
|
// Seed all parameters first so defaults cannot fall through to same-named outer bindings.
|
|
1659
1325
|
const paramScope = invocation.scopes.current();
|
|
@@ -1681,7 +1347,7 @@ export class Interpreter {
|
|
|
1681
1347
|
return run;
|
|
1682
1348
|
// The initial yield assigns the promise before the body can self-resolve.
|
|
1683
1349
|
const box = {};
|
|
1684
|
-
return Effect.map(this.createPromise(Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runner, value, fn.body, box))), (promise) => {
|
|
1350
|
+
return Effect.map(this.createPromise(Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runtime.runner, value, fn.body, box))), (promise) => {
|
|
1685
1351
|
box.promise = promise;
|
|
1686
1352
|
return promise;
|
|
1687
1353
|
});
|
|
@@ -1702,7 +1368,7 @@ export class Interpreter {
|
|
|
1702
1368
|
if (state.draining)
|
|
1703
1369
|
return Deferred.await(request.response);
|
|
1704
1370
|
state.draining = true;
|
|
1705
|
-
return Effect.andThen(this.promises.fork(invocation
|
|
1371
|
+
return Effect.andThen(this.runtime.promises.fork(invocation
|
|
1706
1372
|
.completeGeneratorRequests(state, true)
|
|
1707
1373
|
.pipe(Effect.ensuring(Effect.sync(() => (state.draining = false))))), Deferred.await(request.response));
|
|
1708
1374
|
}
|
|
@@ -1740,7 +1406,7 @@ export class Interpreter {
|
|
|
1740
1406
|
yield* invocation.completeGeneratorRequests(state, asynchronous);
|
|
1741
1407
|
state.completed = true;
|
|
1742
1408
|
});
|
|
1743
|
-
return Effect.andThen(this.promises.fork(body), Deferred.await(request.response));
|
|
1409
|
+
return Effect.andThen(this.runtime.promises.fork(body), Deferred.await(request.response));
|
|
1744
1410
|
}
|
|
1745
1411
|
return Deferred.await(request.response);
|
|
1746
1412
|
});
|
|
@@ -2018,38 +1684,12 @@ export class Interpreter {
|
|
|
2018
1684
|
}
|
|
2019
1685
|
return new ToolReference([...objectValue.path, key]);
|
|
2020
1686
|
}
|
|
2021
|
-
if (objectValue instanceof
|
|
2022
|
-
if (typeof key === "string" && promiseStatics.has(key)) {
|
|
2023
|
-
return new PromiseMethodReference(key);
|
|
2024
|
-
}
|
|
2025
|
-
throw new InterpreterRuntimeError(`Promise.${String(key)} is not available. Available: Promise.all, Promise.allSettled, Promise.race, Promise.any, Promise.resolve, and Promise.reject; consume promises with await.`, propertyNode);
|
|
2026
|
-
}
|
|
2027
|
-
if (objectValue instanceof SymbolNamespace) {
|
|
2028
|
-
if (key === "asyncIterator")
|
|
2029
|
-
return new ComputedValue(AsyncIteratorSymbol);
|
|
2030
|
-
if (key === "iterator")
|
|
2031
|
-
return new ComputedValue(IteratorSymbol);
|
|
2032
|
-
return new ComputedValue(undefined);
|
|
2033
|
-
}
|
|
2034
|
-
if (objectValue instanceof GlobalNamespace) {
|
|
1687
|
+
if (objectValue instanceof HostFunction || objectValue instanceof HostNamespace) {
|
|
2035
1688
|
if (typeof key === "string" && isBlockedMember(key)) {
|
|
2036
1689
|
throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available.`, propertyNode);
|
|
2037
1690
|
}
|
|
2038
|
-
if (typeof key !== "string")
|
|
2039
|
-
return new ComputedValue(undefined);
|
|
2040
|
-
if (objectValue.name === "Math" && mathConstants.has(key)) {
|
|
2041
|
-
return new ComputedValue(Math[key]);
|
|
2042
|
-
}
|
|
2043
|
-
if (objectValue.name === "JSON") {
|
|
2044
|
-
if (jsonStatics.has(key))
|
|
2045
|
-
return new JsonMethodReference(key);
|
|
2046
|
-
return new ComputedValue(undefined);
|
|
2047
|
-
}
|
|
2048
|
-
if (globalStaticMembers[objectValue.name]?.has(key)) {
|
|
2049
|
-
return new GlobalMethodReference(objectValue.name, key);
|
|
2050
|
-
}
|
|
2051
1691
|
// Unknown static members read as undefined so feature detection works like native JS.
|
|
2052
|
-
return new ComputedValue(
|
|
1692
|
+
return new ComputedValue(objectValue.member(key, propertyNode));
|
|
2053
1693
|
}
|
|
2054
1694
|
if (typeof objectValue === "string") {
|
|
2055
1695
|
if (key === "length")
|
|
@@ -2066,23 +1706,6 @@ export class Interpreter {
|
|
|
2066
1706
|
return new IntrinsicReference(objectValue, key);
|
|
2067
1707
|
return new ComputedValue(undefined);
|
|
2068
1708
|
}
|
|
2069
|
-
if (objectValue instanceof CoercionFunction) {
|
|
2070
|
-
if (typeof key === "string" && isBlockedMember(key)) {
|
|
2071
|
-
throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available.`, propertyNode);
|
|
2072
|
-
}
|
|
2073
|
-
if (typeof key !== "string")
|
|
2074
|
-
return new ComputedValue(undefined);
|
|
2075
|
-
if (objectValue.name === "Number" && numberConstants.has(key)) {
|
|
2076
|
-
return new ComputedValue(Number[key]);
|
|
2077
|
-
}
|
|
2078
|
-
if (objectValue.name === "Number" && numberStatics.has(key)) {
|
|
2079
|
-
return new GlobalMethodReference("Number", key);
|
|
2080
|
-
}
|
|
2081
|
-
if (objectValue.name === "String" && stringStatics.has(key)) {
|
|
2082
|
-
return new GlobalMethodReference("String", key);
|
|
2083
|
-
}
|
|
2084
|
-
return new ComputedValue(undefined);
|
|
2085
|
-
}
|
|
2086
1709
|
if (objectValue instanceof Values.Date) {
|
|
2087
1710
|
if (typeof key === "string" && dateMethods.has(key))
|
|
2088
1711
|
return new IntrinsicReference(objectValue, key);
|