@opencode/codemode 2.0.11 → 2.0.12
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/callback.d.ts +2 -0
- package/dist/interpreter/callback.js +8 -0
- package/dist/interpreter/errors.js +1 -0
- package/dist/interpreter/interpreter.d.ts +1 -1
- package/dist/interpreter/interpreter.js +28 -24
- package/dist/interpreter/intrinsics.d.ts +2 -0
- package/dist/interpreter/intrinsics.js +10 -0
- package/dist/interpreter/model.js +3 -2
- package/dist/stdlib/array.js +8 -1
- package/dist/stdlib/collections.js +25 -0
- package/dist/stdlib/date.js +5 -0
- package/dist/stdlib/number.js +1 -0
- package/dist/stdlib/object.js +2 -2
- package/dist/stdlib/string.js +2 -0
- package/dist/tool-runtime.d.ts +2 -0
- package/dist/tool-runtime.js +2 -0
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@ export declare const preserveConsumerError: <A, R>(cursor: IteratorCursor<R>, ef
|
|
|
14
14
|
* default hint as "string", like their `Symbol.toPrimitive`.
|
|
15
15
|
*/
|
|
16
16
|
export declare const toPrimitive: <R>(ctx: Interpreter<R>, value: unknown, hint: "number" | "string" | "default") => Effect.Effect<unknown, unknown, R>;
|
|
17
|
+
/** Invoke(value, name): calls the method the value would find through its prototype. */
|
|
18
|
+
export declare const invoke: <R>(ctx: Interpreter<R>, value: unknown, name: string, label: string) => Effect.Effect<unknown, unknown, R>;
|
|
17
19
|
export declare const toPrimitiveString: <R>(ctx: Interpreter<R>, value: unknown) => Effect.Effect<string, unknown, R>;
|
|
18
20
|
export declare const toPrimitiveNumber: <R>(ctx: Interpreter<R>, value: unknown) => Effect.Effect<number, unknown, R>;
|
|
19
21
|
export declare const isSupportedCallback: (value: unknown) => value is Callable;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Effect, Exit } from "effect";
|
|
2
2
|
import { coerceToNumber, coerceToString } from "../stdlib/value.js";
|
|
3
|
+
import { primitivePrototype } from "./intrinsics.js";
|
|
3
4
|
import { typeError } from "./model.js";
|
|
4
5
|
import { Callable, get, Native, DateObj, Obj } from "./objects.js";
|
|
5
6
|
import { typeofValue } from "./references.js";
|
|
@@ -27,6 +28,13 @@ export const toPrimitive = (ctx, value, hint) => {
|
|
|
27
28
|
throw typeError("Cannot convert object to primitive value.");
|
|
28
29
|
});
|
|
29
30
|
};
|
|
31
|
+
/** Invoke(value, name): calls the method the value would find through its prototype. */
|
|
32
|
+
export const invoke = (ctx, value, name, label) => {
|
|
33
|
+
const target = value instanceof Obj ? value : primitivePrototype(ctx.builtins, value);
|
|
34
|
+
if (target === undefined)
|
|
35
|
+
throw typeError(`${label} called on null or undefined.`);
|
|
36
|
+
return ctx.call(get(target, name), value, []);
|
|
37
|
+
};
|
|
30
38
|
export const toPrimitiveString = (ctx, value) => Effect.map(toPrimitive(ctx, value, "string"), coerceToString);
|
|
31
39
|
export const toPrimitiveNumber = (ctx, value) => Effect.map(toPrimitive(ctx, value, "number"), coerceToNumber);
|
|
32
40
|
// The single acceptance list for callbacks: collections, sort, string replacers,
|
|
@@ -150,6 +150,7 @@ export const errorGlobal = (type, ctx) => {
|
|
|
150
150
|
methods(builtins, prototype, [
|
|
151
151
|
["toString", 0, (thisValue) => errorToString(receiver(Obj, thisValue, "Error.prototype.toString"))],
|
|
152
152
|
]);
|
|
153
|
+
methods(builtins, ctor, [["isError", 1, (_, args) => args[0] instanceof ErrorObj]]);
|
|
153
154
|
}
|
|
154
155
|
return ctor;
|
|
155
156
|
};
|
|
@@ -2,7 +2,7 @@ import type { Program } from "acorn";
|
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { type Json } from "../data.js";
|
|
4
4
|
import { type ToolRuntime } from "../tool-runtime.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type Builtins } from "./intrinsics.js";
|
|
6
6
|
import { PromiseObj } from "./objects.js";
|
|
7
7
|
import { Pending } from "./promises.js";
|
|
8
8
|
/** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
|
|
@@ -4,6 +4,7 @@ import { ToolReference } from "../tool-runtime.js";
|
|
|
4
4
|
import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, OptionalShortCircuit, invalidData, Throw, rangeError, typeError, unsupportedSyntax, } from "./model.js";
|
|
5
5
|
import { checkStringLength } from "./limits.js";
|
|
6
6
|
import { locate, materialize } from "./errors.js";
|
|
7
|
+
import { primitivePrototype } from "./intrinsics.js";
|
|
7
8
|
import { globals } from "./globals.js";
|
|
8
9
|
import { assign, Callable, define, get, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Bytes, DateObj, Fn, GeneratorObj, IteratorObj, MapObj, Obj, PromiseObj, SetObj, URLSearchParamsObj, HeadersObj, record, remove, set, } from "./objects.js";
|
|
9
10
|
import { preserveConsumerError } from "./callback.js";
|
|
@@ -27,21 +28,27 @@ const loopExit = (result, labels) => {
|
|
|
27
28
|
return result;
|
|
28
29
|
return undefined;
|
|
29
30
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
// Native engines name the callee (`search(...).catch is not a function`), including call chains. Returns
|
|
32
|
+
// undefined when a link cannot be named, so a chain is either named completely or not at all.
|
|
33
|
+
const calleeDescription = (node) => {
|
|
34
|
+
if (node?.type === "Identifier")
|
|
35
|
+
return node.name;
|
|
36
|
+
if (node?.type === "CallExpression") {
|
|
37
|
+
const target = calleeDescription(node.callee);
|
|
38
|
+
return target === undefined ? undefined : `${target}(...)`;
|
|
39
|
+
}
|
|
40
|
+
if (node?.type !== "MemberExpression")
|
|
41
|
+
return undefined;
|
|
42
|
+
const property = node.property;
|
|
43
|
+
const key = !node.computed && property.type === "Identifier"
|
|
44
|
+
? property.name
|
|
45
|
+
: property.type === "Literal" && typeof property.value === "string"
|
|
46
|
+
? property.value
|
|
47
|
+
: undefined;
|
|
48
|
+
if (key === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const object = calleeDescription(node.object);
|
|
51
|
+
return object === undefined ? undefined : `${object}.${key}`;
|
|
45
52
|
};
|
|
46
53
|
// OrdinaryHasInstance: walk the left operand's chain looking for the constructor's `prototype`.
|
|
47
54
|
const instanceofValue = (lhs, rhs, node) => {
|
|
@@ -1025,7 +1032,7 @@ class Frame {
|
|
|
1025
1032
|
// `new` itself is supported, so a non-constructible callee is a TypeError like JS rather than
|
|
1026
1033
|
// unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
|
|
1027
1034
|
// otherwise; say `new` is unsupported for them and point at the plain call.
|
|
1028
|
-
const name = calleeDescription(node.callee);
|
|
1035
|
+
const name = calleeDescription(node.callee) ?? "The called value";
|
|
1029
1036
|
const message = callee instanceof Fn
|
|
1030
1037
|
? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
|
|
1031
1038
|
: callee instanceof Native
|
|
@@ -1312,7 +1319,7 @@ class Frame {
|
|
|
1312
1319
|
if (callable instanceof Native) {
|
|
1313
1320
|
return yield* self.native(() => callable.call(thisValue, args), node);
|
|
1314
1321
|
}
|
|
1315
|
-
throw typeError(`${calleeDescription(callee)} is not a function.`, callee ?? node);
|
|
1322
|
+
throw typeError(`${calleeDescription(callee) ?? "The called value"} is not a function.`, callee ?? node);
|
|
1316
1323
|
});
|
|
1317
1324
|
}
|
|
1318
1325
|
// Built-ins throw without a location, synchronously or inside their Effect; the call site supplies it.
|
|
@@ -1712,20 +1719,17 @@ class Frame {
|
|
|
1712
1719
|
}
|
|
1713
1720
|
if (objectValue instanceof Obj)
|
|
1714
1721
|
return { target: objectValue, key, receiver: objectValue };
|
|
1715
|
-
//
|
|
1716
|
-
const builtins = self.ctx.builtins;
|
|
1722
|
+
// Strings own length and indexes; every other primitive property reads through the wrapper prototype.
|
|
1717
1723
|
if (typeof objectValue === "string") {
|
|
1718
1724
|
if (key === "length")
|
|
1719
1725
|
return { value: objectValue.length };
|
|
1720
1726
|
const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
|
|
1721
1727
|
if (index !== undefined)
|
|
1722
1728
|
return { value: objectValue[index] };
|
|
1723
|
-
return { target: builtins.String, key, receiver: objectValue };
|
|
1724
1729
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
return { target: builtins.Boolean, key, receiver: objectValue };
|
|
1730
|
+
const proto = primitivePrototype(self.ctx.builtins, objectValue);
|
|
1731
|
+
if (proto !== undefined)
|
|
1732
|
+
return { target: proto, key, receiver: objectValue };
|
|
1729
1733
|
if (objectValue === null || objectValue === undefined) {
|
|
1730
1734
|
throw typeError(`Cannot read properties of ${objectValue} (reading '${String(key)}').`, objectNode);
|
|
1731
1735
|
}
|
|
@@ -9,5 +9,7 @@ declare const builtins: readonly ["Object", "Function", "Array", "String", "Numb
|
|
|
9
9
|
*/
|
|
10
10
|
export type Builtins = Readonly<Record<(typeof builtins)[number] | ErrorType, Obj>>;
|
|
11
11
|
export declare const createErrorValue: (prototype: Obj, message: string | undefined) => ErrorObj;
|
|
12
|
+
/** The prototype a primitive reads its methods from without being boxed; none for null, undefined, and symbols. */
|
|
13
|
+
export declare const primitivePrototype: (builtins: Builtins, value: unknown) => Obj | undefined;
|
|
12
14
|
export declare const createBuiltins: () => Builtins;
|
|
13
15
|
export {};
|
|
@@ -40,6 +40,16 @@ export const createErrorValue = (prototype, message) => {
|
|
|
40
40
|
define(value, "message", message, hidden);
|
|
41
41
|
return value;
|
|
42
42
|
};
|
|
43
|
+
/** The prototype a primitive reads its methods from without being boxed; none for null, undefined, and symbols. */
|
|
44
|
+
export const primitivePrototype = (builtins, value) => {
|
|
45
|
+
if (typeof value === "string")
|
|
46
|
+
return builtins.String;
|
|
47
|
+
if (typeof value === "number")
|
|
48
|
+
return builtins.Number;
|
|
49
|
+
if (typeof value === "boolean")
|
|
50
|
+
return builtins.Boolean;
|
|
51
|
+
return undefined;
|
|
52
|
+
};
|
|
43
53
|
export const createBuiltins = () => {
|
|
44
54
|
const object = new Obj(null);
|
|
45
55
|
// Function.prototype is itself callable and returns undefined.
|
|
@@ -52,9 +52,10 @@ export const uriError = failure("URIError");
|
|
|
52
52
|
export const supportedSyntaxMessage = "This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols. Use plain functions and data objects instead.";
|
|
53
53
|
export const unsupportedSyntax = (kind, node) => new PendingThrow("SyntaxError", `Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
|
|
54
54
|
export const isRecord = (value) => typeof value === "object" && value !== null;
|
|
55
|
+
// Acorn lines are 1-based and its columns are 0-based. Diagnostics use 1-based columns of the submitted source.
|
|
55
56
|
export const sourceLocation = (node) => ({
|
|
56
|
-
line:
|
|
57
|
-
column:
|
|
57
|
+
line: node.loc?.start.line ?? 1,
|
|
58
|
+
column: (node.loc?.start.column ?? 0) + 1,
|
|
58
59
|
});
|
|
59
60
|
export const formatLocation = (node) => {
|
|
60
61
|
if (!node?.loc)
|
package/dist/stdlib/array.js
CHANGED
|
@@ -4,7 +4,7 @@ import { checkArrayLength, checkStringLength, MAX_ARRAY_LENGTH } from "../interp
|
|
|
4
4
|
import { invalidData, IteratorSymbol, rangeError, typeError } from "../interpreter/model.js";
|
|
5
5
|
import { define, get, hidden, Arr, GeneratorObj, IteratorObj, Obj } from "../interpreter/objects.js";
|
|
6
6
|
import { describeValue, rejectCircularInsertion } from "../interpreter/references.js";
|
|
7
|
-
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/callback.js";
|
|
7
|
+
import { applyCollectionCallback, invoke, preserveConsumerError } from "../interpreter/callback.js";
|
|
8
8
|
import { compareText } from "../tool-runtime.js";
|
|
9
9
|
import { coerceToNumber, coerceToString } from "./value.js";
|
|
10
10
|
const arrayLikeSource = (source) => {
|
|
@@ -317,6 +317,13 @@ export const arrayGlobal = (ctx) => {
|
|
|
317
317
|
return target;
|
|
318
318
|
},
|
|
319
319
|
],
|
|
320
|
+
[
|
|
321
|
+
"toLocaleString",
|
|
322
|
+
0,
|
|
323
|
+
(thisValue) => Effect.map(Effect.forEach(self(thisValue, "toLocaleString").items, (item) => item === null || item === undefined
|
|
324
|
+
? Effect.succeed("")
|
|
325
|
+
: Effect.map(invoke(ctx, item, "toLocaleString", "Array.prototype.toLocaleString"), coerceToString)), (parts) => parts.join(",")),
|
|
326
|
+
],
|
|
320
327
|
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").items.keys())],
|
|
321
328
|
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").items.values())],
|
|
322
329
|
[
|
|
@@ -123,6 +123,31 @@ export const mapGlobal = (ctx) => {
|
|
|
123
123
|
return target;
|
|
124
124
|
},
|
|
125
125
|
],
|
|
126
|
+
[
|
|
127
|
+
"getOrInsert",
|
|
128
|
+
2,
|
|
129
|
+
(thisValue, args) => {
|
|
130
|
+
const target = self(thisValue, "getOrInsert").map;
|
|
131
|
+
if (!target.has(args[0]))
|
|
132
|
+
target.set(args[0], args[1]);
|
|
133
|
+
return target.get(args[0]);
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
[
|
|
137
|
+
"getOrInsertComputed",
|
|
138
|
+
2,
|
|
139
|
+
(thisValue, args) => {
|
|
140
|
+
const target = self(thisValue, "getOrInsertComputed").map;
|
|
141
|
+
const apply = applyCollectionCallback(ctx, args[1], "Map.getOrInsertComputed");
|
|
142
|
+
if (target.has(args[0]))
|
|
143
|
+
return target.get(args[0]);
|
|
144
|
+
// The callback sees the stored key (-0 is +0) and its result wins over anything it inserted itself.
|
|
145
|
+
return Effect.map(apply([args[0] === 0 ? 0 : args[0]]), (value) => {
|
|
146
|
+
target.set(args[0], value);
|
|
147
|
+
return value;
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
],
|
|
126
151
|
["delete", 1, (thisValue, args) => self(thisValue, "delete").map.delete(args[0])],
|
|
127
152
|
[
|
|
128
153
|
"clear",
|
package/dist/stdlib/date.js
CHANGED
|
@@ -92,6 +92,11 @@ export const dateGlobal = (ctx) => {
|
|
|
92
92
|
["toTimeString", 0, (thisValue) => new Date(self(thisValue, "toTimeString").time).toTimeString()],
|
|
93
93
|
["toUTCString", 0, (thisValue) => new Date(self(thisValue, "toUTCString").time).toUTCString()],
|
|
94
94
|
["toGMTString", 0, (thisValue) => new Date(self(thisValue, "toGMTString").time).toUTCString()],
|
|
95
|
+
...["toLocaleString", "toLocaleDateString", "toLocaleTimeString"].map((name) => [
|
|
96
|
+
name,
|
|
97
|
+
0,
|
|
98
|
+
(thisValue) => new Date(self(thisValue, name).time)[name]("en-US", { timeZone: "UTC" }),
|
|
99
|
+
]),
|
|
95
100
|
...getters.map((name) => [name, 0, (thisValue) => new Date(self(thisValue, name).time)[name]()]),
|
|
96
101
|
...setters.map(([name, length]) => [
|
|
97
102
|
name,
|
package/dist/stdlib/number.js
CHANGED
|
@@ -50,6 +50,7 @@ export const numberGlobal = (ctx) => {
|
|
|
50
50
|
};
|
|
51
51
|
methods(builtins, builtins.Number, [
|
|
52
52
|
["toFixed", 1, (thisValue, args) => self(thisValue, "toFixed").toFixed(optNum("toFixed", args[0]))],
|
|
53
|
+
["toLocaleString", 0, (thisValue) => self(thisValue, "toLocaleString").toLocaleString("en-US")],
|
|
53
54
|
[
|
|
54
55
|
"toExponential",
|
|
55
56
|
1,
|
package/dist/stdlib/object.js
CHANGED
|
@@ -3,7 +3,7 @@ import { constructor, methods, receiver } from "../interpreter/native.js";
|
|
|
3
3
|
import { AsyncIteratorSymbol, invalidData, IteratorSymbol, rangeError, typeError, } from "../interpreter/model.js";
|
|
4
4
|
import { Callable, define, entries, enumerableKeys, getOwn, hasOwn, hasPrototype, hidden, keys, own, Arr, Bytes, DateObj, ErrorObj, Obj, PromiseObj, RegExpObj, set, } from "../interpreter/objects.js";
|
|
5
5
|
import { containsOpaqueReference, describeValue, rejectCircularInsertion } from "../interpreter/references.js";
|
|
6
|
-
import { preserveConsumerError } from "../interpreter/callback.js";
|
|
6
|
+
import { invoke, preserveConsumerError } from "../interpreter/callback.js";
|
|
7
7
|
import { ToolReference } from "../tool-runtime.js";
|
|
8
8
|
import { groupBy } from "./collections.js";
|
|
9
9
|
import { coerceToString } from "./value.js";
|
|
@@ -161,7 +161,7 @@ export const objectGlobal = (ctx) => {
|
|
|
161
161
|
true,
|
|
162
162
|
],
|
|
163
163
|
["toString", 0, (thisValue) => `[object ${classTag(thisValue)}]`],
|
|
164
|
-
["toLocaleString", 0, (thisValue) =>
|
|
164
|
+
["toLocaleString", 0, (thisValue) => invoke(ctx, thisValue, "toString", "Object.prototype.toLocaleString")],
|
|
165
165
|
[
|
|
166
166
|
"valueOf",
|
|
167
167
|
0,
|
package/dist/stdlib/string.js
CHANGED
|
@@ -130,6 +130,8 @@ export const stringGlobal = (ctx) => {
|
|
|
130
130
|
simple("valueOf", 0, (value) => value),
|
|
131
131
|
simple("toLowerCase", 0, (value) => value.toLowerCase()),
|
|
132
132
|
simple("toUpperCase", 0, (value) => value.toUpperCase()),
|
|
133
|
+
simple("toLocaleLowerCase", 0, (value) => value.toLowerCase()),
|
|
134
|
+
simple("toLocaleUpperCase", 0, (value) => value.toUpperCase()),
|
|
133
135
|
simple("trim", 0, (value) => value.trim()),
|
|
134
136
|
simple("trimStart", 0, (value) => value.trimStart()),
|
|
135
137
|
simple("trimLeft", 0, (value) => value.trimStart()),
|
package/dist/tool-runtime.d.ts
CHANGED
|
@@ -66,6 +66,8 @@ export type Prepared<R = never> = {
|
|
|
66
66
|
};
|
|
67
67
|
export type SearchEntry = {
|
|
68
68
|
readonly description: ToolDescription;
|
|
69
|
+
/** The path split into words, so `zones` matches `get_zones` as a word rather than as a substring of `timezones`. */
|
|
70
|
+
readonly pathWords: ReadonlyArray<string>;
|
|
69
71
|
readonly searchText: string;
|
|
70
72
|
};
|
|
71
73
|
/** Exact callable signature of the built-in `search` function, for host-owned instructions. */
|
package/dist/tool-runtime.js
CHANGED
|
@@ -136,6 +136,7 @@ const makeSearchTool = (searchIndex) => ({
|
|
|
136
136
|
const description = entry.description.description.toLowerCase();
|
|
137
137
|
const score = terms.reduce((total, forms) => total +
|
|
138
138
|
(forms.some((form) => path === form || path.endsWith(`.${form}`)) ? 20 : 0) +
|
|
139
|
+
(forms.some((form) => entry.pathWords.includes(form)) ? 12 : 0) +
|
|
139
140
|
(forms.some((form) => path.includes(form)) ? 8 : 0) +
|
|
140
141
|
(forms.some((form) => description.includes(form)) ? 4 : 0) +
|
|
141
142
|
(forms.some((form) => entry.searchText.includes(form)) ? 2 : 0), 0);
|
|
@@ -163,6 +164,7 @@ export const searchSignature = (() => {
|
|
|
163
164
|
})();
|
|
164
165
|
const toSearchEntry = (visible) => ({
|
|
165
166
|
description: describeTool(visible),
|
|
167
|
+
pathWords: tokenize(visible.path),
|
|
166
168
|
searchText: [
|
|
167
169
|
visible.path,
|
|
168
170
|
visible.tool.description,
|
package/package.json
CHANGED