@opencode/codemode 2.0.10 → 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/README.md +14 -6
- package/dist/data.js +3 -1
- 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/extensions.js +6 -1
- package/dist/interpreter/globals.js +4 -0
- package/dist/interpreter/interpreter.d.ts +7 -1
- package/dist/interpreter/interpreter.js +65 -51
- package/dist/interpreter/intrinsics.d.ts +3 -1
- package/dist/interpreter/intrinsics.js +12 -0
- package/dist/interpreter/model.js +3 -2
- package/dist/interpreter/objects.d.ts +10 -1
- package/dist/interpreter/objects.js +16 -0
- package/dist/interpreter/references.js +6 -1
- package/dist/stdlib/array.js +16 -6
- package/dist/stdlib/bytes.js +8 -5
- package/dist/stdlib/collections.js +41 -8
- package/dist/stdlib/console.js +3 -1
- package/dist/stdlib/date.js +5 -0
- package/dist/stdlib/headers.d.ts +2 -0
- package/dist/stdlib/headers.js +127 -0
- package/dist/stdlib/iterator.d.ts +2 -0
- package/dist/stdlib/iterator.js +17 -0
- package/dist/stdlib/number.js +1 -0
- package/dist/stdlib/object.js +2 -2
- package/dist/stdlib/string.js +6 -3
- package/dist/stdlib/url.d.ts +6 -0
- package/dist/stdlib/url.js +33 -23
- package/dist/stdlib/value.js +3 -1
- package/dist/tool-runtime.d.ts +2 -0
- package/dist/tool-runtime.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,8 +13,8 @@ The idea of code mode was originally introduced by Cloudflare. See
|
|
|
13
13
|
|
|
14
14
|
## How it differs from JavaScript
|
|
15
15
|
|
|
16
|
-
- **Only supported APIs are available.** Programs can use the provided tools
|
|
17
|
-
|
|
16
|
+
- **Only supported APIs are available.** Programs can use the provided tools, supported JavaScript built-ins, and the
|
|
17
|
+
globals the host adds through extensions. Timers, `process`, filesystem access, imports, and modules are unavailable.
|
|
18
18
|
- **Unfinished work is interrupted.** Tool calls and async functions start when called. When the program finishes,
|
|
19
19
|
anything still running is interrupted. Unhandled rejections from un-awaited promises are returned as warnings.
|
|
20
20
|
- **REPL-style results.** Without an explicit `return`, the final top-level expression becomes the result. `undefined`
|
|
@@ -94,11 +94,19 @@ receive `{ extension, name, args }`. An `after` hook also receives how the call
|
|
|
94
94
|
`failure` with its error, or `interrupted`). A failing `before` hook denies the call, and the program catches the
|
|
95
95
|
failure as a thrown error.
|
|
96
96
|
|
|
97
|
-
### `
|
|
97
|
+
### `Extension.make`
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
Extensions are host functions a program calls directly as globals, such as `fetch`. Unlike tools they are not in the
|
|
100
|
+
catalog, not counted against `maxToolCalls`, and not described to the model; the host decides what they mean.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const web = Extension.make({ name: "web", globals: { fetch: (url: string) => globalThis.fetch(url) } })
|
|
104
|
+
const runtime = CodeMode.make({ tools, extensions: [web] })
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Every value crossing in either direction is converted, never shared: arguments come in as copies, results go out as
|
|
108
|
+
copies, and a function inside a result is callable the same way. A global that shadows a built-in or another
|
|
109
|
+
extension throws at `CodeMode.make`.
|
|
102
110
|
|
|
103
111
|
### OpenAPI tools
|
|
104
112
|
|
package/dist/data.js
CHANGED
|
@@ -2,7 +2,7 @@ export * as Data from "./data.js";
|
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { MAX_VALUE_DEPTH } from "./interpreter/limits.js";
|
|
4
4
|
import { invalidData, rangeError, typeError } from "./interpreter/model.js";
|
|
5
|
-
import { Arr, Bytes, Callable, define, ErrorObj, get, keys, Obj, PromiseObj, record, SetObj, URLSearchParamsObj, } from "./interpreter/objects.js";
|
|
5
|
+
import { Arr, Bytes, Callable, define, ErrorObj, get, keys, Obj, PromiseObj, record, SetObj, URLSearchParamsObj, HeadersObj, } from "./interpreter/objects.js";
|
|
6
6
|
import { typeofValue } from "./interpreter/references.js";
|
|
7
7
|
/**
|
|
8
8
|
* What `JSON.stringify` would serialize for a program value, as host JSON: `toJSON` is honored, functions and
|
|
@@ -42,6 +42,8 @@ const walk = (ctx, value, replacer, boundary) => {
|
|
|
42
42
|
}
|
|
43
43
|
if (boundary && value instanceof URLSearchParamsObj)
|
|
44
44
|
return value.params.toString();
|
|
45
|
+
if (value instanceof HeadersObj)
|
|
46
|
+
return Object.fromEntries(value.headers);
|
|
45
47
|
const target = boundary && value instanceof SetObj ? new Arr(ctx.builtins.Array, [...value.set]) : value;
|
|
46
48
|
if (stack.has(target))
|
|
47
49
|
throw typeError("Converting circular structure to JSON.");
|
|
@@ -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
|
};
|
|
@@ -5,7 +5,7 @@ import { createErrorValue, isErrorType } from "./intrinsics.js";
|
|
|
5
5
|
import { MAX_VALUE_DEPTH } from "./limits.js";
|
|
6
6
|
import { PendingThrow, Throw, typeError } from "./model.js";
|
|
7
7
|
import { fn } from "./native.js";
|
|
8
|
-
import { Callable, define, entries, get, has, hidden, keys, Arr, Bytes, DateObj, ErrorObj, GeneratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "./objects.js";
|
|
8
|
+
import { Callable, define, entries, get, has, hidden, keys, Arr, Bytes, DateObj, ErrorObj, GeneratorObj, IteratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, HeadersObj, } from "./objects.js";
|
|
9
9
|
import { describeValue } from "./references.js";
|
|
10
10
|
/**
|
|
11
11
|
* The global bindings of one run's extensions. Everything crossing the boundary is converted: plain data and
|
|
@@ -32,6 +32,8 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
32
32
|
return new URL(value.url.href);
|
|
33
33
|
if (value instanceof URLSearchParamsObj)
|
|
34
34
|
return new URLSearchParams(value.params);
|
|
35
|
+
if (value instanceof HeadersObj)
|
|
36
|
+
return new Headers(value.headers);
|
|
35
37
|
const next = (item) => toHost(item, label, depth + 1, seen);
|
|
36
38
|
if (value instanceof MapObj)
|
|
37
39
|
return new Map([...value.map].map(([key, item]) => [next(key), next(item)]));
|
|
@@ -40,6 +42,7 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
40
42
|
if (!(value instanceof Obj) ||
|
|
41
43
|
value instanceof Callable ||
|
|
42
44
|
value instanceof GeneratorObj ||
|
|
45
|
+
value instanceof IteratorObj ||
|
|
43
46
|
value instanceof PromiseObj) {
|
|
44
47
|
throw typeError(`${label} contains ${describeValue(value)}, which cannot be passed to an extension.`);
|
|
45
48
|
}
|
|
@@ -114,6 +117,8 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
114
117
|
if (value instanceof URLSearchParams) {
|
|
115
118
|
return new URLSearchParamsObj(builtins.URLSearchParams, new URLSearchParams(value));
|
|
116
119
|
}
|
|
120
|
+
if (value instanceof Headers)
|
|
121
|
+
return new HeadersObj(builtins.Headers, new Headers(value));
|
|
117
122
|
if (value instanceof Map) {
|
|
118
123
|
const wrapped = new MapObj(builtins.Map);
|
|
119
124
|
for (const [key, item] of value)
|
|
@@ -11,6 +11,8 @@ import { objectGlobal } from "../stdlib/object.js";
|
|
|
11
11
|
import { regexpGlobal } from "../stdlib/regexp.js";
|
|
12
12
|
import { stringGlobal } from "../stdlib/string.js";
|
|
13
13
|
import { uriGlobal, urlGlobal, urlSearchParamsGlobal } from "../stdlib/url.js";
|
|
14
|
+
import { headersGlobal } from "../stdlib/headers.js";
|
|
15
|
+
import { iteratorGlobals } from "../stdlib/iterator.js";
|
|
14
16
|
import { coercion } from "../stdlib/value.js";
|
|
15
17
|
import { base64Global, cryptoGlobal } from "../stdlib/web.js";
|
|
16
18
|
import { ToolReference } from "../tool-runtime.js";
|
|
@@ -71,6 +73,7 @@ const table = {
|
|
|
71
73
|
Set: (ctx) => setGlobal(ctx),
|
|
72
74
|
URL: (ctx) => urlGlobal(ctx),
|
|
73
75
|
URLSearchParams: (ctx) => urlSearchParamsGlobal(ctx),
|
|
76
|
+
Headers: (ctx) => headersGlobal(ctx),
|
|
74
77
|
Uint8Array: (ctx) => uint8ArrayGlobal(ctx),
|
|
75
78
|
TextEncoder: (ctx) => textEncoderGlobal(ctx),
|
|
76
79
|
TextDecoder: (ctx) => textDecoderGlobal(ctx),
|
|
@@ -88,5 +91,6 @@ export const globalNames = new Set(Object.keys(table));
|
|
|
88
91
|
/** The immutable global bindings of every program, in declaration order. */
|
|
89
92
|
export const globals = (ctx) => {
|
|
90
93
|
generatorGlobals(ctx);
|
|
94
|
+
iteratorGlobals(ctx);
|
|
91
95
|
return Object.entries(table).map(([name, factory]) => [name, factory(ctx)]);
|
|
92
96
|
};
|
|
@@ -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. */
|
|
@@ -23,6 +23,12 @@ export declare class Interpreter<R> {
|
|
|
23
23
|
call(callable: unknown, thisValue: unknown, args: Array<unknown>): Effect.Effect<unknown, unknown, R>;
|
|
24
24
|
await(promise: PromiseObj): Effect.Effect<unknown, unknown, never>;
|
|
25
25
|
iterate(value: unknown): Effect.Effect<{
|
|
26
|
+
next: Effect.Effect<{
|
|
27
|
+
done: boolean;
|
|
28
|
+
value: any;
|
|
29
|
+
}, never, never>;
|
|
30
|
+
close: Effect.Effect<void, never, never>;
|
|
31
|
+
}, never, never> | Effect.Effect<{
|
|
26
32
|
next: Effect.Effect<{
|
|
27
33
|
done: boolean;
|
|
28
34
|
value: unknown;
|
|
@@ -4,8 +4,9 @@ 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
|
-
import { assign, Callable, define, get, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Bytes, DateObj, Fn, GeneratorObj, MapObj, Obj, PromiseObj, SetObj, URLSearchParamsObj, record, remove, set, } from "./objects.js";
|
|
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";
|
|
10
11
|
import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
|
|
11
12
|
import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.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) => {
|
|
@@ -477,10 +484,10 @@ class Frame {
|
|
|
477
484
|
if (declared?.lexical)
|
|
478
485
|
self.predeclarePattern(declared.pattern, declared.mutable, left);
|
|
479
486
|
const right = yield* self.evaluateExpression(node.right);
|
|
480
|
-
const
|
|
481
|
-
const
|
|
487
|
+
const cursor = self.hostCursor(right);
|
|
488
|
+
const iterator = cursor === undefined ? yield* self.customIterator(right, node, awaiting) : undefined;
|
|
482
489
|
if (iterator === undefined && cursor === undefined) {
|
|
483
|
-
throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or
|
|
490
|
+
throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, URLSearchParams, or Headers, or custom iterator value.`, node);
|
|
484
491
|
}
|
|
485
492
|
const close = () => iterator
|
|
486
493
|
? self.closeIterator(iterator, node, awaiting)
|
|
@@ -550,6 +557,18 @@ class Frame {
|
|
|
550
557
|
});
|
|
551
558
|
}
|
|
552
559
|
iterate(value, node) {
|
|
560
|
+
const cursor = this.hostCursor(value);
|
|
561
|
+
if (cursor !== undefined)
|
|
562
|
+
return Effect.succeed(cursor);
|
|
563
|
+
const self = this;
|
|
564
|
+
return Effect.map(this.customIterator(value, node, false), (iterator) => iterator === undefined
|
|
565
|
+
? undefined
|
|
566
|
+
: {
|
|
567
|
+
next: self.nextIteratorResult(iterator, node, false),
|
|
568
|
+
close: Effect.suspend(() => self.closeIterator(iterator, node, false)),
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
hostCursor(value) {
|
|
553
572
|
const iterator = value instanceof Arr
|
|
554
573
|
? value.items[Symbol.iterator]()
|
|
555
574
|
: typeof value === "string"
|
|
@@ -560,29 +579,26 @@ class Frame {
|
|
|
560
579
|
? value.set.values()
|
|
561
580
|
: value instanceof URLSearchParamsObj
|
|
562
581
|
? value.params.entries()
|
|
563
|
-
: value instanceof
|
|
564
|
-
? value.
|
|
565
|
-
:
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
next: self.nextIteratorResult(iterator, node, false),
|
|
584
|
-
close: Effect.suspend(() => self.closeIterator(iterator, node, false)),
|
|
585
|
-
});
|
|
582
|
+
: value instanceof HeadersObj
|
|
583
|
+
? value.headers.entries()
|
|
584
|
+
: value instanceof Bytes
|
|
585
|
+
? value.bytes.values()
|
|
586
|
+
: value instanceof IteratorObj
|
|
587
|
+
? value.iterator
|
|
588
|
+
: undefined;
|
|
589
|
+
if (iterator === undefined)
|
|
590
|
+
return undefined;
|
|
591
|
+
const proto = this.ctx.builtins.Array;
|
|
592
|
+
return {
|
|
593
|
+
next: Effect.sync(() => {
|
|
594
|
+
const step = iterator.next();
|
|
595
|
+
return {
|
|
596
|
+
done: Boolean(step.done),
|
|
597
|
+
value: Array.isArray(step.value) ? new Arr(proto, step.value) : step.value,
|
|
598
|
+
};
|
|
599
|
+
}),
|
|
600
|
+
close: Effect.void,
|
|
601
|
+
};
|
|
586
602
|
}
|
|
587
603
|
customIterator(value, node, allowAsync = true) {
|
|
588
604
|
if (!(value instanceof Obj))
|
|
@@ -1016,7 +1032,7 @@ class Frame {
|
|
|
1016
1032
|
// `new` itself is supported, so a non-constructible callee is a TypeError like JS rather than
|
|
1017
1033
|
// unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
|
|
1018
1034
|
// otherwise; say `new` is unsupported for them and point at the plain call.
|
|
1019
|
-
const name = calleeDescription(node.callee);
|
|
1035
|
+
const name = calleeDescription(node.callee) ?? "The called value";
|
|
1020
1036
|
const message = callee instanceof Fn
|
|
1021
1037
|
? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
|
|
1022
1038
|
: callee instanceof Native
|
|
@@ -1303,7 +1319,7 @@ class Frame {
|
|
|
1303
1319
|
if (callable instanceof Native) {
|
|
1304
1320
|
return yield* self.native(() => callable.call(thisValue, args), node);
|
|
1305
1321
|
}
|
|
1306
|
-
throw typeError(`${calleeDescription(callee)} is not a function.`, callee ?? node);
|
|
1322
|
+
throw typeError(`${calleeDescription(callee) ?? "The called value"} is not a function.`, callee ?? node);
|
|
1307
1323
|
});
|
|
1308
1324
|
}
|
|
1309
1325
|
// Built-ins throw without a location, synchronously or inside their Effect; the call site supplies it.
|
|
@@ -1513,6 +1529,7 @@ class Frame {
|
|
|
1513
1529
|
value instanceof MapObj ||
|
|
1514
1530
|
value instanceof SetObj ||
|
|
1515
1531
|
value instanceof URLSearchParamsObj ||
|
|
1532
|
+
value instanceof HeadersObj ||
|
|
1516
1533
|
value instanceof Bytes) {
|
|
1517
1534
|
const cursor = yield* self.iterate(value, node);
|
|
1518
1535
|
if (!cursor)
|
|
@@ -1702,20 +1719,17 @@ class Frame {
|
|
|
1702
1719
|
}
|
|
1703
1720
|
if (objectValue instanceof Obj)
|
|
1704
1721
|
return { target: objectValue, key, receiver: objectValue };
|
|
1705
|
-
//
|
|
1706
|
-
const builtins = self.ctx.builtins;
|
|
1722
|
+
// Strings own length and indexes; every other primitive property reads through the wrapper prototype.
|
|
1707
1723
|
if (typeof objectValue === "string") {
|
|
1708
1724
|
if (key === "length")
|
|
1709
1725
|
return { value: objectValue.length };
|
|
1710
1726
|
const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
|
|
1711
1727
|
if (index !== undefined)
|
|
1712
1728
|
return { value: objectValue[index] };
|
|
1713
|
-
return { target: builtins.String, key, receiver: objectValue };
|
|
1714
1729
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
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 };
|
|
1719
1733
|
if (objectValue === null || objectValue === undefined) {
|
|
1720
1734
|
throw typeError(`Cannot read properties of ${objectValue} (reading '${String(key)}').`, objectNode);
|
|
1721
1735
|
}
|
|
@@ -2,12 +2,14 @@ import { ErrorObj, Obj } from "./objects.js";
|
|
|
2
2
|
export declare const errorTypes: readonly ["Error", "TypeError", "RangeError", "SyntaxError", "ReferenceError", "EvalError", "URIError", "AggregateError"];
|
|
3
3
|
export type ErrorType = (typeof errorTypes)[number];
|
|
4
4
|
export declare const isErrorType: (name: string) => name is ErrorType;
|
|
5
|
-
declare const builtins: readonly ["Object", "Function", "Array", "String", "Number", "Boolean", "Date", "RegExp", "Map", "Set", "URL", "URLSearchParams", "Uint8Array", "TextEncoder", "TextDecoder", "Promise", "Iterator", "AsyncIterator", "Generator", "AsyncGenerator"];
|
|
5
|
+
declare const builtins: readonly ["Object", "Function", "Array", "String", "Number", "Boolean", "Date", "RegExp", "Map", "Set", "URL", "URLSearchParams", "Headers", "Uint8Array", "TextEncoder", "TextDecoder", "Promise", "Iterator", "AsyncIterator", "Generator", "AsyncGenerator"];
|
|
6
6
|
/**
|
|
7
7
|
* The built-in prototype objects of one runtime, allocated empty in dependency order. The globals populate them
|
|
8
8
|
* and attach their constructors when the runtime is built.
|
|
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 {};
|
|
@@ -24,6 +24,7 @@ const builtins = [
|
|
|
24
24
|
"Set",
|
|
25
25
|
"URL",
|
|
26
26
|
"URLSearchParams",
|
|
27
|
+
"Headers",
|
|
27
28
|
"Uint8Array",
|
|
28
29
|
"TextEncoder",
|
|
29
30
|
"TextDecoder",
|
|
@@ -39,6 +40,16 @@ export const createErrorValue = (prototype, message) => {
|
|
|
39
40
|
define(value, "message", message, hidden);
|
|
40
41
|
return value;
|
|
41
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
|
+
};
|
|
42
53
|
export const createBuiltins = () => {
|
|
43
54
|
const object = new Obj(null);
|
|
44
55
|
// Function.prototype is itself callable and returns undefined.
|
|
@@ -68,6 +79,7 @@ export const createBuiltins = () => {
|
|
|
68
79
|
Set: plain(),
|
|
69
80
|
URL: plain(),
|
|
70
81
|
URLSearchParams: plain(),
|
|
82
|
+
Headers: plain(),
|
|
71
83
|
Uint8Array: plain(),
|
|
72
84
|
TextEncoder: plain(),
|
|
73
85
|
TextDecoder: plain(),
|
|
@@ -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)
|
|
@@ -81,6 +81,11 @@ export declare class GeneratorObj extends Obj {
|
|
|
81
81
|
readonly request: (kind: GeneratorRequestKind, value: unknown) => Effect.Effect<unknown, unknown, unknown>;
|
|
82
82
|
constructor(proto: Obj, asynchronous: boolean, request: (kind: GeneratorRequestKind, value: unknown) => Effect.Effect<unknown, unknown, unknown>);
|
|
83
83
|
}
|
|
84
|
+
/** A built-in collection iterator: live over the host collection, yielding program values. */
|
|
85
|
+
export declare class IteratorObj extends Obj {
|
|
86
|
+
readonly iterator: IteratorObject<unknown>;
|
|
87
|
+
constructor(proto: Obj, iterator: IteratorObject<unknown>);
|
|
88
|
+
}
|
|
84
89
|
export declare class DateObj extends Obj {
|
|
85
90
|
time: number;
|
|
86
91
|
constructor(proto: Obj, time: number);
|
|
@@ -99,6 +104,10 @@ export declare class URLSearchParamsObj extends Obj {
|
|
|
99
104
|
readonly params: URLSearchParams;
|
|
100
105
|
constructor(proto: Obj, params: URLSearchParams);
|
|
101
106
|
}
|
|
107
|
+
export declare class HeadersObj extends Obj {
|
|
108
|
+
readonly headers: Headers;
|
|
109
|
+
constructor(proto: Obj, headers: Headers);
|
|
110
|
+
}
|
|
102
111
|
export declare class URLObj extends Obj {
|
|
103
112
|
readonly url: URL;
|
|
104
113
|
readonly searchParams: URLSearchParamsObj;
|
|
@@ -110,7 +119,7 @@ export declare class Bytes extends Obj {
|
|
|
110
119
|
constructor(proto: Obj, bytes: Uint8Array);
|
|
111
120
|
}
|
|
112
121
|
/** Built-in objects that wrap a host value; data-like, but never plain data. */
|
|
113
|
-
export declare const isWrapper: (value: unknown) => value is DateObj | RegExpObj | MapObj | SetObj | URLObj | URLSearchParamsObj | Bytes;
|
|
122
|
+
export declare const isWrapper: (value: unknown) => value is DateObj | RegExpObj | MapObj | SetObj | URLObj | URLSearchParamsObj | HeadersObj | Bytes;
|
|
114
123
|
export declare const parseArrayIndex: (key: string | number) => number | undefined;
|
|
115
124
|
/** The own property under `key`, including an array's live indexes and `length`. */
|
|
116
125
|
export declare const own: (target: Obj, key: PropertyKey) => Slot | undefined;
|
|
@@ -78,6 +78,14 @@ export class GeneratorObj extends Obj {
|
|
|
78
78
|
this.request = request;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
/** A built-in collection iterator: live over the host collection, yielding program values. */
|
|
82
|
+
export class IteratorObj extends Obj {
|
|
83
|
+
iterator;
|
|
84
|
+
constructor(proto, iterator) {
|
|
85
|
+
super(proto);
|
|
86
|
+
this.iterator = iterator;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
81
89
|
export class DateObj extends Obj {
|
|
82
90
|
time;
|
|
83
91
|
constructor(proto, time) {
|
|
@@ -105,6 +113,13 @@ export class URLSearchParamsObj extends Obj {
|
|
|
105
113
|
this.params = params;
|
|
106
114
|
}
|
|
107
115
|
}
|
|
116
|
+
export class HeadersObj extends Obj {
|
|
117
|
+
headers;
|
|
118
|
+
constructor(proto, headers) {
|
|
119
|
+
super(proto);
|
|
120
|
+
this.headers = headers;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
108
123
|
export class URLObj extends Obj {
|
|
109
124
|
url;
|
|
110
125
|
searchParams;
|
|
@@ -129,6 +144,7 @@ export const isWrapper = (value) => value instanceof DateObj ||
|
|
|
129
144
|
value instanceof SetObj ||
|
|
130
145
|
value instanceof URLObj ||
|
|
131
146
|
value instanceof URLSearchParamsObj ||
|
|
147
|
+
value instanceof HeadersObj ||
|
|
132
148
|
value instanceof Bytes;
|
|
133
149
|
const MAX_ARRAY_INDEX = 4_294_967_295;
|
|
134
150
|
export const parseArrayIndex = (key) => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ToolReference } from "../tool-runtime.js";
|
|
2
2
|
import { invalidData } from "./model.js";
|
|
3
|
-
import { Callable, getOwn, isWrapper, ownKeys, Arr, Bytes, DateObj, GeneratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "./objects.js";
|
|
3
|
+
import { Callable, getOwn, isWrapper, ownKeys, Arr, Bytes, DateObj, GeneratorObj, IteratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, HeadersObj, } from "./objects.js";
|
|
4
4
|
/** Values that cannot cross the data boundary. */
|
|
5
5
|
export const isRuntimeReference = (value) => value instanceof Callable ||
|
|
6
6
|
value instanceof GeneratorObj ||
|
|
7
|
+
value instanceof IteratorObj ||
|
|
7
8
|
value instanceof ToolReference ||
|
|
8
9
|
value instanceof PromiseObj ||
|
|
9
10
|
isWrapper(value);
|
|
@@ -63,10 +64,14 @@ export const describeValue = (value) => {
|
|
|
63
64
|
return "a URL";
|
|
64
65
|
if (value instanceof URLSearchParamsObj)
|
|
65
66
|
return "a URLSearchParams";
|
|
67
|
+
if (value instanceof HeadersObj)
|
|
68
|
+
return "a Headers";
|
|
66
69
|
if (value instanceof Bytes)
|
|
67
70
|
return "a Uint8Array";
|
|
68
71
|
if (value instanceof GeneratorObj)
|
|
69
72
|
return "a generator";
|
|
73
|
+
if (value instanceof IteratorObj)
|
|
74
|
+
return "an iterator";
|
|
70
75
|
if (isRuntimeReference(value))
|
|
71
76
|
return "a function";
|
|
72
77
|
if (typeof value === "object")
|
package/dist/stdlib/array.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, methods, prototypeFrom, receiver } from "../interpreter/native.js";
|
|
3
3
|
import { checkArrayLength, checkStringLength, MAX_ARRAY_LENGTH } from "../interpreter/limits.js";
|
|
4
|
-
import { invalidData, rangeError, typeError } from "../interpreter/model.js";
|
|
5
|
-
import { get, Arr, GeneratorObj, Obj } from "../interpreter/objects.js";
|
|
4
|
+
import { invalidData, IteratorSymbol, rangeError, typeError } from "../interpreter/model.js";
|
|
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,12 +317,21 @@ export const arrayGlobal = (ctx) => {
|
|
|
317
317
|
return target;
|
|
318
318
|
},
|
|
319
319
|
],
|
|
320
|
-
[
|
|
321
|
-
|
|
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
|
+
],
|
|
327
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").items.keys())],
|
|
328
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").items.values())],
|
|
322
329
|
[
|
|
323
330
|
"entries",
|
|
324
331
|
0,
|
|
325
|
-
(thisValue) =>
|
|
332
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
333
|
+
.items.entries()
|
|
334
|
+
.map(([index, item]) => wrap([index, item]))),
|
|
326
335
|
],
|
|
327
336
|
iterate("map", 1, (target, receiver, apply) => Effect.gen(function* () {
|
|
328
337
|
const length = target.length;
|
|
@@ -461,5 +470,6 @@ export const arrayGlobal = (ctx) => {
|
|
|
461
470
|
return accumulator;
|
|
462
471
|
})),
|
|
463
472
|
]);
|
|
473
|
+
define(proto, IteratorSymbol, get(proto, "values"), hidden);
|
|
464
474
|
return array;
|
|
465
475
|
};
|
package/dist/stdlib/bytes.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { checkArrayLength, checkStringLength } from "../interpreter/limits.js";
|
|
3
3
|
import { constructor, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
4
|
-
import { rangeError, syntaxError, typeError } from "../interpreter/model.js";
|
|
5
|
-
import { defineAccessor, get, Arr, Bytes, Obj } from "../interpreter/objects.js";
|
|
4
|
+
import { IteratorSymbol, rangeError, syntaxError, typeError } from "../interpreter/model.js";
|
|
5
|
+
import { define, defineAccessor, get, hidden, Arr, Bytes, IteratorObj, Obj } from "../interpreter/objects.js";
|
|
6
6
|
import { describeValue } from "../interpreter/references.js";
|
|
7
7
|
import { coerceToNumber, coerceToString } from "./value.js";
|
|
8
8
|
/** The bytes a Uint8Array, array, or other iterable of numbers describes; the host array clamps each value. */
|
|
@@ -152,14 +152,17 @@ export const uint8ArrayGlobal = (ctx) => {
|
|
|
152
152
|
["toString", 0, (thisValue) => self(thisValue, "toString").bytes.join(",")],
|
|
153
153
|
["toBase64", 0, (thisValue) => self(thisValue, "toBase64").bytes.toBase64()],
|
|
154
154
|
["toHex", 0, (thisValue) => self(thisValue, "toHex").bytes.toHex()],
|
|
155
|
-
["keys", 0, (thisValue) =>
|
|
156
|
-
["values", 0, (thisValue) =>
|
|
155
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").bytes.keys())],
|
|
156
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").bytes.values())],
|
|
157
157
|
[
|
|
158
158
|
"entries",
|
|
159
159
|
0,
|
|
160
|
-
(thisValue) =>
|
|
160
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
161
|
+
.bytes.entries()
|
|
162
|
+
.map(([index, byte]) => wrapAll([index, byte]))),
|
|
161
163
|
],
|
|
162
164
|
]);
|
|
165
|
+
define(proto, IteratorSymbol, get(proto, "values"), hidden);
|
|
163
166
|
return uint8Array;
|
|
164
167
|
};
|
|
165
168
|
export const textEncoderGlobal = (ctx) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
3
|
-
import { invalidData, typeError } from "../interpreter/model.js";
|
|
4
|
-
import { define, defineAccessor, get, getOwn, hidden, isWrapper, Arr, MapObj, Obj, PromiseObj, SetObj, } from "../interpreter/objects.js";
|
|
3
|
+
import { invalidData, IteratorSymbol, typeError } from "../interpreter/model.js";
|
|
4
|
+
import { define, defineAccessor, get, getOwn, hidden, isWrapper, Arr, IteratorObj, MapObj, Obj, PromiseObj, SetObj, } from "../interpreter/objects.js";
|
|
5
5
|
import { describeValue, isRuntimeReference } from "../interpreter/references.js";
|
|
6
6
|
import { applyCollectionCallback, isSupportedCallback, preserveConsumerError, toPrimitiveNumber, toPrimitiveString, } from "../interpreter/callback.js";
|
|
7
7
|
const coerceGroupByPropertyKey = (ctx, value) => {
|
|
@@ -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",
|
|
@@ -132,12 +157,14 @@ export const mapGlobal = (ctx) => {
|
|
|
132
157
|
return undefined;
|
|
133
158
|
},
|
|
134
159
|
],
|
|
135
|
-
["keys", 0, (thisValue) =>
|
|
136
|
-
["values", 0, (thisValue) =>
|
|
160
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").map.keys())],
|
|
161
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").map.values())],
|
|
137
162
|
[
|
|
138
163
|
"entries",
|
|
139
164
|
0,
|
|
140
|
-
(thisValue) =>
|
|
165
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
166
|
+
.map.entries()
|
|
167
|
+
.map(([key, item]) => wrap([key, item]))),
|
|
141
168
|
],
|
|
142
169
|
[
|
|
143
170
|
"forEach",
|
|
@@ -153,6 +180,7 @@ export const mapGlobal = (ctx) => {
|
|
|
153
180
|
},
|
|
154
181
|
],
|
|
155
182
|
]);
|
|
183
|
+
define(proto, IteratorSymbol, get(proto, "entries"), hidden);
|
|
156
184
|
return map;
|
|
157
185
|
};
|
|
158
186
|
const loadSetRecord = (ctx, source, name) => {
|
|
@@ -187,6 +215,8 @@ const loadSetRecord = (ctx, source, name) => {
|
|
|
187
215
|
size: Math.max(Math.trunc(size), 0),
|
|
188
216
|
has: (item) => Effect.map(ctx.call(has, source, [item]), Boolean),
|
|
189
217
|
keys: () => Effect.flatMap(ctx.call(keys, source, []), (result) => {
|
|
218
|
+
if (result instanceof IteratorObj)
|
|
219
|
+
return Effect.succeed(result.iterator);
|
|
190
220
|
if (result instanceof Arr)
|
|
191
221
|
return Effect.succeed(result.items);
|
|
192
222
|
throw typeError(`Set.${name} expected 'keys' to return an iterator.`);
|
|
@@ -313,12 +343,14 @@ export const setGlobal = (ctx) => {
|
|
|
313
343
|
return undefined;
|
|
314
344
|
},
|
|
315
345
|
],
|
|
316
|
-
["keys", 0, (thisValue) =>
|
|
317
|
-
["values", 0, (thisValue) =>
|
|
346
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").set.values())],
|
|
347
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").set.values())],
|
|
318
348
|
[
|
|
319
349
|
"entries",
|
|
320
350
|
0,
|
|
321
|
-
(thisValue) =>
|
|
351
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
352
|
+
.set.values()
|
|
353
|
+
.map((item) => wrap([item, item]))),
|
|
322
354
|
],
|
|
323
355
|
[
|
|
324
356
|
"forEach",
|
|
@@ -341,5 +373,6 @@ export const setGlobal = (ctx) => {
|
|
|
341
373
|
operation("isSupersetOf"),
|
|
342
374
|
operation("isDisjointFrom"),
|
|
343
375
|
]);
|
|
376
|
+
define(proto, IteratorSymbol, get(proto, "values"), hidden);
|
|
344
377
|
return set;
|
|
345
378
|
};
|
package/dist/stdlib/console.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { methods } from "../interpreter/native.js";
|
|
2
|
-
import { entries, get, Arr, Bytes, DateObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "../interpreter/objects.js";
|
|
2
|
+
import { entries, get, Arr, Bytes, DateObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, HeadersObj, } from "../interpreter/objects.js";
|
|
3
3
|
import { containsOpaqueReference, isRuntimeReference } from "../interpreter/references.js";
|
|
4
4
|
import { coerceToString } from "./value.js";
|
|
5
5
|
const consoleMethods = ["log", "info", "debug", "warn", "error", "dir", "table"];
|
|
@@ -53,6 +53,8 @@ const formatConsoleValue = (value, seen, depth) => {
|
|
|
53
53
|
return coerceToString(value);
|
|
54
54
|
if (value instanceof URLSearchParamsObj)
|
|
55
55
|
return coerceToString(value);
|
|
56
|
+
if (value instanceof HeadersObj)
|
|
57
|
+
return `Headers ${JSON.stringify(Object.fromEntries(value.headers))}`;
|
|
56
58
|
if (value instanceof Bytes)
|
|
57
59
|
return `Uint8Array(${value.bytes.length}) [${value.bytes.join(",")}]`;
|
|
58
60
|
if (depth > MAX_CONSOLE_DEPTH)
|
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,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { constructor, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
3
|
+
import { IteratorSymbol, typeError } from "../interpreter/model.js";
|
|
4
|
+
import { define, entries, get, hidden, Arr, HeadersObj, IteratorObj, Obj } from "../interpreter/objects.js";
|
|
5
|
+
import { applyCollectionCallback } from "../interpreter/callback.js";
|
|
6
|
+
import { isRuntimeReference } from "../interpreter/references.js";
|
|
7
|
+
import { coerceToString } from "./value.js";
|
|
8
|
+
import { readPairs } from "./url.js";
|
|
9
|
+
// The host validates header names and values and throws its own TypeError; the program gets one of its own.
|
|
10
|
+
const attempt = (run) => {
|
|
11
|
+
try {
|
|
12
|
+
return run();
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw typeError(error instanceof Error ? error.message : String(error));
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const constructHeaders = (ctx, init, proto) => {
|
|
19
|
+
const wrap = (headers) => new HeadersObj(proto, headers);
|
|
20
|
+
if (init === undefined)
|
|
21
|
+
return Effect.succeed(wrap(new Headers()));
|
|
22
|
+
return Effect.gen(function* () {
|
|
23
|
+
const pairs = init instanceof Obj ? yield* readPairs(ctx, init, "new Headers(...)") : undefined;
|
|
24
|
+
if (pairs !== undefined)
|
|
25
|
+
return wrap(attempt(() => new Headers(pairs)));
|
|
26
|
+
if (!(init instanceof Obj) || isRuntimeReference(init)) {
|
|
27
|
+
throw typeError("new Headers(...) expects a record of names to values, iterable [name, value] pairs, or Headers.");
|
|
28
|
+
}
|
|
29
|
+
return wrap(attempt(() => new Headers(Object.fromEntries(entries(init).map(([key, value]) => [key, coerceToString(value)])))));
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export const headersGlobal = (ctx) => {
|
|
33
|
+
const builtins = ctx.builtins;
|
|
34
|
+
const proto = builtins.Headers;
|
|
35
|
+
const headers = constructor(builtins, proto, {
|
|
36
|
+
name: "Headers",
|
|
37
|
+
call: requiresNew("Headers"),
|
|
38
|
+
construct: (args, newTarget) => constructHeaders(ctx, args[0], prototypeFrom(newTarget, proto)),
|
|
39
|
+
});
|
|
40
|
+
const self = (thisValue, name) => receiver(HeadersObj, thisValue, `Headers.prototype.${name}`);
|
|
41
|
+
const wrap = (items) => new Arr(builtins.Array, items);
|
|
42
|
+
const arg = (args, index) => coerceToString(args[index]);
|
|
43
|
+
const requireArgs = (name, args, count) => {
|
|
44
|
+
if (args.length < count)
|
|
45
|
+
throw typeError(`Headers.${name} requires ${count} argument${count === 1 ? "" : "s"}.`);
|
|
46
|
+
};
|
|
47
|
+
methods(builtins, proto, [
|
|
48
|
+
[
|
|
49
|
+
"append",
|
|
50
|
+
2,
|
|
51
|
+
(thisValue, args) => {
|
|
52
|
+
requireArgs("append", args, 2);
|
|
53
|
+
const target = self(thisValue, "append").headers;
|
|
54
|
+
return attempt(() => target.append(arg(args, 0), arg(args, 1)));
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
"delete",
|
|
59
|
+
1,
|
|
60
|
+
(thisValue, args) => {
|
|
61
|
+
requireArgs("delete", args, 1);
|
|
62
|
+
const target = self(thisValue, "delete").headers;
|
|
63
|
+
return attempt(() => target.delete(arg(args, 0)));
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
"get",
|
|
68
|
+
1,
|
|
69
|
+
(thisValue, args) => {
|
|
70
|
+
requireArgs("get", args, 1);
|
|
71
|
+
const target = self(thisValue, "get").headers;
|
|
72
|
+
return attempt(() => target.get(arg(args, 0)));
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
["getSetCookie", 0, (thisValue) => wrap(self(thisValue, "getSetCookie").headers.getSetCookie())],
|
|
76
|
+
[
|
|
77
|
+
"has",
|
|
78
|
+
1,
|
|
79
|
+
(thisValue, args) => {
|
|
80
|
+
requireArgs("has", args, 1);
|
|
81
|
+
const target = self(thisValue, "has").headers;
|
|
82
|
+
return attempt(() => target.has(arg(args, 0)));
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
"set",
|
|
87
|
+
2,
|
|
88
|
+
(thisValue, args) => {
|
|
89
|
+
requireArgs("set", args, 2);
|
|
90
|
+
const target = self(thisValue, "set").headers;
|
|
91
|
+
return attempt(() => target.set(arg(args, 0), arg(args, 1)));
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
// Iterator.from because Bun's Headers typings predate iterator helpers; the runtime iterators already have them.
|
|
95
|
+
[
|
|
96
|
+
"keys",
|
|
97
|
+
0,
|
|
98
|
+
(thisValue) => new IteratorObj(builtins.Iterator, Iterator.from(self(thisValue, "keys").headers.keys())),
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
"values",
|
|
102
|
+
0,
|
|
103
|
+
(thisValue) => new IteratorObj(builtins.Iterator, Iterator.from(self(thisValue, "values").headers.values())),
|
|
104
|
+
],
|
|
105
|
+
[
|
|
106
|
+
"entries",
|
|
107
|
+
0,
|
|
108
|
+
(thisValue) => new IteratorObj(builtins.Iterator, Iterator.from(self(thisValue, "entries").headers.entries()).map(([key, value]) => wrap([key, value]))),
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
"forEach",
|
|
112
|
+
1,
|
|
113
|
+
(thisValue, args) => {
|
|
114
|
+
requireArgs("forEach", args, 1);
|
|
115
|
+
const target = self(thisValue, "forEach");
|
|
116
|
+
const apply = applyCollectionCallback(ctx, args[0], "Headers.forEach");
|
|
117
|
+
return Effect.gen(function* () {
|
|
118
|
+
for (const [key, value] of Array.from(target.headers.entries()))
|
|
119
|
+
yield* apply([value, key, target]);
|
|
120
|
+
return undefined;
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
]);
|
|
125
|
+
define(proto, IteratorSymbol, get(proto, "entries"), hidden);
|
|
126
|
+
return headers;
|
|
127
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { methods, receiver } from "../interpreter/native.js";
|
|
2
|
+
import { IteratorObj, record } from "../interpreter/objects.js";
|
|
3
|
+
// Every built-in collection iterator shares the Iterator prototype; JS gives each collection its own, which is only
|
|
4
|
+
// observable through getPrototypeOf.
|
|
5
|
+
export const iteratorGlobals = (ctx) => {
|
|
6
|
+
const builtins = ctx.builtins;
|
|
7
|
+
methods(builtins, builtins.Iterator, [
|
|
8
|
+
[
|
|
9
|
+
"next",
|
|
10
|
+
0,
|
|
11
|
+
(thisValue) => {
|
|
12
|
+
const step = receiver(IteratorObj, thisValue, "Iterator.prototype.next").iterator.next();
|
|
13
|
+
return record(builtins.Object, { value: step.value, done: Boolean(step.done) });
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
]);
|
|
17
|
+
};
|
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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { constructor, methods } from "../interpreter/native.js";
|
|
2
|
+
import { constructor, fn, methods } from "../interpreter/native.js";
|
|
3
3
|
import { checkArrayLength, checkStringLength } from "../interpreter/limits.js";
|
|
4
|
-
import { invalidData, rangeError, typeError } from "../interpreter/model.js";
|
|
5
|
-
import { Arr, PromiseObj, RegExpObj, record } from "../interpreter/objects.js";
|
|
4
|
+
import { invalidData, IteratorSymbol, rangeError, typeError } from "../interpreter/model.js";
|
|
5
|
+
import { define, hidden, Arr, IteratorObj, PromiseObj, RegExpObj, record } from "../interpreter/objects.js";
|
|
6
6
|
import { containsOpaqueReference, typeofValue } from "../interpreter/references.js";
|
|
7
7
|
import { applyCollectionCallback, isSupportedCallback } from "../interpreter/callback.js";
|
|
8
8
|
import { matchToValue, toHostRegex } from "./regexp.js";
|
|
@@ -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()),
|
|
@@ -232,5 +234,6 @@ export const stringGlobal = (ctx) => {
|
|
|
232
234
|
return joined;
|
|
233
235
|
}),
|
|
234
236
|
]);
|
|
237
|
+
define(builtins.String, IteratorSymbol, fn(builtins, "[Symbol.iterator]", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "[Symbol.iterator]")[Symbol.iterator]())), hidden);
|
|
235
238
|
return string;
|
|
236
239
|
};
|
package/dist/stdlib/url.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
1
2
|
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
2
3
|
type UriFunction = "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
|
|
3
4
|
export declare const uriGlobal: <R>(ctx: Interpreter<R>, name: UriFunction) => import("../interpreter/objects.js").Native<R>;
|
|
4
5
|
export declare const urlGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
|
|
6
|
+
/**
|
|
7
|
+
* Reads a synchronous iterable of `[name, value]` pairs as strings; `undefined` when `init` is not iterable. As in
|
|
8
|
+
* WebIDL, the whole sequence is converted before any pair's length is checked.
|
|
9
|
+
*/
|
|
10
|
+
export declare const readPairs: <R>(ctx: Interpreter<R>, init: unknown, label: string) => Effect.Effect<Array<[string, string]> | undefined, unknown, R>;
|
|
5
11
|
export declare const urlSearchParamsGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
|
|
6
12
|
export {};
|
package/dist/stdlib/url.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
3
|
-
import { PendingThrow, typeError, uriError } from "../interpreter/model.js";
|
|
4
|
-
import { defineAccessor, entries, isWrapper, Arr, Obj, URLObj, URLSearchParamsObj } from "../interpreter/objects.js";
|
|
3
|
+
import { IteratorSymbol, PendingThrow, typeError, uriError } from "../interpreter/model.js";
|
|
4
|
+
import { define, defineAccessor, entries, get, hidden, isWrapper, Arr, IteratorObj, Obj, URLObj, URLSearchParamsObj, } from "../interpreter/objects.js";
|
|
5
5
|
import { isRuntimeReference } from "../interpreter/references.js";
|
|
6
6
|
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/callback.js";
|
|
7
7
|
import { coerceToString } from "./value.js";
|
|
@@ -98,11 +98,10 @@ export const urlGlobal = (ctx) => {
|
|
|
98
98
|
]);
|
|
99
99
|
return url;
|
|
100
100
|
};
|
|
101
|
-
const readPair = (ctx, value) => Effect.gen(function* () {
|
|
101
|
+
const readPair = (ctx, value, label) => Effect.gen(function* () {
|
|
102
102
|
const cursor = yield* ctx.iterate(value);
|
|
103
|
-
if (cursor === undefined)
|
|
104
|
-
throw typeError(
|
|
105
|
-
}
|
|
103
|
+
if (cursor === undefined)
|
|
104
|
+
throw typeError(`${label} expects iterable [name, value] pairs.`);
|
|
106
105
|
const items = [];
|
|
107
106
|
while (true) {
|
|
108
107
|
const step = yield* cursor.next;
|
|
@@ -111,6 +110,25 @@ const readPair = (ctx, value) => Effect.gen(function* () {
|
|
|
111
110
|
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => coerceToString(step.value))));
|
|
112
111
|
}
|
|
113
112
|
});
|
|
113
|
+
/**
|
|
114
|
+
* Reads a synchronous iterable of `[name, value]` pairs as strings; `undefined` when `init` is not iterable. As in
|
|
115
|
+
* WebIDL, the whole sequence is converted before any pair's length is checked.
|
|
116
|
+
*/
|
|
117
|
+
export const readPairs = (ctx, init, label) => Effect.gen(function* () {
|
|
118
|
+
const cursor = yield* ctx.iterate(init);
|
|
119
|
+
if (cursor === undefined)
|
|
120
|
+
return undefined;
|
|
121
|
+
const pairs = [];
|
|
122
|
+
while (true) {
|
|
123
|
+
const step = yield* cursor.next;
|
|
124
|
+
if (step.done) {
|
|
125
|
+
if (pairs.some((entry) => entry.length !== 2))
|
|
126
|
+
throw typeError(`${label} expects iterable [name, value] pairs.`);
|
|
127
|
+
return pairs;
|
|
128
|
+
}
|
|
129
|
+
pairs.push(yield* preserveConsumerError(cursor, readPair(ctx, step.value, label)));
|
|
130
|
+
}
|
|
131
|
+
});
|
|
114
132
|
const constructURLSearchParams = (ctx, init, proto) => {
|
|
115
133
|
const wrap = (params) => new URLSearchParamsObj(proto, params);
|
|
116
134
|
if (init === undefined)
|
|
@@ -123,20 +141,9 @@ const constructURLSearchParams = (ctx, init, proto) => {
|
|
|
123
141
|
return Effect.succeed(wrap(new URLSearchParams(coerceToString(init))));
|
|
124
142
|
}
|
|
125
143
|
return Effect.gen(function* () {
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
while (true) {
|
|
130
|
-
const step = yield* cursor.next;
|
|
131
|
-
if (step.done) {
|
|
132
|
-
if (pairs.some((entry) => entry.length !== 2)) {
|
|
133
|
-
throw typeError("new URLSearchParams(...) expects iterable [name, value] pairs.");
|
|
134
|
-
}
|
|
135
|
-
return wrap(new URLSearchParams(pairs.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
|
|
136
|
-
}
|
|
137
|
-
pairs.push(yield* preserveConsumerError(cursor, readPair(ctx, step.value)));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
144
|
+
const pairs = yield* readPairs(ctx, init, "new URLSearchParams(...)");
|
|
145
|
+
if (pairs !== undefined)
|
|
146
|
+
return wrap(new URLSearchParams(pairs));
|
|
140
147
|
if (isRuntimeReference(init)) {
|
|
141
148
|
throw typeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.");
|
|
142
149
|
}
|
|
@@ -230,12 +237,14 @@ export const urlSearchParamsGlobal = (ctx) => {
|
|
|
230
237
|
return undefined;
|
|
231
238
|
},
|
|
232
239
|
],
|
|
233
|
-
["keys", 0, (thisValue) =>
|
|
234
|
-
["values", 0, (thisValue) =>
|
|
240
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").params.keys())],
|
|
241
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").params.values())],
|
|
235
242
|
[
|
|
236
243
|
"entries",
|
|
237
244
|
0,
|
|
238
|
-
(thisValue) =>
|
|
245
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
246
|
+
.params.entries()
|
|
247
|
+
.map(([key, value]) => wrap([key, value]))),
|
|
239
248
|
],
|
|
240
249
|
["toString", 0, (thisValue) => self(thisValue, "toString").params.toString()],
|
|
241
250
|
[
|
|
@@ -253,5 +262,6 @@ export const urlSearchParamsGlobal = (ctx) => {
|
|
|
253
262
|
},
|
|
254
263
|
],
|
|
255
264
|
]);
|
|
265
|
+
define(proto, IteratorSymbol, get(proto, "entries"), hidden);
|
|
256
266
|
return searchParams;
|
|
257
267
|
};
|
package/dist/stdlib/value.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fn } from "../interpreter/native.js";
|
|
2
2
|
import { typeError } from "../interpreter/model.js";
|
|
3
|
-
import { get, isWrapper, Arr, Bytes, DateObj, ErrorObj, MapObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "../interpreter/objects.js";
|
|
3
|
+
import { get, isWrapper, Arr, Bytes, DateObj, ErrorObj, MapObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, HeadersObj, } from "../interpreter/objects.js";
|
|
4
4
|
export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]);
|
|
5
5
|
/** The built-in string form of a value, without consulting program-defined `toString` methods. */
|
|
6
6
|
export const coerceToString = (value) => {
|
|
@@ -20,6 +20,8 @@ export const coerceToString = (value) => {
|
|
|
20
20
|
return value.url.href;
|
|
21
21
|
if (value instanceof URLSearchParamsObj)
|
|
22
22
|
return value.params.toString();
|
|
23
|
+
if (value instanceof HeadersObj)
|
|
24
|
+
return "[object Headers]";
|
|
23
25
|
if (value instanceof Bytes)
|
|
24
26
|
return value.bytes.join(",");
|
|
25
27
|
if (value instanceof ErrorObj) {
|
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