Repository navigation
Conversation
re2 is a NAN addon that downloads a per-Node-ABI binary from GitHub at install time and compiles when that fails: the last install-time network dependency and compiler use left in Koncorde. re2js is a pure JavaScript port of RE2, with the same linear-time guarantee against ReDoS. lib/util/RE2.js reproduces on re2js what `re2` 1.22 did on top of RE2: its JS-to-RE2 syntax translation (ported from its new.cc), its flags (i/m/s honoured, g/y making test() stateful through lastIndex, anything else ignored) and RE2's syntax error messages, which Koncorde forwards. scripts/re2-parity.js compares it with re2 1.22.3 on seeded random patterns: 100 000 patterns, 530 592 test() calls, no behaviour mismatch; error wording identical for 99 %. Two deliberate differences, both from RE2 walking UTF-8 bytes where re2js walks characters: `\C` reads one character, and `\B` no longer matches between the bytes of a multi-byte character. The PR workflow runs the parity on Node 20, 22 and 24. Matching is slower: 2–10x on typical filters, up to 33x with Unicode classes, faster on literal search (scripts/re2-bench.js). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up of kuzzleio/kuzzle#2839: after the three Kuzzle-maintained addons moved to prebuilt N-API binaries,
re2is the last native module that touches the network or a compiler at install time.Why
re2(upstreamuhop/node-re2, not ours) is a NAN addon: its install script downloads a binary per (os, arch, Node ABI) from GitHub releases, and runsnode-gyp rebuildwhen that fails — the same failure class as kuzzleio/kuzzle#2790. It is used for one thing: theregexpkeyword, where it protects Kuzzle from ReDoS (a client can subscribe with any regex).re2jsis a pure JavaScript port of RE2 (v2.8.6, 0 dependencies): same linear-time guarantee, same syntax, nothing to download or compile.What
lib/util/RE2.js: the subset ofre2'sRE2class Koncorde uses (constructor,test(),toString()), on re2js. It reproduces whatre21.22 did on top of the RE2 engine:re2'slib/new.cc(\uXXXX,\u{…},\cX,\p{Long_Name},(?<name>, themflag as(?m),/) — re2js' owntranslateRegExpaccepts more thanre2did (e.g.\8), so it is not used;i/m/shonoured,g/ymakingtest()stateful throughlastIndex, any other character ignored;regexpCondition.js,standardize.jsuse it;re2dropped fromdependencies,re2jsadded.regExpEngine: "re2"option keeps its name and meaning (RE2 semantics);"js"is unchanged.Proof of equivalence
scripts/re2-parity.js— seeded random patterns (literals incl. non-ASCII/astral, classes, Unicode properties, JS escapes, groups, quantifiers, and what RE2 rejects) × random flags × 12test()calls on the same object, against re2 1.22.3:The PR workflow gets a
re2-parityjob (Node 20/22/24). Two deliberate differences, both because RE2 (C++) walks UTF-8 bytes where re2js walks characters:\C(any byte) reads as any character — identical on ASCII;\Bno longer matches between the bytes of a multi-byte character (/\B/on"Aé1": true with re2, false with re2js — re2js is the one that is right).Koncorde's own suite: 423 passing, lint clean.
Trade-off: matching is slower
scripts/re2-bench.js(darwin-arm64, Node 24; the CI job prints it too):^user_@example\.com$/i^[a-z0-9._%+-]+@…$/i(error|warn|fatal)\p{L}+ville$/u(a+)+b(ReDoS-shaped)The cost is per written document × regexp subscriptions on the field: 1 000 regexp subscriptions on one field ≈ 0.1 ms → 0.5–2.5 ms per document. No regexp subscription, no cost.
Options (to decide before undrafting)
re2as anoptionalDependency, re2js as fallback: native speed where the binary installs,npm cino longer fails when it does not — but the GitHub download stays, and behavior (the two differences above, error wording) would depend on the environment.re2and close this:with-retry.shcovers its download failures in Kuzzle's CI.Deciding factor: how many
regexpsubscriptions real projects carry.🤖 Generated with Claude Code