@opencode-ai/codemode 0.0.0-dev-17471
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/README.md +168 -0
- package/dist/codemode.d.ts +148 -0
- package/dist/codemode.js +70 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/interpreter/errors.d.ts +9 -0
- package/dist/interpreter/errors.js +91 -0
- package/dist/interpreter/execute.d.ts +4 -0
- package/dist/interpreter/execute.js +178 -0
- package/dist/interpreter/iterator.d.ts +13 -0
- package/dist/interpreter/iterator.js +4 -0
- package/dist/interpreter/methods.d.ts +17 -0
- package/dist/interpreter/methods.js +1026 -0
- package/dist/interpreter/model.d.ts +151 -0
- package/dist/interpreter/model.js +186 -0
- package/dist/interpreter/promises.d.ts +29 -0
- package/dist/interpreter/promises.js +253 -0
- package/dist/interpreter/references.d.ts +6 -0
- package/dist/interpreter/references.js +114 -0
- package/dist/interpreter/runtime.d.ts +98 -0
- package/dist/interpreter/runtime.js +2351 -0
- package/dist/interpreter/scope.d.ts +15 -0
- package/dist/interpreter/scope.js +79 -0
- package/dist/interpreter/transpile.node.d.ts +5 -0
- package/dist/interpreter/transpile.node.js +19 -0
- package/dist/interpreter/transpile.workerd.d.ts +5 -0
- package/dist/interpreter/transpile.workerd.js +6 -0
- package/dist/openapi/index.d.ts +7 -0
- package/dist/openapi/index.js +101 -0
- package/dist/openapi/runtime.d.ts +4 -0
- package/dist/openapi/runtime.js +283 -0
- package/dist/openapi/spec.d.ts +20 -0
- package/dist/openapi/spec.js +588 -0
- package/dist/openapi/types.d.ts +122 -0
- package/dist/openapi/types.js +2 -0
- package/dist/stdlib/collections.d.ts +4 -0
- package/dist/stdlib/collections.js +57 -0
- package/dist/stdlib/console.d.ts +2 -0
- package/dist/stdlib/console.js +126 -0
- package/dist/stdlib/date.d.ts +7 -0
- package/dist/stdlib/date.js +186 -0
- package/dist/stdlib/json.d.ts +6 -0
- package/dist/stdlib/json.js +124 -0
- package/dist/stdlib/math.d.ts +12 -0
- package/dist/stdlib/math.js +157 -0
- package/dist/stdlib/number.d.ts +6 -0
- package/dist/stdlib/number.js +76 -0
- package/dist/stdlib/object.d.ts +7 -0
- package/dist/stdlib/object.js +100 -0
- package/dist/stdlib/promise.d.ts +2 -0
- package/dist/stdlib/promise.js +1 -0
- package/dist/stdlib/regexp.d.ts +11 -0
- package/dist/stdlib/regexp.js +106 -0
- package/dist/stdlib/string.d.ts +4 -0
- package/dist/stdlib/string.js +48 -0
- package/dist/stdlib/url.d.ts +12 -0
- package/dist/stdlib/url.js +84 -0
- package/dist/stdlib/value.d.ts +12 -0
- package/dist/stdlib/value.js +120 -0
- package/dist/tool-error.d.ts +11 -0
- package/dist/tool-error.js +9 -0
- package/dist/tool-runtime.d.ts +68 -0
- package/dist/tool-runtime.js +390 -0
- package/dist/tool-schema.d.ts +15 -0
- package/dist/tool-schema.js +213 -0
- package/dist/tool.d.ts +55 -0
- package/dist/tool.js +21 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +1 -0
- package/dist/values.d.ts +31 -0
- package/dist/values.js +50 -0
- package/package.json +46 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { HttpClient } from "effect/unstable/http";
|
|
3
|
+
import type { Tool, JsonSchema } from "../tool.js";
|
|
4
|
+
/** A parsed OpenAPI 3.x document. YAML must be parsed by the host. */
|
|
5
|
+
export type Document = Record<string, unknown>;
|
|
6
|
+
/** The operation identity handed to auth resolution and errors. */
|
|
7
|
+
export type Operation = {
|
|
8
|
+
readonly operationId: string | undefined;
|
|
9
|
+
readonly method: string;
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly summary: string | undefined;
|
|
12
|
+
readonly description: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
/** A resolved OpenAPI security scheme from `components.securitySchemes`. */
|
|
15
|
+
export type SecurityScheme = {
|
|
16
|
+
readonly type: "apiKey";
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly in: "header" | "query" | "cookie";
|
|
19
|
+
} | {
|
|
20
|
+
readonly type: "http";
|
|
21
|
+
readonly scheme: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly type: "oauth2";
|
|
24
|
+
} | {
|
|
25
|
+
readonly type: "openIdConnect";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Credential material returned by a host auth resolver. `apiKey` uses the scheme's carrier;
|
|
29
|
+
* `header` supports nonstandard schemes.
|
|
30
|
+
*/
|
|
31
|
+
export type Credential = {
|
|
32
|
+
readonly type: "bearer";
|
|
33
|
+
readonly token: string;
|
|
34
|
+
} | {
|
|
35
|
+
readonly type: "basic";
|
|
36
|
+
readonly username: string;
|
|
37
|
+
readonly password: string;
|
|
38
|
+
} | {
|
|
39
|
+
readonly type: "apiKey";
|
|
40
|
+
readonly value: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly type: "header";
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly value: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resolves credentials at call time. `undefined` tries the next OR alternative; failure aborts.
|
|
48
|
+
*/
|
|
49
|
+
export type AuthResolver = (context: {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly definition: SecurityScheme;
|
|
52
|
+
readonly scopes: ReadonlyArray<string>;
|
|
53
|
+
readonly operation: Operation;
|
|
54
|
+
}) => Effect.Effect<Credential | undefined, unknown>;
|
|
55
|
+
export type Options = {
|
|
56
|
+
readonly spec: Document;
|
|
57
|
+
/** Overrides all document, path, and operation `servers`. Required when no applicable absolute server URL exists. */
|
|
58
|
+
readonly baseUrl?: string | undefined;
|
|
59
|
+
/** Host credential resolution, keyed by security scheme name. */
|
|
60
|
+
readonly auth?: {
|
|
61
|
+
readonly resolve: AuthResolver;
|
|
62
|
+
} | undefined;
|
|
63
|
+
/** Static headers on every request. Not model-visible; declared header params may override them, auth always wins. */
|
|
64
|
+
readonly headers?: Readonly<Record<string, string>> | undefined;
|
|
65
|
+
};
|
|
66
|
+
/** An operation that could not be represented as a tool, and why. */
|
|
67
|
+
export type Skipped = {
|
|
68
|
+
readonly method: string;
|
|
69
|
+
readonly path: string;
|
|
70
|
+
readonly reason: string;
|
|
71
|
+
};
|
|
72
|
+
export type Tools = {
|
|
73
|
+
[name: string]: Tool<HttpClient.HttpClient> | Tools;
|
|
74
|
+
};
|
|
75
|
+
export type Result = {
|
|
76
|
+
/** Namespaced tools; the host places them under a key in its `tools` object. */
|
|
77
|
+
readonly tools: Tools;
|
|
78
|
+
readonly skipped: ReadonlyArray<Skipped>;
|
|
79
|
+
};
|
|
80
|
+
export type Parsed<T> = {
|
|
81
|
+
readonly ok: true;
|
|
82
|
+
readonly value: T;
|
|
83
|
+
} | {
|
|
84
|
+
readonly ok: false;
|
|
85
|
+
readonly reason: string;
|
|
86
|
+
};
|
|
87
|
+
export type InputLocation = "path" | "query" | "header" | "body";
|
|
88
|
+
export type InputField = {
|
|
89
|
+
readonly inputName: string;
|
|
90
|
+
readonly name: string;
|
|
91
|
+
readonly location: InputLocation;
|
|
92
|
+
readonly required: boolean;
|
|
93
|
+
readonly schema: JsonSchema;
|
|
94
|
+
readonly style: "simple" | "form" | "deepObject" | undefined;
|
|
95
|
+
readonly explode: boolean | undefined;
|
|
96
|
+
};
|
|
97
|
+
export type Body = {
|
|
98
|
+
readonly required: boolean;
|
|
99
|
+
readonly mode: "object" | "value";
|
|
100
|
+
readonly mediaType: string;
|
|
101
|
+
};
|
|
102
|
+
export type OperationInput = {
|
|
103
|
+
readonly fields: ReadonlyArray<InputField>;
|
|
104
|
+
readonly body: Body | undefined;
|
|
105
|
+
};
|
|
106
|
+
export type SecurityRequirement = Readonly<Record<string, ReadonlyArray<string>>>;
|
|
107
|
+
export type Plan = {
|
|
108
|
+
readonly operation: Operation;
|
|
109
|
+
readonly url: string;
|
|
110
|
+
readonly fields: ReadonlyArray<InputField>;
|
|
111
|
+
readonly body: Body | undefined;
|
|
112
|
+
readonly security: ReadonlyArray<SecurityRequirement>;
|
|
113
|
+
readonly schemes: Readonly<Record<string, SecurityScheme>>;
|
|
114
|
+
readonly auth: {
|
|
115
|
+
readonly resolve: AuthResolver;
|
|
116
|
+
} | undefined;
|
|
117
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
118
|
+
};
|
|
119
|
+
export type AppliedAuth = {
|
|
120
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
121
|
+
readonly query: Readonly<Record<string, string>>;
|
|
122
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const arrayMethods = new Set([
|
|
2
|
+
"map",
|
|
3
|
+
"filter",
|
|
4
|
+
"find",
|
|
5
|
+
"findIndex",
|
|
6
|
+
"findLast",
|
|
7
|
+
"findLastIndex",
|
|
8
|
+
"some",
|
|
9
|
+
"every",
|
|
10
|
+
"includes",
|
|
11
|
+
"join",
|
|
12
|
+
"reduce",
|
|
13
|
+
"reduceRight",
|
|
14
|
+
"flatMap",
|
|
15
|
+
"forEach",
|
|
16
|
+
"sort",
|
|
17
|
+
"toSorted",
|
|
18
|
+
"slice",
|
|
19
|
+
"concat",
|
|
20
|
+
"indexOf",
|
|
21
|
+
"lastIndexOf",
|
|
22
|
+
"at",
|
|
23
|
+
"flat",
|
|
24
|
+
"reverse",
|
|
25
|
+
"toReversed",
|
|
26
|
+
"with",
|
|
27
|
+
"push",
|
|
28
|
+
"pop",
|
|
29
|
+
"shift",
|
|
30
|
+
"unshift",
|
|
31
|
+
"splice",
|
|
32
|
+
"toSpliced",
|
|
33
|
+
"fill",
|
|
34
|
+
"copyWithin",
|
|
35
|
+
"keys",
|
|
36
|
+
"values",
|
|
37
|
+
"entries",
|
|
38
|
+
]);
|
|
39
|
+
export const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]);
|
|
40
|
+
export const mapStatics = new Set(["groupBy"]);
|
|
41
|
+
export const setMethods = new Set([
|
|
42
|
+
"add",
|
|
43
|
+
"has",
|
|
44
|
+
"delete",
|
|
45
|
+
"clear",
|
|
46
|
+
"forEach",
|
|
47
|
+
"keys",
|
|
48
|
+
"values",
|
|
49
|
+
"entries",
|
|
50
|
+
"union",
|
|
51
|
+
"intersection",
|
|
52
|
+
"difference",
|
|
53
|
+
"symmetricDifference",
|
|
54
|
+
"isSubsetOf",
|
|
55
|
+
"isSupersetOf",
|
|
56
|
+
"isDisjointFrom",
|
|
57
|
+
]);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { containsOpaqueReference, containsRuntimeReference, isRuntimeReference } from "../interpreter/references.js";
|
|
2
|
+
import { copyIn, copyOut } from "../tool-runtime.js";
|
|
3
|
+
import { isCodeModeValue, CodeModeDate, CodeModeMap, CodeModePromise, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "../values.js";
|
|
4
|
+
import { boundedData, coerceToString } from "./value.js";
|
|
5
|
+
export const consoleMethods = new Set(["log", "info", "debug", "warn", "error", "dir", "table"]);
|
|
6
|
+
const MAX_CONSOLE_DEPTH = 32;
|
|
7
|
+
export const formatConsoleMessage = (name, args) => {
|
|
8
|
+
if (name === "dir")
|
|
9
|
+
return args.length === 0 ? "undefined" : formatConsoleArgument(args[0]);
|
|
10
|
+
if (name === "table")
|
|
11
|
+
return formatConsoleTable(args[0], args[1]);
|
|
12
|
+
const prefix = name === "warn" ? "[warn] " : name === "error" ? "[error] " : name === "debug" ? "[debug] " : "";
|
|
13
|
+
return `${prefix}${args.map((arg) => formatConsoleArgument(arg)).join(" ")}`;
|
|
14
|
+
};
|
|
15
|
+
const formatConsoleArgument = (value) => {
|
|
16
|
+
if (value === undefined)
|
|
17
|
+
return "undefined";
|
|
18
|
+
if (typeof value === "string")
|
|
19
|
+
return value;
|
|
20
|
+
return formatConsoleValue(value, new Set(), 0);
|
|
21
|
+
};
|
|
22
|
+
const formatConsoleValue = (value, seen, depth) => {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return "null";
|
|
25
|
+
if (typeof value === "string")
|
|
26
|
+
return JSON.stringify(value);
|
|
27
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
28
|
+
return String(value);
|
|
29
|
+
if (typeof value !== "object")
|
|
30
|
+
return String(value);
|
|
31
|
+
if (value instanceof CodeModePromise)
|
|
32
|
+
return "[Promise (await it to get its value)]";
|
|
33
|
+
if (value instanceof CodeModeDate)
|
|
34
|
+
return coerceToString(value);
|
|
35
|
+
if (value instanceof CodeModeRegExp)
|
|
36
|
+
return coerceToString(value);
|
|
37
|
+
if (value instanceof CodeModeURL)
|
|
38
|
+
return coerceToString(value);
|
|
39
|
+
if (value instanceof CodeModeURLSearchParams)
|
|
40
|
+
return coerceToString(value);
|
|
41
|
+
if (depth > MAX_CONSOLE_DEPTH)
|
|
42
|
+
return "...";
|
|
43
|
+
if (seen.has(value))
|
|
44
|
+
return "[Circular]";
|
|
45
|
+
if (value instanceof CodeModeMap) {
|
|
46
|
+
seen.add(value);
|
|
47
|
+
try {
|
|
48
|
+
const entries = Array.from(value.map.entries(), ([key, item]) => [key, item]);
|
|
49
|
+
return `Map(${value.map.size}) ${formatConsoleValue(entries, seen, depth + 1)}`;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
seen.delete(value);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (value instanceof CodeModeSet) {
|
|
56
|
+
seen.add(value);
|
|
57
|
+
try {
|
|
58
|
+
return `Set(${value.set.size}) ${formatConsoleValue(Array.from(value.set.values()), seen, depth + 1)}`;
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
seen.delete(value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (isRuntimeReference(value))
|
|
65
|
+
return "[opaque reference]";
|
|
66
|
+
seen.add(value);
|
|
67
|
+
try {
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
return `[${value.map((item) => formatConsoleValue(item, seen, depth + 1)).join(",")}]`;
|
|
70
|
+
}
|
|
71
|
+
return `{${Object.entries(value)
|
|
72
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${formatConsoleValue(item, seen, depth + 1)}`)
|
|
73
|
+
.join(",")}}`;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
seen.delete(value);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const formatConsoleTable = (value, columnsArgument) => {
|
|
80
|
+
if (value === undefined)
|
|
81
|
+
return "undefined";
|
|
82
|
+
if (containsOpaqueReference(value))
|
|
83
|
+
return "[opaque reference]";
|
|
84
|
+
const data = boundedData(value, "console.table argument");
|
|
85
|
+
const columns = consoleTableColumns(columnsArgument);
|
|
86
|
+
const rows = consoleTableRows(data, columns);
|
|
87
|
+
const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values))));
|
|
88
|
+
const header = ["(index)", ...keys].join("\t");
|
|
89
|
+
return [
|
|
90
|
+
header,
|
|
91
|
+
...rows.map((row) => [row.index, ...keys.map((key) => formatConsoleTableCell(row.values[key]))].join("\t")),
|
|
92
|
+
].join("\n");
|
|
93
|
+
};
|
|
94
|
+
const consoleTableColumns = (value) => {
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (containsRuntimeReference(value))
|
|
98
|
+
return undefined;
|
|
99
|
+
const columns = copyOut(copyIn(value, "console.table columns"), "nullify");
|
|
100
|
+
return Array.isArray(columns) ? columns.map((column) => String(column)) : undefined;
|
|
101
|
+
};
|
|
102
|
+
const consoleTableRows = (data, columns) => {
|
|
103
|
+
if (Array.isArray(data)) {
|
|
104
|
+
return data.map((item, index) => ({ index: String(index), values: consoleTableValues(item, columns) }));
|
|
105
|
+
}
|
|
106
|
+
if (data !== null && typeof data === "object" && !isCodeModeValue(data)) {
|
|
107
|
+
return Object.entries(data).map(([index, item]) => ({ index, values: consoleTableValues(item, columns) }));
|
|
108
|
+
}
|
|
109
|
+
return [{ index: "0", values: { Value: data } }];
|
|
110
|
+
};
|
|
111
|
+
const consoleTableValues = (value, columns) => {
|
|
112
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !isCodeModeValue(value)) {
|
|
113
|
+
const source = value;
|
|
114
|
+
if (columns !== undefined)
|
|
115
|
+
return Object.fromEntries(columns.map((column) => [column, source[column]]));
|
|
116
|
+
return Object.fromEntries(Object.entries(source));
|
|
117
|
+
}
|
|
118
|
+
return { Value: value };
|
|
119
|
+
};
|
|
120
|
+
const formatConsoleTableCell = (value) => {
|
|
121
|
+
if (value === undefined)
|
|
122
|
+
return "";
|
|
123
|
+
if (typeof value === "string")
|
|
124
|
+
return value;
|
|
125
|
+
return formatConsoleValue(value, new Set(), 0);
|
|
126
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AstNode } from "../interpreter/model.js";
|
|
2
|
+
import { CodeModeDate } from "../values.js";
|
|
3
|
+
export declare const dateMethods: Set<string>;
|
|
4
|
+
export declare const dateStatics: Set<string>;
|
|
5
|
+
export declare const invokeDateStatic: (name: string, args: Array<unknown>, node: AstNode) => number;
|
|
6
|
+
export declare const dateSetterArgumentCount: (name: string) => number | undefined;
|
|
7
|
+
export declare const invokeDateMethod: (value: CodeModeDate, name: string, args: Array<number>, node: AstNode, initialTime?: number) => unknown;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { InterpreterRuntimeError } from "../interpreter/model.js";
|
|
2
|
+
import { CodeModeDate } from "../values.js";
|
|
3
|
+
import { coerceToNumber, coerceToString } from "./value.js";
|
|
4
|
+
const dateSetterArguments = new Map([
|
|
5
|
+
["setTime", 1],
|
|
6
|
+
["setMilliseconds", 1],
|
|
7
|
+
["setUTCMilliseconds", 1],
|
|
8
|
+
["setSeconds", 2],
|
|
9
|
+
["setUTCSeconds", 2],
|
|
10
|
+
["setMinutes", 3],
|
|
11
|
+
["setUTCMinutes", 3],
|
|
12
|
+
["setHours", 4],
|
|
13
|
+
["setUTCHours", 4],
|
|
14
|
+
["setDate", 1],
|
|
15
|
+
["setUTCDate", 1],
|
|
16
|
+
["setMonth", 2],
|
|
17
|
+
["setUTCMonth", 2],
|
|
18
|
+
["setFullYear", 3],
|
|
19
|
+
["setUTCFullYear", 3],
|
|
20
|
+
]);
|
|
21
|
+
export const dateMethods = new Set([
|
|
22
|
+
"getTime",
|
|
23
|
+
"valueOf",
|
|
24
|
+
"toISOString",
|
|
25
|
+
"toJSON",
|
|
26
|
+
"toString",
|
|
27
|
+
"toUTCString",
|
|
28
|
+
"toGMTString",
|
|
29
|
+
"getFullYear",
|
|
30
|
+
"getMonth",
|
|
31
|
+
"getDate",
|
|
32
|
+
"getDay",
|
|
33
|
+
"getHours",
|
|
34
|
+
"getMinutes",
|
|
35
|
+
"getSeconds",
|
|
36
|
+
"getMilliseconds",
|
|
37
|
+
"getUTCFullYear",
|
|
38
|
+
"getUTCMonth",
|
|
39
|
+
"getUTCDate",
|
|
40
|
+
"getUTCDay",
|
|
41
|
+
"getUTCHours",
|
|
42
|
+
"getUTCMinutes",
|
|
43
|
+
"getUTCSeconds",
|
|
44
|
+
"getUTCMilliseconds",
|
|
45
|
+
"getTimezoneOffset",
|
|
46
|
+
...dateSetterArguments.keys(),
|
|
47
|
+
]);
|
|
48
|
+
export const dateStatics = new Set(["now", "parse", "UTC"]);
|
|
49
|
+
export const invokeDateStatic = (name, args, node) => {
|
|
50
|
+
switch (name) {
|
|
51
|
+
case "now":
|
|
52
|
+
return Date.now();
|
|
53
|
+
case "parse":
|
|
54
|
+
return Date.parse(coerceToString(args[0]));
|
|
55
|
+
case "UTC":
|
|
56
|
+
return Date.UTC(...args.map((arg) => coerceToNumber(arg)));
|
|
57
|
+
default:
|
|
58
|
+
throw new InterpreterRuntimeError(`Date.${name} is not available.`, node);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export const dateSetterArgumentCount = (name) => dateSetterArguments.get(name);
|
|
62
|
+
export const invokeDateMethod = (value, name, args, node, initialTime = value.time) => {
|
|
63
|
+
const hosted = new Date(initialTime);
|
|
64
|
+
switch (name) {
|
|
65
|
+
case "getTime":
|
|
66
|
+
case "valueOf":
|
|
67
|
+
return value.time;
|
|
68
|
+
case "toISOString":
|
|
69
|
+
if (!Number.isFinite(value.time))
|
|
70
|
+
throw new InterpreterRuntimeError("Invalid time value.", node).as("RangeError");
|
|
71
|
+
return hosted.toISOString();
|
|
72
|
+
case "toJSON":
|
|
73
|
+
return Number.isFinite(value.time) ? hosted.toISOString() : null;
|
|
74
|
+
case "toString":
|
|
75
|
+
return coerceToString(value);
|
|
76
|
+
case "toUTCString":
|
|
77
|
+
case "toGMTString":
|
|
78
|
+
return hosted.toUTCString();
|
|
79
|
+
case "getFullYear":
|
|
80
|
+
return hosted.getFullYear();
|
|
81
|
+
case "getMonth":
|
|
82
|
+
return hosted.getMonth();
|
|
83
|
+
case "getDate":
|
|
84
|
+
return hosted.getDate();
|
|
85
|
+
case "getDay":
|
|
86
|
+
return hosted.getDay();
|
|
87
|
+
case "getHours":
|
|
88
|
+
return hosted.getHours();
|
|
89
|
+
case "getMinutes":
|
|
90
|
+
return hosted.getMinutes();
|
|
91
|
+
case "getSeconds":
|
|
92
|
+
return hosted.getSeconds();
|
|
93
|
+
case "getMilliseconds":
|
|
94
|
+
return hosted.getMilliseconds();
|
|
95
|
+
case "getUTCFullYear":
|
|
96
|
+
return hosted.getUTCFullYear();
|
|
97
|
+
case "getUTCMonth":
|
|
98
|
+
return hosted.getUTCMonth();
|
|
99
|
+
case "getUTCDate":
|
|
100
|
+
return hosted.getUTCDate();
|
|
101
|
+
case "getUTCDay":
|
|
102
|
+
return hosted.getUTCDay();
|
|
103
|
+
case "getUTCHours":
|
|
104
|
+
return hosted.getUTCHours();
|
|
105
|
+
case "getUTCMinutes":
|
|
106
|
+
return hosted.getUTCMinutes();
|
|
107
|
+
case "getUTCSeconds":
|
|
108
|
+
return hosted.getUTCSeconds();
|
|
109
|
+
case "getUTCMilliseconds":
|
|
110
|
+
return hosted.getUTCMilliseconds();
|
|
111
|
+
case "getTimezoneOffset":
|
|
112
|
+
return hosted.getTimezoneOffset();
|
|
113
|
+
case "setTime":
|
|
114
|
+
return updateDate(value, hosted.setTime(args[0]));
|
|
115
|
+
case "setMilliseconds":
|
|
116
|
+
return updateDate(value, hosted.setMilliseconds(args[0]));
|
|
117
|
+
case "setUTCMilliseconds":
|
|
118
|
+
return updateDate(value, hosted.setUTCMilliseconds(args[0]));
|
|
119
|
+
case "setSeconds":
|
|
120
|
+
if (args.length < 2)
|
|
121
|
+
return updateDate(value, hosted.setSeconds(args[0]));
|
|
122
|
+
return updateDate(value, hosted.setSeconds(args[0], args[1]));
|
|
123
|
+
case "setUTCSeconds":
|
|
124
|
+
if (args.length < 2)
|
|
125
|
+
return updateDate(value, hosted.setUTCSeconds(args[0]));
|
|
126
|
+
return updateDate(value, hosted.setUTCSeconds(args[0], args[1]));
|
|
127
|
+
case "setMinutes":
|
|
128
|
+
if (args.length < 2)
|
|
129
|
+
return updateDate(value, hosted.setMinutes(args[0]));
|
|
130
|
+
if (args.length < 3)
|
|
131
|
+
return updateDate(value, hosted.setMinutes(args[0], args[1]));
|
|
132
|
+
return updateDate(value, hosted.setMinutes(args[0], args[1], args[2]));
|
|
133
|
+
case "setUTCMinutes":
|
|
134
|
+
if (args.length < 2)
|
|
135
|
+
return updateDate(value, hosted.setUTCMinutes(args[0]));
|
|
136
|
+
if (args.length < 3)
|
|
137
|
+
return updateDate(value, hosted.setUTCMinutes(args[0], args[1]));
|
|
138
|
+
return updateDate(value, hosted.setUTCMinutes(args[0], args[1], args[2]));
|
|
139
|
+
case "setHours":
|
|
140
|
+
if (args.length < 2)
|
|
141
|
+
return updateDate(value, hosted.setHours(args[0]));
|
|
142
|
+
if (args.length < 3)
|
|
143
|
+
return updateDate(value, hosted.setHours(args[0], args[1]));
|
|
144
|
+
if (args.length < 4)
|
|
145
|
+
return updateDate(value, hosted.setHours(args[0], args[1], args[2]));
|
|
146
|
+
return updateDate(value, hosted.setHours(args[0], args[1], args[2], args[3]));
|
|
147
|
+
case "setUTCHours":
|
|
148
|
+
if (args.length < 2)
|
|
149
|
+
return updateDate(value, hosted.setUTCHours(args[0]));
|
|
150
|
+
if (args.length < 3)
|
|
151
|
+
return updateDate(value, hosted.setUTCHours(args[0], args[1]));
|
|
152
|
+
if (args.length < 4)
|
|
153
|
+
return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2]));
|
|
154
|
+
return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2], args[3]));
|
|
155
|
+
case "setDate":
|
|
156
|
+
return updateDate(value, hosted.setDate(args[0]));
|
|
157
|
+
case "setUTCDate":
|
|
158
|
+
return updateDate(value, hosted.setUTCDate(args[0]));
|
|
159
|
+
case "setMonth":
|
|
160
|
+
if (args.length < 2)
|
|
161
|
+
return updateDate(value, hosted.setMonth(args[0]));
|
|
162
|
+
return updateDate(value, hosted.setMonth(args[0], args[1]));
|
|
163
|
+
case "setUTCMonth":
|
|
164
|
+
if (args.length < 2)
|
|
165
|
+
return updateDate(value, hosted.setUTCMonth(args[0]));
|
|
166
|
+
return updateDate(value, hosted.setUTCMonth(args[0], args[1]));
|
|
167
|
+
case "setFullYear":
|
|
168
|
+
if (args.length < 2)
|
|
169
|
+
return updateDate(value, hosted.setFullYear(args[0]));
|
|
170
|
+
if (args.length < 3)
|
|
171
|
+
return updateDate(value, hosted.setFullYear(args[0], args[1]));
|
|
172
|
+
return updateDate(value, hosted.setFullYear(args[0], args[1], args[2]));
|
|
173
|
+
case "setUTCFullYear":
|
|
174
|
+
if (args.length < 2)
|
|
175
|
+
return updateDate(value, hosted.setUTCFullYear(args[0]));
|
|
176
|
+
if (args.length < 3)
|
|
177
|
+
return updateDate(value, hosted.setUTCFullYear(args[0], args[1]));
|
|
178
|
+
return updateDate(value, hosted.setUTCFullYear(args[0], args[1], args[2]));
|
|
179
|
+
default:
|
|
180
|
+
throw new InterpreterRuntimeError(`Date method '${name}' is not available.`, node);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const updateDate = (value, time) => {
|
|
184
|
+
value.time = time;
|
|
185
|
+
return time;
|
|
186
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { CallbackRunner } from "../interpreter/methods.js";
|
|
3
|
+
import { type AstNode } from "../interpreter/model.js";
|
|
4
|
+
export declare const jsonStatics: Set<string>;
|
|
5
|
+
export type JsonMethodName = "parse" | "stringify";
|
|
6
|
+
export declare const invokeJsonMethod: <R>(runner: CallbackRunner<R>, name: JsonMethodName, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { applyCollectionCallback } from "../interpreter/methods.js";
|
|
3
|
+
import { InterpreterRuntimeError } from "../interpreter/model.js";
|
|
4
|
+
import { typeofValue } from "../interpreter/references.js";
|
|
5
|
+
import { copyIn, copyOut } from "../tool-runtime.js";
|
|
6
|
+
import { CodeModeDate, CodeModeMap, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "../values.js";
|
|
7
|
+
export const jsonStatics = new Set(["parse", "stringify"]);
|
|
8
|
+
export const invokeJsonMethod = (runner, name, args, node) => {
|
|
9
|
+
return name === "parse" ? parse(runner, args, node) : stringify(runner, args, node);
|
|
10
|
+
};
|
|
11
|
+
const parse = (runner, args, node) => {
|
|
12
|
+
const text = args[0];
|
|
13
|
+
if (typeof text !== "string")
|
|
14
|
+
throw new InterpreterRuntimeError("JSON.parse expects a string.", node);
|
|
15
|
+
const parsed = (() => {
|
|
16
|
+
try {
|
|
17
|
+
return copyIn(JSON.parse(text), "JSON.parse result");
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw new InterpreterRuntimeError(`JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`, node).as("SyntaxError");
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
if (typeofValue(args[1]) !== "function")
|
|
24
|
+
return Effect.succeed(parsed);
|
|
25
|
+
const apply = applyCollectionCallback(runner, args[1], "JSON.parse", node);
|
|
26
|
+
const root = Object.create(null);
|
|
27
|
+
root[""] = parsed;
|
|
28
|
+
const visit = (holder, key) => Effect.gen(function* () {
|
|
29
|
+
const value = holder[key];
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
const length = value.length;
|
|
32
|
+
for (let index = 0; index < length; index += 1) {
|
|
33
|
+
const revived = yield* visit(value, String(index));
|
|
34
|
+
if (revived === undefined)
|
|
35
|
+
Reflect.deleteProperty(value, index);
|
|
36
|
+
else
|
|
37
|
+
value[index] = revived;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (isPlainObject(value)) {
|
|
41
|
+
for (const name of Object.keys(value)) {
|
|
42
|
+
const revived = yield* visit(value, name);
|
|
43
|
+
if (revived === undefined)
|
|
44
|
+
Reflect.deleteProperty(value, name);
|
|
45
|
+
else
|
|
46
|
+
value[name] = revived;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return yield* apply([key, value]);
|
|
50
|
+
});
|
|
51
|
+
return visit(root, "");
|
|
52
|
+
};
|
|
53
|
+
const stringify = (runner, args, node) => {
|
|
54
|
+
const space = args[2];
|
|
55
|
+
const indent = typeof space === "number" || typeof space === "string" ? space : undefined;
|
|
56
|
+
const replacer = args[1];
|
|
57
|
+
const callable = typeofValue(replacer) === "function";
|
|
58
|
+
const checked = copyIn(args[0], "JSON.stringify value", callable);
|
|
59
|
+
const input = callable ? args[0] : checked;
|
|
60
|
+
if (Array.isArray(replacer)) {
|
|
61
|
+
const properties = replacer
|
|
62
|
+
.filter((item) => typeof item === "string" || typeof item === "number")
|
|
63
|
+
.map(String);
|
|
64
|
+
return Effect.succeed(JSON.stringify(copyOut(input, "json"), properties, indent));
|
|
65
|
+
}
|
|
66
|
+
if (!callable) {
|
|
67
|
+
return Effect.succeed(JSON.stringify(copyOut(input, "json"), null, indent));
|
|
68
|
+
}
|
|
69
|
+
const apply = applyCollectionCallback(runner, replacer, "JSON.stringify", node);
|
|
70
|
+
const root = Object.create(null);
|
|
71
|
+
root[""] = input;
|
|
72
|
+
const stack = new Set();
|
|
73
|
+
const visit = (holder, key) => Effect.gen(function* () {
|
|
74
|
+
const value = yield* apply([key, toJSONValue(holder[key])]);
|
|
75
|
+
if (value === undefined || typeofValue(value) === "function")
|
|
76
|
+
return undefined;
|
|
77
|
+
copyIn(value, "JSON.stringify replacer result", true);
|
|
78
|
+
if (typeof value === "number")
|
|
79
|
+
return Number.isFinite(value) ? value : null;
|
|
80
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
81
|
+
return value;
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
if (stack.has(value))
|
|
84
|
+
throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError");
|
|
85
|
+
stack.add(value);
|
|
86
|
+
const result = [];
|
|
87
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
88
|
+
result.push((yield* visit(value, String(index))) ?? null);
|
|
89
|
+
}
|
|
90
|
+
stack.delete(value);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
if (!isPlainObject(value))
|
|
94
|
+
return {};
|
|
95
|
+
if (stack.has(value))
|
|
96
|
+
throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError");
|
|
97
|
+
stack.add(value);
|
|
98
|
+
const result = Object.create(null);
|
|
99
|
+
for (const name of Object.keys(value)) {
|
|
100
|
+
const item = yield* visit(value, name);
|
|
101
|
+
if (item !== undefined)
|
|
102
|
+
result[name] = item;
|
|
103
|
+
}
|
|
104
|
+
stack.delete(value);
|
|
105
|
+
return result;
|
|
106
|
+
});
|
|
107
|
+
return Effect.map(visit(root, ""), (value) => JSON.stringify(value, null, indent));
|
|
108
|
+
};
|
|
109
|
+
const toJSONValue = (value) => {
|
|
110
|
+
if (value instanceof CodeModeDate) {
|
|
111
|
+
return Number.isFinite(value.time) ? new Date(value.time).toISOString() : null;
|
|
112
|
+
}
|
|
113
|
+
if (value instanceof CodeModeURL)
|
|
114
|
+
return value.url.href;
|
|
115
|
+
return value;
|
|
116
|
+
};
|
|
117
|
+
const isPlainObject = (value) => value !== null &&
|
|
118
|
+
typeof value === "object" &&
|
|
119
|
+
!(value instanceof CodeModeDate) &&
|
|
120
|
+
!(value instanceof CodeModeRegExp) &&
|
|
121
|
+
!(value instanceof CodeModeMap) &&
|
|
122
|
+
!(value instanceof CodeModeSet) &&
|
|
123
|
+
!(value instanceof CodeModeURL) &&
|
|
124
|
+
!(value instanceof CodeModeURLSearchParams);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { type SyncIteratorRunner } from "../interpreter/iterator.js";
|
|
3
|
+
import { type AstNode } from "../interpreter/model.js";
|
|
4
|
+
declare global {
|
|
5
|
+
interface Math {
|
|
6
|
+
sumPrecise(values: Iterable<number>): number;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare const mathConstants: Set<string>;
|
|
10
|
+
export declare const mathMethods: Set<string>;
|
|
11
|
+
export declare const invokeMathMethod: (name: string, args: Array<unknown>, node: AstNode) => number;
|
|
12
|
+
export declare const invokeMathSumPrecise: <R>(runner: SyncIteratorRunner<R>, source: unknown, node: AstNode) => Effect.Effect<number, unknown, R>;
|