UNPKG

@bufbuild/cel

Version:

A CEL evaluator for ECMAScript

374 lines (373 loc) 14.6 kB
"use strict"; // Copyright 2024-2025 Buf Technologies, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _Builder_prevId; Object.defineProperty(exports, "__esModule", { value: true }); const encoder = new TextEncoder(); class Builder { constructor() { _Builder_prevId.set(this, 0n); this.sourceInfo = { $typeName: "cel.expr.SourceInfo", syntaxVersion: "", location: "", lineOffsets: [], positions: {}, macroCalls: {}, extensions: [], }; } nextExpr(offset, exprKind) { var _a; this.sourceInfo.positions[(__classPrivateFieldSet(this, _Builder_prevId, (_a = __classPrivateFieldGet(this, _Builder_prevId, "f"), ++_a), "f")).toString()] = offset; return { $typeName: "cel.expr.Expr", id: __classPrivateFieldGet(this, _Builder_prevId, "f"), exprKind, }; } nextEntry(offset, keyKind, value) { var _a; this.sourceInfo.positions[(__classPrivateFieldSet(this, _Builder_prevId, (_a = __classPrivateFieldGet(this, _Builder_prevId, "f"), ++_a), "f")).toString()] = offset; return { $typeName: "cel.expr.Expr.CreateStruct.Entry", id: __classPrivateFieldGet(this, _Builder_prevId, "f"), keyKind, value, optionalEntry: false, }; } newConstExpr(offset, constantKind) { return this.nextExpr(offset, { case: "constExpr", value: { $typeName: "cel.expr.Constant", constantKind }, }); } newCallExpr(offset, functionName, args) { if (functionName === "has" && args.length === 1 && args[0].exprKind?.case === "selectExpr") { return this.expandHasMacro(offset, args[0]); } return this.nextExpr(offset, { case: "callExpr", value: { $typeName: "cel.expr.Expr.Call", function: functionName, args, }, }); } newMemberCallExpr(offset, target, functionName, args) { return this.maybeExpand(offset, this.nextExpr(offset, { case: "callExpr", value: { $typeName: "cel.expr.Expr.Call", function: functionName, target, args, }, })); } newStringExpr(offset, sequence) { return this.newConstExpr(offset, { case: "stringValue", value: sequence.reduce((string, chunk) => { if (typeof chunk !== "string") { if (chunk.some((cp) => cp >= 0xd800 && cp < 0xe000)) { // surrogates, whether paired or not, are not allowed in UTF-8 throw new Error("surrogate code points are not allowed"); } return string + String.fromCodePoint(...chunk); } return string + chunk; }, ""), }); } newBytesExpr(offset, sequence) { const chunks = []; let totalSize = 0; for (const rawChunk of sequence) { const chunk = typeof rawChunk === "string" ? encoder.encode(rawChunk) : rawChunk; chunks.push(chunk); totalSize += chunk.length; } const value = new Uint8Array(totalSize); let chunkOffset = 0; for (const chunk of chunks) { value.set(chunk, chunkOffset); chunkOffset += chunk.length; } return this.newConstExpr(offset, { case: "bytesValue", value, }); } newBoolExpr(offset, keyword) { return this.newConstExpr(offset, { case: "boolValue", value: keyword === "true", }); } newInt64Expr(offset, digits) { return this.newConstExpr(offset, { case: "int64Value", value: digits[0] === "-" ? -BigInt(digits.slice(1)) : BigInt(digits), }); } newUnsignedInt64Expr(offset, digits) { return this.newConstExpr(offset, { case: "uint64Value", value: BigInt(digits), }); } newDoubleExpr(offset, digits) { return this.newConstExpr(offset, { case: "doubleValue", value: parseFloat(digits), }); } newNullExpr(offset) { return this.newConstExpr(offset, { case: "nullValue", value: 0, }); } newIdentExpr(offset, name) { const expr = this.nextExpr(offset, { case: "identExpr", value: { $typeName: "cel.expr.Expr.Ident", name }, }); return expr; } newInfixExpr(offset, op, args) { return this.newCallExpr(offset, op === "in" ? "@in" : `_${op}_`, args); } newSelectExpr(offset, operand, field) { return this.nextExpr(offset, { case: "selectExpr", value: { $typeName: "cel.expr.Expr.Select", operand, field, testOnly: false, }, }); } newIndexExpr(offset, operand, index) { return this.newCallExpr(offset, "_[_]", [operand, index]); } expandHasMacro(offset, target) { if (target.exprKind.case !== "selectExpr") { return this.newCallExpr(offset, "has", [target]); } target.exprKind.value.testOnly = true; return target; } newListExpr(offset, elements) { return this.nextExpr(offset, { case: "listExpr", value: { $typeName: "cel.expr.Expr.CreateList", elements, optionalIndices: [], }, }); } newBoolMacro(offset, iterRange, iterVar, init, loopStep, loopCondition) { return this.nextExpr(offset, { case: "comprehensionExpr", value: { $typeName: "cel.expr.Expr.Comprehension", accuVar: "__result__", accuInit: this.newConstExpr(offset, { case: "boolValue", value: init, }), iterVar, iterVar2: "", // not yet supported iterRange, loopStep, loopCondition, result: this.newIdentExpr(offset, "__result__"), }, }); } newListMacro(offset, iterRange, iterVar, loopStep) { return this.nextExpr(offset, { case: "comprehensionExpr", value: { $typeName: "cel.expr.Expr.Comprehension", accuVar: "__result__", accuInit: this.newListExpr(offset, []), iterVar, iterVar2: "", // not yet supported iterRange, loopCondition: this.newConstExpr(offset, { case: "boolValue", value: true, }), loopStep, result: this.newIdentExpr(offset, "__result__"), }, }); } expandExistsMacro(offset, target, x, test) { return this.newBoolMacro(offset, target, x, false, this.newCallExpr(offset, "_||_", [ this.newIdentExpr(offset, "__result__"), test, ]), this.newCallExpr(offset, "@not_strictly_false", [ this.newCallExpr(offset, "!_", [ this.newIdentExpr(offset, "__result__"), ]), ])); } expandAllMacro(offset, target, x, test) { return this.newBoolMacro(offset, target, x, true, this.newCallExpr(offset, "_&&_", [ this.newIdentExpr(offset, "__result__"), test, ]), this.newCallExpr(offset, "@not_strictly_false", [ this.newIdentExpr(offset, "__result__"), ])); } expandMapMacro(offset, target, x, step) { return this.newListMacro(offset, target, x, this.newCallExpr(offset, "_+_", [ this.newIdentExpr(offset, "__result__"), this.newListExpr(offset, [step]), ])); } expandMapFilterMacro(offset, target, x, test, step) { return this.newListMacro(offset, target, x, this.newCallExpr(offset, "_?_:_", [ test, this.newCallExpr(offset, "_+_", [ this.newIdentExpr(offset, "__result__"), this.newListExpr(offset, [step]), ]), this.newIdentExpr(offset, "__result__"), ])); } expandFilterMacro(offset, target, x, step) { return this.newListMacro(offset, target, x, this.newCallExpr(offset, "_?_:_", [ step, this.newCallExpr(offset, "_+_", [ this.newIdentExpr(offset, "__result__"), this.newListExpr(offset, [this.newIdentExpr(offset, x)]), ]), this.newIdentExpr(offset, "__result__"), ])); } expandExistsOne(offset, iterRange, iterVar, step) { return this.nextExpr(offset, { case: "comprehensionExpr", value: { $typeName: "cel.expr.Expr.Comprehension", accuVar: "__result__", accuInit: this.newConstExpr(offset, { case: "int64Value", value: BigInt(0), }), iterVar, iterVar2: "", // not yet supported iterRange, loopCondition: this.newConstExpr(offset, { case: "boolValue", value: true, }), loopStep: this.newCallExpr(offset, "_?_:_", [ step, this.newCallExpr(offset, "_+_", [ this.newIdentExpr(offset, "__result__"), this.newConstExpr(offset, { case: "int64Value", value: BigInt(1), }), ]), this.newIdentExpr(offset, "__result__"), ]), result: this.newCallExpr(offset, "_==_", [ this.newIdentExpr(offset, "__result__"), this.newConstExpr(offset, { case: "int64Value", value: BigInt(1), }), ]), }, }); } maybeExpand(offset, call) { if (call.exprKind.case === "callExpr") { const callExpr = call.exprKind.value; const varName = callExpr.args[0]; // const varIndex = callExpr.args.length > 1 ? callExpr.args[1] : ""; if (varName !== undefined && call.exprKind.value.target !== undefined && varName.exprKind?.case === "identExpr") { if (callExpr.args.length === 2) { switch (callExpr.function) { case "exists": return this.expandExistsMacro(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1]); case "all": return this.expandAllMacro(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1]); case "map": return this.expandMapMacro(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1]); case "filter": return this.expandFilterMacro(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1]); case "exists_one": case "existsOne": return this.expandExistsOne(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1]); } } if (callExpr.args.length === 3 && callExpr.function == "map") { return this.expandMapFilterMacro(offset, call.exprKind.value.target, varName.exprKind.value.name, call.exprKind.value.args[1], call.exprKind.value.args[2]); } } } return call; } newMapEntry(offset, key, value) { return this.nextEntry(offset, { case: "mapKey", value: key, }, value); } newStructExpr(offset, entries, messageName = "") { return this.nextExpr(offset, { case: "structExpr", value: { $typeName: "cel.expr.Expr.CreateStruct", entries, messageName, }, }); } newStructEntry(offset, field, value) { return this.nextEntry(offset, { case: "fieldKey", value: field, }, value); } } _Builder_prevId = new WeakMap(); exports.default = Builder;