@opencode/codemode 2.0.0 → 2.0.2

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/data.d.ts +6 -5
  2. package/dist/data.js +47 -44
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.js +0 -1
  5. package/dist/interpreter/errors.d.ts +5 -3
  6. package/dist/interpreter/errors.js +51 -22
  7. package/dist/interpreter/execute.js +5 -3
  8. package/dist/interpreter/generators.d.ts +4 -0
  9. package/dist/interpreter/generators.js +25 -0
  10. package/dist/interpreter/globals.js +69 -47
  11. package/dist/interpreter/intrinsics.d.ts +13 -0
  12. package/dist/interpreter/intrinsics.js +82 -0
  13. package/dist/interpreter/model.d.ts +13 -36
  14. package/dist/interpreter/model.js +15 -45
  15. package/dist/interpreter/native.d.ts +19 -0
  16. package/dist/interpreter/native.js +40 -0
  17. package/dist/interpreter/objects.d.ts +106 -13
  18. package/dist/interpreter/objects.js +192 -65
  19. package/dist/interpreter/promises.d.ts +12 -13
  20. package/dist/interpreter/promises.js +59 -54
  21. package/dist/interpreter/references.d.ts +1 -0
  22. package/dist/interpreter/references.js +20 -33
  23. package/dist/interpreter/runner.d.ts +15 -11
  24. package/dist/interpreter/runner.js +21 -21
  25. package/dist/interpreter/runtime.d.ts +3 -3
  26. package/dist/interpreter/runtime.js +165 -327
  27. package/dist/interpreter/scope.js +6 -6
  28. package/dist/stdlib/array.d.ts +4 -2
  29. package/dist/stdlib/array.js +424 -32
  30. package/dist/stdlib/collections.d.ts +3 -7
  31. package/dist/stdlib/collections.js +291 -119
  32. package/dist/stdlib/console.d.ts +3 -2
  33. package/dist/stdlib/console.js +35 -30
  34. package/dist/stdlib/date.d.ts +1 -7
  35. package/dist/stdlib/date.js +93 -188
  36. package/dist/stdlib/json.d.ts +2 -2
  37. package/dist/stdlib/json.js +27 -27
  38. package/dist/stdlib/math.d.ts +2 -2
  39. package/dist/stdlib/math.js +96 -76
  40. package/dist/stdlib/number.d.ts +3 -4
  41. package/dist/stdlib/number.js +95 -60
  42. package/dist/stdlib/object.d.ts +4 -4
  43. package/dist/stdlib/object.js +128 -54
  44. package/dist/stdlib/regexp.d.ts +6 -8
  45. package/dist/stdlib/regexp.js +76 -68
  46. package/dist/stdlib/string.d.ts +2 -2
  47. package/dist/stdlib/string.js +213 -50
  48. package/dist/stdlib/url.d.ts +5 -13
  49. package/dist/stdlib/url.js +202 -102
  50. package/dist/stdlib/value.d.ts +5 -9
  51. package/dist/stdlib/value.js +16 -38
  52. package/dist/stdlib/web.d.ts +4 -4
  53. package/dist/stdlib/web.js +12 -10
  54. package/dist/tool-runtime.d.ts +2 -1
  55. package/dist/tool-runtime.js +2 -2
  56. package/package.json +1 -1
  57. package/dist/interpreter/host.d.ts +0 -41
  58. package/dist/interpreter/host.js +0 -44
  59. package/dist/interpreter/methods.d.ts +0 -4
  60. package/dist/interpreter/methods.js +0 -837
  61. package/dist/values.d.ts +0 -37
  62. package/dist/values.js +0 -56
@@ -1,132 +1,73 @@
1
1
  import { Effect } from "effect";
2
- import { HostFunction, requiresNew } from "../interpreter/host.js";
2
+ import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
3
3
  import { InterpreterRuntimeError } from "../interpreter/model.js";
4
- import { getOwn, ProgramArray, ProgramObject, set } from "../interpreter/objects.js";
4
+ import { define, defineAccessor, get, getOwn, hidden, isWrapper, ProgramArray, ProgramMap, ProgramObject, ProgramPromise, ProgramSet, } from "../interpreter/objects.js";
5
5
  import { describeValue, isRuntimeReference } from "../interpreter/references.js";
6
- import { applyCollectionCallback, preserveConsumerError, toPrimitive } from "../interpreter/runner.js";
7
- import { Values } from "../values.js";
8
- import { coerceToString } from "./value.js";
9
- export const arrayMethods = new Set([
10
- "map",
11
- "filter",
12
- "find",
13
- "findIndex",
14
- "findLast",
15
- "findLastIndex",
16
- "some",
17
- "every",
18
- "includes",
19
- "join",
20
- "reduce",
21
- "reduceRight",
22
- "flatMap",
23
- "forEach",
24
- "sort",
25
- "toSorted",
26
- "slice",
27
- "concat",
28
- "indexOf",
29
- "lastIndexOf",
30
- "at",
31
- "flat",
32
- "reverse",
33
- "toReversed",
34
- "with",
35
- "push",
36
- "pop",
37
- "shift",
38
- "unshift",
39
- "splice",
40
- "toSpliced",
41
- "fill",
42
- "copyWithin",
43
- "keys",
44
- "values",
45
- "entries",
46
- ]);
47
- export const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]);
48
- export const setMethods = new Set([
49
- "add",
50
- "has",
51
- "delete",
52
- "clear",
53
- "forEach",
54
- "keys",
55
- "values",
56
- "entries",
57
- "union",
58
- "intersection",
59
- "difference",
60
- "symmetricDifference",
61
- "isSubsetOf",
62
- "isSupersetOf",
63
- "isDisjointFrom",
64
- ]);
6
+ import { applyCollectionCallback, isSupportedCallback, preserveConsumerError, toPrimitiveNumber, toPrimitiveString, } from "../interpreter/runner.js";
65
7
  const coerceGroupByPropertyKey = (runner, value, node) => {
66
- if (value instanceof Values.Promise)
8
+ if (value instanceof ProgramPromise)
67
9
  return Effect.succeed("[object Promise]");
68
- if (!Values.isValue(value) && isRuntimeReference(value)) {
10
+ if (!isWrapper(value) && isRuntimeReference(value)) {
69
11
  throw new InterpreterRuntimeError(`Object.groupBy callback must return a data value, received ${describeValue(value)}.`, node, "InvalidDataValue");
70
12
  }
71
- return Effect.map(toPrimitive(runner, value, "string", node), coerceToString);
13
+ return toPrimitiveString(runner, value, node);
72
14
  };
73
15
  /** `Map.groupBy` and `Object.groupBy`: the same iteration, keyed into a Map or a data object. */
74
- export const groupBy = (runner, namespace) => new HostFunction({
75
- name: `${namespace}.groupBy`,
76
- call: (args, node) => {
77
- const source = args[0];
78
- if (source === null || source === undefined) {
79
- throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError");
80
- }
81
- const apply = applyCollectionCallback(runner, args[1], `${namespace}.groupBy`, node);
82
- return Effect.gen(function* () {
83
- const cursor = yield* runner.syncIterator(source, node);
84
- if (cursor === undefined) {
85
- throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError");
86
- }
87
- if (namespace === "Map") {
88
- const result = new Values.Map();
89
- let index = 0;
90
- while (true) {
91
- const step = yield* cursor.next;
92
- if (step.done)
93
- return result;
94
- const item = step.value;
95
- const key = yield* preserveConsumerError(cursor, apply([item, index]));
96
- const group = result.map.get(key);
97
- if (group === undefined)
98
- result.map.set(key, new ProgramArray([item]));
99
- else
100
- group.items.push(item);
101
- index += 1;
102
- }
103
- }
104
- const result = new ProgramObject();
16
+ export const groupBy = (runner, namespace) => fn(runner.prototypes, "groupBy", 2, (_, args, node) => {
17
+ const protos = runner.prototypes;
18
+ const source = args[0];
19
+ if (source === null || source === undefined) {
20
+ throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node);
21
+ }
22
+ const apply = applyCollectionCallback(runner, args[1], `${namespace}.groupBy`, node);
23
+ return Effect.gen(function* () {
24
+ const cursor = yield* runner.syncIterator(source, node);
25
+ if (cursor === undefined) {
26
+ throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node);
27
+ }
28
+ if (namespace === "Map") {
29
+ const result = new ProgramMap(protos.Map);
105
30
  let index = 0;
106
31
  while (true) {
107
32
  const step = yield* cursor.next;
108
33
  if (step.done)
109
34
  return result;
110
35
  const item = step.value;
111
- const key = yield* preserveConsumerError(cursor, Effect.flatMap(apply([item, index]), (value) => coerceGroupByPropertyKey(runner, value, node)));
112
- const group = getOwn(result, key);
36
+ const key = yield* preserveConsumerError(cursor, apply([item, index]));
37
+ const group = result.map.get(key);
113
38
  if (group === undefined)
114
- set(result, key, new ProgramArray([item]));
39
+ result.map.set(key, new ProgramArray(protos.Array, [item]));
115
40
  else
116
41
  group.items.push(item);
117
42
  index += 1;
118
43
  }
119
- });
120
- },
44
+ }
45
+ // Object.groupBy returns a null-prototype object, so group names never collide with inherited methods.
46
+ const result = new ProgramObject(null);
47
+ let index = 0;
48
+ while (true) {
49
+ const step = yield* cursor.next;
50
+ if (step.done)
51
+ return result;
52
+ const item = step.value;
53
+ const key = yield* preserveConsumerError(cursor, Effect.flatMap(apply([item, index]), (value) => coerceGroupByPropertyKey(runner, value, node)));
54
+ const group = getOwn(result, key);
55
+ if (group === undefined)
56
+ define(result, key, new ProgramArray(protos.Array, [item]));
57
+ else
58
+ group.items.push(item);
59
+ index += 1;
60
+ }
61
+ });
121
62
  });
122
- const constructMap = (runner, init, node) => {
123
- const target = new Values.Map();
63
+ const constructMap = (runner, init, proto, node) => {
64
+ const target = new ProgramMap(proto);
124
65
  if (init === undefined || init === null)
125
66
  return Effect.succeed(target);
126
67
  return Effect.gen(function* () {
127
68
  const cursor = yield* runner.syncIterator(init, node);
128
69
  if (cursor === undefined) {
129
- throw new InterpreterRuntimeError("new Map(...) expects an iterable of [key, value] pairs or no argument.", node).as("TypeError");
70
+ throw new InterpreterRuntimeError("new Map(...) expects an iterable of [key, value] pairs or no argument.", node);
130
71
  }
131
72
  while (true) {
132
73
  const step = yield* cursor.next;
@@ -134,21 +75,21 @@ const constructMap = (runner, init, node) => {
134
75
  return target;
135
76
  yield* preserveConsumerError(cursor, Effect.sync(() => {
136
77
  if (!(step.value instanceof ProgramObject)) {
137
- throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node).as("TypeError");
78
+ throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node);
138
79
  }
139
80
  target.map.set(getOwn(step.value, 0), getOwn(step.value, 1));
140
81
  }));
141
82
  }
142
83
  });
143
84
  };
144
- const constructSet = (runner, init, node) => {
145
- const target = new Values.Set();
85
+ const constructSet = (runner, init, proto, node) => {
86
+ const target = new ProgramSet(proto);
146
87
  if (init === undefined || init === null)
147
88
  return Effect.succeed(target);
148
89
  return Effect.gen(function* () {
149
90
  const cursor = yield* runner.syncIterator(init, node);
150
91
  if (cursor === undefined) {
151
- throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node).as("TypeError");
92
+ throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node);
152
93
  }
153
94
  while (true) {
154
95
  const step = yield* cursor.next;
@@ -158,16 +99,247 @@ const constructSet = (runner, init, node) => {
158
99
  }
159
100
  });
160
101
  };
161
- export const mapGlobal = (runner) => new HostFunction({
162
- name: "Map",
163
- call: requiresNew("Map"),
164
- construct: (args, node) => constructMap(runner, args[0], node),
165
- instanceOf: (value) => value instanceof Values.Map,
166
- members: { groupBy: groupBy(runner, "Map") },
167
- });
168
- export const setGlobal = (runner) => new HostFunction({
169
- name: "Set",
170
- call: requiresNew("Set"),
171
- construct: (args, node) => constructSet(runner, args[0], node),
172
- instanceOf: (value) => value instanceof Values.Set,
102
+ export const mapGlobal = (runner) => {
103
+ const protos = runner.prototypes;
104
+ const proto = protos.Map;
105
+ const map = constructor(protos, proto, {
106
+ name: "Map",
107
+ call: requiresNew("Map"),
108
+ construct: (args, newTarget, node) => constructMap(runner, args[0], prototypeFrom(newTarget, proto), node),
109
+ });
110
+ define(map, "groupBy", groupBy(runner, "Map"), hidden);
111
+ const self = (thisValue, name, node) => receiver(ProgramMap, thisValue, `Map.prototype.${name}`, node);
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, [
115
+ ["get", 1, (thisValue, args, node) => self(thisValue, "get", node).map.get(args[0])],
116
+ ["has", 1, (thisValue, args, node) => self(thisValue, "has", node).map.has(args[0])],
117
+ [
118
+ "set",
119
+ 2,
120
+ (thisValue, args, node) => {
121
+ const target = self(thisValue, "set", node);
122
+ target.map.set(args[0], args[1]);
123
+ return target;
124
+ },
125
+ ],
126
+ ["delete", 1, (thisValue, args, node) => self(thisValue, "delete", node).map.delete(args[0])],
127
+ [
128
+ "clear",
129
+ 0,
130
+ (thisValue, _, node) => {
131
+ self(thisValue, "clear", node).map.clear();
132
+ return undefined;
133
+ },
134
+ ],
135
+ ["keys", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "keys", node).map.keys()))],
136
+ ["values", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "values", node).map.values()))],
137
+ [
138
+ "entries",
139
+ 0,
140
+ (thisValue, _, node) => wrap(Array.from(self(thisValue, "entries", node).map.entries(), ([key, item]) => wrap([key, item]))),
141
+ ],
142
+ [
143
+ "forEach",
144
+ 1,
145
+ (thisValue, args, node) => {
146
+ const target = self(thisValue, "forEach", node);
147
+ const apply = applyCollectionCallback(runner, args[0], "Map.forEach", node);
148
+ return Effect.gen(function* () {
149
+ for (const [key, item] of Array.from(target.map.entries()))
150
+ yield* apply([item, key, target]);
151
+ return undefined;
152
+ });
153
+ },
154
+ ],
155
+ ]);
156
+ return map;
157
+ };
158
+ const loadSetRecord = (runner, source, name, node) => {
159
+ if (source instanceof ProgramSet) {
160
+ return Effect.succeed({
161
+ size: source.set.size,
162
+ has: (item) => Effect.succeed(source.set.has(item)),
163
+ keys: () => Effect.succeed(source.set.values()),
164
+ });
165
+ }
166
+ if (source instanceof ProgramMap) {
167
+ return Effect.succeed({
168
+ size: source.map.size,
169
+ has: (item) => Effect.succeed(source.map.has(item)),
170
+ keys: () => Effect.succeed(source.map.keys()),
171
+ });
172
+ }
173
+ if (!(source instanceof ProgramObject)) {
174
+ throw new InterpreterRuntimeError(`Set.${name} expects a Set-like object.`, node);
175
+ }
176
+ return Effect.gen(function* () {
177
+ const size = yield* toPrimitiveNumber(runner, get(source, "size"), node);
178
+ if (Number.isNaN(size)) {
179
+ throw new InterpreterRuntimeError(`Set.${name} received a Set-like object with an invalid size.`, node);
180
+ }
181
+ const has = get(source, "has");
182
+ const keys = get(source, "keys");
183
+ if (!isSupportedCallback(has) || !isSupportedCallback(keys)) {
184
+ throw new InterpreterRuntimeError(`Set.${name} expects callable 'has' and 'keys' methods.`, node);
185
+ }
186
+ return {
187
+ size: Math.max(Math.trunc(size), 0),
188
+ has: (item) => Effect.map(runner.invokeCallable(has, source, [item], node), Boolean),
189
+ keys: () => Effect.flatMap(runner.invokeCallable(keys, source, [], node), (result) => {
190
+ if (result instanceof ProgramArray)
191
+ return Effect.succeed(result.items);
192
+ throw new InterpreterRuntimeError(`Set.${name} expected 'keys' to return an iterator.`, node);
193
+ }),
194
+ };
195
+ });
196
+ };
197
+ const setOperation = (runner, target, name, source, node) => Effect.gen(function* () {
198
+ const other = yield* loadSetRecord(runner, source, name, node);
199
+ const copy = () => {
200
+ const result = new ProgramSet(runner.prototypes.Set);
201
+ for (const item of target.set.values())
202
+ result.set.add(item);
203
+ return result;
204
+ };
205
+ if (name === "union") {
206
+ const result = copy();
207
+ for (const item of yield* other.keys())
208
+ result.set.add(item);
209
+ return result;
210
+ }
211
+ if (name === "intersection") {
212
+ const result = new ProgramSet(runner.prototypes.Set);
213
+ if (target.set.size <= other.size) {
214
+ for (const item of target.set.values()) {
215
+ if (yield* other.has(item))
216
+ result.set.add(item);
217
+ }
218
+ return result;
219
+ }
220
+ for (const item of yield* other.keys()) {
221
+ if (target.set.has(item))
222
+ result.set.add(item);
223
+ }
224
+ return result;
225
+ }
226
+ if (name === "difference") {
227
+ const result = copy();
228
+ if (target.set.size <= other.size) {
229
+ for (const item of result.set.values()) {
230
+ if (yield* other.has(item))
231
+ result.set.delete(item);
232
+ }
233
+ return result;
234
+ }
235
+ for (const item of yield* other.keys())
236
+ result.set.delete(item);
237
+ return result;
238
+ }
239
+ if (name === "symmetricDifference") {
240
+ const result = copy();
241
+ for (const item of yield* other.keys()) {
242
+ if (target.set.has(item))
243
+ result.set.delete(item);
244
+ else
245
+ result.set.add(item);
246
+ }
247
+ return result;
248
+ }
249
+ if (name === "isSubsetOf") {
250
+ if (target.set.size > other.size)
251
+ return false;
252
+ for (const item of target.set.values()) {
253
+ if (!(yield* other.has(item)))
254
+ return false;
255
+ }
256
+ return true;
257
+ }
258
+ if (name === "isSupersetOf") {
259
+ if (target.set.size < other.size)
260
+ return false;
261
+ for (const item of yield* other.keys()) {
262
+ if (!target.set.has(item))
263
+ return false;
264
+ }
265
+ return true;
266
+ }
267
+ if (target.set.size <= other.size) {
268
+ for (const item of target.set.values()) {
269
+ if (yield* other.has(item))
270
+ return false;
271
+ }
272
+ return true;
273
+ }
274
+ for (const item of yield* other.keys()) {
275
+ if (target.set.has(item))
276
+ return false;
277
+ }
278
+ return true;
173
279
  });
280
+ export const setGlobal = (runner) => {
281
+ const protos = runner.prototypes;
282
+ const proto = protos.Set;
283
+ const set = constructor(protos, proto, {
284
+ name: "Set",
285
+ call: requiresNew("Set"),
286
+ construct: (args, newTarget, node) => constructSet(runner, args[0], prototypeFrom(newTarget, proto), node),
287
+ });
288
+ const self = (thisValue, name, node) => receiver(ProgramSet, thisValue, `Set.prototype.${name}`, node);
289
+ const wrap = (items) => new ProgramArray(protos.Array, items);
290
+ const operation = (name) => [
291
+ name,
292
+ 1,
293
+ (thisValue, args, node) => setOperation(runner, self(thisValue, name, node), name, args[0], node),
294
+ ];
295
+ defineAccessor(proto, "size", (thisValue) => receiver(ProgramSet, thisValue, "Set.prototype.size").set.size);
296
+ methods(protos, proto, [
297
+ ["has", 1, (thisValue, args, node) => self(thisValue, "has", node).set.has(args[0])],
298
+ [
299
+ "add",
300
+ 1,
301
+ (thisValue, args, node) => {
302
+ const target = self(thisValue, "add", node);
303
+ target.set.add(args[0]);
304
+ return target;
305
+ },
306
+ ],
307
+ ["delete", 1, (thisValue, args, node) => self(thisValue, "delete", node).set.delete(args[0])],
308
+ [
309
+ "clear",
310
+ 0,
311
+ (thisValue, _, node) => {
312
+ self(thisValue, "clear", node).set.clear();
313
+ return undefined;
314
+ },
315
+ ],
316
+ ["keys", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "keys", node).set.values()))],
317
+ ["values", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "values", node).set.values()))],
318
+ [
319
+ "entries",
320
+ 0,
321
+ (thisValue, _, node) => wrap(Array.from(self(thisValue, "entries", node).set.values(), (item) => wrap([item, item]))),
322
+ ],
323
+ [
324
+ "forEach",
325
+ 1,
326
+ (thisValue, args, node) => {
327
+ const target = self(thisValue, "forEach", node);
328
+ const apply = applyCollectionCallback(runner, args[0], "Set.forEach", node);
329
+ return Effect.gen(function* () {
330
+ for (const item of Array.from(target.set.values()))
331
+ yield* apply([item, item, target]);
332
+ return undefined;
333
+ });
334
+ },
335
+ ],
336
+ operation("union"),
337
+ operation("intersection"),
338
+ operation("difference"),
339
+ operation("symmetricDifference"),
340
+ operation("isSubsetOf"),
341
+ operation("isSupersetOf"),
342
+ operation("isDisjointFrom"),
343
+ ]);
344
+ return set;
345
+ };
@@ -1,3 +1,4 @@
1
- import { HostNamespace } from "../interpreter/host.js";
1
+ import { ProgramObject } from "../interpreter/objects.js";
2
+ import type { Runner } from "../interpreter/runner.js";
2
3
  /** Captured console: every method appends one formatted line to `logs`. */
3
- export declare const consoleGlobal: (logs: Array<string>) => HostNamespace;
4
+ export declare const consoleGlobal: <R>(runner: Runner<R>, logs: Array<string>) => ProgramObject;
@@ -1,24 +1,29 @@
1
1
  import { toData, toProgram } from "../data.js";
2
- import { HostNamespace, sync } from "../interpreter/host.js";
3
- import { get, ownEntries, ProgramArray, ProgramObject } from "../interpreter/objects.js";
2
+ import { methods } from "../interpreter/native.js";
3
+ import { entries, get, ProgramArray, ProgramDate, ProgramMap, ProgramObject, ProgramPromise, ProgramRegExp, ProgramSet, ProgramURL, ProgramURLSearchParams, } from "../interpreter/objects.js";
4
4
  import { containsOpaqueReference, containsRuntimeReference, isRuntimeReference } from "../interpreter/references.js";
5
- import { Values } from "../values.js";
6
5
  import { coerceToString } from "./value.js";
7
6
  const consoleMethods = ["log", "info", "debug", "warn", "error", "dir", "table"];
8
7
  /** Captured console: every method appends one formatted line to `logs`. */
9
- export const consoleGlobal = (logs) => new HostNamespace("console", Object.fromEntries(consoleMethods.map((name) => [
10
- name,
11
- sync(`console.${name}`, (args) => {
12
- logs.push(formatConsoleMessage(name, args));
13
- return undefined;
14
- }),
15
- ])));
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) => [
12
+ name,
13
+ 0,
14
+ (_, args) => {
15
+ logs.push(formatConsoleMessage(protos, name, args));
16
+ return undefined;
17
+ },
18
+ ]));
19
+ return console;
20
+ };
16
21
  const MAX_CONSOLE_DEPTH = 32;
17
- const formatConsoleMessage = (name, args) => {
22
+ const formatConsoleMessage = (protos, name, args) => {
18
23
  if (name === "dir")
19
24
  return args.length === 0 ? "undefined" : formatConsoleArgument(args[0]);
20
25
  if (name === "table")
21
- return formatConsoleTable(args[0], args[1]);
26
+ return formatConsoleTable(protos, args[0], args[1]);
22
27
  const prefix = name === "warn" ? "[warn] " : name === "error" ? "[error] " : name === "debug" ? "[debug] " : "";
23
28
  return `${prefix}${args.map((arg) => formatConsoleArgument(arg)).join(" ")}`;
24
29
  };
@@ -38,34 +43,34 @@ const formatConsoleValue = (value, seen, depth) => {
38
43
  return String(value);
39
44
  if (typeof value !== "object")
40
45
  return String(value);
41
- if (value instanceof Values.Promise)
46
+ if (value instanceof ProgramPromise)
42
47
  return "[Promise (await it to get its value)]";
43
- if (value instanceof Values.Date)
48
+ if (value instanceof ProgramDate)
44
49
  return coerceToString(value);
45
- if (value instanceof Values.RegExp)
50
+ if (value instanceof ProgramRegExp)
46
51
  return coerceToString(value);
47
- if (value instanceof Values.URL)
52
+ if (value instanceof ProgramURL)
48
53
  return coerceToString(value);
49
- if (value instanceof Values.URLSearchParams)
54
+ if (value instanceof ProgramURLSearchParams)
50
55
  return coerceToString(value);
51
56
  if (depth > MAX_CONSOLE_DEPTH)
52
57
  return "...";
53
58
  if (seen.has(value))
54
59
  return "[Circular]";
55
- if (value instanceof Values.Map) {
60
+ if (value instanceof ProgramMap) {
56
61
  seen.add(value);
57
62
  try {
58
- const entries = Array.from(value.map.entries(), ([key, item]) => new ProgramArray([key, item]));
59
- return `Map(${value.map.size}) ${formatConsoleValue(new ProgramArray(entries), seen, depth + 1)}`;
63
+ const items = Array.from(value.map.entries(), ([key, item]) => `[${formatItems([key, item], seen, depth + 1)}]`);
64
+ return `Map(${value.map.size}) [${items.join(",")}]`;
60
65
  }
61
66
  finally {
62
67
  seen.delete(value);
63
68
  }
64
69
  }
65
- if (value instanceof Values.Set) {
70
+ if (value instanceof ProgramSet) {
66
71
  seen.add(value);
67
72
  try {
68
- return `Set(${value.set.size}) ${formatConsoleValue(new ProgramArray([...value.set.values()]), seen, depth + 1)}`;
73
+ return `Set(${value.set.size}) [${formatItems([...value.set.values()], seen, depth + 1)}]`;
69
74
  }
70
75
  finally {
71
76
  seen.delete(value);
@@ -75,12 +80,11 @@ const formatConsoleValue = (value, seen, depth) => {
75
80
  return "[opaque reference]";
76
81
  seen.add(value);
77
82
  try {
78
- if (value instanceof ProgramArray) {
79
- return `[${value.items.map((item) => formatConsoleValue(item, seen, depth + 1)).join(",")}]`;
80
- }
83
+ if (value instanceof ProgramArray)
84
+ return `[${formatItems(value.items, seen, depth + 1)}]`;
81
85
  if (!(value instanceof ProgramObject))
82
86
  return "[object Object]";
83
- return `{${ownEntries(value)
87
+ return `{${entries(value)
84
88
  .map(([key, item]) => `${JSON.stringify(key)}:${formatConsoleValue(item, seen, depth + 1)}`)
85
89
  .join(",")}}`;
86
90
  }
@@ -88,12 +92,13 @@ const formatConsoleValue = (value, seen, depth) => {
88
92
  seen.delete(value);
89
93
  }
90
94
  };
91
- const formatConsoleTable = (value, columnsArgument) => {
95
+ const formatItems = (items, seen, depth) => items.map((item) => formatConsoleValue(item, seen, depth)).join(",");
96
+ const formatConsoleTable = (protos, value, columnsArgument) => {
92
97
  if (value === undefined)
93
98
  return "undefined";
94
99
  if (containsOpaqueReference(value))
95
100
  return "[opaque reference]";
96
- const data = toProgram(value, "console.table argument");
101
+ const data = toProgram(protos, value, "console.table argument");
97
102
  const columns = consoleTableColumns(columnsArgument);
98
103
  const rows = consoleTableRows(data, columns);
99
104
  const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values))));
@@ -116,7 +121,7 @@ const consoleTableRows = (data, columns) => {
116
121
  return data.items.map((item, index) => ({ index: String(index), values: consoleTableValues(item, columns) }));
117
122
  }
118
123
  if (data instanceof ProgramObject) {
119
- return ownEntries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
124
+ return entries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
120
125
  }
121
126
  return [{ index: "0", values: { Value: data } }];
122
127
  };
@@ -124,7 +129,7 @@ const consoleTableValues = (value, columns) => {
124
129
  if (value instanceof ProgramObject && !(value instanceof ProgramArray)) {
125
130
  if (columns !== undefined)
126
131
  return Object.fromEntries(columns.map((column) => [column, get(value, column)]));
127
- return Object.fromEntries(ownEntries(value));
132
+ return Object.fromEntries(entries(value));
128
133
  }
129
134
  return { Value: value };
130
135
  };
@@ -1,8 +1,2 @@
1
- import { HostFunction } from "../interpreter/host.js";
2
- import { type AstNode } from "../interpreter/model.js";
3
1
  import { type Runner } from "../interpreter/runner.js";
4
- import { Values } from "../values.js";
5
- export declare const dateMethods: Set<string>;
6
- export declare const dateGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
7
- export declare const dateSetterArgumentCount: (name: string) => number | undefined;
8
- export declare const invokeDateMethod: (value: Values.Date, name: string, args: Array<number>, node: AstNode, initialTime?: number) => unknown;
2
+ export declare const dateGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;