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