re2

Node.js bindings for Google's RE2 engine — a linear-time, ReDoS-safe drop-in replacement for JavaScript's RegExp.

Library
npm
v1.26.1
559stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
79/100Good
Development Activity92
Maintenance84
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
85/100Excellent
Architecture88
Code Quality90
Innovation85
Learning Curve78

node-re2 wraps Google’s RE2 regular expression engine as a native Node.js C++ addon, giving JavaScript a way to run regular expressions in guaranteed linear time instead of the built-in engine’s exponential worst case. Untrusted patterns paired with adversarial input strings can freeze a Node process for as long as it takes to trigger a ReDoS attack against the native RegExp engine; RE2 sidesteps that class of vulnerability entirely by compiling patterns into a deterministic finite automaton instead of backtracking.

The library keeps API compatibility with RegExp as its central design goal: RE2 instances expose the same properties and methods, hook into Symbol.match/Symbol.replace/Symbol.search/Symbol.split/Symbol.matchAll so they work transparently with String.prototype methods, and ship full TypeScript declarations. It also accepts raw binary input (Buffer, typed arrays, ArrayBuffer, SharedArrayBuffer) for matching directly against file or network data, and provides RE2.Set for compiling many patterns into a single automaton for fast multi-pattern matching.

What You Get

  • Native RE2 regex engine bindings compiled as a Node.js C++ addon, with prebuilt binaries downloaded for common platforms and Node ABIs.
  • A drop-in RE2 constructor that mirrors RegExp’s properties, methods, and well-known Symbol hooks so existing String.prototype call sites keep working unchanged.
  • RE2.Set for compiling and testing many patterns at once against a single input via one automaton.
  • First-class Buffer/TypedArray/ArrayBuffer support for matching against binary data with byte-offset results, no UTF-8/UTF-16 round-tripping required.
  • Full TypeScript type declarations (re2.d.ts) covering both string- and buffer-based method overloads.

Common Use Cases

  • Validating or matching user-supplied regular expressions where an attacker-controlled pattern could otherwise cause a ReDoS denial of service.
  • Filtering or parsing untrusted input (form fields, log lines, HTTP bodies) with regexes at high throughput and predictable latency.
  • Building CLI or server tools that run many regex patterns against streams of binary data efficiently via RE2.Set.
  • Replacing RegExp in hot code paths that don’t rely on lookahead/backreferences, to get linear-time performance guarantees under load.

Under The Hood

Architecture node-re2 splits cleanly into a thin JavaScript entry point and a C++ native addon. re2.js loads the compiled build/Release/re2.node binary and layers on the pieces that make the addon feel like a native RegExp — installing Symbol.match/search/replace/split aliases and a generator-based Symbol.matchAll — while every actual matching operation lives in lib/, organized one file per RegExp method (exec.cc, test.cc, match.cc, replace.cc, search.cc, split.cc, to_string.cc, accessors.cc) plus shared infrastructure (wrapped_re2.h for the core class holding the re2::RE2* instance, flags, and lastIndex; isolate_data.h for per-V8-isolate addon state; pattern.cc for translating JS RegExp syntax, including Unicode property escapes, into RE2 syntax at construction time; util.cc for the UTF-8/UTF-16 buffer conversion every input site shares). RE2.Set (set.cc/wrapped_re2_set.h) is a parallel, self-contained path for compiling multiple patterns into one automaton. Because RE2 itself and its Abseil dependency are vendored as git submodules under vendor/ and compiled directly via node-gyp/binding.gyp rather than dynamically linked, the addon has no runtime dependency on a system RE2 install.

Tech Stack The addon is built with node-gyp and Nan (Native Abstractions for Node.js) against Node’s V8/N-API surface, compiling the project’s own lib/*.cc alongside vendored copies of Google’s RE2 and Abseil-cpp (both git submodules) per binding.gyp’s platform-specific compiler flags for GCC/Clang/MSVC. Distribution avoids forcing a local compile: the install script first tries install-artifact-from-github to pull a prebuilt re2.node for the current platform/Node ABI combination (macOS, Linux glibc and musl, Windows; x64 and arm64), verified against SHA-256 hashes stamped into package.json at publish time by hash-github-cache, and only falls back to node-gyp rebuild if no matching artifact exists. The public surface is typed via a hand-written re2.d.ts checked by tsc —noEmit through a dedicated ts-tests/ project, tests run under tape-six across worker-thread, sequential, and multi-process modes, Prettier enforces formatting, and GitHub Actions plus Dependabot round out CI.

Code Quality Test coverage is extensive and specific rather than smoke-level: twenty-plus tests/test-*.mjs files exercise construction edge cases, buffer/typed-array inputs, RE2.Set, replace/split/match/search semantics, Unicode edge cases, and truncated UTF-8 handling, run three different ways (worker threads, sequential, multi-process) to catch concurrency issues specific to a native addon. Error handling in the C++ layer is explicit — invalid constructor arguments throw typed TypeError/SyntaxError via Nan’s exception helpers rather than crashing or returning undefined, and a dedicated binary-data classifier in wrapped_re2.h centralizes logic that would otherwise be duplicated across every method. The codebase favors small, single-responsibility .cc files per operation, and the public TypeScript declarations are exercised by a real compile step rather than left to drift from the implementation. Inline comment density in the C++ layer is comparatively light, offset by an unusually thorough ARCHITECTURE.md documenting the same ground at the project level.

API Design The public API is designed to disappear: both new RE2(pattern, flags) and RE2(pattern, flags) work, and Symbol.match/replace/search/split/matchAll let existing String.prototype call sites accept an RE2 instance with zero code changes, with named capture groups round-tripping exactly as they would with native RegExp. Buffer-aware overloads are additive rather than a separate API — the same exec/match/test/replace/search/split methods accept Buffer/TypedArray/ArrayBuffer and return buffer-typed results with byte offsets, so no parallel “binary mode” API had to be learned. The one deliberate rough edge is also the one that matters most for adoption: unsupported RegExp features (backreferences, lookahead) throw a clear SyntaxError at construction time instead of silently changing match semantics, so a port from RegExp fails loudly and immediately rather than producing subtly wrong matches in production.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search