@doki-land/dejavu-engine 0.0.14 → 0.0.15
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/runtime/errors.d.ts +15 -0
- package/dist/runtime/errors.js +22 -0
- package/dist/runtime/filter.js +10 -4
- package/dist/runtime/function.d.ts +1 -0
- package/dist/runtime/function.js +13 -7
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/test.d.ts +1 -0
- package/dist/runtime/test.js +20 -14
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured runtime error for generated AOT modules.
|
|
3
|
+
*
|
|
4
|
+
* Generated code never throws a bare `Error`: every failure carries the stable
|
|
5
|
+
* diagnostic `code`, the `render` stage, structured `args` and a human-readable
|
|
6
|
+
* message so hosts can classify errors without parsing `message`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DejavuRuntimeError extends Error {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
readonly stage = "render";
|
|
11
|
+
readonly args: Record<string, unknown>;
|
|
12
|
+
constructor(code: string, detail?: string, args?: Record<string, unknown>);
|
|
13
|
+
}
|
|
14
|
+
/** Build a structured render error. */
|
|
15
|
+
export declare function runtimeError(code: string, detail?: string, args?: Record<string, unknown>): DejavuRuntimeError;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured runtime error for generated AOT modules.
|
|
3
|
+
*
|
|
4
|
+
* Generated code never throws a bare `Error`: every failure carries the stable
|
|
5
|
+
* diagnostic `code`, the `render` stage, structured `args` and a human-readable
|
|
6
|
+
* message so hosts can classify errors without parsing `message`.
|
|
7
|
+
*/
|
|
8
|
+
export class DejavuRuntimeError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
stage = "render";
|
|
11
|
+
args;
|
|
12
|
+
constructor(code, detail, args) {
|
|
13
|
+
super(detail ? `${code}: ${detail}` : code);
|
|
14
|
+
this.name = "DejavuRuntimeError";
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.args = args ?? {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Build a structured render error. */
|
|
20
|
+
export function runtimeError(code, detail, args) {
|
|
21
|
+
return new DejavuRuntimeError(code, detail, args);
|
|
22
|
+
}
|
package/dist/runtime/filter.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { htmlEscape } from "./escape.js";
|
|
2
|
+
import { runtimeError } from "./errors.js";
|
|
2
3
|
import { valueToString } from "./value.js";
|
|
3
4
|
/** 与 Rust `dejavu_ir::registry::FILTERS` 同序同构的静态描述。 */
|
|
4
5
|
export const FILTERS = [
|
|
@@ -20,11 +21,16 @@ export function filterSpec(name) {
|
|
|
20
21
|
export function applyFilter(name, value, args) {
|
|
21
22
|
const spec = filterSpec(name);
|
|
22
23
|
if (!spec) {
|
|
23
|
-
throw
|
|
24
|
+
throw runtimeError("dejavu.template.unknown-filter", name, { filter: name });
|
|
24
25
|
}
|
|
25
26
|
if (args.length < spec.minArgs || args.length > spec.maxArgs) {
|
|
26
|
-
throw
|
|
27
|
-
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}
|
|
27
|
+
throw runtimeError("dejavu.template.filter-arity", `${spec.name} expects ` +
|
|
28
|
+
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}`, {
|
|
29
|
+
filter: spec.name,
|
|
30
|
+
minArgs: spec.minArgs,
|
|
31
|
+
maxArgs: spec.maxArgs,
|
|
32
|
+
got: args.length,
|
|
33
|
+
});
|
|
28
34
|
}
|
|
29
35
|
switch (name) {
|
|
30
36
|
case "escape":
|
|
@@ -77,7 +83,7 @@ export function applyFilter(name, value, args) {
|
|
|
77
83
|
return slugify(valueToString(value));
|
|
78
84
|
default:
|
|
79
85
|
// Unreachable: `filterSpec` already rejected unknown names.
|
|
80
|
-
throw
|
|
86
|
+
throw runtimeError("dejavu.template.unknown-filter", name);
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
/**
|
package/dist/runtime/function.js
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* 与 Rust `dejavu_ir::registry::FUNCTIONS` 和 `builtins::call_function` 对齐。
|
|
5
5
|
* 仅允许 `name(args)` 形式的裸标识符调用;成员调用与未知名字一律报错。
|
|
6
6
|
*/
|
|
7
|
+
import { runtimeError } from "./errors.js";
|
|
7
8
|
/** 与 Rust `dejavu_ir::registry::FUNCTIONS` 同序同构的静态描述。 */
|
|
8
9
|
export const FUNCTIONS = [
|
|
9
|
-
{ name: "range", aliases: [], minArgs: 2, maxArgs: 3 },
|
|
10
|
-
{ name: "min", aliases: [], minArgs: 2, maxArgs: 2 },
|
|
11
|
-
{ name: "max", aliases: [], minArgs: 2, maxArgs: 2 },
|
|
10
|
+
{ name: "range", aliases: [], minArgs: 2, maxArgs: 3, capability: "pure" },
|
|
11
|
+
{ name: "min", aliases: [], minArgs: 2, maxArgs: 2, capability: "pure" },
|
|
12
|
+
{ name: "max", aliases: [], minArgs: 2, maxArgs: 2, capability: "pure" },
|
|
12
13
|
];
|
|
13
14
|
/** `range` 允许产出的最大元素数,与 Rust `RANGE_LIMIT` 一致。 */
|
|
14
15
|
const RANGE_LIMIT = 10_000;
|
|
@@ -18,11 +19,16 @@ export function functionSpec(name) {
|
|
|
18
19
|
export function callFunction(name, args) {
|
|
19
20
|
const spec = functionSpec(name);
|
|
20
21
|
if (!spec) {
|
|
21
|
-
throw
|
|
22
|
+
throw runtimeError("dejavu.template.unknown-function", name, { function: name });
|
|
22
23
|
}
|
|
23
24
|
if (args.length < spec.minArgs || args.length > spec.maxArgs) {
|
|
24
|
-
throw
|
|
25
|
-
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}
|
|
25
|
+
throw runtimeError("dejavu.template.function-arity", `${spec.name} expects ` +
|
|
26
|
+
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}`, {
|
|
27
|
+
function: spec.name,
|
|
28
|
+
minArgs: spec.minArgs,
|
|
29
|
+
maxArgs: spec.maxArgs,
|
|
30
|
+
got: args.length,
|
|
31
|
+
});
|
|
26
32
|
}
|
|
27
33
|
switch (spec.name) {
|
|
28
34
|
case "range":
|
|
@@ -33,7 +39,7 @@ export function callFunction(name, args) {
|
|
|
33
39
|
return numericPair(args, false);
|
|
34
40
|
default:
|
|
35
41
|
// Unreachable: `functionSpec` already rejected unknown names.
|
|
36
|
-
throw
|
|
42
|
+
throw runtimeError("dejavu.template.unknown-function", name);
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
/** `range(start, stop, step=1)`,非法输入按值模型规则返回 null。 */
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* 与 Rust `dejavu-codegen` Node stub 以及 `dejavu-types` 的 filter 系统语义一致。
|
|
6
6
|
*/
|
|
7
7
|
export { htmlEscape } from "./escape.js";
|
|
8
|
+
export { DejavuRuntimeError, runtimeError } from "./errors.js";
|
|
8
9
|
export { valueToString, isTruthy, valuesEqual } from "./value.js";
|
|
9
10
|
export { applyFilter } from "./filter.js";
|
|
10
11
|
export { FUNCTIONS, functionSpec, callFunction } from "./function.js";
|
package/dist/runtime/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* 与 Rust `dejavu-codegen` Node stub 以及 `dejavu-types` 的 filter 系统语义一致。
|
|
6
6
|
*/
|
|
7
7
|
export { htmlEscape } from "./escape.js";
|
|
8
|
+
export { DejavuRuntimeError, runtimeError } from "./errors.js";
|
|
8
9
|
export { valueToString, isTruthy, valuesEqual } from "./value.js";
|
|
9
10
|
export { applyFilter } from "./filter.js";
|
|
10
11
|
export { FUNCTIONS, functionSpec, callFunction } from "./function.js";
|
package/dist/runtime/test.d.ts
CHANGED
package/dist/runtime/test.js
CHANGED
|
@@ -5,19 +5,20 @@
|
|
|
5
5
|
* 语法为 `expr is name` / `expr is not name` / `expr is name(args)`,
|
|
6
6
|
* 本文件只负责对已求值的左值执行谓词。
|
|
7
7
|
*/
|
|
8
|
+
import { runtimeError } from "./errors.js";
|
|
8
9
|
import { isTruthy } from "./value.js";
|
|
9
10
|
/** 与 Rust `dejavu_ir::registry::TESTS` 同序同构的静态描述。 */
|
|
10
11
|
export const TESTS = [
|
|
11
|
-
{ name: "null", aliases: ["none"], minArgs: 0, maxArgs: 0 },
|
|
12
|
-
{ name: "truthy", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
13
|
-
{ name: "empty", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
14
|
-
{ name: "array", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
15
|
-
{ name: "object", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
16
|
-
{ name: "string", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
17
|
-
{ name: "number", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
18
|
-
{ name: "boolean", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
19
|
-
{ name: "even", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
20
|
-
{ name: "odd", aliases: [], minArgs: 0, maxArgs: 0 },
|
|
12
|
+
{ name: "null", aliases: ["none"], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
13
|
+
{ name: "truthy", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
14
|
+
{ name: "empty", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
15
|
+
{ name: "array", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
16
|
+
{ name: "object", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
17
|
+
{ name: "string", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
18
|
+
{ name: "number", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
19
|
+
{ name: "boolean", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
20
|
+
{ name: "even", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
21
|
+
{ name: "odd", aliases: [], minArgs: 0, maxArgs: 0, capability: "pure" },
|
|
21
22
|
];
|
|
22
23
|
export function testSpec(name) {
|
|
23
24
|
return TESTS.find((spec) => spec.name === name || spec.aliases.includes(name));
|
|
@@ -26,11 +27,16 @@ export function testSpec(name) {
|
|
|
26
27
|
export function applyTest(name, value, args, negated = false) {
|
|
27
28
|
const spec = testSpec(name);
|
|
28
29
|
if (!spec) {
|
|
29
|
-
throw
|
|
30
|
+
throw runtimeError("dejavu.template.unknown-test", name, { test: name });
|
|
30
31
|
}
|
|
31
32
|
if (args.length < spec.minArgs || args.length > spec.maxArgs) {
|
|
32
|
-
throw
|
|
33
|
-
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}
|
|
33
|
+
throw runtimeError("dejavu.template.test-arity", `${spec.name} expects ` +
|
|
34
|
+
`${spec.minArgs}..${spec.maxArgs} argument(s), got ${args.length}`, {
|
|
35
|
+
test: spec.name,
|
|
36
|
+
minArgs: spec.minArgs,
|
|
37
|
+
maxArgs: spec.maxArgs,
|
|
38
|
+
got: args.length,
|
|
39
|
+
});
|
|
34
40
|
}
|
|
35
41
|
let result;
|
|
36
42
|
switch (spec.name) {
|
|
@@ -69,7 +75,7 @@ export function applyTest(name, value, args, negated = false) {
|
|
|
69
75
|
break;
|
|
70
76
|
default:
|
|
71
77
|
// Unreachable: `testSpec` already rejected unknown names.
|
|
72
|
-
throw
|
|
78
|
+
throw runtimeError("dejavu.template.unknown-test", name);
|
|
73
79
|
}
|
|
74
80
|
return result !== negated;
|
|
75
81
|
}
|