@opencode/codemode 0.0.0-dev-19530 → 2.0.0

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 +5 -6
  2. package/dist/data.js +44 -47
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/interpreter/errors.d.ts +3 -5
  6. package/dist/interpreter/errors.js +22 -51
  7. package/dist/interpreter/execute.js +3 -5
  8. package/dist/interpreter/globals.js +47 -69
  9. package/dist/interpreter/host.d.ts +41 -0
  10. package/dist/interpreter/host.js +44 -0
  11. package/dist/interpreter/methods.d.ts +4 -0
  12. package/dist/interpreter/methods.js +837 -0
  13. package/dist/interpreter/model.d.ts +36 -13
  14. package/dist/interpreter/model.js +45 -15
  15. package/dist/interpreter/objects.d.ts +13 -106
  16. package/dist/interpreter/objects.js +65 -192
  17. package/dist/interpreter/promises.d.ts +13 -12
  18. package/dist/interpreter/promises.js +54 -59
  19. package/dist/interpreter/references.d.ts +0 -1
  20. package/dist/interpreter/references.js +33 -20
  21. package/dist/interpreter/runner.d.ts +11 -15
  22. package/dist/interpreter/runner.js +21 -21
  23. package/dist/interpreter/runtime.d.ts +3 -3
  24. package/dist/interpreter/runtime.js +327 -165
  25. package/dist/interpreter/scope.js +6 -6
  26. package/dist/stdlib/array.d.ts +2 -4
  27. package/dist/stdlib/array.js +32 -424
  28. package/dist/stdlib/collections.d.ts +7 -3
  29. package/dist/stdlib/collections.js +119 -291
  30. package/dist/stdlib/console.d.ts +2 -3
  31. package/dist/stdlib/console.js +30 -35
  32. package/dist/stdlib/date.d.ts +7 -1
  33. package/dist/stdlib/date.js +188 -93
  34. package/dist/stdlib/json.d.ts +2 -2
  35. package/dist/stdlib/json.js +27 -27
  36. package/dist/stdlib/math.d.ts +2 -2
  37. package/dist/stdlib/math.js +76 -96
  38. package/dist/stdlib/number.d.ts +4 -3
  39. package/dist/stdlib/number.js +60 -95
  40. package/dist/stdlib/object.d.ts +4 -4
  41. package/dist/stdlib/object.js +54 -128
  42. package/dist/stdlib/regexp.d.ts +8 -6
  43. package/dist/stdlib/regexp.js +68 -76
  44. package/dist/stdlib/string.d.ts +2 -2
  45. package/dist/stdlib/string.js +50 -213
  46. package/dist/stdlib/url.d.ts +13 -5
  47. package/dist/stdlib/url.js +102 -202
  48. package/dist/stdlib/value.d.ts +9 -5
  49. package/dist/stdlib/value.js +38 -16
  50. package/dist/stdlib/web.d.ts +4 -4
  51. package/dist/stdlib/web.js +10 -12
  52. package/dist/tool-runtime.d.ts +1 -2
  53. package/dist/tool-runtime.js +2 -2
  54. package/dist/values.d.ts +37 -0
  55. package/dist/values.js +56 -0
  56. package/package.json +1 -1
  57. package/dist/interpreter/generators.d.ts +0 -4
  58. package/dist/interpreter/generators.js +0 -25
  59. package/dist/interpreter/intrinsics.d.ts +0 -13
  60. package/dist/interpreter/intrinsics.js +0 -82
  61. package/dist/interpreter/native.d.ts +0 -19
  62. package/dist/interpreter/native.js +0 -40
@@ -1,17 +1,25 @@
1
1
  import { Cause, Deferred, Effect, Exit } from "effect";
2
- import { toProgram } from "../data.js";
2
+ import { ToolRuntimeError, toProgram } from "../data.js";
3
3
  import { ToolReference } from "../tool-runtime.js";
4
- import { AsyncIteratorSymbol, GeneratorReturn, InterpreterRuntimeError, IteratorSymbol, locate, OptionalShortCircuit, ProgramThrow, rangeError, unsupportedSyntax, } from "./model.js";
4
+ import { AsyncIteratorSymbol, CodeModeGenerator, ComputedValue, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError, IteratorSymbol, OptionalShortCircuit, PromiseInstanceMethodReference, ProgramThrow, unsupportedSyntax, } from "./model.js";
5
5
  import { caughtErrorValue } from "./errors.js";
6
6
  import { globals } from "./globals.js";
7
- import { assign, Callable, define, get, has, hasPrototype, keys, NativeFunction, parseArrayIndex, ProgramArray, ProgramDate, ProgramFunction, ProgramGenerator, ProgramMap, ProgramObject, ProgramPromise, ProgramSet, ProgramURLSearchParams, record, remove, set, } from "./objects.js";
7
+ import { HostFunction, HostNamespace } from "./host.js";
8
+ import { invokeIntrinsic } from "./methods.js";
9
+ import { assign, get, has, ownKeys, parseArrayIndex, ProgramArray, ProgramFunction, ProgramObject, record, remove, set, } from "./objects.js";
8
10
  import { preserveConsumerError } from "./runner.js";
9
- import { PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
10
- import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
11
+ import { invokePromiseInstanceMethod, PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
12
+ import { containsOpaqueReference, describeValue, isRuntimeReference, rejectCircularInsertion, typeofValue, } from "./references.js";
11
13
  import { ScopeStack } from "./scope.js";
12
- import { constructRegExp } from "../stdlib/regexp.js";
14
+ import { arrayMethods, mapMethods, setMethods } from "../stdlib/collections.js";
15
+ import { dateMethods } from "../stdlib/date.js";
16
+ import { numberMethods } from "../stdlib/number.js";
17
+ import { constructRegExp, regexpMethods, regexpProperties } from "../stdlib/regexp.js";
18
+ import { stringMethods } from "../stdlib/string.js";
19
+ import { uriArgument, urlMethods, urlProperties, urlSearchParamsMethods, urlWritableProperties } from "../stdlib/url.js";
13
20
  import { enumerableSource } from "../stdlib/object.js";
14
- import { coerceToNumber, coerceToString, compoundOperators } from "../stdlib/value.js";
21
+ import { coerceToNumber, coerceToString, compoundOperators, errorBrandName } from "../stdlib/value.js";
22
+ import { Values } from "../values.js";
15
23
  // What a loop does with its body's result: exit with a StatementResult, or undefined to keep iterating.
16
24
  // Unlabelled break ends this loop; a label the loop does not carry propagates outward.
17
25
  const loopExit = (result, labels) => {
@@ -42,16 +50,37 @@ const calleeDescription = (callee) => {
42
50
  }
43
51
  return "The called value";
44
52
  };
45
- // OrdinaryHasInstance: walk the left operand's chain looking for the constructor's `prototype`.
53
+ const constructorName = (value) => {
54
+ if (typeof value === "string")
55
+ return "String";
56
+ if (typeof value === "number")
57
+ return "Number";
58
+ if (typeof value === "boolean")
59
+ return "Boolean";
60
+ if (value instanceof ProgramArray)
61
+ return "Array";
62
+ if (value instanceof Values.Date)
63
+ return "Date";
64
+ if (value instanceof Values.RegExp)
65
+ return "RegExp";
66
+ if (value instanceof Values.Map)
67
+ return "Map";
68
+ if (value instanceof Values.Set)
69
+ return "Set";
70
+ if (value instanceof Values.URL)
71
+ return "URL";
72
+ if (value instanceof Values.URLSearchParams)
73
+ return "URLSearchParams";
74
+ if (value instanceof Values.Promise)
75
+ return "Promise";
76
+ if (!(value instanceof ProgramObject) || value instanceof ProgramFunction)
77
+ return undefined;
78
+ return errorBrandName(value) ?? "Object";
79
+ };
46
80
  const instanceofValue = (lhs, rhs, node) => {
47
- if (!(rhs instanceof Callable)) {
48
- throw new InterpreterRuntimeError("The right-hand side of 'instanceof' is not callable.", node);
49
- }
50
- const prototype = get(rhs, "prototype");
51
- if (!(prototype instanceof ProgramObject)) {
52
- throw new InterpreterRuntimeError("The right-hand side of 'instanceof' has no 'prototype' object.", node);
53
- }
54
- return hasPrototype(lhs, prototype);
81
+ if (rhs instanceof HostFunction && rhs.instanceOf !== undefined)
82
+ return rhs.instanceOf(lhs);
83
+ throw new InterpreterRuntimeError("The right-hand side of 'instanceof' must be a supported constructor: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", node);
55
84
  };
56
85
  const collectPatternNames = (pattern, out = []) => {
57
86
  switch (pattern.type) {
@@ -141,6 +170,10 @@ const loopDeclaration = (left, statement) => {
141
170
  lexical: kind !== "var",
142
171
  };
143
172
  };
173
+ const isOpaqueMemberReference = (value) => value instanceof ToolReference ||
174
+ value instanceof PromiseInstanceMethodReference ||
175
+ value instanceof IntrinsicReference ||
176
+ value instanceof GeneratorMethodReference;
144
177
  const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
145
178
  /** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
146
179
  export class Runtime {
@@ -148,29 +181,29 @@ export class Runtime {
148
181
  search;
149
182
  toolKeys;
150
183
  promises;
151
- prototypes;
152
184
  logs;
153
185
  runner;
186
+ /** Built-in globals by name, unaffected by program shadowing. */
187
+ builtins;
154
188
  root;
155
- constructor(executeTool, search, toolKeys, promises, prototypes, logs = [], extraGlobals = () => []) {
189
+ constructor(executeTool, search, toolKeys, promises, logs = [], extraGlobals = () => []) {
156
190
  this.executeTool = executeTool;
157
191
  this.search = search;
158
192
  this.toolKeys = toolKeys;
159
193
  this.promises = promises;
160
- this.prototypes = prototypes;
161
194
  this.logs = logs;
162
195
  const globalScope = new Map();
163
196
  // Calling back into the program never reads frame state, so any frame serves; the root is always alive.
164
197
  this.root = new Frame(this, new ScopeStack([globalScope]));
165
198
  this.runner = {
166
- invokeCallable: (callable, thisValue, args, node) => this.root.invokeCallable(callable, thisValue, args, node),
199
+ invokeFunction: (fn, args) => this.root.invokeFunction(fn, args),
200
+ invokeCallable: (callable, args, node) => this.root.invokeCallable(callable, args, node),
167
201
  settlePromise: (promise) => this.root.settlePromise(promise),
168
202
  syncIterator: (value, node) => this.root.syncIterator(value, node),
169
- prototypes,
170
203
  };
171
- for (const [name, value] of [...globals(this), ...extraGlobals(this)]) {
204
+ this.builtins = new Map([...globals(this), ...extraGlobals(this)]);
205
+ for (const [name, value] of this.builtins)
172
206
  globalScope.set(name, { mutable: false, value });
173
- }
174
207
  }
175
208
  run(program) {
176
209
  return this.root.run(program);
@@ -216,7 +249,10 @@ class Frame {
216
249
  }
217
250
  // Fork at the call site so admission and hooks occur when the call is made.
218
251
  createToolCallPromise(path, args) {
219
- return this.runtime.promises.create(Effect.suspend(() => this.runtime.executeTool(path, args)));
252
+ return this.createPromise(Effect.suspend(() => this.runtime.executeTool(path, args)));
253
+ }
254
+ createPromise(effect) {
255
+ return this.runtime.promises.create(effect);
220
256
  }
221
257
  // Fiber exits make settlement idempotent; yielding prevents inline continuation.
222
258
  settlePromise(promise) {
@@ -289,7 +325,7 @@ class Frame {
289
325
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
290
326
  }
291
327
  createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
292
- return new ProgramFunction(this.runtime.prototypes.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
328
+ return new ProgramFunction(name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
293
329
  }
294
330
  // NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
295
331
  evaluateNamed(node, name) {
@@ -469,7 +505,7 @@ class Frame {
469
505
  const iterator = yield* self.customIterator(right, node, awaiting);
470
506
  const cursor = iterator === undefined ? yield* self.syncIterator(right, node) : undefined;
471
507
  if (iterator === undefined && cursor === undefined) {
472
- throw new InterpreterRuntimeError(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams, or custom iterator value.`, node);
508
+ throw new InterpreterRuntimeError(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams, or custom iterator value.`, node).as("TypeError");
473
509
  }
474
510
  const close = () => iterator
475
511
  ? self.closeIterator(iterator, node, awaiting)
@@ -543,21 +579,20 @@ class Frame {
543
579
  ? value.items[Symbol.iterator]()
544
580
  : typeof value === "string"
545
581
  ? value[Symbol.iterator]()
546
- : value instanceof ProgramMap
582
+ : value instanceof Values.Map
547
583
  ? value.map.entries()
548
- : value instanceof ProgramSet
584
+ : value instanceof Values.Set
549
585
  ? value.set.values()
550
- : value instanceof ProgramURLSearchParams
586
+ : value instanceof Values.URLSearchParams
551
587
  ? value.params.entries()
552
588
  : undefined;
553
589
  if (iterator !== undefined) {
554
- const proto = this.runtime.prototypes.Array;
555
590
  return Effect.succeed({
556
591
  next: Effect.sync(() => {
557
592
  const step = iterator.next();
558
593
  return {
559
594
  done: Boolean(step.done),
560
- value: Array.isArray(step.value) ? new ProgramArray(proto, step.value) : step.value,
595
+ value: Array.isArray(step.value) ? new ProgramArray(step.value) : step.value,
561
596
  };
562
597
  }),
563
598
  close: Effect.void,
@@ -572,6 +607,15 @@ class Frame {
572
607
  });
573
608
  }
574
609
  customIterator(value, node, allowAsync = true) {
610
+ if (value instanceof CodeModeGenerator) {
611
+ if (value.asynchronous && !allowAsync)
612
+ return Effect.undefined;
613
+ return Effect.succeed({
614
+ iterator: value,
615
+ next: new GeneratorMethodReference(value, "next"),
616
+ asynchronous: value.asynchronous,
617
+ });
618
+ }
575
619
  if (!(value instanceof ProgramObject))
576
620
  return Effect.undefined;
577
621
  const asyncMethod = allowAsync ? get(value, AsyncIteratorSymbol) : undefined;
@@ -579,11 +623,13 @@ class Frame {
579
623
  if (method === undefined || method === null)
580
624
  return Effect.undefined;
581
625
  const self = this;
582
- return Effect.map(this.invokeCallable(this.requireIteratorMethod(method, "Iterator method", node), value, [], node), (iterator) => {
583
- const object = self.requireIteratorObject(iterator, "Iterator method result", node);
626
+ return Effect.map(this.invokeCallable(this.requireIteratorMethod(method, "Iterator method", node), [], node), (iterator) => {
627
+ const object = self.requireIterator(iterator, node);
584
628
  return {
585
629
  iterator: object,
586
- next: self.requireIteratorMethod(get(object, "next"), "Iterator next", node),
630
+ next: object instanceof CodeModeGenerator
631
+ ? new GeneratorMethodReference(object, "next")
632
+ : self.requireIteratorMethod(get(object, "next"), "Iterator next", node),
587
633
  asynchronous: asyncMethod !== undefined && asyncMethod !== null,
588
634
  };
589
635
  });
@@ -592,10 +638,10 @@ class Frame {
592
638
  const self = this;
593
639
  return Effect.gen(function* () {
594
640
  if (iterator.asynchronous) {
595
- const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(iterator.next, iterator.iterator, [], node)), "Iterator next() result", node);
641
+ const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(iterator.next, [], node)), "Iterator next() result", node);
596
642
  return { done: Boolean(get(object, "done")), value: get(object, "value") };
597
643
  }
598
- const called = yield* Effect.exit(self.invokeCallable(iterator.next, iterator.iterator, [], node));
644
+ const called = yield* Effect.exit(self.invokeCallable(iterator.next, [], node));
599
645
  if (!Exit.isSuccess(called)) {
600
646
  if (awaiting)
601
647
  yield* Effect.yieldNow;
@@ -619,17 +665,19 @@ class Frame {
619
665
  });
620
666
  }
621
667
  closeIterator(iterator, node, awaiting = true) {
622
- const close = get(iterator.iterator, "return");
668
+ const close = iterator.iterator instanceof CodeModeGenerator
669
+ ? new GeneratorMethodReference(iterator.iterator, "return")
670
+ : get(iterator.iterator, "return");
623
671
  if (close === undefined || close === null)
624
672
  return iterator.asynchronous || !awaiting ? Effect.void : Effect.yieldNow;
625
673
  const self = this;
626
674
  return Effect.gen(function* () {
627
675
  const method = self.requireIteratorMethod(close, "Iterator return", node);
628
676
  if (iterator.asynchronous) {
629
- self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(method, iterator.iterator, [], node)), "Iterator return() result", node);
677
+ self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(method, [], node)), "Iterator return() result", node);
630
678
  return;
631
679
  }
632
- const called = yield* Effect.exit(self.invokeCallable(method, iterator.iterator, [], node));
680
+ const called = yield* Effect.exit(self.invokeCallable(method, [], node));
633
681
  if (!Exit.isSuccess(called)) {
634
682
  if (awaiting)
635
683
  yield* Effect.yieldNow;
@@ -648,12 +696,17 @@ class Frame {
648
696
  requireIteratorObject(value, context, node) {
649
697
  if (value instanceof ProgramObject)
650
698
  return value;
651
- throw new InterpreterRuntimeError(`${context} must be an object.`, node);
699
+ throw new InterpreterRuntimeError(`${context} must be an object.`, node).as("TypeError");
700
+ }
701
+ requireIterator(value, node) {
702
+ return value instanceof CodeModeGenerator
703
+ ? value
704
+ : this.requireIteratorObject(value, "Iterator method result", node);
652
705
  }
653
706
  requireIteratorMethod(value, context, node) {
654
707
  if (typeofValue(value) === "function")
655
708
  return value;
656
- throw new InterpreterRuntimeError(`${context} must be a function.`, node);
709
+ throw new InterpreterRuntimeError(`${context} must be a function.`, node).as("TypeError");
657
710
  }
658
711
  // for...in over null/undefined iterates nothing, like JS.
659
712
  enumerableKeys(value, node) {
@@ -661,7 +714,7 @@ class Frame {
661
714
  return [...this.runtime.toolKeys(value.path)];
662
715
  if (value === null || value === undefined)
663
716
  return [];
664
- return keys(enumerableSource(this.runtime.runner, "for...in", value, node));
717
+ return ownKeys(enumerableSource("for...in", value, node)).filter((key) => typeof key === "string");
665
718
  }
666
719
  evaluateForInStatement(node, labels) {
667
720
  const left = node.left;
@@ -749,7 +802,7 @@ class Frame {
749
802
  if (cause.reasons.some(Cause.isInterruptReason) || Cause.squash(cause) instanceof GeneratorReturn || !handler) {
750
803
  return Effect.failCause(cause);
751
804
  }
752
- const caught = caughtErrorValue(self.runtime.runner, Cause.squash(cause));
805
+ const caught = caughtErrorValue(Cause.squash(cause));
753
806
  const parameter = handler.param;
754
807
  self.scopes.push();
755
808
  return Effect.gen(function* () {
@@ -815,14 +868,14 @@ class Frame {
815
868
  const consumed = new Set();
816
869
  for (const property of pattern.properties) {
817
870
  if (property.type === "RestElement") {
818
- const rest = new ProgramObject(self.runtime.prototypes.Object);
871
+ const rest = new ProgramObject();
819
872
  assign(rest, value, consumed);
820
873
  yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
821
874
  continue;
822
875
  }
823
876
  const key = yield* self.destructuringPropertyKey(property);
824
877
  consumed.add(typeof key === "symbol" ? key : String(key));
825
- yield* self.declarePattern(property.value, get(value, key), mutable, property, initialize);
878
+ yield* self.declarePattern(property.value, self.destructuringPropertyValue(value, key), mutable, property, initialize);
826
879
  }
827
880
  return;
828
881
  }
@@ -855,14 +908,14 @@ class Frame {
855
908
  const consumed = new Set();
856
909
  for (const property of pattern.properties) {
857
910
  if (property.type === "RestElement") {
858
- const rest = new ProgramObject(self.runtime.prototypes.Object);
911
+ const rest = new ProgramObject();
859
912
  assign(rest, value, consumed);
860
913
  yield* self.assignPattern(property.argument, rest, property);
861
914
  continue;
862
915
  }
863
916
  const key = yield* self.destructuringPropertyKey(property);
864
917
  consumed.add(typeof key === "symbol" ? key : String(key));
865
- yield* self.assignPattern(property.value, get(value, key), property);
918
+ yield* self.assignPattern(property.value, self.destructuringPropertyValue(value, key), property);
866
919
  }
867
920
  return;
868
921
  }
@@ -882,14 +935,14 @@ class Frame {
882
935
  return Effect.gen(function* () {
883
936
  const cursor = yield* self.syncIterator(value, pattern);
884
937
  if (cursor === undefined) {
885
- throw new InterpreterRuntimeError("Array destructuring requires a supported iterable value.", pattern);
938
+ throw new InterpreterRuntimeError("Array destructuring requires a supported iterable value.", pattern).as("TypeError");
886
939
  }
887
940
  let done = false;
888
941
  for (const element of pattern.elements) {
889
942
  if (done) {
890
943
  if (element === null)
891
944
  continue;
892
- yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new ProgramArray(self.runtime.prototypes.Array) : undefined, element);
945
+ yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new ProgramArray() : undefined, element);
893
946
  if (element.type === "RestElement")
894
947
  return;
895
948
  continue;
@@ -908,7 +961,7 @@ class Frame {
908
961
  if (!done)
909
962
  rest.push(next.value);
910
963
  }
911
- yield* consume(element.argument, new ProgramArray(self.runtime.prototypes.Array, rest), element);
964
+ yield* consume(element.argument, new ProgramArray(rest), element);
912
965
  return;
913
966
  }
914
967
  const consumed = consume(element, step.done ? undefined : step.value, pattern);
@@ -932,13 +985,22 @@ class Frame {
932
985
  return Effect.succeed(String(keyNode.value));
933
986
  throw unsupportedSyntax(keyNode.type, keyNode);
934
987
  }
988
+ destructuringPropertyValue(source, key) {
989
+ if (!(source instanceof ProgramArray))
990
+ return get(source, key);
991
+ if (has(source, key))
992
+ return get(source, key);
993
+ if (typeof key === "string" && arrayMethods.has(key))
994
+ return new IntrinsicReference(source, key);
995
+ return undefined;
996
+ }
935
997
  evaluateExpression(node) {
936
998
  switch (node.type) {
937
999
  case "Literal": {
938
1000
  const regex = node.regex;
939
1001
  if (regex)
940
- return Effect.sync(() => constructRegExp(this.runtime.prototypes, [regex.pattern, regex.flags], node));
941
- return Effect.sync(() => toProgram(this.runtime.prototypes, node.value, "Literal"));
1002
+ return Effect.sync(() => constructRegExp([regex.pattern, regex.flags], node));
1003
+ return Effect.sync(() => toProgram(node.value, "Literal"));
942
1004
  }
943
1005
  case "Identifier":
944
1006
  return Effect.sync(() => this.scopes.get(node.name, node));
@@ -996,7 +1058,7 @@ class Frame {
996
1058
  return Effect.gen(function* () {
997
1059
  const callee = yield* self.evaluateExpression(node.callee);
998
1060
  // Globals are built with this interpreter's R; `instanceof` cannot recover the type argument.
999
- const construct = callee instanceof NativeFunction ? callee.construct : undefined;
1061
+ const construct = callee instanceof HostFunction ? callee.construct : undefined;
1000
1062
  if (construct === undefined) {
1001
1063
  // `new` itself is supported, so a non-constructible callee is a TypeError like JS rather than
1002
1064
  // unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
@@ -1004,13 +1066,13 @@ class Frame {
1004
1066
  const name = calleeDescription(node.callee);
1005
1067
  const message = callee instanceof ProgramFunction
1006
1068
  ? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
1007
- : callee instanceof NativeFunction
1069
+ : callee instanceof HostFunction
1008
1070
  ? `new ${name}(...) is not supported; call ${name}(...) without new instead.`
1009
1071
  : `${name} is not a constructor.`;
1010
- throw new InterpreterRuntimeError(message, node);
1072
+ throw new InterpreterRuntimeError(message, node).as("TypeError");
1011
1073
  }
1012
1074
  const args = yield* self.evaluateCallArguments(node.arguments);
1013
- return yield* construct(args, callee, node);
1075
+ return yield* construct(args, node);
1014
1076
  });
1015
1077
  }
1016
1078
  evaluateBinaryExpression(node) {
@@ -1024,7 +1086,7 @@ class Frame {
1024
1086
  const rhs = yield* self.evaluateExpression(node.right);
1025
1087
  if (operator === "instanceof")
1026
1088
  return instanceofValue(lhs, rhs, node);
1027
- return toProgram(self.runtime.prototypes, self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
1089
+ return toProgram(self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
1028
1090
  });
1029
1091
  }
1030
1092
  applyBinaryOperator(operator, lhs, rhs, node) {
@@ -1041,7 +1103,7 @@ class Frame {
1041
1103
  // Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
1042
1104
  // Dates use their default string hint for addition and loose equality, and epoch time elsewhere.
1043
1105
  const coerceOperand = (operand) => {
1044
- if (operand instanceof ProgramDate) {
1106
+ if (operand instanceof Values.Date) {
1045
1107
  return operator === "+" || operator === "==" || operator === "!=" ? coerceToString(operand) : operand.time;
1046
1108
  }
1047
1109
  return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand;
@@ -1126,7 +1188,7 @@ class Frame {
1126
1188
  if (containsOpaqueReference(value)) {
1127
1189
  throw new InterpreterRuntimeError("Unary operators require data values.", node, "InvalidDataValue");
1128
1190
  }
1129
- const operand = value instanceof ProgramDate
1191
+ const operand = value instanceof Values.Date
1130
1192
  ? value.time
1131
1193
  : value !== null && typeof value === "object"
1132
1194
  ? coerceToString(value)
@@ -1145,7 +1207,7 @@ class Frame {
1145
1207
  default:
1146
1208
  throw new InterpreterRuntimeError(`Unsupported unary operator '${operator}'.`, node);
1147
1209
  }
1148
- return toProgram(this.runtime.prototypes, result, "Unary expression result");
1210
+ return toProgram(result, "Unary expression result");
1149
1211
  });
1150
1212
  }
1151
1213
  evaluateAssignmentExpression(node) {
@@ -1166,7 +1228,7 @@ class Frame {
1166
1228
  if (operator !== "=") {
1167
1229
  const current = self.scopes.get(name, left);
1168
1230
  const rightValue = yield* self.evaluateExpression(node.right);
1169
- const next = toProgram(self.runtime.prototypes, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1231
+ const next = toProgram(self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1170
1232
  return self.scopes.set(name, next, left);
1171
1233
  }
1172
1234
  const rightValue = yield* self.evaluateNamed(node.right, name);
@@ -1176,7 +1238,7 @@ class Frame {
1176
1238
  return yield* self.modifyMember(left, (current) => Effect.map(self.evaluateExpression(node.right), (rightValue) => {
1177
1239
  if (operator === "=")
1178
1240
  return { write: true, next: rightValue, result: rightValue };
1179
- const next = toProgram(self.runtime.prototypes, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1241
+ const next = toProgram(self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1180
1242
  return { write: true, next, result: next };
1181
1243
  }));
1182
1244
  }
@@ -1241,37 +1303,23 @@ class Frame {
1241
1303
  }
1242
1304
  throw new InterpreterRuntimeError("Update target must be an Identifier or MemberExpression.", argument);
1243
1305
  }
1244
- // EvaluateCall: a member callee supplies its base object as `this`; anything else calls with undefined.
1245
1306
  evaluateCallExpression(node) {
1246
1307
  const callee = node.callee;
1247
1308
  const self = this;
1248
1309
  return Effect.gen(function* () {
1249
1310
  if (callee.type === "Super")
1250
1311
  throw unsupportedSyntax(callee.type, callee);
1251
- const { callable, thisValue } = callee.type === "MemberExpression"
1252
- ? yield* self.readMethod(callee)
1253
- : { callable: yield* self.evaluateExpression(callee), thisValue: undefined };
1312
+ const callable = yield* self.evaluateExpression(callee);
1254
1313
  if (callable === OptionalShortCircuit)
1255
1314
  return OptionalShortCircuit;
1256
1315
  if ((callable === null || callable === undefined) && node.optional)
1257
1316
  return OptionalShortCircuit;
1258
1317
  const args = yield* self.evaluateCallArguments(node.arguments);
1259
- return yield* self.invokeCallable(callable, thisValue, args, node, callee);
1260
- });
1261
- }
1262
- readMethod(node) {
1263
- return Effect.map(this.getMemberReference(node), (reference) => {
1264
- if (reference === OptionalShortCircuit)
1265
- return { callable: OptionalShortCircuit, thisValue: undefined };
1266
- if (reference instanceof ToolReference)
1267
- return { callable: reference, thisValue: undefined };
1268
- if ("value" in reference)
1269
- return { callable: reference.value, thisValue: undefined };
1270
- return { callable: this.readReference(reference, node), thisValue: reference.receiver };
1318
+ return yield* self.invokeCallable(callable, args, node, callee);
1271
1319
  });
1272
1320
  }
1273
1321
  // The single dispatch for every invocation: call expressions and callbacks share it.
1274
- invokeCallable(callable, thisValue, args, node, callee) {
1322
+ invokeCallable(callable, args, node, callee) {
1275
1323
  const self = this;
1276
1324
  return Effect.gen(function* () {
1277
1325
  if (callable instanceof ToolReference) {
@@ -1280,11 +1328,27 @@ class Frame {
1280
1328
  }
1281
1329
  return yield* self.createToolCallPromise(callable.path, args);
1282
1330
  }
1283
- if (callable instanceof ProgramFunction)
1331
+ if (callable instanceof ProgramFunction) {
1284
1332
  return yield* self.invokeFunction(callable, args);
1285
- if (callable instanceof NativeFunction)
1286
- return yield* callable.call(thisValue, args, node);
1287
- throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node);
1333
+ }
1334
+ if (callable instanceof GeneratorMethodReference) {
1335
+ if (callable.kind === "iterator")
1336
+ return callable.generator;
1337
+ const requested = callable.generator.request(callable.kind, args[0], node);
1338
+ return callable.generator.asynchronous ? yield* self.createPromise(requested) : yield* requested;
1339
+ }
1340
+ if (callable instanceof IntrinsicReference) {
1341
+ return yield* invokeIntrinsic(self.runtime.runner, callable, args, node);
1342
+ }
1343
+ if (callable instanceof PromiseInstanceMethodReference) {
1344
+ return yield* invokePromiseInstanceMethod(self.runtime.runner, self.runtime.promises, callable, args, node);
1345
+ }
1346
+ if (callable instanceof HostFunction)
1347
+ return yield* callable.call(args, node);
1348
+ if (callable === undefined || callable === null) {
1349
+ throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node).as("TypeError");
1350
+ }
1351
+ throw new InterpreterRuntimeError("Only tools are callable here.", callee ?? node);
1288
1352
  });
1289
1353
  }
1290
1354
  evaluateCallArguments(argNodes) {
@@ -1296,7 +1360,7 @@ class Frame {
1296
1360
  const spread = yield* self.evaluateExpression(argNode.argument);
1297
1361
  const cursor = yield* self.syncIterator(spread, argNode);
1298
1362
  if (cursor === undefined)
1299
- throw new InterpreterRuntimeError("Spread arguments require a synchronous iterable.", argNode);
1363
+ throw new InterpreterRuntimeError("Spread arguments require a synchronous iterable.", argNode).as("TypeError");
1300
1364
  while (true) {
1301
1365
  const step = yield* cursor.next;
1302
1366
  if (step.done)
@@ -1312,7 +1376,6 @@ class Frame {
1312
1376
  });
1313
1377
  }
1314
1378
  invokeFunction(fn, args) {
1315
- const self = this;
1316
1379
  const invocation = new Frame(this.runtime, new ScopeStack([...fn.capturedScopes, new Map()]));
1317
1380
  const run = Effect.gen(function* () {
1318
1381
  // Seed all parameters first so defaults cannot fall through to same-named outer bindings.
@@ -1324,7 +1387,7 @@ class Frame {
1324
1387
  }
1325
1388
  for (const [index, parameter] of fn.parameters.entries()) {
1326
1389
  if (parameter.type === "RestElement") {
1327
- yield* invocation.declarePattern(parameter.argument, new ProgramArray(self.runtime.prototypes.Array, args.slice(index)), true, parameter, true);
1390
+ yield* invocation.declarePattern(parameter.argument, new ProgramArray(args.slice(index)), true, parameter, true);
1328
1391
  break;
1329
1392
  }
1330
1393
  yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
@@ -1347,12 +1410,10 @@ class Frame {
1347
1410
  const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
1348
1411
  invocation.generatorState = state;
1349
1412
  invocation.generatorAsync = asynchronous;
1350
- const protos = this.runtime.prototypes;
1351
- const result = (value, done) => record(protos.Object, { value, done });
1352
- const request = (kind, value, node) => {
1413
+ const generator = new CodeModeGenerator(asynchronous, (kind, value, node) => {
1353
1414
  const request = { kind, value, response: Deferred.makeUnsafe() };
1354
1415
  if (!asynchronous && state.active) {
1355
- return Effect.fail(new InterpreterRuntimeError("Generator is already running.", node));
1416
+ return Effect.fail(new InterpreterRuntimeError("Generator is already running.", node).as("TypeError"));
1356
1417
  }
1357
1418
  if (asynchronous && (state.completed || (!state.started && kind !== "next"))) {
1358
1419
  state.started = true;
@@ -1368,13 +1429,13 @@ class Frame {
1368
1429
  if (state.completed) {
1369
1430
  if (kind === "throw")
1370
1431
  return Effect.fail(new ProgramThrow(value));
1371
- return Effect.succeed(result(kind === "return" ? value : undefined, true));
1432
+ return Effect.succeed(record({ value: kind === "return" ? value : undefined, done: true }));
1372
1433
  }
1373
1434
  if (!state.started && kind !== "next") {
1374
1435
  state.completed = true;
1375
1436
  if (kind === "throw")
1376
1437
  return Effect.fail(new ProgramThrow(value));
1377
- return Effect.succeed(result(value, true));
1438
+ return Effect.succeed(record({ value, done: true }));
1378
1439
  }
1379
1440
  state.pending.push(request);
1380
1441
  if (state.available) {
@@ -1394,7 +1455,7 @@ class Frame {
1394
1455
  const active = state.active;
1395
1456
  state.active = undefined;
1396
1457
  if (active) {
1397
- Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed(result(exit.value, true)) : exit);
1458
+ Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed(record({ value: exit.value, done: true })) : exit);
1398
1459
  }
1399
1460
  yield* invocation.completeGeneratorRequests(state, asynchronous);
1400
1461
  state.completed = true;
@@ -1402,13 +1463,11 @@ class Frame {
1402
1463
  return Effect.andThen(this.runtime.promises.fork(body), Deferred.await(request.response));
1403
1464
  }
1404
1465
  return Deferred.await(request.response);
1405
- };
1406
- const generator = new ProgramGenerator(asynchronous ? protos.AsyncGenerator : protos.Generator, asynchronous, request);
1466
+ });
1407
1467
  return generator;
1408
1468
  }
1409
1469
  completeGeneratorRequests(state, asynchronous) {
1410
1470
  const self = this;
1411
- const result = (value, done) => record(self.runtime.prototypes.Object, { value, done });
1412
1471
  return Effect.gen(function* () {
1413
1472
  while (true) {
1414
1473
  const pending = self.dequeueGeneratorRequest(state);
@@ -1420,10 +1479,10 @@ class Frame {
1420
1479
  }
1421
1480
  if (asynchronous && pending.kind === "return") {
1422
1481
  const resolved = yield* Effect.exit(self.awaitValue(pending.value));
1423
- Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed(result(resolved.value, true)) : resolved);
1482
+ Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed(record({ value: resolved.value, done: true })) : resolved);
1424
1483
  continue;
1425
1484
  }
1426
- Deferred.doneUnsafe(pending.response, Exit.succeed(result(pending.kind === "return" ? pending.value : undefined, true)));
1485
+ Deferred.doneUnsafe(pending.response, Exit.succeed(record({ value: pending.kind === "return" ? pending.value : undefined, done: true })));
1427
1486
  }
1428
1487
  });
1429
1488
  }
@@ -1464,7 +1523,7 @@ class Frame {
1464
1523
  const state = this.generatorState;
1465
1524
  if (!state?.active)
1466
1525
  throw new InterpreterRuntimeError("Generator has no active request.", node);
1467
- Deferred.doneUnsafe(state.active.response, Exit.succeed(record(this.runtime.prototypes.Object, { value, done: false })));
1526
+ Deferred.doneUnsafe(state.active.response, Exit.succeed(record({ value, done: false })));
1468
1527
  state.active = undefined;
1469
1528
  return Effect.flatMap(this.takeGeneratorRequest(state), (request) => {
1470
1529
  state.active = request;
@@ -1482,9 +1541,9 @@ class Frame {
1482
1541
  return Effect.gen(function* () {
1483
1542
  if (value instanceof ProgramArray ||
1484
1543
  typeof value === "string" ||
1485
- value instanceof ProgramMap ||
1486
- value instanceof ProgramSet ||
1487
- value instanceof ProgramURLSearchParams) {
1544
+ value instanceof Values.Map ||
1545
+ value instanceof Values.Set ||
1546
+ value instanceof Values.URLSearchParams) {
1488
1547
  const cursor = yield* self.syncIterator(value, node);
1489
1548
  if (!cursor)
1490
1549
  throw new InterpreterRuntimeError("Built-in iterator is unavailable.", node);
@@ -1502,25 +1561,29 @@ class Frame {
1502
1561
  }
1503
1562
  if (error instanceof ProgramThrow) {
1504
1563
  yield* cursor.close;
1505
- throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node);
1564
+ throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node).as("TypeError");
1506
1565
  }
1507
1566
  return yield* Effect.failCause(resumed.cause);
1508
1567
  }
1509
1568
  }
1510
1569
  const iterator = yield* self.customIterator(value, node, self.generatorAsync);
1511
1570
  if (!iterator)
1512
- throw new InterpreterRuntimeError("yield* requires a compatible iterable value.", node);
1571
+ throw new InterpreterRuntimeError("yield* requires a compatible iterable value.", node).as("TypeError");
1513
1572
  let kind = "next";
1514
1573
  let input = undefined;
1515
1574
  while (true) {
1516
- const method = kind === "next" ? iterator.next : get(iterator.iterator, kind);
1575
+ const method = kind === "next"
1576
+ ? iterator.next
1577
+ : iterator.iterator instanceof CodeModeGenerator
1578
+ ? new GeneratorMethodReference(iterator.iterator, kind)
1579
+ : get(iterator.iterator, kind);
1517
1580
  if (method === undefined || method === null) {
1518
1581
  if (kind === "return")
1519
1582
  return yield* Effect.fail(new GeneratorReturn(input));
1520
1583
  yield* self.closeIterator(iterator, node, self.generatorAsync);
1521
- throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node);
1584
+ throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node).as("TypeError");
1522
1585
  }
1523
- const called = yield* self.invokeCallable(self.requireIteratorMethod(method, `Iterator ${kind}`, node), iterator.iterator, [input], node);
1586
+ const called = yield* self.invokeCallable(self.requireIteratorMethod(method, `Iterator ${kind}`, node), [input], node);
1524
1587
  const result = self.requireIteratorObject(iterator.asynchronous ? yield* self.awaitValue(called) : called, `Iterator ${kind}() result`, node);
1525
1588
  const done = Boolean(get(result, "done"));
1526
1589
  const resultValue = self.generatorAsync && !iterator.asynchronous
@@ -1547,7 +1610,7 @@ class Frame {
1547
1610
  });
1548
1611
  }
1549
1612
  evaluateObjectExpression(node) {
1550
- const objectValue = new ProgramObject(this.runtime.prototypes.Object);
1613
+ const objectValue = new ProgramObject();
1551
1614
  const self = this;
1552
1615
  return Effect.gen(function* () {
1553
1616
  for (const property of node.properties) {
@@ -1555,7 +1618,7 @@ class Frame {
1555
1618
  const spread = yield* self.evaluateExpression(property.argument);
1556
1619
  if (spread === null || spread === undefined)
1557
1620
  continue;
1558
- assign(objectValue, enumerableSource(self.runtime.runner, "Object spread", spread, property));
1621
+ assign(objectValue, enumerableSource("Object spread", spread, property));
1559
1622
  continue;
1560
1623
  }
1561
1624
  if (property.kind !== "init") {
@@ -1580,7 +1643,7 @@ class Frame {
1580
1643
  : key === AsyncIteratorSymbol
1581
1644
  ? "[Symbol.asyncIterator]"
1582
1645
  : String(key);
1583
- define(objectValue, key, yield* self.evaluateNamed(property.value, name));
1646
+ set(objectValue, key, yield* self.evaluateNamed(property.value, name));
1584
1647
  }
1585
1648
  return objectValue;
1586
1649
  });
@@ -1599,7 +1662,7 @@ class Frame {
1599
1662
  const spread = yield* self.evaluateExpression(element.argument);
1600
1663
  const cursor = yield* self.syncIterator(spread, element);
1601
1664
  if (cursor === undefined)
1602
- throw new InterpreterRuntimeError("Array spread requires a synchronous iterable.", element);
1665
+ throw new InterpreterRuntimeError("Array spread requires a synchronous iterable.", element).as("TypeError");
1603
1666
  while (true) {
1604
1667
  const step = yield* cursor.next;
1605
1668
  if (step.done)
@@ -1611,7 +1674,7 @@ class Frame {
1611
1674
  values.push(yield* self.evaluateExpression(element));
1612
1675
  }
1613
1676
  }
1614
- return new ProgramArray(self.runtime.prototypes.Array, values);
1677
+ return new ProgramArray(values);
1615
1678
  });
1616
1679
  }
1617
1680
  evaluateTemplateLiteral(node) {
@@ -1629,7 +1692,7 @@ class Frame {
1629
1692
  output += quasi.value.cooked;
1630
1693
  if (index < expressions.length) {
1631
1694
  const raw = yield* self.evaluateExpression(expressions[index]);
1632
- output += coerceToString(toProgram(self.runtime.prototypes, raw, "Template interpolation"));
1695
+ output += coerceToString(toProgram(raw, "Template interpolation"));
1633
1696
  }
1634
1697
  }
1635
1698
  return output;
@@ -1644,7 +1707,7 @@ class Frame {
1644
1707
  }
1645
1708
  return this.applyBinaryOperator(operator.slice(0, -1), current, incoming, node);
1646
1709
  }
1647
- getMemberReference(node) {
1710
+ getMemberReference(node, operation = "read") {
1648
1711
  const objectNode = node.object;
1649
1712
  const propertyNode = node.property;
1650
1713
  if (objectNode.type === "Super")
@@ -1669,49 +1732,123 @@ class Frame {
1669
1732
  }
1670
1733
  return new ToolReference([...objectValue.path, key]);
1671
1734
  }
1672
- if (objectValue instanceof ProgramObject)
1673
- return { target: objectValue, key, receiver: objectValue };
1674
- // Primitives read through their wrapper prototype without being boxed; strings own length and indexes.
1675
- const protos = self.runtime.prototypes;
1735
+ if (objectValue instanceof HostFunction || objectValue instanceof HostNamespace) {
1736
+ // Unknown static members read as undefined so feature detection works like native JS.
1737
+ return new ComputedValue(objectValue.member(key, propertyNode));
1738
+ }
1739
+ // Values have no prototype chain, so `.constructor` resolves to the owning built-in directly.
1740
+ if (operation === "read" &&
1741
+ key === "constructor" &&
1742
+ !(objectValue instanceof ProgramObject && has(objectValue, key))) {
1743
+ const name = constructorName(objectValue);
1744
+ if (name !== undefined)
1745
+ return new ComputedValue(self.runtime.builtins.get(name));
1746
+ }
1676
1747
  if (typeof objectValue === "string") {
1677
1748
  if (key === "length")
1678
- return { value: objectValue.length };
1749
+ return new ComputedValue(objectValue.length);
1679
1750
  const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
1680
1751
  if (index !== undefined)
1681
- return { value: objectValue[index] };
1682
- return { target: protos.String, key, receiver: objectValue };
1752
+ return new ComputedValue(objectValue[index]);
1753
+ if (typeof key === "string" && stringMethods.has(key))
1754
+ return new IntrinsicReference(objectValue, key);
1755
+ return new ComputedValue(undefined);
1756
+ }
1757
+ if (typeof objectValue === "number") {
1758
+ if (typeof key === "string" && numberMethods.has(key))
1759
+ return new IntrinsicReference(objectValue, key);
1760
+ return new ComputedValue(undefined);
1761
+ }
1762
+ if (objectValue instanceof Values.Date) {
1763
+ if (typeof key === "string" && dateMethods.has(key))
1764
+ return new IntrinsicReference(objectValue, key);
1765
+ return new ComputedValue(undefined);
1766
+ }
1767
+ if (objectValue instanceof Values.RegExp) {
1768
+ if (key === "lastIndex")
1769
+ return { target: objectValue, key };
1770
+ if (typeof key === "string" && regexpProperties.has(key)) {
1771
+ return new ComputedValue(objectValue.regex[key]);
1772
+ }
1773
+ if (typeof key === "string" && regexpMethods.has(key))
1774
+ return new IntrinsicReference(objectValue, key);
1775
+ return new ComputedValue(undefined);
1776
+ }
1777
+ if (objectValue instanceof Values.Map) {
1778
+ if (key === "size")
1779
+ return new ComputedValue(objectValue.map.size);
1780
+ if (typeof key === "string" && mapMethods.has(key))
1781
+ return new IntrinsicReference(objectValue, key);
1782
+ return new ComputedValue(undefined);
1783
+ }
1784
+ if (objectValue instanceof Values.Set) {
1785
+ if (key === "size")
1786
+ return new ComputedValue(objectValue.set.size);
1787
+ if (typeof key === "string" && setMethods.has(key))
1788
+ return new IntrinsicReference(objectValue, key);
1789
+ return new ComputedValue(undefined);
1790
+ }
1791
+ if (objectValue instanceof Values.URL) {
1792
+ if (key === "searchParams") {
1793
+ return new ComputedValue(objectValue.searchParams);
1794
+ }
1795
+ if (typeof key === "string" && urlMethods.has(key))
1796
+ return new IntrinsicReference(objectValue, key);
1797
+ if (typeof key === "string" && urlProperties.has(key))
1798
+ return { target: objectValue, key };
1799
+ return new ComputedValue(undefined);
1800
+ }
1801
+ if (objectValue instanceof Values.URLSearchParams) {
1802
+ if (key === "size")
1803
+ return new ComputedValue(objectValue.params.size);
1804
+ if (typeof key === "string" && urlSearchParamsMethods.has(key)) {
1805
+ return new IntrinsicReference(objectValue, key);
1806
+ }
1807
+ return new ComputedValue(undefined);
1808
+ }
1809
+ // Reject unknown promise properties so a missing await cannot hide.
1810
+ if (objectValue instanceof Values.Promise) {
1811
+ if (key === "then" || key === "catch" || key === "finally") {
1812
+ return new PromiseInstanceMethodReference(objectValue, key);
1813
+ }
1814
+ throw new InterpreterRuntimeError("This value is an un-awaited Promise; await it first - e.g. `const result = await tools.ns.tool(...)`.", objectNode, "InvalidDataValue");
1815
+ }
1816
+ if (objectValue instanceof CodeModeGenerator) {
1817
+ if (key === "next" || key === "return" || key === "throw") {
1818
+ return new GeneratorMethodReference(objectValue, key);
1819
+ }
1820
+ if ((key === IteratorSymbol && !objectValue.asynchronous) ||
1821
+ (key === AsyncIteratorSymbol && objectValue.asynchronous)) {
1822
+ return new GeneratorMethodReference(objectValue, "iterator");
1823
+ }
1824
+ return new ComputedValue(undefined);
1683
1825
  }
1684
- if (typeof objectValue === "number")
1685
- return { target: protos.Number, key, receiver: objectValue };
1686
- if (typeof objectValue === "boolean")
1687
- return { target: protos.Boolean, key, receiver: objectValue };
1688
- if (objectValue === null || objectValue === undefined) {
1689
- throw new InterpreterRuntimeError(`Cannot read properties of ${objectValue} (reading '${String(key)}').`, objectNode);
1826
+ if (objectValue instanceof ProgramObject)
1827
+ return { target: objectValue, key };
1828
+ if (isRuntimeReference(objectValue)) {
1829
+ throw new InterpreterRuntimeError(`Cannot read properties of ${describeValue(objectValue)}; only data values expose properties.`, objectNode, "InvalidDataValue");
1690
1830
  }
1691
1831
  throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode);
1692
1832
  });
1693
1833
  }
1694
- readReference(reference, node) {
1695
- // Reject unknown promise properties so a missing await cannot hide.
1696
- if (reference.target instanceof ProgramPromise && !has(reference.target, reference.key)) {
1697
- throw new InterpreterRuntimeError("This value is an un-awaited Promise; await it first - e.g. `const result = await tools.ns.tool(...)`.", node.object, "InvalidDataValue");
1698
- }
1699
- try {
1700
- return get(reference.target, reference.key, reference.receiver);
1701
- }
1702
- catch (error) {
1703
- throw locate(error, node);
1704
- }
1705
- }
1706
1834
  readMember(node) {
1835
+ const self = this;
1707
1836
  return Effect.map(this.getMemberReference(node), (reference) => {
1708
1837
  if (reference === OptionalShortCircuit)
1709
1838
  return OptionalShortCircuit;
1710
- if (reference instanceof ToolReference)
1711
- return reference;
1712
- if ("value" in reference)
1839
+ if (reference instanceof ComputedValue)
1713
1840
  return reference.value;
1714
- return this.readReference(reference, node);
1841
+ if (reference === undefined || isOpaqueMemberReference(reference))
1842
+ return reference;
1843
+ const value = self.readReferenceValue(reference, reference.key);
1844
+ if (value === undefined &&
1845
+ reference.target instanceof ProgramArray &&
1846
+ typeof reference.key === "string" &&
1847
+ arrayMethods.has(reference.key) &&
1848
+ !has(reference.target, reference.key)) {
1849
+ return new IntrinsicReference(reference.target, reference.key);
1850
+ }
1851
+ return value;
1715
1852
  });
1716
1853
  }
1717
1854
  writeMember(node, value) {
@@ -1722,50 +1859,75 @@ class Frame {
1722
1859
  if (target.type !== "MemberExpression") {
1723
1860
  throw new InterpreterRuntimeError("Only data fields may be deleted.", argument);
1724
1861
  }
1725
- return Effect.map(this.getMemberReference(target), (reference) => {
1862
+ return Effect.map(this.getMemberReference(target, "delete"), (reference) => {
1726
1863
  if (reference === OptionalShortCircuit)
1727
1864
  return true;
1728
- if (reference instanceof ToolReference || "value" in reference || reference.receiver !== reference.target) {
1865
+ if (reference instanceof ComputedValue ||
1866
+ reference === undefined ||
1867
+ isOpaqueMemberReference(reference) ||
1868
+ reference.target instanceof Values.URL) {
1729
1869
  throw new InterpreterRuntimeError("Only data fields may be deleted.", target, "InvalidDataValue");
1730
1870
  }
1731
- if (remove(reference.target, reference.key))
1732
- return true;
1733
- throw new InterpreterRuntimeError(`Cannot delete property '${String(reference.key)}'.`, target);
1871
+ if (reference.target instanceof Values.RegExp) {
1872
+ return Reflect.deleteProperty(reference.target.regex, reference.key);
1873
+ }
1874
+ return remove(reference.target, reference.key);
1734
1875
  });
1735
1876
  }
1736
1877
  // Resolve side-effecting object and key expressions exactly once.
1737
1878
  modifyMember(node, compute) {
1738
1879
  const self = this;
1739
1880
  return Effect.gen(function* () {
1740
- const reference = yield* self.getMemberReference(node);
1741
- if (reference === OptionalShortCircuit || reference instanceof ToolReference || "value" in reference) {
1881
+ const reference = yield* self.getMemberReference(node, "write");
1882
+ if (reference === OptionalShortCircuit ||
1883
+ reference instanceof ComputedValue ||
1884
+ reference === undefined ||
1885
+ isOpaqueMemberReference(reference)) {
1742
1886
  throw new InterpreterRuntimeError("Only data fields may be assigned.", node);
1743
1887
  }
1744
- if (reference.receiver !== reference.target) {
1745
- throw new InterpreterRuntimeError(`Cannot create property '${String(reference.key)}' on ${typeof reference.receiver} '${String(reference.receiver)}'.`, node);
1746
- }
1747
1888
  const key = reference.key;
1748
- const { write, next, result } = yield* compute(self.readReference(reference, node));
1889
+ const { write, next, result } = yield* compute(self.readReferenceValue(reference, key));
1749
1890
  if (write)
1750
- self.assignToReference(reference.target, key, next, node);
1891
+ self.assignToReference(reference, key, next, node);
1751
1892
  return result;
1752
1893
  });
1753
1894
  }
1754
- assignToReference(target, key, next, node) {
1755
- rejectCircularInsertion(target, next, target instanceof ProgramArray ? "Array assignment result" : "Object assignment result", node);
1756
- const written = (() => {
1895
+ readReferenceValue(reference, key) {
1896
+ if (reference.target instanceof Values.URL) {
1897
+ return Reflect.get(reference.target.url, key);
1898
+ }
1899
+ if (reference.target instanceof Values.RegExp)
1900
+ return reference.target.lastIndex;
1901
+ return get(reference.target, key);
1902
+ }
1903
+ assignToReference(reference, key, next, node) {
1904
+ if (reference.target instanceof Values.URL) {
1905
+ const property = key;
1906
+ if (!urlWritableProperties.has(property)) {
1907
+ throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError");
1908
+ }
1757
1909
  try {
1758
- return set(target, key, next);
1910
+ const url = reference.target.url;
1911
+ url[property] = uriArgument(next, `URL.${property} value`);
1912
+ return;
1759
1913
  }
1760
1914
  catch (error) {
1761
- throw locate(error, node);
1915
+ if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError)
1916
+ throw error;
1917
+ throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError");
1762
1918
  }
1763
- })();
1764
- if (written)
1919
+ }
1920
+ if (reference.target instanceof Values.RegExp) {
1921
+ reference.target.lastIndex = next;
1922
+ return;
1923
+ }
1924
+ const target = reference.target;
1925
+ rejectCircularInsertion(target, next, target instanceof ProgramArray ? "Array assignment result" : "Object assignment result", node);
1926
+ if (set(target, key, next))
1765
1927
  return;
1766
- if (target instanceof ProgramArray && key === "length")
1767
- throw rangeError("Invalid array length", node);
1768
- throw new InterpreterRuntimeError(`Cannot assign to read only property '${String(key)}'.`, node);
1928
+ if (target instanceof ProgramArray)
1929
+ throw new InterpreterRuntimeError("Invalid array length", node).as("RangeError");
1930
+ throw new InterpreterRuntimeError(`Cannot assign to read only property '${String(key)}'.`, node).as("TypeError");
1769
1931
  }
1770
1932
  toPropertyKey(value, node) {
1771
1933
  if (typeof value === "string" || typeof value === "number") {