API reference

RegExp

14/15Coverage10/15Strict (zero caveats)

PCRE2 under the hood, but aligned to the ECMAScript dialect by default so the everyday edge cases (`$` at the true end, an unset backreference matching empty, `\uXXXX` escapes) behave as real JS does. The recurring divergences are structural: strings are byte-indexed, so match offsets are byte positions unless you opt into `-regex=es-utf16`; `exec` results carry `index`, `input` and `groups`, and so does each step of `matchAll`'s iterator. The whole-program `-regex=<mode>` flag trades fidelity for speed across five modes, and the `u`/`d` flags are out of scope for V1 (`y`/sticky is implemented).

Exact Works, with caveats Not supported

Construction: new RegExp(pattern, flags?)

supported
new RegExp(pattern: string, flags?: string): RegExp

Compiles the pattern once via PCRE2 and throws a real, catchable SyntaxError on an invalid pattern. The flags string is validated as in real JS — a duplicate flag ("gg") or an unrecognized flag character ("z") throws a SyntaxError. A \uXXXX/\xXX escape compiles as an ECMAScript escape in the default and es-ascii modes.

Parameters
patternstring
The pattern source.
flagsstring
Optional flag string (e.g. "gi").
Returns

RegExp — A compiled RegExp.

const fromCtor = new RegExp("[a-z]+@[a-z]+\\.[a-z]+", "i")
console.log(fromCtor.source)
See it in a full example →

Literal syntax: /pattern/flags

Works, with caveats
/pattern/flags

Regex literals desugar to the same construction at parse time. An unescaped '/' inside a [...] character class does not end the literal.

const fromLiteral = /[a-z]+@[a-z]+\.[a-z]+/i
const withSlashClass = /[a/b]/
console.log(withSlashClass.source) // [a/b]
See it in a full example →
⚠ Differences from standard
  • x in /foo/ mis-lexes the / as division (the lexer's regex-vs-division disambiguation gap, since in isn't its own token in this lexer) — a small, deliberately-accepted gap

.source / .flags

Exact
re.source: string; re.flags: string

Field reads decomposed once at construction: .flags reports the canonical d,g,i,m,s,u,v,y order regardless of how the flags were given, and an empty pattern's .source is the spec placeholder "(?:)".

Returns

string — The pattern source / flag string.

const r = new RegExp("^\\d+$", "gm")
console.log(r.flags) // gm
See it in a full example →

.global / .ignoreCase / .multiline / .dotAll

Exact
re.global | re.ignoreCase | re.multiline | re.dotAll: boolean

The four boolean flag accessors, decomposed from the flags string once at construction — no method needs to re-parse it.

Returns

boolean — Whether the corresponding flag is set.

const r = new RegExp("^\\d+$", "gm")
console.log(r.global)     // 1
console.log(r.multiline)  // 1
See it in a full example →

.lastIndex

Exact
re.lastIndex: number

The iteration cursor: mutated by .exec()/.test()/global str.match()/str.matchAll()/str.replace()/str.replaceAll() (advances on a successful g-flagged match, resets to 0 after a failed one), and deliberately untouched by str.split()/str.search(), matching real JS.

Returns

number — The next match start offset.

const g = /\d+/g
let match = g.exec("a1 b22 c333")
while (match !== null) { console.log(match[0]); match = g.exec("a1 b22 c333") }
console.log(g.lastIndex) // 0
See it in a full example →

.test(str)

Exact
re.test(str: string): boolean

A real PCRE2 match returning a boolean. A g-flagged RegExp reads/advances .lastIndex exactly as .exec() does, so a while (re.test(s)) loop steps through every match; a non-global RegExp always matches from offset 0 and never touches .lastIndex.

Parameters
strstring
The subject string.
Returns

boolean — Whether the pattern matches.

const digits = /[0-9]+/
console.log(digits.test("abc123")) // 1
console.log(digits.test("abcdef")) // 0
See it in a full example →

.exec(str)

Exact
re.exec(str: string): RegExpExecArray | null

Returns string[] | null — index 0 is the full match, 1..N are the numbered capture groups; real, working m !== null / if (m) checks against the result. A global RegExp reads/writes .lastIndex exactly like real JS, so the while ((m = re.exec(s)) !== null) idiom works. All matching methods route through the one compiled PCRE2 handle, so the -regex dialect mode applies uniformly here and to match/matchAll/replace/replaceAll/split/search.

Parameters
strstring
The subject string.
Returns

string[] | null — Match array, or null on no match.

const range = /(\d+)-(\d+)/
const m = range.exec("range: 12-34 end")
if (m !== null) { console.log(m[1]); console.log(m[2]) } // 12 / 34
See it in a full example →

str.match(regexp)

Works, with caveats
str.match(regexp: RegExp): string[] | null

Without g: identical to regexp.exec(str). With g: full-match-only strings, and null (not []) on zero matches — matching real JS exactly.

Parameters
regexpRegExp
The pattern to match.
Returns

string[] | null — Match array, or null.

const allDigits = "a1 b22 c333".match(/\d+/g)
if (allDigits !== null) { console.log(allDigits.length) } // 3
console.log("nothing".match(/\d+/g) === null) // true
See it in a full example →
⚠ Differences from standard
  • With a regex held in a variable (not a literal), the result has no index/input/groups; a non-global literal's result carries them, as .exec()'s does

str.matchAll(regexp)

Exact
str.matchAll(regexp: RegExp): RegExpStringIterator<RegExpExecArray>

A RegExp String Iterator over every match, each step an exec result with index, input and groups. It runs on a clone of the RegExp, starting at its lastIndex, so the original's lastIndex is untouched. Throws a TypeError without the g flag.

Parameters
regexpRegExp
A g-flagged pattern.
Returns

RegExpStringIterator<RegExpExecArray> — An iterator of exec results.

for (const each of "a-1 b-22 c-333".matchAll(/(\w)-(\d+)/g)) {
  console.log(each[0], each.index)
}
See it in a full example →

str.replace(regexp, replacement)

Works, with caveats
str.replace(regexp: RegExp, replacement: string | ((m, offset, string) => string)): string

Replaces the first match without g, every match with g; the callback runs exactly once per match.

Parameters
regexpRegExp
The pattern to match.
replacementstring | function
Template string or a callback.
Returns

string — The resulting string.

console.log("range: 12-34 end".replace(/(\d+)-(\d+)/, "[$2:$1]")) // range: [34:12] end
console.log("a1 b22 c333".replace(/\d+/g, (m: string, offset: number) => m + "@" + offset))
See it in a full example →
⚠ Differences from standard
  • Replacement template supports $1-$9/$&/$$ only (` $ `/$'` — pre-/post-match text — are out of scope)
  • The callback form is invoked with a fixed (match, offset, string) — real JS's variadic ...capturedGroups in the middle isn't supported (a callback's arity is fixed at compile time but a pattern's capture count is only known at runtime; a callback declaring more than 3 parameters is a compile-time error)

str.replaceAll(regexp, replacement)

Works, with caveats
str.replaceAll(regexp: RegExp, replacement: string | ((m, offset, string) => string)): string

Same replacement rules as .replace(); requires the g flag, throwing TypeError otherwise.

Parameters
regexpRegExp
A g-flagged pattern.
replacementstring | function
Template string or a callback.
Returns

string — The resulting string.

console.log("cat dog cat".replaceAll(/cat/g, "DOG")) // DOG dog DOG
See it in a full example →
⚠ Differences from standard
  • Same replacement narrowing as .replace() ($1-$9/$&/$$ only; fixed (match, offset, string) callback)

str.split(regexp)

Exact
str.split(regexp: RegExp): string[]

Finds every match regardless of the g flag (its own local search loop, like real JS), splicing the separator's capture groups in after each piece (an unmatched one as undefined). A regex that never matches returns a single-element array holding the whole subject.

Parameters
regexpRegExp
The delimiter pattern.
Returns

string[] — The split pieces.

const parts = "a1b22c333d".split(/\d+/)
console.log(parts.length) // 4
See it in a full example →

str.search(regexp)

supported
str.search(regexp: string | RegExp): number

Always searches from offset 0, restores .lastIndex afterward — invisible to later .exec()/.test() iteration, matching real JS exactly. A plain-string argument is coerced to a RegExp as in real JS (metacharacters interpreted). Returns -1 on no match.

Parameters
regexpRegExp
The pattern to search for.
Returns

number — Match offset, or -1.

console.log("hello world".search(/world/)) // 6
console.log("hello world".search(/xyz/))   // -1
See it in a full example →

y (sticky) flag

Exact
re.sticky: boolean // /pattern/y, new RegExp(p, "y")

A sticky RegExp matches only at exactly .lastIndex: the match is anchored there, .lastIndex advances to the match end on success and resets to 0 on failure, exactly as for g. The real RegExpBuiltinExec rule — lastIndex is honoured when global OR sticky is set — flows through exec, test, match, matchAll, replace, replaceAll and search.

Returns

boolean — Whether the y flag is set.

const re = /foo/y
re.lastIndex = 3
console.log(re.test("barfoo"), re.lastIndex)  // true 6
console.log(re.test("barfoo"), re.lastIndex)  // false 0
See it in a full example →

u / d flags

Not supported
// not supported

The u (unicode) and d (indices) flags are deferred for the whole feature's V1. \u{…} code-point escapes, surrogate handling, Unicode \p{…}/class semantics, and strict-syntax validation are a later option.