@noya-app/noya-api-client-react 0.1.41 → 0.1.43
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +14 -0
- package/dist/index.js +3182 -166
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3204 -188
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5134,17 +5134,17 @@ var TypeSystemDuplicateFormat = class extends TypeBoxError {
|
|
|
5134
5134
|
};
|
|
5135
5135
|
var TypeSystem;
|
|
5136
5136
|
(function(TypeSystem2) {
|
|
5137
|
-
function
|
|
5137
|
+
function Type3(kind, check2) {
|
|
5138
5138
|
if (type_exports2.Has(kind))
|
|
5139
5139
|
throw new TypeSystemDuplicateTypeKind(kind);
|
|
5140
|
-
type_exports2.Set(kind,
|
|
5140
|
+
type_exports2.Set(kind, check2);
|
|
5141
5141
|
return (options = {}) => Unsafe({ ...options, [Kind]: kind });
|
|
5142
5142
|
}
|
|
5143
|
-
TypeSystem2.Type =
|
|
5144
|
-
function Format(format,
|
|
5143
|
+
TypeSystem2.Type = Type3;
|
|
5144
|
+
function Format(format, check2) {
|
|
5145
5145
|
if (format_exports.Has(format))
|
|
5146
5146
|
throw new TypeSystemDuplicateFormat(format);
|
|
5147
|
-
format_exports.Set(format,
|
|
5147
|
+
format_exports.Set(format, check2);
|
|
5148
5148
|
return format;
|
|
5149
5149
|
}
|
|
5150
5150
|
TypeSystem2.Format = Format;
|
|
@@ -5717,11 +5717,8 @@ function validateUUID(value) {
|
|
|
5717
5717
|
format_exports.Set("color", () => true);
|
|
5718
5718
|
format_exports.Set("uuid", validateUUID);
|
|
5719
5719
|
|
|
5720
|
-
// ../state-manager/src/ConnectedUsersManager.ts
|
|
5721
|
-
var import_observable4 = require("@noya-app/observable");
|
|
5722
|
-
|
|
5723
5720
|
// ../state-manager/src/ConnectionEventManager.ts
|
|
5724
|
-
var
|
|
5721
|
+
var import_observable4 = require("@noya-app/observable");
|
|
5725
5722
|
|
|
5726
5723
|
// ../../node_modules/mutative/dist/mutative.esm.mjs
|
|
5727
5724
|
var PROXY_DRAFT = Symbol.for("__MUTATIVE_PROXY_DRAFT__");
|
|
@@ -7314,7 +7311,7 @@ var import_noya_utils4 = require("@noya-app/noya-utils");
|
|
|
7314
7311
|
|
|
7315
7312
|
// ../state-manager/src/FilePropertyManager.ts
|
|
7316
7313
|
var import_noya_utils5 = require("@noya-app/noya-utils");
|
|
7317
|
-
var
|
|
7314
|
+
var import_observable5 = require("@noya-app/observable");
|
|
7318
7315
|
|
|
7319
7316
|
// ../state-manager/src/historyEntries.ts
|
|
7320
7317
|
var HistoryEntries;
|
|
@@ -7384,149 +7381,3163 @@ var HistoryEntries;
|
|
|
7384
7381
|
}
|
|
7385
7382
|
}
|
|
7386
7383
|
}
|
|
7387
|
-
return result;
|
|
7388
|
-
}
|
|
7389
|
-
HistoryEntries2.compactPatches = compactPatches;
|
|
7390
|
-
function pathsEqual(a, b) {
|
|
7391
|
-
if (a.length !== b.length) {
|
|
7392
|
-
return false;
|
|
7384
|
+
return result;
|
|
7385
|
+
}
|
|
7386
|
+
HistoryEntries2.compactPatches = compactPatches;
|
|
7387
|
+
function pathsEqual(a, b) {
|
|
7388
|
+
if (a.length !== b.length) {
|
|
7389
|
+
return false;
|
|
7390
|
+
}
|
|
7391
|
+
return a.every((path2, index) => {
|
|
7392
|
+
const other = b[index];
|
|
7393
|
+
if (typeof path2 === "object" && "id" in path2 && typeof other === "object" && "id" in other) {
|
|
7394
|
+
return path2.id === other.id;
|
|
7395
|
+
}
|
|
7396
|
+
return path2 === other;
|
|
7397
|
+
});
|
|
7398
|
+
}
|
|
7399
|
+
HistoryEntries2.pathsEqual = pathsEqual;
|
|
7400
|
+
})(HistoryEntries || (HistoryEntries = {}));
|
|
7401
|
+
|
|
7402
|
+
// ../state-manager/src/IOManager.ts
|
|
7403
|
+
var import_observable6 = require("@noya-app/observable");
|
|
7404
|
+
|
|
7405
|
+
// ../state-manager/src/jwt.ts
|
|
7406
|
+
function base64UrlEncode(str) {
|
|
7407
|
+
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
7408
|
+
}
|
|
7409
|
+
function base64UrlDecode(str) {
|
|
7410
|
+
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
7411
|
+
switch (str.length % 4) {
|
|
7412
|
+
case 2:
|
|
7413
|
+
str += "==";
|
|
7414
|
+
break;
|
|
7415
|
+
case 3:
|
|
7416
|
+
str += "=";
|
|
7417
|
+
break;
|
|
7418
|
+
}
|
|
7419
|
+
return atob(str);
|
|
7420
|
+
}
|
|
7421
|
+
var HEADER = {
|
|
7422
|
+
alg: "HS256",
|
|
7423
|
+
typ: "JWT"
|
|
7424
|
+
};
|
|
7425
|
+
var JWT_ERROR = {
|
|
7426
|
+
INVALID_JWT_FORMAT: "Invalid JWT format"
|
|
7427
|
+
// INVALID_SIGNATURE: "Invalid signature",
|
|
7428
|
+
};
|
|
7429
|
+
async function createJwt({
|
|
7430
|
+
payload,
|
|
7431
|
+
secret,
|
|
7432
|
+
header
|
|
7433
|
+
}) {
|
|
7434
|
+
const encoder = new TextEncoder();
|
|
7435
|
+
const encodedHeader = base64UrlEncode(
|
|
7436
|
+
JSON.stringify({ ...HEADER, ...header })
|
|
7437
|
+
);
|
|
7438
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(payload));
|
|
7439
|
+
const dataToSign = `${encodedHeader}.${encodedPayload}`;
|
|
7440
|
+
const key = await crypto.subtle.importKey(
|
|
7441
|
+
"raw",
|
|
7442
|
+
encoder.encode(secret),
|
|
7443
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
7444
|
+
false,
|
|
7445
|
+
["sign"]
|
|
7446
|
+
);
|
|
7447
|
+
const signature = await crypto.subtle.sign(
|
|
7448
|
+
"HMAC",
|
|
7449
|
+
key,
|
|
7450
|
+
encoder.encode(dataToSign)
|
|
7451
|
+
);
|
|
7452
|
+
const encodedSignature = base64UrlEncode(
|
|
7453
|
+
String.fromCharCode(...new Uint8Array(signature))
|
|
7454
|
+
);
|
|
7455
|
+
return `${dataToSign}.${encodedSignature}`;
|
|
7456
|
+
}
|
|
7457
|
+
async function decodeJwt({
|
|
7458
|
+
token,
|
|
7459
|
+
secret
|
|
7460
|
+
}) {
|
|
7461
|
+
if (typeof token !== "string") {
|
|
7462
|
+
throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
|
|
7463
|
+
}
|
|
7464
|
+
const [encodedHeader, encodedPayload, encodedSignature] = token.split(".");
|
|
7465
|
+
if (!encodedHeader || !encodedPayload || !encodedSignature) {
|
|
7466
|
+
throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
|
|
7467
|
+
}
|
|
7468
|
+
const headerJson = base64UrlDecode(encodedHeader);
|
|
7469
|
+
const payloadJson = base64UrlDecode(encodedPayload);
|
|
7470
|
+
const header = JSON.parse(headerJson);
|
|
7471
|
+
const payload = JSON.parse(payloadJson);
|
|
7472
|
+
const dataToVerify = `${encodedHeader}.${encodedPayload}`;
|
|
7473
|
+
const encoder = new TextEncoder();
|
|
7474
|
+
if (secret !== void 0) {
|
|
7475
|
+
const key = await crypto.subtle.importKey(
|
|
7476
|
+
"raw",
|
|
7477
|
+
encoder.encode(secret),
|
|
7478
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
7479
|
+
false,
|
|
7480
|
+
["verify"]
|
|
7481
|
+
);
|
|
7482
|
+
const binarySignature = base64UrlDecode(encodedSignature);
|
|
7483
|
+
const signature = new Uint8Array(
|
|
7484
|
+
[...binarySignature].map((char) => char.charCodeAt(0))
|
|
7485
|
+
);
|
|
7486
|
+
const valid = await crypto.subtle.verify(
|
|
7487
|
+
"HMAC",
|
|
7488
|
+
key,
|
|
7489
|
+
signature,
|
|
7490
|
+
encoder.encode(dataToVerify)
|
|
7491
|
+
);
|
|
7492
|
+
return { header, payload, valid };
|
|
7493
|
+
}
|
|
7494
|
+
return { header, payload, valid: false };
|
|
7495
|
+
}
|
|
7496
|
+
var jwt;
|
|
7497
|
+
((jwt2) => {
|
|
7498
|
+
jwt2.encode = createJwt;
|
|
7499
|
+
jwt2.decode = decodeJwt;
|
|
7500
|
+
jwt2.ERROR = JWT_ERROR;
|
|
7501
|
+
jwt2.DEFAULT_HEADER = HEADER;
|
|
7502
|
+
})(jwt || (jwt = {}));
|
|
7503
|
+
|
|
7504
|
+
// ../state-manager/src/MenuManager.ts
|
|
7505
|
+
var import_noya_utils6 = require("@noya-app/noya-utils");
|
|
7506
|
+
var import_observable7 = require("@noya-app/observable");
|
|
7507
|
+
|
|
7508
|
+
// ../state-manager/src/multiplayer.ts
|
|
7509
|
+
var import_noya_utils7 = require("@noya-app/noya-utils");
|
|
7510
|
+
var import_observable9 = require("@noya-app/observable");
|
|
7511
|
+
|
|
7512
|
+
// ../state-manager/src/stateManager.ts
|
|
7513
|
+
var import_observable8 = require("@noya-app/observable");
|
|
7514
|
+
|
|
7515
|
+
// ../state-manager/src/multiplayer.ts
|
|
7516
|
+
var createHash = (value, options) => (0, import_noya_utils7.hash)(value, { ...options, ignoreUndefinedProperties: true });
|
|
7517
|
+
|
|
7518
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/errors.js
|
|
7519
|
+
var ParseError = class extends Error {
|
|
7520
|
+
#wasConstructedWithAst = false;
|
|
7521
|
+
#node;
|
|
7522
|
+
constructor(message, node, cause) {
|
|
7523
|
+
super(message, { cause });
|
|
7524
|
+
this.name = "ParseError";
|
|
7525
|
+
this.#node = node;
|
|
7526
|
+
if (!node?.input) return;
|
|
7527
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7528
|
+
}
|
|
7529
|
+
get node() {
|
|
7530
|
+
return this.#node;
|
|
7531
|
+
}
|
|
7532
|
+
withAst(node) {
|
|
7533
|
+
if (this.#node) return this;
|
|
7534
|
+
this.#node = node;
|
|
7535
|
+
if (!node?.input) return this;
|
|
7536
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7537
|
+
return this;
|
|
7538
|
+
}
|
|
7539
|
+
};
|
|
7540
|
+
var EvaluationError = class extends Error {
|
|
7541
|
+
#node;
|
|
7542
|
+
constructor(message, node, cause) {
|
|
7543
|
+
super(message, { cause });
|
|
7544
|
+
this.name = "EvaluationError";
|
|
7545
|
+
this.#node = node;
|
|
7546
|
+
if (!node?.input) return;
|
|
7547
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7548
|
+
}
|
|
7549
|
+
get node() {
|
|
7550
|
+
return this.#node;
|
|
7551
|
+
}
|
|
7552
|
+
withAst(node) {
|
|
7553
|
+
if (this.#node) return this;
|
|
7554
|
+
this.#node = node;
|
|
7555
|
+
if (!node?.input) return this;
|
|
7556
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7557
|
+
return this;
|
|
7558
|
+
}
|
|
7559
|
+
};
|
|
7560
|
+
var TypeError2 = class extends Error {
|
|
7561
|
+
#node;
|
|
7562
|
+
constructor(message, node, cause) {
|
|
7563
|
+
super(message, { cause });
|
|
7564
|
+
this.name = "TypeError";
|
|
7565
|
+
this.#node = node;
|
|
7566
|
+
if (!node?.input) return;
|
|
7567
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7568
|
+
}
|
|
7569
|
+
get node() {
|
|
7570
|
+
return this.#node;
|
|
7571
|
+
}
|
|
7572
|
+
withAst(node) {
|
|
7573
|
+
if (this.#node) return this;
|
|
7574
|
+
this.#node = node;
|
|
7575
|
+
if (!node?.input) return this;
|
|
7576
|
+
this.message = formatErrorWithHighlight(this.message, node);
|
|
7577
|
+
return this;
|
|
7578
|
+
}
|
|
7579
|
+
};
|
|
7580
|
+
function formatErrorWithHighlight(message, node) {
|
|
7581
|
+
if (node?.pos === void 0) return message;
|
|
7582
|
+
const pos = node.pos;
|
|
7583
|
+
const input = node.input;
|
|
7584
|
+
let lineNum = 1;
|
|
7585
|
+
let currentPos = 0;
|
|
7586
|
+
let columnNum = 0;
|
|
7587
|
+
while (currentPos < pos) {
|
|
7588
|
+
if (input[currentPos] === "\n") {
|
|
7589
|
+
lineNum++;
|
|
7590
|
+
columnNum = 0;
|
|
7591
|
+
} else {
|
|
7592
|
+
columnNum++;
|
|
7593
|
+
}
|
|
7594
|
+
currentPos++;
|
|
7595
|
+
}
|
|
7596
|
+
let contextStart = pos;
|
|
7597
|
+
let contextEnd = pos;
|
|
7598
|
+
while (contextStart > 0 && input[contextStart - 1] !== "\n") contextStart--;
|
|
7599
|
+
while (contextEnd < input.length && input[contextEnd] !== "\n") contextEnd++;
|
|
7600
|
+
const line = input.slice(contextStart, contextEnd);
|
|
7601
|
+
const lineNumber = `${lineNum}`.padStart(4, " ");
|
|
7602
|
+
const spaces = " ".repeat(9 + columnNum);
|
|
7603
|
+
return `${message}
|
|
7604
|
+
|
|
7605
|
+
> ${lineNumber} | ${line}
|
|
7606
|
+
${spaces}^`;
|
|
7607
|
+
}
|
|
7608
|
+
|
|
7609
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/parser.js
|
|
7610
|
+
var TOKEN = {
|
|
7611
|
+
EOF: 0,
|
|
7612
|
+
NUMBER: 1,
|
|
7613
|
+
STRING: 2,
|
|
7614
|
+
BOOLEAN: 3,
|
|
7615
|
+
NULL: 4,
|
|
7616
|
+
IDENTIFIER: 5,
|
|
7617
|
+
PLUS: 6,
|
|
7618
|
+
MINUS: 7,
|
|
7619
|
+
MULTIPLY: 8,
|
|
7620
|
+
DIVIDE: 9,
|
|
7621
|
+
MODULO: 10,
|
|
7622
|
+
EQ: 11,
|
|
7623
|
+
NE: 12,
|
|
7624
|
+
LT: 13,
|
|
7625
|
+
LE: 14,
|
|
7626
|
+
GT: 15,
|
|
7627
|
+
GE: 16,
|
|
7628
|
+
AND: 17,
|
|
7629
|
+
OR: 18,
|
|
7630
|
+
NOT: 19,
|
|
7631
|
+
IN: 20,
|
|
7632
|
+
LPAREN: 21,
|
|
7633
|
+
RPAREN: 22,
|
|
7634
|
+
LBRACKET: 23,
|
|
7635
|
+
RBRACKET: 24,
|
|
7636
|
+
LBRACE: 25,
|
|
7637
|
+
RBRACE: 26,
|
|
7638
|
+
DOT: 27,
|
|
7639
|
+
COMMA: 28,
|
|
7640
|
+
COLON: 29,
|
|
7641
|
+
QUESTION: 30,
|
|
7642
|
+
BYTES: 31
|
|
7643
|
+
};
|
|
7644
|
+
var ASTNode = class extends Array {
|
|
7645
|
+
#pos;
|
|
7646
|
+
#input;
|
|
7647
|
+
constructor(pos, input, elements) {
|
|
7648
|
+
super();
|
|
7649
|
+
this.#pos = pos;
|
|
7650
|
+
this.#input = input;
|
|
7651
|
+
this.push(...elements);
|
|
7652
|
+
}
|
|
7653
|
+
get input() {
|
|
7654
|
+
return this.#input;
|
|
7655
|
+
}
|
|
7656
|
+
get pos() {
|
|
7657
|
+
return this.#pos;
|
|
7658
|
+
}
|
|
7659
|
+
};
|
|
7660
|
+
var TOKEN_BY_NUMBER = {};
|
|
7661
|
+
for (const key in TOKEN) TOKEN_BY_NUMBER[TOKEN[key]] = key;
|
|
7662
|
+
var RESERVED = /* @__PURE__ */ new Set([
|
|
7663
|
+
"as",
|
|
7664
|
+
"break",
|
|
7665
|
+
"const",
|
|
7666
|
+
"continue",
|
|
7667
|
+
"else",
|
|
7668
|
+
"for",
|
|
7669
|
+
"function",
|
|
7670
|
+
"if",
|
|
7671
|
+
"import",
|
|
7672
|
+
"let",
|
|
7673
|
+
"loop",
|
|
7674
|
+
"package",
|
|
7675
|
+
"namespace",
|
|
7676
|
+
"return",
|
|
7677
|
+
"var",
|
|
7678
|
+
"void",
|
|
7679
|
+
"while"
|
|
7680
|
+
]);
|
|
7681
|
+
var HEX_CODES = new Uint8Array(256);
|
|
7682
|
+
for (const ch of "0123456789abcdefABCDEF") HEX_CODES[ch.charCodeAt(0)] = 1;
|
|
7683
|
+
var IDENTIFIER_CODES = new Uint8Array(256);
|
|
7684
|
+
for (const ch of "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_") {
|
|
7685
|
+
IDENTIFIER_CODES[ch.charCodeAt(0)] = 1;
|
|
7686
|
+
}
|
|
7687
|
+
var STRING_ESCAPES = {
|
|
7688
|
+
"\\": "\\",
|
|
7689
|
+
"?": "?",
|
|
7690
|
+
'"': '"',
|
|
7691
|
+
"'": "'",
|
|
7692
|
+
"`": "`",
|
|
7693
|
+
a: "\x07",
|
|
7694
|
+
b: "\b",
|
|
7695
|
+
f: "\f",
|
|
7696
|
+
n: "\n",
|
|
7697
|
+
r: "\r",
|
|
7698
|
+
t: " ",
|
|
7699
|
+
v: "\v"
|
|
7700
|
+
};
|
|
7701
|
+
var Lexer = class {
|
|
7702
|
+
constructor(input) {
|
|
7703
|
+
this.input = input;
|
|
7704
|
+
this.pos = 0;
|
|
7705
|
+
this.length = input.length;
|
|
7706
|
+
}
|
|
7707
|
+
// Read next token
|
|
7708
|
+
nextToken() {
|
|
7709
|
+
if (this.pos >= this.length) return { type: TOKEN.EOF, value: null, pos: this.pos };
|
|
7710
|
+
const ch = this.input[this.pos];
|
|
7711
|
+
const next = this.input[this.pos + 1];
|
|
7712
|
+
switch (ch) {
|
|
7713
|
+
// Whitespaces
|
|
7714
|
+
case " ":
|
|
7715
|
+
case " ":
|
|
7716
|
+
case "\n":
|
|
7717
|
+
case "\r":
|
|
7718
|
+
this.pos++;
|
|
7719
|
+
return this.nextToken();
|
|
7720
|
+
// Operators
|
|
7721
|
+
case "=":
|
|
7722
|
+
if (next !== "=") break;
|
|
7723
|
+
return { type: TOKEN.EQ, value: "==", pos: (this.pos += 2) - 2 };
|
|
7724
|
+
case "&":
|
|
7725
|
+
if (next !== "&") break;
|
|
7726
|
+
return { type: TOKEN.AND, value: "&&", pos: (this.pos += 2) - 2 };
|
|
7727
|
+
case "|":
|
|
7728
|
+
if (next !== "|") break;
|
|
7729
|
+
return { type: TOKEN.OR, value: "||", pos: (this.pos += 2) - 2 };
|
|
7730
|
+
case "+":
|
|
7731
|
+
return { type: TOKEN.PLUS, value: "+", pos: this.pos++ };
|
|
7732
|
+
case "-":
|
|
7733
|
+
return { type: TOKEN.MINUS, value: "-", pos: this.pos++ };
|
|
7734
|
+
case "*":
|
|
7735
|
+
return { type: TOKEN.MULTIPLY, value: "*", pos: this.pos++ };
|
|
7736
|
+
case "/":
|
|
7737
|
+
if (next === "/") {
|
|
7738
|
+
while (this.pos < this.length && this.input[this.pos] !== "\n") this.pos++;
|
|
7739
|
+
return this.nextToken();
|
|
7740
|
+
}
|
|
7741
|
+
return { type: TOKEN.DIVIDE, value: "/", pos: this.pos++ };
|
|
7742
|
+
case "%":
|
|
7743
|
+
return { type: TOKEN.MODULO, value: "%", pos: this.pos++ };
|
|
7744
|
+
case "<":
|
|
7745
|
+
if (next === "=") return { type: TOKEN.LE, value: "<=", pos: (this.pos += 2) - 2 };
|
|
7746
|
+
return { type: TOKEN.LT, value: "<", pos: this.pos++ };
|
|
7747
|
+
case ">":
|
|
7748
|
+
if (next === "=") return { type: TOKEN.GE, value: ">=", pos: (this.pos += 2) - 2 };
|
|
7749
|
+
return { type: TOKEN.GT, value: ">", pos: this.pos++ };
|
|
7750
|
+
case "!":
|
|
7751
|
+
if (next === "=") return { type: TOKEN.NE, value: "!=", pos: (this.pos += 2) - 2 };
|
|
7752
|
+
return { type: TOKEN.NOT, value: "!", pos: this.pos++ };
|
|
7753
|
+
case "(":
|
|
7754
|
+
return { type: TOKEN.LPAREN, value: "(", pos: this.pos++ };
|
|
7755
|
+
case ")":
|
|
7756
|
+
return { type: TOKEN.RPAREN, value: ")", pos: this.pos++ };
|
|
7757
|
+
case "[":
|
|
7758
|
+
return { type: TOKEN.LBRACKET, value: "[", pos: this.pos++ };
|
|
7759
|
+
case "]":
|
|
7760
|
+
return { type: TOKEN.RBRACKET, value: "]", pos: this.pos++ };
|
|
7761
|
+
case "{":
|
|
7762
|
+
return { type: TOKEN.LBRACE, value: "{", pos: this.pos++ };
|
|
7763
|
+
case "}":
|
|
7764
|
+
return { type: TOKEN.RBRACE, value: "}", pos: this.pos++ };
|
|
7765
|
+
case ".":
|
|
7766
|
+
return { type: TOKEN.DOT, value: ".", pos: this.pos++ };
|
|
7767
|
+
case ",":
|
|
7768
|
+
return { type: TOKEN.COMMA, value: ",", pos: this.pos++ };
|
|
7769
|
+
case ":":
|
|
7770
|
+
return { type: TOKEN.COLON, value: ":", pos: this.pos++ };
|
|
7771
|
+
case "?":
|
|
7772
|
+
return { type: TOKEN.QUESTION, value: "?", pos: this.pos++ };
|
|
7773
|
+
case `"`:
|
|
7774
|
+
case `'`:
|
|
7775
|
+
return this.readString();
|
|
7776
|
+
// Check for string prefixes (b, B, r, R followed by quote)
|
|
7777
|
+
case "b":
|
|
7778
|
+
case "B":
|
|
7779
|
+
case "r":
|
|
7780
|
+
case "R":
|
|
7781
|
+
if (next === '"' || next === "'") {
|
|
7782
|
+
this.pos++;
|
|
7783
|
+
return this.readString(ch.toLowerCase());
|
|
7784
|
+
}
|
|
7785
|
+
return this.readIdentifier();
|
|
7786
|
+
default: {
|
|
7787
|
+
if (ch >= "0" && ch <= "9") return this.readNumber();
|
|
7788
|
+
if (IDENTIFIER_CODES[ch.charCodeAt(0)]) return this.readIdentifier();
|
|
7789
|
+
}
|
|
7790
|
+
}
|
|
7791
|
+
throw new ParseError(`Unexpected character: ${ch}`, { pos: this.pos, input: this.input });
|
|
7792
|
+
}
|
|
7793
|
+
_parseAsBigInt(start, end, isHex, unsigned) {
|
|
7794
|
+
const string = this.input.substring(start, end);
|
|
7795
|
+
if (unsigned === "u" || unsigned === "U") {
|
|
7796
|
+
this.pos++;
|
|
7797
|
+
try {
|
|
7798
|
+
return {
|
|
7799
|
+
type: TOKEN.NUMBER,
|
|
7800
|
+
value: new UnsignedInt(string),
|
|
7801
|
+
pos: start
|
|
7802
|
+
};
|
|
7803
|
+
} catch (_err) {
|
|
7804
|
+
}
|
|
7805
|
+
} else {
|
|
7806
|
+
try {
|
|
7807
|
+
return {
|
|
7808
|
+
type: TOKEN.NUMBER,
|
|
7809
|
+
value: BigInt(string),
|
|
7810
|
+
pos: start
|
|
7811
|
+
};
|
|
7812
|
+
} catch (_err) {
|
|
7813
|
+
}
|
|
7814
|
+
}
|
|
7815
|
+
throw new ParseError(isHex ? `Invalid hex integer: ${string}` : `Invalid integer: ${string}`, {
|
|
7816
|
+
pos: start,
|
|
7817
|
+
input: this.input
|
|
7818
|
+
});
|
|
7819
|
+
}
|
|
7820
|
+
readNumber() {
|
|
7821
|
+
const { input, length, pos: start } = this;
|
|
7822
|
+
if (input[start] === "0" && (input[start + 1] === "x" || input[start + 1] === "X")) {
|
|
7823
|
+
this.pos += 2;
|
|
7824
|
+
while (this.pos < length && HEX_CODES[input[this.pos].charCodeAt(0)]) this.pos++;
|
|
7825
|
+
return this._parseAsBigInt(start, this.pos, true, input[this.pos]);
|
|
7826
|
+
}
|
|
7827
|
+
let ch;
|
|
7828
|
+
while (this.pos < length && (ch = input[this.pos]) >= "0" && ch <= "9") this.pos++;
|
|
7829
|
+
if (ch === "." && (ch = input[this.pos + 1]) >= "0" && ch <= "9") {
|
|
7830
|
+
this.pos++;
|
|
7831
|
+
while (this.pos < length && (ch = input[this.pos]) >= "0" && ch <= "9") this.pos++;
|
|
7832
|
+
const string = input.substring(start, this.pos);
|
|
7833
|
+
const value = Number(string);
|
|
7834
|
+
if (Number.isFinite(value)) return { type: TOKEN.NUMBER, value, pos: start };
|
|
7835
|
+
throw new ParseError(`Invalid number: ${value}`, { pos: start, input: this.input });
|
|
7836
|
+
}
|
|
7837
|
+
return this._parseAsBigInt(start, this.pos, false, input[this.pos]);
|
|
7838
|
+
}
|
|
7839
|
+
readString(prefix) {
|
|
7840
|
+
const delimiter = this.input[this.pos++];
|
|
7841
|
+
if (this.input[this.pos] === delimiter && this.input[this.pos + 1] === delimiter) {
|
|
7842
|
+
this.pos += 2;
|
|
7843
|
+
return this.readTripleQuotedString(delimiter, prefix);
|
|
7844
|
+
}
|
|
7845
|
+
return this.readSingleQuotedString(delimiter, prefix);
|
|
7846
|
+
}
|
|
7847
|
+
_closeQuotedString(rawValue, prefix) {
|
|
7848
|
+
if (prefix === "b") {
|
|
7849
|
+
const processed = this.processEscapes(rawValue, true);
|
|
7850
|
+
const bytes = new Uint8Array(processed.length);
|
|
7851
|
+
for (let i = 0; i < processed.length; i++) {
|
|
7852
|
+
bytes[i] = processed.charCodeAt(i) & 255;
|
|
7853
|
+
}
|
|
7854
|
+
return { type: TOKEN.BYTES, value: bytes, pos: this.pos - rawValue.length - 2 };
|
|
7855
|
+
}
|
|
7856
|
+
const value = prefix === "r" ? rawValue : this.processEscapes(rawValue, false);
|
|
7857
|
+
return { type: TOKEN.STRING, value, pos: this.pos - rawValue.length };
|
|
7858
|
+
}
|
|
7859
|
+
readSingleQuotedString(delimiter, prefix) {
|
|
7860
|
+
const { input, length, pos: start } = this;
|
|
7861
|
+
const needsEscapeHandling = prefix !== "r";
|
|
7862
|
+
while (this.pos < length) {
|
|
7863
|
+
const ch = input[this.pos];
|
|
7864
|
+
if (ch === delimiter) {
|
|
7865
|
+
const rawValue = input.slice(start, this.pos);
|
|
7866
|
+
this.pos++;
|
|
7867
|
+
return this._closeQuotedString(rawValue, prefix);
|
|
7868
|
+
}
|
|
7869
|
+
if (ch === "\n" || ch === "\r") {
|
|
7870
|
+
throw new ParseError("Newlines not allowed in single-quoted strings", {
|
|
7871
|
+
pos: start - 1,
|
|
7872
|
+
input
|
|
7873
|
+
});
|
|
7874
|
+
}
|
|
7875
|
+
if (ch === "\\" && needsEscapeHandling) {
|
|
7876
|
+
this.pos += 2;
|
|
7877
|
+
if (this.pos > length) {
|
|
7878
|
+
throw new ParseError("Unterminated escape sequence", {
|
|
7879
|
+
pos: start - 1,
|
|
7880
|
+
input
|
|
7881
|
+
});
|
|
7882
|
+
}
|
|
7883
|
+
continue;
|
|
7884
|
+
}
|
|
7885
|
+
this.pos++;
|
|
7886
|
+
}
|
|
7887
|
+
throw new ParseError("Unterminated string", { pos: start - 1, input });
|
|
7888
|
+
}
|
|
7889
|
+
readTripleQuotedString(delimiter, prefix) {
|
|
7890
|
+
const start = this.pos;
|
|
7891
|
+
const needsEscapeHandling = prefix !== "r";
|
|
7892
|
+
while (this.pos < this.length) {
|
|
7893
|
+
const ch = this.input[this.pos];
|
|
7894
|
+
if (ch === delimiter && this.input[this.pos + 1] === delimiter && this.input[this.pos + 2] === delimiter) {
|
|
7895
|
+
const rawValue = this.input.slice(start, this.pos);
|
|
7896
|
+
this.pos += 3;
|
|
7897
|
+
return this._closeQuotedString(rawValue, prefix);
|
|
7898
|
+
}
|
|
7899
|
+
if (ch === "\\" && needsEscapeHandling) {
|
|
7900
|
+
this.pos += 2;
|
|
7901
|
+
if (this.pos > this.length) {
|
|
7902
|
+
throw new ParseError("Unterminated escape sequence", {
|
|
7903
|
+
pos: start - 3,
|
|
7904
|
+
input: this.input
|
|
7905
|
+
});
|
|
7906
|
+
}
|
|
7907
|
+
continue;
|
|
7908
|
+
}
|
|
7909
|
+
this.pos++;
|
|
7910
|
+
}
|
|
7911
|
+
throw new ParseError("Unterminated triple-quoted string", { pos: start - 3, input: this.input });
|
|
7912
|
+
}
|
|
7913
|
+
processEscapes(str, isBytes) {
|
|
7914
|
+
let result = "";
|
|
7915
|
+
let i = 0;
|
|
7916
|
+
while (i < str.length) {
|
|
7917
|
+
if (str[i] !== "\\" || i + 1 >= str.length) {
|
|
7918
|
+
result += str[i++];
|
|
7919
|
+
continue;
|
|
7920
|
+
}
|
|
7921
|
+
const next = str[i + 1];
|
|
7922
|
+
if (STRING_ESCAPES[next]) {
|
|
7923
|
+
result += STRING_ESCAPES[next];
|
|
7924
|
+
i += 2;
|
|
7925
|
+
} else if (next === "u") {
|
|
7926
|
+
if (isBytes) throw new ParseError("\\u not allowed in bytes literals");
|
|
7927
|
+
const hex = str.substring(i + 2, i + 6);
|
|
7928
|
+
if (hex.length !== 4 || !/^[0-9a-fA-F]{4}$/.test(hex)) {
|
|
7929
|
+
throw new ParseError(`Invalid Unicode escape: \\u${hex}`);
|
|
7930
|
+
}
|
|
7931
|
+
const code = Number.parseInt(hex, 16);
|
|
7932
|
+
if (code >= 55296 && code <= 57343) {
|
|
7933
|
+
throw new ParseError(`Invalid Unicode surrogate: \\u${hex}`);
|
|
7934
|
+
}
|
|
7935
|
+
result += String.fromCharCode(code);
|
|
7936
|
+
i += 6;
|
|
7937
|
+
} else if (next === "U") {
|
|
7938
|
+
if (isBytes) throw new ParseError("\\U not allowed in bytes literals");
|
|
7939
|
+
const hex = str.substring(i + 2, i + 10);
|
|
7940
|
+
if (hex.length !== 8 || !/^[0-9a-fA-F]{8}$/.test(hex)) {
|
|
7941
|
+
throw new ParseError(`Invalid Unicode escape: \\U${hex}`);
|
|
7942
|
+
}
|
|
7943
|
+
const code = Number.parseInt(hex, 16);
|
|
7944
|
+
if (code > 1114111) throw new ParseError(`Invalid Unicode escape: \\U${hex}`);
|
|
7945
|
+
if (code >= 55296 && code <= 57343) {
|
|
7946
|
+
throw new ParseError(`Invalid Unicode surrogate: \\U${hex}`);
|
|
7947
|
+
}
|
|
7948
|
+
result += String.fromCodePoint(code);
|
|
7949
|
+
i += 10;
|
|
7950
|
+
} else if (next === "x" || next === "X") {
|
|
7951
|
+
const hex = str.substring(i + 2, i + 4);
|
|
7952
|
+
if (hex.length !== 2 || !/^[0-9a-fA-F]{2}$/.test(hex)) {
|
|
7953
|
+
throw new ParseError(`Invalid hex escape: \\${next}${hex}`);
|
|
7954
|
+
}
|
|
7955
|
+
result += String.fromCharCode(Number.parseInt(hex, 16));
|
|
7956
|
+
i += 4;
|
|
7957
|
+
} else if (next >= "0" && next <= "7") {
|
|
7958
|
+
const octal = str.substring(i + 1, i + 4);
|
|
7959
|
+
if (octal.length !== 3 || !/^[0-7]{3}$/.test(octal)) {
|
|
7960
|
+
throw new ParseError("Octal escape must be 3 digits");
|
|
7961
|
+
}
|
|
7962
|
+
const value = Number.parseInt(octal, 8);
|
|
7963
|
+
if (value > 255) {
|
|
7964
|
+
throw new ParseError(`Octal escape out of range: \\${octal}`);
|
|
7965
|
+
}
|
|
7966
|
+
result += String.fromCharCode(value);
|
|
7967
|
+
i += 4;
|
|
7968
|
+
} else {
|
|
7969
|
+
throw new ParseError(`Invalid escape sequence: \\${next}`);
|
|
7970
|
+
}
|
|
7971
|
+
}
|
|
7972
|
+
return result;
|
|
7973
|
+
}
|
|
7974
|
+
readIdentifier() {
|
|
7975
|
+
const start = this.pos;
|
|
7976
|
+
while (this.pos < this.length && IDENTIFIER_CODES[this.input[this.pos].charCodeAt(0)])
|
|
7977
|
+
this.pos++;
|
|
7978
|
+
const text = this.input.substring(start, this.pos);
|
|
7979
|
+
switch (text) {
|
|
7980
|
+
case "true":
|
|
7981
|
+
return { type: TOKEN.BOOLEAN, value: true, pos: start };
|
|
7982
|
+
case "false":
|
|
7983
|
+
return { type: TOKEN.BOOLEAN, value: false, pos: start };
|
|
7984
|
+
case "null":
|
|
7985
|
+
return { type: TOKEN.NULL, value: null, pos: start };
|
|
7986
|
+
case "in":
|
|
7987
|
+
return { type: TOKEN.IN, value: "in", pos: start };
|
|
7988
|
+
default:
|
|
7989
|
+
return { type: TOKEN.IDENTIFIER, value: text, pos: start };
|
|
7990
|
+
}
|
|
7991
|
+
}
|
|
7992
|
+
};
|
|
7993
|
+
var Parser = class {
|
|
7994
|
+
constructor(input) {
|
|
7995
|
+
this.input = input;
|
|
7996
|
+
this.lexer = new Lexer(input);
|
|
7997
|
+
this.currentToken = this.lexer.nextToken();
|
|
7998
|
+
}
|
|
7999
|
+
consume(expectedType) {
|
|
8000
|
+
const token = this.currentToken;
|
|
8001
|
+
this.currentToken = this.lexer.nextToken();
|
|
8002
|
+
if (token.type === expectedType) return token;
|
|
8003
|
+
throw new ParseError(
|
|
8004
|
+
`Expected ${TOKEN_BY_NUMBER[expectedType]}, got ${TOKEN_BY_NUMBER[token.type]}`,
|
|
8005
|
+
{ pos: token.pos, input: this.input }
|
|
8006
|
+
);
|
|
8007
|
+
}
|
|
8008
|
+
match(type) {
|
|
8009
|
+
return this.currentToken.type === type;
|
|
8010
|
+
}
|
|
8011
|
+
// Parse entry point
|
|
8012
|
+
parse() {
|
|
8013
|
+
const result = this.parseExpression();
|
|
8014
|
+
if (!this.match(TOKEN.EOF)) {
|
|
8015
|
+
throw new ParseError(`Unexpected character: '${this.input[this.lexer.pos - 1]}'`, {
|
|
8016
|
+
pos: this.currentToken.pos,
|
|
8017
|
+
input: this.input
|
|
8018
|
+
});
|
|
8019
|
+
}
|
|
8020
|
+
return result;
|
|
8021
|
+
}
|
|
8022
|
+
// Expression ::= LogicalOr ('?' Expression ':' Expression)? // Made right-associative
|
|
8023
|
+
parseExpression() {
|
|
8024
|
+
const expr = this.parseLogicalOr();
|
|
8025
|
+
if (this.match(TOKEN.QUESTION)) {
|
|
8026
|
+
const token = this.consume(TOKEN.QUESTION);
|
|
8027
|
+
const consequent = this.parseExpression();
|
|
8028
|
+
this.consume(TOKEN.COLON);
|
|
8029
|
+
return new ASTNode(token.pos, this.input, ["?:", expr, consequent, this.parseExpression()]);
|
|
8030
|
+
}
|
|
8031
|
+
return expr;
|
|
8032
|
+
}
|
|
8033
|
+
// LogicalOr ::= LogicalAnd ('||' LogicalAnd)*
|
|
8034
|
+
parseLogicalOr() {
|
|
8035
|
+
let expr = this.parseLogicalAnd();
|
|
8036
|
+
while (this.match(TOKEN.OR)) {
|
|
8037
|
+
const token = this.consume(TOKEN.OR);
|
|
8038
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseLogicalAnd()]);
|
|
8039
|
+
}
|
|
8040
|
+
return expr;
|
|
8041
|
+
}
|
|
8042
|
+
// LogicalAnd ::= Equality ('&&' Equality)*
|
|
8043
|
+
parseLogicalAnd() {
|
|
8044
|
+
let expr = this.parseEquality();
|
|
8045
|
+
while (this.match(TOKEN.AND)) {
|
|
8046
|
+
const token = this.consume(TOKEN.AND);
|
|
8047
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseEquality()]);
|
|
8048
|
+
}
|
|
8049
|
+
return expr;
|
|
8050
|
+
}
|
|
8051
|
+
// Equality ::= Relational (('==' | '!=') Relational)*
|
|
8052
|
+
parseEquality() {
|
|
8053
|
+
let expr = this.parseRelational();
|
|
8054
|
+
while (this.match(TOKEN.EQ) || this.match(TOKEN.NE)) {
|
|
8055
|
+
const token = this.currentToken;
|
|
8056
|
+
this.currentToken = this.lexer.nextToken();
|
|
8057
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseRelational()]);
|
|
8058
|
+
}
|
|
8059
|
+
return expr;
|
|
8060
|
+
}
|
|
8061
|
+
// Relational ::= Additive (('<' | '<=' | '>' | '>=' | 'in') Additive)*
|
|
8062
|
+
parseRelational() {
|
|
8063
|
+
let expr = this.parseAdditive();
|
|
8064
|
+
while (this.match(TOKEN.LT) || this.match(TOKEN.LE) || this.match(TOKEN.GT) || this.match(TOKEN.GE) || this.match(TOKEN.IN)) {
|
|
8065
|
+
const token = this.currentToken;
|
|
8066
|
+
this.currentToken = this.lexer.nextToken();
|
|
8067
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseAdditive()]);
|
|
8068
|
+
}
|
|
8069
|
+
return expr;
|
|
8070
|
+
}
|
|
8071
|
+
// Additive ::= Multiplicative (('+' | '-') Multiplicative)*
|
|
8072
|
+
parseAdditive() {
|
|
8073
|
+
let expr = this.parseMultiplicative();
|
|
8074
|
+
while (this.match(TOKEN.PLUS) || this.match(TOKEN.MINUS)) {
|
|
8075
|
+
const token = this.currentToken;
|
|
8076
|
+
this.currentToken = this.lexer.nextToken();
|
|
8077
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseMultiplicative()]);
|
|
8078
|
+
}
|
|
8079
|
+
return expr;
|
|
8080
|
+
}
|
|
8081
|
+
// Multiplicative ::= Unary (('*' | '/' | '%') Unary)*
|
|
8082
|
+
parseMultiplicative() {
|
|
8083
|
+
let expr = this.parseUnary();
|
|
8084
|
+
while (this.match(TOKEN.MULTIPLY) || this.match(TOKEN.DIVIDE) || this.match(TOKEN.MODULO)) {
|
|
8085
|
+
const token = this.currentToken;
|
|
8086
|
+
this.currentToken = this.lexer.nextToken();
|
|
8087
|
+
expr = new ASTNode(token.pos, this.input, [token.value, expr, this.parseUnary()]);
|
|
8088
|
+
}
|
|
8089
|
+
return expr;
|
|
8090
|
+
}
|
|
8091
|
+
// Unary ::= ('!' | '-')* Postfix
|
|
8092
|
+
parseUnary() {
|
|
8093
|
+
const token = this.currentToken;
|
|
8094
|
+
if (token.type === TOKEN.NOT) {
|
|
8095
|
+
this.currentToken = this.lexer.nextToken();
|
|
8096
|
+
return new ASTNode(token.pos, this.input, ["!_", this.parseUnary()]);
|
|
8097
|
+
}
|
|
8098
|
+
if (token.type === TOKEN.MINUS) {
|
|
8099
|
+
this.currentToken = this.lexer.nextToken();
|
|
8100
|
+
return new ASTNode(token.pos, this.input, ["-_", this.parseUnary()]);
|
|
8101
|
+
}
|
|
8102
|
+
return this.parsePostfix();
|
|
8103
|
+
}
|
|
8104
|
+
assertReservedIdentifier(property) {
|
|
8105
|
+
if (!RESERVED.has(property.value)) return;
|
|
8106
|
+
throw new ParseError(`Reserved identifier: ${property.value}`, {
|
|
8107
|
+
pos: property.pos,
|
|
8108
|
+
input: this.input
|
|
8109
|
+
});
|
|
8110
|
+
}
|
|
8111
|
+
// Postfix ::= Primary (('.' IDENTIFIER ('(' ArgumentList ')')? | '[' Expression ']'))*
|
|
8112
|
+
parsePostfix() {
|
|
8113
|
+
let expr = this.parsePrimary();
|
|
8114
|
+
while (true) {
|
|
8115
|
+
if (this.match(TOKEN.DOT)) {
|
|
8116
|
+
this.consume(TOKEN.DOT);
|
|
8117
|
+
const property = this.consume(TOKEN.IDENTIFIER);
|
|
8118
|
+
if (this.match(TOKEN.LPAREN)) {
|
|
8119
|
+
this.consume(TOKEN.LPAREN);
|
|
8120
|
+
const args = this.parseArgumentList();
|
|
8121
|
+
this.consume(TOKEN.RPAREN);
|
|
8122
|
+
expr = new ASTNode(property.pos, this.input, ["rcall", property.value, expr, args]);
|
|
8123
|
+
} else {
|
|
8124
|
+
expr = new ASTNode(property.pos, this.input, [".", expr, property.value]);
|
|
8125
|
+
}
|
|
8126
|
+
} else if (this.match(TOKEN.LBRACKET)) {
|
|
8127
|
+
const token = this.consume(TOKEN.LBRACKET);
|
|
8128
|
+
const index = this.parseExpression();
|
|
8129
|
+
this.consume(TOKEN.RBRACKET);
|
|
8130
|
+
expr = new ASTNode(token.pos, this.input, ["[]", expr, index]);
|
|
8131
|
+
} else {
|
|
8132
|
+
break;
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
8135
|
+
return expr;
|
|
8136
|
+
}
|
|
8137
|
+
// Primary ::= NUMBER | STRING | BOOLEAN | NULL | IDENTIFIER | '(' Expression ')' | Array | Object
|
|
8138
|
+
parsePrimary() {
|
|
8139
|
+
switch (this.currentToken.type) {
|
|
8140
|
+
case TOKEN.NUMBER: {
|
|
8141
|
+
const token = this.consume(TOKEN.NUMBER);
|
|
8142
|
+
return new ASTNode(token.pos, this.input, ["value", token.value]);
|
|
8143
|
+
}
|
|
8144
|
+
case TOKEN.STRING: {
|
|
8145
|
+
const token = this.consume(TOKEN.STRING);
|
|
8146
|
+
return new ASTNode(token.pos, this.input, ["value", token.value]);
|
|
8147
|
+
}
|
|
8148
|
+
case TOKEN.BYTES: {
|
|
8149
|
+
const token = this.consume(TOKEN.BYTES);
|
|
8150
|
+
return new ASTNode(token.pos, this.input, ["value", token.value]);
|
|
8151
|
+
}
|
|
8152
|
+
case TOKEN.BOOLEAN: {
|
|
8153
|
+
const token = this.consume(TOKEN.BOOLEAN);
|
|
8154
|
+
return new ASTNode(token.pos, this.input, ["value", token.value]);
|
|
8155
|
+
}
|
|
8156
|
+
case TOKEN.NULL: {
|
|
8157
|
+
const token = this.consume(TOKEN.NULL);
|
|
8158
|
+
return new ASTNode(token.pos, this.input, ["value", token.value]);
|
|
8159
|
+
}
|
|
8160
|
+
case TOKEN.IDENTIFIER: {
|
|
8161
|
+
const identifier = this.consume(TOKEN.IDENTIFIER);
|
|
8162
|
+
this.assertReservedIdentifier(identifier);
|
|
8163
|
+
if (this.match(TOKEN.LPAREN)) {
|
|
8164
|
+
this.consume(TOKEN.LPAREN);
|
|
8165
|
+
const args = this.parseArgumentList();
|
|
8166
|
+
this.consume(TOKEN.RPAREN);
|
|
8167
|
+
return new ASTNode(identifier.pos, this.input, ["call", identifier.value, args]);
|
|
8168
|
+
}
|
|
8169
|
+
return new ASTNode(identifier.pos, this.input, ["id", identifier.value]);
|
|
8170
|
+
}
|
|
8171
|
+
case TOKEN.LPAREN: {
|
|
8172
|
+
this.consume(TOKEN.LPAREN);
|
|
8173
|
+
const expr = this.parseExpression();
|
|
8174
|
+
this.consume(TOKEN.RPAREN);
|
|
8175
|
+
return expr;
|
|
8176
|
+
}
|
|
8177
|
+
case TOKEN.LBRACKET:
|
|
8178
|
+
return this.parseList();
|
|
8179
|
+
case TOKEN.LBRACE:
|
|
8180
|
+
return this.parseMap();
|
|
8181
|
+
}
|
|
8182
|
+
throw new ParseError(`Unexpected token: ${TOKEN_BY_NUMBER[this.currentToken.type]}`, {
|
|
8183
|
+
pos: this.currentToken.pos,
|
|
8184
|
+
input: this.input
|
|
8185
|
+
});
|
|
8186
|
+
}
|
|
8187
|
+
parseList() {
|
|
8188
|
+
const token = this.consume(TOKEN.LBRACKET);
|
|
8189
|
+
const elements = [];
|
|
8190
|
+
if (!this.match(TOKEN.RBRACKET)) {
|
|
8191
|
+
elements.push(this.parseExpression());
|
|
8192
|
+
while (this.match(TOKEN.COMMA)) {
|
|
8193
|
+
this.consume(TOKEN.COMMA);
|
|
8194
|
+
if (!this.match(TOKEN.RBRACKET)) {
|
|
8195
|
+
elements.push(this.parseExpression());
|
|
8196
|
+
}
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
this.consume(TOKEN.RBRACKET);
|
|
8200
|
+
return new ASTNode(token.pos, this.input, ["list", elements]);
|
|
8201
|
+
}
|
|
8202
|
+
parseMap() {
|
|
8203
|
+
const token = this.consume(TOKEN.LBRACE);
|
|
8204
|
+
const properties = [];
|
|
8205
|
+
if (!this.match(TOKEN.RBRACE)) {
|
|
8206
|
+
properties.push(this.parseProperty());
|
|
8207
|
+
while (this.match(TOKEN.COMMA)) {
|
|
8208
|
+
this.consume(TOKEN.COMMA);
|
|
8209
|
+
if (!this.match(TOKEN.RBRACE)) {
|
|
8210
|
+
properties.push(this.parseProperty());
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
8214
|
+
this.consume(TOKEN.RBRACE);
|
|
8215
|
+
return new ASTNode(token.pos, this.input, ["map", properties]);
|
|
8216
|
+
}
|
|
8217
|
+
parseProperty() {
|
|
8218
|
+
const key = this.parseExpression();
|
|
8219
|
+
this.consume(TOKEN.COLON);
|
|
8220
|
+
const value = this.parseExpression();
|
|
8221
|
+
return [key, value];
|
|
8222
|
+
}
|
|
8223
|
+
parseArgumentList() {
|
|
8224
|
+
const args = [];
|
|
8225
|
+
if (!this.match(TOKEN.RPAREN)) {
|
|
8226
|
+
args.push(this.parseExpression());
|
|
8227
|
+
while (this.match(TOKEN.COMMA)) {
|
|
8228
|
+
this.consume(TOKEN.COMMA);
|
|
8229
|
+
if (!this.match(TOKEN.RPAREN)) {
|
|
8230
|
+
args.push(this.parseExpression());
|
|
8231
|
+
}
|
|
8232
|
+
}
|
|
8233
|
+
}
|
|
8234
|
+
return args;
|
|
8235
|
+
}
|
|
8236
|
+
};
|
|
8237
|
+
|
|
8238
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/functions.js
|
|
8239
|
+
var UnsignedInt = class {
|
|
8240
|
+
#value;
|
|
8241
|
+
constructor(value) {
|
|
8242
|
+
this.verify(BigInt(value));
|
|
8243
|
+
}
|
|
8244
|
+
get value() {
|
|
8245
|
+
return this.#value;
|
|
8246
|
+
}
|
|
8247
|
+
valueOf() {
|
|
8248
|
+
return this.#value;
|
|
8249
|
+
}
|
|
8250
|
+
verify(v) {
|
|
8251
|
+
if (v < 0n || v > 18446744073709551615n) throw new EvaluationError("Unsigned integer overflow");
|
|
8252
|
+
this.#value = v;
|
|
8253
|
+
}
|
|
8254
|
+
get [Symbol.toStringTag]() {
|
|
8255
|
+
return `value = ${this.#value}`;
|
|
8256
|
+
}
|
|
8257
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
8258
|
+
return `UnsignedInteger { value: ${this.#value} }`;
|
|
8259
|
+
}
|
|
8260
|
+
};
|
|
8261
|
+
var UNIT_NANOSECONDS = {
|
|
8262
|
+
h: 3600000000000n,
|
|
8263
|
+
m: 60000000000n,
|
|
8264
|
+
s: 1000000000n,
|
|
8265
|
+
ms: 1000000n,
|
|
8266
|
+
us: 1000n,
|
|
8267
|
+
\u00B5s: 1000n,
|
|
8268
|
+
ns: 1n
|
|
8269
|
+
};
|
|
8270
|
+
var Duration = class _Duration {
|
|
8271
|
+
#seconds;
|
|
8272
|
+
#nanos;
|
|
8273
|
+
constructor(seconds, nanos = 0) {
|
|
8274
|
+
this.#seconds = BigInt(seconds);
|
|
8275
|
+
this.#nanos = nanos;
|
|
8276
|
+
}
|
|
8277
|
+
get seconds() {
|
|
8278
|
+
return this.#seconds;
|
|
8279
|
+
}
|
|
8280
|
+
get nanos() {
|
|
8281
|
+
return this.#nanos;
|
|
8282
|
+
}
|
|
8283
|
+
valueOf() {
|
|
8284
|
+
return Number(this.#seconds) * 1e3 + this.#nanos / 1e6;
|
|
8285
|
+
}
|
|
8286
|
+
addDuration(other) {
|
|
8287
|
+
const nanos = this.#nanos + other.nanos;
|
|
8288
|
+
return new _Duration(
|
|
8289
|
+
this.#seconds + other.seconds + BigInt(Math.floor(nanos / 1e9)),
|
|
8290
|
+
nanos % 1e9
|
|
8291
|
+
);
|
|
8292
|
+
}
|
|
8293
|
+
subtractDuration(other) {
|
|
8294
|
+
const nanos = this.#nanos - other.nanos;
|
|
8295
|
+
return new _Duration(
|
|
8296
|
+
this.#seconds - other.seconds + BigInt(Math.floor(nanos / 1e9)),
|
|
8297
|
+
(nanos + 1e9) % 1e9
|
|
8298
|
+
);
|
|
8299
|
+
}
|
|
8300
|
+
extendTimestamp(ts) {
|
|
8301
|
+
return new Date(
|
|
8302
|
+
ts.getTime() + Number(this.#seconds) * 1e3 + Math.floor(this.#nanos / 1e6)
|
|
8303
|
+
);
|
|
8304
|
+
}
|
|
8305
|
+
subtractTimestamp(ts) {
|
|
8306
|
+
return new Date(
|
|
8307
|
+
ts.getTime() - Number(this.#seconds) * 1e3 - Math.floor(this.#nanos / 1e6)
|
|
8308
|
+
);
|
|
8309
|
+
}
|
|
8310
|
+
toString() {
|
|
8311
|
+
const nanos = this.#nanos ? (this.#nanos / 1e9).toLocaleString("en-US", { useGrouping: false, maximumFractionDigits: 9 }).slice(1) : "";
|
|
8312
|
+
return `${this.#seconds}${nanos}s`;
|
|
8313
|
+
}
|
|
8314
|
+
getHours() {
|
|
8315
|
+
return this.#seconds / 3600n;
|
|
8316
|
+
}
|
|
8317
|
+
getMinutes() {
|
|
8318
|
+
return this.#seconds / 60n;
|
|
8319
|
+
}
|
|
8320
|
+
getSeconds() {
|
|
8321
|
+
return this.#seconds;
|
|
8322
|
+
}
|
|
8323
|
+
getMilliseconds() {
|
|
8324
|
+
return this.#seconds * 1000n + BigInt(Math.floor(this.#nanos / 1e6));
|
|
8325
|
+
}
|
|
8326
|
+
get [Symbol.toStringTag]() {
|
|
8327
|
+
return "google.protobuf.Duration";
|
|
8328
|
+
}
|
|
8329
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
8330
|
+
return `google.protobuf.Duration { seconds: ${this.#seconds}, nanos: ${this.#nanos} }`;
|
|
8331
|
+
}
|
|
8332
|
+
};
|
|
8333
|
+
function registerFunctions(registry) {
|
|
8334
|
+
const functionOverload = (sig, handler) => registry.registerFunctionOverload(sig, handler);
|
|
8335
|
+
const identity = (v) => v;
|
|
8336
|
+
functionOverload("has(ast): bool", function(ast) {
|
|
8337
|
+
const selector = ast[2][0];
|
|
8338
|
+
if (selector[0] === ".") return hasNestedField(this, selector, ast) !== void 0;
|
|
8339
|
+
throw new EvaluationError("has() invalid argument", ast);
|
|
8340
|
+
});
|
|
8341
|
+
function hasNestedField(ev, selector, ast) {
|
|
8342
|
+
switch (selector[0]) {
|
|
8343
|
+
case "id":
|
|
8344
|
+
return ev.eval(selector);
|
|
8345
|
+
case ".": {
|
|
8346
|
+
const obj = hasNestedField(ev, selector[1], ast);
|
|
8347
|
+
if (!obj) throw new EvaluationError(`No such key: ${selector[2]}`, selector);
|
|
8348
|
+
const type = ev.debugType(obj);
|
|
8349
|
+
return type.fieldLazy(obj, selector[2], ast, ev);
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
throw new EvaluationError("has() invalid argument", ast);
|
|
8353
|
+
}
|
|
8354
|
+
functionOverload("dyn(dyn): dyn", identity);
|
|
8355
|
+
for (const _t in TYPES) {
|
|
8356
|
+
const type = TYPES[_t];
|
|
8357
|
+
if (!(type instanceof Type2)) continue;
|
|
8358
|
+
functionOverload(`type(${type.name}): type`, () => type);
|
|
8359
|
+
}
|
|
8360
|
+
functionOverload("bool(bool): bool", identity);
|
|
8361
|
+
functionOverload("bool(string): bool", (v) => {
|
|
8362
|
+
switch (v) {
|
|
8363
|
+
case "1":
|
|
8364
|
+
case "t":
|
|
8365
|
+
case "true":
|
|
8366
|
+
case "TRUE":
|
|
8367
|
+
case "True":
|
|
8368
|
+
return true;
|
|
8369
|
+
case "0":
|
|
8370
|
+
case "f":
|
|
8371
|
+
case "false":
|
|
8372
|
+
case "FALSE":
|
|
8373
|
+
case "False":
|
|
8374
|
+
return false;
|
|
8375
|
+
default:
|
|
8376
|
+
throw new EvaluationError(`bool() conversion error: invalid string value "${v}"`);
|
|
8377
|
+
}
|
|
8378
|
+
});
|
|
8379
|
+
const objectKeys = Object.keys;
|
|
8380
|
+
functionOverload("size(string): int", (v) => BigInt(stringSize(v)));
|
|
8381
|
+
functionOverload("size(bytes): int", (v) => BigInt(v.length));
|
|
8382
|
+
functionOverload("size(list): int", (v) => BigInt(v.length ?? v.size));
|
|
8383
|
+
functionOverload(
|
|
8384
|
+
"size(map): int",
|
|
8385
|
+
(v) => BigInt(v instanceof Map ? v.size : objectKeys(v).length)
|
|
8386
|
+
);
|
|
8387
|
+
functionOverload("string.size(): int", (v) => BigInt(stringSize(v)));
|
|
8388
|
+
functionOverload("bytes.size(): int", (v) => BigInt(v.length));
|
|
8389
|
+
functionOverload("list.size(): int", (v) => BigInt(v.length ?? v.size));
|
|
8390
|
+
functionOverload(
|
|
8391
|
+
"map.size(): int",
|
|
8392
|
+
(v) => BigInt(v instanceof Map ? v.size : objectKeys(v).length)
|
|
8393
|
+
);
|
|
8394
|
+
functionOverload("bytes(string): bytes", (v) => ByteOpts.fromString(v));
|
|
8395
|
+
functionOverload("bytes(bytes): bytes", identity);
|
|
8396
|
+
functionOverload("double(double): double", identity);
|
|
8397
|
+
functionOverload("double(int): double", (v) => Number(v));
|
|
8398
|
+
functionOverload("double(string): double", (v) => {
|
|
8399
|
+
if (!v || v !== v.trim())
|
|
8400
|
+
throw new EvaluationError("double() type error: cannot convert to double");
|
|
8401
|
+
const s = v.toLowerCase();
|
|
8402
|
+
switch (s) {
|
|
8403
|
+
case "inf":
|
|
8404
|
+
case "+inf":
|
|
8405
|
+
case "infinity":
|
|
8406
|
+
case "+infinity":
|
|
8407
|
+
return Number.POSITIVE_INFINITY;
|
|
8408
|
+
case "-inf":
|
|
8409
|
+
case "-infinity":
|
|
8410
|
+
return Number.NEGATIVE_INFINITY;
|
|
8411
|
+
case "nan":
|
|
8412
|
+
return Number.NaN;
|
|
8413
|
+
default: {
|
|
8414
|
+
const parsed = Number(v);
|
|
8415
|
+
if (!Number.isNaN(parsed)) return parsed;
|
|
8416
|
+
throw new EvaluationError("double() type error: cannot convert to double");
|
|
8417
|
+
}
|
|
8418
|
+
}
|
|
8419
|
+
});
|
|
8420
|
+
functionOverload("int(int): int", identity);
|
|
8421
|
+
functionOverload("int(double): int", (v) => {
|
|
8422
|
+
if (Number.isFinite(v)) return BigInt(Math.trunc(v));
|
|
8423
|
+
throw new EvaluationError("int() type error: integer overflow");
|
|
8424
|
+
});
|
|
8425
|
+
functionOverload("int(string): int", (v) => {
|
|
8426
|
+
if (v !== v.trim() || v.length > 20 || v.includes("0x")) {
|
|
8427
|
+
throw new EvaluationError("int() type error: cannot convert to int");
|
|
8428
|
+
}
|
|
8429
|
+
try {
|
|
8430
|
+
const num = BigInt(v);
|
|
8431
|
+
if (num <= 9223372036854775807n && num >= -9223372036854775808n) return num;
|
|
8432
|
+
} catch (_e) {
|
|
8433
|
+
}
|
|
8434
|
+
throw new EvaluationError("int() type error: cannot convert to int");
|
|
8435
|
+
});
|
|
8436
|
+
functionOverload("uint(uint): uint", identity);
|
|
8437
|
+
functionOverload("uint(double): uint", (v) => {
|
|
8438
|
+
if (Number.isFinite(v)) return BigInt(Math.trunc(v));
|
|
8439
|
+
throw new EvaluationError("int() type error: integer overflow");
|
|
8440
|
+
});
|
|
8441
|
+
functionOverload("uint(string): uint", (v) => {
|
|
8442
|
+
if (v !== v.trim() || v.length > 20 || v.includes("0x")) {
|
|
8443
|
+
throw new EvaluationError("uint() type error: cannot convert to uint");
|
|
8444
|
+
}
|
|
8445
|
+
try {
|
|
8446
|
+
const num = BigInt(v);
|
|
8447
|
+
if (num <= 18446744073709551615n && num >= 0n) return num;
|
|
8448
|
+
} catch (_e) {
|
|
8449
|
+
}
|
|
8450
|
+
throw new EvaluationError("uint() type error: cannot convert to uint");
|
|
8451
|
+
});
|
|
8452
|
+
functionOverload("string(string): string", identity);
|
|
8453
|
+
functionOverload("string(bool): string", (v) => `${v}`);
|
|
8454
|
+
functionOverload("string(int): string", (v) => `${v}`);
|
|
8455
|
+
functionOverload("string(bytes): string", (v) => ByteOpts.toUtf8(v));
|
|
8456
|
+
functionOverload("string(double): string", (v) => {
|
|
8457
|
+
if (v === Infinity) return "+Inf";
|
|
8458
|
+
if (v === -Infinity) return "-Inf";
|
|
8459
|
+
return `${v}`;
|
|
8460
|
+
});
|
|
8461
|
+
functionOverload("string.startsWith(string): bool", (a, b) => a.startsWith(b));
|
|
8462
|
+
functionOverload("string.endsWith(string): bool", (a, b) => a.endsWith(b));
|
|
8463
|
+
functionOverload("string.contains(string): bool", (a, b) => a.includes(b));
|
|
8464
|
+
functionOverload(
|
|
8465
|
+
"string.indexOf(string): bool",
|
|
8466
|
+
(string, search) => BigInt(string.indexOf(search))
|
|
8467
|
+
);
|
|
8468
|
+
functionOverload("string.indexOf(string, int): bool", (string, search, fromIndex) => {
|
|
8469
|
+
if (search === "") return fromIndex;
|
|
8470
|
+
fromIndex = Number(fromIndex);
|
|
8471
|
+
if (fromIndex < 0 || fromIndex >= string.length) {
|
|
8472
|
+
throw new EvaluationError("string.indexOf(search, fromIndex): fromIndex out of range");
|
|
8473
|
+
}
|
|
8474
|
+
return BigInt(string.indexOf(search, fromIndex));
|
|
8475
|
+
});
|
|
8476
|
+
functionOverload(
|
|
8477
|
+
"string.lastIndexOf(string): bool",
|
|
8478
|
+
(string, search) => BigInt(string.lastIndexOf(search))
|
|
8479
|
+
);
|
|
8480
|
+
functionOverload("string.lastIndexOf(string, int): bool", (string, search, fromIndex) => {
|
|
8481
|
+
if (search === "") return fromIndex;
|
|
8482
|
+
fromIndex = Number(fromIndex);
|
|
8483
|
+
if (fromIndex < 0 || fromIndex >= string.length) {
|
|
8484
|
+
throw new EvaluationError("string.lastIndexOf(search, fromIndex): fromIndex out of range");
|
|
8485
|
+
}
|
|
8486
|
+
return BigInt(string.lastIndexOf(search, fromIndex));
|
|
8487
|
+
});
|
|
8488
|
+
functionOverload("string.substring(int): string", (string, start) => {
|
|
8489
|
+
start = Number(start);
|
|
8490
|
+
if (start < 0 || start > string.length) {
|
|
8491
|
+
throw new EvaluationError("string.substring(start, end): start index out of range");
|
|
8492
|
+
}
|
|
8493
|
+
return string.substring(start);
|
|
8494
|
+
});
|
|
8495
|
+
functionOverload("string.substring(int, int): string", (string, start, end) => {
|
|
8496
|
+
start = Number(start);
|
|
8497
|
+
if (start < 0 || start > string.length) {
|
|
8498
|
+
throw new EvaluationError("string.substring(start, end): start index out of range");
|
|
8499
|
+
}
|
|
8500
|
+
end = Number(end);
|
|
8501
|
+
if (end < start || end > string.length) {
|
|
8502
|
+
throw new EvaluationError("string.substring(start, end): end index out of range");
|
|
8503
|
+
}
|
|
8504
|
+
return string.substring(start, end);
|
|
8505
|
+
});
|
|
8506
|
+
functionOverload("string.matches(string): bool", (a, b) => {
|
|
8507
|
+
try {
|
|
8508
|
+
return new RegExp(b).test(a);
|
|
8509
|
+
} catch (_err) {
|
|
8510
|
+
throw new EvaluationError(`Invalid regular expression: ${b}`);
|
|
8511
|
+
}
|
|
8512
|
+
});
|
|
8513
|
+
functionOverload("string.split(string): list", (s, sep) => s.split(sep));
|
|
8514
|
+
functionOverload("string.split(string, int): list", (s, sep, l) => s.split(sep, l));
|
|
8515
|
+
functionOverload("list.join(): string", (v) => {
|
|
8516
|
+
for (let i = 0; i < v.length; i++) {
|
|
8517
|
+
if (typeof v[i] !== "string") {
|
|
8518
|
+
throw new EvaluationError("string.join(): list must contain only strings");
|
|
8519
|
+
}
|
|
8520
|
+
}
|
|
8521
|
+
return v.join("");
|
|
8522
|
+
});
|
|
8523
|
+
functionOverload("list.join(string): string", (v, sep) => {
|
|
8524
|
+
for (let i = 0; i < v.length; i++) {
|
|
8525
|
+
if (typeof v[i] !== "string") {
|
|
8526
|
+
throw new EvaluationError("string.join(separator): list must contain only strings");
|
|
8527
|
+
}
|
|
8528
|
+
}
|
|
8529
|
+
return v.join(sep);
|
|
8530
|
+
});
|
|
8531
|
+
const textEncoder = new TextEncoder("utf8");
|
|
8532
|
+
const textDecoder = new TextDecoder("utf8");
|
|
8533
|
+
const ByteOpts = typeof Buffer !== "undefined" ? {
|
|
8534
|
+
byteLength: (v) => Buffer.byteLength(v),
|
|
8535
|
+
fromString: (str) => Buffer.from(str, "utf8"),
|
|
8536
|
+
toHex: (b) => Buffer.prototype.hexSlice.call(b, 0, b.length),
|
|
8537
|
+
toBase64: (b) => Buffer.prototype.base64Slice.call(b, 0, b.length),
|
|
8538
|
+
toUtf8: (b) => Buffer.prototype.utf8Slice.call(b, 0, b.length),
|
|
8539
|
+
jsonParse: (b) => JSON.parse(b)
|
|
8540
|
+
} : {
|
|
8541
|
+
textEncoder: new TextEncoder("utf8"),
|
|
8542
|
+
byteLength: (v) => textEncoder.encode(v).length,
|
|
8543
|
+
fromString: (str) => textEncoder.encode(str),
|
|
8544
|
+
toHex: Uint8Array.prototype.toHex ? (b) => b.toHex() : (b) => Array.from(b, (i) => i.toString(16).padStart(2, "0")).join(""),
|
|
8545
|
+
toBase64: Uint8Array.prototype.toBase64 ? (b) => b.toBase64() : (b) => btoa(Array.from(b, (i) => String.fromCodePoint(i)).join("")),
|
|
8546
|
+
toUtf8: (b) => textDecoder.decode(b),
|
|
8547
|
+
jsonParse: (b) => JSON.parse(textEncoder.decode(b))
|
|
8548
|
+
};
|
|
8549
|
+
functionOverload("bytes.json(): map", ByteOpts.jsonParse);
|
|
8550
|
+
functionOverload("bytes.hex(): string", ByteOpts.toHex);
|
|
8551
|
+
functionOverload("bytes.string(): string", ByteOpts.toUtf8);
|
|
8552
|
+
functionOverload("bytes.base64(): string", ByteOpts.toBase64);
|
|
8553
|
+
functionOverload("bytes.at(int): int", (b, index) => {
|
|
8554
|
+
if (index < 0 || index >= b.length) throw new EvaluationError("Bytes index out of range");
|
|
8555
|
+
return BigInt(b[index]);
|
|
8556
|
+
});
|
|
8557
|
+
const TS = "google.protobuf.Timestamp";
|
|
8558
|
+
function tzDate(d, timeZone) {
|
|
8559
|
+
return new Date(d.toLocaleString("en-US", { timeZone }));
|
|
8560
|
+
}
|
|
8561
|
+
function getDayOfYear(d, tz) {
|
|
8562
|
+
const workingDate = tz ? tzDate(d, tz) : new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
|
|
8563
|
+
const start = new Date(workingDate.getFullYear(), 0, 0);
|
|
8564
|
+
return BigInt(Math.floor((workingDate - start) / 864e5) - 1);
|
|
8565
|
+
}
|
|
8566
|
+
functionOverload(`timestamp(string): ${TS}`, (v) => {
|
|
8567
|
+
if (v.length < 20 || v.length > 30) {
|
|
8568
|
+
throw new EvaluationError("timestamp() requires a string in ISO 8601 format");
|
|
8569
|
+
}
|
|
8570
|
+
const d = new Date(v);
|
|
8571
|
+
if (d <= 253402300799999 && d >= -621355968e5) return d;
|
|
8572
|
+
throw new EvaluationError("timestamp() requires a string in ISO 8601 format");
|
|
8573
|
+
});
|
|
8574
|
+
functionOverload(`timestamp(int): ${TS}`, (i) => {
|
|
8575
|
+
i = Number(i) * 1e3;
|
|
8576
|
+
if (i <= 253402300799999 && i >= -621355968e5) return new Date(i);
|
|
8577
|
+
throw new EvaluationError("timestamp() requires a valid integer unix timestamp");
|
|
8578
|
+
});
|
|
8579
|
+
functionOverload(`${TS}.getDate(): int`, (d) => BigInt(d.getUTCDate()));
|
|
8580
|
+
functionOverload(`${TS}.getDate(string): int`, (d, tz) => BigInt(tzDate(d, tz).getDate()));
|
|
8581
|
+
functionOverload(`${TS}.getDayOfMonth(): int`, (d) => BigInt(d.getUTCDate() - 1));
|
|
8582
|
+
functionOverload(
|
|
8583
|
+
`${TS}.getDayOfMonth(string): int`,
|
|
8584
|
+
(d, tz) => BigInt(tzDate(d, tz).getDate() - 1)
|
|
8585
|
+
);
|
|
8586
|
+
functionOverload(`${TS}.getDayOfWeek(): int`, (d) => BigInt(d.getUTCDay()));
|
|
8587
|
+
functionOverload(`${TS}.getDayOfWeek(string): int`, (d, tz) => BigInt(tzDate(d, tz).getDay()));
|
|
8588
|
+
functionOverload(`${TS}.getDayOfYear(): int`, getDayOfYear);
|
|
8589
|
+
functionOverload(`${TS}.getDayOfYear(string): int`, getDayOfYear);
|
|
8590
|
+
functionOverload(`${TS}.getFullYear(): int`, (d) => BigInt(d.getUTCFullYear()));
|
|
8591
|
+
functionOverload(`${TS}.getFullYear(string): int`, (d, tz) => BigInt(tzDate(d, tz).getFullYear()));
|
|
8592
|
+
functionOverload(`${TS}.getHours(): int`, (d) => BigInt(d.getUTCHours()));
|
|
8593
|
+
functionOverload(`${TS}.getHours(string): int`, (d, tz) => BigInt(tzDate(d, tz).getHours()));
|
|
8594
|
+
functionOverload(`${TS}.getMilliseconds(): int`, (d) => BigInt(d.getUTCMilliseconds()));
|
|
8595
|
+
functionOverload(`${TS}.getMilliseconds(string): int`, (d) => BigInt(d.getUTCMilliseconds()));
|
|
8596
|
+
functionOverload(`${TS}.getMinutes(): int`, (d) => BigInt(d.getUTCMinutes()));
|
|
8597
|
+
functionOverload(`${TS}.getMinutes(string): int`, (d, tz) => BigInt(tzDate(d, tz).getMinutes()));
|
|
8598
|
+
functionOverload(`${TS}.getMonth(): int`, (d) => BigInt(d.getUTCMonth()));
|
|
8599
|
+
functionOverload(`${TS}.getMonth(string): int`, (d, tz) => BigInt(tzDate(d, tz).getMonth()));
|
|
8600
|
+
functionOverload(`${TS}.getSeconds(): int`, (d) => BigInt(d.getUTCSeconds()));
|
|
8601
|
+
functionOverload(`${TS}.getSeconds(string): int`, (d, tz) => BigInt(tzDate(d, tz).getSeconds()));
|
|
8602
|
+
const parseDurationPattern = /(\d*\.?\d*)(ns|us|µs|ms|s|m|h)/;
|
|
8603
|
+
function parseDuration(string) {
|
|
8604
|
+
if (!string) throw new EvaluationError(`Invalid duration string: ''`);
|
|
8605
|
+
const isNegative = string[0] === "-";
|
|
8606
|
+
if (string[0] === "-" || string[0] === "+") string = string.slice(1);
|
|
8607
|
+
let nanoseconds = BigInt(0);
|
|
8608
|
+
while (true) {
|
|
8609
|
+
const match = parseDurationPattern.exec(string);
|
|
8610
|
+
if (!match) throw new EvaluationError(`Invalid duration string: ${string}`);
|
|
8611
|
+
if (match.index !== 0) throw new EvaluationError(`Invalid duration string: ${string}`);
|
|
8612
|
+
string = string.slice(match[0].length);
|
|
8613
|
+
const unitNanos = UNIT_NANOSECONDS[match[2]];
|
|
8614
|
+
const [intPart = "0", fracPart = ""] = match[1].split(".");
|
|
8615
|
+
const intVal = BigInt(intPart) * unitNanos;
|
|
8616
|
+
const fracNanos = fracPart ? BigInt(fracPart.slice(0, 13).padEnd(13, "0")) * unitNanos / 10000000000000n : 0n;
|
|
8617
|
+
nanoseconds += intVal + fracNanos;
|
|
8618
|
+
if (string === "") break;
|
|
8619
|
+
}
|
|
8620
|
+
const seconds = nanoseconds >= 1000000000n ? nanoseconds / 1000000000n : 0n;
|
|
8621
|
+
const nanos = Number(nanoseconds % 1000000000n);
|
|
8622
|
+
if (isNegative) return new Duration(-seconds, -nanos);
|
|
8623
|
+
return new Duration(seconds, nanos);
|
|
8624
|
+
}
|
|
8625
|
+
functionOverload(`duration(string): google.protobuf.Duration`, (s) => parseDuration(s));
|
|
8626
|
+
functionOverload(`google.protobuf.Duration.getHours(): int`, (d) => d.getHours());
|
|
8627
|
+
functionOverload(`google.protobuf.Duration.getMinutes(): int`, (d) => d.getMinutes());
|
|
8628
|
+
functionOverload(`google.protobuf.Duration.getSeconds(): int`, (d) => d.getSeconds());
|
|
8629
|
+
functionOverload(`google.protobuf.Duration.getMilliseconds(): int`, (d) => d.getMilliseconds());
|
|
8630
|
+
function getIterableElementType(receiverType, checker) {
|
|
8631
|
+
if (receiverType.type === "list") return receiverType.valueType;
|
|
8632
|
+
if (receiverType.type === "map") return receiverType.keyType;
|
|
8633
|
+
return checker.getType("dyn");
|
|
8634
|
+
}
|
|
8635
|
+
function validateIdentifierArg(args, functionDesc) {
|
|
8636
|
+
const identArg = args[0];
|
|
8637
|
+
if (identArg instanceof ASTNode && identArg[0] === "id") return identArg[1];
|
|
8638
|
+
throw new TypeError2(`${functionDesc} requires first argument to be an identifier`, identArg);
|
|
8639
|
+
}
|
|
8640
|
+
function predicateTypeCheck(methodName) {
|
|
8641
|
+
return (checker, receiverType, args) => {
|
|
8642
|
+
const varName = validateIdentifierArg(args, `${methodName}(var, predicate)`);
|
|
8643
|
+
const elementType = getIterableElementType(receiverType, checker);
|
|
8644
|
+
const scopedChecker = checker.createOverlay(varName, elementType);
|
|
8645
|
+
const predicateType = scopedChecker.check(args[1]);
|
|
8646
|
+
if (predicateType.isDynOrBool()) return predicateType;
|
|
8647
|
+
throw new TypeError2(`predicate must return bool, got '${predicateType}'`, args[1]);
|
|
8648
|
+
};
|
|
8649
|
+
}
|
|
8650
|
+
function mapTypeCheck(checker, receiverType, args) {
|
|
8651
|
+
const funcDesc = `map(var, ${args.length === 3 ? "filter, " : ""}transform)`;
|
|
8652
|
+
const varName = validateIdentifierArg(args, funcDesc);
|
|
8653
|
+
const elementType = getIterableElementType(receiverType, checker);
|
|
8654
|
+
const scopedChecker = checker.createOverlay(varName, elementType);
|
|
8655
|
+
if (args.length === 3) {
|
|
8656
|
+
const filterType = scopedChecker.check(args[1]);
|
|
8657
|
+
if (!filterType.isDynOrBool()) {
|
|
8658
|
+
throw new TypeError2(
|
|
8659
|
+
`${funcDesc} filter predicate must return bool, got '${filterType}'`,
|
|
8660
|
+
args[1]
|
|
8661
|
+
);
|
|
8662
|
+
}
|
|
8663
|
+
}
|
|
8664
|
+
return checker.getType(`list<${scopedChecker.check(args[args.length - 1])}>`);
|
|
8665
|
+
}
|
|
8666
|
+
function filterTypeCheck(checker, receiverType, args) {
|
|
8667
|
+
const funcDesc = `filter(var, filter)`;
|
|
8668
|
+
const varName = validateIdentifierArg(args, funcDesc);
|
|
8669
|
+
const elementType = getIterableElementType(receiverType, checker);
|
|
8670
|
+
const scopedChecker = checker.createOverlay(varName, elementType);
|
|
8671
|
+
const filterType = scopedChecker.check(args[1]);
|
|
8672
|
+
if (filterType.isDynOrBool()) return checker.getType(`list<${elementType}>`);
|
|
8673
|
+
throw new TypeError2(`${funcDesc} predicate must return bool, got '${filterType}'`, args[1]);
|
|
8674
|
+
}
|
|
8675
|
+
functionOverload("list.all(ast, ast): bool", {
|
|
8676
|
+
handler: allMacro,
|
|
8677
|
+
typeCheck: predicateTypeCheck("all")
|
|
8678
|
+
});
|
|
8679
|
+
functionOverload("map.all(ast, ast): bool", {
|
|
8680
|
+
handler: allMacro,
|
|
8681
|
+
typeCheck: predicateTypeCheck("all")
|
|
8682
|
+
});
|
|
8683
|
+
functionOverload("list.exists(ast, ast): bool", {
|
|
8684
|
+
handler: existsMacro,
|
|
8685
|
+
typeCheck: predicateTypeCheck("exists")
|
|
8686
|
+
});
|
|
8687
|
+
functionOverload("map.exists(ast, ast): bool", {
|
|
8688
|
+
handler: existsMacro,
|
|
8689
|
+
typeCheck: predicateTypeCheck("exists")
|
|
8690
|
+
});
|
|
8691
|
+
functionOverload("list.exists_one(ast, ast): bool", {
|
|
8692
|
+
handler: existsOneMacro,
|
|
8693
|
+
typeCheck: predicateTypeCheck("exists_one")
|
|
8694
|
+
});
|
|
8695
|
+
functionOverload("map.exists_one(ast, ast): bool", {
|
|
8696
|
+
handler: existsOneMacro,
|
|
8697
|
+
typeCheck: predicateTypeCheck("exists_one")
|
|
8698
|
+
});
|
|
8699
|
+
functionOverload("list.map(ast, ast): list", { handler: mapMacro, typeCheck: mapTypeCheck });
|
|
8700
|
+
functionOverload("list.map(ast, ast, ast): list", {
|
|
8701
|
+
handler: filterMapMacro,
|
|
8702
|
+
typeCheck: mapTypeCheck
|
|
8703
|
+
});
|
|
8704
|
+
functionOverload("map.map(ast, ast): list", { handler: mapMacro, typeCheck: mapTypeCheck });
|
|
8705
|
+
functionOverload("map.map(ast, ast, ast): list", {
|
|
8706
|
+
handler: filterMapMacro,
|
|
8707
|
+
typeCheck: mapTypeCheck
|
|
8708
|
+
});
|
|
8709
|
+
functionOverload("list.filter(ast, ast): list", {
|
|
8710
|
+
handler: filterMacro,
|
|
8711
|
+
typeCheck: filterTypeCheck
|
|
8712
|
+
});
|
|
8713
|
+
functionOverload("map.filter(ast, ast): list", { handler: filterMacro, typeCheck: filterTypeCheck });
|
|
8714
|
+
}
|
|
8715
|
+
var kPredicateEvaluator = Symbol("predicateEvaluator");
|
|
8716
|
+
function allMacro(receiver, ast) {
|
|
8717
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8718
|
+
"all(var, predicate)",
|
|
8719
|
+
ast
|
|
8720
|
+
);
|
|
8721
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8722
|
+
let error = null;
|
|
8723
|
+
for (let i = 0; i < items.length; i++) {
|
|
8724
|
+
try {
|
|
8725
|
+
if (evaluator.childEvaluateBool(items[i])) continue;
|
|
8726
|
+
return false;
|
|
8727
|
+
} catch (e) {
|
|
8728
|
+
if (e.message.includes("Unknown variable")) throw e;
|
|
8729
|
+
if (e.message.includes("predicate result is not a boolean")) throw e;
|
|
8730
|
+
error ??= e;
|
|
8731
|
+
}
|
|
8732
|
+
}
|
|
8733
|
+
if (error) throw error;
|
|
8734
|
+
return true;
|
|
8735
|
+
}
|
|
8736
|
+
function existsMacro(receiver, ast) {
|
|
8737
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8738
|
+
"exists(var, predicate)",
|
|
8739
|
+
ast
|
|
8740
|
+
);
|
|
8741
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8742
|
+
let error;
|
|
8743
|
+
for (let i = 0; i < items.length; i++) {
|
|
8744
|
+
try {
|
|
8745
|
+
if (evaluator.childEvaluateBool(items[i])) return true;
|
|
8746
|
+
} catch (e) {
|
|
8747
|
+
if (e.message.includes("Unknown variable")) throw e;
|
|
8748
|
+
if (e.message.includes("predicate result is not a boolean")) throw e;
|
|
8749
|
+
error ??= e;
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
if (error) throw error;
|
|
8753
|
+
return false;
|
|
8754
|
+
}
|
|
8755
|
+
function existsOneMacro(receiver, ast) {
|
|
8756
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8757
|
+
"exists_one(var, predicate)",
|
|
8758
|
+
ast
|
|
8759
|
+
);
|
|
8760
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8761
|
+
let count = 0;
|
|
8762
|
+
for (let i = 0; i < items.length; i++) {
|
|
8763
|
+
if (evaluator.childEvaluateBool(items[i]) === false) continue;
|
|
8764
|
+
if (++count > 1) return false;
|
|
8765
|
+
}
|
|
8766
|
+
return count === 1;
|
|
8767
|
+
}
|
|
8768
|
+
function mapMacro(receiver, ast) {
|
|
8769
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8770
|
+
"map(var, transform)",
|
|
8771
|
+
ast
|
|
8772
|
+
);
|
|
8773
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8774
|
+
const results = [];
|
|
8775
|
+
for (let i = 0; i < items.length; i++) results[i] = evaluator.childEvaluate(items[i]);
|
|
8776
|
+
return results;
|
|
8777
|
+
}
|
|
8778
|
+
function filterMapMacro(receiver, ast) {
|
|
8779
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8780
|
+
"map(var, filter, transform)",
|
|
8781
|
+
ast
|
|
8782
|
+
);
|
|
8783
|
+
const transform = ast[3][2];
|
|
8784
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8785
|
+
const results = [];
|
|
8786
|
+
for (let i = 0; i < items.length; i++) {
|
|
8787
|
+
switch (evaluator.childEvaluateBool(items[i])) {
|
|
8788
|
+
case false:
|
|
8789
|
+
continue;
|
|
8790
|
+
case true:
|
|
8791
|
+
results.push(evaluator.eval(transform));
|
|
8792
|
+
continue;
|
|
8793
|
+
}
|
|
8794
|
+
}
|
|
8795
|
+
return results;
|
|
8796
|
+
}
|
|
8797
|
+
function filterMacro(receiver, ast) {
|
|
8798
|
+
const evaluator = ast[kPredicateEvaluator] ??= this.predicateEvaluator(
|
|
8799
|
+
"filter(var, predicate)",
|
|
8800
|
+
ast
|
|
8801
|
+
);
|
|
8802
|
+
const items = evaluator.getIterableItems(receiver);
|
|
8803
|
+
const results = [];
|
|
8804
|
+
for (let i = 0; i < items.length; i++) {
|
|
8805
|
+
const item = items[i];
|
|
8806
|
+
if (evaluator.childEvaluateBool(item) === false) continue;
|
|
8807
|
+
results.push(item);
|
|
8808
|
+
}
|
|
8809
|
+
return results;
|
|
8810
|
+
}
|
|
8811
|
+
function stringSize(str) {
|
|
8812
|
+
let count = 0;
|
|
8813
|
+
for (const c of str) count++;
|
|
8814
|
+
return count;
|
|
8815
|
+
}
|
|
8816
|
+
|
|
8817
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/registry.js
|
|
8818
|
+
var Type2 = class {
|
|
8819
|
+
#name;
|
|
8820
|
+
constructor(name) {
|
|
8821
|
+
this.#name = name;
|
|
8822
|
+
Object.freeze(this);
|
|
8823
|
+
}
|
|
8824
|
+
get name() {
|
|
8825
|
+
return this.#name;
|
|
8826
|
+
}
|
|
8827
|
+
get [Symbol.toStringTag]() {
|
|
8828
|
+
return `Type<${this.#name}>`;
|
|
8829
|
+
}
|
|
8830
|
+
toString() {
|
|
8831
|
+
return `Type<${this.#name}>`;
|
|
8832
|
+
}
|
|
8833
|
+
};
|
|
8834
|
+
var TYPES = {
|
|
8835
|
+
string: new Type2("string"),
|
|
8836
|
+
bool: new Type2("bool"),
|
|
8837
|
+
int: new Type2("int"),
|
|
8838
|
+
uint: new Type2("uint"),
|
|
8839
|
+
double: new Type2("double"),
|
|
8840
|
+
map: new Type2("map"),
|
|
8841
|
+
list: new Type2("list"),
|
|
8842
|
+
bytes: new Type2("bytes"),
|
|
8843
|
+
null_type: new Type2("null"),
|
|
8844
|
+
type: new Type2("type"),
|
|
8845
|
+
google: {
|
|
8846
|
+
protobuf: {
|
|
8847
|
+
Timestamp: new Type2("google.protobuf.Timestamp"),
|
|
8848
|
+
Duration: new Type2("google.protobuf.Duration")
|
|
8849
|
+
}
|
|
8850
|
+
}
|
|
8851
|
+
};
|
|
8852
|
+
TYPES["google.protobuf.Timestamp"] = TYPES.google.protobuf.Timestamp;
|
|
8853
|
+
TYPES["google.protobuf.Duration"] = TYPES.google.protobuf.Duration;
|
|
8854
|
+
var LayeredMap = class _LayeredMap {
|
|
8855
|
+
#parent = null;
|
|
8856
|
+
#entries = null;
|
|
8857
|
+
constructor(source) {
|
|
8858
|
+
if (source instanceof _LayeredMap) {
|
|
8859
|
+
this.#parent = source;
|
|
8860
|
+
this.#entries = /* @__PURE__ */ new Map();
|
|
8861
|
+
} else {
|
|
8862
|
+
this.#entries = new Map(source);
|
|
8863
|
+
}
|
|
8864
|
+
}
|
|
8865
|
+
fork(lock = true) {
|
|
8866
|
+
if (lock) this.set = this.#throwLocked;
|
|
8867
|
+
return new this.constructor(this);
|
|
8868
|
+
}
|
|
8869
|
+
#throwLocked() {
|
|
8870
|
+
throw new Error("Cannot modify frozen registry");
|
|
8871
|
+
}
|
|
8872
|
+
set(key, value) {
|
|
8873
|
+
this.#entries.set(key, value);
|
|
8874
|
+
return this;
|
|
8875
|
+
}
|
|
8876
|
+
has(key) {
|
|
8877
|
+
return this.#entries.has(key) || (this.#parent ? this.#parent.has(key) : false);
|
|
8878
|
+
}
|
|
8879
|
+
get(key) {
|
|
8880
|
+
return this.#entries.get(key) || this.#parent?.get(key);
|
|
8881
|
+
}
|
|
8882
|
+
*#entryIterator() {
|
|
8883
|
+
if (this.#parent) yield* this.#parent;
|
|
8884
|
+
yield* this.#entries;
|
|
8885
|
+
}
|
|
8886
|
+
[Symbol.iterator]() {
|
|
8887
|
+
return this.#entryIterator();
|
|
8888
|
+
}
|
|
8889
|
+
get size() {
|
|
8890
|
+
return this.#entries.size + (this.#parent ? this.#parent.size : 0);
|
|
8891
|
+
}
|
|
8892
|
+
};
|
|
8893
|
+
var DynVariableRegistry = class extends LayeredMap {
|
|
8894
|
+
constructor(source = null, marker = null) {
|
|
8895
|
+
super(source, marker);
|
|
8896
|
+
}
|
|
8897
|
+
get(name) {
|
|
8898
|
+
const value = super.get(name);
|
|
8899
|
+
return value === void 0 ? dynType : value;
|
|
8900
|
+
}
|
|
8901
|
+
};
|
|
8902
|
+
function createLayeredMap(source, MapCtor = LayeredMap, lock = true) {
|
|
8903
|
+
if (source instanceof MapCtor) return source.fork(lock);
|
|
8904
|
+
return new MapCtor(source);
|
|
8905
|
+
}
|
|
8906
|
+
var TypeDeclaration = class {
|
|
8907
|
+
#matchesCache = /* @__PURE__ */ new WeakMap();
|
|
8908
|
+
constructor({ kind, type, name, keyType, valueType, values }) {
|
|
8909
|
+
this.kind = kind;
|
|
8910
|
+
this.type = type;
|
|
8911
|
+
this.name = name;
|
|
8912
|
+
if (keyType) this.keyType = keyType;
|
|
8913
|
+
if (valueType) this.valueType = valueType;
|
|
8914
|
+
if (values) this.values = values;
|
|
8915
|
+
if (kind === "list") this.fieldLazy = this.#getListField;
|
|
8916
|
+
else if (kind === "map") this.fieldLazy = this.#getMapField;
|
|
8917
|
+
else if (kind === "message") this.fieldLazy = this.#getMessageField;
|
|
8918
|
+
else if (kind === "dyn") this.fieldLazy = this.#getMapField;
|
|
8919
|
+
Object.freeze(this);
|
|
8920
|
+
}
|
|
8921
|
+
isDynOrBool() {
|
|
8922
|
+
return this.type === "bool" || this.kind === "dyn";
|
|
8923
|
+
}
|
|
8924
|
+
toString() {
|
|
8925
|
+
return this.name;
|
|
8926
|
+
}
|
|
8927
|
+
#getMessageField(obj, key, ast, ev) {
|
|
8928
|
+
const type = ev.objectTypesByConstructor.get(obj.constructor);
|
|
8929
|
+
if (!type) return;
|
|
8930
|
+
if (!type.fields) return Object.hasOwn(obj, key) ? obj[key] : void 0;
|
|
8931
|
+
const valueType = type.fields[key];
|
|
8932
|
+
if (!valueType) return;
|
|
8933
|
+
const value = obj[key];
|
|
8934
|
+
if (valueType.kind === "dyn") return value;
|
|
8935
|
+
const actualType = ev.debugType(value);
|
|
8936
|
+
if (valueType.matches(actualType)) return value;
|
|
8937
|
+
throw new EvaluationError(
|
|
8938
|
+
`Field '${key}' is not of type '${valueType}', got '${actualType}'`,
|
|
8939
|
+
ast
|
|
8940
|
+
);
|
|
8941
|
+
}
|
|
8942
|
+
#getMapField(obj, key, ast, ev) {
|
|
8943
|
+
let value;
|
|
8944
|
+
if (obj instanceof Map) value = obj.get(key);
|
|
8945
|
+
else value = Object.hasOwn(obj, key) ? obj[key] : void 0;
|
|
8946
|
+
if (value === void 0) return;
|
|
8947
|
+
if (this.valueType.kind === "dyn") return value;
|
|
8948
|
+
const type = ev.debugType(value);
|
|
8949
|
+
if (this.valueType.matches(type)) return value;
|
|
8950
|
+
throw new EvaluationError(
|
|
8951
|
+
`Field '${key}' is not of type '${this.valueType}', got '${type}'`,
|
|
8952
|
+
ast
|
|
8953
|
+
);
|
|
8954
|
+
}
|
|
8955
|
+
#getListField(obj, key, ast, ev) {
|
|
8956
|
+
if (!(typeof key === "number" || typeof key === "bigint")) return;
|
|
8957
|
+
const value = obj[key];
|
|
8958
|
+
if (value === void 0) {
|
|
8959
|
+
throw new EvaluationError(
|
|
8960
|
+
`No such key: index out of bounds, index ${key} ${key < 0 ? "< 0" : `>= size ${obj.length}`}`,
|
|
8961
|
+
ast
|
|
8962
|
+
);
|
|
8963
|
+
}
|
|
8964
|
+
const type = ev.debugType(value);
|
|
8965
|
+
if (this.valueType.matches(type)) return value;
|
|
8966
|
+
throw new EvaluationError(
|
|
8967
|
+
`List item with index '${key}' is not of type '${this.valueType}', got '${type}'`,
|
|
8968
|
+
ast
|
|
8969
|
+
);
|
|
8970
|
+
}
|
|
8971
|
+
fieldLazy() {
|
|
8972
|
+
}
|
|
8973
|
+
field(obj, key, ast, ev) {
|
|
8974
|
+
const v = this.fieldLazy(obj, key, ast, ev);
|
|
8975
|
+
if (v !== void 0) return v;
|
|
8976
|
+
throw new EvaluationError(`No such key: ${key}`, ast);
|
|
8977
|
+
}
|
|
8978
|
+
matchesBoth(other) {
|
|
8979
|
+
return this.matches(other) && other.matches(this);
|
|
8980
|
+
}
|
|
8981
|
+
matches(other) {
|
|
8982
|
+
return this.#matchesCache.get(other) ?? this.#matchesCache.set(other, this.#matches(other)).get(other);
|
|
8983
|
+
}
|
|
8984
|
+
#matches(other) {
|
|
8985
|
+
if (this === other) return true;
|
|
8986
|
+
if (other.kind === "dyn") return other.valueType ? this.matches(other.valueType) : true;
|
|
8987
|
+
switch (this.kind) {
|
|
8988
|
+
case "dyn":
|
|
8989
|
+
return true;
|
|
8990
|
+
case "list":
|
|
8991
|
+
return other.kind === "list" && this.valueType.matches(other.valueType);
|
|
8992
|
+
case "map":
|
|
8993
|
+
return other.kind === "map" && this.keyType.matches(other.keyType) && this.valueType.matches(other.valueType);
|
|
8994
|
+
default:
|
|
8995
|
+
return this.name === other.name;
|
|
8996
|
+
}
|
|
8997
|
+
}
|
|
8998
|
+
};
|
|
8999
|
+
var FunctionDeclaration = class {
|
|
9000
|
+
constructor({ name, receiverType, argTypes, returnType, handler, typeCheck }) {
|
|
9001
|
+
this.name = name;
|
|
9002
|
+
this.macro = argTypes.includes(astType);
|
|
9003
|
+
this.receiverType = receiverType || null;
|
|
9004
|
+
this.argTypes = argTypes;
|
|
9005
|
+
this.returnType = returnType;
|
|
9006
|
+
const receiverString = receiverType ? `${receiverType}.` : "";
|
|
9007
|
+
this.signature = `${receiverString}${name}(${argTypes.join(", ")}): ${returnType}`;
|
|
9008
|
+
this.handler = handler;
|
|
9009
|
+
this.typeCheck = typeCheck;
|
|
9010
|
+
Object.freeze(this);
|
|
9011
|
+
}
|
|
9012
|
+
matchesArgs(argTypes) {
|
|
9013
|
+
if (argTypes.length !== this.argTypes.length) return false;
|
|
9014
|
+
return this.argTypes.every((t, i) => t.matches(argTypes[i]));
|
|
9015
|
+
}
|
|
9016
|
+
};
|
|
9017
|
+
var OperatorDeclaration = class {
|
|
9018
|
+
constructor({ operator, leftType, rightType, handler, returnType }) {
|
|
9019
|
+
this.operator = operator;
|
|
9020
|
+
this.leftType = leftType;
|
|
9021
|
+
this.rightType = rightType || null;
|
|
9022
|
+
this.handler = handler;
|
|
9023
|
+
this.returnType = returnType;
|
|
9024
|
+
if (rightType) this.signature = `${leftType} ${operator} ${rightType}: ${returnType}`;
|
|
9025
|
+
else this.signature = `${operator}${leftType}: ${returnType}`;
|
|
9026
|
+
Object.freeze(this);
|
|
9027
|
+
}
|
|
9028
|
+
get isUnary() {
|
|
9029
|
+
return this.rightType === null;
|
|
9030
|
+
}
|
|
9031
|
+
get isBinary() {
|
|
9032
|
+
return this.rightType !== null;
|
|
9033
|
+
}
|
|
9034
|
+
equals(other) {
|
|
9035
|
+
return this.operator === other.operator && this.leftType === other.leftType && this.rightType === other.rightType;
|
|
9036
|
+
}
|
|
9037
|
+
};
|
|
9038
|
+
function _createListType(valueType) {
|
|
9039
|
+
return new TypeDeclaration({
|
|
9040
|
+
kind: "list",
|
|
9041
|
+
name: `list<${valueType}>`,
|
|
9042
|
+
type: "list",
|
|
9043
|
+
valueType
|
|
9044
|
+
});
|
|
9045
|
+
}
|
|
9046
|
+
function _createPrimitiveType(name) {
|
|
9047
|
+
return new TypeDeclaration({
|
|
9048
|
+
kind: "primitive",
|
|
9049
|
+
name,
|
|
9050
|
+
type: name
|
|
9051
|
+
});
|
|
9052
|
+
}
|
|
9053
|
+
function _createMessageType(name) {
|
|
9054
|
+
return new TypeDeclaration({
|
|
9055
|
+
kind: "message",
|
|
9056
|
+
name,
|
|
9057
|
+
type: name
|
|
9058
|
+
});
|
|
9059
|
+
}
|
|
9060
|
+
function _createDynType(valueType) {
|
|
9061
|
+
const name = valueType ? `dyn<${valueType}>` : "dyn";
|
|
9062
|
+
return new TypeDeclaration({
|
|
9063
|
+
kind: "dyn",
|
|
9064
|
+
name,
|
|
9065
|
+
type: name,
|
|
9066
|
+
valueType
|
|
9067
|
+
});
|
|
9068
|
+
}
|
|
9069
|
+
function _createMapType(keyType, valueType) {
|
|
9070
|
+
return new TypeDeclaration({
|
|
9071
|
+
kind: "map",
|
|
9072
|
+
name: `map<${keyType}, ${valueType}>`,
|
|
9073
|
+
type: "map",
|
|
9074
|
+
keyType,
|
|
9075
|
+
valueType
|
|
9076
|
+
});
|
|
9077
|
+
}
|
|
9078
|
+
var dynType = _createDynType();
|
|
9079
|
+
var astType = _createPrimitiveType("ast");
|
|
9080
|
+
var listType = _createListType(dynType);
|
|
9081
|
+
var mapType = _createMapType(dynType, dynType);
|
|
9082
|
+
var celTypes = Object.freeze({
|
|
9083
|
+
string: _createPrimitiveType("string"),
|
|
9084
|
+
bool: _createPrimitiveType("bool"),
|
|
9085
|
+
int: _createPrimitiveType("int"),
|
|
9086
|
+
uint: _createPrimitiveType("uint"),
|
|
9087
|
+
double: _createPrimitiveType("double"),
|
|
9088
|
+
bytes: _createPrimitiveType("bytes"),
|
|
9089
|
+
dyn: dynType,
|
|
9090
|
+
null: _createPrimitiveType("null"),
|
|
9091
|
+
type: _createPrimitiveType("type"),
|
|
9092
|
+
"google.protobuf.Timestamp": _createPrimitiveType("google.protobuf.Timestamp"),
|
|
9093
|
+
"google.protobuf.Duration": _createPrimitiveType("google.protobuf.Duration"),
|
|
9094
|
+
list: listType,
|
|
9095
|
+
"list<dyn>": listType,
|
|
9096
|
+
map: mapType,
|
|
9097
|
+
"map<dyn, dyn>": mapType
|
|
9098
|
+
});
|
|
9099
|
+
var FunctionsByReceiver = class {
|
|
9100
|
+
/** @type {Array<FunctionDeclaration>} */
|
|
9101
|
+
functions = [];
|
|
9102
|
+
exists = false;
|
|
9103
|
+
hasMacro = false;
|
|
9104
|
+
add(decl) {
|
|
9105
|
+
this.exists = true;
|
|
9106
|
+
if (decl.macro) this.hasMacro = true;
|
|
9107
|
+
this.functions.push(decl);
|
|
9108
|
+
}
|
|
9109
|
+
findMatch(argTypes) {
|
|
9110
|
+
if (!this.exists) return null;
|
|
9111
|
+
for (const fn of this.functions) {
|
|
9112
|
+
if (fn.matchesArgs(argTypes)) return fn;
|
|
9113
|
+
}
|
|
9114
|
+
return null;
|
|
9115
|
+
}
|
|
9116
|
+
};
|
|
9117
|
+
var NO_RECEIVER = new FunctionsByReceiver();
|
|
9118
|
+
var FunctionCandidates = class {
|
|
9119
|
+
exists = false;
|
|
9120
|
+
hasMacro = false;
|
|
9121
|
+
returnType = null;
|
|
9122
|
+
/** @type {Map<string|null, FunctionsByReceiver>} */
|
|
9123
|
+
#byReceiverType = /* @__PURE__ */ new Map();
|
|
9124
|
+
add(declaration) {
|
|
9125
|
+
this.exists = true;
|
|
9126
|
+
if (declaration.macro) this.hasMacro = true;
|
|
9127
|
+
if (!this.returnType) this.returnType = declaration.returnType;
|
|
9128
|
+
else if (declaration.typeCheck) this.returnType = dynType;
|
|
9129
|
+
else if (this.returnType !== declaration.returnType) this.returnType = dynType;
|
|
9130
|
+
const receiverType = declaration.receiverType;
|
|
9131
|
+
const coll = this.#byReceiverType.get(receiverType) || this.#byReceiverType.set(receiverType, new FunctionsByReceiver()).get(receiverType);
|
|
9132
|
+
coll.add(declaration);
|
|
9133
|
+
}
|
|
9134
|
+
filterByReceiverType(receiverType) {
|
|
9135
|
+
if (receiverType === null) return this.#byReceiverType.get(null) || NO_RECEIVER;
|
|
9136
|
+
return (
|
|
9137
|
+
// First try exact match
|
|
9138
|
+
this.#byReceiverType.get(receiverType) || // For generic types, also try matching with the base type
|
|
9139
|
+
// e.g., if looking for list<string>, also check list<dyn>
|
|
9140
|
+
(receiverType.type === "list" || receiverType.type === "map" ? this.#byReceiverType.get(celTypes[receiverType.type]) : null) || NO_RECEIVER
|
|
9141
|
+
);
|
|
9142
|
+
}
|
|
9143
|
+
};
|
|
9144
|
+
function splitByComma(str) {
|
|
9145
|
+
const parts = [];
|
|
9146
|
+
let current2 = "";
|
|
9147
|
+
let depth = 0;
|
|
9148
|
+
for (const char of str) {
|
|
9149
|
+
if (char === "<") depth++;
|
|
9150
|
+
else if (char === ">") depth--;
|
|
9151
|
+
else if (char === "," && depth === 0) {
|
|
9152
|
+
parts.push(current2);
|
|
9153
|
+
current2 = "";
|
|
9154
|
+
continue;
|
|
9155
|
+
}
|
|
9156
|
+
current2 += char;
|
|
9157
|
+
}
|
|
9158
|
+
if (current2) parts.push(current2);
|
|
9159
|
+
return parts;
|
|
9160
|
+
}
|
|
9161
|
+
var builtinObjectTypes = [
|
|
9162
|
+
[void 0, "map"],
|
|
9163
|
+
[Object, "map"],
|
|
9164
|
+
[Map, "map"],
|
|
9165
|
+
[Array, "list"],
|
|
9166
|
+
[Uint8Array, "bytes"],
|
|
9167
|
+
[Date, "google.protobuf.Timestamp"],
|
|
9168
|
+
[Duration, "google.protobuf.Duration"],
|
|
9169
|
+
[UnsignedInt, "uint"],
|
|
9170
|
+
[Type2, "type"]
|
|
9171
|
+
];
|
|
9172
|
+
if (typeof Buffer !== "undefined") builtinObjectTypes.push([Buffer, "bytes"]);
|
|
9173
|
+
var Registry = class _Registry {
|
|
9174
|
+
#overloadResolutionCache = {};
|
|
9175
|
+
#overloadCheckCache = {};
|
|
9176
|
+
#typeDeclarations;
|
|
9177
|
+
#operatorDeclarations;
|
|
9178
|
+
#functionDeclarations;
|
|
9179
|
+
#dynTypes = /* @__PURE__ */ new Map();
|
|
9180
|
+
constructor(opts = {}) {
|
|
9181
|
+
this.objectTypes = createLayeredMap(opts.objectTypes);
|
|
9182
|
+
this.objectTypesByConstructor = createLayeredMap(opts.objectTypesByConstructor);
|
|
9183
|
+
this.objectTypeInstances = createLayeredMap(opts.objectTypeInstances);
|
|
9184
|
+
this.#functionDeclarations = createLayeredMap(opts.functionDeclarations);
|
|
9185
|
+
this.#operatorDeclarations = createLayeredMap(opts.operatorDeclarations);
|
|
9186
|
+
this.#typeDeclarations = createLayeredMap(
|
|
9187
|
+
opts.typeDeclarations || Object.entries(celTypes),
|
|
9188
|
+
void 0,
|
|
9189
|
+
false
|
|
9190
|
+
);
|
|
9191
|
+
this.variables = opts.unlistedVariablesAreDyn ? createLayeredMap(opts.variables, DynVariableRegistry) : createLayeredMap(opts.variables);
|
|
9192
|
+
if (!this.variables.size) {
|
|
9193
|
+
for (const [instance, name] of builtinObjectTypes) {
|
|
9194
|
+
this.registerType(name, instance, true);
|
|
9195
|
+
}
|
|
9196
|
+
const globalValues2 = new Map(Object.entries(TYPES));
|
|
9197
|
+
for (const [name, type] of globalValues2) {
|
|
9198
|
+
if (!(type instanceof Type2)) continue;
|
|
9199
|
+
this.registerVariable(name, "type");
|
|
9200
|
+
}
|
|
9201
|
+
}
|
|
9202
|
+
}
|
|
9203
|
+
#invalidateOverloadsCache() {
|
|
9204
|
+
this.#overloadResolutionCache = {};
|
|
9205
|
+
this.#overloadCheckCache = {};
|
|
9206
|
+
}
|
|
9207
|
+
registerVariable(name, type) {
|
|
9208
|
+
if (this.variables.has(name)) throw new Error(`Variable already registered: ${name}`);
|
|
9209
|
+
this.variables.set(name, type instanceof TypeDeclaration ? type : this.getType(type));
|
|
9210
|
+
return this;
|
|
9211
|
+
}
|
|
9212
|
+
getFunctionCandidates(receiverType, functionName, argCount) {
|
|
9213
|
+
const candidates = new FunctionCandidates();
|
|
9214
|
+
for (const [, dec] of this.#functionDeclarations) {
|
|
9215
|
+
if (functionName !== dec.name) continue;
|
|
9216
|
+
if (receiverType === null && dec.receiverType) continue;
|
|
9217
|
+
if (receiverType && dec.receiverType === null) continue;
|
|
9218
|
+
candidates.exists = true;
|
|
9219
|
+
if (dec.macro) candidates.hasMacro = true;
|
|
9220
|
+
if (receiverType && !receiverType.matches(dec.receiverType)) continue;
|
|
9221
|
+
if (dec.argTypes.length !== argCount) continue;
|
|
9222
|
+
candidates.add(dec);
|
|
9223
|
+
}
|
|
9224
|
+
return candidates;
|
|
9225
|
+
}
|
|
9226
|
+
getType(typename) {
|
|
9227
|
+
return this.#parseTypeString(typename, true);
|
|
9228
|
+
}
|
|
9229
|
+
getDynType(type) {
|
|
9230
|
+
return this.#dynTypes.get(type) || this.#dynTypes.set(type, this.#parseTypeString(`dyn<${type}>`, true)).get(type);
|
|
9231
|
+
}
|
|
9232
|
+
assertType(typename, type, signature) {
|
|
9233
|
+
try {
|
|
9234
|
+
return this.#parseTypeString(typename, true);
|
|
9235
|
+
} catch (e) {
|
|
9236
|
+
e.message = `Invalid ${type} '${e.unknownType || typename}' in '${signature}'`;
|
|
9237
|
+
throw e;
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9240
|
+
getFunctionType(typename) {
|
|
9241
|
+
if (typename === "ast") return astType;
|
|
9242
|
+
return this.#parseTypeString(typename, true);
|
|
9243
|
+
}
|
|
9244
|
+
registerType(typename, _d, withoutDynRegistration) {
|
|
9245
|
+
const decl = {
|
|
9246
|
+
name: typename,
|
|
9247
|
+
type: this.#parseTypeString(typename, false),
|
|
9248
|
+
ctor: typeof _d === "function" ? _d : _d?.ctor,
|
|
9249
|
+
fields: this.#normalizeFields(typename, _d?.fields)
|
|
9250
|
+
};
|
|
9251
|
+
if (!withoutDynRegistration) {
|
|
9252
|
+
if (this.objectTypes.has(typename)) throw new Error(`Type already registered: ${typename}`);
|
|
9253
|
+
if (typeof decl.ctor !== "function") {
|
|
9254
|
+
throw new Error(`Constructor function missing for type '${typename}'`);
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9257
|
+
this.objectTypes.set(typename, decl);
|
|
9258
|
+
this.objectTypesByConstructor.set(decl.ctor, decl);
|
|
9259
|
+
if (withoutDynRegistration) return;
|
|
9260
|
+
const type = new Type2(typename);
|
|
9261
|
+
this.objectTypeInstances.set(typename, type);
|
|
9262
|
+
this.registerFunctionOverload(`type(${typename}): type`, () => type);
|
|
9263
|
+
}
|
|
9264
|
+
/** @returns {TypeDeclaration} */
|
|
9265
|
+
#parseTypeString(typeStr, requireKnownTypes = false) {
|
|
9266
|
+
const existing = this.#typeDeclarations.get(typeStr);
|
|
9267
|
+
if (existing) return existing;
|
|
9268
|
+
const dynMatch = typeStr.match(/^dyn<(.+)>$/);
|
|
9269
|
+
if (dynMatch) {
|
|
9270
|
+
const type = this.#parseTypeString(dynMatch[1].trim(), requireKnownTypes);
|
|
9271
|
+
return this.#createDeclaration(_createDynType, `dyn<${type}>`, type);
|
|
9272
|
+
}
|
|
9273
|
+
const listMatch = typeStr.match(/^list<(.+)>$/);
|
|
9274
|
+
if (listMatch) {
|
|
9275
|
+
const vType = this.#parseTypeString(listMatch[1].trim(), requireKnownTypes);
|
|
9276
|
+
return this.#createDeclaration(_createListType, `list<${vType}>`, vType);
|
|
9277
|
+
}
|
|
9278
|
+
const mapMatch = typeStr.match(/^map<(.+)>$/);
|
|
9279
|
+
if (mapMatch) {
|
|
9280
|
+
const parts = splitByComma(mapMatch[1]);
|
|
9281
|
+
if (parts.length !== 2) throw new Error(`Invalid map type: ${typeStr}`);
|
|
9282
|
+
const kType = this.#parseTypeString(parts[0].trim(), requireKnownTypes);
|
|
9283
|
+
const vType = this.#parseTypeString(parts[1].trim(), requireKnownTypes);
|
|
9284
|
+
return this.#createDeclaration(_createMapType, `map<${kType}, ${vType}>`, kType, vType);
|
|
9285
|
+
}
|
|
9286
|
+
if (requireKnownTypes) {
|
|
9287
|
+
const err = new Error(`Unknown type: ${typeStr}`);
|
|
9288
|
+
err.unknownType = typeStr;
|
|
9289
|
+
throw err;
|
|
9290
|
+
}
|
|
9291
|
+
return this.#createDeclaration(_createMessageType, typeStr, typeStr);
|
|
9292
|
+
}
|
|
9293
|
+
#createDeclaration(creator, key, ...args) {
|
|
9294
|
+
return this.#typeDeclarations.get(key) || this.#typeDeclarations.set(key, creator(...args)).get(key);
|
|
9295
|
+
}
|
|
9296
|
+
#findBinaryOverloads(operator, leftType, rightType) {
|
|
9297
|
+
const nonexactMatches = [];
|
|
9298
|
+
for (const [, decl] of this.#operatorDeclarations) {
|
|
9299
|
+
if (decl.operator !== operator) continue;
|
|
9300
|
+
if (this.#exactMatch(decl, leftType, rightType)) return [decl];
|
|
9301
|
+
if (this.#matchesOverload(decl, leftType, rightType)) nonexactMatches.push(decl);
|
|
9302
|
+
}
|
|
9303
|
+
if (nonexactMatches.length === 0 && (operator === "==" || operator === "!=") && this.#hasDynOperand(leftType, rightType)) {
|
|
9304
|
+
const handler = operator === "==" ? (a, b) => a === b : (a, b) => a !== b;
|
|
9305
|
+
return [{ handler, returnType: this.getType("bool") }];
|
|
9306
|
+
}
|
|
9307
|
+
return nonexactMatches;
|
|
9308
|
+
}
|
|
9309
|
+
findUnaryOverload(op, left) {
|
|
9310
|
+
const cached = this.#overloadResolutionCache[op]?.get(left);
|
|
9311
|
+
if (cached !== void 0) return cached;
|
|
9312
|
+
let value = false;
|
|
9313
|
+
for (const [, decl] of this.#operatorDeclarations) {
|
|
9314
|
+
if (decl.operator !== op || decl.leftType !== left) continue;
|
|
9315
|
+
value = decl;
|
|
9316
|
+
break;
|
|
9317
|
+
}
|
|
9318
|
+
return (this.#overloadResolutionCache[op] ??= /* @__PURE__ */ new Map()).set(left, value).get(left);
|
|
9319
|
+
}
|
|
9320
|
+
findBinaryOverload(op, left, right) {
|
|
9321
|
+
return this.#overloadResolutionCache[op]?.get(left)?.get(right) ?? this.#cacheOverloadResult(
|
|
9322
|
+
this.#overloadResolutionCache,
|
|
9323
|
+
op,
|
|
9324
|
+
left,
|
|
9325
|
+
right,
|
|
9326
|
+
this.#findBinaryOverloadUncached(op, left, right)
|
|
9327
|
+
);
|
|
9328
|
+
}
|
|
9329
|
+
checkBinaryOverload(op, left, right) {
|
|
9330
|
+
return this.#overloadCheckCache[op]?.get(left)?.get(right) ?? this.#cacheOverloadResult(
|
|
9331
|
+
this.#overloadCheckCache,
|
|
9332
|
+
op,
|
|
9333
|
+
left,
|
|
9334
|
+
right,
|
|
9335
|
+
this.#checkBinaryOverloadUncached(op, left, right)
|
|
9336
|
+
);
|
|
9337
|
+
}
|
|
9338
|
+
#findBinaryOverloadUncached(operator, leftType, rightType) {
|
|
9339
|
+
const ops = this.#findBinaryOverloads(operator, leftType, rightType);
|
|
9340
|
+
if (ops.length === 0) return false;
|
|
9341
|
+
if (ops.length === 1) return ops[0];
|
|
9342
|
+
throw new Error(`Operator overload '${ops[0].signature}' overlaps with '${ops[1].signature}'.`);
|
|
9343
|
+
}
|
|
9344
|
+
#checkBinaryOverloadUncached(op, left, right) {
|
|
9345
|
+
const ops = this.#findBinaryOverloads(op, left, right);
|
|
9346
|
+
if (ops.length === 0) return false;
|
|
9347
|
+
const firstType = ops[0].returnType;
|
|
9348
|
+
if (ops.every((d) => d.returnType === firstType)) return firstType;
|
|
9349
|
+
if ((firstType.kind === "list" || firstType.kind === "map") && ops.every((d) => d.returnType.kind === firstType.kind)) {
|
|
9350
|
+
return firstType.kind === "list" ? celTypes.list : celTypes.map;
|
|
9351
|
+
}
|
|
9352
|
+
return celTypes.dyn;
|
|
9353
|
+
}
|
|
9354
|
+
#cacheOverloadResult(cache, op, left, right, result) {
|
|
9355
|
+
const opMap = cache[op] ??= /* @__PURE__ */ new Map();
|
|
9356
|
+
const leftMap = opMap.get(left) || opMap.set(left, /* @__PURE__ */ new Map()).get(left);
|
|
9357
|
+
leftMap.set(right, result);
|
|
9358
|
+
return result;
|
|
9359
|
+
}
|
|
9360
|
+
#exactMatch(decl, actualLeft, actualRight) {
|
|
9361
|
+
return actualLeft === decl.leftType && actualRight === decl.rightType || actualLeft.name === `dyn<${decl.leftType}>` && actualRight === decl.rightType || actualLeft === decl.leftType && actualRight.name === `dyn<${decl.rightType}>` || actualLeft.name === `dyn<${decl.leftType}>` && actualRight.name === `dyn<${decl.rightType}>`;
|
|
9362
|
+
}
|
|
9363
|
+
#matchesOverload(decl, actualLeft, actualRight) {
|
|
9364
|
+
if (!this.#isAssignable(actualLeft, decl.leftType)) return false;
|
|
9365
|
+
if (!this.#isAssignable(actualRight, decl.rightType)) return false;
|
|
9366
|
+
return this.#validateParameters(decl.operator, actualLeft, actualRight);
|
|
9367
|
+
}
|
|
9368
|
+
#isAssignable(actual, declared) {
|
|
9369
|
+
if (actual === declared) return true;
|
|
9370
|
+
if (actual.kind === "dyn") {
|
|
9371
|
+
return actual.valueType ? this.#isAssignable(actual.valueType, declared) : true;
|
|
9372
|
+
}
|
|
9373
|
+
if (actual.type !== declared.type) return false;
|
|
9374
|
+
if (declared === celTypes.list) return true;
|
|
9375
|
+
if (declared === celTypes.map) return true;
|
|
9376
|
+
return false;
|
|
9377
|
+
}
|
|
9378
|
+
#validateParameters(operator, leftType, rightType) {
|
|
9379
|
+
if (operator === "in") {
|
|
9380
|
+
if (leftType.kind === "dyn") return true;
|
|
9381
|
+
if (rightType.kind === "list") return rightType.valueType.matchesBoth(leftType);
|
|
9382
|
+
if (rightType.kind === "map") return rightType.keyType.matchesBoth(leftType);
|
|
9383
|
+
return true;
|
|
9384
|
+
}
|
|
9385
|
+
if (operator === "+" || operator === "==" || operator === "!=") {
|
|
9386
|
+
if (leftType.kind === "list" && rightType.kind === "list") {
|
|
9387
|
+
return leftType.matchesBoth(rightType);
|
|
9388
|
+
}
|
|
9389
|
+
if (leftType.kind === "map" && rightType.kind === "map") {
|
|
9390
|
+
return leftType.matchesBoth(rightType);
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
return true;
|
|
9394
|
+
}
|
|
9395
|
+
#hasDynOperand(leftType, rightType) {
|
|
9396
|
+
if (leftType.kind === "dyn" || rightType.kind === "dyn") return true;
|
|
9397
|
+
return false;
|
|
9398
|
+
}
|
|
9399
|
+
#toCelFieldDeclaration(typename, fields, k, requireKnownTypes = false) {
|
|
9400
|
+
try {
|
|
9401
|
+
const field = typeof fields[k] === "string" ? { type: fields[k] } : { ...fields[k] };
|
|
9402
|
+
if (typeof field?.type !== "string") throw new Error(`unsupported declaration`);
|
|
9403
|
+
return this.#parseTypeString(field.type, requireKnownTypes);
|
|
9404
|
+
} catch (e) {
|
|
9405
|
+
e.message = `Field '${k}' in type '${typename}' has unsupported declaration: ${JSON.stringify(fields[k])}`;
|
|
9406
|
+
throw e;
|
|
9407
|
+
}
|
|
9408
|
+
}
|
|
9409
|
+
#normalizeFields(typename, fields) {
|
|
9410
|
+
if (!fields) return;
|
|
9411
|
+
const all = {};
|
|
9412
|
+
for (const k of Object.keys(fields)) all[k] = this.#toCelFieldDeclaration(typename, fields, k);
|
|
9413
|
+
return all;
|
|
9414
|
+
}
|
|
9415
|
+
clone(opts = {}) {
|
|
9416
|
+
return new _Registry({
|
|
9417
|
+
objectTypes: this.objectTypes,
|
|
9418
|
+
objectTypesByConstructor: this.objectTypesByConstructor,
|
|
9419
|
+
objectTypeInstances: this.objectTypeInstances,
|
|
9420
|
+
typeDeclarations: this.#typeDeclarations,
|
|
9421
|
+
operatorDeclarations: this.#operatorDeclarations,
|
|
9422
|
+
functionDeclarations: this.#functionDeclarations,
|
|
9423
|
+
variables: this.variables,
|
|
9424
|
+
unlistedVariablesAreDyn: opts.unlistedVariablesAreDyn
|
|
9425
|
+
});
|
|
9426
|
+
}
|
|
9427
|
+
/** @param {string} signature */
|
|
9428
|
+
#parseFunctionDeclaration(signature, handler, typeCheck) {
|
|
9429
|
+
const match = signature.match(/^(?:([a-zA-Z0-9.]+)\.)?(\w+)\((.*?)\):\s*(.+)$/);
|
|
9430
|
+
if (!match) throw new Error(`Invalid signature: ${signature}`);
|
|
9431
|
+
const [, receiverType, name, argsStr, _returnType] = match;
|
|
9432
|
+
try {
|
|
9433
|
+
return new FunctionDeclaration({
|
|
9434
|
+
name,
|
|
9435
|
+
receiverType: receiverType ? this.getType(receiverType.trim()) : null,
|
|
9436
|
+
returnType: this.getType(_returnType.trim() || "dyn"),
|
|
9437
|
+
argTypes: splitByComma(argsStr).map((s) => this.getFunctionType(s.trim())),
|
|
9438
|
+
handler,
|
|
9439
|
+
typeCheck
|
|
9440
|
+
});
|
|
9441
|
+
} catch (e) {
|
|
9442
|
+
throw new Error(`Invalid function declaration: ${signature}`);
|
|
9443
|
+
}
|
|
9444
|
+
}
|
|
9445
|
+
/**
|
|
9446
|
+
* @param {FunctionDeclaration} a
|
|
9447
|
+
* @param {FunctionDeclaration} b
|
|
9448
|
+
*/
|
|
9449
|
+
#functionSignatureOverlaps(a, b) {
|
|
9450
|
+
if (a.name !== b.name) return false;
|
|
9451
|
+
if (a.argTypes.length !== b.argTypes.length) return false;
|
|
9452
|
+
if ((a.receiverType || b.receiverType) && (!a.receiverType || !b.receiverType)) return false;
|
|
9453
|
+
const isDifferentReceiver = a.receiverType !== b.receiverType && a.receiverType !== dynType && b.receiverType !== dynType;
|
|
9454
|
+
return !isDifferentReceiver && (b.macro || a.macro || b.argTypes.every((type1, i) => {
|
|
9455
|
+
const type2 = a.argTypes[i];
|
|
9456
|
+
if (type1 === type2) return true;
|
|
9457
|
+
if (type1 === astType || type2 === astType) return true;
|
|
9458
|
+
if (type1 === dynType || type2 === dynType) return true;
|
|
9459
|
+
return false;
|
|
9460
|
+
}));
|
|
9461
|
+
}
|
|
9462
|
+
/** @param {FunctionDeclaration} newDec */
|
|
9463
|
+
#checkOverlappingSignatures(newDec) {
|
|
9464
|
+
for (const [, decl] of this.#functionDeclarations) {
|
|
9465
|
+
if (!this.#functionSignatureOverlaps(decl, newDec)) continue;
|
|
9466
|
+
throw new Error(
|
|
9467
|
+
`Function signature '${newDec.signature}' overlaps with existing overload '${decl.signature}'.`
|
|
9468
|
+
);
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
registerFunctionOverload(s, handlerOrOptions) {
|
|
9472
|
+
const handler = typeof handlerOrOptions === "function" ? handlerOrOptions : handlerOrOptions.handler;
|
|
9473
|
+
const options = typeof handlerOrOptions === "function" ? {} : handlerOrOptions;
|
|
9474
|
+
const dec = this.#parseFunctionDeclaration(s, handler, options.typeCheck);
|
|
9475
|
+
this.#checkOverlappingSignatures(dec);
|
|
9476
|
+
this.#functionDeclarations.set(dec.signature, dec);
|
|
9477
|
+
}
|
|
9478
|
+
registerOperatorOverload(string, handler) {
|
|
9479
|
+
const unaryParts = string.match(/^([-!])([\w.<>]+)(?::\s*([\w.<>]+))?$/);
|
|
9480
|
+
if (unaryParts) {
|
|
9481
|
+
const [, op2, operandType, returnType2] = unaryParts;
|
|
9482
|
+
return this.unaryOverload(op2, operandType, handler, returnType2);
|
|
9483
|
+
}
|
|
9484
|
+
const parts = string.match(
|
|
9485
|
+
/^([\w.<>]+) ([-+*%/]|==|!=|<|<=|>|>=|in) ([\w.<>]+)(?::\s*([\w.<>]+))?$/
|
|
9486
|
+
);
|
|
9487
|
+
if (!parts) throw new Error(`Operator overload invalid: ${string}`);
|
|
9488
|
+
const [, leftType, op, rightType, returnType] = parts;
|
|
9489
|
+
return this.binaryOverload(leftType, op, rightType, handler, returnType);
|
|
9490
|
+
}
|
|
9491
|
+
unaryOverload(op, typeStr, handler, returnTypeStr) {
|
|
9492
|
+
const leftType = this.assertType(typeStr, "type", `${op}${typeStr}`);
|
|
9493
|
+
const returnType = this.assertType(
|
|
9494
|
+
returnTypeStr || typeStr,
|
|
9495
|
+
"return type",
|
|
9496
|
+
`${op}${typeStr}: ${returnTypeStr || typeStr}`
|
|
9497
|
+
);
|
|
9498
|
+
const decl = new OperatorDeclaration({ operator: `${op}_`, leftType, returnType, handler });
|
|
9499
|
+
if (this.#hasOverload(decl)) {
|
|
9500
|
+
throw new Error(`Operator overload already registered: ${op}${typeStr}`);
|
|
9501
|
+
}
|
|
9502
|
+
this.#operatorDeclarations.set(decl.signature, decl);
|
|
9503
|
+
this.#invalidateOverloadsCache();
|
|
9504
|
+
}
|
|
9505
|
+
#hasOverload(decl) {
|
|
9506
|
+
for (const [, other] of this.#operatorDeclarations) if (decl.equals(other)) return true;
|
|
9507
|
+
return false;
|
|
9508
|
+
}
|
|
9509
|
+
binaryOverload(leftTypeStr, op, rightTypeStr, handler, returnTypeStr) {
|
|
9510
|
+
returnTypeStr ??= isRelational(op) ? "bool" : leftTypeStr;
|
|
9511
|
+
const sig = `${leftTypeStr} ${op} ${rightTypeStr}: ${returnTypeStr}`;
|
|
9512
|
+
const leftType = this.assertType(leftTypeStr, "left type", sig);
|
|
9513
|
+
const rightType = this.assertType(rightTypeStr, "right type", sig);
|
|
9514
|
+
const returnType = this.assertType(returnTypeStr, "return type", sig);
|
|
9515
|
+
if (isRelational(op) && returnType.type !== "bool") {
|
|
9516
|
+
throw new Error(`Comparison operator '${op}' must return 'bool', got '${returnType.type}'`);
|
|
9517
|
+
}
|
|
9518
|
+
const dec = new OperatorDeclaration({ operator: op, leftType, rightType, returnType, handler });
|
|
9519
|
+
if (this.#hasOverload(dec)) {
|
|
9520
|
+
throw new Error(`Operator overload already registered: ${dec.signature}`);
|
|
9521
|
+
}
|
|
9522
|
+
if (op === "==") {
|
|
9523
|
+
const declarations = [
|
|
9524
|
+
new OperatorDeclaration({
|
|
9525
|
+
operator: "!=",
|
|
9526
|
+
leftType,
|
|
9527
|
+
rightType,
|
|
9528
|
+
handler(a, b, ast, ev) {
|
|
9529
|
+
return !handler(a, b, ast, ev);
|
|
9530
|
+
},
|
|
9531
|
+
returnType
|
|
9532
|
+
})
|
|
9533
|
+
];
|
|
9534
|
+
if (leftType !== rightType) {
|
|
9535
|
+
declarations.push(
|
|
9536
|
+
new OperatorDeclaration({
|
|
9537
|
+
operator: "==",
|
|
9538
|
+
leftType: rightType,
|
|
9539
|
+
rightType: leftType,
|
|
9540
|
+
handler(a, b, ast, ev) {
|
|
9541
|
+
return handler(b, a, ast, ev);
|
|
9542
|
+
},
|
|
9543
|
+
returnType
|
|
9544
|
+
}),
|
|
9545
|
+
new OperatorDeclaration({
|
|
9546
|
+
operator: "!=",
|
|
9547
|
+
leftType: rightType,
|
|
9548
|
+
rightType: leftType,
|
|
9549
|
+
handler(a, b, ast, ev) {
|
|
9550
|
+
return !handler(b, a, ast, ev);
|
|
9551
|
+
},
|
|
9552
|
+
returnType
|
|
9553
|
+
})
|
|
9554
|
+
);
|
|
9555
|
+
}
|
|
9556
|
+
for (const decl of declarations) {
|
|
9557
|
+
if (!this.#hasOverload(decl)) continue;
|
|
9558
|
+
throw new Error(`Operator overload already registered: ${decl.signature}`);
|
|
9559
|
+
}
|
|
9560
|
+
for (const decl of declarations) this.#operatorDeclarations.set(decl.signature, decl);
|
|
9561
|
+
}
|
|
9562
|
+
this.#operatorDeclarations.set(dec.signature, dec);
|
|
9563
|
+
this.#invalidateOverloadsCache();
|
|
9564
|
+
}
|
|
9565
|
+
};
|
|
9566
|
+
function isRelational(op) {
|
|
9567
|
+
return op === "<" || op === "<=" || op === ">" || op === ">=" || op === "==" || op === "!=" || op === "in";
|
|
9568
|
+
}
|
|
9569
|
+
function createRegistry(opts) {
|
|
9570
|
+
return new Registry(opts);
|
|
9571
|
+
}
|
|
9572
|
+
|
|
9573
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/overloads.js
|
|
9574
|
+
function registerOverloads(registry) {
|
|
9575
|
+
const unaryOverload2 = registry.unaryOverload.bind(registry);
|
|
9576
|
+
const binaryOverload2 = registry.binaryOverload.bind(registry);
|
|
9577
|
+
function verifyInteger(v, ast) {
|
|
9578
|
+
if (v <= 9223372036854775807n && v >= -9223372036854775808n) return v;
|
|
9579
|
+
throw new EvaluationError(`integer overflow: ${v}`, ast);
|
|
9580
|
+
}
|
|
9581
|
+
unaryOverload2("!", "bool", (a) => !a);
|
|
9582
|
+
unaryOverload2("-", "int", (a) => -a);
|
|
9583
|
+
binaryOverload2("int", "*", "int", (a, b, ast) => verifyInteger(a * b, ast));
|
|
9584
|
+
binaryOverload2("int", "+", "int", (a, b, ast) => verifyInteger(a + b, ast));
|
|
9585
|
+
binaryOverload2("int", "-", "int", (a, b, ast) => verifyInteger(a - b, ast));
|
|
9586
|
+
binaryOverload2("int", "/", "int", (a, b, ast) => {
|
|
9587
|
+
if (b === 0n) throw new EvaluationError("division by zero", ast);
|
|
9588
|
+
return a / b;
|
|
9589
|
+
});
|
|
9590
|
+
binaryOverload2("int", "%", "int", (a, b, ast) => {
|
|
9591
|
+
if (b === 0n) throw new EvaluationError("modulo by zero", ast);
|
|
9592
|
+
return a % b;
|
|
9593
|
+
});
|
|
9594
|
+
unaryOverload2("-", "double", (a) => -a);
|
|
9595
|
+
binaryOverload2("double", "*", "double", (a, b) => a * b);
|
|
9596
|
+
binaryOverload2("double", "+", "double", (a, b) => a + b);
|
|
9597
|
+
binaryOverload2("double", "-", "double", (a, b) => a - b);
|
|
9598
|
+
binaryOverload2("double", "/", "double", (a, b, ast) => {
|
|
9599
|
+
if (b === 0) throw new EvaluationError("division by zero", ast);
|
|
9600
|
+
return a / b;
|
|
9601
|
+
});
|
|
9602
|
+
binaryOverload2("string", "+", "string", (a, b) => a + b);
|
|
9603
|
+
binaryOverload2("list", "+", "list", (a, b) => [...a, ...b]);
|
|
9604
|
+
binaryOverload2("bytes", "+", "bytes", (a, b) => {
|
|
9605
|
+
const result = new Uint8Array(a.length + b.length);
|
|
9606
|
+
result.set(a, 0);
|
|
9607
|
+
result.set(b, a.length);
|
|
9608
|
+
return result;
|
|
9609
|
+
});
|
|
9610
|
+
const GPD = "google.protobuf.Duration";
|
|
9611
|
+
binaryOverload2(GPD, "+", GPD, (a, b) => a.addDuration(b));
|
|
9612
|
+
binaryOverload2(GPD, "-", GPD, (a, b) => a.subtractDuration(b));
|
|
9613
|
+
binaryOverload2(GPD, "==", GPD, (a, b) => a.seconds === b.seconds && a.nanos === b.nanos);
|
|
9614
|
+
const GPT = "google.protobuf.Timestamp";
|
|
9615
|
+
binaryOverload2(GPT, "==", GPT, (a, b) => a.getTime() === b.getTime());
|
|
9616
|
+
binaryOverload2(GPT, "-", GPD, (a, b) => b.subtractTimestamp(a));
|
|
9617
|
+
binaryOverload2(GPT, "+", GPD, (a, b) => b.extendTimestamp(a));
|
|
9618
|
+
binaryOverload2(GPD, "+", GPT, (a, b) => a.extendTimestamp(b));
|
|
9619
|
+
function listIncludes(value, list, ast, ev) {
|
|
9620
|
+
if (list instanceof Set && list.has(value)) return true;
|
|
9621
|
+
for (const v of list) if (isEqual2(value, v, ev)) return true;
|
|
9622
|
+
return false;
|
|
9623
|
+
}
|
|
9624
|
+
function listStrictIncludes(value, list) {
|
|
9625
|
+
return Array.isArray(list) ? list.includes(value) : list.has(value);
|
|
9626
|
+
}
|
|
9627
|
+
for (const t of ["string", "bool", "null", "type"])
|
|
9628
|
+
binaryOverload2(t, "in", `list`, listStrictIncludes);
|
|
9629
|
+
for (const t of ["int", "double", "list", "map"]) binaryOverload2(t, "in", `list`, listIncludes);
|
|
9630
|
+
for (const t of ["string", "int", "double", "bool", "null"]) {
|
|
9631
|
+
binaryOverload2(t, "in", "map", (a, b) => {
|
|
9632
|
+
if (b instanceof Map) return b.get(a) !== void 0;
|
|
9633
|
+
return Object.hasOwn(b, a) ? b[a] !== void 0 : false;
|
|
9634
|
+
});
|
|
9635
|
+
}
|
|
9636
|
+
for (const t of ["type", "null", "bool", "string", "int", "uint", "double"]) {
|
|
9637
|
+
binaryOverload2(t, "==", t, (a, b) => a === b);
|
|
9638
|
+
}
|
|
9639
|
+
binaryOverload2("int", `==`, `dyn<double>`, (a, b) => a == b);
|
|
9640
|
+
binaryOverload2("int", `==`, `dyn<uint>`, (a, b) => a == b.valueOf());
|
|
9641
|
+
binaryOverload2("uint", `==`, `dyn<double>`, (a, b) => a.valueOf() == b);
|
|
9642
|
+
binaryOverload2("uint", `==`, `dyn<int>`, (a, b) => a.valueOf() == b);
|
|
9643
|
+
binaryOverload2("double", `==`, `dyn<int>`, (a, b) => a == b);
|
|
9644
|
+
binaryOverload2("double", `==`, `dyn<uint>`, (a, b) => a == b.valueOf());
|
|
9645
|
+
binaryOverload2("bytes", `==`, "bytes", (a, b) => {
|
|
9646
|
+
let i = a.length;
|
|
9647
|
+
if (i !== b.length) return false;
|
|
9648
|
+
while (i--) if (a[i] !== b[i]) return false;
|
|
9649
|
+
return true;
|
|
9650
|
+
});
|
|
9651
|
+
binaryOverload2("list", `==`, "list", (a, b, ast, ev) => {
|
|
9652
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
9653
|
+
const length = a.length;
|
|
9654
|
+
if (length !== b.length) return false;
|
|
9655
|
+
for (let i = 0; i < length; i++) {
|
|
9656
|
+
if (!isEqual2(a[i], b[i], ev)) return false;
|
|
9657
|
+
}
|
|
9658
|
+
return true;
|
|
9659
|
+
}
|
|
9660
|
+
if (a instanceof Set && b instanceof Set) {
|
|
9661
|
+
if (a.size !== b.size) return false;
|
|
9662
|
+
for (const value of a) if (!b.has(value)) return false;
|
|
9663
|
+
return true;
|
|
9664
|
+
}
|
|
9665
|
+
const arr = a instanceof Set ? b : a;
|
|
9666
|
+
const set4 = a instanceof Set ? a : b;
|
|
9667
|
+
if (!Array.isArray(arr)) return false;
|
|
9668
|
+
if (arr.length !== set4?.size) return false;
|
|
9669
|
+
for (let i = 0; i < arr.length; i++) if (!set4.has(arr[i])) return false;
|
|
9670
|
+
return true;
|
|
9671
|
+
});
|
|
9672
|
+
binaryOverload2("map", `==`, "map", (a, b, ast, ev) => {
|
|
9673
|
+
if (a instanceof Map && b instanceof Map) {
|
|
9674
|
+
if (a.size !== b.size) return false;
|
|
9675
|
+
for (const [key, value] of a)
|
|
9676
|
+
if (!(b.has(key) && isEqual2(value, b.get(key), ev))) return false;
|
|
9677
|
+
return true;
|
|
9678
|
+
}
|
|
9679
|
+
if (a instanceof Map || b instanceof Map) {
|
|
9680
|
+
const obj = a instanceof Map ? b : a;
|
|
9681
|
+
const map3 = a instanceof Map ? a : b;
|
|
9682
|
+
const keysObj = Object.keys(obj);
|
|
9683
|
+
if (map3.size !== keysObj.length) return false;
|
|
9684
|
+
for (const [key, value] of map3) {
|
|
9685
|
+
if (!(key in obj && isEqual2(value, obj[key], ev))) return false;
|
|
9686
|
+
}
|
|
9687
|
+
return true;
|
|
9688
|
+
}
|
|
9689
|
+
const keysA = Object.keys(a);
|
|
9690
|
+
const keysB = Object.keys(b);
|
|
9691
|
+
if (keysA.length !== keysB.length) return false;
|
|
9692
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
9693
|
+
const key = keysA[i];
|
|
9694
|
+
if (!(key in b && isEqual2(a[key], b[key], ev))) return false;
|
|
9695
|
+
}
|
|
9696
|
+
return true;
|
|
9697
|
+
});
|
|
9698
|
+
binaryOverload2("uint", "+", "uint", (a, b) => new UnsignedInt(a.valueOf() + b.valueOf()));
|
|
9699
|
+
binaryOverload2("uint", "-", "uint", (a, b) => new UnsignedInt(a.valueOf() - b.valueOf()));
|
|
9700
|
+
binaryOverload2("uint", "*", "uint", (a, b) => new UnsignedInt(a.valueOf() * b.valueOf()));
|
|
9701
|
+
binaryOverload2("uint", "/", "uint", (a, b, ast) => {
|
|
9702
|
+
if (b.valueOf() === 0n) throw new EvaluationError("division by zero", ast);
|
|
9703
|
+
return new UnsignedInt(a.valueOf() / b.valueOf());
|
|
9704
|
+
});
|
|
9705
|
+
binaryOverload2("uint", "%", "uint", (a, b, ast) => {
|
|
9706
|
+
if (b.valueOf() === 0n) throw new EvaluationError("modulo by zero", ast);
|
|
9707
|
+
return new UnsignedInt(a.valueOf() % b.valueOf());
|
|
9708
|
+
});
|
|
9709
|
+
for (const [left, right] of [
|
|
9710
|
+
["int", "int"],
|
|
9711
|
+
["uint", "uint"],
|
|
9712
|
+
["double", "double"],
|
|
9713
|
+
["string", "string"],
|
|
9714
|
+
["google.protobuf.Timestamp", "google.protobuf.Timestamp"],
|
|
9715
|
+
["google.protobuf.Duration", "google.protobuf.Duration"],
|
|
9716
|
+
["int", "uint"],
|
|
9717
|
+
["int", "double"],
|
|
9718
|
+
["double", "int"],
|
|
9719
|
+
["double", "uint"],
|
|
9720
|
+
["uint", "int"],
|
|
9721
|
+
["uint", "double"]
|
|
9722
|
+
]) {
|
|
9723
|
+
binaryOverload2(left, "<", right, (a, b) => a < b);
|
|
9724
|
+
binaryOverload2(left, "<=", right, (a, b) => a <= b);
|
|
9725
|
+
binaryOverload2(left, ">", right, (a, b) => a > b);
|
|
9726
|
+
binaryOverload2(left, ">=", right, (a, b) => a >= b);
|
|
9727
|
+
}
|
|
9728
|
+
}
|
|
9729
|
+
function isEqual2(a, b, ev) {
|
|
9730
|
+
if (a === b) return true;
|
|
9731
|
+
switch (typeof a) {
|
|
9732
|
+
case "string":
|
|
9733
|
+
return false;
|
|
9734
|
+
case "bigint":
|
|
9735
|
+
if (typeof b === "number") return a == b;
|
|
9736
|
+
return false;
|
|
9737
|
+
case "number":
|
|
9738
|
+
if (typeof b === "bigint") return a == b;
|
|
9739
|
+
return false;
|
|
9740
|
+
case "boolean":
|
|
9741
|
+
return false;
|
|
9742
|
+
case "object":
|
|
9743
|
+
if (typeof b !== "object" || a === null || b === null) return false;
|
|
9744
|
+
const leftType = ev.objectTypesByConstructor.get(a.constructor)?.type;
|
|
9745
|
+
const rightType = ev.objectTypesByConstructor.get(b.constructor)?.type;
|
|
9746
|
+
if (!leftType || leftType !== rightType) return false;
|
|
9747
|
+
const handler = ev.registry.findBinaryOverload("==", leftType, rightType)?.handler;
|
|
9748
|
+
if (!handler) return false;
|
|
9749
|
+
return handler(a, b, null, ev);
|
|
9750
|
+
}
|
|
9751
|
+
throw new EvaluationError(`Cannot compare values of type ${typeof a}`);
|
|
9752
|
+
}
|
|
9753
|
+
|
|
9754
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/type-checker.js
|
|
9755
|
+
var TypeChecker = class {
|
|
9756
|
+
constructor({ ctx, objectTypes, objectTypesByConstructor, registry }) {
|
|
9757
|
+
this.ctx = ctx;
|
|
9758
|
+
this.objectTypes = objectTypes;
|
|
9759
|
+
this.objectTypesByConstructor = objectTypesByConstructor;
|
|
9760
|
+
this.registry = registry;
|
|
9761
|
+
}
|
|
9762
|
+
/**
|
|
9763
|
+
* Get a TypeDeclaration instance for a type name
|
|
9764
|
+
* @param {string} typeName - The type name (e.g., 'string', 'int', 'dyn')
|
|
9765
|
+
* @returns {TypeDeclaration} The type declaration instance
|
|
9766
|
+
*/
|
|
9767
|
+
getType(typeName) {
|
|
9768
|
+
return this.registry.getType(typeName);
|
|
9769
|
+
}
|
|
9770
|
+
createOverlay(varName, varType) {
|
|
9771
|
+
return new this.constructor({
|
|
9772
|
+
ctx: this.ctx.createOverlay(varName, varType),
|
|
9773
|
+
objectTypes: this.objectTypes,
|
|
9774
|
+
objectTypesByConstructor: this.objectTypesByConstructor,
|
|
9775
|
+
registry: this.registry
|
|
9776
|
+
});
|
|
9777
|
+
}
|
|
9778
|
+
/**
|
|
9779
|
+
* Check an expression and return its inferred type
|
|
9780
|
+
* @param {Array|any} ast - The AST node to check
|
|
9781
|
+
* @returns {Object} The inferred type declaration
|
|
9782
|
+
* @throws {TypeError} If type checking fails
|
|
9783
|
+
*/
|
|
9784
|
+
check(ast) {
|
|
9785
|
+
if (ast.checkedType) return ast.checkedType;
|
|
9786
|
+
switch (ast[0]) {
|
|
9787
|
+
case "value":
|
|
9788
|
+
return ast.checkedType ??= this.inferLiteralType(ast[1]);
|
|
9789
|
+
case "id":
|
|
9790
|
+
return ast.checkedType ??= this.checkVariable(ast);
|
|
9791
|
+
case ".":
|
|
9792
|
+
case "[]":
|
|
9793
|
+
return ast.checkedType ??= this.checkAccess(ast);
|
|
9794
|
+
case "call":
|
|
9795
|
+
return ast.checkedType ??= this.checkCall(ast);
|
|
9796
|
+
case "rcall":
|
|
9797
|
+
return ast.checkedType ??= this.checkReceiverCall(ast);
|
|
9798
|
+
case "list":
|
|
9799
|
+
return ast.checkedType ??= this.checkList(ast);
|
|
9800
|
+
case "map":
|
|
9801
|
+
return ast.checkedType ??= this.checkMap(ast);
|
|
9802
|
+
case "?:":
|
|
9803
|
+
return ast.checkedType ??= this.checkTernary(ast);
|
|
9804
|
+
case "||":
|
|
9805
|
+
case "&&":
|
|
9806
|
+
return ast.checkedType ??= this.checkLogicalOp(ast);
|
|
9807
|
+
case "!_":
|
|
9808
|
+
case "-_":
|
|
9809
|
+
return ast.checkedType ??= this.checkUnaryOperator(ast);
|
|
9810
|
+
case "==":
|
|
9811
|
+
case "!=":
|
|
9812
|
+
case "<":
|
|
9813
|
+
case "<=":
|
|
9814
|
+
case ">":
|
|
9815
|
+
case ">=":
|
|
9816
|
+
case "+":
|
|
9817
|
+
case "-":
|
|
9818
|
+
case "*":
|
|
9819
|
+
case "/":
|
|
9820
|
+
case "%":
|
|
9821
|
+
case "in":
|
|
9822
|
+
return ast.checkedType ??= this.checkBinaryOperator(ast);
|
|
9823
|
+
default:
|
|
9824
|
+
throw new TypeError2(`Unknown operation: ${ast[0]}`, ast);
|
|
9825
|
+
}
|
|
9826
|
+
}
|
|
9827
|
+
inferLiteralType(value) {
|
|
9828
|
+
switch (typeof value) {
|
|
9829
|
+
case "string":
|
|
9830
|
+
return this.getType("string");
|
|
9831
|
+
case "bigint":
|
|
9832
|
+
return this.getType("int");
|
|
9833
|
+
case "number":
|
|
9834
|
+
return this.getType("double");
|
|
9835
|
+
case "boolean":
|
|
9836
|
+
return this.getType("bool");
|
|
9837
|
+
case "object":
|
|
9838
|
+
if (value === null) return this.getType("null");
|
|
9839
|
+
const type = this.objectTypesByConstructor.get(value.constructor)?.type;
|
|
9840
|
+
if (type) return type;
|
|
9841
|
+
throw new TypeError2(`Unsupported type: ${value.constructor?.name || typeof value}`);
|
|
9842
|
+
default:
|
|
9843
|
+
throw new TypeError2(`Unsupported type: ${typeof value}`);
|
|
9844
|
+
}
|
|
9845
|
+
}
|
|
9846
|
+
checkVariable(ast) {
|
|
9847
|
+
const varName = ast[1];
|
|
9848
|
+
const varType = this.ctx.getType(varName);
|
|
9849
|
+
if (varType !== void 0) return varType;
|
|
9850
|
+
throw new TypeError2(`Unknown variable: ${varName}`, ast);
|
|
9851
|
+
}
|
|
9852
|
+
checkAccess(ast) {
|
|
9853
|
+
const leftType = this.check(ast[1]);
|
|
9854
|
+
if (leftType.kind === "dyn") return leftType;
|
|
9855
|
+
const indexType = ast[0] === "[]" ? this.check(ast[2]) : this.getType("string");
|
|
9856
|
+
const indexTypeName = indexType.type;
|
|
9857
|
+
if (leftType.kind === "list") {
|
|
9858
|
+
if (indexTypeName !== "int" && indexTypeName !== "dyn") {
|
|
9859
|
+
throw new TypeError2(`List index must be int, got '${indexTypeName}'`, ast);
|
|
9860
|
+
}
|
|
9861
|
+
return leftType.valueType;
|
|
9862
|
+
}
|
|
9863
|
+
if (leftType.kind === "map") return leftType.valueType;
|
|
9864
|
+
const customType = this.objectTypes.get(leftType.name);
|
|
9865
|
+
if (customType) {
|
|
9866
|
+
if (!(indexTypeName === "string" || indexTypeName === "dyn")) {
|
|
9867
|
+
throw new TypeError2(
|
|
9868
|
+
`Cannot index type '${leftType.name}' with type '${indexTypeName}'`,
|
|
9869
|
+
ast
|
|
9870
|
+
);
|
|
9871
|
+
}
|
|
9872
|
+
if (customType.fields) {
|
|
9873
|
+
const keyName2 = ast[0] === "." ? ast[2] : void 0;
|
|
9874
|
+
if (keyName2) {
|
|
9875
|
+
const fieldType = customType.fields[keyName2];
|
|
9876
|
+
if (fieldType) return fieldType;
|
|
9877
|
+
throw new TypeError2(`No such key: ${keyName2}`, ast);
|
|
9878
|
+
}
|
|
9879
|
+
}
|
|
9880
|
+
return this.getType("dyn");
|
|
9881
|
+
}
|
|
9882
|
+
throw new TypeError2(`Cannot index type '${leftType}'`, ast);
|
|
9883
|
+
}
|
|
9884
|
+
checkCall(ast) {
|
|
9885
|
+
const functionName = ast[1];
|
|
9886
|
+
const args = ast[2];
|
|
9887
|
+
const byReceiver = (ast.functionCandidates ??= this.registry.getFunctionCandidates(
|
|
9888
|
+
null,
|
|
9889
|
+
functionName,
|
|
9890
|
+
args.length
|
|
9891
|
+
)).filterByReceiverType(null);
|
|
9892
|
+
if (!byReceiver.exists) throw new TypeError2(`Function not found: '${functionName}'`, ast);
|
|
9893
|
+
if (byReceiver.hasMacro) return this.#returnMacroType(null, byReceiver, args, ast);
|
|
9894
|
+
const argTypes = args.map(this.check, this);
|
|
9895
|
+
const decl = byReceiver.findMatch(argTypes);
|
|
9896
|
+
if (!decl) {
|
|
9897
|
+
throw new TypeError2(
|
|
9898
|
+
`found no matching overload for '${functionName}(${argTypes.join(", ")})'`,
|
|
9899
|
+
ast
|
|
9900
|
+
);
|
|
9901
|
+
}
|
|
9902
|
+
return decl.returnType;
|
|
9903
|
+
}
|
|
9904
|
+
#returnMacroType(receiverType, byReceiver, args, ast) {
|
|
9905
|
+
const candidate = byReceiver.functions[0];
|
|
9906
|
+
if (candidate.typeCheck) return candidate.typeCheck(this, receiverType, args, ast);
|
|
9907
|
+
return candidate.returnType;
|
|
9908
|
+
}
|
|
9909
|
+
checkReceiverCall(ast) {
|
|
9910
|
+
const methodName = ast[1];
|
|
9911
|
+
const args = ast[3];
|
|
9912
|
+
const receiverType = this.check(ast[2]);
|
|
9913
|
+
const functionCandidates = ast.functionCandidates ??= this.registry.getFunctionCandidates(
|
|
9914
|
+
receiverType,
|
|
9915
|
+
methodName,
|
|
9916
|
+
args.length
|
|
9917
|
+
);
|
|
9918
|
+
if (!functionCandidates.exists) {
|
|
9919
|
+
throw new TypeError2(
|
|
9920
|
+
`Function not found: '${methodName}' for value of type '${receiverType}'`,
|
|
9921
|
+
ast
|
|
9922
|
+
);
|
|
7393
9923
|
}
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
9924
|
+
if (receiverType.kind === "dyn") return functionCandidates.returnType || receiverType;
|
|
9925
|
+
const byReceiver = functionCandidates.filterByReceiverType(receiverType);
|
|
9926
|
+
if (byReceiver.hasMacro) return this.#returnMacroType(receiverType, byReceiver, args, ast);
|
|
9927
|
+
const argTypes = args.map(this.check, this);
|
|
9928
|
+
const decl = byReceiver.findMatch(argTypes);
|
|
9929
|
+
if (!decl) {
|
|
9930
|
+
throw new TypeError2(
|
|
9931
|
+
`found no matching overload for '${receiverType.type}.${methodName}(${argTypes.join(
|
|
9932
|
+
", "
|
|
9933
|
+
)})'`,
|
|
9934
|
+
ast
|
|
9935
|
+
);
|
|
9936
|
+
}
|
|
9937
|
+
return decl.returnType;
|
|
9938
|
+
}
|
|
9939
|
+
checkList(ast) {
|
|
9940
|
+
const elements = ast[1];
|
|
9941
|
+
if (elements.length === 0) return this.getType(`list`);
|
|
9942
|
+
const firstType = this.check(elements[0]);
|
|
9943
|
+
const allSameType = elements.every((e) => firstType === this.check(e));
|
|
9944
|
+
if (allSameType) return this.getType(`list<${firstType}>`);
|
|
9945
|
+
return this.getType(`list`);
|
|
9946
|
+
}
|
|
9947
|
+
checkMap(ast) {
|
|
9948
|
+
const entries = ast[1];
|
|
9949
|
+
if (entries.length === 0) return this.getType("map");
|
|
9950
|
+
const firstKeyType = this.check(entries[0][0]);
|
|
9951
|
+
const firstValueType = this.check(entries[0][1]);
|
|
9952
|
+
let allSameKeyType = true;
|
|
9953
|
+
let allSameValueType = true;
|
|
9954
|
+
for (let i = 1; i < entries.length; i++) {
|
|
9955
|
+
const [key, value] = entries[i];
|
|
9956
|
+
if (firstKeyType !== this.check(key)) allSameKeyType = false;
|
|
9957
|
+
if (firstValueType !== this.check(value)) allSameValueType = false;
|
|
9958
|
+
}
|
|
9959
|
+
const inferredKeyType = allSameKeyType ? firstKeyType : "dyn";
|
|
9960
|
+
const inferredValueType = allSameValueType ? firstValueType : "dyn";
|
|
9961
|
+
return this.getType(`map<${inferredKeyType}, ${inferredValueType}>`);
|
|
9962
|
+
}
|
|
9963
|
+
checkTernary(ast) {
|
|
9964
|
+
const condType = this.check(ast[1]);
|
|
9965
|
+
if (!condType.isDynOrBool()) {
|
|
9966
|
+
throw new TypeError2(`Ternary condition must be bool, got '${condType}'`, ast);
|
|
9967
|
+
}
|
|
9968
|
+
const trueType = this.check(ast[2]);
|
|
9969
|
+
const falseType = this.check(ast[3]);
|
|
9970
|
+
if (trueType === falseType) return trueType;
|
|
9971
|
+
if (trueType.name === "dyn") return trueType;
|
|
9972
|
+
if (falseType.name === "dyn") return falseType;
|
|
9973
|
+
throw new TypeError2(
|
|
9974
|
+
`Ternary branches must have the same type, got '${trueType}' and '${falseType}'`,
|
|
9975
|
+
ast
|
|
9976
|
+
);
|
|
9977
|
+
}
|
|
9978
|
+
checkLogicalOp(ast) {
|
|
9979
|
+
const leftType = this.check(ast[1]);
|
|
9980
|
+
const rightType = this.check(ast[2]);
|
|
9981
|
+
if (!leftType.isDynOrBool()) {
|
|
9982
|
+
throw new TypeError2(`Logical operator requires bool operands, got '${leftType}'`, ast);
|
|
9983
|
+
}
|
|
9984
|
+
if (!rightType.isDynOrBool()) {
|
|
9985
|
+
throw new TypeError2(`Logical operator requires bool operands, got '${rightType}'`, ast);
|
|
9986
|
+
}
|
|
9987
|
+
return this.getType("bool");
|
|
9988
|
+
}
|
|
9989
|
+
checkUnaryOperator(ast) {
|
|
9990
|
+
const op = ast[0];
|
|
9991
|
+
const operandType = this.check(ast[1]);
|
|
9992
|
+
if (operandType.kind === "dyn") return op === "!_" ? this.getType("bool") : operandType;
|
|
9993
|
+
const overload = this.registry.findUnaryOverload(op, operandType);
|
|
9994
|
+
if (overload) return overload.returnType;
|
|
9995
|
+
throw new TypeError2(`no such overload: ${op[0]}${operandType.type}`, ast);
|
|
9996
|
+
}
|
|
9997
|
+
checkBinaryOperator(ast) {
|
|
9998
|
+
const op = ast[0];
|
|
9999
|
+
const leftType = this.check(ast[1]);
|
|
10000
|
+
const rightType = this.check(ast[2]);
|
|
10001
|
+
const type = this.registry.checkBinaryOverload(op, leftType, rightType);
|
|
10002
|
+
if (type) return type;
|
|
10003
|
+
throw new TypeError2(`no such overload: ${leftType} ${op} ${rightType}`, ast);
|
|
10004
|
+
}
|
|
10005
|
+
};
|
|
10006
|
+
|
|
10007
|
+
// ../../node_modules/@marcbachmann/cel-js/lib/evaluator.js
|
|
10008
|
+
var globalRegistry = createRegistry();
|
|
10009
|
+
registerOverloads(globalRegistry);
|
|
10010
|
+
registerFunctions(globalRegistry);
|
|
10011
|
+
var handlers = new Map(
|
|
10012
|
+
Object.entries({
|
|
10013
|
+
value(ast) {
|
|
10014
|
+
return ast[1];
|
|
10015
|
+
},
|
|
10016
|
+
id(ast, ev) {
|
|
10017
|
+
return ev.value(ast[1], ast).value;
|
|
10018
|
+
},
|
|
10019
|
+
"||"(ast, ev) {
|
|
10020
|
+
try {
|
|
10021
|
+
const left = ev.eval(ast[1]);
|
|
10022
|
+
if (left === true) return true;
|
|
10023
|
+
if (left !== false) {
|
|
10024
|
+
throw new EvaluationError("Left operand of || is not a boolean", ast[1]);
|
|
10025
|
+
}
|
|
10026
|
+
} catch (err) {
|
|
10027
|
+
if (err.message.includes("Unknown variable")) throw err;
|
|
10028
|
+
if (err.message.includes("is not a boolean")) throw err;
|
|
10029
|
+
const right2 = ev.eval(ast[2]);
|
|
10030
|
+
if (right2 === true) return true;
|
|
10031
|
+
if (right2 === false) throw err;
|
|
10032
|
+
throw new EvaluationError("Right operand of || is not a boolean", ast[2]);
|
|
10033
|
+
}
|
|
10034
|
+
const right = ev.eval(ast[2]);
|
|
10035
|
+
if (typeof right === "boolean") return right;
|
|
10036
|
+
throw new EvaluationError("Right operand of || is not a boolean", ast[2]);
|
|
10037
|
+
},
|
|
10038
|
+
"&&"(ast, ev) {
|
|
10039
|
+
try {
|
|
10040
|
+
const left = ev.eval(ast[1]);
|
|
10041
|
+
if (left === false) return false;
|
|
10042
|
+
if (left !== true) {
|
|
10043
|
+
throw new EvaluationError("Left operand of && is not a boolean", ast[1]);
|
|
10044
|
+
}
|
|
10045
|
+
} catch (err) {
|
|
10046
|
+
if (err.message.includes("Unknown variable")) throw err;
|
|
10047
|
+
if (err.message.includes("is not a boolean")) throw err;
|
|
10048
|
+
const right2 = ev.eval(ast[2]);
|
|
10049
|
+
if (right2 === false) return false;
|
|
10050
|
+
if (right2 === true) throw err;
|
|
10051
|
+
throw new EvaluationError("Right operand of && is not a boolean", ast[2]);
|
|
10052
|
+
}
|
|
10053
|
+
const right = ev.eval(ast[2]);
|
|
10054
|
+
if (typeof right === "boolean") return right;
|
|
10055
|
+
throw new EvaluationError("Right operand of && is not a boolean", ast[2]);
|
|
10056
|
+
},
|
|
10057
|
+
"."(ast, ev) {
|
|
10058
|
+
const left = ev.eval(ast[1]);
|
|
10059
|
+
return ev.debugType(left).field(left, ast[2], ast, ev);
|
|
10060
|
+
},
|
|
10061
|
+
"[]"(ast, ev) {
|
|
10062
|
+
const left = ev.eval(ast[1]);
|
|
10063
|
+
return ev.debugType(left).field(left, ev.eval(ast[2]), ast, ev);
|
|
10064
|
+
},
|
|
10065
|
+
rcall(ast, ev) {
|
|
10066
|
+
const functionName = ast[1];
|
|
10067
|
+
const receiver = ev.eval(ast[2]);
|
|
10068
|
+
const checkedType = ast[2].checkedType || ev.celTypes.dyn;
|
|
10069
|
+
const argAst = ast[3];
|
|
10070
|
+
const argLen = argAst.length;
|
|
10071
|
+
const functionCandidates = ast.functionCandidates ??= ev.registry.getFunctionCandidates(
|
|
10072
|
+
checkedType,
|
|
10073
|
+
functionName,
|
|
10074
|
+
argLen
|
|
10075
|
+
);
|
|
10076
|
+
const receiverType = checkedType.kind !== "dyn" ? checkedType : ev.debugType(receiver);
|
|
10077
|
+
if (!functionCandidates.exists) {
|
|
10078
|
+
throw new EvaluationError(
|
|
10079
|
+
`Function not found: '${functionName}' for value of type '${receiverType}'`,
|
|
10080
|
+
ast
|
|
10081
|
+
);
|
|
7398
10082
|
}
|
|
7399
|
-
|
|
10083
|
+
const byReceiver = functionCandidates.filterByReceiverType(receiverType);
|
|
10084
|
+
let args;
|
|
10085
|
+
let argTypes;
|
|
10086
|
+
if (byReceiver.hasMacro) {
|
|
10087
|
+
args = argAst;
|
|
10088
|
+
argTypes = ast.argMacroTypes ??= new Array(argLen).fill(ev.registry.getFunctionType("ast"));
|
|
10089
|
+
} else {
|
|
10090
|
+
args = ast.argValues ??= new Array(argLen);
|
|
10091
|
+
argTypes = ast.argTypes ??= new Array(argLen);
|
|
10092
|
+
for (let i = 0; i < argLen; i++) {
|
|
10093
|
+
const arg = argAst[i];
|
|
10094
|
+
args[i] = ev.eval(arg);
|
|
10095
|
+
argTypes[i] = getFunctionArgType(arg.checkedType, ev.debugType(args[i]), ev);
|
|
10096
|
+
}
|
|
10097
|
+
}
|
|
10098
|
+
const decl = byReceiver.findMatch(argTypes);
|
|
10099
|
+
if (!decl) {
|
|
10100
|
+
throw new EvaluationError(
|
|
10101
|
+
`found no matching overload for '${receiverType.type}.${functionName}(${argTypes.join(
|
|
10102
|
+
", "
|
|
10103
|
+
)})'`,
|
|
10104
|
+
ast
|
|
10105
|
+
);
|
|
10106
|
+
}
|
|
10107
|
+
try {
|
|
10108
|
+
if (decl.macro) return decl.handler.call(ev, receiver, ast);
|
|
10109
|
+
return decl.handler.call(ev, receiver, ...args);
|
|
10110
|
+
} catch (err) {
|
|
10111
|
+
if (err instanceof EvaluationError) throw err.withAst(ast);
|
|
10112
|
+
throw err;
|
|
10113
|
+
}
|
|
10114
|
+
},
|
|
10115
|
+
call(ast, ev) {
|
|
10116
|
+
const functionName = ast[1];
|
|
10117
|
+
const argAst = ast[2];
|
|
10118
|
+
const argLen = argAst.length;
|
|
10119
|
+
const functionCandidates = ast.functionCandidates ??= ev.registry.getFunctionCandidates(
|
|
10120
|
+
null,
|
|
10121
|
+
functionName,
|
|
10122
|
+
argLen
|
|
10123
|
+
);
|
|
10124
|
+
if (functionCandidates.exists === false) {
|
|
10125
|
+
throw new EvaluationError(`Function not found: '${functionName}'`, ast);
|
|
10126
|
+
}
|
|
10127
|
+
const byReceiver = functionCandidates.filterByReceiverType(null);
|
|
10128
|
+
let args;
|
|
10129
|
+
let argTypes;
|
|
10130
|
+
if (functionCandidates.hasMacro) {
|
|
10131
|
+
args = argAst;
|
|
10132
|
+
argTypes = ast.argMacroTypes ??= new Array(argLen).fill(ev.registry.getFunctionType("ast"));
|
|
10133
|
+
} else {
|
|
10134
|
+
args = ast.argValues ??= new Array(argLen);
|
|
10135
|
+
argTypes = ast.argTypes ??= new Array(argLen);
|
|
10136
|
+
for (let i = 0; i < argLen; i++) {
|
|
10137
|
+
const arg = argAst[i];
|
|
10138
|
+
args[i] = ev.eval(arg);
|
|
10139
|
+
argTypes[i] = getFunctionArgType(arg.checkedType, ev.debugType(args[i]), ev);
|
|
10140
|
+
}
|
|
10141
|
+
}
|
|
10142
|
+
const decl = byReceiver.findMatch(argTypes);
|
|
10143
|
+
if (!decl) {
|
|
10144
|
+
throw new EvaluationError(
|
|
10145
|
+
`found no matching overload for '${functionName}(${argTypes.join(", ")})'`,
|
|
10146
|
+
ast
|
|
10147
|
+
);
|
|
10148
|
+
}
|
|
10149
|
+
try {
|
|
10150
|
+
if (decl.macro) return decl.handler.call(ev, ast);
|
|
10151
|
+
return decl.handler.apply(ev, args);
|
|
10152
|
+
} catch (err) {
|
|
10153
|
+
if (err instanceof EvaluationError) throw err.withAst(ast);
|
|
10154
|
+
throw err;
|
|
10155
|
+
}
|
|
10156
|
+
},
|
|
10157
|
+
list(ast, ev) {
|
|
10158
|
+
const elements = ast[1];
|
|
10159
|
+
const result = new Array(elements.length);
|
|
10160
|
+
for (let i = 0; i < elements.length; i++) result[i] = ev.eval(elements[i]);
|
|
10161
|
+
return result;
|
|
10162
|
+
},
|
|
10163
|
+
map(ast, ev) {
|
|
10164
|
+
const result = {};
|
|
10165
|
+
const props = ast[1];
|
|
10166
|
+
for (let i = 0; i < props.length; i++) {
|
|
10167
|
+
const e = props[i];
|
|
10168
|
+
result[ev.eval(e[0])] = ev.eval(e[1]);
|
|
10169
|
+
}
|
|
10170
|
+
return result;
|
|
10171
|
+
},
|
|
10172
|
+
"?:"(ast, ev) {
|
|
10173
|
+
const condition = ev.eval(ast[1]);
|
|
10174
|
+
if (condition === true) return ev.eval(ast[2]);
|
|
10175
|
+
else if (condition === false) return ev.eval(ast[3]);
|
|
10176
|
+
throw new EvaluationError("Ternary condition must be a boolean");
|
|
10177
|
+
},
|
|
10178
|
+
"!_": unaryOverload,
|
|
10179
|
+
"-_": unaryOverload,
|
|
10180
|
+
"!=": binaryOverload,
|
|
10181
|
+
"==": binaryOverload,
|
|
10182
|
+
in: binaryOverload,
|
|
10183
|
+
"+": binaryOverload,
|
|
10184
|
+
"-": binaryOverload,
|
|
10185
|
+
"*": binaryOverload,
|
|
10186
|
+
"/": binaryOverload,
|
|
10187
|
+
"%": binaryOverload,
|
|
10188
|
+
"<": binaryOverload,
|
|
10189
|
+
"<=": binaryOverload,
|
|
10190
|
+
">": binaryOverload,
|
|
10191
|
+
">=": binaryOverload
|
|
10192
|
+
})
|
|
10193
|
+
);
|
|
10194
|
+
function unaryOverload(ast, ev) {
|
|
10195
|
+
const left = ev.eval(ast[1]);
|
|
10196
|
+
const leftType = ev.debugType(left);
|
|
10197
|
+
const overload = ev.registry.findUnaryOverload(ast[0], leftType);
|
|
10198
|
+
if (overload) return overload.handler(left);
|
|
10199
|
+
throw new EvaluationError(`no such overload: ${ast[0][0]}${leftType}`, ast);
|
|
10200
|
+
}
|
|
10201
|
+
function binaryOverload(ast, ev) {
|
|
10202
|
+
const left = ev.eval(ast[1]);
|
|
10203
|
+
const right = ev.eval(ast[2]);
|
|
10204
|
+
const leftType = getOperandType(ast[1].checkedType, ev.debugType(left), ev);
|
|
10205
|
+
const rightType = getOperandType(ast[2].checkedType, ev.debugType(right), ev);
|
|
10206
|
+
const overload = ev.registry.findBinaryOverload(ast[0], leftType, rightType);
|
|
10207
|
+
if (overload) return overload.handler(left, right, ast, ev);
|
|
10208
|
+
throw new EvaluationError(`no such overload: ${leftType} ${ast[0]} ${rightType}`, ast);
|
|
10209
|
+
}
|
|
10210
|
+
function getOperandType(checkedType, runtimeType, ev) {
|
|
10211
|
+
if (checkedType === runtimeType || !checkedType) return runtimeType;
|
|
10212
|
+
if (checkedType.kind === "dyn") return ev.registry.getDynType(runtimeType);
|
|
10213
|
+
if (checkedType.kind !== runtimeType.kind) {
|
|
10214
|
+
throw new EvaluationError(`Type mismatch: expected ${checkedType}, got ${runtimeType}`);
|
|
10215
|
+
}
|
|
10216
|
+
return checkedType;
|
|
10217
|
+
}
|
|
10218
|
+
function getFunctionArgType(checkedType, runtimeType) {
|
|
10219
|
+
if (checkedType === runtimeType || !checkedType || checkedType.kind === "dyn") return runtimeType;
|
|
10220
|
+
if (checkedType.kind !== runtimeType.kind) {
|
|
10221
|
+
throw new EvaluationError(`Type mismatch: expected ${checkedType}, got ${runtimeType}`);
|
|
10222
|
+
}
|
|
10223
|
+
return checkedType;
|
|
10224
|
+
}
|
|
10225
|
+
var Context = class {
|
|
10226
|
+
createOverlay(name, type) {
|
|
10227
|
+
return new OverlayContext({
|
|
10228
|
+
parent: this,
|
|
10229
|
+
variableName: name,
|
|
10230
|
+
variableType: type
|
|
7400
10231
|
});
|
|
7401
10232
|
}
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
// ../state-manager/src/jwt.ts
|
|
7409
|
-
function base64UrlEncode(str) {
|
|
7410
|
-
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
7411
|
-
}
|
|
7412
|
-
function base64UrlDecode(str) {
|
|
7413
|
-
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
7414
|
-
switch (str.length % 4) {
|
|
7415
|
-
case 2:
|
|
7416
|
-
str += "==";
|
|
7417
|
-
break;
|
|
7418
|
-
case 3:
|
|
7419
|
-
str += "=";
|
|
7420
|
-
break;
|
|
10233
|
+
getVariable(name) {
|
|
10234
|
+
const type = this.getType(name);
|
|
10235
|
+
if (!type) return;
|
|
10236
|
+
const value = this.getValue(name);
|
|
10237
|
+
if (value === void 0) return;
|
|
10238
|
+
return { type, value };
|
|
7421
10239
|
}
|
|
7422
|
-
return atob(str);
|
|
7423
|
-
}
|
|
7424
|
-
var HEADER = {
|
|
7425
|
-
alg: "HS256",
|
|
7426
|
-
typ: "JWT"
|
|
7427
10240
|
};
|
|
7428
|
-
var
|
|
7429
|
-
|
|
7430
|
-
|
|
10241
|
+
var RootContext = class extends Context {
|
|
10242
|
+
constructor({ variables, fallbackValues }) {
|
|
10243
|
+
super();
|
|
10244
|
+
this.variables = variables;
|
|
10245
|
+
this.fallbackValues = fallbackValues;
|
|
10246
|
+
this.primary = null;
|
|
10247
|
+
this.primaryGetter = this.#getFromSecondary;
|
|
10248
|
+
}
|
|
10249
|
+
getType(name) {
|
|
10250
|
+
return this.variables.get(name);
|
|
10251
|
+
}
|
|
10252
|
+
getValue() {
|
|
10253
|
+
}
|
|
10254
|
+
setPrimaryContext(primary) {
|
|
10255
|
+
if (typeof primary !== "object") throw new EvaluationError("Context must be an object");
|
|
10256
|
+
this.primary = primary;
|
|
10257
|
+
if (!primary) this.getValue = this.#getFromSecondary;
|
|
10258
|
+
else if (primary instanceof Map) this.getValue = this.#getFromMap;
|
|
10259
|
+
else this.getValue = this.#getFromObject;
|
|
10260
|
+
}
|
|
10261
|
+
#getFromSecondary(key) {
|
|
10262
|
+
return this.fallbackValues.get(key);
|
|
10263
|
+
}
|
|
10264
|
+
#getFromObject(key) {
|
|
10265
|
+
const v = Object.hasOwn(this.primary, key) ? this.primary[key] : void 0;
|
|
10266
|
+
if (v !== void 0) return v;
|
|
10267
|
+
return this.fallbackValues.get(key);
|
|
10268
|
+
}
|
|
10269
|
+
#getFromMap(key) {
|
|
10270
|
+
const v = this.primary.get(key);
|
|
10271
|
+
if (v !== void 0) return v;
|
|
10272
|
+
return this.fallbackValues.get(key);
|
|
10273
|
+
}
|
|
7431
10274
|
};
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
JSON.stringify({ ...HEADER, ...header })
|
|
7440
|
-
);
|
|
7441
|
-
const encodedPayload = base64UrlEncode(JSON.stringify(payload));
|
|
7442
|
-
const dataToSign = `${encodedHeader}.${encodedPayload}`;
|
|
7443
|
-
const key = await crypto.subtle.importKey(
|
|
7444
|
-
"raw",
|
|
7445
|
-
encoder.encode(secret),
|
|
7446
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
7447
|
-
false,
|
|
7448
|
-
["sign"]
|
|
7449
|
-
);
|
|
7450
|
-
const signature = await crypto.subtle.sign(
|
|
7451
|
-
"HMAC",
|
|
7452
|
-
key,
|
|
7453
|
-
encoder.encode(dataToSign)
|
|
7454
|
-
);
|
|
7455
|
-
const encodedSignature = base64UrlEncode(
|
|
7456
|
-
String.fromCharCode(...new Uint8Array(signature))
|
|
7457
|
-
);
|
|
7458
|
-
return `${dataToSign}.${encodedSignature}`;
|
|
7459
|
-
}
|
|
7460
|
-
async function decodeJwt({
|
|
7461
|
-
token,
|
|
7462
|
-
secret
|
|
7463
|
-
}) {
|
|
7464
|
-
if (typeof token !== "string") {
|
|
7465
|
-
throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
|
|
10275
|
+
var OverlayContext = class extends Context {
|
|
10276
|
+
constructor({ parent, variableName, variableType }) {
|
|
10277
|
+
super();
|
|
10278
|
+
this.parent = parent;
|
|
10279
|
+
this.variableName = variableName;
|
|
10280
|
+
this.variableType = variableType;
|
|
10281
|
+
this.variableValue = void 0;
|
|
7466
10282
|
}
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
10283
|
+
getType(name) {
|
|
10284
|
+
if (this.variableName === name) return this.variableType;
|
|
10285
|
+
return this.parent.getType(name);
|
|
7470
10286
|
}
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
10287
|
+
getValue(name) {
|
|
10288
|
+
if (this.variableName === name) return this.variableValue;
|
|
10289
|
+
return this.parent.getValue(name);
|
|
10290
|
+
}
|
|
10291
|
+
setVariableValue(value) {
|
|
10292
|
+
this.variableValue = value;
|
|
10293
|
+
}
|
|
10294
|
+
};
|
|
10295
|
+
var registryByEnvironment = /* @__PURE__ */ new WeakMap();
|
|
10296
|
+
var globalValues = new Map(Object.entries(TYPES));
|
|
10297
|
+
var Environment = class _Environment {
|
|
10298
|
+
#variables;
|
|
10299
|
+
#registry;
|
|
10300
|
+
#evaluator;
|
|
10301
|
+
#typeChecker;
|
|
10302
|
+
#opts;
|
|
10303
|
+
constructor(opts) {
|
|
10304
|
+
this.#opts = opts;
|
|
10305
|
+
this.#registry = (opts?.inherit instanceof _Environment ? registryByEnvironment.get(opts.inherit) : globalRegistry).clone({
|
|
10306
|
+
unlistedVariablesAreDyn: opts?.unlistedVariablesAreDyn ?? false
|
|
10307
|
+
});
|
|
10308
|
+
this.#variables = this.#registry.variables;
|
|
10309
|
+
const childOpts = {
|
|
10310
|
+
registry: this.#registry,
|
|
10311
|
+
variables: this.#variables,
|
|
10312
|
+
objectTypes: this.#registry.objectTypes,
|
|
10313
|
+
objectTypesByConstructor: this.#registry.objectTypesByConstructor,
|
|
10314
|
+
ctx: new RootContext({
|
|
10315
|
+
variables: this.#variables,
|
|
10316
|
+
fallbackValues: globalValues
|
|
10317
|
+
})
|
|
10318
|
+
};
|
|
10319
|
+
this.#typeChecker = new TypeChecker(childOpts);
|
|
10320
|
+
this.#evaluator = new Evaluator({ ...childOpts, typeChecker: this.#typeChecker });
|
|
10321
|
+
registryByEnvironment.set(this, this.#registry);
|
|
10322
|
+
Object.freeze(this);
|
|
10323
|
+
}
|
|
10324
|
+
clone(opts) {
|
|
10325
|
+
return new _Environment({
|
|
10326
|
+
inherit: this,
|
|
10327
|
+
unlistedVariablesAreDyn: this.#opts?.unlistedVariablesAreDyn ?? false
|
|
10328
|
+
});
|
|
10329
|
+
}
|
|
10330
|
+
registerFunction(string, handler) {
|
|
10331
|
+
this.#registry.registerFunctionOverload(string, handler);
|
|
10332
|
+
return this;
|
|
10333
|
+
}
|
|
10334
|
+
registerOperator(string, handler) {
|
|
10335
|
+
this.#registry.registerOperatorOverload(string, handler);
|
|
10336
|
+
return this;
|
|
10337
|
+
}
|
|
10338
|
+
registerType(typename, constructor) {
|
|
10339
|
+
this.#registry.registerType(typename, constructor);
|
|
10340
|
+
return this;
|
|
10341
|
+
}
|
|
10342
|
+
registerVariable(name, type) {
|
|
10343
|
+
this.#registry.registerVariable(name, type);
|
|
10344
|
+
return this;
|
|
10345
|
+
}
|
|
10346
|
+
hasVariable(name) {
|
|
10347
|
+
return this.#registry.variables.has(name);
|
|
10348
|
+
}
|
|
10349
|
+
check(expression) {
|
|
10350
|
+
try {
|
|
10351
|
+
const typeDecl = this.#typeChecker.check(new Parser(expression).parse());
|
|
10352
|
+
return { valid: true, type: this.#formatTypeForCheck(typeDecl) };
|
|
10353
|
+
} catch (e) {
|
|
10354
|
+
return { valid: false, error: e };
|
|
10355
|
+
}
|
|
10356
|
+
}
|
|
10357
|
+
#checkAST(ast) {
|
|
10358
|
+
try {
|
|
10359
|
+
const typeDecl = this.#typeChecker.check(ast);
|
|
10360
|
+
return { valid: true, type: this.#formatTypeForCheck(typeDecl) };
|
|
10361
|
+
} catch (e) {
|
|
10362
|
+
return { valid: false, error: e };
|
|
10363
|
+
}
|
|
10364
|
+
}
|
|
10365
|
+
#formatTypeForCheck(typeDecl) {
|
|
10366
|
+
if (typeDecl.name === `list<dyn>`) return "list";
|
|
10367
|
+
if (typeDecl.name === `map<dyn, dyn>`) return "map";
|
|
10368
|
+
return `${typeDecl.name}`;
|
|
10369
|
+
}
|
|
10370
|
+
parse(expression) {
|
|
10371
|
+
const ast = new Parser(expression).parse();
|
|
10372
|
+
const evaluateParsed = this.#evaluateAST.bind(this, ast);
|
|
10373
|
+
evaluateParsed.check = this.#checkAST.bind(this, ast);
|
|
10374
|
+
evaluateParsed.ast = ast;
|
|
10375
|
+
return evaluateParsed;
|
|
10376
|
+
}
|
|
10377
|
+
evaluate(expression, context) {
|
|
10378
|
+
return this.#evaluateAST(new Parser(expression).parse(), context);
|
|
10379
|
+
}
|
|
10380
|
+
#evaluateAST(ast, context = null) {
|
|
10381
|
+
const evaluator = this.#evaluator;
|
|
10382
|
+
evaluator.ctx.setPrimaryContext(context);
|
|
10383
|
+
evaluator.tryCheck(ast);
|
|
10384
|
+
return evaluator.eval(ast);
|
|
10385
|
+
}
|
|
10386
|
+
};
|
|
10387
|
+
function unsupportedType(type) {
|
|
10388
|
+
throw new EvaluationError(`Unsupported type: ${type}`);
|
|
10389
|
+
}
|
|
10390
|
+
var Evaluator = class {
|
|
10391
|
+
handlers = handlers;
|
|
10392
|
+
celTypes = celTypes;
|
|
10393
|
+
constructor({ registry, objectTypes, objectTypesByConstructor, typeChecker, ctx }) {
|
|
10394
|
+
this.objectTypes = objectTypes;
|
|
10395
|
+
this.objectTypesByConstructor = objectTypesByConstructor;
|
|
10396
|
+
this.registry = registry;
|
|
10397
|
+
this.typeChecker = typeChecker;
|
|
10398
|
+
this.ctx = ctx;
|
|
10399
|
+
}
|
|
10400
|
+
value(name, ast) {
|
|
10401
|
+
const dec = this.ctx.getVariable(name);
|
|
10402
|
+
if (!dec) throw new EvaluationError(`Unknown variable: ${name}`, ast);
|
|
10403
|
+
const valueType = this.debugType(dec.value);
|
|
10404
|
+
if (dec.type.matches(valueType)) return dec;
|
|
10405
|
+
throw new EvaluationError(
|
|
10406
|
+
`Variable '${name}' is not of type '${dec.type}', got '${valueType}'`,
|
|
10407
|
+
ast
|
|
7488
10408
|
);
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
10409
|
+
}
|
|
10410
|
+
predicateEvaluator(functionName, ast) {
|
|
10411
|
+
return new PredicateEvaluator(this, functionName, ast);
|
|
10412
|
+
}
|
|
10413
|
+
debugType(v) {
|
|
10414
|
+
switch (typeof v) {
|
|
10415
|
+
case "string":
|
|
10416
|
+
return this.celTypes.string;
|
|
10417
|
+
case "bigint":
|
|
10418
|
+
return this.celTypes.int;
|
|
10419
|
+
case "number":
|
|
10420
|
+
return this.celTypes.double;
|
|
10421
|
+
case "boolean":
|
|
10422
|
+
return this.celTypes.bool;
|
|
10423
|
+
case "object":
|
|
10424
|
+
if (v === null) return this.celTypes.null;
|
|
10425
|
+
return this.objectTypesByConstructor.get(v.constructor)?.type || unsupportedType(v.constructor?.name || typeof v);
|
|
10426
|
+
default:
|
|
10427
|
+
unsupportedType(typeof v);
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10430
|
+
tryCheck(ast) {
|
|
10431
|
+
try {
|
|
10432
|
+
return ast.checkedType || this.typeChecker.check(ast);
|
|
10433
|
+
} catch (_e) {
|
|
10434
|
+
}
|
|
10435
|
+
}
|
|
10436
|
+
eval(ast) {
|
|
10437
|
+
const handler = this.handlers.get(ast[0]);
|
|
10438
|
+
if (handler) return handler(ast, this);
|
|
10439
|
+
throw new EvaluationError(`Unknown operation: ${ast[0]}`, ast);
|
|
10440
|
+
}
|
|
10441
|
+
};
|
|
10442
|
+
var PredicateEvaluator = class extends Evaluator {
|
|
10443
|
+
constructor(e, functionName, ast) {
|
|
10444
|
+
super(e);
|
|
10445
|
+
const [identifier, predicate] = ast[3];
|
|
10446
|
+
if (identifier?.[0] !== "id") {
|
|
10447
|
+
throw new EvaluationError(`${functionName} invalid predicate iteration variable`, ast);
|
|
10448
|
+
}
|
|
10449
|
+
this.ast = ast;
|
|
10450
|
+
this.functionName = functionName;
|
|
10451
|
+
this.predicateVariable = identifier[1];
|
|
10452
|
+
this.predicateExpression = predicate;
|
|
10453
|
+
const receiverType = ast[2].checkedType || this.celTypes.dyn;
|
|
10454
|
+
let predicateType = this.celTypes.dyn;
|
|
10455
|
+
if (receiverType.type === "list") predicateType = receiverType.valueType;
|
|
10456
|
+
if (receiverType.type === "map") predicateType = receiverType.keyType;
|
|
10457
|
+
this.ctx = this.ctx.createOverlay(this.predicateVariable, predicateType);
|
|
10458
|
+
this.tryCheck(predicate);
|
|
10459
|
+
}
|
|
10460
|
+
getIterableItems(collection) {
|
|
10461
|
+
if (Array.isArray(collection)) return collection;
|
|
10462
|
+
if (collection instanceof Set) return [...collection];
|
|
10463
|
+
if (collection instanceof Map) return [...collection.keys()];
|
|
10464
|
+
if (typeof collection === "object") return Object.keys(collection);
|
|
10465
|
+
throw new EvaluationError(
|
|
10466
|
+
`${this.functionName} cannot iterate over non-collection type. argument must be a list, map, or object`,
|
|
10467
|
+
this.ast
|
|
7494
10468
|
);
|
|
7495
|
-
return { header, payload, valid };
|
|
7496
10469
|
}
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
var
|
|
10470
|
+
childEvaluateBool(item) {
|
|
10471
|
+
this.ctx.setVariableValue(item);
|
|
10472
|
+
switch (this.eval(this.predicateExpression)) {
|
|
10473
|
+
case true:
|
|
10474
|
+
return true;
|
|
10475
|
+
case false:
|
|
10476
|
+
return false;
|
|
10477
|
+
default:
|
|
10478
|
+
throw new EvaluationError(
|
|
10479
|
+
`${this.functionName} predicate result is not a boolean`,
|
|
10480
|
+
Array.isArray(this.predicateExpression) ? this.predicateExpression : this.ast
|
|
10481
|
+
);
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
childEvaluate(item) {
|
|
10485
|
+
this.ctx.setVariableValue(item);
|
|
10486
|
+
return this.eval(this.predicateExpression);
|
|
10487
|
+
}
|
|
10488
|
+
};
|
|
10489
|
+
var globalEnvironment = new Environment({
|
|
10490
|
+
unlistedVariablesAreDyn: true
|
|
10491
|
+
});
|
|
7517
10492
|
|
|
7518
|
-
// ../state-manager/src/
|
|
7519
|
-
var
|
|
10493
|
+
// ../state-manager/src/multiplayerPolicies.ts
|
|
10494
|
+
var import_noya_utils8 = require("@noya-app/noya-utils");
|
|
10495
|
+
var celEnvironment = new Environment({
|
|
10496
|
+
unlistedVariablesAreDyn: true
|
|
10497
|
+
});
|
|
10498
|
+
var MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
10499
|
+
celEnvironment.registerFunction("random(): double", () => Math.random()).registerFunction("randomInt(int, int): int", (min, max) => {
|
|
10500
|
+
if (max < min) {
|
|
10501
|
+
throw new Error(
|
|
10502
|
+
"randomInt requires the second argument to be greater than or equal to the first"
|
|
10503
|
+
);
|
|
10504
|
+
}
|
|
10505
|
+
if (max === min) {
|
|
10506
|
+
return min;
|
|
10507
|
+
}
|
|
10508
|
+
const span = max - min + 1n;
|
|
10509
|
+
if (span > MAX_SAFE_INTEGER_BIGINT) {
|
|
10510
|
+
throw new Error("randomInt range is too large to generate safely");
|
|
10511
|
+
}
|
|
10512
|
+
const spanNumber = Number(span);
|
|
10513
|
+
const offset = BigInt(Math.floor(Math.random() * spanNumber));
|
|
10514
|
+
return min + offset;
|
|
10515
|
+
}).registerFunction(
|
|
10516
|
+
"now(): double",
|
|
10517
|
+
function() {
|
|
10518
|
+
const nowVariable = this.ctx.getVariable("now");
|
|
10519
|
+
const nowValue = nowVariable?.value ?? Date.now();
|
|
10520
|
+
return typeof nowValue === "number" ? nowValue : Number(nowValue);
|
|
10521
|
+
}
|
|
10522
|
+
).registerFunction(
|
|
10523
|
+
"timestamp(): string",
|
|
10524
|
+
function() {
|
|
10525
|
+
const nowVariable = this.ctx.getVariable("now");
|
|
10526
|
+
const nowValue = typeof nowVariable?.value === "number" ? nowVariable.value : typeof nowVariable?.value === "string" ? Number(nowVariable.value) : Date.now();
|
|
10527
|
+
return new Date(nowValue).toISOString();
|
|
10528
|
+
}
|
|
10529
|
+
).registerFunction("uuid(): string", () => (0, import_noya_utils8.uuid)());
|
|
10530
|
+
var READ_DENIED = Symbol("readDenied");
|
|
7520
10531
|
|
|
7521
10532
|
// ../state-manager/src/NoyaManager.ts
|
|
7522
|
-
var
|
|
10533
|
+
var import_noya_utils12 = require("@noya-app/noya-utils");
|
|
7523
10534
|
var import_observable18 = require("@noya-app/observable");
|
|
7524
10535
|
|
|
7525
10536
|
// ../noya-pipeline/src/graphToTasks.ts
|
|
7526
|
-
var
|
|
10537
|
+
var import_observable10 = require("@noya-app/observable");
|
|
7527
10538
|
|
|
7528
10539
|
// ../noya-pipeline/src/state.ts
|
|
7529
|
-
var
|
|
10540
|
+
var import_noya_utils9 = require("@noya-app/noya-utils");
|
|
7530
10541
|
var rectSchema = Type.Object({
|
|
7531
10542
|
x: Type.Number(),
|
|
7532
10543
|
y: Type.Number(),
|
|
@@ -7625,23 +10636,26 @@ var pipelineSchema = Type.Object(
|
|
|
7625
10636
|
);
|
|
7626
10637
|
|
|
7627
10638
|
// ../state-manager/src/PipelineManager.ts
|
|
7628
|
-
var
|
|
10639
|
+
var import_observable11 = require("@noya-app/observable");
|
|
7629
10640
|
|
|
7630
10641
|
// ../state-manager/src/PublishingManager.ts
|
|
7631
|
-
var
|
|
10642
|
+
var import_observable12 = require("@noya-app/observable");
|
|
7632
10643
|
|
|
7633
10644
|
// ../state-manager/src/ResourceManager.ts
|
|
7634
|
-
var
|
|
7635
|
-
var
|
|
10645
|
+
var import_noya_utils10 = require("@noya-app/noya-utils");
|
|
10646
|
+
var import_observable13 = require("@noya-app/observable");
|
|
7636
10647
|
|
|
7637
10648
|
// ../state-manager/src/rpcManager.ts
|
|
7638
|
-
var
|
|
7639
|
-
var
|
|
10649
|
+
var import_noya_utils11 = require("@noya-app/noya-utils");
|
|
10650
|
+
var import_observable14 = require("@noya-app/observable");
|
|
7640
10651
|
|
|
7641
10652
|
// ../state-manager/src/SecretManager.ts
|
|
7642
|
-
var
|
|
10653
|
+
var import_observable15 = require("@noya-app/observable");
|
|
7643
10654
|
|
|
7644
10655
|
// ../state-manager/src/TaskManager.ts
|
|
10656
|
+
var import_observable16 = require("@noya-app/observable");
|
|
10657
|
+
|
|
10658
|
+
// ../state-manager/src/UserManager.ts
|
|
7645
10659
|
var import_observable17 = require("@noya-app/observable");
|
|
7646
10660
|
|
|
7647
10661
|
// ../state-manager/src/NoyaManager.ts
|
|
@@ -7655,7 +10669,7 @@ var createMutatorParametersSchema = Type.Object({
|
|
|
7655
10669
|
});
|
|
7656
10670
|
|
|
7657
10671
|
// ../state-manager/src/sync/localRpcHelpers.ts
|
|
7658
|
-
var
|
|
10672
|
+
var import_noya_utils13 = require("@noya-app/noya-utils");
|
|
7659
10673
|
|
|
7660
10674
|
// ../noya-keymap/src/hooks.ts
|
|
7661
10675
|
var import_react4 = require("react");
|
|
@@ -7953,7 +10967,7 @@ var FileDropTarget = memoGeneric(function FileDropTarget2({ children, onDropFile
|
|
|
7953
10967
|
var import_react8 = require("react");
|
|
7954
10968
|
|
|
7955
10969
|
// ../noya-react-utils/src/hooks/useDeepArray.ts
|
|
7956
|
-
var
|
|
10970
|
+
var import_noya_utils14 = require("@noya-app/noya-utils");
|
|
7957
10971
|
var import_react9 = require("react");
|
|
7958
10972
|
function useJsonMemo(value) {
|
|
7959
10973
|
const stringified = (0, import_react9.useMemo)(
|
|
@@ -7968,7 +10982,7 @@ function useJsonMemo(value) {
|
|
|
7968
10982
|
}
|
|
7969
10983
|
|
|
7970
10984
|
// ../noya-react-utils/src/hooks/useDeepState.ts
|
|
7971
|
-
var
|
|
10985
|
+
var import_noya_utils15 = require("@noya-app/noya-utils");
|
|
7972
10986
|
var import_react10 = require("react");
|
|
7973
10987
|
|
|
7974
10988
|
// ../noya-react-utils/src/hooks/useFetch.ts
|
|
@@ -7999,7 +11013,7 @@ var import_react17 = require("react");
|
|
|
7999
11013
|
var import_react18 = require("react");
|
|
8000
11014
|
|
|
8001
11015
|
// ../noya-react-utils/src/hooks/useShallowArray.ts
|
|
8002
|
-
var
|
|
11016
|
+
var import_noya_utils16 = require("@noya-app/noya-utils");
|
|
8003
11017
|
var import_react19 = require("react");
|
|
8004
11018
|
|
|
8005
11019
|
// ../noya-react-utils/src/hooks/useStableCallback.ts
|
|
@@ -8009,7 +11023,7 @@ var import_react20 = require("react");
|
|
|
8009
11023
|
var import_react21 = require("react");
|
|
8010
11024
|
|
|
8011
11025
|
// ../noya-react-utils/src/hooks/useUrlHashParameters.ts
|
|
8012
|
-
var
|
|
11026
|
+
var import_noya_utils17 = require("@noya-app/noya-utils");
|
|
8013
11027
|
var import_react22 = require("react");
|
|
8014
11028
|
|
|
8015
11029
|
// ../noya-react-utils/src/hooks/useWindowSize.ts
|
|
@@ -8160,7 +11174,7 @@ var import_react55 = __toESM(require("react"));
|
|
|
8160
11174
|
var import_client = require("react-dom/client");
|
|
8161
11175
|
|
|
8162
11176
|
// ../noya-multiplayer-react/src/inspector/StateInspector.tsx
|
|
8163
|
-
var
|
|
11177
|
+
var import_noya_utils18 = require("@noya-app/noya-utils");
|
|
8164
11178
|
var import_react54 = __toESM(require("react"));
|
|
8165
11179
|
|
|
8166
11180
|
// ../../node_modules/react-inspector/dist/index.mjs
|
|
@@ -9564,14 +12578,15 @@ function StateInspectorRow({
|
|
|
9564
12578
|
colorScheme,
|
|
9565
12579
|
selected,
|
|
9566
12580
|
style: style2,
|
|
9567
|
-
variant
|
|
12581
|
+
variant,
|
|
12582
|
+
bordered = true
|
|
9568
12583
|
}) {
|
|
9569
12584
|
const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
|
|
9570
12585
|
return /* @__PURE__ */ import_react46.default.createElement(
|
|
9571
12586
|
"div",
|
|
9572
12587
|
{
|
|
9573
12588
|
style: {
|
|
9574
|
-
borderBottom: `1px solid ${solidBorderColor}
|
|
12589
|
+
borderBottom: bordered ? `1px solid ${solidBorderColor}` : void 0,
|
|
9575
12590
|
fontSize: "12px",
|
|
9576
12591
|
fontFamily: "Menlo, monospace",
|
|
9577
12592
|
padding: "2px 12px 1px",
|
|
@@ -10646,12 +13661,13 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
10646
13661
|
colorScheme = "light",
|
|
10647
13662
|
anchor = "right",
|
|
10648
13663
|
unstyled = false,
|
|
13664
|
+
advanced = false,
|
|
10649
13665
|
...props
|
|
10650
13666
|
}) {
|
|
10651
13667
|
const {
|
|
10652
13668
|
multiplayerStateManager,
|
|
10653
13669
|
assetManager,
|
|
10654
|
-
|
|
13670
|
+
userManager,
|
|
10655
13671
|
secretManager,
|
|
10656
13672
|
ephemeralUserDataManager,
|
|
10657
13673
|
connectionEventManager,
|
|
@@ -10738,8 +13754,8 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
10738
13754
|
const assetsInitialized = useObservable2(assetManager.isInitialized$);
|
|
10739
13755
|
const secrets = useObservable2(secretManager.secrets$);
|
|
10740
13756
|
const secretsInitialized = useObservable2(secretManager.isInitialized$);
|
|
10741
|
-
const connectedUsers = useObservable2(
|
|
10742
|
-
const userId = useObservable2(
|
|
13757
|
+
const connectedUsers = useObservable2(userManager.connectedUsers$);
|
|
13758
|
+
const userId = useObservable2(userManager.currentUserId$);
|
|
10743
13759
|
const state = useObservable2(multiplayerStateManager.optimisticState$);
|
|
10744
13760
|
const inputsInitialized = useObservable2(ioManager.inputsInitialized$);
|
|
10745
13761
|
const outputTransformsInitialized = useObservable2(
|
|
@@ -10837,12 +13853,13 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
10837
13853
|
}
|
|
10838
13854
|
)
|
|
10839
13855
|
},
|
|
10840
|
-
/* @__PURE__ */ import_react54.default.createElement(StateInspectorDisclosureRowInner, { style: { flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ import_react54.default.createElement(
|
|
13856
|
+
/* @__PURE__ */ import_react54.default.createElement(StateInspectorDisclosureRowInner, { style: { flex: "0 0 auto" } }, connectedUsers?.map((user, index, array) => /* @__PURE__ */ import_react54.default.createElement(
|
|
10841
13857
|
StateInspectorRow,
|
|
10842
13858
|
{
|
|
10843
13859
|
key: user.id,
|
|
10844
13860
|
colorScheme,
|
|
10845
|
-
variant: user.id === userId ? "up" : void 0
|
|
13861
|
+
variant: user.id === userId ? "up" : void 0,
|
|
13862
|
+
bordered: index !== array.length - 1
|
|
10846
13863
|
},
|
|
10847
13864
|
user.image && /* @__PURE__ */ import_react54.default.createElement(
|
|
10848
13865
|
"img",
|
|
@@ -11014,7 +14031,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11014
14031
|
"Delete"
|
|
11015
14032
|
))))
|
|
11016
14033
|
),
|
|
11017
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14034
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11018
14035
|
StateInspectorDisclosureSection,
|
|
11019
14036
|
{
|
|
11020
14037
|
title: /* @__PURE__ */ import_react54.default.createElement(StateInspectorTitleLabel, null, "Resources (", resources.length, ")", /* @__PURE__ */ import_react54.default.createElement(ColoredDot, { type: resourcesInitialized ? "success" : "error" })),
|
|
@@ -11041,7 +14058,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11041
14058
|
{
|
|
11042
14059
|
theme: theme3,
|
|
11043
14060
|
onClick: async () => {
|
|
11044
|
-
const path2 = prompt("Enter directory path") || (0,
|
|
14061
|
+
const path2 = prompt("Enter directory path") || (0, import_noya_utils18.uuid)();
|
|
11045
14062
|
await resourceManager.createResource({
|
|
11046
14063
|
type: "directory",
|
|
11047
14064
|
path: path2
|
|
@@ -11057,9 +14074,9 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11057
14074
|
const file = await uploadFile();
|
|
11058
14075
|
resourceManager.createResource({
|
|
11059
14076
|
type: "asset",
|
|
11060
|
-
path: file.name || (0,
|
|
14077
|
+
path: file.name || (0, import_noya_utils18.uuid)(),
|
|
11061
14078
|
asset: {
|
|
11062
|
-
content:
|
|
14079
|
+
content: import_noya_utils18.Base64.encode(await file.arrayBuffer()),
|
|
11063
14080
|
contentType: file.type,
|
|
11064
14081
|
encoding: "base64"
|
|
11065
14082
|
}
|
|
@@ -11096,7 +14113,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11096
14113
|
"Rename"
|
|
11097
14114
|
)))))
|
|
11098
14115
|
),
|
|
11099
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14116
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11100
14117
|
StateInspectorDisclosureSection,
|
|
11101
14118
|
{
|
|
11102
14119
|
title: /* @__PURE__ */ import_react54.default.createElement(StateInspectorTitleLabel, null, "Secrets", /* @__PURE__ */ import_react54.default.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
|
|
@@ -11127,8 +14144,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11127
14144
|
"Delete"
|
|
11128
14145
|
))))
|
|
11129
14146
|
),
|
|
11130
|
-
|
|
11131
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14147
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11132
14148
|
StateInspectorDisclosureSection,
|
|
11133
14149
|
{
|
|
11134
14150
|
open: showInputs,
|
|
@@ -11150,7 +14166,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11150
14166
|
/* @__PURE__ */ import_react54.default.createElement("span", null, "No inputs")
|
|
11151
14167
|
))
|
|
11152
14168
|
),
|
|
11153
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14169
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11154
14170
|
StateInspectorDisclosureSection,
|
|
11155
14171
|
{
|
|
11156
14172
|
open: showOutputTransforms,
|
|
@@ -11177,7 +14193,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11177
14193
|
/* @__PURE__ */ import_react54.default.createElement("span", null, "No output transforms")
|
|
11178
14194
|
))
|
|
11179
14195
|
),
|
|
11180
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14196
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11181
14197
|
StateInspectorDisclosureSection,
|
|
11182
14198
|
{
|
|
11183
14199
|
title: "Tasks",
|
|
@@ -11222,7 +14238,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11222
14238
|
}
|
|
11223
14239
|
))))
|
|
11224
14240
|
),
|
|
11225
|
-
/* @__PURE__ */ import_react54.default.createElement(
|
|
14241
|
+
advanced && /* @__PURE__ */ import_react54.default.createElement(
|
|
11226
14242
|
ActivityEventsSection,
|
|
11227
14243
|
{
|
|
11228
14244
|
colorScheme,
|
|
@@ -11244,7 +14260,7 @@ var StateInspector = memoGeneric(function StateInspector2({
|
|
|
11244
14260
|
)
|
|
11245
14261
|
);
|
|
11246
14262
|
});
|
|
11247
|
-
var truncateAsset = (0,
|
|
14263
|
+
var truncateAsset = (0, import_noya_utils18.memoize)((asset) => {
|
|
11248
14264
|
if (asset.url.startsWith("data:") || asset.url.startsWith("blob:")) {
|
|
11249
14265
|
return { ...asset, url: ellipsis(asset.url, 40) };
|
|
11250
14266
|
}
|
|
@@ -11321,12 +14337,12 @@ var UserPointerInternal = memoGeneric(function UserPointerInternal2({
|
|
|
11321
14337
|
});
|
|
11322
14338
|
});
|
|
11323
14339
|
var UserPointersOverlay = memoGeneric(function UserPointers({
|
|
11324
|
-
|
|
14340
|
+
userManager,
|
|
11325
14341
|
ephemeralUserDataManager,
|
|
11326
14342
|
renderUserPointer
|
|
11327
14343
|
}) {
|
|
11328
14344
|
const currentUserId = useObservable2(ephemeralUserDataManager.currentUserId$);
|
|
11329
|
-
const connectedUsers = useObservable2(
|
|
14345
|
+
const connectedUsers = useObservable2(userManager.connectedUsers$);
|
|
11330
14346
|
return /* @__PURE__ */ import_react61.default.createElement(import_react61.default.Fragment, null, connectedUsers.map((user) => {
|
|
11331
14347
|
if (user.id === currentUserId) return null;
|
|
11332
14348
|
return /* @__PURE__ */ import_react61.default.createElement(
|