@opencode/codemode 2.0.12 → 2.0.14

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 (49) hide show
  1. package/dist/data.d.ts +5 -4
  2. package/dist/interpreter/callback.d.ts +10 -15
  3. package/dist/interpreter/callback.js +15 -7
  4. package/dist/interpreter/errors.d.ts +3 -3
  5. package/dist/interpreter/errors.js +1 -2
  6. package/dist/interpreter/execute.d.ts +2 -1
  7. package/dist/interpreter/extensions.d.ts +2 -1
  8. package/dist/interpreter/extensions.js +7 -35
  9. package/dist/interpreter/globals.d.ts +2 -1
  10. package/dist/interpreter/globals.js +1 -1
  11. package/dist/interpreter/interpreter.d.ts +8 -19
  12. package/dist/interpreter/interpreter.js +96 -98
  13. package/dist/interpreter/intrinsics.d.ts +3 -3
  14. package/dist/interpreter/intrinsics.js +2 -0
  15. package/dist/interpreter/model.d.ts +7 -8
  16. package/dist/interpreter/model.js +0 -1
  17. package/dist/interpreter/native.d.ts +5 -5
  18. package/dist/interpreter/objects.d.ts +148 -47
  19. package/dist/interpreter/objects.js +224 -26
  20. package/dist/interpreter/promises.d.ts +7 -7
  21. package/dist/interpreter/promises.js +32 -11
  22. package/dist/interpreter/references.d.ts +8 -7
  23. package/dist/interpreter/references.js +10 -46
  24. package/dist/interpreter/scope.d.ts +5 -4
  25. package/dist/stdlib/array.d.ts +2 -1
  26. package/dist/stdlib/array.js +29 -51
  27. package/dist/stdlib/bytes.js +14 -24
  28. package/dist/stdlib/collections.js +27 -30
  29. package/dist/stdlib/console.d.ts +2 -2
  30. package/dist/stdlib/console.js +6 -50
  31. package/dist/stdlib/date.js +1 -2
  32. package/dist/stdlib/headers.js +10 -22
  33. package/dist/stdlib/iterator.d.ts +1 -1
  34. package/dist/stdlib/iterator.js +294 -6
  35. package/dist/stdlib/json.js +3 -5
  36. package/dist/stdlib/math.js +5 -17
  37. package/dist/stdlib/number.js +8 -21
  38. package/dist/stdlib/object.d.ts +3 -4
  39. package/dist/stdlib/object.js +5 -16
  40. package/dist/stdlib/regexp.d.ts +3 -3
  41. package/dist/stdlib/regexp.js +1 -2
  42. package/dist/stdlib/string.js +10 -20
  43. package/dist/stdlib/url.d.ts +2 -1
  44. package/dist/stdlib/url.js +6 -16
  45. package/dist/stdlib/value.d.ts +0 -3
  46. package/dist/stdlib/value.js +2 -74
  47. package/dist/stdlib/web.js +1 -2
  48. package/dist/tool-runtime.js +38 -28
  49. package/package.json +1 -1
@@ -6,14 +6,14 @@ import { checkStringLength } from "./limits.js";
6
6
  import { locate, materialize } from "./errors.js";
7
7
  import { primitivePrototype } from "./intrinsics.js";
8
8
  import { globals } from "./globals.js";
9
- import { assign, Callable, define, get, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Bytes, DateObj, Fn, GeneratorObj, IteratorObj, MapObj, Obj, PromiseObj, SetObj, URLSearchParamsObj, HeadersObj, record, remove, set, } from "./objects.js";
9
+ import { assign, Callable, define, get, hostCursor, IteratorObj, has, hidden, hasPrototype, keys, Native, parseArrayIndex, Arr, Fn, GeneratorObj, Obj, PromiseObj, record, remove, set, coerceToNumber, coerceToString, } from "./objects.js";
10
10
  import { preserveConsumerError } from "./callback.js";
11
11
  import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
12
12
  import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
13
13
  import { ScopeStack } from "./scope.js";
14
14
  import { constructRegExp } from "../stdlib/regexp.js";
15
15
  import { enumerableSource } from "../stdlib/object.js";
16
- import { coerceToNumber, coerceToString, compoundOperators } from "../stdlib/value.js";
16
+ import { compoundOperators } from "../stdlib/value.js";
17
17
  // What a loop does with its body's result: exit with a StatementResult, or undefined to keep iterating.
18
18
  // Unlabelled break ends this loop; a label the loop does not carry propagates outward.
19
19
  const loopExit = (result, labels) => {
@@ -51,6 +51,14 @@ const calleeDescription = (node) => {
51
51
  return object === undefined ? undefined : `${object}.${key}`;
52
52
  };
53
53
  // OrdinaryHasInstance: walk the left operand's chain looking for the constructor's `prototype`.
54
+ // acorn types every literal as possibly a BigInt or RegExp; regex literals become RegExp objects before this is asked.
55
+ const literal = (node) => {
56
+ if (typeof node.value === "bigint")
57
+ throw typeError("BigInt literals are not supported.", node);
58
+ if (node.value instanceof RegExp)
59
+ throw unsupportedSyntax("RegExpLiteral", node);
60
+ return node.value;
61
+ };
54
62
  const instanceofValue = (lhs, rhs, node) => {
55
63
  if (!(rhs instanceof Callable)) {
56
64
  throw typeError("The right-hand side of 'instanceof' is not callable.", node);
@@ -180,6 +188,9 @@ export class Interpreter {
180
188
  iterate(value) {
181
189
  return this.root.iterate(value);
182
190
  }
191
+ iterateDirect(value) {
192
+ return this.root.iterateDirect(value);
193
+ }
183
194
  /** Runs one host tool: arguments cross as JSON and the result comes back as program values. */
184
195
  tool(run, args) {
185
196
  const ctx = this;
@@ -307,7 +318,16 @@ class Frame {
307
318
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
308
319
  }
309
320
  createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
310
- return new Fn(this.ctx.builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
321
+ const builtins = this.ctx.builtins;
322
+ const fn = new Fn(builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
323
+ // Each generator function gets its own prototype, so `g() instanceof g` holds as in JS.
324
+ if (node.generator)
325
+ define(fn, "prototype", new Obj(node.async ? builtins.AsyncGenerator : builtins.Generator), hidden);
326
+ // The body of a named function expression sees its own name, read-only.
327
+ if (node.type === "FunctionExpression" && node.id) {
328
+ fn.capturedScopes.push(new Map([[node.id.name, { mutable: false, value: fn, initialized: true }]]));
329
+ }
330
+ return fn;
311
331
  }
312
332
  // NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
313
333
  evaluateNamed(node, name) {
@@ -316,11 +336,12 @@ class Frame {
316
336
  }
317
337
  return this.evaluateExpression(node);
318
338
  }
339
+ // Repeated `function` declarations and `var` clashes are legal: the last declaration wins.
319
340
  hoistFunctions(statements) {
320
341
  for (const node of statements) {
321
342
  if (node.type !== "FunctionDeclaration")
322
343
  continue;
323
- this.scopes.declare(node.id.name, this.createFunction(node), true, node);
344
+ this.scopes.current().set(node.id.name, { mutable: true, value: this.createFunction(node), initialized: true });
324
345
  }
325
346
  }
326
347
  // Hoisted `var` bindings start undefined, or copy a same-named parameter. Function bodies hoist
@@ -484,10 +505,10 @@ class Frame {
484
505
  if (declared?.lexical)
485
506
  self.predeclarePattern(declared.pattern, declared.mutable, left);
486
507
  const right = yield* self.evaluateExpression(node.right);
487
- const cursor = self.hostCursor(right);
508
+ const cursor = self.builtinCursor(right);
488
509
  const iterator = cursor === undefined ? yield* self.customIterator(right, node, awaiting) : undefined;
489
510
  if (iterator === undefined && cursor === undefined) {
490
- throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, URLSearchParams, or Headers, or custom iterator value.`, node);
511
+ throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an iterable value, received ${describeValue(right)}.`, node);
491
512
  }
492
513
  const close = () => iterator
493
514
  ? self.closeIterator(iterator, node, awaiting)
@@ -525,10 +546,9 @@ class Frame {
525
546
  const bodyExit = yield* Effect.exit(evaluateBody(step.value));
526
547
  if (!Exit.isSuccess(bodyExit)) {
527
548
  // Process interruption must remain prompt; user cleanup cannot extend a timeout.
528
- if (!Cause.hasInterruptsOnly(bodyExit.cause)) {
529
- yield* Effect.exit(close());
530
- }
531
- return yield* Effect.failCause(bodyExit.cause);
549
+ if (Cause.hasInterruptsOnly(bodyExit.cause))
550
+ return yield* Effect.failCause(bodyExit.cause);
551
+ return yield* preserveConsumerError(close(), Effect.failCause(bodyExit.cause));
532
552
  }
533
553
  const exit = loopExit(bodyExit.value, labels);
534
554
  if (exit !== undefined) {
@@ -557,49 +577,41 @@ class Frame {
557
577
  });
558
578
  }
559
579
  iterate(value, node) {
560
- const cursor = this.hostCursor(value);
580
+ const cursor = this.builtinCursor(value);
561
581
  if (cursor !== undefined)
562
582
  return Effect.succeed(cursor);
563
- const self = this;
564
- return Effect.map(this.customIterator(value, node, false), (iterator) => iterator === undefined
565
- ? undefined
566
- : {
567
- next: self.nextIteratorResult(iterator, node, false),
568
- close: Effect.suspend(() => self.closeIterator(iterator, node, false)),
569
- });
583
+ return Effect.map(this.customIterator(value, node, false), (iterator) => iterator === undefined ? undefined : this.customCursor(iterator, node));
584
+ }
585
+ /** GetIteratorDirect: drive an iterator by its own `next`, without asking for `[Symbol.iterator]`. */
586
+ iterateDirect(value, node) {
587
+ if (value instanceof IteratorObj)
588
+ return value.cursor;
589
+ if (!(value instanceof Obj)) {
590
+ throw typeError(`An iterator must be an object, received ${describeValue(value)}.`, node);
591
+ }
592
+ return this.customCursor({
593
+ iterator: value,
594
+ next: this.requireIteratorMethod(get(value, "next"), "Iterator next", node),
595
+ asynchronous: false,
596
+ }, node);
570
597
  }
571
- hostCursor(value) {
572
- const iterator = value instanceof Arr
573
- ? value.items[Symbol.iterator]()
574
- : typeof value === "string"
575
- ? value[Symbol.iterator]()
576
- : value instanceof MapObj
577
- ? value.map.entries()
578
- : value instanceof SetObj
579
- ? value.set.values()
580
- : value instanceof URLSearchParamsObj
581
- ? value.params.entries()
582
- : value instanceof HeadersObj
583
- ? value.headers.entries()
584
- : value instanceof Bytes
585
- ? value.bytes.values()
586
- : value instanceof IteratorObj
587
- ? value.iterator
588
- : undefined;
589
- if (iterator === undefined)
590
- return undefined;
591
- const proto = this.ctx.builtins.Array;
598
+ customCursor(iterator, node) {
592
599
  return {
593
- next: Effect.sync(() => {
594
- const step = iterator.next();
595
- return {
596
- done: Boolean(step.done),
597
- value: Array.isArray(step.value) ? new Arr(proto, step.value) : step.value,
598
- };
599
- }),
600
- close: Effect.void,
600
+ next: this.nextIteratorResult(iterator, node, false),
601
+ close: Effect.suspend(() => this.closeIterator(iterator, node, false)),
601
602
  };
602
603
  }
604
+ builtinCursor(value) {
605
+ // Natives build their cursors without knowing R, like `lift` in native.ts.
606
+ if (value instanceof IteratorObj)
607
+ return value.cursor;
608
+ const iterator = typeof value === "string"
609
+ ? value[Symbol.iterator]()
610
+ : value instanceof Obj
611
+ ? value.iterator(this.ctx.builtins)
612
+ : undefined;
613
+ return iterator === undefined ? undefined : hostCursor(iterator);
614
+ }
603
615
  customIterator(value, node, allowAsync = true) {
604
616
  if (!(value instanceof Obj))
605
617
  return Effect.undefined;
@@ -941,7 +953,7 @@ class Frame {
941
953
  return;
942
954
  }
943
955
  const consumed = consume(element, step.done ? undefined : step.value, pattern);
944
- yield* step.done ? consumed : preserveConsumerError(cursor, consumed);
956
+ yield* step.done ? consumed : preserveConsumerError(cursor.close, consumed);
945
957
  }
946
958
  if (!done)
947
959
  yield* cursor.close;
@@ -953,7 +965,7 @@ class Frame {
953
965
  }
954
966
  const keyNode = property.key;
955
967
  if (property.computed) {
956
- return Effect.map(this.evaluateExpression(keyNode), (value) => this.toPropertyKey(value, keyNode));
968
+ return Effect.map(this.evaluateExpression(keyNode), (value) => this.toPropertyKey(value));
957
969
  }
958
970
  if (keyNode.type === "Identifier")
959
971
  return Effect.succeed(keyNode.name);
@@ -967,9 +979,7 @@ class Frame {
967
979
  const regex = node.regex;
968
980
  if (regex)
969
981
  return Effect.sync(() => constructRegExp(this.ctx.builtins, [regex.pattern, regex.flags]));
970
- if (typeof node.value === "bigint")
971
- throw typeError("BigInt literals are not supported.", node);
972
- return Effect.succeed(node.value);
982
+ return Effect.succeed(literal(node));
973
983
  }
974
984
  case "Identifier":
975
985
  return Effect.sync(() => this.scopes.get(node.name, node));
@@ -1069,14 +1079,9 @@ class Frame {
1069
1079
  if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) {
1070
1080
  throw invalidData("Binary operators require data values.", node);
1071
1081
  }
1072
- // Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
1073
- // Dates use their default string hint for addition and loose equality, and epoch time elsewhere.
1074
- const coerceOperand = (operand) => {
1075
- if (operand instanceof DateObj) {
1076
- return operator === "+" || operator === "==" || operator === "!=" ? coerceToString(operand) : operand.time;
1077
- }
1078
- return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand;
1079
- };
1082
+ // Addition and loose equality use the default hint; every other operator asks for a number.
1083
+ const hint = operator === "+" || operator === "==" || operator === "!=" ? "default" : "number";
1084
+ const coerceOperand = (operand) => (operand instanceof Obj ? operand.toPrimitive(hint) : operand);
1080
1085
  const bothObjects = lhs !== null && typeof lhs === "object" && rhs !== null && typeof rhs === "object";
1081
1086
  const l = coerceOperand(lhs);
1082
1087
  const r = coerceOperand(rhs);
@@ -1161,11 +1166,7 @@ class Frame {
1161
1166
  if (containsOpaqueReference(value)) {
1162
1167
  throw invalidData("Unary operators require data values.", node);
1163
1168
  }
1164
- const operand = value instanceof DateObj
1165
- ? value.time
1166
- : value !== null && typeof value === "object"
1167
- ? coerceToString(value)
1168
- : value;
1169
+ const operand = value instanceof Obj ? value.toPrimitive("number") : value;
1169
1170
  let result;
1170
1171
  switch (operator) {
1171
1172
  case "+":
@@ -1358,14 +1359,14 @@ class Frame {
1358
1359
  if (depth > MAX_CALL_DEPTH)
1359
1360
  throw rangeError("Maximum call stack size exceeded", node);
1360
1361
  const invocation = new Frame(this.ctx, new ScopeStack([...fn.capturedScopes, new Map()]), depth);
1361
- const run = Effect.gen(function* () {
1362
- // Seed all parameters first so defaults cannot fall through to same-named outer bindings.
1363
- const paramScope = invocation.scopes.current();
1364
- for (const parameter of fn.parameters) {
1365
- for (const name of collectPatternNames(parameter)) {
1366
- paramScope.set(name, { mutable: true, value: undefined, initialized: false });
1367
- }
1362
+ // Seed all parameters first so defaults cannot fall through to same-named outer bindings.
1363
+ const paramScope = invocation.scopes.current();
1364
+ for (const parameter of fn.parameters) {
1365
+ for (const name of collectPatternNames(parameter)) {
1366
+ paramScope.set(name, { mutable: true, value: undefined, initialized: false });
1368
1367
  }
1368
+ }
1369
+ const bind = Effect.gen(function* () {
1369
1370
  for (const [index, parameter] of fn.parameters.entries()) {
1370
1371
  if (parameter.type === "RestElement") {
1371
1372
  yield* invocation.declarePattern(parameter.argument, new Arr(self.ctx.builtins.Array, args.slice(index)), true, parameter, true);
@@ -1373,6 +1374,8 @@ class Frame {
1373
1374
  }
1374
1375
  yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
1375
1376
  }
1377
+ });
1378
+ const body = Effect.gen(function* () {
1376
1379
  if (fn.body.type === "BlockStatement") {
1377
1380
  invocation.scopes.push();
1378
1381
  invocation.hoistVars(fn.body.body, paramScope);
@@ -1381,14 +1384,17 @@ class Frame {
1381
1384
  }
1382
1385
  return yield* invocation.evaluateExpression(fn.body);
1383
1386
  });
1387
+ // Generators bind parameters at the call and defer only the body to the first `next()`, as in JS.
1384
1388
  if (fn.generator)
1385
- return Effect.succeed(this.createGenerator(invocation, run, fn.async));
1389
+ return Effect.map(bind, () => this.createGenerator(invocation, body, fn));
1390
+ const run = Effect.andThen(bind, body);
1386
1391
  if (!fn.async)
1387
1392
  return run;
1388
1393
  return this.ctx.pending.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.ctx, value, self)));
1389
1394
  });
1390
1395
  }
1391
- createGenerator(invocation, run, asynchronous) {
1396
+ createGenerator(invocation, run, fn) {
1397
+ const asynchronous = fn.async;
1392
1398
  const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
1393
1399
  invocation.generatorState = state;
1394
1400
  invocation.generatorAsync = asynchronous;
@@ -1447,8 +1453,8 @@ class Frame {
1447
1453
  }
1448
1454
  return Deferred.await(request.response);
1449
1455
  };
1450
- const generator = new GeneratorObj(asynchronous ? builtins.AsyncGenerator : builtins.Generator, asynchronous, request);
1451
- return generator;
1456
+ const proto = get(fn, "prototype");
1457
+ return new GeneratorObj(proto instanceof Obj ? proto : builtins.Generator, asynchronous, request);
1452
1458
  }
1453
1459
  completeGeneratorRequests(state, asynchronous) {
1454
1460
  const self = this;
@@ -1524,16 +1530,8 @@ class Frame {
1524
1530
  delegateYield(value, node) {
1525
1531
  const self = this;
1526
1532
  return Effect.gen(function* () {
1527
- if (value instanceof Arr ||
1528
- typeof value === "string" ||
1529
- value instanceof MapObj ||
1530
- value instanceof SetObj ||
1531
- value instanceof URLSearchParamsObj ||
1532
- value instanceof HeadersObj ||
1533
- value instanceof Bytes) {
1534
- const cursor = yield* self.iterate(value, node);
1535
- if (!cursor)
1536
- throw typeError("Built-in iterator is unavailable.", node);
1533
+ const cursor = self.builtinCursor(value);
1534
+ if (cursor !== undefined) {
1537
1535
  while (true) {
1538
1536
  const step = yield* cursor.next;
1539
1537
  if (step.done)
@@ -1610,13 +1608,13 @@ class Frame {
1610
1608
  const keyNode = property.key;
1611
1609
  let key;
1612
1610
  if (property.computed) {
1613
- key = self.toPropertyKey(yield* self.evaluateExpression(keyNode), keyNode);
1611
+ key = self.toPropertyKey(yield* self.evaluateExpression(keyNode));
1614
1612
  }
1615
1613
  else if (keyNode.type === "Identifier") {
1616
1614
  key = keyNode.name;
1617
1615
  }
1618
1616
  else if (keyNode.type === "Literal") {
1619
- key = self.toPropertyKey(keyNode.value, keyNode);
1617
+ key = self.toPropertyKey(literal(keyNode));
1620
1618
  }
1621
1619
  else {
1622
1620
  throw typeError("Unsupported object property key shape.", keyNode);
@@ -1707,10 +1705,10 @@ class Frame {
1707
1705
  if ((objectValue === null || objectValue === undefined) && node.optional)
1708
1706
  return OptionalShortCircuit;
1709
1707
  const key = node.computed
1710
- ? self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode)
1708
+ ? self.toPropertyKey(yield* self.evaluateExpression(propertyNode))
1711
1709
  : propertyNode.type === "Identifier"
1712
1710
  ? propertyNode.name
1713
- : self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode);
1711
+ : self.toPropertyKey(yield* self.evaluateExpression(propertyNode));
1714
1712
  if (objectValue instanceof ToolReference) {
1715
1713
  if (typeof key !== "string") {
1716
1714
  throw typeError("Tool paths must use string property names.", propertyNode);
@@ -1768,9 +1766,11 @@ class Frame {
1768
1766
  }
1769
1767
  evaluateDeleteExpression(argument) {
1770
1768
  const target = argument.type === "ChainExpression" ? argument.expression : argument;
1771
- if (target.type !== "MemberExpression") {
1769
+ if (target.type === "Identifier")
1772
1770
  throw typeError("Only data fields may be deleted.", argument);
1773
- }
1771
+ // `delete <non-reference>` evaluates the operand and is true, as in JS.
1772
+ if (target.type !== "MemberExpression")
1773
+ return Effect.map(this.evaluateExpression(target), () => true);
1774
1774
  return Effect.map(this.getMemberReference(target), (reference) => {
1775
1775
  if (reference === OptionalShortCircuit)
1776
1776
  return true;
@@ -1816,12 +1816,10 @@ class Frame {
1816
1816
  throw rangeError("Invalid array length", node);
1817
1817
  throw typeError(`Cannot assign to read only property '${String(key)}'.`, node);
1818
1818
  }
1819
- toPropertyKey(value, node) {
1820
- if (typeof value === "string" || typeof value === "number") {
1821
- return value;
1822
- }
1823
- if (value === AsyncIteratorSymbol || value === IteratorSymbol)
1819
+ // ToPropertyKey: anything else becomes its string form, so `counts[row.category]` works when the field is null.
1820
+ toPropertyKey(value) {
1821
+ if (typeof value === "string" || typeof value === "number" || typeof value === "symbol")
1824
1822
  return value;
1825
- throw typeError("Property key must be a string or number, or Symbol.asyncIterator/Symbol.iterator.", node);
1823
+ return coerceToString(value);
1826
1824
  }
1827
1825
  }
@@ -1,8 +1,8 @@
1
- import { ErrorObj, Obj } from "./objects.js";
1
+ import { ErrorObj, Obj, type Value } from "./objects.js";
2
2
  export declare const errorTypes: readonly ["Error", "TypeError", "RangeError", "SyntaxError", "ReferenceError", "EvalError", "URIError", "AggregateError"];
3
3
  export type ErrorType = (typeof errorTypes)[number];
4
4
  export declare const isErrorType: (name: string) => name is ErrorType;
5
- declare const builtins: readonly ["Object", "Function", "Array", "String", "Number", "Boolean", "Date", "RegExp", "Map", "Set", "URL", "URLSearchParams", "Headers", "Uint8Array", "TextEncoder", "TextDecoder", "Promise", "Iterator", "AsyncIterator", "Generator", "AsyncGenerator"];
5
+ declare const builtins: readonly ["Object", "Function", "Array", "String", "Number", "Boolean", "Date", "RegExp", "Map", "Set", "URL", "URLSearchParams", "Headers", "Uint8Array", "TextEncoder", "TextDecoder", "Promise", "Iterator", "IteratorHelper", "AsyncIterator", "Generator", "AsyncGenerator"];
6
6
  /**
7
7
  * The built-in prototype objects of one runtime, allocated empty in dependency order. The globals populate them
8
8
  * and attach their constructors when the runtime is built.
@@ -10,6 +10,6 @@ declare const builtins: readonly ["Object", "Function", "Array", "String", "Numb
10
10
  export type Builtins = Readonly<Record<(typeof builtins)[number] | ErrorType, Obj>>;
11
11
  export declare const createErrorValue: (prototype: Obj, message: string | undefined) => ErrorObj;
12
12
  /** The prototype a primitive reads its methods from without being boxed; none for null, undefined, and symbols. */
13
- export declare const primitivePrototype: (builtins: Builtins, value: unknown) => Obj | undefined;
13
+ export declare const primitivePrototype: (builtins: Builtins, value: Value) => Obj | undefined;
14
14
  export declare const createBuiltins: () => Builtins;
15
15
  export {};
@@ -30,6 +30,7 @@ const builtins = [
30
30
  "TextDecoder",
31
31
  "Promise",
32
32
  "Iterator",
33
+ "IteratorHelper",
33
34
  "AsyncIterator",
34
35
  "Generator",
35
36
  "AsyncGenerator",
@@ -85,6 +86,7 @@ export const createBuiltins = () => {
85
86
  TextDecoder: plain(),
86
87
  Promise: plain(),
87
88
  Iterator: iterator,
89
+ IteratorHelper: new Obj(iterator),
88
90
  AsyncIterator: asyncIterator,
89
91
  Generator: new Obj(iterator),
90
92
  AsyncGenerator: new Obj(asyncIterator),
@@ -2,7 +2,7 @@ import type { Node } from "acorn";
2
2
  import { Context } from "effect";
3
3
  import type { ErrorType } from "./intrinsics.js";
4
4
  import type { DiagnosticKind } from "../codemode.js";
5
- import type { ErrorObj } from "./objects.js";
5
+ import type { ErrorObj, Value } from "./objects.js";
6
6
  /** Any parsed node; the interpreter narrows on `type` and reads `loc` for diagnostics. */
7
7
  export type AstNode = Node;
8
8
  /** The program call a built-in is running under: where to locate failures born inside it, and how deep the stack is there. */
@@ -12,14 +12,14 @@ export declare const CallSite: Context.Reference<{
12
12
  }>;
13
13
  export type Binding = {
14
14
  mutable: boolean;
15
- value: unknown;
15
+ value: Value;
16
16
  initialized?: boolean;
17
17
  };
18
18
  export type StatementResult = {
19
19
  kind: "none";
20
20
  } | {
21
21
  kind: "return";
22
- value: unknown;
22
+ value: Value;
23
23
  } | {
24
24
  kind: "break";
25
25
  label?: string;
@@ -32,12 +32,12 @@ export declare const AsyncIteratorSymbol: unique symbol;
32
32
  export declare const IteratorSymbol: unique symbol;
33
33
  export declare const IteratorSymbols: readonly [typeof AsyncIteratorSymbol, typeof IteratorSymbol];
34
34
  export declare class Throw {
35
- readonly value: unknown;
36
- constructor(value: unknown);
35
+ readonly value: Value;
36
+ constructor(value: Value);
37
37
  }
38
38
  export declare class GeneratorReturn {
39
- readonly value: unknown;
40
- constructor(value: unknown);
39
+ readonly value: Value;
40
+ constructor(value: Value);
41
41
  }
42
42
  export declare const OptionalShortCircuit: unique symbol;
43
43
  /**
@@ -64,7 +64,6 @@ export declare const syntaxError: (message: string, node?: AstNode) => PendingTh
64
64
  export declare const uriError: (message: string, node?: AstNode) => PendingThrow;
65
65
  export declare const supportedSyntaxMessage = "This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols. Use plain functions and data objects instead.";
66
66
  export declare const unsupportedSyntax: (kind: string, node: AstNode) => PendingThrow;
67
- export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
68
67
  export declare const sourceLocation: (node: AstNode) => {
69
68
  readonly line: number;
70
69
  readonly column: number;
@@ -51,7 +51,6 @@ export const uriError = failure("URIError");
51
51
  // Orient the agent rather than enumerate JavaScript; interpreter-support.md is the full matrix.
52
52
  export const supportedSyntaxMessage = "This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols. Use plain functions and data objects instead.";
53
53
  export const unsupportedSyntax = (kind, node) => new PendingThrow("SyntaxError", `Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
54
- export const isRecord = (value) => typeof value === "object" && value !== null;
55
54
  // Acorn lines are 1-based and its columns are 0-based. Diagnostics use 1-based columns of the submitted source.
56
55
  export const sourceLocation = (node) => ({
57
56
  line: node.loc?.start.line ?? 1,
@@ -1,13 +1,13 @@
1
1
  import { Effect } from "effect";
2
2
  import type { Builtins } from "./intrinsics.js";
3
- import { type Callable, Native, type NativeOptions, Obj } from "./objects.js";
4
- /** A native function body: a plain value, a thrown `PendingThrow`, or an Effect. */
5
- export type Impl = (thisValue: unknown, args: Array<unknown>) => unknown;
3
+ import { type Callable, Native, type NativeOptions, Obj, type Value } from "./objects.js";
4
+ /** A native function body: a value, a thrown `PendingThrow`, or an Effect of a value. */
5
+ export type Impl = (thisValue: Value, args: Array<Value>) => Value | Effect.Effect<Value, unknown, unknown>;
6
6
  export declare const native: <R>(builtins: Builtins, options: NativeOptions<R>) => Native<R>;
7
7
  export declare const fn: <R>(builtins: Builtins, name: string, length: number, impl: Impl) => Native<R>;
8
8
  export type Method = readonly [name: string, length: number, impl: Impl];
9
9
  export declare const methods: (builtins: Builtins, target: Obj, table: ReadonlyArray<Method>) => void;
10
- export declare const constants: (target: Obj, table: Record<string, unknown>) => void;
10
+ export declare const constants: (target: Obj, table: Record<string, Value>) => void;
11
11
  /** A constructor wired to its prototype: `C.prototype === proto` and `proto.constructor === C`. */
12
12
  export declare const constructor: <R>(builtins: Builtins, proto: Obj, options: NativeOptions<R>) => Native<R>;
13
13
  /** The `call` of a constructor that JS requires to be invoked with `new`. */
@@ -15,4 +15,4 @@ export declare const requiresNew: (name: string) => () => Effect.Effect<never, u
15
15
  /** The instance prototype for `new` via `newTarget.prototype`, falling back to the built-in's own. */
16
16
  export declare const prototypeFrom: (newTarget: Callable, fallback: Obj) => Obj;
17
17
  /** Narrows a method receiver to the built-in it belongs to, or throws the TypeError JS would. */
18
- export declare const receiver: <T extends Obj>(cls: abstract new (...args: never) => T, thisValue: unknown, method: string) => T;
18
+ export declare const receiver: <T extends Obj>(cls: abstract new (...args: never) => T, thisValue: Value, method: string) => T;