@opencode/codemode 2.0.10 → 2.0.11
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/extensions.js +6 -1
- package/dist/interpreter/globals.js +4 -0
- package/dist/interpreter/interpreter.d.ts +6 -0
- package/dist/interpreter/interpreter.js +37 -27
- package/dist/interpreter/intrinsics.d.ts +1 -1
- package/dist/interpreter/intrinsics.js +2 -0
- 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 +8 -5
- package/dist/stdlib/bytes.js +8 -5
- package/dist/stdlib/collections.js +16 -8
- package/dist/stdlib/console.js +3 -1
- 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/string.js +4 -3
- package/dist/stdlib/url.d.ts +6 -0
- package/dist/stdlib/url.js +33 -23
- package/dist/stdlib/value.js +3 -1
- 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.");
|
|
@@ -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
|
};
|
|
@@ -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;
|
|
@@ -5,7 +5,7 @@ import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, Optiona
|
|
|
5
5
|
import { checkStringLength } from "./limits.js";
|
|
6
6
|
import { locate, materialize } from "./errors.js";
|
|
7
7
|
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";
|
|
8
|
+
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
9
|
import { preserveConsumerError } from "./callback.js";
|
|
10
10
|
import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
|
|
11
11
|
import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
|
|
@@ -477,10 +477,10 @@ class Frame {
|
|
|
477
477
|
if (declared?.lexical)
|
|
478
478
|
self.predeclarePattern(declared.pattern, declared.mutable, left);
|
|
479
479
|
const right = yield* self.evaluateExpression(node.right);
|
|
480
|
-
const
|
|
481
|
-
const
|
|
480
|
+
const cursor = self.hostCursor(right);
|
|
481
|
+
const iterator = cursor === undefined ? yield* self.customIterator(right, node, awaiting) : undefined;
|
|
482
482
|
if (iterator === undefined && cursor === undefined) {
|
|
483
|
-
throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or
|
|
483
|
+
throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, URLSearchParams, or Headers, or custom iterator value.`, node);
|
|
484
484
|
}
|
|
485
485
|
const close = () => iterator
|
|
486
486
|
? self.closeIterator(iterator, node, awaiting)
|
|
@@ -550,6 +550,18 @@ class Frame {
|
|
|
550
550
|
});
|
|
551
551
|
}
|
|
552
552
|
iterate(value, node) {
|
|
553
|
+
const cursor = this.hostCursor(value);
|
|
554
|
+
if (cursor !== undefined)
|
|
555
|
+
return Effect.succeed(cursor);
|
|
556
|
+
const self = this;
|
|
557
|
+
return Effect.map(this.customIterator(value, node, false), (iterator) => iterator === undefined
|
|
558
|
+
? undefined
|
|
559
|
+
: {
|
|
560
|
+
next: self.nextIteratorResult(iterator, node, false),
|
|
561
|
+
close: Effect.suspend(() => self.closeIterator(iterator, node, false)),
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
hostCursor(value) {
|
|
553
565
|
const iterator = value instanceof Arr
|
|
554
566
|
? value.items[Symbol.iterator]()
|
|
555
567
|
: typeof value === "string"
|
|
@@ -560,29 +572,26 @@ class Frame {
|
|
|
560
572
|
? value.set.values()
|
|
561
573
|
: value instanceof URLSearchParamsObj
|
|
562
574
|
? 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
|
-
});
|
|
575
|
+
: value instanceof HeadersObj
|
|
576
|
+
? value.headers.entries()
|
|
577
|
+
: value instanceof Bytes
|
|
578
|
+
? value.bytes.values()
|
|
579
|
+
: value instanceof IteratorObj
|
|
580
|
+
? value.iterator
|
|
581
|
+
: undefined;
|
|
582
|
+
if (iterator === undefined)
|
|
583
|
+
return undefined;
|
|
584
|
+
const proto = this.ctx.builtins.Array;
|
|
585
|
+
return {
|
|
586
|
+
next: Effect.sync(() => {
|
|
587
|
+
const step = iterator.next();
|
|
588
|
+
return {
|
|
589
|
+
done: Boolean(step.done),
|
|
590
|
+
value: Array.isArray(step.value) ? new Arr(proto, step.value) : step.value,
|
|
591
|
+
};
|
|
592
|
+
}),
|
|
593
|
+
close: Effect.void,
|
|
594
|
+
};
|
|
586
595
|
}
|
|
587
596
|
customIterator(value, node, allowAsync = true) {
|
|
588
597
|
if (!(value instanceof Obj))
|
|
@@ -1513,6 +1522,7 @@ class Frame {
|
|
|
1513
1522
|
value instanceof MapObj ||
|
|
1514
1523
|
value instanceof SetObj ||
|
|
1515
1524
|
value instanceof URLSearchParamsObj ||
|
|
1525
|
+
value instanceof HeadersObj ||
|
|
1516
1526
|
value instanceof Bytes) {
|
|
1517
1527
|
const cursor = yield* self.iterate(value, node);
|
|
1518
1528
|
if (!cursor)
|
|
@@ -2,7 +2,7 @@ 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.
|
|
@@ -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",
|
|
@@ -68,6 +69,7 @@ export const createBuiltins = () => {
|
|
|
68
69
|
Set: plain(),
|
|
69
70
|
URL: plain(),
|
|
70
71
|
URLSearchParams: plain(),
|
|
72
|
+
Headers: plain(),
|
|
71
73
|
Uint8Array: plain(),
|
|
72
74
|
TextEncoder: plain(),
|
|
73
75
|
TextDecoder: plain(),
|
|
@@ -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,8 +1,8 @@
|
|
|
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
7
|
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/callback.js";
|
|
8
8
|
import { compareText } from "../tool-runtime.js";
|
|
@@ -317,12 +317,14 @@ export const arrayGlobal = (ctx) => {
|
|
|
317
317
|
return target;
|
|
318
318
|
},
|
|
319
319
|
],
|
|
320
|
-
["keys", 0, (thisValue) =>
|
|
321
|
-
["values", 0, (thisValue) =>
|
|
320
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").items.keys())],
|
|
321
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").items.values())],
|
|
322
322
|
[
|
|
323
323
|
"entries",
|
|
324
324
|
0,
|
|
325
|
-
(thisValue) =>
|
|
325
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
326
|
+
.items.entries()
|
|
327
|
+
.map(([index, item]) => wrap([index, item]))),
|
|
326
328
|
],
|
|
327
329
|
iterate("map", 1, (target, receiver, apply) => Effect.gen(function* () {
|
|
328
330
|
const length = target.length;
|
|
@@ -461,5 +463,6 @@ export const arrayGlobal = (ctx) => {
|
|
|
461
463
|
return accumulator;
|
|
462
464
|
})),
|
|
463
465
|
]);
|
|
466
|
+
define(proto, IteratorSymbol, get(proto, "values"), hidden);
|
|
464
467
|
return array;
|
|
465
468
|
};
|
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) => {
|
|
@@ -132,12 +132,14 @@ export const mapGlobal = (ctx) => {
|
|
|
132
132
|
return undefined;
|
|
133
133
|
},
|
|
134
134
|
],
|
|
135
|
-
["keys", 0, (thisValue) =>
|
|
136
|
-
["values", 0, (thisValue) =>
|
|
135
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").map.keys())],
|
|
136
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").map.values())],
|
|
137
137
|
[
|
|
138
138
|
"entries",
|
|
139
139
|
0,
|
|
140
|
-
(thisValue) =>
|
|
140
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
141
|
+
.map.entries()
|
|
142
|
+
.map(([key, item]) => wrap([key, item]))),
|
|
141
143
|
],
|
|
142
144
|
[
|
|
143
145
|
"forEach",
|
|
@@ -153,6 +155,7 @@ export const mapGlobal = (ctx) => {
|
|
|
153
155
|
},
|
|
154
156
|
],
|
|
155
157
|
]);
|
|
158
|
+
define(proto, IteratorSymbol, get(proto, "entries"), hidden);
|
|
156
159
|
return map;
|
|
157
160
|
};
|
|
158
161
|
const loadSetRecord = (ctx, source, name) => {
|
|
@@ -187,6 +190,8 @@ const loadSetRecord = (ctx, source, name) => {
|
|
|
187
190
|
size: Math.max(Math.trunc(size), 0),
|
|
188
191
|
has: (item) => Effect.map(ctx.call(has, source, [item]), Boolean),
|
|
189
192
|
keys: () => Effect.flatMap(ctx.call(keys, source, []), (result) => {
|
|
193
|
+
if (result instanceof IteratorObj)
|
|
194
|
+
return Effect.succeed(result.iterator);
|
|
190
195
|
if (result instanceof Arr)
|
|
191
196
|
return Effect.succeed(result.items);
|
|
192
197
|
throw typeError(`Set.${name} expected 'keys' to return an iterator.`);
|
|
@@ -313,12 +318,14 @@ export const setGlobal = (ctx) => {
|
|
|
313
318
|
return undefined;
|
|
314
319
|
},
|
|
315
320
|
],
|
|
316
|
-
["keys", 0, (thisValue) =>
|
|
317
|
-
["values", 0, (thisValue) =>
|
|
321
|
+
["keys", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "keys").set.values())],
|
|
322
|
+
["values", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "values").set.values())],
|
|
318
323
|
[
|
|
319
324
|
"entries",
|
|
320
325
|
0,
|
|
321
|
-
(thisValue) =>
|
|
326
|
+
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
327
|
+
.set.values()
|
|
328
|
+
.map((item) => wrap([item, item]))),
|
|
322
329
|
],
|
|
323
330
|
[
|
|
324
331
|
"forEach",
|
|
@@ -341,5 +348,6 @@ export const setGlobal = (ctx) => {
|
|
|
341
348
|
operation("isSupersetOf"),
|
|
342
349
|
operation("isDisjointFrom"),
|
|
343
350
|
]);
|
|
351
|
+
define(proto, IteratorSymbol, get(proto, "values"), hidden);
|
|
344
352
|
return set;
|
|
345
353
|
};
|
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)
|
|
@@ -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/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";
|
|
@@ -232,5 +232,6 @@ export const stringGlobal = (ctx) => {
|
|
|
232
232
|
return joined;
|
|
233
233
|
}),
|
|
234
234
|
]);
|
|
235
|
+
define(builtins.String, IteratorSymbol, fn(builtins, "[Symbol.iterator]", 0, (thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "[Symbol.iterator]")[Symbol.iterator]())), hidden);
|
|
235
236
|
return string;
|
|
236
237
|
};
|
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/package.json
CHANGED