@opencode/codemode 0.0.0-beta-19425 → 0.0.0-beta-19507

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.
@@ -1,11 +1,12 @@
1
1
  import { Cause, Deferred, Effect, Exit } from "effect";
2
2
  import { ToolRuntimeError, toProgram } from "../data.js";
3
3
  import { ToolReference } from "../tool-runtime.js";
4
- import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, ComputedValue, GeneratorMethodReference, GeneratorReturn, IntrinsicReference, InterpreterRuntimeError, isRecord, IteratorSymbol, IteratorSymbols, OptionalShortCircuit, PromiseInstanceMethodReference, ProgramThrow, 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
7
  import { HostFunction, HostNamespace } from "./host.js";
8
8
  import { invokeIntrinsic } from "./methods.js";
9
+ import { assign, get, has, ownKeys, parseArrayIndex, ProgramArray, ProgramFunction, ProgramObject, record, remove, set, } from "./objects.js";
9
10
  import { preserveConsumerError } from "./runner.js";
10
11
  import { invokePromiseInstanceMethod, PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
11
12
  import { containsOpaqueReference, describeValue, isRuntimeReference, rejectCircularInsertion, typeofValue, } from "./references.js";
@@ -16,15 +17,22 @@ import { numberMethods } from "../stdlib/number.js";
16
17
  import { constructRegExp, regexpMethods, regexpProperties } from "../stdlib/regexp.js";
17
18
  import { stringMethods } from "../stdlib/string.js";
18
19
  import { uriArgument, urlMethods, urlProperties, urlSearchParamsMethods, urlWritableProperties } from "../stdlib/url.js";
20
+ import { enumerableSource } from "../stdlib/object.js";
19
21
  import { coerceToNumber, coerceToString, compoundOperators, errorBrandName } from "../stdlib/value.js";
20
22
  import { Values } from "../values.js";
21
- const MAX_ARRAY_LENGTH = 4_294_967_295;
22
- const parseArrayIndex = (key) => {
23
- const property = String(key);
24
- if (!/^(0|[1-9]\d*)$/.test(property))
25
- return undefined;
26
- const index = Number(property);
27
- return index < MAX_ARRAY_LENGTH ? index : undefined;
23
+ // What a loop does with its body's result: exit with a StatementResult, or undefined to keep iterating.
24
+ // Unlabelled break ends this loop; a label the loop does not carry propagates outward.
25
+ const loopExit = (result, labels) => {
26
+ if (result.kind === "return")
27
+ return result;
28
+ if (result.kind === "break") {
29
+ if (result.label !== undefined && !labels?.has(result.label))
30
+ return result;
31
+ return { kind: "none" };
32
+ }
33
+ if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label))
34
+ return result;
35
+ return undefined;
28
36
  };
29
37
  const calleeDescription = (callee) => {
30
38
  if (callee?.type === "Identifier")
@@ -42,7 +50,6 @@ const calleeDescription = (callee) => {
42
50
  }
43
51
  return "The called value";
44
52
  };
45
- const hasOwn = (value, key) => value !== null && typeof value === "object" && Object.hasOwn(value, key);
46
53
  const constructorName = (value) => {
47
54
  if (typeof value === "string")
48
55
  return "String";
@@ -50,7 +57,7 @@ const constructorName = (value) => {
50
57
  return "Number";
51
58
  if (typeof value === "boolean")
52
59
  return "Boolean";
53
- if (Array.isArray(value))
60
+ if (value instanceof ProgramArray)
54
61
  return "Array";
55
62
  if (value instanceof Values.Date)
56
63
  return "Date";
@@ -66,7 +73,7 @@ const constructorName = (value) => {
66
73
  return "URLSearchParams";
67
74
  if (value instanceof Values.Promise)
68
75
  return "Promise";
69
- if (value === null || typeof value !== "object" || isRuntimeReference(value))
76
+ if (!(value instanceof ProgramObject) || value instanceof ProgramFunction)
70
77
  return undefined;
71
78
  return errorBrandName(value) ?? "Object";
72
79
  };
@@ -100,6 +107,55 @@ const collectPatternNames = (pattern, out = []) => {
100
107
  }
101
108
  return out;
102
109
  };
110
+ // `var` names declared anywhere in a function body except inside nested functions, which own theirs.
111
+ // Memoized per body: a function's var names never change, and hoisting runs on every call.
112
+ const varNames = new WeakMap();
113
+ const collectVarNames = (node, out = []) => {
114
+ if (!node)
115
+ return out;
116
+ switch (node.type) {
117
+ case "VariableDeclaration":
118
+ if (node.kind === "var")
119
+ for (const declaration of node.declarations)
120
+ collectPatternNames(declaration.id, out);
121
+ break;
122
+ case "BlockStatement":
123
+ for (const statement of node.body)
124
+ collectVarNames(statement, out);
125
+ break;
126
+ case "IfStatement":
127
+ collectVarNames(node.consequent, out);
128
+ collectVarNames(node.alternate, out);
129
+ break;
130
+ case "ForStatement":
131
+ if (node.init?.type === "VariableDeclaration")
132
+ collectVarNames(node.init, out);
133
+ collectVarNames(node.body, out);
134
+ break;
135
+ case "ForInStatement":
136
+ case "ForOfStatement":
137
+ if (node.left.type === "VariableDeclaration")
138
+ collectVarNames(node.left, out);
139
+ collectVarNames(node.body, out);
140
+ break;
141
+ case "WhileStatement":
142
+ case "DoWhileStatement":
143
+ case "LabeledStatement":
144
+ collectVarNames(node.body, out);
145
+ break;
146
+ case "SwitchStatement":
147
+ for (const item of node.cases)
148
+ for (const statement of item.consequent)
149
+ collectVarNames(statement, out);
150
+ break;
151
+ case "TryStatement":
152
+ collectVarNames(node.block, out);
153
+ collectVarNames(node.handler?.body, out);
154
+ collectVarNames(node.finalizer, out);
155
+ break;
156
+ }
157
+ return out;
158
+ };
103
159
  const loopDeclaration = (left, statement) => {
104
160
  if (left.type !== "VariableDeclaration")
105
161
  return undefined;
@@ -118,12 +174,6 @@ const isOpaqueMemberReference = (value) => value instanceof ToolReference ||
118
174
  value instanceof PromiseInstanceMethodReference ||
119
175
  value instanceof IntrinsicReference ||
120
176
  value instanceof GeneratorMethodReference;
121
- const copyIteratorSymbols = (source, target, consumed) => {
122
- for (const symbol of IteratorSymbols) {
123
- if (!consumed?.has(symbol) && Object.hasOwn(source, symbol))
124
- Reflect.set(target, symbol, Reflect.get(source, symbol));
125
- }
126
- };
127
177
  const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
128
178
  /** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
129
179
  export class Runtime {
@@ -136,7 +186,7 @@ export class Runtime {
136
186
  /** Built-in globals by name, unaffected by program shadowing. */
137
187
  builtins;
138
188
  root;
139
- constructor(executeTool, search, toolKeys, promises, logs = []) {
189
+ constructor(executeTool, search, toolKeys, promises, logs = [], extraGlobals = () => []) {
140
190
  this.executeTool = executeTool;
141
191
  this.search = search;
142
192
  this.toolKeys = toolKeys;
@@ -151,7 +201,7 @@ export class Runtime {
151
201
  settlePromise: (promise) => this.root.settlePromise(promise),
152
202
  syncIterator: (value, node) => this.root.syncIterator(value, node),
153
203
  };
154
- this.builtins = new Map(globals(this));
204
+ this.builtins = new Map([...globals(this), ...extraGlobals(this)]);
155
205
  for (const [name, value] of this.builtins)
156
206
  globalScope.set(name, { mutable: false, value });
157
207
  }
@@ -176,6 +226,7 @@ class Frame {
176
226
  return Effect.gen(function* () {
177
227
  self.predeclareLexical(program.body);
178
228
  self.hoistFunctions(program.body);
229
+ self.hoistVars(program.body);
179
230
  let value = undefined;
180
231
  for (const [index, statement] of program.body.entries()) {
181
232
  if (index === program.body.length - 1 && statement.type === "ExpressionStatement") {
@@ -273,8 +324,15 @@ class Frame {
273
324
  return { kind: "none" };
274
325
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
275
326
  }
276
- createFunction(node) {
277
- return new CodeModeFunction(node.params, node.body, this.scopes.capture(), node.async, node.generator);
327
+ createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
328
+ return new ProgramFunction(name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
329
+ }
330
+ // NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
331
+ evaluateNamed(node, name) {
332
+ if (node.type === "ArrowFunctionExpression" || (node.type === "FunctionExpression" && !node.id)) {
333
+ return Effect.sync(() => this.createFunction(node, name));
334
+ }
335
+ return this.evaluateExpression(node);
278
336
  }
279
337
  hoistFunctions(statements) {
280
338
  for (const node of statements) {
@@ -283,6 +341,19 @@ class Frame {
283
341
  this.scopes.declare(node.id.name, this.createFunction(node), true, node);
284
342
  }
285
343
  }
344
+ // Hoisted `var` bindings start undefined, or copy a same-named parameter. Function bodies hoist
345
+ // into their own scope above the parameters so closures in parameter defaults keep seeing outer names.
346
+ hoistVars(statements, parameters) {
347
+ const names = varNames.get(statements) ??
348
+ statements.reduce((out, statement) => collectVarNames(statement, out), []);
349
+ varNames.set(statements, names);
350
+ const scope = this.scopes.current();
351
+ for (const name of names) {
352
+ if (scope.has(name))
353
+ continue;
354
+ scope.set(name, { mutable: true, value: parameters?.get(name)?.value, initialized: true });
355
+ }
356
+ }
286
357
  predeclareLexical(statements) {
287
358
  for (const statement of statements) {
288
359
  if (statement.type !== "VariableDeclaration")
@@ -318,7 +389,9 @@ class Frame {
318
389
  self.scopes.push();
319
390
  return yield* Effect.gen(function* () {
320
391
  const cases = node.cases;
321
- self.predeclareLexical(cases.flatMap((branch) => branch.consequent));
392
+ const statements = cases.flatMap((branch) => branch.consequent);
393
+ self.predeclareLexical(statements);
394
+ self.hoistFunctions(statements);
322
395
  let defaultIndex;
323
396
  let selected;
324
397
  for (const [index, branch] of cases.entries()) {
@@ -359,20 +432,9 @@ class Frame {
359
432
  const self = this;
360
433
  return Effect.gen(function* () {
361
434
  while (yield* self.evaluateExpression(node.test)) {
362
- const result = yield* self.evaluateStatement(node.body);
363
- if (result.kind === "continue") {
364
- if (result.label !== undefined && !labels?.has(result.label))
365
- return result;
366
- continue;
367
- }
368
- if (result.kind === "break") {
369
- if (result.label !== undefined && !labels?.has(result.label))
370
- return result;
371
- return { kind: "none" };
372
- }
373
- if (result.kind === "return") {
374
- return result;
375
- }
435
+ const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
436
+ if (exit !== undefined)
437
+ return exit;
376
438
  }
377
439
  return { kind: "none" };
378
440
  });
@@ -381,20 +443,9 @@ class Frame {
381
443
  const self = this;
382
444
  return Effect.gen(function* () {
383
445
  do {
384
- const result = yield* self.evaluateStatement(node.body);
385
- if (result.kind === "continue") {
386
- if (result.label !== undefined && !labels?.has(result.label))
387
- return result;
388
- continue;
389
- }
390
- if (result.kind === "break") {
391
- if (result.label !== undefined && !labels?.has(result.label))
392
- return result;
393
- return { kind: "none" };
394
- }
395
- if (result.kind === "return") {
396
- return result;
397
- }
446
+ const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
447
+ if (exit !== undefined)
448
+ return exit;
398
449
  } while (yield* self.evaluateExpression(node.test));
399
450
  return { kind: "none" };
400
451
  });
@@ -429,24 +480,13 @@ class Frame {
429
480
  };
430
481
  nextIteration();
431
482
  while (testNode ? yield* self.evaluateExpression(testNode) : true) {
432
- const result = yield* self.evaluateStatement(node.body);
433
- if (result.kind === "return") {
434
- return result;
435
- }
436
- if (result.kind === "break") {
437
- if (result.label !== undefined && !labels?.has(result.label))
438
- return result;
439
- return { kind: "none" };
440
- }
441
- if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label))
442
- return result;
483
+ const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
484
+ if (exit !== undefined)
485
+ return exit;
443
486
  nextIteration();
444
487
  if (updateNode) {
445
488
  yield* self.evaluateExpression(updateNode);
446
489
  }
447
- if (result.kind === "continue") {
448
- continue;
449
- }
450
490
  }
451
491
  return { kind: "none" };
452
492
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
@@ -477,18 +517,20 @@ class Frame {
477
517
  }
478
518
  const assignment = left.type === "VariableDeclaration" ? undefined : left;
479
519
  const evaluateBody = (value) => Effect.gen(function* () {
480
- if (declared) {
520
+ if (declared?.lexical) {
481
521
  self.scopes.push();
482
- if (declared.lexical)
483
- self.predeclarePattern(declared.pattern, declared.mutable, left);
484
- yield* self.declarePattern(declared.pattern, value, declared.mutable, left, declared.lexical);
522
+ self.predeclarePattern(declared.pattern, declared.mutable, left);
523
+ yield* self.declarePattern(declared.pattern, value, declared.mutable, left, true);
524
+ }
525
+ else if (declared) {
526
+ yield* self.assignPattern(declared.pattern, value, left);
485
527
  }
486
528
  else if (assignment) {
487
529
  yield* self.assignPattern(assignment, value, left);
488
530
  }
489
531
  return yield* self.evaluateStatement(node.body);
490
532
  }).pipe(Effect.ensuring(Effect.sync(() => {
491
- if (declared)
533
+ if (declared?.lexical)
492
534
  self.scopes.pop();
493
535
  })));
494
536
  while (true) {
@@ -506,20 +548,10 @@ class Frame {
506
548
  }
507
549
  return yield* Effect.failCause(bodyExit.cause);
508
550
  }
509
- const result = bodyExit.value;
510
- if (result.kind === "return") {
511
- yield* close();
512
- return result;
513
- }
514
- if (result.kind === "break") {
515
- yield* close();
516
- if (result.label !== undefined && !labels?.has(result.label))
517
- return result;
518
- return { kind: "none" };
519
- }
520
- if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label)) {
551
+ const exit = loopExit(bodyExit.value, labels);
552
+ if (exit !== undefined) {
521
553
  yield* close();
522
- return result;
554
+ return exit;
523
555
  }
524
556
  }
525
557
  }).pipe(Effect.ensuring(Effect.sync(() => {
@@ -543,8 +575,8 @@ class Frame {
543
575
  });
544
576
  }
545
577
  syncIterator(value, node) {
546
- const iterator = Array.isArray(value)
547
- ? value[Symbol.iterator]()
578
+ const iterator = value instanceof ProgramArray
579
+ ? value.items[Symbol.iterator]()
548
580
  : typeof value === "string"
549
581
  ? value[Symbol.iterator]()
550
582
  : value instanceof Values.Map
@@ -558,7 +590,10 @@ class Frame {
558
590
  return Effect.succeed({
559
591
  next: Effect.sync(() => {
560
592
  const step = iterator.next();
561
- return { done: Boolean(step.done), value: step.value };
593
+ return {
594
+ done: Boolean(step.done),
595
+ value: Array.isArray(step.value) ? new ProgramArray(step.value) : step.value,
596
+ };
562
597
  }),
563
598
  close: Effect.void,
564
599
  });
@@ -581,10 +616,10 @@ class Frame {
581
616
  asynchronous: value.asynchronous,
582
617
  });
583
618
  }
584
- if (!isRecord(value) || isRuntimeReference(value))
619
+ if (!(value instanceof ProgramObject))
585
620
  return Effect.undefined;
586
- const asyncMethod = allowAsync ? Reflect.get(value, AsyncIteratorSymbol) : undefined;
587
- const method = asyncMethod ?? Reflect.get(value, IteratorSymbol);
621
+ const asyncMethod = allowAsync ? get(value, AsyncIteratorSymbol) : undefined;
622
+ const method = asyncMethod ?? get(value, IteratorSymbol);
588
623
  if (method === undefined || method === null)
589
624
  return Effect.undefined;
590
625
  const self = this;
@@ -594,7 +629,7 @@ class Frame {
594
629
  iterator: object,
595
630
  next: object instanceof CodeModeGenerator
596
631
  ? new GeneratorMethodReference(object, "next")
597
- : self.requireIteratorMethod(object.next, "Iterator next", node),
632
+ : self.requireIteratorMethod(get(object, "next"), "Iterator next", node),
598
633
  asynchronous: asyncMethod !== undefined && asyncMethod !== null,
599
634
  };
600
635
  });
@@ -604,7 +639,7 @@ class Frame {
604
639
  return Effect.gen(function* () {
605
640
  if (iterator.asynchronous) {
606
641
  const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(iterator.next, [], node)), "Iterator next() result", node);
607
- return { done: Boolean(object.done), value: object.value };
642
+ return { done: Boolean(get(object, "done")), value: get(object, "value") };
608
643
  }
609
644
  const called = yield* Effect.exit(self.invokeCallable(iterator.next, [], node));
610
645
  if (!Exit.isSuccess(called)) {
@@ -614,7 +649,7 @@ class Frame {
614
649
  }
615
650
  const captured = yield* Effect.exit(Effect.sync(() => {
616
651
  const object = self.requireIteratorObject(called.value, "Iterator next() result", node);
617
- return { done: Boolean(object.done), value: object.value };
652
+ return { done: Boolean(get(object, "done")), value: get(object, "value") };
618
653
  }));
619
654
  if (!Exit.isSuccess(captured)) {
620
655
  if (awaiting)
@@ -632,7 +667,7 @@ class Frame {
632
667
  closeIterator(iterator, node, awaiting = true) {
633
668
  const close = iterator.iterator instanceof CodeModeGenerator
634
669
  ? new GeneratorMethodReference(iterator.iterator, "return")
635
- : iterator.iterator.return;
670
+ : get(iterator.iterator, "return");
636
671
  if (close === undefined || close === null)
637
672
  return iterator.asynchronous || !awaiting ? Effect.void : Effect.yieldNow;
638
673
  const self = this;
@@ -648,7 +683,7 @@ class Frame {
648
683
  yield* Effect.yieldNow;
649
684
  return yield* Effect.failCause(called.cause);
650
685
  }
651
- const captured = yield* Effect.exit(Effect.sync(() => self.requireIteratorObject(called.value, "Iterator return() result", node).value));
686
+ const captured = yield* Effect.exit(Effect.sync(() => get(self.requireIteratorObject(called.value, "Iterator return() result", node), "value")));
652
687
  if (!Exit.isSuccess(captured)) {
653
688
  if (awaiting)
654
689
  yield* Effect.yieldNow;
@@ -659,7 +694,7 @@ class Frame {
659
694
  });
660
695
  }
661
696
  requireIteratorObject(value, context, node) {
662
- if (isRecord(value) && !isRuntimeReference(value))
697
+ if (value instanceof ProgramObject)
663
698
  return value;
664
699
  throw new InterpreterRuntimeError(`${context} must be an object.`, node).as("TypeError");
665
700
  }
@@ -673,17 +708,13 @@ class Frame {
673
708
  return value;
674
709
  throw new InterpreterRuntimeError(`${context} must be a function.`, node).as("TypeError");
675
710
  }
676
- enumerableKeys(value) {
677
- if (value instanceof ToolReference) {
711
+ // for...in over null/undefined iterates nothing, like JS.
712
+ enumerableKeys(value, node) {
713
+ if (value instanceof ToolReference)
678
714
  return [...this.runtime.toolKeys(value.path)];
679
- }
680
- if (Array.isArray(value)) {
681
- return Object.keys(value);
682
- }
683
- if (value !== null && typeof value === "object" && !isRuntimeReference(value)) {
684
- return Object.keys(value);
685
- }
686
- return undefined;
715
+ if (value === null || value === undefined)
716
+ return [];
717
+ return ownKeys(enumerableSource("for...in", value, node)).filter((key) => typeof key === "string");
687
718
  }
688
719
  evaluateForInStatement(node, labels) {
689
720
  const left = node.left;
@@ -695,43 +726,32 @@ class Frame {
695
726
  if (declared?.lexical)
696
727
  self.predeclarePattern(declared.pattern, declared.mutable, left);
697
728
  const right = yield* self.evaluateExpression(node.right);
698
- const keys = self.enumerableKeys(right);
699
- if (keys === undefined) {
700
- throw new InterpreterRuntimeError("for...in requires a plain object, array, or tools reference. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", node);
701
- }
729
+ const keys = self.enumerableKeys(right, node.right);
702
730
  if (left.type !== "Identifier" && left.type !== "VariableDeclaration") {
703
731
  throw new InterpreterRuntimeError("Unsupported for...in binding.", left);
704
732
  }
705
733
  const assignmentName = left.type === "Identifier" ? left.name : undefined;
706
734
  for (const key of keys) {
707
735
  const result = yield* Effect.gen(function* () {
708
- if (declared) {
736
+ if (declared?.lexical) {
709
737
  self.scopes.push();
710
- if (declared.lexical)
711
- self.predeclarePattern(declared.pattern, declared.mutable, left);
712
- yield* self.declarePattern(declared.pattern, key, declared.mutable, left, declared.lexical);
738
+ self.predeclarePattern(declared.pattern, declared.mutable, left);
739
+ yield* self.declarePattern(declared.pattern, key, declared.mutable, left, true);
740
+ }
741
+ else if (declared) {
742
+ yield* self.assignPattern(declared.pattern, key, left);
713
743
  }
714
744
  else if (assignmentName) {
715
745
  self.scopes.set(assignmentName, key, left);
716
746
  }
717
747
  return yield* self.evaluateStatement(node.body);
718
748
  }).pipe(Effect.ensuring(Effect.sync(() => {
719
- if (declared)
749
+ if (declared?.lexical)
720
750
  self.scopes.pop();
721
751
  })));
722
- if (result.kind === "return") {
723
- return result;
724
- }
725
- if (result.kind === "break") {
726
- if (result.label !== undefined && !labels?.has(result.label))
727
- return result;
728
- return { kind: "none" };
729
- }
730
- if (result.kind === "continue") {
731
- if (result.label !== undefined && !labels?.has(result.label))
732
- return result;
733
- continue;
734
- }
752
+ const exit = loopExit(result, labels);
753
+ if (exit !== undefined)
754
+ return exit;
735
755
  }
736
756
  return { kind: "none" };
737
757
  }).pipe(Effect.ensuring(Effect.sync(() => {
@@ -812,8 +832,16 @@ class Frame {
812
832
  throw new InterpreterRuntimeError("Unsupported variable declaration shape.", declaration);
813
833
  }
814
834
  const init = declaration.init;
815
- const value = init ? yield* self.evaluateExpression(init) : undefined;
816
- yield* self.declarePattern(declaration.id, value, kind !== "const", declaration, kind !== "var");
835
+ // `var x` alone is a no-op: the binding was hoisted on function entry.
836
+ const id = declaration.id;
837
+ const evaluate = (init) => id.type === "Identifier" ? self.evaluateNamed(init, id.name) : self.evaluateExpression(init);
838
+ if (kind === "var") {
839
+ if (init)
840
+ yield* self.assignPattern(id, yield* evaluate(init), declaration);
841
+ continue;
842
+ }
843
+ const value = init ? yield* evaluate(init) : undefined;
844
+ yield* self.declarePattern(declaration.id, value, kind !== "const", declaration, true);
817
845
  }
818
846
  });
819
847
  }
@@ -829,23 +857,19 @@ class Frame {
829
857
  return;
830
858
  }
831
859
  if (pattern.type === "AssignmentPattern") {
832
- const resolved = value === undefined ? yield* self.evaluateExpression(pattern.right) : value;
860
+ const resolved = value === undefined ? yield* self.evaluateDefault(pattern) : value;
833
861
  yield* self.declarePattern(pattern.left, resolved, mutable, node, initialize);
834
862
  return;
835
863
  }
836
864
  if (pattern.type === "ObjectPattern") {
837
- if (value === null || typeof value !== "object" || isRuntimeReference(value)) {
865
+ if (!(value instanceof ProgramObject)) {
838
866
  throw new InterpreterRuntimeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern, "InvalidDataValue");
839
867
  }
840
868
  const consumed = new Set();
841
869
  for (const property of pattern.properties) {
842
870
  if (property.type === "RestElement") {
843
- const rest = Object.create(null);
844
- for (const [key, item] of Object.entries(value)) {
845
- if (!consumed.has(key))
846
- rest[key] = item;
847
- }
848
- copyIteratorSymbols(value, rest, consumed);
871
+ const rest = new ProgramObject();
872
+ assign(rest, value, consumed);
849
873
  yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
850
874
  continue;
851
875
  }
@@ -873,30 +897,25 @@ class Frame {
873
897
  return;
874
898
  }
875
899
  if (pattern.type === "AssignmentPattern") {
876
- const resolved = value === undefined ? yield* self.evaluateExpression(pattern.right) : value;
900
+ const resolved = value === undefined ? yield* self.evaluateDefault(pattern) : value;
877
901
  yield* self.assignPattern(pattern.left, resolved, node);
878
902
  return;
879
903
  }
880
904
  if (pattern.type === "ObjectPattern") {
881
- if (value === null || typeof value !== "object" || isRuntimeReference(value)) {
905
+ if (!(value instanceof ProgramObject)) {
882
906
  throw new InterpreterRuntimeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern, "InvalidDataValue");
883
907
  }
884
- const source = value;
885
908
  const consumed = new Set();
886
909
  for (const property of pattern.properties) {
887
910
  if (property.type === "RestElement") {
888
- const rest = Object.create(null);
889
- for (const [key, item] of Object.entries(source)) {
890
- if (!consumed.has(key))
891
- rest[key] = item;
892
- }
893
- copyIteratorSymbols(source, rest, consumed);
911
+ const rest = new ProgramObject();
912
+ assign(rest, value, consumed);
894
913
  yield* self.assignPattern(property.argument, rest, property);
895
914
  continue;
896
915
  }
897
916
  const key = yield* self.destructuringPropertyKey(property);
898
917
  consumed.add(typeof key === "symbol" ? key : String(key));
899
- yield* self.assignPattern(property.value, self.destructuringPropertyValue(source, key), property);
918
+ yield* self.assignPattern(property.value, self.destructuringPropertyValue(value, key), property);
900
919
  }
901
920
  return;
902
921
  }
@@ -906,6 +925,11 @@ class Frame {
906
925
  throw new InterpreterRuntimeError(`Unsupported assignment pattern '${pattern.type}'.`, node);
907
926
  });
908
927
  }
928
+ evaluateDefault(pattern) {
929
+ return pattern.left.type === "Identifier"
930
+ ? this.evaluateNamed(pattern.right, pattern.left.name)
931
+ : this.evaluateExpression(pattern.right);
932
+ }
909
933
  destructureArrayPattern(pattern, value, consume) {
910
934
  const self = this;
911
935
  return Effect.gen(function* () {
@@ -918,7 +942,7 @@ class Frame {
918
942
  if (done) {
919
943
  if (element === null)
920
944
  continue;
921
- yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? [] : undefined, element);
945
+ yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new ProgramArray() : undefined, element);
922
946
  if (element.type === "RestElement")
923
947
  return;
924
948
  continue;
@@ -937,7 +961,7 @@ class Frame {
937
961
  if (!done)
938
962
  rest.push(next.value);
939
963
  }
940
- yield* consume(element.argument, rest, element);
964
+ yield* consume(element.argument, new ProgramArray(rest), element);
941
965
  return;
942
966
  }
943
967
  const consumed = consume(element, step.done ? undefined : step.value, pattern);
@@ -962,14 +986,10 @@ class Frame {
962
986
  throw unsupportedSyntax(keyNode.type, keyNode);
963
987
  }
964
988
  destructuringPropertyValue(source, key) {
965
- if (!Array.isArray(source))
966
- return Reflect.get(source, key);
967
- if (key === "length")
968
- return source.length;
969
- if (typeof key === "number")
970
- return source[key];
971
- if (Object.hasOwn(source, key))
972
- return Reflect.get(source, key);
989
+ if (!(source instanceof ProgramArray))
990
+ return get(source, key);
991
+ if (has(source, key))
992
+ return get(source, key);
973
993
  if (typeof key === "string" && arrayMethods.has(key))
974
994
  return new IntrinsicReference(source, key);
975
995
  return undefined;
@@ -1044,7 +1064,7 @@ class Frame {
1044
1064
  // unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
1045
1065
  // otherwise; say `new` is unsupported for them and point at the plain call.
1046
1066
  const name = calleeDescription(node.callee);
1047
- const message = callee instanceof CodeModeFunction
1067
+ const message = callee instanceof ProgramFunction
1048
1068
  ? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
1049
1069
  : callee instanceof HostFunction
1050
1070
  ? `new ${name}(...) is not supported; call ${name}(...) without new instead.`
@@ -1074,6 +1094,9 @@ class Frame {
1074
1094
  return lhs === rhs;
1075
1095
  if (operator === "!==")
1076
1096
  return lhs !== rhs;
1097
+ if (operator === "in" && rhs instanceof ProgramObject && !containsOpaqueReference(lhs)) {
1098
+ return has(rhs, lhs !== null && typeof lhs === "object" ? coerceToString(lhs) : lhs);
1099
+ }
1077
1100
  if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) {
1078
1101
  throw new InterpreterRuntimeError("Binary operators require data values.", node, "InvalidDataValue");
1079
1102
  }
@@ -1126,11 +1149,10 @@ class Frame {
1126
1149
  case ">>>":
1127
1150
  return l >>> r;
1128
1151
  case "in":
1129
- if (rhs === null || typeof rhs !== "object") {
1152
+ if (!(rhs instanceof ProgramObject)) {
1130
1153
  throw new InterpreterRuntimeError("The 'in' operator requires a data object on the right-hand side.", node);
1131
1154
  }
1132
- // Never expose properties inherited from host prototypes.
1133
- return Object.hasOwn(rhs, coerceOperand(lhs));
1155
+ return has(rhs, coerceOperand(lhs));
1134
1156
  default:
1135
1157
  throw new InterpreterRuntimeError(`Unsupported binary operator '${operator}'.`, node);
1136
1158
  }
@@ -1209,7 +1231,7 @@ class Frame {
1209
1231
  const next = toProgram(self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1210
1232
  return self.scopes.set(name, next, left);
1211
1233
  }
1212
- const rightValue = yield* self.evaluateExpression(node.right);
1234
+ const rightValue = yield* self.evaluateNamed(node.right, name);
1213
1235
  return self.scopes.set(name, rightValue, left);
1214
1236
  }
1215
1237
  if (left.type === "MemberExpression") {
@@ -1232,7 +1254,7 @@ class Frame {
1232
1254
  const current = self.scopes.get(name, left);
1233
1255
  if (!shouldAssign(current))
1234
1256
  return current;
1235
- const rightValue = yield* self.evaluateExpression(node.right);
1257
+ const rightValue = yield* self.evaluateNamed(node.right, name);
1236
1258
  return self.scopes.set(name, rightValue, left);
1237
1259
  });
1238
1260
  }
@@ -1306,7 +1328,7 @@ class Frame {
1306
1328
  }
1307
1329
  return yield* self.createToolCallPromise(callable.path, args);
1308
1330
  }
1309
- if (callable instanceof CodeModeFunction) {
1331
+ if (callable instanceof ProgramFunction) {
1310
1332
  return yield* self.invokeFunction(callable, args);
1311
1333
  }
1312
1334
  if (callable instanceof GeneratorMethodReference) {
@@ -1365,12 +1387,14 @@ class Frame {
1365
1387
  }
1366
1388
  for (const [index, parameter] of fn.parameters.entries()) {
1367
1389
  if (parameter.type === "RestElement") {
1368
- yield* invocation.declarePattern(parameter.argument, args.slice(index), true, parameter, true);
1390
+ yield* invocation.declarePattern(parameter.argument, new ProgramArray(args.slice(index)), true, parameter, true);
1369
1391
  break;
1370
1392
  }
1371
1393
  yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
1372
1394
  }
1373
1395
  if (fn.body.type === "BlockStatement") {
1396
+ invocation.scopes.push();
1397
+ invocation.hoistVars(fn.body.body, paramScope);
1374
1398
  const result = yield* invocation.evaluateStatement(fn.body);
1375
1399
  return result.kind === "return" ? result.value : undefined;
1376
1400
  }
@@ -1380,12 +1404,7 @@ class Frame {
1380
1404
  return Effect.succeed(this.createGenerator(invocation, run, fn.async));
1381
1405
  if (!fn.async)
1382
1406
  return run;
1383
- // The initial yield assigns the promise before the body can self-resolve.
1384
- const box = {};
1385
- return Effect.map(this.createPromise(Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runtime.runner, value, fn.body, box))), (promise) => {
1386
- box.promise = promise;
1387
- return promise;
1388
- });
1407
+ return this.runtime.promises.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runtime.runner, value, fn.body, self)));
1389
1408
  }
1390
1409
  createGenerator(invocation, run, asynchronous) {
1391
1410
  const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
@@ -1410,13 +1429,13 @@ class Frame {
1410
1429
  if (state.completed) {
1411
1430
  if (kind === "throw")
1412
1431
  return Effect.fail(new ProgramThrow(value));
1413
- return Effect.succeed({ value: kind === "return" ? value : undefined, done: true });
1432
+ return Effect.succeed(record({ value: kind === "return" ? value : undefined, done: true }));
1414
1433
  }
1415
1434
  if (!state.started && kind !== "next") {
1416
1435
  state.completed = true;
1417
1436
  if (kind === "throw")
1418
1437
  return Effect.fail(new ProgramThrow(value));
1419
- return Effect.succeed({ value, done: true });
1438
+ return Effect.succeed(record({ value, done: true }));
1420
1439
  }
1421
1440
  state.pending.push(request);
1422
1441
  if (state.available) {
@@ -1436,7 +1455,7 @@ class Frame {
1436
1455
  const active = state.active;
1437
1456
  state.active = undefined;
1438
1457
  if (active) {
1439
- Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed({ value: exit.value, done: true }) : exit);
1458
+ Deferred.doneUnsafe(active.response, Exit.isSuccess(exit) ? Exit.succeed(record({ value: exit.value, done: true })) : exit);
1440
1459
  }
1441
1460
  yield* invocation.completeGeneratorRequests(state, asynchronous);
1442
1461
  state.completed = true;
@@ -1460,10 +1479,10 @@ class Frame {
1460
1479
  }
1461
1480
  if (asynchronous && pending.kind === "return") {
1462
1481
  const resolved = yield* Effect.exit(self.awaitValue(pending.value));
1463
- Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed({ value: resolved.value, done: true }) : resolved);
1482
+ Deferred.doneUnsafe(pending.response, Exit.isSuccess(resolved) ? Exit.succeed(record({ value: resolved.value, done: true })) : resolved);
1464
1483
  continue;
1465
1484
  }
1466
- Deferred.doneUnsafe(pending.response, Exit.succeed({ value: pending.kind === "return" ? pending.value : undefined, done: true }));
1485
+ Deferred.doneUnsafe(pending.response, Exit.succeed(record({ value: pending.kind === "return" ? pending.value : undefined, done: true })));
1467
1486
  }
1468
1487
  });
1469
1488
  }
@@ -1504,7 +1523,7 @@ class Frame {
1504
1523
  const state = this.generatorState;
1505
1524
  if (!state?.active)
1506
1525
  throw new InterpreterRuntimeError("Generator has no active request.", node);
1507
- Deferred.doneUnsafe(state.active.response, Exit.succeed({ value, done: false }));
1526
+ Deferred.doneUnsafe(state.active.response, Exit.succeed(record({ value, done: false })));
1508
1527
  state.active = undefined;
1509
1528
  return Effect.flatMap(this.takeGeneratorRequest(state), (request) => {
1510
1529
  state.active = request;
@@ -1520,7 +1539,7 @@ class Frame {
1520
1539
  delegateYield(value, node) {
1521
1540
  const self = this;
1522
1541
  return Effect.gen(function* () {
1523
- if (Array.isArray(value) ||
1542
+ if (value instanceof ProgramArray ||
1524
1543
  typeof value === "string" ||
1525
1544
  value instanceof Values.Map ||
1526
1545
  value instanceof Values.Set ||
@@ -1557,7 +1576,7 @@ class Frame {
1557
1576
  ? iterator.next
1558
1577
  : iterator.iterator instanceof CodeModeGenerator
1559
1578
  ? new GeneratorMethodReference(iterator.iterator, kind)
1560
- : iterator.iterator[kind];
1579
+ : get(iterator.iterator, kind);
1561
1580
  if (method === undefined || method === null) {
1562
1581
  if (kind === "return")
1563
1582
  return yield* Effect.fail(new GeneratorReturn(input));
@@ -1566,10 +1585,10 @@ class Frame {
1566
1585
  }
1567
1586
  const called = yield* self.invokeCallable(self.requireIteratorMethod(method, `Iterator ${kind}`, node), [input], node);
1568
1587
  const result = self.requireIteratorObject(iterator.asynchronous ? yield* self.awaitValue(called) : called, `Iterator ${kind}() result`, node);
1569
- const done = Boolean(result.done);
1588
+ const done = Boolean(get(result, "done"));
1570
1589
  const resultValue = self.generatorAsync && !iterator.asynchronous
1571
- ? yield* self.awaitAsyncFromSyncValue(iterator, result.value, node, kind !== "return" && !done)
1572
- : result.value;
1590
+ ? yield* self.awaitAsyncFromSyncValue(iterator, get(result, "value"), node, kind !== "return" && !done)
1591
+ : get(result, "value");
1573
1592
  if (done) {
1574
1593
  if (kind === "return")
1575
1594
  return yield* Effect.fail(new GeneratorReturn(resultValue));
@@ -1591,20 +1610,15 @@ class Frame {
1591
1610
  });
1592
1611
  }
1593
1612
  evaluateObjectExpression(node) {
1594
- const objectValue = Object.create(null);
1613
+ const objectValue = new ProgramObject();
1595
1614
  const self = this;
1596
1615
  return Effect.gen(function* () {
1597
1616
  for (const property of node.properties) {
1598
1617
  if (property.type === "SpreadElement") {
1599
1618
  const spread = yield* self.evaluateExpression(property.argument);
1600
- if (spread === null || spread === undefined || Values.isValue(spread))
1619
+ if (spread === null || spread === undefined)
1601
1620
  continue;
1602
- if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) {
1603
- throw new InterpreterRuntimeError(`Object spread requires a data object, received ${describeValue(spread)}.`, property, "InvalidDataValue");
1604
- }
1605
- for (const [key, value] of Object.entries(spread))
1606
- objectValue[key] = value;
1607
- copyIteratorSymbols(spread, objectValue);
1621
+ assign(objectValue, enumerableSource("Object spread", spread, property));
1608
1622
  continue;
1609
1623
  }
1610
1624
  if (property.kind !== "init") {
@@ -1624,7 +1638,12 @@ class Frame {
1624
1638
  else {
1625
1639
  throw new InterpreterRuntimeError("Unsupported object property key shape.", keyNode);
1626
1640
  }
1627
- Reflect.set(objectValue, key, yield* self.evaluateExpression(property.value));
1641
+ const name = key === IteratorSymbol
1642
+ ? "[Symbol.iterator]"
1643
+ : key === AsyncIteratorSymbol
1644
+ ? "[Symbol.asyncIterator]"
1645
+ : String(key);
1646
+ set(objectValue, key, yield* self.evaluateNamed(property.value, name));
1628
1647
  }
1629
1648
  return objectValue;
1630
1649
  });
@@ -1655,7 +1674,7 @@ class Frame {
1655
1674
  values.push(yield* self.evaluateExpression(element));
1656
1675
  }
1657
1676
  }
1658
- return values;
1677
+ return new ProgramArray(values);
1659
1678
  });
1660
1679
  }
1661
1680
  evaluateTemplateLiteral(node) {
@@ -1718,7 +1737,9 @@ class Frame {
1718
1737
  return new ComputedValue(objectValue.member(key, propertyNode));
1719
1738
  }
1720
1739
  // Values have no prototype chain, so `.constructor` resolves to the owning built-in directly.
1721
- if (operation === "read" && key === "constructor" && !hasOwn(objectValue, key)) {
1740
+ if (operation === "read" &&
1741
+ key === "constructor" &&
1742
+ !(objectValue instanceof ProgramObject && has(objectValue, key))) {
1722
1743
  const name = constructorName(objectValue);
1723
1744
  if (name !== undefined)
1724
1745
  return new ComputedValue(self.runtime.builtins.get(name));
@@ -1802,28 +1823,16 @@ class Frame {
1802
1823
  }
1803
1824
  return new ComputedValue(undefined);
1804
1825
  }
1826
+ if (objectValue instanceof ProgramObject)
1827
+ return { target: objectValue, key };
1805
1828
  if (isRuntimeReference(objectValue)) {
1806
1829
  throw new InterpreterRuntimeError(`Cannot read properties of ${describeValue(objectValue)}; only data values expose properties.`, objectNode, "InvalidDataValue");
1807
1830
  }
1808
- if (typeof objectValue !== "object" || objectValue === null) {
1809
- throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode);
1810
- }
1811
- if (Array.isArray(objectValue)) {
1812
- if (operation === "delete")
1813
- return { target: objectValue, key };
1814
- const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
1815
- if (key !== "length" && !(typeof key === "string" && arrayMethods.has(key)) && index === undefined) {
1816
- if (typeof key === "string" && Object.hasOwn(objectValue, key)) {
1817
- return new ComputedValue(objectValue[key]);
1818
- }
1819
- return new ComputedValue(undefined);
1820
- }
1821
- return { target: objectValue, key: index ?? key };
1822
- }
1823
- return { target: objectValue, key };
1831
+ throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode);
1824
1832
  });
1825
1833
  }
1826
1834
  readMember(node) {
1835
+ const self = this;
1827
1836
  return Effect.map(this.getMemberReference(node), (reference) => {
1828
1837
  if (reference === OptionalShortCircuit)
1829
1838
  return OptionalShortCircuit;
@@ -1831,19 +1840,15 @@ class Frame {
1831
1840
  return reference.value;
1832
1841
  if (reference === undefined || isOpaqueMemberReference(reference))
1833
1842
  return reference;
1834
- if (Array.isArray(reference.target)) {
1835
- if (reference.key === "length")
1836
- return reference.target.length;
1837
- if (typeof reference.key === "string")
1838
- return new IntrinsicReference(reference.target, reference.key);
1839
- return Reflect.get(reference.target, reference.key);
1840
- }
1841
- if (reference.target instanceof Values.RegExp)
1842
- return reference.target.lastIndex;
1843
- if (reference.target instanceof Values.URL) {
1844
- return Reflect.get(reference.target.url, reference.key);
1845
- }
1846
- return Reflect.get(reference.target, reference.key);
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;
1847
1852
  });
1848
1853
  }
1849
1854
  writeMember(node, value) {
@@ -1866,7 +1871,7 @@ class Frame {
1866
1871
  if (reference.target instanceof Values.RegExp) {
1867
1872
  return Reflect.deleteProperty(reference.target.regex, reference.key);
1868
1873
  }
1869
- return Reflect.deleteProperty(reference.target, reference.key);
1874
+ return remove(reference.target, reference.key);
1870
1875
  });
1871
1876
  }
1872
1877
  // Resolve side-effecting object and key expressions exactly once.
@@ -1880,13 +1885,6 @@ class Frame {
1880
1885
  isOpaqueMemberReference(reference)) {
1881
1886
  throw new InterpreterRuntimeError("Only data fields may be assigned.", node);
1882
1887
  }
1883
- if (Array.isArray(reference.target)) {
1884
- if (reference.key === "length")
1885
- throw new InterpreterRuntimeError("Array length cannot be assigned.", node);
1886
- if (typeof reference.key === "string" && arrayMethods.has(reference.key)) {
1887
- throw new InterpreterRuntimeError("Array methods cannot be assigned.", node);
1888
- }
1889
- }
1890
1888
  const key = reference.key;
1891
1889
  const { write, next, result } = yield* compute(self.readReferenceValue(reference, key));
1892
1890
  if (write)
@@ -1900,18 +1898,9 @@ class Frame {
1900
1898
  }
1901
1899
  if (reference.target instanceof Values.RegExp)
1902
1900
  return reference.target.lastIndex;
1903
- return Reflect.get(reference.target, key);
1901
+ return get(reference.target, key);
1904
1902
  }
1905
1903
  assignToReference(reference, key, next, node) {
1906
- if (Array.isArray(reference.target)) {
1907
- const target = reference.target;
1908
- if (typeof key !== "number" || parseArrayIndex(key) === undefined) {
1909
- throw new InterpreterRuntimeError("Array assignment index must be a valid array index.", node, "InvalidDataValue");
1910
- }
1911
- rejectCircularInsertion(target, next, "Array assignment result", node);
1912
- target[key] = next;
1913
- return;
1914
- }
1915
1904
  if (reference.target instanceof Values.URL) {
1916
1905
  const property = key;
1917
1906
  if (!urlWritableProperties.has(property)) {
@@ -1933,8 +1922,12 @@ class Frame {
1933
1922
  return;
1934
1923
  }
1935
1924
  const target = reference.target;
1936
- rejectCircularInsertion(target, next, "Object assignment result", node);
1937
- Reflect.set(target, key, next);
1925
+ rejectCircularInsertion(target, next, target instanceof ProgramArray ? "Array assignment result" : "Object assignment result", node);
1926
+ if (set(target, key, next))
1927
+ return;
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");
1938
1931
  }
1939
1932
  toPropertyKey(value, node) {
1940
1933
  if (typeof value === "string" || typeof value === "number") {