@telorun/cel 0.0.0-stage → 0.108.0
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/LICENSE +17 -0
- package/README.md +281 -2
- package/dist/activation.d.ts +27 -0
- package/dist/activation.d.ts.map +1 -0
- package/dist/activation.js +24 -0
- package/dist/backend-runtime.d.ts +184 -0
- package/dist/backend-runtime.d.ts.map +1 -0
- package/dist/backend-runtime.js +425 -0
- package/dist/bounded-cache.d.ts +21 -0
- package/dist/bounded-cache.d.ts.map +1 -0
- package/dist/bounded-cache.js +42 -0
- package/dist/catalog-runtime.d.ts +59 -0
- package/dist/catalog-runtime.d.ts.map +1 -0
- package/dist/catalog-runtime.js +786 -0
- package/dist/cel-expression.d.ts +32 -0
- package/dist/cel-expression.d.ts.map +1 -0
- package/dist/cel-expression.js +29 -0
- package/dist/cel-map-value.d.ts +47 -0
- package/dist/cel-map-value.d.ts.map +1 -0
- package/dist/cel-map-value.js +85 -0
- package/dist/cel-program.d.ts +44 -0
- package/dist/cel-program.d.ts.map +1 -0
- package/dist/cel-program.js +72 -0
- package/dist/cel-type.d.ts +131 -0
- package/dist/cel-type.d.ts.map +1 -0
- package/dist/cel-type.js +293 -0
- package/dist/cel-value.d.ts +166 -0
- package/dist/cel-value.d.ts.map +1 -0
- package/dist/cel-value.js +225 -0
- package/dist/check-diagnostic.d.ts +54 -0
- package/dist/check-diagnostic.d.ts.map +1 -0
- package/dist/check-diagnostic.js +66 -0
- package/dist/checker.d.ts +86 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +806 -0
- package/dist/closure-backend.d.ts +21 -0
- package/dist/closure-backend.d.ts.map +1 -0
- package/dist/closure-backend.js +487 -0
- package/dist/comprehension-bindings.d.ts +33 -0
- package/dist/comprehension-bindings.d.ts.map +1 -0
- package/dist/comprehension-bindings.js +50 -0
- package/dist/comprehension-runtime.d.ts +44 -0
- package/dist/comprehension-runtime.d.ts.map +1 -0
- package/dist/comprehension-runtime.js +137 -0
- package/dist/declared-chain.d.ts +35 -0
- package/dist/declared-chain.d.ts.map +1 -0
- package/dist/declared-chain.js +36 -0
- package/dist/duration-value.d.ts +70 -0
- package/dist/duration-value.d.ts.map +1 -0
- package/dist/duration-value.js +149 -0
- package/dist/emitted-module.d.ts +207 -0
- package/dist/emitted-module.d.ts.map +1 -0
- package/dist/emitted-module.js +359 -0
- package/dist/engine-version.d.ts +3 -0
- package/dist/engine-version.d.ts.map +1 -0
- package/dist/engine-version.js +8 -0
- package/dist/environment-digest.d.ts +44 -0
- package/dist/environment-digest.d.ts.map +1 -0
- package/dist/environment-digest.js +98 -0
- package/dist/environment.d.ts +291 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +474 -0
- package/dist/function-catalog.d.ts +66 -0
- package/dist/function-catalog.d.ts.map +1 -0
- package/dist/function-catalog.js +77 -0
- package/dist/function-registry.d.ts +118 -0
- package/dist/function-registry.d.ts.map +1 -0
- package/dist/function-registry.js +292 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/integer-arithmetic.d.ts +27 -0
- package/dist/integer-arithmetic.d.ts.map +1 -0
- package/dist/integer-arithmetic.js +58 -0
- package/dist/js-emitter.d.ts +133 -0
- package/dist/js-emitter.d.ts.map +1 -0
- package/dist/js-emitter.js +568 -0
- package/dist/json-schema-type.d.ts +182 -0
- package/dist/json-schema-type.d.ts.map +1 -0
- package/dist/json-schema-type.js +487 -0
- package/dist/json-text-scan.d.ts +28 -0
- package/dist/json-text-scan.d.ts.map +1 -0
- package/dist/json-text-scan.js +159 -0
- package/dist/lexer.d.ts +103 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +458 -0
- package/dist/macro-check.d.ts +41 -0
- package/dist/macro-check.d.ts.map +1 -0
- package/dist/macro-check.js +162 -0
- package/dist/macro-shape.d.ts +24 -0
- package/dist/macro-shape.d.ts.map +1 -0
- package/dist/macro-shape.js +55 -0
- package/dist/member-read.d.ts +89 -0
- package/dist/member-read.d.ts.map +1 -0
- package/dist/member-read.js +166 -0
- package/dist/namespace-resolution.d.ts +35 -0
- package/dist/namespace-resolution.d.ts.map +1 -0
- package/dist/namespace-resolution.js +160 -0
- package/dist/nominal-type.d.ts +63 -0
- package/dist/nominal-type.d.ts.map +1 -0
- package/dist/nominal-type.js +98 -0
- package/dist/nullable-access.d.ts +38 -0
- package/dist/nullable-access.d.ts.map +1 -0
- package/dist/nullable-access.js +93 -0
- package/dist/parse-limits.d.ts +26 -0
- package/dist/parse-limits.d.ts.map +1 -0
- package/dist/parse-limits.js +21 -0
- package/dist/parser.d.ts +48 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +503 -0
- package/dist/qualified-calls.d.ts +22 -0
- package/dist/qualified-calls.d.ts.map +1 -0
- package/dist/qualified-calls.js +27 -0
- package/dist/regular-expression.d.ts +48 -0
- package/dist/regular-expression.d.ts.map +1 -0
- package/dist/regular-expression.js +77 -0
- package/dist/reserved-words.d.ts +52 -0
- package/dist/reserved-words.d.ts.map +1 -0
- package/dist/reserved-words.js +77 -0
- package/dist/resolved-call.d.ts +46 -0
- package/dist/resolved-call.d.ts.map +1 -0
- package/dist/resolved-call.js +15 -0
- package/dist/root-references.d.ts +23 -0
- package/dist/root-references.d.ts.map +1 -0
- package/dist/root-references.js +120 -0
- package/dist/runtime-library.d.ts +67 -0
- package/dist/runtime-library.d.ts.map +1 -0
- package/dist/runtime-library.js +554 -0
- package/dist/serializer.d.ts +24 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +256 -0
- package/dist/sha256.d.ts +20 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +103 -0
- package/dist/signature.d.ts +72 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +61 -0
- package/dist/signatures/function-catalog.json +788 -0
- package/dist/signatures/standard-library.json +229 -0
- package/dist/standard-library.d.ts +41 -0
- package/dist/standard-library.d.ts.map +1 -0
- package/dist/standard-library.js +85 -0
- package/dist/syntax-diagnostic.d.ts +61 -0
- package/dist/syntax-diagnostic.d.ts.map +1 -0
- package/dist/syntax-diagnostic.js +28 -0
- package/dist/syntax-tree.d.ts +160 -0
- package/dist/syntax-tree.d.ts.map +1 -0
- package/dist/syntax-tree.js +58 -0
- package/dist/timestamp-value.d.ts +62 -0
- package/dist/timestamp-value.d.ts.map +1 -0
- package/dist/timestamp-value.js +238 -0
- package/dist/tree-equality.d.ts +15 -0
- package/dist/tree-equality.d.ts.map +1 -0
- package/dist/tree-equality.js +105 -0
- package/dist/type-expression.d.ts +42 -0
- package/dist/type-expression.d.ts.map +1 -0
- package/dist/type-expression.js +154 -0
- package/dist/value-equality.d.ts +38 -0
- package/dist/value-equality.d.ts.map +1 -0
- package/dist/value-equality.js +196 -0
- package/dist/value-text.d.ts +25 -0
- package/dist/value-text.d.ts.map +1 -0
- package/dist/value-text.js +44 -0
- package/dist/zoned-calendar.d.ts +61 -0
- package/dist/zoned-calendar.d.ts.map +1 -0
- package/dist/zoned-calendar.js +143 -0
- package/package.json +56 -3
- package/src/activation.ts +32 -0
- package/src/backend-runtime.ts +604 -0
- package/src/bounded-cache.ts +45 -0
- package/src/catalog-runtime.ts +921 -0
- package/src/cel-expression.ts +53 -0
- package/src/cel-map-value.ts +97 -0
- package/src/cel-program.ts +103 -0
- package/src/cel-type.ts +359 -0
- package/src/cel-value.ts +361 -0
- package/src/check-diagnostic.ts +104 -0
- package/src/checker.ts +1045 -0
- package/src/closure-backend.ts +547 -0
- package/src/comprehension-bindings.ts +66 -0
- package/src/comprehension-runtime.ts +157 -0
- package/src/declared-chain.ts +45 -0
- package/src/duration-value.ts +160 -0
- package/src/emitted-module.ts +494 -0
- package/src/engine-version.ts +9 -0
- package/src/environment-digest.ts +111 -0
- package/src/environment.ts +761 -0
- package/src/function-catalog.ts +140 -0
- package/src/function-registry.ts +341 -0
- package/src/index.ts +407 -0
- package/src/integer-arithmetic.ts +64 -0
- package/src/js-emitter.ts +721 -0
- package/src/json-schema-type.ts +664 -0
- package/src/json-text-scan.ts +163 -0
- package/src/lexer.ts +562 -0
- package/src/macro-check.ts +197 -0
- package/src/macro-shape.ts +66 -0
- package/src/member-read.ts +167 -0
- package/src/namespace-resolution.ts +167 -0
- package/src/nominal-type.ts +149 -0
- package/src/nullable-access.ts +95 -0
- package/src/parse-limits.ts +36 -0
- package/src/parser.ts +554 -0
- package/src/qualified-calls.ts +39 -0
- package/src/regular-expression.ts +101 -0
- package/src/reserved-words.ts +94 -0
- package/src/resolved-call.ts +47 -0
- package/src/root-references.ts +126 -0
- package/src/runtime-library.ts +639 -0
- package/src/serializer.ts +262 -0
- package/src/sha256.ts +112 -0
- package/src/signature.ts +127 -0
- package/src/signatures/function-catalog.json +788 -0
- package/src/signatures/standard-library.json +235 -0
- package/src/standard-library.ts +149 -0
- package/src/syntax-diagnostic.ts +72 -0
- package/src/syntax-tree.ts +229 -0
- package/src/timestamp-value.ts +310 -0
- package/src/tree-equality.ts +130 -0
- package/src/type-expression.ts +182 -0
- package/src/value-equality.ts +201 -0
- package/src/value-text.ts +45 -0
- package/src/zoned-calendar.ts +178 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named types a host registers — the one mechanism, with none of the vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* A nominal type is a name over a base type, with its own operators, comparisons,
|
|
5
|
+
* conversions and member functions, and with named **invariant** type parameters. It
|
|
6
|
+
* is not its base: a value of the base does not stand where the named type is wanted,
|
|
7
|
+
* and only what the definition declares applies to it. That is what makes a named type
|
|
8
|
+
* worth having — a slot that wants one refuses a plain value of the base, which is
|
|
9
|
+
* exactly what an engine typing by wrapper class cannot express.
|
|
10
|
+
*
|
|
11
|
+
* Invariance is deliberate: `Holder<string>` and `Holder<int>` are unrelated, so a
|
|
12
|
+
* type argument that differs is a mistake with its own diagnostic rather than a silent
|
|
13
|
+
* widening to the base.
|
|
14
|
+
*
|
|
15
|
+
* `Self` inside a definition names the type being defined, with its own parameters
|
|
16
|
+
* applied, so a member can answer its own type without repeating it.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { CelType, NominalType } from "./cel-type.js";
|
|
20
|
+
import { parameterOf } from "./cel-type.js";
|
|
21
|
+
import type { NominalResolver } from "./type-expression.js";
|
|
22
|
+
import { parseTypeExpression } from "./type-expression.js";
|
|
23
|
+
|
|
24
|
+
export interface NominalOperatorDeclaration {
|
|
25
|
+
readonly operator: string;
|
|
26
|
+
/** Type expressions; `Self` names the type being defined. */
|
|
27
|
+
readonly parameters: readonly string[];
|
|
28
|
+
readonly returns: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface NominalTypeDefinition {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
/** The type expression a value of this type is, underneath. */
|
|
34
|
+
readonly base: string;
|
|
35
|
+
/** Invariant type parameter names, each a single capital letter. */
|
|
36
|
+
readonly parameters?: readonly string[];
|
|
37
|
+
/** Operators over the type, written with `Self`. */
|
|
38
|
+
readonly operators?: readonly NominalOperatorDeclaration[];
|
|
39
|
+
/** Operator symbols to register as `(Self, Self): bool`. */
|
|
40
|
+
readonly comparisons?: readonly string[];
|
|
41
|
+
/** Conversion signatures, e.g. `string(Self): string`. */
|
|
42
|
+
readonly conversions?: readonly string[];
|
|
43
|
+
/** Member signatures, e.g. `Self.scaled(int): Self`. */
|
|
44
|
+
readonly members?: readonly string[];
|
|
45
|
+
readonly description?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const NAME = /^[A-Za-z_][A-Za-z0-9_.]*$/;
|
|
49
|
+
const PARAMETER = /^[A-Z]$/;
|
|
50
|
+
const LANGUAGE_NAMES = new Set([
|
|
51
|
+
"dyn",
|
|
52
|
+
"int",
|
|
53
|
+
"uint",
|
|
54
|
+
"double",
|
|
55
|
+
"bool",
|
|
56
|
+
"string",
|
|
57
|
+
"bytes",
|
|
58
|
+
"null",
|
|
59
|
+
"null_type",
|
|
60
|
+
"type",
|
|
61
|
+
"list",
|
|
62
|
+
"map",
|
|
63
|
+
"optional",
|
|
64
|
+
"timestamp",
|
|
65
|
+
"duration",
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
export class CelTypeRegistrationError extends Error {
|
|
69
|
+
constructor(message: string) {
|
|
70
|
+
super(message);
|
|
71
|
+
this.name = "CelTypeRegistrationError";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A registered nominal type: its definition, its base, and the type `Self` names. */
|
|
76
|
+
export interface RegisteredType {
|
|
77
|
+
readonly definition: NominalTypeDefinition;
|
|
78
|
+
readonly base: CelType;
|
|
79
|
+
readonly parameters: readonly string[];
|
|
80
|
+
/** The type with its own parameters applied — what `Self` resolves to. */
|
|
81
|
+
readonly self: NominalType;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function validateTypeName(name: string): void {
|
|
85
|
+
if (!NAME.test(name)) {
|
|
86
|
+
throw new CelTypeRegistrationError(`${JSON.stringify(name)} is not spelled as a type name`);
|
|
87
|
+
}
|
|
88
|
+
if (LANGUAGE_NAMES.has(name)) {
|
|
89
|
+
throw new CelTypeRegistrationError(`${JSON.stringify(name)} is a type of the language and cannot be redefined`);
|
|
90
|
+
}
|
|
91
|
+
if (PARAMETER.test(name)) {
|
|
92
|
+
throw new CelTypeRegistrationError(
|
|
93
|
+
`${JSON.stringify(name)} is a single capital letter, which a signature reads as a type parameter`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Builds the registered form of a definition. `resolveNominal` resolves names the
|
|
100
|
+
* definition's own base or members mention, including itself through `Self`.
|
|
101
|
+
*/
|
|
102
|
+
export function buildRegisteredType(
|
|
103
|
+
definition: NominalTypeDefinition,
|
|
104
|
+
resolveNominal: NominalResolver,
|
|
105
|
+
): RegisteredType {
|
|
106
|
+
validateTypeName(definition.name);
|
|
107
|
+
const parameters = definition.parameters ?? [];
|
|
108
|
+
for (const parameter of parameters) {
|
|
109
|
+
if (!PARAMETER.test(parameter)) {
|
|
110
|
+
throw new CelTypeRegistrationError(
|
|
111
|
+
`type parameter ${JSON.stringify(parameter)} of ${definition.name} must be a single capital letter`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const self: NominalType = {
|
|
116
|
+
kind: "nominal",
|
|
117
|
+
name: definition.name,
|
|
118
|
+
base: { kind: "dyn" },
|
|
119
|
+
args: parameters.map(parameterOf),
|
|
120
|
+
};
|
|
121
|
+
const withSelf: NominalResolver = (name, args) =>
|
|
122
|
+
name === "Self" || name === definition.name
|
|
123
|
+
? { ...self, args: args.length > 0 ? args : self.args }
|
|
124
|
+
: resolveNominal(name, args);
|
|
125
|
+
let base: CelType;
|
|
126
|
+
try {
|
|
127
|
+
base = parseTypeExpression(definition.base, withSelf);
|
|
128
|
+
} catch (cause) {
|
|
129
|
+
throw new CelTypeRegistrationError(
|
|
130
|
+
`the base of ${definition.name} does not read as a type: ${(cause as Error).message}`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return { definition, base, parameters, self: { ...self, base } };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** The signatures a definition declares, as text, in registration order. */
|
|
137
|
+
export function nominalSignatures(definition: NominalTypeDefinition): readonly string[] {
|
|
138
|
+
return [...(definition.conversions ?? []), ...(definition.members ?? [])];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The operator declarations a definition implies, its comparisons expanded. */
|
|
142
|
+
export function nominalOperators(definition: NominalTypeDefinition): readonly NominalOperatorDeclaration[] {
|
|
143
|
+
const comparisons = (definition.comparisons ?? []).map((operator) => ({
|
|
144
|
+
operator,
|
|
145
|
+
parameters: ["Self", "Self"],
|
|
146
|
+
returns: "bool",
|
|
147
|
+
}));
|
|
148
|
+
return [...(definition.operators ?? []), ...comparisons];
|
|
149
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which dereferences a guard has proven safe.
|
|
3
|
+
*
|
|
4
|
+
* A value whose declared type admits null is only safely dereferenced where something
|
|
5
|
+
* has proven it is not null, and **what counts as proof is exactly three constructs**:
|
|
6
|
+
* a ternary, `&&` and `||`. Not more, not less. That bound is not a simplification — a
|
|
7
|
+
* consumer switching engines must not newly accept an expression (which recognising
|
|
8
|
+
* another construct would do) nor newly reject one (which recognising fewer would do),
|
|
9
|
+
* and a guard written as a function call is deliberately not proof.
|
|
10
|
+
*
|
|
11
|
+
* The rules, over a condition `c`:
|
|
12
|
+
*
|
|
13
|
+
* - `chain != null` proves `chain` where `c` holds; `chain == null` proves it where `c`
|
|
14
|
+
* fails. `null` may stand on either side of the comparison.
|
|
15
|
+
* - `!c` swaps the two.
|
|
16
|
+
* - `a && b` proves, where it holds, everything `a` and `b` prove; where it fails,
|
|
17
|
+
* nothing, since either arm may be the one that failed.
|
|
18
|
+
* - `a || b` is the mirror: where it fails, both arms failed, so both their negative
|
|
19
|
+
* proofs hold.
|
|
20
|
+
*
|
|
21
|
+
* A chain is a plain path of named members (`error.code`), which is what a proof can
|
|
22
|
+
* name: nothing proves anything about `xs[i].code`, because the index is not part of a
|
|
23
|
+
* name.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { CelNode } from "./syntax-tree.js";
|
|
27
|
+
|
|
28
|
+
/** The dotted path a node spells, if it is a plain chain of named members. */
|
|
29
|
+
export function chainText(node: CelNode): string | undefined {
|
|
30
|
+
if (node.kind === "ident") return node.name;
|
|
31
|
+
if (node.kind !== "select" || node.optional || node.field === "") return undefined;
|
|
32
|
+
const operand = chainText(node.operand);
|
|
33
|
+
return operand === undefined ? undefined : `${operand}.${node.field}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The name a chain is rooted at, or nothing when it is not a chain of plain members over a
|
|
38
|
+
* name. It is what says whether the chain's subject is a name the EXPRESSION bound — a
|
|
39
|
+
* comprehension variable, a `cel.bind` name — rather than one the host declared.
|
|
40
|
+
*/
|
|
41
|
+
export function chainRoot(node: CelNode): string | undefined {
|
|
42
|
+
if (node.kind === "ident") return node.name;
|
|
43
|
+
if (node.kind !== "select" || node.optional || node.field === "") return undefined;
|
|
44
|
+
return chainRoot(node.operand);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The chains proven non-null where the condition holds. */
|
|
48
|
+
export function provenWhereTrue(condition: CelNode): readonly string[] {
|
|
49
|
+
switch (condition.kind) {
|
|
50
|
+
case "binary":
|
|
51
|
+
if (condition.operator === "!=") return nullTest(condition);
|
|
52
|
+
if (condition.operator === "&&") {
|
|
53
|
+
return [...provenWhereTrue(condition.left), ...provenWhereTrue(condition.right)];
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
case "unary":
|
|
57
|
+
return condition.operator === "!" ? provenWhereFalse(condition.operand) : [];
|
|
58
|
+
default:
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The chains proven non-null where the condition fails. */
|
|
64
|
+
export function provenWhereFalse(condition: CelNode): readonly string[] {
|
|
65
|
+
switch (condition.kind) {
|
|
66
|
+
case "binary":
|
|
67
|
+
if (condition.operator === "==") return nullTest(condition);
|
|
68
|
+
if (condition.operator === "||") {
|
|
69
|
+
return [...provenWhereFalse(condition.left), ...provenWhereFalse(condition.right)];
|
|
70
|
+
}
|
|
71
|
+
return [];
|
|
72
|
+
case "unary":
|
|
73
|
+
return condition.operator === "!" ? provenWhereTrue(condition.operand) : [];
|
|
74
|
+
default:
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The chain a comparison against `null` is about, either way round. */
|
|
80
|
+
function nullTest(comparison: Extract<CelNode, { kind: "binary" }>): readonly string[] {
|
|
81
|
+
const { left, right } = comparison;
|
|
82
|
+
if (isNullLiteral(right)) {
|
|
83
|
+
const chain = chainText(left);
|
|
84
|
+
return chain === undefined ? [] : [chain];
|
|
85
|
+
}
|
|
86
|
+
if (isNullLiteral(left)) {
|
|
87
|
+
const chain = chainText(right);
|
|
88
|
+
return chain === undefined ? [] : [chain];
|
|
89
|
+
}
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isNullLiteral(node: CelNode): boolean {
|
|
94
|
+
return node.kind === "literal" && node.literal.type === "null";
|
|
95
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the front end refuses to read because it is too big.
|
|
3
|
+
*
|
|
4
|
+
* An expression arrives from a manifest, from an editor buffer or over a wire, so
|
|
5
|
+
* the parser is a hostile-input boundary: without a bound, nesting alone exhausts
|
|
6
|
+
* the call stack of a recursive-descent parser, and a generated list exhausts
|
|
7
|
+
* memory. Each limit is reported as an ordinary ranged diagnostic — never a
|
|
8
|
+
* thrown error — so an editor keeps the prefix it could read.
|
|
9
|
+
*
|
|
10
|
+
* The defaults are the ones every already-written manifest was accepted under.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface CelParseLimits {
|
|
14
|
+
/** Nodes in the tree. */
|
|
15
|
+
readonly maxNodes: number;
|
|
16
|
+
/** Nesting depth of the expression grammar. */
|
|
17
|
+
readonly maxDepth: number;
|
|
18
|
+
/** Elements in one list literal. */
|
|
19
|
+
readonly maxListElements: number;
|
|
20
|
+
/** Entries in one map literal. */
|
|
21
|
+
readonly maxMapEntries: number;
|
|
22
|
+
/** Arguments at one call. */
|
|
23
|
+
readonly maxCallArguments: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const DEFAULT_PARSE_LIMITS: CelParseLimits = {
|
|
27
|
+
maxNodes: 100000,
|
|
28
|
+
maxDepth: 250,
|
|
29
|
+
maxListElements: 1000,
|
|
30
|
+
maxMapEntries: 1000,
|
|
31
|
+
maxCallArguments: 32,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function resolveParseLimits(limits?: Partial<CelParseLimits>): CelParseLimits {
|
|
35
|
+
return limits ? { ...DEFAULT_PARSE_LIMITS, ...limits } : DEFAULT_PARSE_LIMITS;
|
|
36
|
+
}
|