# node-re2 [![NPM version][npm-img]][npm-url]

[npm-img]: https://img.shields.io/npm/v/re2.svg
[npm-url]: https://npmjs.org/package/re2

This project provides Node.js bindings for [RE2](https://github.com/google/re2):
a fast, safe alternative to backtracking regular expression engines written by [Russ Cox](http://swtch.com/~rsc/) in C++.
To learn more about RE2, start with [Regular Expression Matching in the Wild](http://swtch.com/~rsc/regexp/regexp3.html). More resources are on his [Implementing Regular Expressions](http://swtch.com/~rsc/regexp/) page.

`RE2`'s regular expression language is almost a superset of what `RegExp` provides
(see [Syntax](https://github.com/google/re2/wiki/Syntax)),
but it lacks backreferences and lookahead assertions. See below for details.

`RE2` always works in [Unicode mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode) &mdash; character codes are interpreted as Unicode code points, not as binary values of UTF-16.
See `RE2.unicodeWarningLevel` below for details.

`RE2` emulates standard `RegExp`, making it a practical drop-in replacement in most cases.
It also provides `String`-based regular expression methods. The constructor accepts `RegExp` directly, honoring all properties.

It can work with [Node.js Buffers](https://nodejs.org/api/buffer.html) directly, reducing overhead and making processing of long files fast.

The project is a C++ addon built with [nan](https://github.com/nodejs/nan). It cannot be used in web browsers.
All documentation is in this README and in the [wiki](https://github.com/uhop/node-re2/wiki) &mdash; browse the [index](https://github.com/uhop/node-re2/wiki/Home), or [search it](https://uhop.github.io/wiki-search/app/?wiki=uhop/node-re2) by name.

## Why use node-re2?

The built-in Node.js regular expression engine can run in exponential time with a special combination:
 - A vulnerable regular expression
 - "Evil input"

This can lead to what is known as a [Regular Expression Denial of Service (ReDoS)](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS).
To check if your regular expressions are vulnerable, try one of these projects:
 - [rxxr2](http://www.cs.bham.ac.uk/~hxt/research/rxxr2/)
 - [safe-regex](https://github.com/substack/safe-regex)

Neither project is perfect.

node-re2 protects against ReDoS by evaluating patterns in `RE2` instead of the built-in regex engine.

To run the bundled benchmark (make sure node-re2 is built first):

```bash
npx nano-bench bench/bad-pattern.mjs
```

## Standard features

`RE2` objects are created just like `RegExp`:

* [`new RE2(pattern[, flags])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp)

Supported flags: `g` (global), `i` (ignoreCase), `m` (multiline), `s` (dotAll), `u` (unicode, always on), `y` (sticky), `d` (hasIndices).

Supported properties:

* [`re2.lastIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex)
* [`re2.global`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global)
* [`re2.ignoreCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase)
* [`re2.multiline`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline)
* [`re2.dotAll`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll)
* [`re2.unicode`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode) &mdash; always `true`; see details below.
* [`re2.sticky`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky)
* [`re2.hasIndices`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/hasIndices)
* [`re2.source`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source)
* [`re2.flags`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags)

Supported methods:

* [`re2.exec(str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec)
* [`re2.test(str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)
* [`re2.toString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString)

Well-known symbol-based methods are supported (see [Symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)):

* [`re2[Symbol.match](str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/match)
* [`re2[Symbol.matchAll](str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/matchAll)
* [`re2[Symbol.search](str)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/search)
* [`re2[Symbol.replace](str, newSubStr|function)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/replace)
* [`re2[Symbol.split](str[, limit])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/split)

This lets you use `RE2` instances on strings directly, just like `RegExp`:

```js
const re = new RE2('1');
'213'.match(re);        // [ '1', index: 1, input: '213' ]
'213'.search(re);       // 1
'213'.replace(re, '+'); // 2+3
'213'.split(re);        // [ '2', '3' ]

Array.from('2131'.matchAll(new RE2('1', 'g'))); // matchAll requires the g flag
// [['1', index: 1, input: '2131'], ['1', index: 3, input: '2131']]
```

[Named groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group) are supported.

## Extensions

### Shortcut construction

`RE2` can be created from a regular expression:

```js
const re1 = new RE2(/ab*/ig); // from a RegExp object
const re2 = new RE2(re1);     // from another RE2 object
```

### `String` methods

`RE2` provides the standard `String` regex methods with swapped receiver and argument:

* `re2.match(str)`
  * See [`str.match(regexp)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match)
* `re2.replace(str, newSubStr|function)`
  * See [`str.replace(regexp, newSubStr|function)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
* `re2.search(str)`
  * See [`str.search(regexp)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search)
* `re2.split(str[, limit])`
  * See [`str.split(regexp[, limit])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split)

These methods are also available as well-known symbol-based methods for transparent use with ES6 string/regex machinery.

### `Buffer` support

Most methods accept Buffers instead of strings for direct UTF-8 processing:

* `re2.exec(buf)`
* `re2.test(buf)`
* `re2.match(buf)`
* `re2.search(buf)`
* `re2.split(buf[, limit])`
* `re2.replace(buf, replacer)`

Differences from string-based versions:

* All buffers are assumed to be encoded as [UTF-8](https://en.wikipedia.org/wiki/UTF-8)
  (ASCII is a proper subset of UTF-8).
* Results are `Buffer` objects, even in composite objects. Convert with
  [`buf.toString()`](https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end).
* All offsets and lengths are in bytes, not characters (each UTF-8 character occupies 1–4 bytes).
  This lets you slice buffers directly without costly character-to-byte recalculations.

When `re2.replace()` is used with a replacer function, the replacer receives string arguments and character offsets by default. Set `useBuffers` to `true` on the function to receive byte offsets instead:

```js
function strReplacer(match, offset, input) {
	// typeof match == "string"
	return "<= " + offset + " characters|";
}

RE2("б").replace("абв", strReplacer);
// "а<= 1 characters|в"

function bufReplacer(match, offset, input) {
	// typeof match == "string"
	return "<= " + offset + " bytes|";
}
bufReplacer.useBuffers = true;

RE2("б").replace("абв", bufReplacer);
// "а<= 2 bytes|в"
```

This works for both string and buffer inputs. Buffer input produces buffer output; string input produces string output.

### `RE2.Set`

Use `RE2.Set` when the same string must be tested against many patterns. It builds a single automaton and frequently beats running individual regular expressions one by one.

While `test()` can be simulated by combining patterns with `|`, `match()` returns which patterns matched &mdash; something a single regular expression cannot do.

* `new RE2.Set(patterns[, flagsOrOptions][, options])`
  * `patterns` is any iterable of strings, `Buffer`s, `RegExp`, or `RE2` instances; flags (if provided) apply to the whole set.
  * `flagsOrOptions` can be a string/`Buffer` with standard flags (`i`, `m`, `s`, `u`, `g`, `y`, `d`).
  * `options.anchor` can be `'unanchored'` (default), `'start'`, or `'both'`.
  * `options.maxMem` is the DFA memory budget in bytes (positive integer). Default is 8 MiB &mdash; raise it to compile sets that would otherwise fail with `"RE2.Set could not be compiled."`.
* `set.test(str)` returns `true` if any pattern matches and `false` otherwise.
* `set.match(str)` returns an array of indexes of matching patterns.
  * This is an array of integer indices of patterns that matched sorted in ascending order.
  * If no patterns matched, an empty array is returned.
* Read-only properties:
  * `set.size` (number of patterns), `set.flags` (`RegExp` flags as a string), `set.anchor` (anchor mode as a string)
  * `set.source` (all patterns joined with `|` as a string), `set.sources` (individual pattern sources as an array of strings)
  * `set.maxMem` (number) &mdash; effective DFA memory budget in bytes

It is based on [RE2::Set](https://github.com/google/re2/blob/main/re2/set.h).

Example:

```js
const routes = new RE2.Set([
  '^/users/\\d+$',
  '^/posts/\\d+$'
], 'i', {anchor: 'start'});

routes.test('/users/7');     // true
routes.match('/posts/42');   // [1]
routes.sources;              // ['^/users/\\d+$', '^/posts/\\d+$']
routes.toString();           // '/^/users/\\d+$|^/posts/\\d+$/iu'
```

To run the bundled benchmark (make sure node-re2 is built first):

```bash
npx nano-bench bench/set-match.mjs
```

### Calculate length

Two helpers convert between UTF-8 and UTF-16 sizes:

* `RE2.getUtf8Length(str)` &mdash; byte size needed to encode a string as a UTF-8 buffer.
* `RE2.getUtf16Length(buf)` &mdash; character count needed to decode a UTF-8 buffer as a string.

### Property: `internalSource`

`source` emulates the standard `RegExp` property and can recreate an identical `RE2` or `RegExp` instance. To inspect the RE2-translated pattern (useful for debugging), use the read-only `internalSource` property.

### Unicode warning level

`RE2` always works in Unicode mode. In most cases this is either invisible or preferred. For applications that need tight control, the static property `RE2.unicodeWarningLevel` governs what happens when a non-Unicode regular expression is created.

If a regular expression lacks the `u` flag, it is added silently by default:

```js
const x = /./;
x.flags; // ''
const y = new RE2(x);
y.flags; // 'u'
```

Values of `RE2.unicodeWarningLevel`:

* `'nothing'` (default) &mdash; silently add `u`.
* `'warnOnce'` &mdash; warn once, then silently add `u`. Assigning this value resets the one-time flag.
* `'warn'` &mdash; warn every time, still add `u`.
* `'throw'` &mdash; throw `SyntaxError`.
* Any other value is silently ignored, leaving the previous value unchanged.

Warnings and exceptions help audit an application for stray non-Unicode regular expressions.

`RE2.unicodeWarningLevel` is global. Be careful in multi-threaded environments &mdash; it is shared across threads.

## How to install

```bash
npm install re2
```

The project works with other package managers but is not tested with them.
See the wiki for notes on [yarn](https://github.com/uhop/node-re2/wiki/Using-with-yarn) and [pnpm](https://github.com/uhop/node-re2/wiki/Using-with-pnpm).

### Supported Node.js versions

`re2` supports every non-EOL Node.js release &mdash; current and active LTS lines. As a native (`nan`) addon it runs on Node.js only, not Bun or Deno. The authoritative supported range is the `engines` field in `package.json`; it also pins the minimum patch releases the build toolchain ([`node-gyp`](https://github.com/nodejs/node-gyp) 13) requires. Check `engines` for the exact floor rather than a version repeated here.

### Install scripts (npm 12+)

`re2` downloads or builds its native binary in an `install` script. Starting with npm 12
(July 2026), npm does not run dependency install scripts unless the package is listed in the
`allowScripts` field of your project's `package.json` &mdash; without it, `npm install re2`
fails with `ESTRICTALLOWSCRIPTS`. npm 11.16+ still runs the scripts but prints a warning.

Allow `re2` before installing:

```bash
npm pkg set allowScripts.re2=true --json
npm install re2
```

Or use npm's approval tooling &mdash; note that `npm approve-scripts` only matches installed
packages, so under npm 12 the package has to be installed with scripts skipped first:

```bash
npm install re2 --ignore-scripts
npm approve-scripts re2
npm rebuild re2
```

`npm approve-scripts` pins the approval to the installed version, so version updates ask again;
pass `--no-allow-scripts-pin` (or use the `allowScripts.re2=true` form above) to allow all
versions. No other package in `re2`'s dependency tree runs install scripts. For the full story see
[NPM 12 and install scripts](https://github.com/uhop/install-artifact-from-github/wiki/NPM-12-and-install-scripts)
and GitHub's official [announcement of the npm v12 breaking changes](https://github.blog/changelog/2026-06-09-upcoming-breaking-changes-for-npm-v12/).

### Precompiled artifacts

The [install script](https://github.com/uhop/install-artifact-from-github/blob/master/bin/install-from-cache.js) attempts to download a prebuilt artifact from GitHub Releases. A download from GitHub is [verified](https://github.com/uhop/install-artifact-from-github/wiki/Verifying-artifacts) against the SHA-256 hashes pinned in this package's `artifactHashes` field before it is used &mdash; a binary that is not byte-for-byte the one published is rejected. Override the download location with the `RE2_DOWNLOAD_MIRROR` environment variable (a mirror serves your own builds and is not hash-checked). To skip the download entirely and always build from source, set `RE2_DOWNLOAD_FORCE_BUILD` to a non-empty value.

If the download fails or is rejected, the script builds RE2 locally using [node-gyp](https://github.com/nodejs/node-gyp).

## How to use

It is used just like `RegExp`.

```js
const RE2 = require('re2');

// with default flags
let re = new RE2('a(b*)');
let result = re.exec('abbc');
console.log(result[0]); // 'abb'
console.log(result[1]); // 'bb'

result = re.exec('aBbC');
console.log(result[0]); // 'a'
console.log(result[1]); // ''

// with explicit flags
re = new RE2('a(b*)', 'i');
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'

// from regular expression object
const regexp = new RegExp('a(b*)', 'i');
re = new RE2(regexp);
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'

// from regular expression literal
re = new RE2(/a(b*)/i);
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'

// from another RE2 object
const rex = new RE2(re);
result = rex.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'

// shortcut
result = new RE2('ab*').exec('abba');

// factory
result = RE2('ab*').exec('abba');
```

## Limitations (things RE2 does not support)

`RE2` avoids any regular expression features that require worst-case exponential time to evaluate.
The most notable missing features are backreferences and lookahead assertions.
If your application uses them, you should continue to use `RegExp` &mdash;
but since they are fundamentally vulnerable to
[ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS),
consider replacing them.

`RE2` throws `SyntaxError` for unsupported features.
Wrap `RE2` declarations in a try-catch to fall back to `RegExp`:

```js
let re = /(a)+(b)*/;
try {
  re = new RE2(re);
  // use RE2 as a drop-in replacement
} catch (e) {
  // use the original RegExp
}
const result = re.exec(sample);
```

`RE2` may also behave differently from the built-in engine in corner cases.

### Backreferences

`RE2` does not support backreferences &mdash; numbered references to previously
matched groups (`\1`, `\2`, etc.). Example:

```js
/(cat|dog)\1/.test("catcat"); // true
/(cat|dog)\1/.test("dogdog"); // true
/(cat|dog)\1/.test("catdog"); // false
/(cat|dog)\1/.test("dogcat"); // false
```

### Lookahead assertions

`RE2` does not support lookahead assertions, which make a match depend on subsequent contents.

```js
/abc(?=def)/; // match abc only if it is followed by def
/abc(?!def)/; // match abc only if it is not followed by def
```

### Mismatched behavior

`RE2` and the built-in engine may disagree in edge cases. Verify your regular expressions before switching. They should work in the vast majority of cases.

Example:

```js
const RE2 = require('re2');

const pattern = '(?:(a)|(b)|(c))+';

const built_in = new RegExp(pattern);
const re2 = new RE2(pattern);

const input = 'abc';

const bi_res = built_in.exec(input);
const re2_res = re2.exec(input);

console.log('bi_res: ' + bi_res);    // prints: bi_res: abc,,,c
console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c
```

### Unicode

`RE2` always works in Unicode mode. See `RE2.unicodeWarningLevel` above for details.

#### Unicode classes `\p{...}` and `\P{...}`

node-re2 follows [MDN's Unicode character class escape reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Unicode_character_class_escape) &mdash; the same set of property escapes that JavaScript's native `RegExp` accepts with the `u` flag.

Supported categories:

- **General_Category** &mdash; both short names (e.g., `\p{L}`, `\p{Lu}`) and long names (e.g., `\p{Letter}`, `\p{Uppercase_Letter}`). The `gc=` and `General_Category=` prefixes also work: `\p{gc=Letter}`, `\p{General_Category=Letter}`.
- **Script** &mdash; e.g., `\p{Script=Latin}`, `\p{sc=Cyrillic}`. ISO 15924 four-letter codes are accepted as well: `\p{sc=Latn}`.
- **Script_Extensions** &mdash; e.g., `\p{Script_Extensions=Hani}`, `\p{scx=Latn}`. Matches characters whose Script_Extensions list includes the named script (a superset of `Script=`).
- **Binary properties** &mdash; the full ECMAScript set of binary properties, including:
  - `Alphabetic`, `ASCII`, `ASCII_Hex_Digit`, `Hex_Digit`, `White_Space`, `Math`, `Dash`, `Diacritic`, `Quotation_Mark`, `Bidi_Mirrored`, `Bidi_Control`, `Default_Ignorable_Code_Point`
  - `Lowercase`, `Uppercase`, `Cased`, `Case_Ignorable`, `Changes_When_Lowercased`, `Changes_When_Uppercased`, `Changes_When_Casefolded`, `Changes_When_Casemapped`, `Changes_When_Titlecased`, `Changes_When_NFKC_Casefolded`
  - `ID_Start`, `ID_Continue`, `XID_Start`, `XID_Continue`, `Pattern_Syntax`, `Pattern_White_Space`
  - `Emoji`, `Emoji_Presentation`, `Emoji_Modifier`, `Emoji_Modifier_Base`, `Emoji_Component`, `Extended_Pictographic`, `Regional_Indicator`
  - `Grapheme_Base`, `Grapheme_Extend`, `Extender`, `Variation_Selector`, `Join_Control`, `Logical_Order_Exception`, `Sentence_Terminal`, `Terminal_Punctuation`, `Soft_Dotted`, `Radical`, `Unified_Ideograph`, `Ideographic`, `IDS_Binary_Operator`, `IDS_Trinary_Operator`, `Noncharacter_Code_Point`, `Deprecated`, `Any`, `Assigned`

  Short aliases listed in [PropertyAliases.txt](https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt) are accepted alongside the canonical names: `\p{Alpha}` ≡ `\p{Alphabetic}`, `\p{Hex}` ≡ `\p{Hex_Digit}`, `\p{Lower}` ≡ `\p{Lowercase}`, etc.

The negated form `\P{...}` and use inside character classes (`[\p{L}\p{Emoji}]`, `[^\p{ASCII}]`) work for every category.

**Not supported:** *Properties of Strings* (`\p{Basic_Emoji}`, `\p{RGI_Emoji}`, etc.). These match multi-codepoint sequences and require the `v` flag, which RE2 does not model.

Tables are baked in at build time from Unicode 17.0. To target a newer Unicode version, bump `@unicode/unicode-XX.X.X` in `devDependencies` and run `node scripts/gen-unicode-properties.mjs`.

## Release history

- 1.26.1 *Security fix (#272): a `Buffer` subject, pattern, or replacement ending in a truncated multi-byte UTF-8 character no longer reads past the end of the buffer &mdash; for `replace()` and `split()` those stray bytes were copied into the returned `Buffer`. Buffer input only; strings were never affected. Thx, [OvOhao](https://github.com/OvOhao).*
- 1.26.0 *Verified prebuilt downloads. Thx, [ataberk-xyz](https://github.com/ataberk-xyz).*
- 1.25.2 *Two DoS security fixes: a global `match()` with an empty-matchable pattern (`a*`, `(?:)`, &hellip;) no longer loops forever exhausting memory (GHSA-6hxr-mr5r-9836), and an out-of-range `lastIndex` on a non-ASCII subject no longer reads past the buffer and crashes (GHSA-ff84-5f28-78qj). Both now match the built-in engine. Thx, [ataberk-xyz](https://github.com/ataberk-xyz).*
- 1.25.1 *Security fix (GHSA-8hcv-x26h-mcgp): a global `replace()` using an output-amplifying template (`$'` or `` $` ``) on very large input could exceed V8's maximum string length and abort the whole process. It now throws a catchable `RangeError`, matching the built-in engine. Thx, [ataberk-xyz](https://github.com/ataberk-xyz).*
- 1.25.0 *Full Unicode 17.0.0 property classes (Fixes #226). New `maxMem` option for `RE2.Set`. Faster matching on pure-ASCII inputs. Narrowed Node support &mdash; drops Node 25.x and older patch releases.*
- 1.24.1 *Support for Node 22, 24, 26 + precompiled binaries.*
- 1.24.0 *Fixed multi-threaded crash in worker threads (#235). Added named import: `import {RE2} from 're2'`. Added CJS test. Updated docs and dependencies.*
- 1.23.3 *Updated Abseil and dev dependencies.*
- 1.23.2 *Updated dev dependencies.*
- 1.23.1 *Updated Abseil and dev dependencies.*
- 1.23.0 *Updated all dependencies, upgraded tooling. New feature: `RE2.Set` (thx, [Wes](https://github.com/wrmedford)).*
- 1.22.3 *Technical release: upgraded QEMU emulations to native ARM runners to speed up the build process.*
- 1.22.2 *Updated all dependencies and the list of pre-compiled targets: Node 20, 22, 24, 25 (thx, [Jiayu Liu](https://github.com/jimexist)).*
- 1.22.1 *Added support for translation of scripts as Unicode classes.*
- 1.22.0 *Added support for translation of Unicode classes (thx, [John Livingston](https://github.com/JohnXLivingston)). Added [attestations](https://github.com/uhop/node-re2/attestations).*
- 1.21.5 *Updated all dependencies and the list of pre-compiled targets. Fixed minor bugs. C++ style fix (thx, [Benjamin Brienen](https://github.com/BenjaminBrienen)). Added Windows 11 ARM build runner (thx, [Kagami Sascha Rosylight](https://github.com/saschanaz)).*
- 1.21.4 *Fixed a regression reported by [caroline-matsec](https://github.com/caroline-matsec), thx! Added pre-compilation targets for Alpine Linux on ARM. Updated deps.*
- 1.21.3 *Fixed an empty string regression reported by [Rhys Arkins](https://github.com/rarkins), thx! Updated deps.*
- 1.21.2 *Fixed another memory regression reported by [matthewvalentine](https://github.com/matthewvalentine), thx! Updated deps. Added more tests and benchmarks.*
- 1.21.1 *Fixed a memory regression reported by [matthewvalentine](https://github.com/matthewvalentine), thx! Updated deps.*
- 1.21.0 *Fixed the performance problem reported by [matthewvalentine](https://github.com/matthewvalentine) (thx!). The change improves performance for multiple use cases.*
- 1.20.12 *Updated deps. Maintenance chores. Fixes for buffer-related bugs: `exec()` index (reported by [matthewvalentine](https://github.com/matthewvalentine), thx) and `match()` index.*
- 1.20.11 *Updated deps. Added support for Node 22 (thx, [Elton Leong](https://github.com/eltonkl)).*
- 1.20.10 *Updated deps. Removed files the pack used for development (thx, [Haruaki OTAKE](https://github.com/aaharu)). Added arm64 Linux prebilds (thx, [Christopher M](https://github.com/cmanou)). Fixed non-`npm` `corepack` problem (thx, [Steven](https://github.com/styfle)).*
- 1.20.9 *Updated deps. Added more `absail-cpp` files that manifested itself on NixOS. Thx, [Laura Hausmann](https://github.com/zotanmew).*
- 1.20.8 *Updated deps: `install-artifact-from-github`. A default HTTPS agent is used for fetching precompiled artifacts avoiding unnecessary long wait times.*
- 1.20.7 *Added more `absail-cpp` files that manifested itself on ARM Alpine. Thx, [Laura Hausmann](https://github.com/zotanmew).*
- 1.20.6 *Updated deps, notably `node-gyp`.*
- 1.20.5 *Updated deps, added Node 21 and retired Node 16 as pre-compilation targets.*
- 1.20.4 *Updated deps. Fix: the 2nd argument of the constructor overrides flags. Thx, [gost-serb](https://github.com/gost-serb).*
- 1.20.3 *Fix: subsequent numbers are incorporated into group if they would form a legal group reference. Thx, [Oleksii Vasyliev](https://github.com/le0pard).*
- 1.20.2 *Fix: added a missing C++ file, which caused a bug on Alpine Linux. Thx, [rbitanga-manticore](https://github.com/rbitanga-manticore).*
- 1.20.1 *Fix: files included in the npm package to build the C++ code.*
- 1.20.0 *Updated RE2. New version uses `abseil-cpp` and required the adaptation work. Thx, [Stefano Rivera](https://github.com/stefanor).*

The rest can be consulted in the project's wiki [Release history](https://github.com/uhop/node-re2/wiki/Release-history).

## License

BSD-3-Clause
