@opencode/codemode 2.0.5 → 2.0.7
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.
|
@@ -5,7 +5,7 @@ import { formatLocation, PendingThrow, Throw, sourceLocation, typeError } from "
|
|
|
5
5
|
import { containsRuntimeReference } from "./references.js";
|
|
6
6
|
import { createErrorValue, isErrorType } from "./intrinsics.js";
|
|
7
7
|
import { constructor, methods, prototypeFrom, receiver } from "./native.js";
|
|
8
|
-
import { define, get, hidden, Arr, ErrorObj, Obj } from "./objects.js";
|
|
8
|
+
import { define, get, has, hidden, Arr, ErrorObj, Obj } from "./objects.js";
|
|
9
9
|
import { formatValue } from "../stdlib/console.js";
|
|
10
10
|
import { coerceToString } from "../stdlib/value.js";
|
|
11
11
|
export const normalizeError = (error) => {
|
|
@@ -128,9 +128,17 @@ export const errorGlobal = (type, ctx) => {
|
|
|
128
128
|
const prototype = builtins[type];
|
|
129
129
|
const construct = (args, newTarget) => {
|
|
130
130
|
const proto = prototypeFrom(newTarget, prototype);
|
|
131
|
-
|
|
131
|
+
const created = type === "AggregateError"
|
|
132
132
|
? constructAggregateErrorValue(ctx, args, proto)
|
|
133
133
|
: Effect.sync(() => createErrorValue(proto, args[0] === undefined ? undefined : coerceToString(args[0])));
|
|
134
|
+
// ES2022 `new Error(message, { cause })`: installed only when the options object has the property at all.
|
|
135
|
+
const options = args[type === "AggregateError" ? 2 : 1];
|
|
136
|
+
if (!(options instanceof Obj) || !has(options, "cause"))
|
|
137
|
+
return created;
|
|
138
|
+
return Effect.map(created, (value) => {
|
|
139
|
+
define(value, "cause", get(options, "cause"), hidden);
|
|
140
|
+
return value;
|
|
141
|
+
});
|
|
134
142
|
};
|
|
135
143
|
const ctor = constructor(builtins, prototype, {
|
|
136
144
|
name: type,
|
|
@@ -3,9 +3,9 @@ import { coerceToString } from "../stdlib/value.js";
|
|
|
3
3
|
import { hooked } from "../tool-runtime.js";
|
|
4
4
|
import { createErrorValue, isErrorType } from "./intrinsics.js";
|
|
5
5
|
import { MAX_VALUE_DEPTH } from "./limits.js";
|
|
6
|
-
import { Throw, typeError } from "./model.js";
|
|
6
|
+
import { PendingThrow, Throw, typeError } from "./model.js";
|
|
7
7
|
import { fn } from "./native.js";
|
|
8
|
-
import { Callable, define, entries, get, Arr, Bytes, DateObj, ErrorObj, GeneratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "./objects.js";
|
|
8
|
+
import { Callable, define, entries, get, has, hidden, keys, Arr, Bytes, DateObj, ErrorObj, GeneratorObj, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "./objects.js";
|
|
9
9
|
import { describeValue } from "./references.js";
|
|
10
10
|
/**
|
|
11
11
|
* The global bindings of one run's extensions. Everything crossing the boundary is converted: plain data and
|
|
@@ -43,15 +43,30 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
43
43
|
value instanceof PromiseObj) {
|
|
44
44
|
throw typeError(`${label} contains ${describeValue(value)}, which cannot be passed to an extension.`);
|
|
45
45
|
}
|
|
46
|
+
if (seen.has(value))
|
|
47
|
+
throw typeError(`${label} contains a circular value.`);
|
|
48
|
+
seen.add(value);
|
|
46
49
|
if (value instanceof ErrorObj) {
|
|
47
50
|
const name = coerceToString(get(value, "name"));
|
|
48
51
|
const message = get(value, "message");
|
|
49
52
|
const text = message === undefined ? "" : coerceToString(message);
|
|
50
|
-
|
|
53
|
+
const copied = name === "AggregateError" ? new AggregateError([], text) : new (hostErrors.get(name) ?? Error)(text);
|
|
54
|
+
for (const key of new Set(["cause", ...keys(value)])) {
|
|
55
|
+
if (uncrossed.has(key) || !has(value, key))
|
|
56
|
+
continue;
|
|
57
|
+
const item = crossing(() => next(get(value, key)));
|
|
58
|
+
if (item === left)
|
|
59
|
+
continue;
|
|
60
|
+
Object.defineProperty(copied, key, {
|
|
61
|
+
value: item,
|
|
62
|
+
writable: true,
|
|
63
|
+
configurable: true,
|
|
64
|
+
enumerable: key !== "cause",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
seen.delete(value);
|
|
68
|
+
return copied;
|
|
51
69
|
}
|
|
52
|
-
if (seen.has(value))
|
|
53
|
-
throw typeError(`${label} contains a circular value.`);
|
|
54
|
-
seen.add(value);
|
|
55
70
|
const copied = value instanceof Arr
|
|
56
71
|
? value.items.map(next)
|
|
57
72
|
: Object.fromEntries(entries(value)
|
|
@@ -68,6 +83,7 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
68
83
|
if (typeof value === "function")
|
|
69
84
|
return wrap(value, label);
|
|
70
85
|
if (value !== null && typeof value === "object") {
|
|
86
|
+
const next = (item, path) => fromHost(item, path, depth + 1, seen);
|
|
71
87
|
if (value instanceof Date)
|
|
72
88
|
return new DateObj(builtins.Date, value.getTime());
|
|
73
89
|
if (value instanceof RegExp)
|
|
@@ -77,14 +93,27 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
77
93
|
if (value instanceof ArrayBuffer)
|
|
78
94
|
return new Bytes(builtins.Uint8Array, new Uint8Array(value.slice(0)));
|
|
79
95
|
if (value instanceof Error) {
|
|
80
|
-
|
|
96
|
+
if (seen.has(value))
|
|
97
|
+
throw typeError(`${label} produced a circular value.`);
|
|
98
|
+
seen.add(value);
|
|
99
|
+
const copied = createErrorValue(builtins[isErrorType(value.name) ? value.name : "Error"], value.message);
|
|
100
|
+
const fields = value;
|
|
101
|
+
for (const key of new Set(["cause", ...Object.keys(value)])) {
|
|
102
|
+
if (uncrossed.has(key) || !(key in value) || typeof fields[key] === "function")
|
|
103
|
+
continue;
|
|
104
|
+
const item = crossing(() => next(fields[key], `${label}.${key}`));
|
|
105
|
+
if (item === left)
|
|
106
|
+
continue;
|
|
107
|
+
define(copied, key, item, key === "cause" ? hidden : undefined);
|
|
108
|
+
}
|
|
109
|
+
seen.delete(value);
|
|
110
|
+
return copied;
|
|
81
111
|
}
|
|
82
112
|
if (value instanceof URL)
|
|
83
113
|
return new URLObj(builtins.URL, builtins.URLSearchParams, new URL(value.href));
|
|
84
114
|
if (value instanceof URLSearchParams) {
|
|
85
115
|
return new URLSearchParamsObj(builtins.URLSearchParams, new URLSearchParams(value));
|
|
86
116
|
}
|
|
87
|
-
const next = (item, path) => fromHost(item, path, depth + 1, seen);
|
|
88
117
|
if (value instanceof Map) {
|
|
89
118
|
const wrapped = new MapObj(builtins.Map);
|
|
90
119
|
for (const [key, item] of value)
|
|
@@ -138,6 +167,23 @@ export const extensionGlobals = (ctx, extensions) => {
|
|
|
138
167
|
});
|
|
139
168
|
return extensions.flatMap((extension) => Object.entries(extension.globals).map(([name, value]) => [name, wrap(value, name, (args) => ({ extension: extension.name, name, args }))]));
|
|
140
169
|
};
|
|
170
|
+
/**
|
|
171
|
+
* An error crosses as its name, message, `cause`, and own enumerable fields, such as Node's `code`, `errno`,
|
|
172
|
+
* `syscall`, and `path`. `stack` stays on its own side, and no field may shadow an Error method. A field that cannot
|
|
173
|
+
* cross (a socket, a handle, a function) is left behind so the error itself always arrives.
|
|
174
|
+
*/
|
|
175
|
+
const uncrossed = new Set(["stack", "constructor", "toString", "__proto__"]);
|
|
176
|
+
const left = Symbol("left behind");
|
|
177
|
+
const crossing = (convert) => {
|
|
178
|
+
try {
|
|
179
|
+
return convert();
|
|
180
|
+
}
|
|
181
|
+
catch (reason) {
|
|
182
|
+
if (reason instanceof PendingThrow)
|
|
183
|
+
return left;
|
|
184
|
+
throw reason;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
141
187
|
const hostErrors = new Map([
|
|
142
188
|
["TypeError", TypeError],
|
|
143
189
|
["RangeError", RangeError],
|
package/package.json
CHANGED