@opencode/codemode 2.0.0 → 2.0.2
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 +6 -5
- package/dist/data.js +47 -44
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/interpreter/errors.d.ts +5 -3
- package/dist/interpreter/errors.js +51 -22
- package/dist/interpreter/execute.js +5 -3
- package/dist/interpreter/generators.d.ts +4 -0
- package/dist/interpreter/generators.js +25 -0
- package/dist/interpreter/globals.js +69 -47
- package/dist/interpreter/intrinsics.d.ts +13 -0
- package/dist/interpreter/intrinsics.js +82 -0
- package/dist/interpreter/model.d.ts +13 -36
- package/dist/interpreter/model.js +15 -45
- package/dist/interpreter/native.d.ts +19 -0
- package/dist/interpreter/native.js +40 -0
- package/dist/interpreter/objects.d.ts +106 -13
- package/dist/interpreter/objects.js +192 -65
- package/dist/interpreter/promises.d.ts +12 -13
- package/dist/interpreter/promises.js +59 -54
- package/dist/interpreter/references.d.ts +1 -0
- package/dist/interpreter/references.js +20 -33
- package/dist/interpreter/runner.d.ts +15 -11
- package/dist/interpreter/runner.js +21 -21
- package/dist/interpreter/runtime.d.ts +3 -3
- package/dist/interpreter/runtime.js +165 -327
- package/dist/interpreter/scope.js +6 -6
- package/dist/stdlib/array.d.ts +4 -2
- package/dist/stdlib/array.js +424 -32
- package/dist/stdlib/collections.d.ts +3 -7
- package/dist/stdlib/collections.js +291 -119
- package/dist/stdlib/console.d.ts +3 -2
- package/dist/stdlib/console.js +35 -30
- package/dist/stdlib/date.d.ts +1 -7
- package/dist/stdlib/date.js +93 -188
- package/dist/stdlib/json.d.ts +2 -2
- package/dist/stdlib/json.js +27 -27
- package/dist/stdlib/math.d.ts +2 -2
- package/dist/stdlib/math.js +96 -76
- package/dist/stdlib/number.d.ts +3 -4
- package/dist/stdlib/number.js +95 -60
- package/dist/stdlib/object.d.ts +4 -4
- package/dist/stdlib/object.js +128 -54
- package/dist/stdlib/regexp.d.ts +6 -8
- package/dist/stdlib/regexp.js +76 -68
- package/dist/stdlib/string.d.ts +2 -2
- package/dist/stdlib/string.js +213 -50
- package/dist/stdlib/url.d.ts +5 -13
- package/dist/stdlib/url.js +202 -102
- package/dist/stdlib/value.d.ts +5 -9
- package/dist/stdlib/value.js +16 -38
- package/dist/stdlib/web.d.ts +4 -4
- package/dist/stdlib/web.js +12 -10
- package/dist/tool-runtime.d.ts +2 -1
- package/dist/tool-runtime.js +2 -2
- package/package.json +1 -1
- package/dist/interpreter/host.d.ts +0 -41
- package/dist/interpreter/host.js +0 -44
- package/dist/interpreter/methods.d.ts +0 -4
- package/dist/interpreter/methods.js +0 -837
- package/dist/values.d.ts +0 -37
- package/dist/values.js +0 -56
package/dist/stdlib/string.js
CHANGED
|
@@ -1,51 +1,214 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"substr",
|
|
16
|
-
"includes",
|
|
17
|
-
"startsWith",
|
|
18
|
-
"endsWith",
|
|
19
|
-
"indexOf",
|
|
20
|
-
"lastIndexOf",
|
|
21
|
-
"replace",
|
|
22
|
-
"replaceAll",
|
|
23
|
-
"repeat",
|
|
24
|
-
"padStart",
|
|
25
|
-
"padEnd",
|
|
26
|
-
"charAt",
|
|
27
|
-
"charCodeAt",
|
|
28
|
-
"codePointAt",
|
|
29
|
-
"at",
|
|
30
|
-
"concat",
|
|
31
|
-
"toString",
|
|
32
|
-
"match",
|
|
33
|
-
"matchAll",
|
|
34
|
-
"search",
|
|
35
|
-
"localeCompare",
|
|
36
|
-
"normalize",
|
|
37
|
-
"isWellFormed",
|
|
38
|
-
"toWellFormed",
|
|
39
|
-
]);
|
|
40
|
-
const codeUnits = (name, op) => sync(`String.${name}`, (args, node) => op(...args.map((arg) => {
|
|
41
|
-
if (typeof arg !== "number")
|
|
42
|
-
throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node);
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { toProgram } from "../data.js";
|
|
3
|
+
import { constructor, methods } from "../interpreter/native.js";
|
|
4
|
+
import { InterpreterRuntimeError, rangeError } from "../interpreter/model.js";
|
|
5
|
+
import { ProgramArray, ProgramPromise, ProgramRegExp, record } from "../interpreter/objects.js";
|
|
6
|
+
import { containsOpaqueReference, typeofValue } from "../interpreter/references.js";
|
|
7
|
+
import { applyCollectionCallback, isSupportedCallback } from "../interpreter/runner.js";
|
|
8
|
+
import { matchToValue, toHostRegex } from "./regexp.js";
|
|
9
|
+
import { coerceToNumber, coerceToString, coercion } from "./value.js";
|
|
10
|
+
// console is intercepted by the interpreter before reaching here.
|
|
11
|
+
const requireDataArgument = (name, index, arg, node) => {
|
|
12
|
+
if (containsOpaqueReference(arg)) {
|
|
13
|
+
throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a data value.`, node, "InvalidDataValue");
|
|
14
|
+
}
|
|
43
15
|
return arg;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
16
|
+
};
|
|
17
|
+
const replaceAllNeedsGlobal = (pattern, node) => {
|
|
18
|
+
if (!pattern.global) {
|
|
19
|
+
throw new InterpreterRuntimeError(`String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.replace to replace only the first match.`, node);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const replaceWithCallback = (runner, value, name, args, node) => {
|
|
23
|
+
const protos = runner.prototypes;
|
|
24
|
+
const apply = applyCollectionCallback(runner, args[1], `String.${name}`, node);
|
|
25
|
+
const matches = [];
|
|
26
|
+
const collect = (...callbackArgs) => {
|
|
27
|
+
const match = callbackArgs[0];
|
|
28
|
+
const groups = callbackArgs[callbackArgs.length - 1];
|
|
29
|
+
const hasGroups = groups !== null && typeof groups === "object";
|
|
30
|
+
const offset = callbackArgs[callbackArgs.length - (hasGroups ? 3 : 2)];
|
|
31
|
+
if (typeof match !== "string" || typeof offset !== "number") {
|
|
32
|
+
throw new InterpreterRuntimeError(`String.${name} produced an invalid replacement match.`, node);
|
|
33
|
+
}
|
|
34
|
+
if (hasGroups)
|
|
35
|
+
callbackArgs[callbackArgs.length - 1] = record(protos.Object, groups);
|
|
36
|
+
matches.push({ match, offset, args: callbackArgs });
|
|
37
|
+
return match;
|
|
38
|
+
};
|
|
39
|
+
const pattern = args[0];
|
|
40
|
+
if (pattern instanceof ProgramRegExp) {
|
|
41
|
+
if (name === "replaceAll")
|
|
42
|
+
replaceAllNeedsGlobal(pattern.regex, node);
|
|
43
|
+
if (name === "replace")
|
|
44
|
+
value.replace(pattern.regex, collect);
|
|
45
|
+
else
|
|
46
|
+
value.replaceAll(pattern.regex, collect);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const search = coerceToString(requireDataArgument(name, 0, pattern, node));
|
|
50
|
+
if (name === "replace")
|
|
51
|
+
value.replace(search, collect);
|
|
52
|
+
else
|
|
53
|
+
value.replaceAll(search, collect);
|
|
54
|
+
}
|
|
55
|
+
return Effect.gen(function* () {
|
|
56
|
+
const output = [];
|
|
57
|
+
let end = 0;
|
|
58
|
+
for (const match of matches) {
|
|
59
|
+
const replacement = yield* apply(match.args);
|
|
60
|
+
output.push(value.slice(end, match.offset), replacement instanceof ProgramPromise
|
|
61
|
+
? "[object Promise]"
|
|
62
|
+
: coerceToString(toProgram(protos, replacement, `String.${name} replacer result`)));
|
|
63
|
+
end = match.offset + match.match.length;
|
|
64
|
+
}
|
|
65
|
+
output.push(value.slice(end));
|
|
66
|
+
return output.join("");
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
export const stringGlobal = (runner) => {
|
|
70
|
+
const protos = runner.prototypes;
|
|
71
|
+
const string = constructor(protos, protos.String, {
|
|
72
|
+
name: "String",
|
|
73
|
+
length: 1,
|
|
74
|
+
call: coercion(runner, "String").call,
|
|
75
|
+
});
|
|
76
|
+
const codeUnits = (name, op) => [
|
|
77
|
+
name,
|
|
78
|
+
1,
|
|
79
|
+
(_, args, node) => op(...args.map((arg) => {
|
|
80
|
+
if (typeof arg !== "number") {
|
|
81
|
+
throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node);
|
|
82
|
+
}
|
|
83
|
+
return arg;
|
|
84
|
+
})),
|
|
85
|
+
];
|
|
86
|
+
methods(protos, string, [
|
|
87
|
+
codeUnits("fromCharCode", String.fromCharCode),
|
|
88
|
+
codeUnits("fromCodePoint", String.fromCodePoint),
|
|
89
|
+
]);
|
|
90
|
+
const self = (thisValue, name, node) => {
|
|
91
|
+
if (typeof thisValue === "string")
|
|
92
|
+
return thisValue;
|
|
93
|
+
if (thisValue === null || thisValue === undefined) {
|
|
94
|
+
throw new InterpreterRuntimeError(`String.prototype.${name} called on null or undefined.`, node);
|
|
95
|
+
}
|
|
96
|
+
return coerceToString(thisValue);
|
|
97
|
+
};
|
|
98
|
+
// Coerce arguments like native JS; opaque runtime references still reject.
|
|
99
|
+
const str = (name, args, index, node) => coerceToString(requireDataArgument(name, index, args[index], node));
|
|
100
|
+
const num = (name, args, index, node) => coerceToNumber(requireDataArgument(name, index, args[index], node));
|
|
101
|
+
const optNum = (name, args, index, node) => args[index] === undefined ? undefined : num(name, args, index, node);
|
|
102
|
+
const optStr = (name, args, index, node) => args[index] === undefined ? undefined : str(name, args, index, node);
|
|
103
|
+
const rejectRegex = (name, args, node) => {
|
|
104
|
+
if (args[0] instanceof ProgramRegExp) {
|
|
105
|
+
throw new InterpreterRuntimeError(`String.${name} cannot take a regular expression; use regex.test(string) or String.search instead.`, node);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const simple = (name, length, op) => [name, length, (thisValue, args, node) => op(self(thisValue, name, node), args, node)];
|
|
109
|
+
const replace = (name) => simple(name, 2, (value, args, node) => {
|
|
110
|
+
if (isSupportedCallback(args[1]))
|
|
111
|
+
return replaceWithCallback(runner, value, name, args, node);
|
|
112
|
+
if (typeofValue(args[1]) === "function") {
|
|
113
|
+
throw new InterpreterRuntimeError(`String.${name} cannot use this callable as a replacer; wrap it in an arrow function, e.g. (match) => tools.ns.tool(match).`, node);
|
|
114
|
+
}
|
|
115
|
+
if (args[0] instanceof ProgramRegExp) {
|
|
116
|
+
const pattern = args[0].regex;
|
|
117
|
+
const replacement = str(name, args, 1, node);
|
|
118
|
+
if (name === "replaceAll")
|
|
119
|
+
replaceAllNeedsGlobal(pattern, node);
|
|
120
|
+
return name === "replace" ? value.replace(pattern, replacement) : value.replaceAll(pattern, replacement);
|
|
121
|
+
}
|
|
122
|
+
if (name === "replace")
|
|
123
|
+
return value.replace(str(name, args, 0, node), str(name, args, 1, node));
|
|
124
|
+
return value.replaceAll(str(name, args, 0, node), str(name, args, 1, node));
|
|
125
|
+
});
|
|
126
|
+
methods(protos, protos.String, [
|
|
127
|
+
simple("toString", 0, (value) => value),
|
|
128
|
+
simple("valueOf", 0, (value) => value),
|
|
129
|
+
simple("toLowerCase", 0, (value) => value.toLowerCase()),
|
|
130
|
+
simple("toUpperCase", 0, (value) => value.toUpperCase()),
|
|
131
|
+
simple("trim", 0, (value) => value.trim()),
|
|
132
|
+
simple("trimStart", 0, (value) => value.trimStart()),
|
|
133
|
+
simple("trimLeft", 0, (value) => value.trimStart()),
|
|
134
|
+
simple("trimEnd", 0, (value) => value.trimEnd()),
|
|
135
|
+
simple("trimRight", 0, (value) => value.trimEnd()),
|
|
136
|
+
// Locale/options are deliberately unsupported; comparison uses the host default locale.
|
|
137
|
+
simple("localeCompare", 1, (value, args, node) => value.localeCompare(str("localeCompare", args, 0, node))),
|
|
138
|
+
simple("normalize", 0, (value, args, node) => {
|
|
139
|
+
const form = optStr("normalize", args, 0, node);
|
|
140
|
+
try {
|
|
141
|
+
return value.normalize(form);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw rangeError(`String.normalize expects the form "NFC", "NFD", "NFKC", or "NFKD" (got ${JSON.stringify(form)}).`, node);
|
|
145
|
+
}
|
|
146
|
+
}),
|
|
147
|
+
simple("split", 2, (value, args, node) => {
|
|
148
|
+
const wrap = (parts) => new ProgramArray(protos.Array, parts);
|
|
149
|
+
// Native: an undefined separator returns the whole string, not a split on "undefined",
|
|
150
|
+
// unless the limit truncates to zero.
|
|
151
|
+
const requestedLimit = optNum("split", args, 1, node);
|
|
152
|
+
if (args[0] === undefined) {
|
|
153
|
+
return wrap(requestedLimit !== undefined && requestedLimit >>> 0 === 0 ? [] : [value]);
|
|
154
|
+
}
|
|
155
|
+
if (args[0] instanceof ProgramRegExp)
|
|
156
|
+
return wrap(value.split(args[0].regex, requestedLimit));
|
|
157
|
+
return wrap(value.split(str("split", args, 0, node), requestedLimit === undefined ? undefined : requestedLimit >>> 0));
|
|
158
|
+
}),
|
|
159
|
+
simple("slice", 2, (value, args, node) => value.slice(optNum("slice", args, 0, node), optNum("slice", args, 1, node))),
|
|
160
|
+
simple("includes", 1, (value, args, node) => {
|
|
161
|
+
rejectRegex("includes", args, node);
|
|
162
|
+
return value.includes(str("includes", args, 0, node), optNum("includes", args, 1, node));
|
|
163
|
+
}),
|
|
164
|
+
simple("startsWith", 1, (value, args, node) => {
|
|
165
|
+
rejectRegex("startsWith", args, node);
|
|
166
|
+
return value.startsWith(str("startsWith", args, 0, node), optNum("startsWith", args, 1, node));
|
|
167
|
+
}),
|
|
168
|
+
simple("endsWith", 1, (value, args, node) => {
|
|
169
|
+
rejectRegex("endsWith", args, node);
|
|
170
|
+
return value.endsWith(str("endsWith", args, 0, node), optNum("endsWith", args, 1, node));
|
|
171
|
+
}),
|
|
172
|
+
simple("indexOf", 1, (value, args, node) => value.indexOf(str("indexOf", args, 0, node), optNum("indexOf", args, 1, node))),
|
|
173
|
+
simple("lastIndexOf", 1, (value, args, node) => value.lastIndexOf(str("lastIndexOf", args, 0, node), optNum("lastIndexOf", args, 1, node))),
|
|
174
|
+
replace("replace"),
|
|
175
|
+
replace("replaceAll"),
|
|
176
|
+
simple("match", 1, (value, args, node) => {
|
|
177
|
+
const pattern = toHostRegex(args[0], "match", node);
|
|
178
|
+
const matched = value.match(pattern);
|
|
179
|
+
if (matched === null)
|
|
180
|
+
return null;
|
|
181
|
+
// Preserve the own `index` and `groups` properties on non-global matches.
|
|
182
|
+
if (pattern.global)
|
|
183
|
+
return toProgram(protos, matched, "String.match result");
|
|
184
|
+
return matchToValue(protos, matched);
|
|
185
|
+
}),
|
|
186
|
+
simple("matchAll", 1, (value, args, node) => {
|
|
187
|
+
const pattern = toHostRegex(args[0], "matchAll", node, "g");
|
|
188
|
+
if (!pattern.global) {
|
|
189
|
+
throw new InterpreterRuntimeError(`String.matchAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.match for a single match.`, node);
|
|
190
|
+
}
|
|
191
|
+
return new ProgramArray(protos.Array, Array.from(value.matchAll(pattern), (match) => matchToValue(protos, match)));
|
|
192
|
+
}),
|
|
193
|
+
simple("search", 1, (value, args, node) => value.search(toHostRegex(args[0], "search", node))),
|
|
194
|
+
simple("repeat", 1, (value, args, node) => {
|
|
195
|
+
const count = num("repeat", args, 0, node);
|
|
196
|
+
if (!Number.isFinite(count) || count < 0) {
|
|
197
|
+
throw rangeError("String.repeat expects a finite non-negative count.", node);
|
|
198
|
+
}
|
|
199
|
+
return value.repeat(count);
|
|
200
|
+
}),
|
|
201
|
+
simple("padStart", 1, (value, args, node) => value.padStart(num("padStart", args, 0, node), optStr("padStart", args, 1, node))),
|
|
202
|
+
simple("padEnd", 1, (value, args, node) => value.padEnd(num("padEnd", args, 0, node), optStr("padEnd", args, 1, node))),
|
|
203
|
+
simple("charAt", 1, (value, args, node) => value.charAt(optNum("charAt", args, 0, node) ?? 0)),
|
|
204
|
+
simple("at", 1, (value, args, node) => value.at(optNum("at", args, 0, node) ?? 0)),
|
|
205
|
+
simple("substring", 2, (value, args, node) => value.substring(optNum("substring", args, 0, node) ?? 0, optNum("substring", args, 1, node))),
|
|
206
|
+
simple("substr", 2, (value, args, node) => value.substr(optNum("substr", args, 0, node) ?? 0, optNum("substr", args, 1, node))),
|
|
207
|
+
simple("isWellFormed", 0, (value) => value.isWellFormed()),
|
|
208
|
+
simple("toWellFormed", 0, (value) => value.toWellFormed()),
|
|
209
|
+
simple("charCodeAt", 1, (value, args, node) => value.charCodeAt(optNum("charCodeAt", args, 0, node) ?? 0)),
|
|
210
|
+
simple("codePointAt", 1, (value, args, node) => value.codePointAt(optNum("codePointAt", args, 0, node) ?? 0)),
|
|
211
|
+
simple("concat", 1, (value, args, node) => value.concat(...args.map((_, index) => str("concat", args, index, node)))),
|
|
212
|
+
]);
|
|
213
|
+
return string;
|
|
214
|
+
};
|
package/dist/stdlib/url.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type AstNode } from "../interpreter/model.js";
|
|
1
|
+
import type { Prototypes } from "../interpreter/intrinsics.js";
|
|
3
2
|
import { type Runner } from "../interpreter/runner.js";
|
|
4
|
-
|
|
5
|
-
export declare const urlProperties: Set<string>;
|
|
6
|
-
export declare const urlWritableProperties: Set<string>;
|
|
7
|
-
export declare const urlMethods: Set<string>;
|
|
8
|
-
export declare const urlSearchParamsMethods: Set<string>;
|
|
9
|
-
export declare const uriArgument: (value: unknown, label: string) => string;
|
|
3
|
+
export declare const uriArgument: (protos: Prototypes, value: unknown, label: string) => string;
|
|
10
4
|
type UriFunction = "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
|
|
11
|
-
export declare const uriGlobal: (name: UriFunction) =>
|
|
12
|
-
export declare const
|
|
13
|
-
export declare const
|
|
14
|
-
export declare const urlSearchParamsGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
|
|
15
|
-
export declare const invokeURLMethod: (value: Values.URL, name: string, node: AstNode) => string;
|
|
5
|
+
export declare const uriGlobal: <R>(runner: Runner<R>, name: UriFunction) => import("../interpreter/objects.js").NativeFunction<R>;
|
|
6
|
+
export declare const urlGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
|
|
7
|
+
export declare const urlSearchParamsGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
|
|
16
8
|
export {};
|
package/dist/stdlib/url.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { toProgram } from "../data.js";
|
|
3
|
-
import {
|
|
4
|
-
import { InterpreterRuntimeError } from "../interpreter/model.js";
|
|
5
|
-
import {
|
|
2
|
+
import { toProgram, ToolRuntimeError } from "../data.js";
|
|
3
|
+
import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
4
|
+
import { InterpreterRuntimeError, uriError } from "../interpreter/model.js";
|
|
5
|
+
import { defineAccessor, entries, isWrapper, ProgramArray, ProgramObject, ProgramURL, ProgramURLSearchParams, } from "../interpreter/objects.js";
|
|
6
6
|
import { isRuntimeReference } from "../interpreter/references.js";
|
|
7
|
-
import { preserveConsumerError } from "../interpreter/runner.js";
|
|
8
|
-
import { Values } from "../values.js";
|
|
7
|
+
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/runner.js";
|
|
9
8
|
import { coerceToString } from "./value.js";
|
|
10
|
-
|
|
9
|
+
const urlProperties = [
|
|
11
10
|
"href",
|
|
12
11
|
"origin",
|
|
13
12
|
"protocol",
|
|
@@ -19,143 +18,244 @@ export const urlProperties = new Set([
|
|
|
19
18
|
"pathname",
|
|
20
19
|
"search",
|
|
21
20
|
"hash",
|
|
22
|
-
]
|
|
23
|
-
export const
|
|
24
|
-
"href",
|
|
25
|
-
"protocol",
|
|
26
|
-
"username",
|
|
27
|
-
"password",
|
|
28
|
-
"host",
|
|
29
|
-
"hostname",
|
|
30
|
-
"port",
|
|
31
|
-
"pathname",
|
|
32
|
-
"search",
|
|
33
|
-
"hash",
|
|
34
|
-
]);
|
|
35
|
-
export const urlMethods = new Set(["toString", "toJSON"]);
|
|
36
|
-
export const urlSearchParamsMethods = new Set([
|
|
37
|
-
"append",
|
|
38
|
-
"delete",
|
|
39
|
-
"get",
|
|
40
|
-
"getAll",
|
|
41
|
-
"has",
|
|
42
|
-
"set",
|
|
43
|
-
"sort",
|
|
44
|
-
"forEach",
|
|
45
|
-
"keys",
|
|
46
|
-
"values",
|
|
47
|
-
"entries",
|
|
48
|
-
"toString",
|
|
49
|
-
]);
|
|
50
|
-
export const uriArgument = (value, label) => coerceToString(toProgram(value, label));
|
|
21
|
+
];
|
|
22
|
+
export const uriArgument = (protos, value, label) => coerceToString(toProgram(protos, value, label));
|
|
51
23
|
const uriFunctions = {
|
|
52
24
|
encodeURI,
|
|
53
25
|
encodeURIComponent,
|
|
54
26
|
decodeURI,
|
|
55
27
|
decodeURIComponent,
|
|
56
28
|
};
|
|
57
|
-
export const uriGlobal = (name) =>
|
|
58
|
-
const value = uriArgument(args[0], `${name} input`);
|
|
29
|
+
export const uriGlobal = (runner, name) => fn(runner.prototypes, name, 1, (_, args, node) => {
|
|
30
|
+
const value = uriArgument(runner.prototypes, args[0], `${name} input`);
|
|
59
31
|
try {
|
|
60
32
|
return uriFunctions[name](value);
|
|
61
33
|
}
|
|
62
34
|
catch (error) {
|
|
63
|
-
throw
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
export const urlArgument = (value, label) => value instanceof Values.URL ? value.url.href : uriArgument(value, label);
|
|
67
|
-
const urlStatic = (name) => sync(`URL.${name}`, (args, node) => {
|
|
68
|
-
if (args.length === 0) {
|
|
69
|
-
throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError");
|
|
70
|
-
}
|
|
71
|
-
const input = urlArgument(args[0], `URL.${name} input`);
|
|
72
|
-
const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`);
|
|
73
|
-
try {
|
|
74
|
-
const url = new URL(input, base);
|
|
75
|
-
return name === "canParse" ? true : new Values.URL(url);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return name === "canParse" ? false : null;
|
|
35
|
+
throw uriError(`${name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, node);
|
|
79
36
|
}
|
|
80
37
|
});
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
38
|
+
const urlArgument = (protos, value, label) => value instanceof ProgramURL ? value.url.href : uriArgument(protos, value, label);
|
|
39
|
+
export const urlGlobal = (runner) => {
|
|
40
|
+
const protos = runner.prototypes;
|
|
41
|
+
const proto = protos.URL;
|
|
42
|
+
const construct = (args, into, node) => {
|
|
43
|
+
if (args.length === 0) {
|
|
44
|
+
throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node);
|
|
45
|
+
}
|
|
46
|
+
const input = urlArgument(protos, args[0], "new URL input");
|
|
47
|
+
const base = args[1] === undefined ? undefined : urlArgument(protos, args[1], "new URL base");
|
|
48
|
+
try {
|
|
49
|
+
return new ProgramURL(into, protos.URLSearchParams, new URL(input, base));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw new InterpreterRuntimeError(`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, node);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const url = constructor(protos, proto, {
|
|
56
|
+
name: "URL",
|
|
57
|
+
length: 1,
|
|
58
|
+
call: requiresNew("URL"),
|
|
59
|
+
construct: (args, newTarget, node) => Effect.sync(() => construct(args, prototypeFrom(newTarget, proto), node)),
|
|
60
|
+
});
|
|
61
|
+
const parse = (name) => [
|
|
62
|
+
name,
|
|
63
|
+
1,
|
|
64
|
+
(_, args, node) => {
|
|
65
|
+
if (args.length === 0)
|
|
66
|
+
throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node);
|
|
67
|
+
const input = urlArgument(protos, args[0], `URL.${name} input`);
|
|
68
|
+
const base = args[1] === undefined ? undefined : urlArgument(protos, args[1], `URL.${name} base`);
|
|
69
|
+
try {
|
|
70
|
+
const parsed = new URL(input, base);
|
|
71
|
+
return name === "canParse" ? true : new ProgramURL(proto, protos.URLSearchParams, parsed);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return name === "canParse" ? false : null;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
methods(protos, url, [parse("canParse"), parse("parse")]);
|
|
79
|
+
const self = (thisValue, name, node) => receiver(ProgramURL, thisValue, `URL.prototype.${name}`, node);
|
|
80
|
+
for (const name of urlProperties) {
|
|
81
|
+
defineAccessor(proto, name, (thisValue) => self(thisValue, name).url[name], name === "origin"
|
|
82
|
+
? undefined
|
|
83
|
+
: (thisValue, value) => {
|
|
84
|
+
const target = self(thisValue, name);
|
|
85
|
+
try {
|
|
86
|
+
;
|
|
87
|
+
target.url[name] = uriArgument(protos, value, `URL.${name} value`);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError)
|
|
91
|
+
throw error;
|
|
92
|
+
throw new InterpreterRuntimeError(`URL.${name} received an invalid value.`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
92
95
|
}
|
|
96
|
+
defineAccessor(proto, "searchParams", (thisValue) => self(thisValue, "searchParams").searchParams);
|
|
97
|
+
methods(protos, proto, [
|
|
98
|
+
["toString", 0, (thisValue, _, node) => self(thisValue, "toString", node).url.href],
|
|
99
|
+
["toJSON", 0, (thisValue, _, node) => self(thisValue, "toJSON", node).url.href],
|
|
100
|
+
]);
|
|
101
|
+
return url;
|
|
93
102
|
};
|
|
94
|
-
|
|
95
|
-
name: "URL",
|
|
96
|
-
call: requiresNew("URL"),
|
|
97
|
-
construct: syncCall(constructURL),
|
|
98
|
-
instanceOf: (value) => value instanceof Values.URL,
|
|
99
|
-
members: { canParse: urlStatic("canParse"), parse: urlStatic("parse") },
|
|
100
|
-
});
|
|
101
|
-
const readURLSearchParamsPair = (runner, value, node) => Effect.gen(function* () {
|
|
103
|
+
const readPair = (runner, value, node) => Effect.gen(function* () {
|
|
102
104
|
const cursor = yield* runner.syncIterator(value, node);
|
|
103
105
|
if (cursor === undefined) {
|
|
104
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node)
|
|
106
|
+
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node);
|
|
105
107
|
}
|
|
106
108
|
const items = [];
|
|
107
109
|
while (true) {
|
|
108
110
|
const step = yield* cursor.next;
|
|
109
111
|
if (step.done)
|
|
110
112
|
return items;
|
|
111
|
-
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => uriArgument(step.value, "URLSearchParams pair value"))));
|
|
113
|
+
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => uriArgument(runner.prototypes, step.value, "URLSearchParams pair value"))));
|
|
112
114
|
}
|
|
113
115
|
});
|
|
114
|
-
const constructURLSearchParams = (runner, init, node) => {
|
|
116
|
+
const constructURLSearchParams = (runner, init, proto, node) => {
|
|
117
|
+
const wrap = (params) => new ProgramURLSearchParams(proto, params);
|
|
115
118
|
if (init === undefined)
|
|
116
|
-
return Effect.succeed(
|
|
117
|
-
if (init instanceof
|
|
118
|
-
return Effect.succeed(
|
|
119
|
-
}
|
|
119
|
+
return Effect.succeed(wrap(new URLSearchParams()));
|
|
120
|
+
if (init instanceof ProgramURLSearchParams)
|
|
121
|
+
return Effect.succeed(wrap(new URLSearchParams(init.params)));
|
|
120
122
|
if (typeof init === "string")
|
|
121
|
-
return Effect.succeed(
|
|
123
|
+
return Effect.succeed(wrap(new URLSearchParams(init)));
|
|
122
124
|
if (init === null || typeof init === "number" || typeof init === "boolean") {
|
|
123
|
-
return Effect.succeed(
|
|
125
|
+
return Effect.succeed(wrap(new URLSearchParams(coerceToString(init))));
|
|
124
126
|
}
|
|
125
127
|
return Effect.gen(function* () {
|
|
126
128
|
const cursor = yield* runner.syncIterator(init, node);
|
|
127
129
|
if (cursor !== undefined) {
|
|
128
|
-
const
|
|
130
|
+
const pairs = [];
|
|
129
131
|
while (true) {
|
|
130
132
|
const step = yield* cursor.next;
|
|
131
133
|
if (step.done) {
|
|
132
|
-
if (
|
|
133
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node)
|
|
134
|
+
if (pairs.some((entry) => entry.length !== 2)) {
|
|
135
|
+
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node);
|
|
134
136
|
}
|
|
135
|
-
return
|
|
137
|
+
return wrap(new URLSearchParams(pairs.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
|
|
136
138
|
}
|
|
137
|
-
|
|
139
|
+
pairs.push(yield* preserveConsumerError(cursor, readPair(runner, step.value, node)));
|
|
138
140
|
}
|
|
139
141
|
}
|
|
140
142
|
if (isRuntimeReference(init)) {
|
|
141
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.", node)
|
|
143
|
+
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.", node);
|
|
142
144
|
}
|
|
143
|
-
if (
|
|
144
|
-
return
|
|
145
|
+
if (isWrapper(init))
|
|
146
|
+
return wrap(new URLSearchParams());
|
|
145
147
|
if (!(init instanceof ProgramObject)) {
|
|
146
|
-
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.", node)
|
|
148
|
+
throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.", node);
|
|
147
149
|
}
|
|
148
|
-
return
|
|
150
|
+
return wrap(new URLSearchParams(Object.fromEntries(entries(init).map(([key, value]) => [key, coerceToString(value)]))));
|
|
149
151
|
});
|
|
150
152
|
};
|
|
151
|
-
export const urlSearchParamsGlobal = (runner) =>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
export const urlSearchParamsGlobal = (runner) => {
|
|
154
|
+
const protos = runner.prototypes;
|
|
155
|
+
const proto = protos.URLSearchParams;
|
|
156
|
+
const searchParams = constructor(protos, proto, {
|
|
157
|
+
name: "URLSearchParams",
|
|
158
|
+
call: requiresNew("URLSearchParams"),
|
|
159
|
+
construct: (args, newTarget, node) => constructURLSearchParams(runner, args[0], prototypeFrom(newTarget, proto), node),
|
|
160
|
+
});
|
|
161
|
+
const self = (thisValue, name, node) => receiver(ProgramURLSearchParams, thisValue, `URLSearchParams.prototype.${name}`, node);
|
|
162
|
+
const wrap = (items) => new ProgramArray(protos.Array, items);
|
|
163
|
+
const arg = (name, args, index) => uriArgument(protos, args[index], `URLSearchParams.${name} argument ${index + 1}`);
|
|
164
|
+
const requireArgs = (name, args, count, node) => {
|
|
165
|
+
if (args.length < count) {
|
|
166
|
+
throw new InterpreterRuntimeError(`URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`, node);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
defineAccessor(proto, "size", (thisValue) => self(thisValue, "size").params.size);
|
|
170
|
+
methods(protos, proto, [
|
|
171
|
+
[
|
|
172
|
+
"append",
|
|
173
|
+
2,
|
|
174
|
+
(thisValue, args, node) => {
|
|
175
|
+
requireArgs("append", args, 2, node);
|
|
176
|
+
self(thisValue, "append", node).params.append(arg("append", args, 0), arg("append", args, 1));
|
|
177
|
+
return undefined;
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
[
|
|
181
|
+
"delete",
|
|
182
|
+
1,
|
|
183
|
+
(thisValue, args, node) => {
|
|
184
|
+
requireArgs("delete", args, 1, node);
|
|
185
|
+
const params = self(thisValue, "delete", node).params;
|
|
186
|
+
if (args[1] !== undefined)
|
|
187
|
+
params.delete(arg("delete", args, 0), arg("delete", args, 1));
|
|
188
|
+
else
|
|
189
|
+
params.delete(arg("delete", args, 0));
|
|
190
|
+
return undefined;
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
[
|
|
194
|
+
"get",
|
|
195
|
+
1,
|
|
196
|
+
(thisValue, args, node) => {
|
|
197
|
+
requireArgs("get", args, 1, node);
|
|
198
|
+
return self(thisValue, "get", node).params.get(arg("get", args, 0));
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
[
|
|
202
|
+
"getAll",
|
|
203
|
+
1,
|
|
204
|
+
(thisValue, args, node) => {
|
|
205
|
+
requireArgs("getAll", args, 1, node);
|
|
206
|
+
return wrap(self(thisValue, "getAll", node).params.getAll(arg("getAll", args, 0)));
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
[
|
|
210
|
+
"has",
|
|
211
|
+
1,
|
|
212
|
+
(thisValue, args, node) => {
|
|
213
|
+
requireArgs("has", args, 1, node);
|
|
214
|
+
const params = self(thisValue, "has", node).params;
|
|
215
|
+
return args[1] !== undefined
|
|
216
|
+
? params.has(arg("has", args, 0), arg("has", args, 1))
|
|
217
|
+
: params.has(arg("has", args, 0));
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
[
|
|
221
|
+
"set",
|
|
222
|
+
2,
|
|
223
|
+
(thisValue, args, node) => {
|
|
224
|
+
requireArgs("set", args, 2, node);
|
|
225
|
+
self(thisValue, "set", node).params.set(arg("set", args, 0), arg("set", args, 1));
|
|
226
|
+
return undefined;
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
[
|
|
230
|
+
"sort",
|
|
231
|
+
0,
|
|
232
|
+
(thisValue, _, node) => {
|
|
233
|
+
self(thisValue, "sort", node).params.sort();
|
|
234
|
+
return undefined;
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
["keys", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "keys", node).params.keys()))],
|
|
238
|
+
["values", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "values", node).params.values()))],
|
|
239
|
+
[
|
|
240
|
+
"entries",
|
|
241
|
+
0,
|
|
242
|
+
(thisValue, _, node) => wrap(Array.from(self(thisValue, "entries", node).params.entries(), ([key, value]) => wrap([key, value]))),
|
|
243
|
+
],
|
|
244
|
+
["toString", 0, (thisValue, _, node) => self(thisValue, "toString", node).params.toString()],
|
|
245
|
+
[
|
|
246
|
+
"forEach",
|
|
247
|
+
1,
|
|
248
|
+
(thisValue, args, node) => {
|
|
249
|
+
requireArgs("forEach", args, 1, node);
|
|
250
|
+
const target = self(thisValue, "forEach", node);
|
|
251
|
+
const apply = applyCollectionCallback(runner, args[0], "URLSearchParams.forEach", node);
|
|
252
|
+
return Effect.gen(function* () {
|
|
253
|
+
for (const [key, value] of Array.from(target.params.entries()))
|
|
254
|
+
yield* apply([value, key, target]);
|
|
255
|
+
return undefined;
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
]);
|
|
260
|
+
return searchParams;
|
|
161
261
|
};
|