2026-10-17 · 8 min read
- regex
- unicode
- javascript
JavaScript has two Unicode modes, and they are alternatives. The u flag makes a pattern Unicode-aware: property escapes such as \p{L} work, and a surrogate pair is one character. The v flag is Unicode sets mode. It includes that Unicode behavior and adds set syntax inside character classes. new RegExp('a', 'uv') throws. Pick one flag.
Without either flag, property escapes are not active. In Flashman's tester, \p{L} with only g does not match the letters in Ab. A class that happened to work because an engine treated unknown escapes as literals can start throwing, or matching a different set, when someone adds v.
Use the operators only where you mean a set
Inside a v-mode class, -- is difference and && is intersection. Brackets can nest. On the fixture AbC9, [\p{L}--\p{Lu}] with gv matches b: letters, minus uppercase. [\p{L}&&\p{Lu}] with gv matches A and C. [[a-c]--[b]] with gv matches a and c. The same nested pattern with gu is a syntax error.
[a--b] with gv, tested on a-b, matches a. The class means the set containing a minus the set containing b. The hyphen is the operator. It is not a character the class can match. Under gu, [a--b] throws Range out of order. There is no reading of those four characters that means the same thing in both modes.
- Put v on patterns that use -- or &&.
- Put u on patterns that only need property escapes.
- Never send both flags to the RegExp constructor.
- Retest a class that was copied from a u-mode pattern.
Escape literals the set syntax reserved
To match a hyphen in v mode, escape it. [a\-\-b] with gv matches a, -, and b on the fixture a-b. An unescaped parenthesis is also syntax: [(] with gv throws Invalid character in character class, and [\(] matches (. The reserved literal characters inside a v-mode class include parentheses, brackets, braces, slash, hyphen, backslash, and pipe. Escape the one you are trying to match.
A double punctuator is an operator or an error, not two literals. && is intersection. Writing it as two escaped ampersands, [a\&\&b], matches a, &, and b. If a pattern arrived from a builder that only knew u mode, look for these characters before you add v to the flag string.
Compare one global pass in the tester
The regex tester creates a RegExp and runs matchAll once. matchAll requires a global pattern, so the flags to type are gv or gu. Flag v alone throws because the expression is not global. The panel lists the match index and positional capture groups. It does not keep lastIndex between runs, and it does not apply sticky behavior unless the pattern includes y. Add y only when you mean a sticky scan, and expect a different list.
If the runtime throws Invalid flags for v, that engine has no Unicode sets mode. Stay on u and rewrite the class without difference, intersection, or nested sets. Diff the gu match list against the gv match list for the same fixture, and store both in JSON with the pattern and the flags. The pattern, the flags, and the fixture are one test. Changing only the flags is a different pattern.