@opencode/codemode 0.0.0-dev-19631 → 0.0.0-dev-19634

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.
Files changed (62) hide show
  1. package/dist/codemode.js +1 -1
  2. package/dist/data.d.ts +3 -3
  3. package/dist/data.js +37 -31
  4. package/dist/interpreter/callback.d.ts +20 -0
  5. package/dist/interpreter/{runner.js → callback.js} +10 -10
  6. package/dist/interpreter/errors.d.ts +5 -5
  7. package/dist/interpreter/errors.js +21 -22
  8. package/dist/interpreter/execute.d.ts +2 -2
  9. package/dist/interpreter/execute.js +11 -11
  10. package/dist/interpreter/extensions.d.ts +2 -2
  11. package/dist/interpreter/extensions.js +42 -36
  12. package/dist/interpreter/generators.d.ts +2 -3
  13. package/dist/interpreter/generators.js +8 -8
  14. package/dist/interpreter/globals.d.ts +2 -12
  15. package/dist/interpreter/globals.js +41 -37
  16. package/dist/interpreter/interpreter.d.ts +31 -0
  17. package/dist/interpreter/{runtime.js → interpreter.js} +118 -117
  18. package/dist/interpreter/intrinsics.d.ts +5 -5
  19. package/dist/interpreter/intrinsics.js +16 -10
  20. package/dist/interpreter/model.d.ts +3 -3
  21. package/dist/interpreter/model.js +1 -1
  22. package/dist/interpreter/native.d.ts +9 -9
  23. package/dist/interpreter/native.js +9 -9
  24. package/dist/interpreter/objects.d.ts +51 -46
  25. package/dist/interpreter/objects.js +57 -40
  26. package/dist/interpreter/promises.d.ts +13 -13
  27. package/dist/interpreter/promises.js +70 -70
  28. package/dist/interpreter/references.js +17 -15
  29. package/dist/openapi/types.d.ts +1 -1
  30. package/dist/stdlib/array.d.ts +3 -3
  31. package/dist/stdlib/array.js +31 -31
  32. package/dist/stdlib/bytes.d.ts +10 -0
  33. package/dist/stdlib/bytes.js +228 -0
  34. package/dist/stdlib/collections.d.ts +4 -4
  35. package/dist/stdlib/collections.js +55 -55
  36. package/dist/stdlib/console.d.ts +3 -3
  37. package/dist/stdlib/console.js +24 -22
  38. package/dist/stdlib/date.d.ts +2 -2
  39. package/dist/stdlib/date.js +19 -19
  40. package/dist/stdlib/json.d.ts +3 -3
  41. package/dist/stdlib/json.js +24 -24
  42. package/dist/stdlib/math.d.ts +3 -3
  43. package/dist/stdlib/math.js +7 -7
  44. package/dist/stdlib/number.d.ts +3 -3
  45. package/dist/stdlib/number.js +11 -11
  46. package/dist/stdlib/object.d.ts +5 -5
  47. package/dist/stdlib/object.js +41 -39
  48. package/dist/stdlib/regexp.d.ts +6 -6
  49. package/dist/stdlib/regexp.js +24 -24
  50. package/dist/stdlib/string.d.ts +2 -2
  51. package/dist/stdlib/string.js +24 -24
  52. package/dist/stdlib/url.d.ts +6 -6
  53. package/dist/stdlib/url.js +39 -39
  54. package/dist/stdlib/value.d.ts +3 -3
  55. package/dist/stdlib/value.js +18 -14
  56. package/dist/stdlib/web.d.ts +4 -4
  57. package/dist/stdlib/web.js +19 -5
  58. package/dist/tool-runtime.d.ts +2 -2
  59. package/dist/tool-runtime.js +2 -2
  60. package/package.json +1 -1
  61. package/dist/interpreter/runner.d.ts +0 -27
  62. package/dist/interpreter/runtime.d.ts +0 -19
@@ -0,0 +1,228 @@
1
+ import { Effect } from "effect";
2
+ import { checkArrayLength, checkStringLength } from "../interpreter/limits.js";
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";
6
+ import { describeValue } from "../interpreter/references.js";
7
+ import { coerceToNumber, coerceToString } from "./value.js";
8
+ /** The bytes a Uint8Array, array, or other iterable of numbers describes; the host array clamps each value. */
9
+ const collectBytes = (ctx, source, name) => {
10
+ if (source instanceof Bytes)
11
+ return Effect.succeed(new Uint8Array(source.bytes));
12
+ return Effect.gen(function* () {
13
+ const cursor = yield* ctx.iterate(source);
14
+ if (cursor === undefined) {
15
+ throw typeError(`${name} expects a Uint8Array, an array, or an iterable of numbers, received ${describeValue(source)}.`);
16
+ }
17
+ const values = [];
18
+ while (true) {
19
+ const step = yield* cursor.next;
20
+ if (step.done)
21
+ return Uint8Array.from(values);
22
+ values.push(coerceToNumber(step.value));
23
+ checkArrayLength(values.length);
24
+ }
25
+ });
26
+ };
27
+ const constructBytes = (ctx, args, proto) => {
28
+ const source = args[0];
29
+ if (source !== null && typeof source === "object") {
30
+ return Effect.map(collectBytes(ctx, source, "new Uint8Array(...)"), (bytes) => new Bytes(proto, bytes));
31
+ }
32
+ const length = source === undefined ? 0 : coerceToNumber(source);
33
+ if (!Number.isInteger(length) || length < 0)
34
+ throw rangeError(`Invalid typed array length: ${coerceToString(source)}`);
35
+ checkArrayLength(length);
36
+ return Effect.succeed(new Bytes(proto, new Uint8Array(length)));
37
+ };
38
+ export const uint8ArrayGlobal = (ctx) => {
39
+ const builtins = ctx.builtins;
40
+ const proto = builtins.Uint8Array;
41
+ const wrap = (bytes) => new Bytes(proto, bytes);
42
+ const uint8Array = constructor(builtins, proto, {
43
+ name: "Uint8Array",
44
+ length: 3,
45
+ call: requiresNew("Uint8Array"),
46
+ construct: (args, newTarget) => constructBytes(ctx, args, prototypeFrom(newTarget, proto)),
47
+ });
48
+ const decode = (name, args, from) => {
49
+ if (typeof args[0] !== "string")
50
+ throw typeError(`Uint8Array.${name} expects a string.`);
51
+ try {
52
+ return wrap(from(args[0]));
53
+ }
54
+ catch {
55
+ throw syntaxError(`Uint8Array.${name}: the string is not valid ${name === "fromHex" ? "hex" : "base64"}.`);
56
+ }
57
+ };
58
+ methods(builtins, uint8Array, [
59
+ ["from", 1, (_, args) => Effect.map(collectBytes(ctx, args[0], "Uint8Array.from"), wrap)],
60
+ ["of", 0, (_, args) => wrap(Uint8Array.from(args, coerceToNumber))],
61
+ ["fromBase64", 1, (_, args) => decode("fromBase64", args, (text) => Uint8Array.fromBase64(text))],
62
+ ["fromHex", 1, (_, args) => decode("fromHex", args, (text) => Uint8Array.fromHex(text))],
63
+ ]);
64
+ const self = (thisValue, name) => receiver(Bytes, thisValue, `Uint8Array.prototype.${name}`);
65
+ const optNumber = (name, value, label) => {
66
+ if (value === undefined)
67
+ return undefined;
68
+ if (typeof value !== "number")
69
+ throw typeError(`Uint8Array.${name} expects ${label} to be a number.`);
70
+ return value;
71
+ };
72
+ const wrapAll = (items) => new Arr(builtins.Array, items);
73
+ defineAccessor(proto, "length", (thisValue) => self(thisValue, "length").bytes.length);
74
+ methods(builtins, proto, [
75
+ ["at", 1, (thisValue, args) => self(thisValue, "at").bytes.at(optNumber("at", args[0], "index") ?? 0)],
76
+ [
77
+ "slice",
78
+ 2,
79
+ (thisValue, args) => wrap(self(thisValue, "slice").bytes.slice(optNumber("slice", args[0], "start"), optNumber("slice", args[1], "end"))),
80
+ ],
81
+ // A view on the same bytes, as in JS: writes through one are visible through the other.
82
+ [
83
+ "subarray",
84
+ 2,
85
+ (thisValue, args) => wrap(self(thisValue, "subarray").bytes.subarray(optNumber("subarray", args[0], "start"), optNumber("subarray", args[1], "end"))),
86
+ ],
87
+ [
88
+ "set",
89
+ 1,
90
+ (thisValue, args) => {
91
+ const target = self(thisValue, "set");
92
+ const offset = optNumber("set", args[1], "offset") ?? 0;
93
+ return Effect.map(collectBytes(ctx, args[0], "Uint8Array.set"), (source) => {
94
+ if (!Number.isInteger(offset) || offset < 0 || source.length + offset > target.bytes.length) {
95
+ throw rangeError("Uint8Array.set: the source does not fit at that offset.");
96
+ }
97
+ target.bytes.set(source, offset);
98
+ return undefined;
99
+ });
100
+ },
101
+ ],
102
+ [
103
+ "fill",
104
+ 1,
105
+ (thisValue, args) => {
106
+ const target = self(thisValue, "fill");
107
+ target.bytes.fill(coerceToNumber(args[0]), optNumber("fill", args[1], "start"), optNumber("fill", args[2], "end"));
108
+ return target;
109
+ },
110
+ ],
111
+ [
112
+ "reverse",
113
+ 0,
114
+ (thisValue) => {
115
+ const target = self(thisValue, "reverse");
116
+ target.bytes.reverse();
117
+ return target;
118
+ },
119
+ ],
120
+ [
121
+ "indexOf",
122
+ 1,
123
+ (thisValue, args) => self(thisValue, "indexOf").bytes.indexOf(coerceToNumber(args[0]), optNumber("indexOf", args[1], "start index")),
124
+ ],
125
+ [
126
+ "lastIndexOf",
127
+ 1,
128
+ (thisValue, args) => {
129
+ const target = self(thisValue, "lastIndexOf").bytes;
130
+ return args[1] === undefined
131
+ ? target.lastIndexOf(coerceToNumber(args[0]))
132
+ : target.lastIndexOf(coerceToNumber(args[0]), optNumber("lastIndexOf", args[1], "start index"));
133
+ },
134
+ ],
135
+ [
136
+ "includes",
137
+ 1,
138
+ (thisValue, args) => self(thisValue, "includes").bytes.includes(coerceToNumber(args[0]), optNumber("includes", args[1], "start index")),
139
+ ],
140
+ [
141
+ "join",
142
+ 1,
143
+ (thisValue, args) => {
144
+ if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) {
145
+ throw typeError("Uint8Array.join expects zero arguments or one string separator.");
146
+ }
147
+ const joined = self(thisValue, "join").bytes.join(args.length === 0 ? "," : args[0]);
148
+ checkStringLength(joined.length);
149
+ return joined;
150
+ },
151
+ ],
152
+ ["toString", 0, (thisValue) => self(thisValue, "toString").bytes.join(",")],
153
+ ["toBase64", 0, (thisValue) => self(thisValue, "toBase64").bytes.toBase64()],
154
+ ["toHex", 0, (thisValue) => self(thisValue, "toHex").bytes.toHex()],
155
+ ["keys", 0, (thisValue) => wrapAll(Array.from(self(thisValue, "keys").bytes.keys()))],
156
+ ["values", 0, (thisValue) => wrapAll(Array.from(self(thisValue, "values").bytes.values()))],
157
+ [
158
+ "entries",
159
+ 0,
160
+ (thisValue) => wrapAll(Array.from(self(thisValue, "entries").bytes.entries(), ([index, byte]) => wrapAll([index, byte]))),
161
+ ],
162
+ ]);
163
+ return uint8Array;
164
+ };
165
+ export const textEncoderGlobal = (ctx) => {
166
+ const builtins = ctx.builtins;
167
+ const proto = builtins.TextEncoder;
168
+ const encoder = new TextEncoder();
169
+ defineAccessor(proto, "encoding", () => "utf-8");
170
+ methods(builtins, proto, [
171
+ ["encode", 0, (_, args) => new Bytes(builtins.Uint8Array, encoder.encode(coerceToString(args[0] ?? "")))],
172
+ ]);
173
+ return constructor(builtins, proto, {
174
+ name: "TextEncoder",
175
+ call: requiresNew("TextEncoder"),
176
+ construct: (_, newTarget) => Effect.succeed(new Obj(prototypeFrom(newTarget, proto))),
177
+ });
178
+ };
179
+ /** A `TextDecoder` holding the host decoder its label and options configured. */
180
+ export class TextDecoderObj extends Obj {
181
+ decoder;
182
+ constructor(proto, decoder) {
183
+ super(proto);
184
+ this.decoder = decoder;
185
+ }
186
+ }
187
+ // The WHATWG labels for UTF-8, the only encoding CodeMode decodes.
188
+ const utf8Labels = new Set(["unicode-1-1-utf-8", "unicode11utf8", "unicode20utf8", "utf-8", "utf8", "x-unicode20utf8"]);
189
+ export const textDecoderGlobal = (ctx) => {
190
+ const builtins = ctx.builtins;
191
+ const proto = builtins.TextDecoder;
192
+ const self = (thisValue, name) => receiver(TextDecoderObj, thisValue, `TextDecoder.prototype.${name}`);
193
+ defineAccessor(proto, "encoding", (thisValue) => self(thisValue, "encoding").decoder.encoding);
194
+ defineAccessor(proto, "fatal", (thisValue) => self(thisValue, "fatal").decoder.fatal);
195
+ defineAccessor(proto, "ignoreBOM", (thisValue) => self(thisValue, "ignoreBOM").decoder.ignoreBOM);
196
+ methods(builtins, proto, [
197
+ [
198
+ "decode",
199
+ 0,
200
+ (thisValue, args) => {
201
+ const decoder = self(thisValue, "decode").decoder;
202
+ if (args[0] === undefined)
203
+ return "";
204
+ if (!(args[0] instanceof Bytes)) {
205
+ throw typeError(`TextDecoder.decode expects a Uint8Array, received ${describeValue(args[0])}.`);
206
+ }
207
+ try {
208
+ return decoder.decode(args[0].bytes);
209
+ }
210
+ catch {
211
+ throw typeError(`TextDecoder.decode: the input is not valid ${decoder.encoding}.`);
212
+ }
213
+ },
214
+ ],
215
+ ]);
216
+ return constructor(builtins, proto, {
217
+ name: "TextDecoder",
218
+ call: requiresNew("TextDecoder"),
219
+ construct: (args, newTarget) => Effect.sync(() => {
220
+ const label = args[0] === undefined ? "utf-8" : coerceToString(args[0]).trim().toLowerCase();
221
+ if (!utf8Labels.has(label))
222
+ throw rangeError(`The "${label}" encoding is not supported; only UTF-8 is.`);
223
+ const options = args[1] instanceof Obj ? args[1] : undefined;
224
+ const flag = (name) => options !== undefined && Boolean(get(options, name));
225
+ return new TextDecoderObj(prototypeFrom(newTarget, proto), new TextDecoder("utf-8", { fatal: flag("fatal"), ignoreBOM: flag("ignoreBOM") }));
226
+ }),
227
+ });
228
+ };
@@ -1,5 +1,5 @@
1
- import { type Runner } from "../interpreter/runner.js";
1
+ import type { Interpreter } from "../interpreter/interpreter.js";
2
2
  /** `Map.groupBy` and `Object.groupBy`: the same iteration, keyed into a Map or a data object. */
3
- export declare const groupBy: <R>(runner: Runner<R>, namespace: "Map" | "Object") => import("../interpreter/objects.js").NativeFunction<R>;
4
- export declare const mapGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
5
- export declare const setGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
3
+ export declare const groupBy: <R>(ctx: Interpreter<R>, namespace: "Map" | "Object") => import("../interpreter/objects.js").Native<R>;
4
+ export declare const mapGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
5
+ export declare const setGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
@@ -1,32 +1,32 @@
1
1
  import { Effect } from "effect";
2
2
  import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
3
3
  import { invalidData, typeError } from "../interpreter/model.js";
4
- import { define, defineAccessor, get, getOwn, hidden, isWrapper, ProgramArray, ProgramMap, ProgramObject, ProgramPromise, ProgramSet, } from "../interpreter/objects.js";
4
+ import { define, defineAccessor, get, getOwn, hidden, isWrapper, Arr, MapObj, Obj, PromiseObj, SetObj, } from "../interpreter/objects.js";
5
5
  import { describeValue, isRuntimeReference } from "../interpreter/references.js";
6
- import { applyCollectionCallback, isSupportedCallback, preserveConsumerError, toPrimitiveNumber, toPrimitiveString, } from "../interpreter/runner.js";
7
- const coerceGroupByPropertyKey = (runner, value) => {
8
- if (value instanceof ProgramPromise)
6
+ import { applyCollectionCallback, isSupportedCallback, preserveConsumerError, toPrimitiveNumber, toPrimitiveString, } from "../interpreter/callback.js";
7
+ const coerceGroupByPropertyKey = (ctx, value) => {
8
+ if (value instanceof PromiseObj)
9
9
  return Effect.succeed("[object Promise]");
10
10
  if (!isWrapper(value) && isRuntimeReference(value)) {
11
11
  throw invalidData(`Object.groupBy callback must return a data value, received ${describeValue(value)}.`);
12
12
  }
13
- return toPrimitiveString(runner, value);
13
+ return toPrimitiveString(ctx, value);
14
14
  };
15
15
  /** `Map.groupBy` and `Object.groupBy`: the same iteration, keyed into a Map or a data object. */
16
- export const groupBy = (runner, namespace) => fn(runner.prototypes, "groupBy", 2, (_, args) => {
17
- const protos = runner.prototypes;
16
+ export const groupBy = (ctx, namespace) => fn(ctx.builtins, "groupBy", 2, (_, args) => {
17
+ const builtins = ctx.builtins;
18
18
  const source = args[0];
19
19
  if (source === null || source === undefined) {
20
20
  throw typeError(`${namespace}.groupBy expects an iterable collection.`);
21
21
  }
22
- const apply = applyCollectionCallback(runner, args[1], `${namespace}.groupBy`);
22
+ const apply = applyCollectionCallback(ctx, args[1], `${namespace}.groupBy`);
23
23
  return Effect.gen(function* () {
24
- const cursor = yield* runner.syncIterator(source);
24
+ const cursor = yield* ctx.iterate(source);
25
25
  if (cursor === undefined) {
26
26
  throw typeError(`${namespace}.groupBy expects an iterable collection.`);
27
27
  }
28
28
  if (namespace === "Map") {
29
- const result = new ProgramMap(protos.Map);
29
+ const result = new MapObj(builtins.Map);
30
30
  let index = 0;
31
31
  while (true) {
32
32
  const step = yield* cursor.next;
@@ -36,36 +36,36 @@ export const groupBy = (runner, namespace) => fn(runner.prototypes, "groupBy", 2
36
36
  const key = yield* preserveConsumerError(cursor, apply([item, index]));
37
37
  const group = result.map.get(key);
38
38
  if (group === undefined)
39
- result.map.set(key, new ProgramArray(protos.Array, [item]));
39
+ result.map.set(key, new Arr(builtins.Array, [item]));
40
40
  else
41
41
  group.items.push(item);
42
42
  index += 1;
43
43
  }
44
44
  }
45
45
  // Object.groupBy returns a null-prototype object, so group names never collide with inherited methods.
46
- const result = new ProgramObject(null);
46
+ const result = new Obj(null);
47
47
  let index = 0;
48
48
  while (true) {
49
49
  const step = yield* cursor.next;
50
50
  if (step.done)
51
51
  return result;
52
52
  const item = step.value;
53
- const key = yield* preserveConsumerError(cursor, Effect.flatMap(apply([item, index]), (value) => coerceGroupByPropertyKey(runner, value)));
53
+ const key = yield* preserveConsumerError(cursor, Effect.flatMap(apply([item, index]), (value) => coerceGroupByPropertyKey(ctx, value)));
54
54
  const group = getOwn(result, key);
55
55
  if (group === undefined)
56
- define(result, key, new ProgramArray(protos.Array, [item]));
56
+ define(result, key, new Arr(builtins.Array, [item]));
57
57
  else
58
58
  group.items.push(item);
59
59
  index += 1;
60
60
  }
61
61
  });
62
62
  });
63
- const constructMap = (runner, init, proto) => {
64
- const target = new ProgramMap(proto);
63
+ const constructMap = (ctx, init, proto) => {
64
+ const target = new MapObj(proto);
65
65
  if (init === undefined || init === null)
66
66
  return Effect.succeed(target);
67
67
  return Effect.gen(function* () {
68
- const cursor = yield* runner.syncIterator(init);
68
+ const cursor = yield* ctx.iterate(init);
69
69
  if (cursor === undefined) {
70
70
  throw typeError("new Map(...) expects an iterable of [key, value] pairs or no argument.");
71
71
  }
@@ -74,7 +74,7 @@ const constructMap = (runner, init, proto) => {
74
74
  if (step.done)
75
75
  return target;
76
76
  yield* preserveConsumerError(cursor, Effect.sync(() => {
77
- if (!(step.value instanceof ProgramObject)) {
77
+ if (!(step.value instanceof Obj)) {
78
78
  throw typeError("new Map(...) expects [key, value] pairs as entry objects.");
79
79
  }
80
80
  target.map.set(getOwn(step.value, 0), getOwn(step.value, 1));
@@ -82,12 +82,12 @@ const constructMap = (runner, init, proto) => {
82
82
  }
83
83
  });
84
84
  };
85
- const constructSet = (runner, init, proto) => {
86
- const target = new ProgramSet(proto);
85
+ const constructSet = (ctx, init, proto) => {
86
+ const target = new SetObj(proto);
87
87
  if (init === undefined || init === null)
88
88
  return Effect.succeed(target);
89
89
  return Effect.gen(function* () {
90
- const cursor = yield* runner.syncIterator(init);
90
+ const cursor = yield* ctx.iterate(init);
91
91
  if (cursor === undefined) {
92
92
  throw typeError("new Set(...) expects a synchronous iterable or no argument.");
93
93
  }
@@ -99,19 +99,19 @@ const constructSet = (runner, init, proto) => {
99
99
  }
100
100
  });
101
101
  };
102
- export const mapGlobal = (runner) => {
103
- const protos = runner.prototypes;
104
- const proto = protos.Map;
105
- const map = constructor(protos, proto, {
102
+ export const mapGlobal = (ctx) => {
103
+ const builtins = ctx.builtins;
104
+ const proto = builtins.Map;
105
+ const map = constructor(builtins, proto, {
106
106
  name: "Map",
107
107
  call: requiresNew("Map"),
108
- construct: (args, newTarget) => constructMap(runner, args[0], prototypeFrom(newTarget, proto)),
108
+ construct: (args, newTarget) => constructMap(ctx, args[0], prototypeFrom(newTarget, proto)),
109
109
  });
110
- define(map, "groupBy", groupBy(runner, "Map"), hidden);
111
- const self = (thisValue, name) => receiver(ProgramMap, thisValue, `Map.prototype.${name}`);
112
- const wrap = (items) => new ProgramArray(protos.Array, items);
113
- defineAccessor(proto, "size", (thisValue) => receiver(ProgramMap, thisValue, "Map.prototype.size").map.size);
114
- methods(protos, proto, [
110
+ define(map, "groupBy", groupBy(ctx, "Map"), hidden);
111
+ const self = (thisValue, name) => receiver(MapObj, thisValue, `Map.prototype.${name}`);
112
+ const wrap = (items) => new Arr(builtins.Array, items);
113
+ defineAccessor(proto, "size", (thisValue) => receiver(MapObj, thisValue, "Map.prototype.size").map.size);
114
+ methods(builtins, proto, [
115
115
  ["get", 1, (thisValue, args) => self(thisValue, "get").map.get(args[0])],
116
116
  ["has", 1, (thisValue, args) => self(thisValue, "has").map.has(args[0])],
117
117
  [
@@ -144,7 +144,7 @@ export const mapGlobal = (runner) => {
144
144
  1,
145
145
  (thisValue, args) => {
146
146
  const target = self(thisValue, "forEach");
147
- const apply = applyCollectionCallback(runner, args[0], "Map.forEach");
147
+ const apply = applyCollectionCallback(ctx, args[0], "Map.forEach");
148
148
  return Effect.gen(function* () {
149
149
  for (const [key, item] of Array.from(target.map.entries()))
150
150
  yield* apply([item, key, target]);
@@ -155,26 +155,26 @@ export const mapGlobal = (runner) => {
155
155
  ]);
156
156
  return map;
157
157
  };
158
- const loadSetRecord = (runner, source, name) => {
159
- if (source instanceof ProgramSet) {
158
+ const loadSetRecord = (ctx, source, name) => {
159
+ if (source instanceof SetObj) {
160
160
  return Effect.succeed({
161
161
  size: source.set.size,
162
162
  has: (item) => Effect.succeed(source.set.has(item)),
163
163
  keys: () => Effect.succeed(source.set.values()),
164
164
  });
165
165
  }
166
- if (source instanceof ProgramMap) {
166
+ if (source instanceof MapObj) {
167
167
  return Effect.succeed({
168
168
  size: source.map.size,
169
169
  has: (item) => Effect.succeed(source.map.has(item)),
170
170
  keys: () => Effect.succeed(source.map.keys()),
171
171
  });
172
172
  }
173
- if (!(source instanceof ProgramObject)) {
173
+ if (!(source instanceof Obj)) {
174
174
  throw typeError(`Set.${name} expects a Set-like object.`);
175
175
  }
176
176
  return Effect.gen(function* () {
177
- const size = yield* toPrimitiveNumber(runner, get(source, "size"));
177
+ const size = yield* toPrimitiveNumber(ctx, get(source, "size"));
178
178
  if (Number.isNaN(size)) {
179
179
  throw typeError(`Set.${name} received a Set-like object with an invalid size.`);
180
180
  }
@@ -185,19 +185,19 @@ const loadSetRecord = (runner, source, name) => {
185
185
  }
186
186
  return {
187
187
  size: Math.max(Math.trunc(size), 0),
188
- has: (item) => Effect.map(runner.invokeCallable(has, source, [item]), Boolean),
189
- keys: () => Effect.flatMap(runner.invokeCallable(keys, source, []), (result) => {
190
- if (result instanceof ProgramArray)
188
+ has: (item) => Effect.map(ctx.call(has, source, [item]), Boolean),
189
+ keys: () => Effect.flatMap(ctx.call(keys, source, []), (result) => {
190
+ if (result instanceof Arr)
191
191
  return Effect.succeed(result.items);
192
192
  throw typeError(`Set.${name} expected 'keys' to return an iterator.`);
193
193
  }),
194
194
  };
195
195
  });
196
196
  };
197
- const setOperation = (runner, target, name, source) => Effect.gen(function* () {
198
- const other = yield* loadSetRecord(runner, source, name);
197
+ const setOperation = (ctx, target, name, source) => Effect.gen(function* () {
198
+ const other = yield* loadSetRecord(ctx, source, name);
199
199
  const copy = () => {
200
- const result = new ProgramSet(runner.prototypes.Set);
200
+ const result = new SetObj(ctx.builtins.Set);
201
201
  for (const item of target.set.values())
202
202
  result.set.add(item);
203
203
  return result;
@@ -209,7 +209,7 @@ const setOperation = (runner, target, name, source) => Effect.gen(function* () {
209
209
  return result;
210
210
  }
211
211
  if (name === "intersection") {
212
- const result = new ProgramSet(runner.prototypes.Set);
212
+ const result = new SetObj(ctx.builtins.Set);
213
213
  if (target.set.size <= other.size) {
214
214
  for (const item of target.set.values()) {
215
215
  if (yield* other.has(item))
@@ -277,23 +277,23 @@ const setOperation = (runner, target, name, source) => Effect.gen(function* () {
277
277
  }
278
278
  return true;
279
279
  });
280
- export const setGlobal = (runner) => {
281
- const protos = runner.prototypes;
282
- const proto = protos.Set;
283
- const set = constructor(protos, proto, {
280
+ export const setGlobal = (ctx) => {
281
+ const builtins = ctx.builtins;
282
+ const proto = builtins.Set;
283
+ const set = constructor(builtins, proto, {
284
284
  name: "Set",
285
285
  call: requiresNew("Set"),
286
- construct: (args, newTarget) => constructSet(runner, args[0], prototypeFrom(newTarget, proto)),
286
+ construct: (args, newTarget) => constructSet(ctx, args[0], prototypeFrom(newTarget, proto)),
287
287
  });
288
- const self = (thisValue, name) => receiver(ProgramSet, thisValue, `Set.prototype.${name}`);
289
- const wrap = (items) => new ProgramArray(protos.Array, items);
288
+ const self = (thisValue, name) => receiver(SetObj, thisValue, `Set.prototype.${name}`);
289
+ const wrap = (items) => new Arr(builtins.Array, items);
290
290
  const operation = (name) => [
291
291
  name,
292
292
  1,
293
- (thisValue, args) => setOperation(runner, self(thisValue, name), name, args[0]),
293
+ (thisValue, args) => setOperation(ctx, self(thisValue, name), name, args[0]),
294
294
  ];
295
- defineAccessor(proto, "size", (thisValue) => receiver(ProgramSet, thisValue, "Set.prototype.size").set.size);
296
- methods(protos, proto, [
295
+ defineAccessor(proto, "size", (thisValue) => receiver(SetObj, thisValue, "Set.prototype.size").set.size);
296
+ methods(builtins, proto, [
297
297
  ["has", 1, (thisValue, args) => self(thisValue, "has").set.has(args[0])],
298
298
  [
299
299
  "add",
@@ -325,7 +325,7 @@ export const setGlobal = (runner) => {
325
325
  1,
326
326
  (thisValue, args) => {
327
327
  const target = self(thisValue, "forEach");
328
- const apply = applyCollectionCallback(runner, args[0], "Set.forEach");
328
+ const apply = applyCollectionCallback(ctx, args[0], "Set.forEach");
329
329
  return Effect.gen(function* () {
330
330
  for (const item of Array.from(target.set.values()))
331
331
  yield* apply([item, item, target]);
@@ -1,4 +1,4 @@
1
- import { ProgramObject } from "../interpreter/objects.js";
2
- import type { Runner } from "../interpreter/runner.js";
1
+ import { Obj } from "../interpreter/objects.js";
2
+ import type { Interpreter } from "../interpreter/interpreter.js";
3
3
  /** Captured console: every method appends one formatted line to `logs`. */
4
- export declare const consoleGlobal: <R>(runner: Runner<R>, logs: Array<string>) => ProgramObject;
4
+ export declare const consoleGlobal: <R>(ctx: Interpreter<R>) => Obj;
@@ -1,29 +1,29 @@
1
1
  import { toData, toProgram } from "../data.js";
2
2
  import { methods } from "../interpreter/native.js";
3
- import { entries, get, ProgramArray, ProgramDate, ProgramMap, ProgramObject, ProgramPromise, ProgramRegExp, ProgramSet, ProgramURL, ProgramURLSearchParams, } from "../interpreter/objects.js";
3
+ import { entries, get, Arr, Bytes, DateObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "../interpreter/objects.js";
4
4
  import { containsOpaqueReference, containsRuntimeReference, isRuntimeReference } from "../interpreter/references.js";
5
5
  import { coerceToString } from "./value.js";
6
6
  const consoleMethods = ["log", "info", "debug", "warn", "error", "dir", "table"];
7
7
  /** Captured console: every method appends one formatted line to `logs`. */
8
- export const consoleGlobal = (runner, logs) => {
9
- const protos = runner.prototypes;
10
- const console = new ProgramObject(protos.Object);
11
- methods(protos, console, consoleMethods.map((name) => [
8
+ export const consoleGlobal = (ctx) => {
9
+ const builtins = ctx.builtins;
10
+ const console = new Obj(builtins.Object);
11
+ methods(builtins, console, consoleMethods.map((name) => [
12
12
  name,
13
13
  0,
14
14
  (_, args) => {
15
- logs.push(formatConsoleMessage(protos, name, args));
15
+ ctx.logs.push(formatConsoleMessage(builtins, name, args));
16
16
  return undefined;
17
17
  },
18
18
  ]));
19
19
  return console;
20
20
  };
21
21
  const MAX_CONSOLE_DEPTH = 32;
22
- const formatConsoleMessage = (protos, name, args) => {
22
+ const formatConsoleMessage = (builtins, name, args) => {
23
23
  if (name === "dir")
24
24
  return args.length === 0 ? "undefined" : formatConsoleArgument(args[0]);
25
25
  if (name === "table")
26
- return formatConsoleTable(protos, args[0], args[1]);
26
+ return formatConsoleTable(builtins, args[0], args[1]);
27
27
  const prefix = name === "warn" ? "[warn] " : name === "error" ? "[error] " : name === "debug" ? "[debug] " : "";
28
28
  return `${prefix}${args.map((arg) => formatConsoleArgument(arg)).join(" ")}`;
29
29
  };
@@ -43,21 +43,23 @@ const formatConsoleValue = (value, seen, depth) => {
43
43
  return String(value);
44
44
  if (typeof value !== "object")
45
45
  return String(value);
46
- if (value instanceof ProgramPromise)
46
+ if (value instanceof PromiseObj)
47
47
  return "[Promise (await it to get its value)]";
48
- if (value instanceof ProgramDate)
48
+ if (value instanceof DateObj)
49
49
  return coerceToString(value);
50
- if (value instanceof ProgramRegExp)
50
+ if (value instanceof RegExpObj)
51
51
  return coerceToString(value);
52
- if (value instanceof ProgramURL)
52
+ if (value instanceof URLObj)
53
53
  return coerceToString(value);
54
- if (value instanceof ProgramURLSearchParams)
54
+ if (value instanceof URLSearchParamsObj)
55
55
  return coerceToString(value);
56
+ if (value instanceof Bytes)
57
+ return `Uint8Array(${value.bytes.length}) [${value.bytes.join(",")}]`;
56
58
  if (depth > MAX_CONSOLE_DEPTH)
57
59
  return "...";
58
60
  if (seen.has(value))
59
61
  return "[Circular]";
60
- if (value instanceof ProgramMap) {
62
+ if (value instanceof MapObj) {
61
63
  seen.add(value);
62
64
  try {
63
65
  const items = Array.from(value.map.entries(), ([key, item]) => `[${formatItems([key, item], seen, depth + 1)}]`);
@@ -67,7 +69,7 @@ const formatConsoleValue = (value, seen, depth) => {
67
69
  seen.delete(value);
68
70
  }
69
71
  }
70
- if (value instanceof ProgramSet) {
72
+ if (value instanceof SetObj) {
71
73
  seen.add(value);
72
74
  try {
73
75
  return `Set(${value.set.size}) [${formatItems([...value.set.values()], seen, depth + 1)}]`;
@@ -80,9 +82,9 @@ const formatConsoleValue = (value, seen, depth) => {
80
82
  return "[opaque reference]";
81
83
  seen.add(value);
82
84
  try {
83
- if (value instanceof ProgramArray)
85
+ if (value instanceof Arr)
84
86
  return `[${formatItems(value.items, seen, depth + 1)}]`;
85
- if (!(value instanceof ProgramObject))
87
+ if (!(value instanceof Obj))
86
88
  return "[object Object]";
87
89
  return `{${entries(value)
88
90
  .map(([key, item]) => `${JSON.stringify(key)}:${formatConsoleValue(item, seen, depth + 1)}`)
@@ -93,12 +95,12 @@ const formatConsoleValue = (value, seen, depth) => {
93
95
  }
94
96
  };
95
97
  const formatItems = (items, seen, depth) => items.map((item) => formatConsoleValue(item, seen, depth)).join(",");
96
- const formatConsoleTable = (protos, value, columnsArgument) => {
98
+ const formatConsoleTable = (builtins, value, columnsArgument) => {
97
99
  if (value === undefined)
98
100
  return "undefined";
99
101
  if (containsOpaqueReference(value))
100
102
  return "[opaque reference]";
101
- const data = toProgram(protos, value, "console.table argument");
103
+ const data = toProgram(builtins, value, "console.table argument");
102
104
  const columns = consoleTableColumns(columnsArgument);
103
105
  const rows = consoleTableRows(data, columns);
104
106
  const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values))));
@@ -117,16 +119,16 @@ const consoleTableColumns = (value) => {
117
119
  return Array.isArray(columns) ? columns.map((column) => String(column)) : undefined;
118
120
  };
119
121
  const consoleTableRows = (data, columns) => {
120
- if (data instanceof ProgramArray) {
122
+ if (data instanceof Arr) {
121
123
  return data.items.map((item, index) => ({ index: String(index), values: consoleTableValues(item, columns) }));
122
124
  }
123
- if (data instanceof ProgramObject) {
125
+ if (data instanceof Obj) {
124
126
  return entries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
125
127
  }
126
128
  return [{ index: "0", values: { Value: data } }];
127
129
  };
128
130
  const consoleTableValues = (value, columns) => {
129
- if (value instanceof ProgramObject && !(value instanceof ProgramArray)) {
131
+ if (value instanceof Obj && !(value instanceof Arr)) {
130
132
  if (columns !== undefined)
131
133
  return Object.fromEntries(columns.map((column) => [column, get(value, column)]));
132
134
  return Object.fromEntries(entries(value));
@@ -1,2 +1,2 @@
1
- import { type Runner } from "../interpreter/runner.js";
2
- export declare const dateGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
1
+ import type { Interpreter } from "../interpreter/interpreter.js";
2
+ export declare const dateGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;