@opencode/codemode 2.0.16 → 2.0.17

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.
package/dist/data.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export * as Data from "./data.js";
2
2
  import { Effect, type Schema } from "effect";
3
3
  import type { Interpreter } from "./interpreter/interpreter.js";
4
- import { type Value } from "./interpreter/objects.js";
4
+ import { Obj, type Value } from "./interpreter/objects.js";
5
5
  export type Json = Schema.Json;
6
- type Replacer<R> = (args: Array<Value>) => Effect.Effect<Value, unknown, R>;
6
+ type Replacer<R> = (args: Array<Value>, holder: Obj) => Effect.Effect<Value, unknown, R>;
7
7
  /**
8
8
  * What `JSON.stringify` would serialize for a program value, as host JSON: `toJSON` is honored, functions and
9
9
  * `undefined` vanish, non-finite numbers become null, and everything else is copied. Two departures from JS
package/dist/data.js CHANGED
@@ -28,7 +28,7 @@ const walk = (ctx, value, replacer, boundary) => {
28
28
  const settled = raw instanceof PromiseObj ? yield* ctx.await(raw) : raw;
29
29
  const toJSON = settled instanceof Obj ? get(settled, "toJSON") : undefined;
30
30
  const own = toJSON instanceof Callable ? yield* ctx.call(toJSON, settled, [key]) : settled;
31
- const value = replacer === undefined ? own : yield* replacer([key, own]);
31
+ const value = replacer === undefined ? own : yield* replacer([key, own], holder);
32
32
  if (value === undefined || typeofValue(value) === "function")
33
33
  return undefined;
34
34
  if (typeof value === "number")
@@ -4,14 +4,21 @@ import { Callable, type Cursor, type Value } from "./objects.js";
4
4
  /** IteratorClose: a consumer failure closes the iterator and wins over any close failure, except that a generator's
5
5
  * return() is a return completion, so a failing close wins over it, as after `break`. */
6
6
  export declare const preserveConsumerError: <A, R>(close: Cursor<R>["close"], effect: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>;
7
+ export type Hint = "number" | "string" | "default";
7
8
  /**
8
9
  * ToPrimitive: calls `valueOf`/`toString` in hint order and returns the first primitive result. Dates treat the
9
- * default hint as "string", like their `Symbol.toPrimitive`.
10
+ * default hint as "string", like their `Symbol.toPrimitive`. Opaque values (functions, promises, generators, tool
11
+ * references) pass through unchanged so callers reject or describe them in their built-in form.
10
12
  */
11
- export declare const toPrimitive: <R>(ctx: Interpreter<R>, value: Value, hint: "number" | "string" | "default") => Effect.Effect<Value, unknown, R>;
13
+ export declare const toPrimitive: <R>(ctx: Interpreter<R>, value: Value, hint: Hint) => Effect.Effect<Value, unknown, R>;
12
14
  /** Invoke(value, name): calls the method the value would find through its prototype. */
13
15
  export declare const invoke: <R>(ctx: Interpreter<R>, value: Value, name: string, label: string) => Effect.Effect<Value, unknown, R>;
14
16
  export declare const toPrimitiveString: <R>(ctx: Interpreter<R>, value: Value) => Effect.Effect<string, unknown, R>;
15
17
  export declare const toPrimitiveNumber: <R>(ctx: Interpreter<R>, value: Value) => Effect.Effect<number, unknown, R>;
18
+ /**
19
+ * Runs a native body on its arguments after ToPrimitive, in order, with one hint for all positions or one per
20
+ * position. Primitive arguments skip the Effect entirely.
21
+ */
22
+ export declare const withPrimitives: <R>(ctx: Interpreter<R>, hints: Hint | ReadonlyArray<Hint>, values: Array<Value>, body: (primitives: Array<Value>) => Value | Effect.Effect<Value, unknown, R>) => Value | Effect.Effect<Value, unknown, R>;
16
23
  export declare const isSupportedCallback: (value: Value) => value is Callable;
17
- export declare const applyCollectionCallback: <R>(ctx: Interpreter<R>, callback: Value, name: string) => ((args: Array<Value>) => Effect.Effect<Value, unknown, R>);
24
+ export declare const applyCollectionCallback: <R>(ctx: Interpreter<R>, callback: Value, name: string) => ((args: Array<Value>, thisValue?: Value) => Effect.Effect<Value, unknown, R>);
@@ -2,7 +2,7 @@ import { Cause, Effect, Exit } from "effect";
2
2
  import { primitivePrototype } from "./intrinsics.js";
3
3
  import { GeneratorReturn, typeError } from "./model.js";
4
4
  import { Callable, get, Native, DateObj, Obj, coerceToNumber, coerceToString, } from "./objects.js";
5
- import { typeofValue } from "./references.js";
5
+ import { isOpaque, typeofValue } from "./references.js";
6
6
  /** IteratorClose: a consumer failure closes the iterator and wins over any close failure, except that a generator's
7
7
  * return() is a return completion, so a failing close wins over it, as after `break`. */
8
8
  export const preserveConsumerError = (close, effect) => Effect.flatMap(Effect.exit(effect), (exit) => {
@@ -17,10 +17,11 @@ export const preserveConsumerError = (close, effect) => Effect.flatMap(Effect.ex
17
17
  });
18
18
  /**
19
19
  * ToPrimitive: calls `valueOf`/`toString` in hint order and returns the first primitive result. Dates treat the
20
- * default hint as "string", like their `Symbol.toPrimitive`.
20
+ * default hint as "string", like their `Symbol.toPrimitive`. Opaque values (functions, promises, generators, tool
21
+ * references) pass through unchanged so callers reject or describe them in their built-in form.
21
22
  */
22
23
  export const toPrimitive = (ctx, value, hint) => {
23
- if (!(value instanceof Obj))
24
+ if (!(value instanceof Obj) || isOpaque(value))
24
25
  return Effect.succeed(value);
25
26
  const asString = hint === "string" || (hint === "default" && value instanceof DateObj);
26
27
  const order = asString ? ["toString", "valueOf"] : ["valueOf", "toString"];
@@ -45,6 +46,18 @@ export const invoke = (ctx, value, name, label) => {
45
46
  };
46
47
  export const toPrimitiveString = (ctx, value) => Effect.map(toPrimitive(ctx, value, "string"), coerceToString);
47
48
  export const toPrimitiveNumber = (ctx, value) => Effect.map(toPrimitive(ctx, value, "number"), coerceToNumber);
49
+ /**
50
+ * Runs a native body on its arguments after ToPrimitive, in order, with one hint for all positions or one per
51
+ * position. Primitive arguments skip the Effect entirely.
52
+ */
53
+ export const withPrimitives = (ctx, hints, values, body) => {
54
+ if (!values.some((value) => value instanceof Obj))
55
+ return body(values);
56
+ return Effect.flatMap(Effect.forEach(values, (value, index) => toPrimitive(ctx, value, typeof hints === "string" ? hints : hints[index])), (primitives) => {
57
+ const result = body(primitives);
58
+ return Effect.isEffect(result) ? result : Effect.succeed(result);
59
+ });
60
+ };
48
61
  // The single acceptance list for callbacks: collections, sort, string replacers,
49
62
  // Array.from mappers, and promise reactions all admit exactly these callables.
50
63
  // Admission means dispatchable, not necessarily invocable: new-requiring
@@ -57,5 +70,5 @@ export const applyCollectionCallback = (ctx, callback, name) => {
57
70
  }
58
71
  throw typeError(`${name} expects a function callback.`);
59
72
  }
60
- return (callbackArgs) => ctx.call(callback, undefined, callbackArgs);
73
+ return (callbackArgs, thisValue) => ctx.call(callback, thisValue, callbackArgs);
61
74
  };
@@ -6,6 +6,7 @@ import { containsRuntimeReference } from "./references.js";
6
6
  import { createErrorValue, isErrorType } from "./intrinsics.js";
7
7
  import { constructor, methods, prototypeFrom, receiver } from "./native.js";
8
8
  import { define, get, has, hidden, Arr, ErrorObj, Obj, coerceToString, } from "./objects.js";
9
+ import { toPrimitiveString } from "./callback.js";
9
10
  import { formatValue } from "../stdlib/console.js";
10
11
  export const normalizeError = (error) => {
11
12
  if (error instanceof PendingThrow) {
@@ -109,15 +110,15 @@ export const createAggregateErrorValue = (ctx, errors, message, proto = ctx.buil
109
110
  return value;
110
111
  };
111
112
  const constructAggregateErrorValue = (ctx, args, proto) => Effect.gen(function* () {
113
+ const message = args[1] === undefined ? "" : yield* toPrimitiveString(ctx, args[1]);
112
114
  const cursor = yield* ctx.iterate(args[0]);
113
115
  if (cursor === undefined)
114
116
  throw typeError("new AggregateError(...) expects a synchronous iterable of errors.");
115
117
  const errors = [];
116
118
  while (true) {
117
119
  const step = yield* cursor.next;
118
- if (step.done) {
119
- return createAggregateErrorValue(ctx, errors, args[1] === undefined ? "" : coerceToString(args[1]), proto);
120
- }
120
+ if (step.done)
121
+ return createAggregateErrorValue(ctx, errors, message, proto);
121
122
  errors.push(step.value);
122
123
  }
123
124
  });
@@ -129,7 +130,7 @@ export const errorGlobal = (type, ctx) => {
129
130
  const proto = prototypeFrom(newTarget, prototype);
130
131
  const created = type === "AggregateError"
131
132
  ? constructAggregateErrorValue(ctx, args, proto)
132
- : Effect.sync(() => createErrorValue(proto, args[0] === undefined ? undefined : coerceToString(args[0])));
133
+ : Effect.map(args[0] === undefined ? Effect.undefined : toPrimitiveString(ctx, args[0]), (message) => createErrorValue(proto, message));
133
134
  // ES2022 `new Error(message, { cause })`: installed only when the options object has the property at all.
134
135
  const options = args[type === "AggregateError" ? 2 : 1];
135
136
  if (!(options instanceof Obj) || !has(options, "cause"))
@@ -150,6 +151,9 @@ export const errorGlobal = (type, ctx) => {
150
151
  ["toString", 0, (thisValue) => errorToString(receiver(Obj, thisValue, "Error.prototype.toString"))],
151
152
  ]);
152
153
  methods(builtins, ctor, [["isError", 1, (_, args) => args[0] instanceof ErrorObj]]);
154
+ return ctor;
153
155
  }
156
+ // Derived constructors extend Error itself, so its statics are inherited. The globals table creates Error first.
157
+ ctor.proto = get(builtins.Error, "constructor");
154
158
  return ctor;
155
159
  };
@@ -1,4 +1,4 @@
1
- import type { Value } from "./objects.js";
1
+ import { type Value } from "./objects.js";
2
2
  import type { Interpreter } from "./interpreter.js";
3
3
  /** Names bound in every program before extensions apply. */
4
4
  export declare const globalNames: ReadonlySet<string>;
@@ -1,7 +1,8 @@
1
1
  import { Effect } from "effect";
2
+ import { Arr, Callable, coerceToInteger, coerceToString, get, Obj } from "./objects.js";
2
3
  import { arrayGlobal } from "../stdlib/array.js";
3
4
  import { textDecoderGlobal, textEncoderGlobal, uint8ArrayGlobal } from "../stdlib/bytes.js";
4
- import { mapGlobal, setGlobal } from "../stdlib/collections.js";
5
+ import { mapGlobal, setGlobal, weakMapGlobal, weakSetGlobal } from "../stdlib/collections.js";
5
6
  import { consoleGlobal } from "../stdlib/console.js";
6
7
  import { dateGlobal } from "../stdlib/date.js";
7
8
  import { jsonGlobal } from "../stdlib/json.js";
@@ -18,8 +19,9 @@ import { base64Global, cryptoGlobal, structuredCloneGlobal } from "../stdlib/web
18
19
  import { ToolReference } from "../tool-runtime.js";
19
20
  import { errorGlobal } from "./errors.js";
20
21
  import { errorTypes } from "./intrinsics.js";
21
- import { constants, constructor, native } from "./native.js";
22
+ import { constants, constructor, methods, native, receiver } from "./native.js";
22
23
  import { AsyncIteratorSymbol, IteratorSymbol, typeError } from "./model.js";
24
+ import { checkArrayLength } from "./limits.js";
23
25
  import { generatorGlobals } from "./generators.js";
24
26
  import { promiseGlobal } from "./promises.js";
25
27
  // Function.prototype.constructor exists so `fn.constructor === Function` holds; dynamic code is unsupported.
@@ -27,6 +29,24 @@ const functionGlobal = (ctx) => {
27
29
  const reject = () => Effect.sync(() => {
28
30
  throw typeError("The Function constructor is not supported; write the function inline.");
29
31
  });
32
+ const target = (thisValue, method) => receiver(Callable, thisValue, `Function.prototype.${method}`);
33
+ methods(ctx.builtins, ctx.builtins.Function, [
34
+ ["call", 1, (thisValue, args) => ctx.call(target(thisValue, "call"), args[0], args.slice(1))],
35
+ ["apply", 2, (thisValue, args) => ctx.call(target(thisValue, "apply"), args[0], listFromArrayLike(args[1]))],
36
+ [
37
+ "bind",
38
+ 1,
39
+ (thisValue, args) => {
40
+ const fn = target(thisValue, "bind");
41
+ const bound = args.slice(1);
42
+ return native(ctx.builtins, {
43
+ name: `bound ${coerceToString(get(fn, "name"))}`,
44
+ length: Math.max(0, fn.length - bound.length),
45
+ call: (_, rest) => ctx.call(fn, args[0], [...bound, ...rest]),
46
+ });
47
+ },
48
+ ],
49
+ ]);
30
50
  return constructor(ctx.builtins, ctx.builtins.Function, {
31
51
  name: "Function",
32
52
  length: 1,
@@ -34,6 +54,18 @@ const functionGlobal = (ctx) => {
34
54
  construct: reject,
35
55
  });
36
56
  };
57
+ // CreateListFromArrayLike: `apply` reads `length` and the indexed properties of any object.
58
+ const listFromArrayLike = (value) => {
59
+ if (value === undefined || value === null)
60
+ return [];
61
+ if (value instanceof Arr)
62
+ return [...value.items];
63
+ if (!(value instanceof Obj))
64
+ throw typeError("Function.prototype.apply expects an array-like argument list.");
65
+ const length = Math.max(0, coerceToInteger(get(value, "length")));
66
+ checkArrayLength(length);
67
+ return Array.from({ length }, (_, index) => get(value, String(index)));
68
+ };
37
69
  const symbolGlobal = (ctx) => {
38
70
  const symbol = native(ctx.builtins, {
39
71
  name: "Symbol",
@@ -72,6 +104,8 @@ const table = {
72
104
  RegExp: (ctx) => regexpGlobal(ctx),
73
105
  Map: (ctx) => mapGlobal(ctx),
74
106
  Set: (ctx) => setGlobal(ctx),
107
+ WeakMap: (ctx) => weakMapGlobal(ctx),
108
+ WeakSet: (ctx) => weakSetGlobal(ctx),
75
109
  URL: (ctx) => urlGlobal(ctx),
76
110
  URLSearchParams: (ctx) => urlSearchParamsGlobal(ctx),
77
111
  Headers: (ctx) => headersGlobal(ctx),