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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +0 -6
  2. package/dist/codemode.d.ts +12 -9
  3. package/dist/codemode.js +9 -5
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.js +0 -1
  6. package/dist/interpreter/errors.d.ts +6 -4
  7. package/dist/interpreter/errors.js +10 -25
  8. package/dist/interpreter/execute.d.ts +3 -4
  9. package/dist/interpreter/execute.js +18 -11
  10. package/dist/interpreter/iterator.d.ts +13 -0
  11. package/dist/interpreter/iterator.js +4 -0
  12. package/dist/interpreter/methods.d.ts +16 -3
  13. package/dist/interpreter/methods.js +290 -101
  14. package/dist/interpreter/model.d.ts +79 -10
  15. package/dist/interpreter/model.js +102 -2
  16. package/dist/interpreter/promises.d.ts +13 -15
  17. package/dist/interpreter/promises.js +52 -70
  18. package/dist/interpreter/references.d.ts +0 -1
  19. package/dist/interpreter/references.js +77 -57
  20. package/dist/interpreter/runtime.d.ts +95 -16
  21. package/dist/interpreter/runtime.js +960 -549
  22. package/dist/openapi/spec.js +6 -3
  23. package/dist/stdlib/collections.d.ts +1 -6
  24. package/dist/stdlib/collections.js +1 -117
  25. package/dist/stdlib/console.d.ts +2 -3
  26. package/dist/stdlib/console.js +28 -39
  27. package/dist/stdlib/date.d.ts +4 -5
  28. package/dist/stdlib/date.js +12 -34
  29. package/dist/stdlib/json.d.ts +6 -3
  30. package/dist/stdlib/json.js +63 -40
  31. package/dist/stdlib/math.d.ts +7 -3
  32. package/dist/stdlib/math.js +153 -85
  33. package/dist/stdlib/number.d.ts +4 -2
  34. package/dist/stdlib/number.js +37 -30
  35. package/dist/stdlib/object.d.ts +6 -6
  36. package/dist/stdlib/object.js +87 -84
  37. package/dist/stdlib/promise.d.ts +2 -0
  38. package/dist/stdlib/promise.js +1 -0
  39. package/dist/stdlib/regexp.d.ts +7 -6
  40. package/dist/stdlib/regexp.js +34 -48
  41. package/dist/stdlib/string.d.ts +3 -1
  42. package/dist/stdlib/string.js +17 -20
  43. package/dist/stdlib/url.d.ts +6 -10
  44. package/dist/stdlib/url.js +25 -102
  45. package/dist/stdlib/value.d.ts +7 -8
  46. package/dist/stdlib/value.js +56 -56
  47. package/dist/tool-runtime.d.ts +15 -16
  48. package/dist/tool-runtime.js +150 -13
  49. package/dist/values.d.ts +16 -22
  50. package/dist/values.js +17 -23
  51. package/package.json +1 -1
  52. package/dist/data.d.ts +0 -25
  53. package/dist/data.js +0 -153
  54. package/dist/interpreter/globals.d.ts +0 -13
  55. package/dist/interpreter/globals.js +0 -63
  56. package/dist/interpreter/host.d.ts +0 -41
  57. package/dist/interpreter/host.js +0 -44
  58. package/dist/interpreter/objects.d.ts +0 -37
  59. package/dist/interpreter/objects.js +0 -151
  60. package/dist/interpreter/runner.d.ts +0 -24
  61. package/dist/interpreter/runner.js +0 -45
  62. package/dist/stdlib/array.d.ts +0 -3
  63. package/dist/stdlib/array.js +0 -68
  64. package/dist/stdlib/web.d.ts +0 -4
  65. package/dist/stdlib/web.js +0 -20
@@ -1,10 +1,23 @@
1
- import type { Node } from "acorn";
2
1
  import type { Effect } from "effect";
3
- import type { DiagnosticKind } from "../codemode.js";
4
- import type { ProgramObject } from "./objects.js";
5
- import type { Values } from "../values.js";
6
- /** Any parsed node; the interpreter narrows on `type` and reads `loc` for diagnostics. */
7
- export type AstNode = Node;
2
+ import type { SafeObject } from "../tool-runtime.js";
3
+ import type { CodeModePromise, CodeModeRegExp, CodeModeURL } from "../values.js";
4
+ export type SourcePosition = {
5
+ line: number;
6
+ column: number;
7
+ };
8
+ export type SourceLocation = {
9
+ start: SourcePosition;
10
+ end: SourcePosition;
11
+ };
12
+ export type AstNode = {
13
+ type: string;
14
+ loc?: SourceLocation;
15
+ [key: string]: unknown;
16
+ };
17
+ export type ProgramNode = AstNode & {
18
+ type: "Program";
19
+ body: Array<AstNode>;
20
+ };
8
21
  export type Binding = {
9
22
  mutable: boolean;
10
23
  value: unknown;
@@ -23,9 +36,17 @@ export type StatementResult = {
23
36
  label?: string;
24
37
  };
25
38
  export type MemberReference = {
26
- target: ProgramObject | Values.RegExp | Values.URL;
39
+ target: SafeObject | Array<unknown> | CodeModeRegExp | CodeModeURL;
27
40
  key: PropertyKey;
28
41
  };
42
+ export declare class CodeModeFunction {
43
+ readonly parameters: ReadonlyArray<AstNode>;
44
+ readonly body: AstNode;
45
+ readonly capturedScopes: ReadonlyArray<Map<string, Binding>>;
46
+ readonly async: boolean;
47
+ readonly generator: boolean;
48
+ constructor(parameters: ReadonlyArray<AstNode>, body: AstNode, capturedScopes: ReadonlyArray<Map<string, Binding>>, async: boolean, generator: boolean);
49
+ }
29
50
  export type GeneratorRequestKind = "next" | "return" | "throw";
30
51
  export declare class CodeModeGenerator {
31
52
  readonly asynchronous: boolean;
@@ -46,14 +67,51 @@ export declare class ComputedValue {
46
67
  readonly value: unknown;
47
68
  constructor(value: unknown);
48
69
  }
70
+ export declare class PromiseNamespace {
71
+ }
72
+ export declare class SymbolNamespace {
73
+ }
49
74
  export declare const AsyncIteratorSymbol: unique symbol;
50
75
  export declare const IteratorSymbol: unique symbol;
51
76
  export declare const IteratorSymbols: readonly [typeof AsyncIteratorSymbol, typeof IteratorSymbol];
77
+ export type PromiseMethodName = "all" | "allSettled" | "race" | "any" | "resolve" | "reject";
78
+ export declare class PromiseMethodReference {
79
+ readonly name: PromiseMethodName;
80
+ constructor(name: PromiseMethodName);
81
+ }
52
82
  export type PromiseInstanceMethodName = "then" | "catch" | "finally";
53
83
  export declare class PromiseInstanceMethodReference {
54
- readonly promise: Values.Promise;
84
+ readonly promise: CodeModePromise;
55
85
  readonly name: PromiseInstanceMethodName;
56
- constructor(promise: Values.Promise, name: PromiseInstanceMethodName);
86
+ constructor(promise: CodeModePromise, name: PromiseInstanceMethodName);
87
+ }
88
+ export declare class PromiseCapabilityFunction {
89
+ readonly settle: (value: unknown) => void;
90
+ constructor(settle: (value: unknown) => void);
91
+ }
92
+ export type GlobalNamespaceName = "Object" | "Math" | "JSON" | "Array" | "console" | "Date" | "RegExp" | "Map" | "Set" | "URL" | "URLSearchParams";
93
+ export declare class GlobalNamespace {
94
+ readonly name: GlobalNamespaceName;
95
+ constructor(name: GlobalNamespaceName);
96
+ }
97
+ export declare class GlobalMethodReference {
98
+ readonly namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String";
99
+ readonly name: string;
100
+ constructor(namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String", name: string);
101
+ }
102
+ export declare class JsonMethodReference {
103
+ readonly name: "parse" | "stringify";
104
+ constructor(name: "parse" | "stringify");
105
+ }
106
+ export declare class CoercionFunction {
107
+ readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
108
+ constructor(name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN");
109
+ }
110
+ export declare class UriFunction {
111
+ readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
112
+ constructor(name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent");
113
+ }
114
+ export declare class SearchFunction {
57
115
  }
58
116
  export declare class ProgramThrow {
59
117
  readonly value: unknown;
@@ -63,7 +121,13 @@ export declare class GeneratorReturn {
63
121
  readonly value: unknown;
64
122
  constructor(value: unknown);
65
123
  }
124
+ export declare class ErrorConstructorReference {
125
+ readonly name: string;
126
+ constructor(name: string);
127
+ }
128
+ export type DiagnosticKind = "ParseError" | "UnsupportedSyntax" | "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded" | "TimeoutExceeded" | "ToolFailure" | "ExecutionFailure";
66
129
  export declare const OptionalShortCircuit: unique symbol;
130
+ export declare const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
67
131
  export declare class InterpreterRuntimeError extends Error {
68
132
  readonly kind: DiagnosticKind;
69
133
  readonly suggestions?: ReadonlyArray<string> | undefined;
@@ -72,9 +136,14 @@ export declare class InterpreterRuntimeError extends Error {
72
136
  constructor(message: string, node?: AstNode, kind?: DiagnosticKind, suggestions?: ReadonlyArray<string> | undefined);
73
137
  as(errorName: string): this;
74
138
  }
75
- 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.";
76
139
  export declare const unsupportedSyntax: (kind: string, node: AstNode) => InterpreterRuntimeError;
77
140
  export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
141
+ export declare const asNode: (value: unknown, context: string) => AstNode;
142
+ export declare const getArray: (node: AstNode, key: string) => Array<unknown>;
143
+ export declare const getString: (node: AstNode, key: string) => string;
144
+ export declare const getBoolean: (node: AstNode, key: string) => boolean;
145
+ export declare const getOptionalNode: (node: AstNode, key: string) => AstNode | undefined;
146
+ export declare const getNode: (node: AstNode, key: string) => AstNode;
78
147
  export declare const sourceLocation: (node: AstNode) => {
79
148
  readonly line: number;
80
149
  readonly column: number;
@@ -1,3 +1,17 @@
1
+ export class CodeModeFunction {
2
+ parameters;
3
+ body;
4
+ capturedScopes;
5
+ async;
6
+ generator;
7
+ constructor(parameters, body, capturedScopes, async, generator) {
8
+ this.parameters = parameters;
9
+ this.body = body;
10
+ this.capturedScopes = capturedScopes;
11
+ this.async = async;
12
+ this.generator = generator;
13
+ }
14
+ }
1
15
  export class CodeModeGenerator {
2
16
  asynchronous;
3
17
  request;
@@ -28,9 +42,19 @@ export class ComputedValue {
28
42
  this.value = value;
29
43
  }
30
44
  }
45
+ export class PromiseNamespace {
46
+ }
47
+ export class SymbolNamespace {
48
+ }
31
49
  export const AsyncIteratorSymbol = Symbol("codemode.async-iterator");
32
50
  export const IteratorSymbol = Symbol("codemode.iterator");
33
51
  export const IteratorSymbols = [AsyncIteratorSymbol, IteratorSymbol];
52
+ export class PromiseMethodReference {
53
+ name;
54
+ constructor(name) {
55
+ this.name = name;
56
+ }
57
+ }
34
58
  export class PromiseInstanceMethodReference {
35
59
  promise;
36
60
  name;
@@ -39,6 +63,46 @@ export class PromiseInstanceMethodReference {
39
63
  this.name = name;
40
64
  }
41
65
  }
66
+ export class PromiseCapabilityFunction {
67
+ settle;
68
+ constructor(settle) {
69
+ this.settle = settle;
70
+ }
71
+ }
72
+ export class GlobalNamespace {
73
+ name;
74
+ constructor(name) {
75
+ this.name = name;
76
+ }
77
+ }
78
+ export class GlobalMethodReference {
79
+ namespace;
80
+ name;
81
+ constructor(namespace, name) {
82
+ this.namespace = namespace;
83
+ this.name = name;
84
+ }
85
+ }
86
+ export class JsonMethodReference {
87
+ name;
88
+ constructor(name) {
89
+ this.name = name;
90
+ }
91
+ }
92
+ export class CoercionFunction {
93
+ name;
94
+ constructor(name) {
95
+ this.name = name;
96
+ }
97
+ }
98
+ export class UriFunction {
99
+ name;
100
+ constructor(name) {
101
+ this.name = name;
102
+ }
103
+ }
104
+ export class SearchFunction {
105
+ }
42
106
  export class ProgramThrow {
43
107
  value;
44
108
  constructor(value) {
@@ -51,7 +115,14 @@ export class GeneratorReturn {
51
115
  this.value = value;
52
116
  }
53
117
  }
118
+ export class ErrorConstructorReference {
119
+ name;
120
+ constructor(name) {
121
+ this.name = name;
122
+ }
123
+ }
54
124
  export const OptionalShortCircuit = Symbol("codemode.optional-short-circuit");
125
+ export const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
55
126
  export class InterpreterRuntimeError extends Error {
56
127
  kind;
57
128
  suggestions;
@@ -70,10 +141,39 @@ export class InterpreterRuntimeError extends Error {
70
141
  return this;
71
142
  }
72
143
  }
73
- // Orient the agent rather than enumerate JavaScript; interpreter-support.md is the full matrix.
74
- 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.";
75
144
  export const unsupportedSyntax = (kind, node) => new InterpreterRuntimeError(`Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
76
145
  export const isRecord = (value) => typeof value === "object" && value !== null;
146
+ export const asNode = (value, context) => {
147
+ if (!isRecord(value) || typeof value.type !== "string") {
148
+ throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`);
149
+ }
150
+ return value;
151
+ };
152
+ export const getArray = (node, key) => {
153
+ const value = node[key];
154
+ if (!Array.isArray(value))
155
+ throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node);
156
+ return value;
157
+ };
158
+ export const getString = (node, key) => {
159
+ const value = node[key];
160
+ if (typeof value !== "string")
161
+ throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node);
162
+ return value;
163
+ };
164
+ export const getBoolean = (node, key) => {
165
+ const value = node[key];
166
+ if (typeof value !== "boolean")
167
+ throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node);
168
+ return value;
169
+ };
170
+ export const getOptionalNode = (node, key) => {
171
+ const value = node[key];
172
+ if (value === undefined || value === null)
173
+ return undefined;
174
+ return asNode(value, key);
175
+ };
176
+ export const getNode = (node, key) => asNode(node[key], key);
77
177
  export const sourceLocation = (node) => ({
78
178
  line: Math.max(1, (node.loc?.start.line ?? 2) - 1),
79
179
  column: Math.max(1, (node.loc?.start.column ?? 4) - 3),
@@ -1,9 +1,9 @@
1
1
  import { Effect, Exit, Scope } from "effect";
2
2
  import type { Diagnostic } from "../codemode.js";
3
- import { type AstNode, InterpreterRuntimeError, PromiseInstanceMethodReference } from "./model.js";
4
- import { HostFunction } from "./host.js";
5
- import { Values } from "../values.js";
6
- import { type Runner } from "./runner.js";
3
+ import { type AstNode, InterpreterRuntimeError, PromiseInstanceMethodReference, PromiseMethodReference } from "./model.js";
4
+ import { type CallbackRunner } from "./methods.js";
5
+ import { CodeModePromise } from "../values.js";
6
+ import type { SyncIteratorRunner } from "./iterator.js";
7
7
  export declare class PromiseRuntime<R> {
8
8
  private readonly scope;
9
9
  private readonly active;
@@ -12,20 +12,18 @@ export declare class PromiseRuntime<R> {
12
12
  private readonly failures;
13
13
  private nextID;
14
14
  constructor(scope: Scope.Scope);
15
- createWithSelf(body: (self: {
16
- promise?: Values.Promise;
17
- }) => Effect.Effect<unknown, unknown, R>): Effect.Effect<Values.Promise, never, R>;
18
- create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<Values.Promise, never, R>;
19
- markObserved(promise: Values.Promise): void;
20
- await(promise: Values.Promise): Effect.Effect<Exit.Exit<unknown, unknown>>;
15
+ create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<CodeModePromise, never, R>;
16
+ markObserved(promise: CodeModePromise): void;
17
+ await(promise: CodeModePromise): Effect.Effect<Exit.Exit<unknown, unknown>>;
21
18
  fork(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<void, never, R>;
22
19
  diagnostics(): Array<Diagnostic>;
23
20
  interrupt(): Effect.Effect<Array<Diagnostic>>;
24
21
  }
25
22
  export declare const selfResolutionError: (node?: AstNode) => InterpreterRuntimeError;
26
- export declare const resolvePromiseValue: <R>(runner: Runner<R>, value: unknown, node: AstNode, own?: {
27
- promise?: Values.Promise;
23
+ export declare const resolvePromiseValue: <R>(runner: CallbackRunner<R>, value: unknown, node: AstNode, own?: {
24
+ promise?: CodeModePromise;
28
25
  }) => Effect.Effect<unknown, unknown, R>;
29
- export declare const resolvePromise: <R>(runner: Runner<R>, promises: PromiseRuntime<R>, value: unknown, node: AstNode) => Effect.Effect<Values.Promise, never, R>;
30
- export declare const invokePromiseInstanceMethod: <R>(runner: Runner<R>, promises: PromiseRuntime<R>, ref: PromiseInstanceMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<Values.Promise, never, R>;
31
- export declare const promiseGlobal: <R>(runner: Runner<R>, promises: PromiseRuntime<R>) => HostFunction<R>;
26
+ export declare const resolvePromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, value: unknown, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
27
+ export declare const invokePromiseMethod: <R>(runner: CallbackRunner<R> & SyncIteratorRunner<R>, promises: PromiseRuntime<R>, ref: PromiseMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
28
+ export declare const invokePromiseInstanceMethod: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, ref: PromiseInstanceMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
29
+ export declare const constructPromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, executor: unknown, node: AstNode) => Effect.Effect<CodeModePromise, unknown, R>;
@@ -1,17 +1,10 @@
1
1
  import { Cause, Deferred, Effect, Exit, Fiber, Scope } from "effect";
2
- import { InterpreterRuntimeError, ProgramThrow, PromiseInstanceMethodReference } from "./model.js";
3
- import { get, ProgramArray, ProgramFunction, ProgramObject, record } from "./objects.js";
4
- import { HostFunction, requiresNew, sync } from "./host.js";
2
+ import { CodeModeFunction, InterpreterRuntimeError, ProgramThrow, PromiseCapabilityFunction, PromiseInstanceMethodReference, PromiseMethodReference, } from "./model.js";
5
3
  import { caughtErrorValue, normalizeError } from "./errors.js";
4
+ import { applyCollectionCallback, isSupportedCallback } from "./methods.js";
6
5
  import { typeofValue } from "./references.js";
7
6
  import { createAggregateErrorValue } from "../stdlib/value.js";
8
- import { Values } from "../values.js";
9
- import { applyCollectionCallback, isSupportedCallback } from "./runner.js";
10
- // A `resolve`/`reject` handed to an executor or thenable: calling it settles the capability.
11
- const capability = (name, settle) => sync(name, (args) => {
12
- settle(args[0]);
13
- return undefined;
14
- });
7
+ import { CodeModePromise } from "../values.js";
15
8
  // Observation only controls rejection reporting; program completion interrupts all promise work.
16
9
  export class PromiseRuntime {
17
10
  scope;
@@ -23,20 +16,12 @@ export class PromiseRuntime {
23
16
  constructor(scope) {
24
17
  this.scope = scope;
25
18
  }
26
- // Resolution bodies need the promise's own identity to reject `resolve(promise)` self-resolution.
27
- createWithSelf(body) {
28
- const self = {};
29
- return Effect.map(this.create(body(self)), (promise) => {
30
- self.promise = promise;
31
- return promise;
32
- });
33
- }
34
19
  create(effect) {
35
20
  return Effect.suspend(() => {
36
21
  // Allocate before forking so reruns get distinct IDs and diagnostics retain creation order.
37
22
  const id = this.nextID++;
38
23
  return Effect.map(Effect.forkIn(effect, this.scope, { startImmediately: true }), (fiber) => {
39
- const promise = new Values.Promise(fiber);
24
+ const promise = new CodeModePromise(fiber);
40
25
  this.active.add(promise);
41
26
  this.ids.set(promise, id);
42
27
  fiber.addObserver((exit) => {
@@ -87,19 +72,23 @@ export const selfResolutionError = (node) => new InterpreterRuntimeError("Chaini
87
72
  export const resolvePromiseValue = (runner, value, node, own) => {
88
73
  if (own?.promise !== undefined && value === own.promise)
89
74
  return Effect.fail(selfResolutionError(node));
90
- if (value instanceof Values.Promise)
75
+ if (value instanceof CodeModePromise)
91
76
  return runner.settlePromise(value);
92
- if (!(value instanceof ProgramObject))
77
+ if (value === null || typeof value !== "object" || !Object.hasOwn(value, "then"))
93
78
  return Effect.succeed(value);
94
- const then = get(value, "then");
79
+ const then = value.then;
95
80
  if (typeofValue(then) !== "function")
96
81
  return Effect.succeed(value);
97
82
  return Effect.gen(function* () {
98
83
  // Promise resolution invokes a thenable's method in a later job.
99
84
  yield* Effect.yieldNow;
100
85
  const deferred = Deferred.makeUnsafe();
101
- const resolve = capability("resolve", (result) => Deferred.doneUnsafe(deferred, Exit.succeed(result)));
102
- const reject = capability("reject", (reason) => Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(reason))));
86
+ const resolve = new PromiseCapabilityFunction((result) => {
87
+ Deferred.doneUnsafe(deferred, Exit.succeed(result));
88
+ });
89
+ const reject = new PromiseCapabilityFunction((reason) => {
90
+ Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(reason)));
91
+ });
103
92
  const executed = yield* Effect.exit(runner.invokeCallable(then, [resolve, reject], node));
104
93
  if (!Exit.isSuccess(executed)) {
105
94
  if (Cause.hasInterruptsOnly(executed.cause))
@@ -110,22 +99,25 @@ export const resolvePromiseValue = (runner, value, node, own) => {
110
99
  });
111
100
  };
112
101
  export const resolvePromise = (runner, promises, value, node) => {
113
- if (value instanceof Values.Promise)
102
+ if (value instanceof CodeModePromise)
114
103
  return Effect.succeed(value);
115
- return promises.createWithSelf((self) => resolvePromiseValue(runner, value, node, self));
104
+ const box = {};
105
+ return Effect.map(promises.create(resolvePromiseValue(runner, value, node, box)), (promise) => {
106
+ box.promise = promise;
107
+ return promise;
108
+ });
116
109
  };
117
- const promiseStatics = ["all", "allSettled", "race", "any", "resolve", "reject"];
118
- const invokePromiseMethod = (runner, promises, name, args, node) => {
119
- if (name === "resolve") {
110
+ export const invokePromiseMethod = (runner, promises, ref, args, node) => {
111
+ if (ref.name === "resolve") {
120
112
  return resolvePromise(runner, promises, args[0], node);
121
113
  }
122
- if (name === "reject") {
114
+ if (ref.name === "reject") {
123
115
  return promises.create(Effect.fail(new ProgramThrow(args[0])));
124
116
  }
125
117
  return promises.create(Effect.gen(function* () {
126
118
  const cursor = yield* runner.syncIterator(args[0], node);
127
119
  if (cursor === undefined) {
128
- throw new InterpreterRuntimeError(`Promise.${name} expects an array or other synchronous iterable.`, node).as("TypeError");
120
+ throw new InterpreterRuntimeError(`Promise.${ref.name} expects an array or other synchronous iterable.`, node).as("TypeError");
129
121
  }
130
122
  const items = [];
131
123
  while (true) {
@@ -136,25 +128,28 @@ const invokePromiseMethod = (runner, promises, name, args, node) => {
136
128
  promises.markObserved(item);
137
129
  items.push(item);
138
130
  }
139
- if (name === "all") {
140
- return new ProgramArray(yield* settleAfterTurn(Effect.all(items.map((item) => Effect.flatten(promises.await(item))), { concurrency: "unbounded" })));
131
+ if (ref.name === "all") {
132
+ return yield* settleAfterTurn(Effect.all(items.map((item) => Effect.flatten(promises.await(item))), { concurrency: "unbounded" }));
141
133
  }
142
- if (name === "allSettled") {
134
+ if (ref.name === "allSettled") {
143
135
  const outcomes = [];
144
136
  for (const item of items) {
145
137
  const exit = yield* promises.await(item);
146
138
  if (Exit.isSuccess(exit)) {
147
- outcomes.push(record({ status: "fulfilled", value: exit.value }));
139
+ outcomes.push(Object.assign(Object.create(null), { status: "fulfilled", value: exit.value }));
148
140
  continue;
149
141
  }
150
142
  if (Cause.hasInterruptsOnly(exit.cause))
151
143
  return yield* Effect.failCause(exit.cause);
152
- outcomes.push(record({ status: "rejected", reason: caughtErrorValue(Cause.squash(exit.cause)) }));
144
+ outcomes.push(Object.assign(Object.create(null), {
145
+ status: "rejected",
146
+ reason: caughtErrorValue(Cause.squash(exit.cause)),
147
+ }));
153
148
  }
154
149
  yield* Effect.yieldNow;
155
- return new ProgramArray(outcomes);
150
+ return outcomes;
156
151
  }
157
- if (name === "race") {
152
+ if (ref.name === "race") {
158
153
  if (items.length === 0) {
159
154
  throw new InterpreterRuntimeError("Promise.race([]) would never settle; provide at least one promise or value.", node);
160
155
  }
@@ -180,15 +175,21 @@ export const invokePromiseInstanceMethod = (runner, promises, ref, args, node) =
180
175
  const onRejected = reactionHandler(ref.name === "then" ? args[1] : args[0], method, node);
181
176
  return chainReaction(runner, promises, ref.promise, onFulfilled, onRejected, method, node);
182
177
  };
183
- const constructPromise = (runner, promises, executor, node) => {
184
- if (!(executor instanceof ProgramFunction)) {
178
+ export const constructPromise = (runner, promises, executor, node) => {
179
+ if (!(executor instanceof CodeModeFunction)) {
185
180
  throw new InterpreterRuntimeError("new Promise(...) expects an executor function (e.g. new Promise((resolve, reject) => { ... })).", node).as("TypeError");
186
181
  }
187
182
  return Effect.gen(function* () {
188
183
  const deferred = Deferred.makeUnsafe();
189
- const promise = yield* promises.createWithSelf((self) => Effect.flatMap(Deferred.await(deferred), (value) => resolvePromiseValue(runner, value, node, self)));
190
- const resolve = capability("resolve", (value) => Deferred.doneUnsafe(deferred, Exit.succeed(value)));
191
- const reject = capability("reject", (value) => Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(value))));
184
+ const box = {};
185
+ const promise = yield* promises.create(Effect.flatMap(Deferred.await(deferred), (value) => resolvePromiseValue(runner, value, node, box)));
186
+ box.promise = promise;
187
+ const resolve = new PromiseCapabilityFunction((value) => {
188
+ Deferred.doneUnsafe(deferred, Exit.succeed(value));
189
+ });
190
+ const reject = new PromiseCapabilityFunction((value) => {
191
+ Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(value)));
192
+ });
192
193
  const executed = yield* Effect.exit(runner.invokeFunction(executor, [resolve, reject]));
193
194
  if (!Exit.isSuccess(executed)) {
194
195
  if (Cause.hasInterruptsOnly(executed.cause))
@@ -223,15 +224,20 @@ const reactionExit = (promises, source) => Effect.gen(function* () {
223
224
  return exit;
224
225
  });
225
226
  const chainReaction = (runner, promises, source, onFulfilled, onRejected, method, node) => {
226
- return promises.createWithSelf((self) => Effect.gen(function* () {
227
+ const box = {};
228
+ const body = Effect.gen(function* () {
227
229
  const exit = yield* reactionExit(promises, source);
228
230
  const handler = Exit.isSuccess(exit) ? onFulfilled : onRejected;
229
231
  if (handler === undefined)
230
232
  return yield* exit;
231
233
  const input = Exit.isSuccess(exit) ? exit.value : caughtErrorValue(Cause.squash(exit.cause));
232
234
  const result = yield* applyCollectionCallback(runner, handler, method, node)([input]);
233
- return yield* resolvePromiseValue(runner, result, node, self);
234
- }));
235
+ return yield* resolvePromiseValue(runner, result, node, box);
236
+ });
237
+ return Effect.map(promises.create(body), (derived) => {
238
+ box.promise = derived;
239
+ return derived;
240
+ });
235
241
  };
236
242
  const chainFinally = (runner, promises, source, cleanup, method, node) => promises.create(Effect.gen(function* () {
237
243
  const exit = yield* reactionExit(promises, source);
@@ -245,27 +251,3 @@ const chainFinally = (runner, promises, source, cleanup, method, node) => promis
245
251
  }
246
252
  return yield* exit;
247
253
  }));
248
- export const promiseGlobal = (runner, promises) => {
249
- // Combinators are not callbacks: `[p].map(Promise.resolve)` must ask for an arrow function.
250
- const statics = new Map(promiseStatics.map((name) => [
251
- name,
252
- new HostFunction({
253
- name: `Promise.${name}`,
254
- call: (args, node) => invokePromiseMethod(runner, promises, name, args, node),
255
- callback: false,
256
- }),
257
- ]));
258
- return new HostFunction({
259
- name: "Promise",
260
- call: requiresNew("Promise"),
261
- construct: (args, node) => constructPromise(runner, promises, args[0], node),
262
- instanceOf: (value) => value instanceof Values.Promise,
263
- // Unknown statics fail loudly so a missing await cannot hide behind `undefined`.
264
- members: (key, node) => {
265
- const method = typeof key === "string" ? statics.get(key) : undefined;
266
- if (method !== undefined)
267
- return method;
268
- throw new InterpreterRuntimeError(`Promise.${String(key)} is not available. Available: Promise.all, Promise.allSettled, Promise.race, Promise.any, Promise.resolve, and Promise.reject; consume promises with await.`, node);
269
- },
270
- });
271
- };
@@ -3,5 +3,4 @@ export declare const isRuntimeReference: (value: unknown) => boolean;
3
3
  export declare const containsRuntimeReference: (value: unknown) => boolean;
4
4
  export declare const containsOpaqueReference: (value: unknown) => boolean;
5
5
  export declare const rejectCircularInsertion: (container: object, value: unknown, label: string, node: AstNode, seen?: Set<object>) => void;
6
- export declare const describeValue: (value: unknown) => string;
7
6
  export declare const typeofValue: (value: unknown) => string;