Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 96 additions & 69 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
"license-header": "license-header --ignore 'packages/**'",
"lint": "biome lint --error-on-warnings"
},
"workspaces": ["packages/cel-spec", "packages/cel", "packages/example"],
"workspaces": [
"packages/cel-spec",
"packages/cel",
"packages/example",
"packages/re2"
],
"type": "module",
"packageManager": "npm@10.9.0",
"licenseHeader": {
Expand Down
7 changes: 4 additions & 3 deletions packages/cel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@
"@bufbuild/protobuf": "^2.6.2"
},
"dependencies": {
"@bufbuild/cel-spec": "0.4.0"
"@bufbuild/cel-spec": "0.4.0",
"@bufbuild/re2": "0.4.0"
},
"devDependencies": {
"expect-type": "^1.3.0",
"peggy": "^5.0.6",
"peggy-ts": "github:hudlow/peggy-ts#v0.0.9",
"expect-type": "^1.3.0"
"peggy-ts": "github:hudlow/peggy-ts#v0.0.9"
}
}
57 changes: 2 additions & 55 deletions packages/cel/src/std/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,63 +26,10 @@ import { equals } from "../equals.js";
import { celMethod, celFunc } from "../func.js";
import type { CelList } from "../list.js";
import type { CelMap } from "../map.js";

/**
* Patterns that are supported in ECMAScript RE and not in
* RE2.
*
* ECMAScript Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet
* RE2: https://github.com/google/re2/wiki/syntax
*/
const invalidPatterns = [
/\\[1-9]/, // backreference eg: \1
/\\k<.>/, // backreference eg: \k<name>
/\(\?\=/, // lookahead eg: Jack(?=Sprat)
/\(\?\!/, // negative lookahead eg: Jack(?!Sprat)
/\(\?\<\=/, // lookbehind eg: (?<=Sprat)Jack
/\(\?\<\!/, // negative lookbehind eg: (?<!Sprat)Jack,
/\\c[A-Z]/, // control character eg: /\cM\cJ/
/\\u[0-9a-fA-F]{4}/, // UTF-16 code-unit
/\\0(?!\d)/, // NUL
/\[\\b.*\]/, // Backspace eg: [\b]
];

const flagPattern = new RegExp(/^\(\?(?<flags>[ims\-]+)\)/);
import { RE2JS } from "@bufbuild/re2";

export function matches(this: string, pattern: string): boolean {
for (const invalidPattern of invalidPatterns) {
if (invalidPattern.test(pattern)) {
throw new Error(
`Error evaluating pattern ${pattern}, invalid RE2 syntax`,
);
}
}
// CEL use RE2 syntax which is a subset of Ecmascript RE except for
// the flags and the ability to change the flags mid-sequence.
//
// The conformance tests use flags at the very beginning of the sequence, which
// is likely the most common place where this rare feature will be used.
//
// Instead of importing an RE2 engine to be able to support this niche, we
// can instead just check for the flags at the very beginning and apply them.
//
// Unsupported flags and flags mid-sequence will fail with to compile the regex.
//
// Users can choose to override this function and provide an RE2 engine if they really
// need to.
let flags = "";
const flagMatches = pattern.match(flagPattern);
if (flagMatches) {
for (let flag of flagMatches?.groups?.flags ?? "") {
if (flag == "-") {
break;
}
flags += flag;
}
pattern = pattern.substring(flagMatches[0].length);
}
const re = new RegExp(pattern, flags);
return re.test(this);
return RE2JS.compile(pattern).test(this);
}

function compareDuration(
Expand Down
Loading
Loading