@opencode/codemode 0.0.0-beta-19507 → 0.0.0-dev-19274

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 (65) hide show
  1. package/README.md +0 -6
  2. package/dist/codemode.d.ts +12 -9
  3. package/dist/codemode.js +9 -5
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.js +0 -1
  6. package/dist/interpreter/errors.d.ts +6 -4
  7. package/dist/interpreter/errors.js +10 -25
  8. package/dist/interpreter/execute.d.ts +3 -4
  9. package/dist/interpreter/execute.js +18 -11
  10. package/dist/interpreter/iterator.d.ts +13 -0
  11. package/dist/interpreter/iterator.js +4 -0
  12. package/dist/interpreter/methods.d.ts +16 -3
  13. package/dist/interpreter/methods.js +290 -101
  14. package/dist/interpreter/model.d.ts +79 -10
  15. package/dist/interpreter/model.js +102 -2
  16. package/dist/interpreter/promises.d.ts +13 -15
  17. package/dist/interpreter/promises.js +52 -70
  18. package/dist/interpreter/references.d.ts +0 -1
  19. package/dist/interpreter/references.js +77 -57
  20. package/dist/interpreter/runtime.d.ts +95 -16
  21. package/dist/interpreter/runtime.js +960 -549
  22. package/dist/openapi/spec.js +6 -3
  23. package/dist/stdlib/collections.d.ts +1 -6
  24. package/dist/stdlib/collections.js +1 -117
  25. package/dist/stdlib/console.d.ts +2 -3
  26. package/dist/stdlib/console.js +28 -39
  27. package/dist/stdlib/date.d.ts +4 -5
  28. package/dist/stdlib/date.js +12 -34
  29. package/dist/stdlib/json.d.ts +6 -3
  30. package/dist/stdlib/json.js +63 -40
  31. package/dist/stdlib/math.d.ts +7 -3
  32. package/dist/stdlib/math.js +153 -85
  33. package/dist/stdlib/number.d.ts +4 -2
  34. package/dist/stdlib/number.js +37 -30
  35. package/dist/stdlib/object.d.ts +6 -6
  36. package/dist/stdlib/object.js +87 -84
  37. package/dist/stdlib/promise.d.ts +2 -0
  38. package/dist/stdlib/promise.js +1 -0
  39. package/dist/stdlib/regexp.d.ts +7 -6
  40. package/dist/stdlib/regexp.js +34 -48
  41. package/dist/stdlib/string.d.ts +3 -1
  42. package/dist/stdlib/string.js +17 -20
  43. package/dist/stdlib/url.d.ts +6 -10
  44. package/dist/stdlib/url.js +25 -102
  45. package/dist/stdlib/value.d.ts +7 -8
  46. package/dist/stdlib/value.js +56 -56
  47. package/dist/tool-runtime.d.ts +15 -16
  48. package/dist/tool-runtime.js +150 -13
  49. package/dist/values.d.ts +16 -22
  50. package/dist/values.js +17 -23
  51. package/package.json +1 -1
  52. package/dist/data.d.ts +0 -25
  53. package/dist/data.js +0 -153
  54. package/dist/interpreter/globals.d.ts +0 -13
  55. package/dist/interpreter/globals.js +0 -63
  56. package/dist/interpreter/host.d.ts +0 -41
  57. package/dist/interpreter/host.js +0 -44
  58. package/dist/interpreter/objects.d.ts +0 -37
  59. package/dist/interpreter/objects.js +0 -151
  60. package/dist/interpreter/runner.d.ts +0 -24
  61. package/dist/interpreter/runner.js +0 -45
  62. package/dist/stdlib/array.d.ts +0 -3
  63. package/dist/stdlib/array.js +0 -68
  64. package/dist/stdlib/web.d.ts +0 -4
  65. package/dist/stdlib/web.js +0 -20
@@ -1,4 +1,5 @@
1
1
  import { fromSchemaOpenApi3_0, fromSchemaOpenApi3_1 } from "effect/JsonSchema";
2
+ import { isBlockedMember } from "../tool-runtime.js";
2
3
  export const methods = new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
3
4
  const parameterLocations = ["path", "query", "header"];
4
5
  const ignoredHeaderParameters = new Set(["accept", "content-type", "authorization"]);
@@ -362,7 +363,8 @@ export const operationInput = (document, pathItem, operation) => {
362
363
  ok: true,
363
364
  value: {
364
365
  fields: fields.map((field) => {
365
- const base = conflicts.has(field.name) ? `${field.location}_${field.name}` : field.name;
366
+ const visibleName = isBlockedMember(field.name) ? `${field.name}_2` : field.name;
367
+ const base = conflicts.has(field.name) ? `${field.location}_${visibleName}` : visibleName;
366
368
  const next = (index) => {
367
369
  const candidate = index === 1 ? base : `${base}_${index}`;
368
370
  return used.has(candidate) ? next(index + 1) : candidate;
@@ -442,10 +444,11 @@ export const operationOutput = (document, operation, definitions) => {
442
444
  };
443
445
  };
444
446
  const sanitizeOperationSegment = (raw) => {
445
- return (raw
447
+ const base = raw
446
448
  .replaceAll(/[^A-Za-z0-9_$]+/g, "_")
447
449
  .replace(/^_+|_+$/g, "")
448
- .replace(/^([0-9])/, "_$1") || "operation");
450
+ .replace(/^([0-9])/, "_$1") || "operation";
451
+ return isBlockedMember(base) ? `${base}_2` : base;
449
452
  };
450
453
  const fallbackOperationId = (method, path) => [
451
454
  method,
@@ -1,9 +1,4 @@
1
- import { HostFunction } from "../interpreter/host.js";
2
- import { type Runner } from "../interpreter/runner.js";
3
1
  export declare const arrayMethods: Set<string>;
4
2
  export declare const mapMethods: Set<string>;
3
+ export declare const mapStatics: Set<string>;
5
4
  export declare const setMethods: Set<string>;
6
- /** `Map.groupBy` and `Object.groupBy`: the same iteration, keyed into a Map or a data object. */
7
- export declare const groupBy: <R>(runner: Runner<R>, namespace: "Map" | "Object") => HostFunction<R>;
8
- export declare const mapGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
9
- export declare const setGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
@@ -1,11 +1,3 @@
1
- import { Effect } from "effect";
2
- import { HostFunction, requiresNew } from "../interpreter/host.js";
3
- import { InterpreterRuntimeError } from "../interpreter/model.js";
4
- import { getOwn, ProgramArray, ProgramObject, set } from "../interpreter/objects.js";
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
1
  export const arrayMethods = new Set([
10
2
  "map",
11
3
  "filter",
@@ -45,6 +37,7 @@ export const arrayMethods = new Set([
45
37
  "entries",
46
38
  ]);
47
39
  export const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]);
40
+ export const mapStatics = new Set(["groupBy"]);
48
41
  export const setMethods = new Set([
49
42
  "add",
50
43
  "has",
@@ -62,112 +55,3 @@ export const setMethods = new Set([
62
55
  "isSupersetOf",
63
56
  "isDisjointFrom",
64
57
  ]);
65
- const coerceGroupByPropertyKey = (runner, value, node) => {
66
- if (value instanceof Values.Promise)
67
- return Effect.succeed("[object Promise]");
68
- if (!Values.isValue(value) && isRuntimeReference(value)) {
69
- throw new InterpreterRuntimeError(`Object.groupBy callback must return a data value, received ${describeValue(value)}.`, node, "InvalidDataValue");
70
- }
71
- return Effect.map(toPrimitive(runner, value, "string", node), coerceToString);
72
- };
73
- /** `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();
105
- let index = 0;
106
- while (true) {
107
- const step = yield* cursor.next;
108
- if (step.done)
109
- return result;
110
- 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);
113
- if (group === undefined)
114
- set(result, key, new ProgramArray([item]));
115
- else
116
- group.items.push(item);
117
- index += 1;
118
- }
119
- });
120
- },
121
- });
122
- const constructMap = (runner, init, node) => {
123
- const target = new Values.Map();
124
- if (init === undefined || init === null)
125
- return Effect.succeed(target);
126
- return Effect.gen(function* () {
127
- const cursor = yield* runner.syncIterator(init, node);
128
- if (cursor === undefined) {
129
- throw new InterpreterRuntimeError("new Map(...) expects an iterable of [key, value] pairs or no argument.", node).as("TypeError");
130
- }
131
- while (true) {
132
- const step = yield* cursor.next;
133
- if (step.done)
134
- return target;
135
- yield* preserveConsumerError(cursor, Effect.sync(() => {
136
- if (!(step.value instanceof ProgramObject)) {
137
- throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node).as("TypeError");
138
- }
139
- target.map.set(getOwn(step.value, 0), getOwn(step.value, 1));
140
- }));
141
- }
142
- });
143
- };
144
- const constructSet = (runner, init, node) => {
145
- const target = new Values.Set();
146
- if (init === undefined || init === null)
147
- return Effect.succeed(target);
148
- return Effect.gen(function* () {
149
- const cursor = yield* runner.syncIterator(init, node);
150
- if (cursor === undefined) {
151
- throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node).as("TypeError");
152
- }
153
- while (true) {
154
- const step = yield* cursor.next;
155
- if (step.done)
156
- return target;
157
- target.set.add(step.value);
158
- }
159
- });
160
- };
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,
173
- });
@@ -1,3 +1,2 @@
1
- import { HostNamespace } from "../interpreter/host.js";
2
- /** Captured console: every method appends one formatted line to `logs`. */
3
- export declare const consoleGlobal: (logs: Array<string>) => HostNamespace;
1
+ export declare const consoleMethods: Set<string>;
2
+ export declare const formatConsoleMessage: (name: string, args: Array<unknown>) => string;
@@ -1,20 +1,10 @@
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";
4
1
  import { containsOpaqueReference, containsRuntimeReference, isRuntimeReference } from "../interpreter/references.js";
5
- import { Values } from "../values.js";
6
- import { coerceToString } from "./value.js";
7
- const consoleMethods = ["log", "info", "debug", "warn", "error", "dir", "table"];
8
- /** 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
- ])));
2
+ import { copyIn, copyOut } from "../tool-runtime.js";
3
+ import { isCodeModeValue, CodeModeDate, CodeModeMap, CodeModePromise, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "../values.js";
4
+ import { boundedData, coerceToString } from "./value.js";
5
+ export const consoleMethods = new Set(["log", "info", "debug", "warn", "error", "dir", "table"]);
16
6
  const MAX_CONSOLE_DEPTH = 32;
17
- const formatConsoleMessage = (name, args) => {
7
+ export const formatConsoleMessage = (name, args) => {
18
8
  if (name === "dir")
19
9
  return args.length === 0 ? "undefined" : formatConsoleArgument(args[0]);
20
10
  if (name === "table")
@@ -38,34 +28,34 @@ const formatConsoleValue = (value, seen, depth) => {
38
28
  return String(value);
39
29
  if (typeof value !== "object")
40
30
  return String(value);
41
- if (value instanceof Values.Promise)
31
+ if (value instanceof CodeModePromise)
42
32
  return "[Promise (await it to get its value)]";
43
- if (value instanceof Values.Date)
33
+ if (value instanceof CodeModeDate)
44
34
  return coerceToString(value);
45
- if (value instanceof Values.RegExp)
35
+ if (value instanceof CodeModeRegExp)
46
36
  return coerceToString(value);
47
- if (value instanceof Values.URL)
37
+ if (value instanceof CodeModeURL)
48
38
  return coerceToString(value);
49
- if (value instanceof Values.URLSearchParams)
39
+ if (value instanceof CodeModeURLSearchParams)
50
40
  return coerceToString(value);
51
41
  if (depth > MAX_CONSOLE_DEPTH)
52
42
  return "...";
53
43
  if (seen.has(value))
54
44
  return "[Circular]";
55
- if (value instanceof Values.Map) {
45
+ if (value instanceof CodeModeMap) {
56
46
  seen.add(value);
57
47
  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)}`;
48
+ const entries = Array.from(value.map.entries(), ([key, item]) => [key, item]);
49
+ return `Map(${value.map.size}) ${formatConsoleValue(entries, seen, depth + 1)}`;
60
50
  }
61
51
  finally {
62
52
  seen.delete(value);
63
53
  }
64
54
  }
65
- if (value instanceof Values.Set) {
55
+ if (value instanceof CodeModeSet) {
66
56
  seen.add(value);
67
57
  try {
68
- return `Set(${value.set.size}) ${formatConsoleValue(new ProgramArray([...value.set.values()]), seen, depth + 1)}`;
58
+ return `Set(${value.set.size}) ${formatConsoleValue(Array.from(value.set.values()), seen, depth + 1)}`;
69
59
  }
70
60
  finally {
71
61
  seen.delete(value);
@@ -75,12 +65,10 @@ const formatConsoleValue = (value, seen, depth) => {
75
65
  return "[opaque reference]";
76
66
  seen.add(value);
77
67
  try {
78
- if (value instanceof ProgramArray) {
79
- return `[${value.items.map((item) => formatConsoleValue(item, seen, depth + 1)).join(",")}]`;
68
+ if (Array.isArray(value)) {
69
+ return `[${value.map((item) => formatConsoleValue(item, seen, depth + 1)).join(",")}]`;
80
70
  }
81
- if (!(value instanceof ProgramObject))
82
- return "[object Object]";
83
- return `{${ownEntries(value)
71
+ return `{${Object.entries(value)
84
72
  .map(([key, item]) => `${JSON.stringify(key)}:${formatConsoleValue(item, seen, depth + 1)}`)
85
73
  .join(",")}}`;
86
74
  }
@@ -93,7 +81,7 @@ const formatConsoleTable = (value, columnsArgument) => {
93
81
  return "undefined";
94
82
  if (containsOpaqueReference(value))
95
83
  return "[opaque reference]";
96
- const data = toProgram(value, "console.table argument");
84
+ const data = boundedData(value, "console.table argument");
97
85
  const columns = consoleTableColumns(columnsArgument);
98
86
  const rows = consoleTableRows(data, columns);
99
87
  const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values))));
@@ -108,23 +96,24 @@ const consoleTableColumns = (value) => {
108
96
  return undefined;
109
97
  if (containsRuntimeReference(value))
110
98
  return undefined;
111
- const columns = toData(value, "console.table columns", "result");
99
+ const columns = copyOut(copyIn(value, "console.table columns"), "nullify");
112
100
  return Array.isArray(columns) ? columns.map((column) => String(column)) : undefined;
113
101
  };
114
102
  const consoleTableRows = (data, columns) => {
115
- if (data instanceof ProgramArray) {
116
- return data.items.map((item, index) => ({ index: String(index), values: consoleTableValues(item, columns) }));
103
+ if (Array.isArray(data)) {
104
+ return data.map((item, index) => ({ index: String(index), values: consoleTableValues(item, columns) }));
117
105
  }
118
- if (data instanceof ProgramObject) {
119
- return ownEntries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
106
+ if (data !== null && typeof data === "object" && !isCodeModeValue(data)) {
107
+ return Object.entries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
120
108
  }
121
109
  return [{ index: "0", values: { Value: data } }];
122
110
  };
123
111
  const consoleTableValues = (value, columns) => {
124
- if (value instanceof ProgramObject && !(value instanceof ProgramArray)) {
112
+ if (value !== null && typeof value === "object" && !Array.isArray(value) && !isCodeModeValue(value)) {
113
+ const source = value;
125
114
  if (columns !== undefined)
126
- return Object.fromEntries(columns.map((column) => [column, get(value, column)]));
127
- return Object.fromEntries(ownEntries(value));
115
+ return Object.fromEntries(columns.map((column) => [column, source[column]]));
116
+ return Object.fromEntries(Object.entries(source));
128
117
  }
129
118
  return { Value: value };
130
119
  };
@@ -1,8 +1,7 @@
1
- import { HostFunction } from "../interpreter/host.js";
2
1
  import { type AstNode } from "../interpreter/model.js";
3
- import { type Runner } from "../interpreter/runner.js";
4
- import { Values } from "../values.js";
2
+ import { CodeModeDate } from "../values.js";
5
3
  export declare const dateMethods: Set<string>;
6
- export declare const dateGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
4
+ export declare const dateStatics: Set<string>;
5
+ export declare const invokeDateStatic: (name: string, args: Array<unknown>, node: AstNode) => number;
7
6
  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;
7
+ export declare const invokeDateMethod: (value: CodeModeDate, name: string, args: Array<number>, node: AstNode, initialTime?: number) => unknown;
@@ -1,8 +1,5 @@
1
- import { Effect } from "effect";
2
- import { HostFunction, sync } from "../interpreter/host.js";
3
1
  import { InterpreterRuntimeError } from "../interpreter/model.js";
4
- import { toPrimitive } from "../interpreter/runner.js";
5
- import { Values } from "../values.js";
2
+ import { CodeModeDate } from "../values.js";
6
3
  import { coerceToNumber, coerceToString } from "./value.js";
7
4
  const dateSetterArguments = new Map([
8
5
  ["setTime", 1],
@@ -27,8 +24,6 @@ export const dateMethods = new Set([
27
24
  "toISOString",
28
25
  "toJSON",
29
26
  "toString",
30
- "toDateString",
31
- "toTimeString",
32
27
  "toUTCString",
33
28
  "toGMTString",
34
29
  "getFullYear",
@@ -50,32 +45,19 @@ export const dateMethods = new Set([
50
45
  "getTimezoneOffset",
51
46
  ...dateSetterArguments.keys(),
52
47
  ]);
53
- const constructDate = (runner, args, node) => {
54
- if (args.length === 0)
55
- return Effect.succeed(new Values.Date(Date.now()));
56
- if (args.length === 1) {
57
- const arg = args[0];
58
- if (arg instanceof Values.Date)
59
- return Effect.succeed(new Values.Date(arg.time));
60
- return Effect.map(toPrimitive(runner, arg, "number", node), (value) => typeof value === "string"
61
- ? new Values.Date(Date.parse(value))
62
- : new Values.Date(new Date(coerceToNumber(value)).getTime()));
48
+ export const dateStatics = new Set(["now", "parse", "UTC"]);
49
+ export const invokeDateStatic = (name, args, node) => {
50
+ switch (name) {
51
+ case "now":
52
+ return Date.now();
53
+ case "parse":
54
+ return Date.parse(coerceToString(args[0]));
55
+ case "UTC":
56
+ return Date.UTC(...args.map((arg) => coerceToNumber(arg)));
57
+ default:
58
+ throw new InterpreterRuntimeError(`Date.${name} is not available.`, node);
63
59
  }
64
- const parts = args.map((arg) => coerceToNumber(arg));
65
- return Effect.succeed(new Values.Date(new Date(...parts).getTime()));
66
60
  };
67
- export const dateGlobal = (runner) => new HostFunction({
68
- name: "Date",
69
- // ISO instead of the host's locale string: date strings are deterministic and must not leak the host timezone.
70
- call: () => Effect.sync(() => new Date().toISOString()),
71
- construct: (args, node) => constructDate(runner, args, node),
72
- instanceOf: (value) => value instanceof Values.Date,
73
- members: {
74
- now: sync("Date.now", () => Date.now()),
75
- parse: sync("Date.parse", (args) => Date.parse(coerceToString(args[0]))),
76
- UTC: sync("Date.UTC", (args) => Date.UTC(...args.map((arg) => coerceToNumber(arg)))),
77
- },
78
- });
79
61
  export const dateSetterArgumentCount = (name) => dateSetterArguments.get(name);
80
62
  export const invokeDateMethod = (value, name, args, node, initialTime = value.time) => {
81
63
  const hosted = new Date(initialTime);
@@ -91,10 +73,6 @@ export const invokeDateMethod = (value, name, args, node, initialTime = value.ti
91
73
  return Number.isFinite(value.time) ? hosted.toISOString() : null;
92
74
  case "toString":
93
75
  return coerceToString(value);
94
- case "toDateString":
95
- return hosted.toDateString();
96
- case "toTimeString":
97
- return hosted.toTimeString();
98
76
  case "toUTCString":
99
77
  case "toGMTString":
100
78
  return hosted.toUTCString();
@@ -1,3 +1,6 @@
1
- import { HostNamespace } from "../interpreter/host.js";
2
- import { type Runner } from "../interpreter/runner.js";
3
- export declare const jsonGlobal: <R>(runner: Runner<R>) => HostNamespace;
1
+ import { Effect } from "effect";
2
+ import type { CallbackRunner } from "../interpreter/methods.js";
3
+ import { type AstNode } from "../interpreter/model.js";
4
+ export declare const jsonStatics: Set<string>;
5
+ export type JsonMethodName = "parse" | "stringify";
6
+ export declare const invokeJsonMethod: <R>(runner: CallbackRunner<R>, name: JsonMethodName, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
@@ -1,22 +1,20 @@
1
1
  import { Effect } from "effect";
2
- import { HostFunction, HostNamespace } from "../interpreter/host.js";
3
- import { applyCollectionCallback } from "../interpreter/runner.js";
2
+ import { applyCollectionCallback } from "../interpreter/methods.js";
4
3
  import { InterpreterRuntimeError } from "../interpreter/model.js";
5
4
  import { typeofValue } from "../interpreter/references.js";
6
- import { fromData, toData, toProgram } from "../data.js";
7
- import { get, ownKeys, ProgramArray, ProgramObject, record, remove, set } from "../interpreter/objects.js";
8
- import { Values } from "../values.js";
9
- export const jsonGlobal = (runner) => new HostNamespace("JSON", {
10
- parse: new HostFunction({ name: "JSON.parse", call: (args, node) => parse(runner, args, node) }),
11
- stringify: new HostFunction({ name: "JSON.stringify", call: (args, node) => stringify(runner, args, node) }),
12
- });
5
+ import { copyIn, copyOut } from "../tool-runtime.js";
6
+ import { CodeModeDate, CodeModeMap, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "../values.js";
7
+ export const jsonStatics = new Set(["parse", "stringify"]);
8
+ export const invokeJsonMethod = (runner, name, args, node) => {
9
+ return name === "parse" ? parse(runner, args, node) : stringify(runner, args, node);
10
+ };
13
11
  const parse = (runner, args, node) => {
14
12
  const text = args[0];
15
13
  if (typeof text !== "string")
16
14
  throw new InterpreterRuntimeError("JSON.parse expects a string.", node);
17
15
  const parsed = (() => {
18
16
  try {
19
- return fromData(JSON.parse(text), "JSON.parse result");
17
+ return copyIn(JSON.parse(text), "JSON.parse result");
20
18
  }
21
19
  catch (error) {
22
20
  throw new InterpreterRuntimeError(`JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`, node).as("SyntaxError");
@@ -25,63 +23,80 @@ const parse = (runner, args, node) => {
25
23
  if (typeofValue(args[1]) !== "function")
26
24
  return Effect.succeed(parsed);
27
25
  const apply = applyCollectionCallback(runner, args[1], "JSON.parse", node);
26
+ const root = Object.create(null);
27
+ root[""] = parsed;
28
28
  const visit = (holder, key) => Effect.gen(function* () {
29
- const value = get(holder, key);
30
- if (value instanceof ProgramObject) {
31
- for (const name of ownKeys(value)) {
29
+ const value = holder[key];
30
+ if (Array.isArray(value)) {
31
+ const length = value.length;
32
+ for (let index = 0; index < length; index += 1) {
33
+ const revived = yield* visit(value, String(index));
34
+ if (revived === undefined)
35
+ Reflect.deleteProperty(value, index);
36
+ else
37
+ value[index] = revived;
38
+ }
39
+ }
40
+ else if (isPlainObject(value)) {
41
+ for (const name of Object.keys(value)) {
32
42
  const revived = yield* visit(value, name);
33
43
  if (revived === undefined)
34
- remove(value, name);
44
+ Reflect.deleteProperty(value, name);
35
45
  else
36
- set(value, name, revived);
46
+ value[name] = revived;
37
47
  }
38
48
  }
39
49
  return yield* apply([key, value]);
40
50
  });
41
- return visit(record({ "": parsed }), "");
51
+ return visit(root, "");
42
52
  };
43
53
  const stringify = (runner, args, node) => {
44
54
  const space = args[2];
45
55
  const indent = typeof space === "number" || typeof space === "string" ? space : undefined;
46
56
  const replacer = args[1];
47
- if (typeofValue(replacer) !== "function") {
48
- const properties = replacer instanceof ProgramArray
49
- ? replacer.items
50
- .filter((item) => typeof item === "string" || typeof item === "number")
51
- .map(String)
52
- : null;
53
- return Effect.succeed(JSON.stringify(toData(args[0], "JSON.stringify value"), properties, indent));
57
+ const callable = typeofValue(replacer) === "function";
58
+ const checked = copyIn(args[0], "JSON.stringify value", callable);
59
+ const input = callable ? args[0] : checked;
60
+ if (Array.isArray(replacer)) {
61
+ const properties = replacer
62
+ .filter((item) => typeof item === "string" || typeof item === "number")
63
+ .map(String);
64
+ return Effect.succeed(JSON.stringify(copyOut(input, "json"), properties, indent));
65
+ }
66
+ if (!callable) {
67
+ return Effect.succeed(JSON.stringify(copyOut(input, "json"), null, indent));
54
68
  }
55
- // Validate up front; the replacer walk below reads the original value.
56
- toProgram(args[0], "JSON.stringify value");
57
69
  const apply = applyCollectionCallback(runner, replacer, "JSON.stringify", node);
70
+ const root = Object.create(null);
71
+ root[""] = input;
58
72
  const stack = new Set();
59
73
  const visit = (holder, key) => Effect.gen(function* () {
60
- const value = yield* apply([key, toJSONValue(get(holder, key))]);
74
+ const value = yield* apply([key, toJSONValue(holder[key])]);
61
75
  if (value === undefined || typeofValue(value) === "function")
62
76
  return undefined;
63
- toProgram(value, "JSON.stringify replacer result");
77
+ copyIn(value, "JSON.stringify replacer result", true);
64
78
  if (typeof value === "number")
65
79
  return Number.isFinite(value) ? value : null;
66
80
  if (value === null || typeof value === "string" || typeof value === "boolean")
67
81
  return value;
68
- if (!(value instanceof ProgramObject))
69
- return {};
70
- if (stack.has(value))
71
- throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError");
72
- stack.add(value);
73
- if (value instanceof ProgramArray) {
82
+ if (Array.isArray(value)) {
83
+ if (stack.has(value))
84
+ throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError");
85
+ stack.add(value);
74
86
  const result = [];
75
- for (let index = 0; index < value.items.length; index += 1) {
87
+ for (let index = 0; index < value.length; index += 1) {
76
88
  result.push((yield* visit(value, String(index))) ?? null);
77
89
  }
78
90
  stack.delete(value);
79
91
  return result;
80
92
  }
93
+ if (!isPlainObject(value))
94
+ return {};
95
+ if (stack.has(value))
96
+ throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError");
97
+ stack.add(value);
81
98
  const result = Object.create(null);
82
- for (const name of ownKeys(value)) {
83
- if (typeof name !== "string")
84
- continue;
99
+ for (const name of Object.keys(value)) {
85
100
  const item = yield* visit(value, name);
86
101
  if (item !== undefined)
87
102
  result[name] = item;
@@ -89,13 +104,21 @@ const stringify = (runner, args, node) => {
89
104
  stack.delete(value);
90
105
  return result;
91
106
  });
92
- return Effect.map(visit(record({ "": args[0] }), ""), (value) => JSON.stringify(value, null, indent));
107
+ return Effect.map(visit(root, ""), (value) => JSON.stringify(value, null, indent));
93
108
  };
94
109
  const toJSONValue = (value) => {
95
- if (value instanceof Values.Date) {
110
+ if (value instanceof CodeModeDate) {
96
111
  return Number.isFinite(value.time) ? new Date(value.time).toISOString() : null;
97
112
  }
98
- if (value instanceof Values.URL)
113
+ if (value instanceof CodeModeURL)
99
114
  return value.url.href;
100
115
  return value;
101
116
  };
117
+ const isPlainObject = (value) => value !== null &&
118
+ typeof value === "object" &&
119
+ !(value instanceof CodeModeDate) &&
120
+ !(value instanceof CodeModeRegExp) &&
121
+ !(value instanceof CodeModeMap) &&
122
+ !(value instanceof CodeModeSet) &&
123
+ !(value instanceof CodeModeURL) &&
124
+ !(value instanceof CodeModeURLSearchParams);
@@ -1,8 +1,12 @@
1
- import { HostNamespace } from "../interpreter/host.js";
2
- import { type Runner } from "../interpreter/runner.js";
1
+ import { Effect } from "effect";
2
+ import { type SyncIteratorRunner } from "../interpreter/iterator.js";
3
+ import { type AstNode } from "../interpreter/model.js";
3
4
  declare global {
4
5
  interface Math {
5
6
  sumPrecise(values: Iterable<number>): number;
6
7
  }
7
8
  }
8
- export declare const mathGlobal: <R>(runner: Runner<R>) => HostNamespace;
9
+ export declare const mathConstants: Set<string>;
10
+ export declare const mathMethods: Set<string>;
11
+ export declare const invokeMathMethod: (name: string, args: Array<unknown>, node: AstNode) => number;
12
+ export declare const invokeMathSumPrecise: <R>(runner: SyncIteratorRunner<R>, source: unknown, node: AstNode) => Effect.Effect<number, unknown, R>;