@opencode/codemode 2.0.2 → 2.0.4

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 (71) hide show
  1. package/dist/codemode.d.ts +3 -0
  2. package/dist/codemode.js +12 -1
  3. package/dist/data.d.ts +14 -21
  4. package/dist/data.js +72 -140
  5. package/dist/extension.d.ts +11 -0
  6. package/dist/extension.js +9 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +1 -0
  9. package/dist/interpreter/callback.d.ts +20 -0
  10. package/dist/interpreter/{runner.js → callback.js} +14 -14
  11. package/dist/interpreter/errors.d.ts +12 -5
  12. package/dist/interpreter/errors.js +66 -54
  13. package/dist/interpreter/execute.d.ts +2 -2
  14. package/dist/interpreter/execute.js +15 -15
  15. package/dist/interpreter/extensions.d.ts +8 -0
  16. package/dist/interpreter/extensions.js +155 -0
  17. package/dist/interpreter/generators.d.ts +2 -3
  18. package/dist/interpreter/generators.js +10 -10
  19. package/dist/interpreter/globals.d.ts +4 -12
  20. package/dist/interpreter/globals.js +56 -49
  21. package/dist/interpreter/interpreter.d.ts +34 -0
  22. package/dist/interpreter/{runtime.js → interpreter.js} +250 -215
  23. package/dist/interpreter/intrinsics.d.ts +5 -5
  24. package/dist/interpreter/intrinsics.js +16 -10
  25. package/dist/interpreter/limits.d.ts +10 -0
  26. package/dist/interpreter/limits.js +19 -0
  27. package/dist/interpreter/model.d.ts +27 -14
  28. package/dist/interpreter/model.js +22 -14
  29. package/dist/interpreter/native.d.ts +12 -13
  30. package/dist/interpreter/native.js +17 -16
  31. package/dist/interpreter/objects.d.ts +55 -48
  32. package/dist/interpreter/objects.js +64 -44
  33. package/dist/interpreter/promises.d.ts +13 -15
  34. package/dist/interpreter/promises.js +89 -85
  35. package/dist/interpreter/references.d.ts +1 -2
  36. package/dist/interpreter/references.js +18 -16
  37. package/dist/interpreter/scope.js +6 -6
  38. package/dist/openapi/types.d.ts +1 -1
  39. package/dist/stdlib/array.d.ts +3 -4
  40. package/dist/stdlib/array.js +115 -110
  41. package/dist/stdlib/bytes.d.ts +10 -0
  42. package/dist/stdlib/bytes.js +228 -0
  43. package/dist/stdlib/collections.d.ts +4 -4
  44. package/dist/stdlib/collections.js +89 -89
  45. package/dist/stdlib/console.d.ts +5 -3
  46. package/dist/stdlib/console.js +30 -37
  47. package/dist/stdlib/date.d.ts +2 -2
  48. package/dist/stdlib/date.js +35 -35
  49. package/dist/stdlib/json.d.ts +3 -3
  50. package/dist/stdlib/json.js +29 -67
  51. package/dist/stdlib/math.d.ts +3 -3
  52. package/dist/stdlib/math.js +17 -21
  53. package/dist/stdlib/number.d.ts +3 -3
  54. package/dist/stdlib/number.js +32 -36
  55. package/dist/stdlib/object.d.ts +5 -5
  56. package/dist/stdlib/object.js +59 -62
  57. package/dist/stdlib/regexp.d.ts +7 -8
  58. package/dist/stdlib/regexp.js +40 -48
  59. package/dist/stdlib/string.d.ts +2 -2
  60. package/dist/stdlib/string.js +110 -88
  61. package/dist/stdlib/url.d.ts +4 -6
  62. package/dist/stdlib/url.js +86 -90
  63. package/dist/stdlib/value.d.ts +3 -3
  64. package/dist/stdlib/value.js +26 -24
  65. package/dist/stdlib/web.d.ts +4 -4
  66. package/dist/stdlib/web.js +22 -8
  67. package/dist/tool-runtime.d.ts +12 -5
  68. package/dist/tool-runtime.js +25 -11
  69. package/package.json +1 -1
  70. package/dist/interpreter/runner.d.ts +0 -28
  71. package/dist/interpreter/runtime.d.ts +0 -19
@@ -1,7 +1,7 @@
1
1
  import { type AstNode } from "../interpreter/model.js";
2
- import { ProgramObject } from "../interpreter/objects.js";
3
- import { type Runner } from "../interpreter/runner.js";
4
- export declare const enumerableSource: <R>(runner: Runner<R>, label: string, value: unknown, node: AstNode) => ProgramObject;
5
- export declare const objectAssign: <R>(runner: Runner<R>, args: Array<unknown>, node: AstNode) => unknown;
2
+ import { Obj } from "../interpreter/objects.js";
3
+ import type { Interpreter } from "../interpreter/interpreter.js";
4
+ export declare const enumerableSource: <R>(ctx: Interpreter<R>, label: string, value: unknown, node?: AstNode) => Obj;
5
+ export declare const objectAssign: <R>(ctx: Interpreter<R>, args: Array<unknown>) => unknown;
6
6
  export declare const classTag: (value: unknown) => string;
7
- export declare const objectGlobal: <R>(runner: Runner<R>, toolKeys: (path: ReadonlyArray<string>) => ReadonlyArray<string>) => import("../interpreter/objects.js").NativeFunction<R>;
7
+ export declare const objectGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
@@ -1,66 +1,65 @@
1
1
  import { Effect } from "effect";
2
- import { toProgram } from "../data.js";
3
2
  import { constructor, methods, receiver } from "../interpreter/native.js";
4
- import { AsyncIteratorSymbol, InterpreterRuntimeError, IteratorSymbol, rangeError, } from "../interpreter/model.js";
5
- import { Callable, define, entries, enumerableKeys, getOwn, hasOwn, hasPrototype, hidden, keys, own, ProgramArray, ProgramDate, ProgramError, ProgramObject, ProgramPromise, ProgramRegExp, set, } from "../interpreter/objects.js";
3
+ import { AsyncIteratorSymbol, invalidData, IteratorSymbol, rangeError, typeError, } from "../interpreter/model.js";
4
+ import { Callable, define, entries, enumerableKeys, getOwn, hasOwn, hasPrototype, hidden, keys, own, Arr, Bytes, DateObj, ErrorObj, Obj, PromiseObj, RegExpObj, set, } from "../interpreter/objects.js";
6
5
  import { containsOpaqueReference, describeValue, rejectCircularInsertion } from "../interpreter/references.js";
7
- import { preserveConsumerError } from "../interpreter/runner.js";
6
+ import { preserveConsumerError } from "../interpreter/callback.js";
8
7
  import { ToolReference } from "../tool-runtime.js";
9
8
  import { groupBy } from "./collections.js";
10
9
  import { coerceToString } from "./value.js";
11
10
  // ToObject for enumeration.
12
- export const enumerableSource = (runner, label, value, node) => {
11
+ export const enumerableSource = (ctx, label, value, node) => {
13
12
  if (value === null || value === undefined) {
14
- throw new InterpreterRuntimeError(`${label} cannot convert ${describeValue(value)} to an object.`, node);
13
+ throw typeError(`${label} cannot convert ${describeValue(value)} to an object.`, node);
15
14
  }
16
- if (value instanceof ProgramPromise) {
17
- throw new InterpreterRuntimeError(`${label} received an un-awaited Promise; await it before inspecting the result.`, node, "InvalidDataValue");
15
+ if (value instanceof PromiseObj) {
16
+ throw invalidData(`${label} received an un-awaited Promise; await it before inspecting the result.`, node);
18
17
  }
19
18
  if (value instanceof ToolReference) {
20
- throw new InterpreterRuntimeError(`${label} cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or search({ query }) for signatures.`, node, "InvalidDataValue");
19
+ throw invalidData(`${label} cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or search({ query }) for signatures.`, node);
21
20
  }
22
21
  if (typeof value === "string")
23
- return new ProgramArray(runner.prototypes.Array, [...value]);
24
- if (value instanceof ProgramObject)
22
+ return new Arr(ctx.builtins.Array, [...value]);
23
+ if (value instanceof Obj)
25
24
  return value;
26
- return new ProgramObject(runner.prototypes.Object);
25
+ return new Obj(ctx.builtins.Object);
27
26
  };
28
- export const objectAssign = (runner, args, node) => {
27
+ export const objectAssign = (ctx, args) => {
29
28
  const target = args[0];
30
29
  // JS would box a primitive target; wrappers and primitives cannot hold fields here.
31
- if (!(target instanceof ProgramObject)) {
32
- throw new InterpreterRuntimeError(`Object.assign expects a data object or array target, received ${describeValue(target)}.`, node);
30
+ if (!(target instanceof Obj)) {
31
+ throw typeError(`Object.assign expects a data object or array target, received ${describeValue(target)}.`);
33
32
  }
34
33
  const seen = new Set();
35
34
  for (const source of args.slice(1)) {
36
35
  if (source === null || source === undefined)
37
36
  continue;
38
- const from = enumerableSource(runner, "Object.assign(...)", source, node);
37
+ const from = enumerableSource(ctx, "Object.assign(...)", source);
39
38
  for (const key of enumerableKeys(from)) {
40
- rejectCircularInsertion(target, getOwn(from, key), "Object.assign result", node, seen);
39
+ rejectCircularInsertion(target, getOwn(from, key), "Object.assign result", seen);
41
40
  if (!set(target, key, getOwn(from, key))) {
42
- if (target instanceof ProgramArray && key === "length")
43
- throw rangeError("Invalid array length", node);
44
- throw new InterpreterRuntimeError(`Cannot assign to read only property '${String(key)}'.`, node);
41
+ if (target instanceof Arr && key === "length")
42
+ throw rangeError("Invalid array length");
43
+ throw typeError(`Cannot assign to read only property '${String(key)}'.`);
45
44
  }
46
45
  }
47
46
  }
48
47
  return target;
49
48
  };
50
- const objectFromEntries = (runner, source, node) => {
51
- const out = new ProgramObject(runner.prototypes.Object);
49
+ const objectFromEntries = (ctx, source) => {
50
+ const out = new Obj(ctx.builtins.Object);
52
51
  return Effect.gen(function* () {
53
- const cursor = yield* runner.syncIterator(source, node);
52
+ const cursor = yield* ctx.iterate(source);
54
53
  if (cursor === undefined) {
55
- throw new InterpreterRuntimeError("Object.fromEntries expects a synchronous iterable of entries.", node);
54
+ throw typeError("Object.fromEntries expects a synchronous iterable of entries.");
56
55
  }
57
56
  while (true) {
58
57
  const step = yield* cursor.next;
59
58
  if (step.done)
60
59
  return out;
61
60
  yield* preserveConsumerError(cursor, Effect.sync(() => {
62
- if (!(step.value instanceof ProgramObject) || containsOpaqueReference(step.value)) {
63
- throw new InterpreterRuntimeError("Object.fromEntries expects [key, value] entry objects.", node);
61
+ if (!(step.value instanceof Obj) || containsOpaqueReference(step.value)) {
62
+ throw typeError("Object.fromEntries expects [key, value] entry objects.");
64
63
  }
65
64
  define(out, coerceToString(getOwn(step.value, 0)), getOwn(step.value, 1));
66
65
  }));
@@ -72,16 +71,18 @@ export const classTag = (value) => {
72
71
  return "Null";
73
72
  if (value === undefined)
74
73
  return "Undefined";
75
- if (value instanceof ProgramArray)
74
+ if (value instanceof Arr)
76
75
  return "Array";
77
76
  if (value instanceof Callable)
78
77
  return "Function";
79
- if (value instanceof ProgramError)
78
+ if (value instanceof ErrorObj)
80
79
  return "Error";
81
- if (value instanceof ProgramDate)
80
+ if (value instanceof DateObj)
82
81
  return "Date";
83
- if (value instanceof ProgramRegExp)
82
+ if (value instanceof RegExpObj)
84
83
  return "RegExp";
84
+ if (value instanceof Bytes)
85
+ return "Uint8Array";
85
86
  if (typeof value === "string")
86
87
  return "String";
87
88
  if (typeof value === "number")
@@ -93,84 +94,80 @@ export const classTag = (value) => {
93
94
  const propertyKey = (value) => value === AsyncIteratorSymbol || value === IteratorSymbol ? value : coerceToString(value);
94
95
  // Object constructs identically with or without new, like JS. Only `keys` copies its result into the
95
96
  // program; `values`, `entries`, `assign`, and `fromEntries` hand back the program's own values.
96
- export const objectGlobal = (runner, toolKeys) => {
97
- const protos = runner.prototypes;
98
- const construct = (args, node) => {
97
+ export const objectGlobal = (ctx) => {
98
+ const builtins = ctx.builtins;
99
+ const construct = (args) => {
99
100
  const first = args[0];
100
101
  if (first === null || first === undefined)
101
- return new ProgramObject(protos.Object);
102
- if (typeof first === "object")
102
+ return new Obj(builtins.Object);
103
+ if (first instanceof Obj)
103
104
  return first;
104
- throw new InterpreterRuntimeError(`Object(${typeof first}) wrapper objects are not supported; use the primitive value directly.`, node);
105
+ throw typeError(`Object(${typeof first}) wrapper objects are not supported; use the primitive value directly.`);
105
106
  };
106
- const object = constructor(protos, protos.Object, {
107
+ const object = constructor(builtins, builtins.Object, {
107
108
  name: "Object",
108
109
  length: 1,
109
- call: (_, args, node) => Effect.sync(() => construct(args, node)),
110
- construct: (args, _, node) => Effect.sync(() => construct(args, node)),
110
+ call: (_, args) => Effect.sync(() => construct(args)),
111
+ construct: (args) => Effect.sync(() => construct(args)),
111
112
  });
112
- methods(protos, object, [
113
+ methods(builtins, object, [
113
114
  [
114
115
  "keys",
115
116
  1,
116
- (_, args, node) => toProgram(protos, args[0] instanceof ToolReference
117
- ? [...toolKeys(args[0].path)]
118
- : keys(enumerableSource(runner, "Object.keys(...)", args[0], node)), "Object.keys result"),
117
+ (_, args) => new Arr(builtins.Array, args[0] instanceof ToolReference
118
+ ? [...ctx.tools.keys(args[0].path)]
119
+ : keys(enumerableSource(ctx, "Object.keys(...)", args[0]))),
119
120
  ],
120
121
  [
121
122
  "values",
122
123
  1,
123
- (_, args, node) => new ProgramArray(protos.Array, entries(enumerableSource(runner, "Object.values(...)", args[0], node)).map((entry) => entry[1])),
124
+ (_, args) => new Arr(builtins.Array, entries(enumerableSource(ctx, "Object.values(...)", args[0])).map((entry) => entry[1])),
124
125
  ],
125
126
  [
126
127
  "entries",
127
128
  1,
128
- (_, args, node) => new ProgramArray(protos.Array, entries(enumerableSource(runner, "Object.entries(...)", args[0], node)).map((entry) => new ProgramArray(protos.Array, entry))),
129
- ],
130
- [
131
- "hasOwn",
132
- 2,
133
- (_, args, node) => hasOwn(enumerableSource(runner, "Object.hasOwn(...)", args[0], node), propertyKey(args[1])),
129
+ (_, args) => new Arr(builtins.Array, entries(enumerableSource(ctx, "Object.entries(...)", args[0])).map((entry) => new Arr(builtins.Array, entry))),
134
130
  ],
131
+ ["hasOwn", 2, (_, args) => hasOwn(enumerableSource(ctx, "Object.hasOwn(...)", args[0]), propertyKey(args[1]))],
135
132
  [
136
133
  "is",
137
134
  2,
138
- (_, args, node) => {
135
+ (_, args) => {
139
136
  if (containsOpaqueReference(args[0]) || containsOpaqueReference(args[1])) {
140
- throw new InterpreterRuntimeError("Object.is requires data values.", node, "InvalidDataValue");
137
+ throw invalidData("Object.is requires data values.");
141
138
  }
142
139
  return Object.is(args[0], args[1]);
143
140
  },
144
141
  ],
145
- ["assign", 2, (_, args, node) => objectAssign(runner, args, node)],
146
- ["fromEntries", 1, (_, args, node) => objectFromEntries(runner, args[0], node)],
142
+ ["assign", 2, (_, args) => objectAssign(ctx, args)],
143
+ ["fromEntries", 1, (_, args) => objectFromEntries(ctx, args[0])],
147
144
  ]);
148
- define(object, "groupBy", groupBy(runner, "Object"), hidden);
149
- methods(protos, protos.Object, [
145
+ define(object, "groupBy", groupBy(ctx, "Object"), hidden);
146
+ methods(builtins, builtins.Object, [
150
147
  [
151
148
  "hasOwnProperty",
152
149
  1,
153
- (thisValue, args, node) => hasOwn(receiver(ProgramObject, thisValue, "Object.prototype.hasOwnProperty", node), propertyKey(args[0])),
150
+ (thisValue, args) => hasOwn(receiver(Obj, thisValue, "Object.prototype.hasOwnProperty"), propertyKey(args[0])),
154
151
  ],
155
152
  [
156
153
  "isPrototypeOf",
157
154
  1,
158
- (thisValue, args, node) => hasPrototype(args[0], receiver(ProgramObject, thisValue, "Object.prototype.isPrototypeOf", node)),
155
+ (thisValue, args) => hasPrototype(args[0], receiver(Obj, thisValue, "Object.prototype.isPrototypeOf")),
159
156
  ],
160
157
  [
161
158
  "propertyIsEnumerable",
162
159
  1,
163
- (thisValue, args, node) => own(receiver(ProgramObject, thisValue, "Object.prototype.propertyIsEnumerable", node), propertyKey(args[0]))
164
- ?.enumerable === true,
160
+ (thisValue, args) => own(receiver(Obj, thisValue, "Object.prototype.propertyIsEnumerable"), propertyKey(args[0]))?.enumerable ===
161
+ true,
165
162
  ],
166
163
  ["toString", 0, (thisValue) => `[object ${classTag(thisValue)}]`],
167
164
  ["toLocaleString", 0, (thisValue) => `[object ${classTag(thisValue)}]`],
168
165
  [
169
166
  "valueOf",
170
167
  0,
171
- (thisValue, _, node) => {
168
+ (thisValue) => {
172
169
  if (thisValue === null || thisValue === undefined) {
173
- throw new InterpreterRuntimeError("Object.prototype.valueOf called on null or undefined.", node);
170
+ throw typeError("Object.prototype.valueOf called on null or undefined.");
174
171
  }
175
172
  return thisValue;
176
173
  },
@@ -1,8 +1,7 @@
1
- import type { Prototypes } from "../interpreter/intrinsics.js";
2
- import { type AstNode } from "../interpreter/model.js";
3
- import { ProgramArray, ProgramObject, ProgramRegExp } from "../interpreter/objects.js";
4
- import type { Runner } from "../interpreter/runner.js";
5
- export declare const toHostRegex: (arg: unknown, method: string, node: AstNode, extraFlags?: string) => RegExp;
6
- export declare const matchToValue: (protos: Prototypes, match: RegExpMatchArray) => ProgramArray;
7
- export declare const constructRegExp: (protos: Prototypes, args: Array<unknown>, node: AstNode, proto?: ProgramObject) => ProgramRegExp;
8
- export declare const regexpGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
1
+ import type { Builtins } from "../interpreter/intrinsics.js";
2
+ import { Arr, Obj, RegExpObj } from "../interpreter/objects.js";
3
+ import type { Interpreter } from "../interpreter/interpreter.js";
4
+ export declare const toHostRegex: (arg: unknown, method: string, extraFlags?: string) => RegExp;
5
+ export declare const matchToValue: (builtins: Builtins, match: RegExpMatchArray) => Arr;
6
+ export declare const constructRegExp: (builtins: Builtins, args: Array<unknown>, proto?: Obj) => RegExpObj;
7
+ export declare const regexpGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
@@ -1,7 +1,7 @@
1
1
  import { Effect } from "effect";
2
2
  import { constructor, methods, prototypeFrom, receiver } from "../interpreter/native.js";
3
- import { InterpreterRuntimeError, syntaxError } from "../interpreter/model.js";
4
- import { define, defineAccessor, getOwn, ProgramArray, ProgramObject, ProgramRegExp, record, set, } from "../interpreter/objects.js";
3
+ import { syntaxError, typeError } from "../interpreter/model.js";
4
+ import { define, defineAccessor, Arr, Obj, RegExpObj, record } from "../interpreter/objects.js";
5
5
  import { coerceToNumber, coerceToString } from "./value.js";
6
6
  const flagProperties = [
7
7
  "hasIndices",
@@ -15,114 +15,106 @@ const flagProperties = [
15
15
  ];
16
16
  const regexFailureReason = (error) => (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "");
17
17
  const escapeRegexHint = 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.';
18
- export const toHostRegex = (arg, method, node, extraFlags = "") => {
18
+ export const toHostRegex = (arg, method, extraFlags = "") => {
19
19
  // Native parity: an undefined pattern behaves as an empty pattern.
20
20
  if (arg === undefined)
21
21
  return new RegExp("", extraFlags);
22
- if (arg instanceof ProgramRegExp)
22
+ if (arg instanceof RegExpObj)
23
23
  return arg.regex;
24
24
  if (typeof arg === "string") {
25
25
  try {
26
26
  return new RegExp(arg, extraFlags);
27
27
  }
28
28
  catch (error) {
29
- throw syntaxError(`String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`, node);
29
+ throw syntaxError(`String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`);
30
30
  }
31
31
  }
32
- throw new InterpreterRuntimeError(`String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`, node);
32
+ throw typeError(`String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`);
33
33
  };
34
- export const matchToValue = (protos, match) => {
35
- const result = new ProgramArray(protos.Array, Array.from(match, (group) => group));
34
+ export const matchToValue = (builtins, match) => {
35
+ const result = new Arr(builtins.Array, Array.from(match, (group) => group));
36
36
  if (match.index !== undefined)
37
37
  define(result, "index", match.index);
38
38
  if (match.input !== undefined)
39
39
  define(result, "input", match.input);
40
40
  if (match.groups)
41
- define(result, "groups", record(protos.Object, match.groups));
41
+ define(result, "groups", record(builtins.Object, match.groups));
42
42
  if (match.indices)
43
- define(result, "indices", indicesToValue(protos, match.indices));
43
+ define(result, "indices", indicesToValue(builtins, match.indices));
44
44
  return result;
45
45
  };
46
- export const constructRegExp = (protos, args, node, proto = protos.RegExp) => {
46
+ export const constructRegExp = (builtins, args, proto = builtins.RegExp) => {
47
47
  const first = args[0];
48
- const pattern = first instanceof ProgramRegExp ? first.regex.source : first === undefined ? "" : coerceToString(first);
48
+ const pattern = first instanceof RegExpObj ? first.regex.source : first === undefined ? "" : coerceToString(first);
49
49
  const flagsArg = args[1];
50
50
  if (flagsArg !== undefined && typeof flagsArg !== "string") {
51
- throw syntaxError(`RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`, node);
51
+ throw syntaxError(`RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`);
52
52
  }
53
- const flags = flagsArg ?? (first instanceof ProgramRegExp ? first.regex.flags : "");
53
+ const flags = flagsArg ?? (first instanceof RegExpObj ? first.regex.flags : "");
54
54
  try {
55
- return new ProgramRegExp(proto, pattern, flags);
55
+ return new RegExpObj(proto, pattern, flags);
56
56
  }
57
57
  catch (error) {
58
58
  const reason = regexFailureReason(error);
59
59
  throw syntaxError(/flag/i.test(reason)
60
60
  ? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.`
61
- : `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`, node);
61
+ : `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`);
62
62
  }
63
63
  };
64
- const toLength = (value) => {
65
- const number = coerceToNumber(value);
66
- if (Number.isNaN(number) || number <= 0)
67
- return 0;
68
- return Math.min(Math.floor(number), Number.MAX_SAFE_INTEGER);
69
- };
70
64
  // RegExp constructs identically with or without new, like JS.
71
- export const regexpGlobal = (runner) => {
72
- const protos = runner.prototypes;
73
- const proto = protos.RegExp;
74
- const regexp = constructor(protos, proto, {
65
+ export const regexpGlobal = (ctx) => {
66
+ const builtins = ctx.builtins;
67
+ const proto = builtins.RegExp;
68
+ const regexp = constructor(builtins, proto, {
75
69
  name: "RegExp",
76
70
  length: 2,
77
- call: (_, args, node) => Effect.sync(() => constructRegExp(protos, args, node)),
78
- construct: (args, newTarget, node) => Effect.sync(() => constructRegExp(protos, args, node, prototypeFrom(newTarget, proto))),
71
+ call: (_, args) => Effect.sync(() => constructRegExp(builtins, args)),
72
+ construct: (args, newTarget) => Effect.sync(() => constructRegExp(builtins, args, prototypeFrom(newTarget, proto))),
79
73
  });
80
- methods(protos, regexp, [
74
+ methods(builtins, regexp, [
81
75
  [
82
76
  "escape",
83
77
  1,
84
- (_, args, node) => {
78
+ (_, args) => {
85
79
  if (typeof args[0] !== "string")
86
- throw new InterpreterRuntimeError("RegExp.escape expects a string.", node);
80
+ throw typeError("RegExp.escape expects a string.");
87
81
  return RegExp.escape(args[0]);
88
82
  },
89
83
  ],
90
84
  ]);
91
- const self = (thisValue, name, node) => receiver(ProgramRegExp, thisValue, `RegExp.prototype.${name}`, node);
85
+ const self = (thisValue, name) => receiver(RegExpObj, thisValue, `RegExp.prototype.${name}`);
92
86
  defineAccessor(proto, "source", (thisValue) => self(thisValue, "source").regex.source);
93
87
  defineAccessor(proto, "flags", (thisValue) => self(thisValue, "flags").regex.flags);
88
+ // The host regex holds the only lastIndex, so exec/test and the String methods share one counter.
89
+ defineAccessor(proto, "lastIndex", (thisValue) => self(thisValue, "lastIndex").regex.lastIndex, (thisValue, value) => {
90
+ self(thisValue, "lastIndex").regex.lastIndex = coerceToNumber(value);
91
+ });
94
92
  for (const name of flagProperties)
95
93
  defineAccessor(proto, name, (thisValue) => self(thisValue, name).regex[name]);
96
- // exec/test run the host regex from the program-visible lastIndex and write it back only when g or y is set.
97
94
  const run = (name) => [
98
95
  name,
99
96
  1,
100
- (thisValue, args, node) => {
101
- const value = self(thisValue, name, node);
102
- const input = coerceToString(args[0]);
103
- const stateful = value.regex.global || value.regex.sticky;
104
- value.regex.lastIndex = toLength(getOwn(value, "lastIndex"));
105
- const matched = value.regex.exec(input);
106
- if (stateful)
107
- set(value, "lastIndex", value.regex.lastIndex);
97
+ (thisValue, args) => {
98
+ const value = self(thisValue, name);
99
+ const matched = value.regex.exec(coerceToString(args[0]));
108
100
  if (name === "test")
109
101
  return matched !== null;
110
- return matched === null ? null : matchToValue(protos, matched);
102
+ return matched === null ? null : matchToValue(builtins, matched);
111
103
  },
112
104
  ];
113
- methods(protos, proto, [
105
+ methods(builtins, proto, [
114
106
  run("exec"),
115
107
  run("test"),
116
- ["toString", 0, (thisValue, _, node) => coerceToString(self(thisValue, "toString", node))],
108
+ ["toString", 0, (thisValue) => coerceToString(self(thisValue, "toString"))],
117
109
  ]);
118
110
  return regexp;
119
111
  };
120
- const indicesToValue = (protos, indices) => {
121
- const range = (pair) => pair === undefined ? undefined : new ProgramArray(protos.Array, [...pair]);
122
- const result = new ProgramArray(protos.Array, Array.from(indices, range));
112
+ const indicesToValue = (builtins, indices) => {
113
+ const range = (pair) => pair === undefined ? undefined : new Arr(builtins.Array, [...pair]);
114
+ const result = new Arr(builtins.Array, Array.from(indices, range));
123
115
  const groups = indices.groups;
124
116
  define(result, "groups", groups === undefined
125
117
  ? undefined
126
- : record(protos.Object, Object.fromEntries(Object.entries(groups).map(([key, pair]) => [key, range(pair)]))));
118
+ : record(builtins.Object, Object.fromEntries(Object.entries(groups).map(([key, pair]) => [key, range(pair)]))));
127
119
  return result;
128
120
  };
@@ -1,2 +1,2 @@
1
- import { type Runner } from "../interpreter/runner.js";
2
- export declare const stringGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
1
+ import type { Interpreter } from "../interpreter/interpreter.js";
2
+ export declare const stringGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;