JS: Regex Flag v (unicodeSets)

By Xah Lee. Date: . Last updated: .

(new in ECMAScript 2024)

work in progress

What's regex flag v

The v flag (unicodeSets) is an upgrade to the older u (unicode) flag for JavaScript regular expressions. It enables enhanced Unicode features.

when on, it features ALL capabilities of the u flag.

and:

Unicode properties of strings

\p{unicode_property} can match unicode properties of strings, such as emoji sequences with skin color modifiers, or nation's flags made of 2 code points, etc.

console.log("🇺🇳".match(/\p{RGI_Emoji_Flag_Sequence}/v));
// [ "🇺🇳", index: 0, input: "🇺🇳", groups: undefined ]

Set notation in character classes

Set notation in character classes: intersection (&&), union, and subtraction (--), plus nested classes and multi-code-point matches.

const xresult = "é Δ α β".matchAll(/[\p{Lowercase}&&\p{Script=Greek}]/gv);
console.log(Array.from(xresult));
/*
[
  [ "α", index: 4, input: "é Δ α β", groups: undefined ],
  [ "β", index: 6, input: "é Δ α β", groups: undefined ]
]
*/

Cannot be used with flag u

flag u and v cannot be used together. only one of them. when both are used, it throws SyntaxError.

const rgx = /x/uv;
// error: Uncaught SyntaxError: Invalid regular expression flags

Some patterns valid under u are invalid under v (stricter character class rules).

🟢 tip: flag v fixes lots classic regex problems, and added advanced features. It's good idea to always have it on, unless you have specific reason not to.

Example. intersection of unicode properties

// get lowercase Greek letters.
const rgx = /[\p{Lowercase}&&\p{Script=Greek}]/gv;
const xtext = "symbols à á â ⊕ Δ α β";
const xresult = xtext.matchAll(rgx);
console.log(
 Array.from(xresult),
);
/*
[
  [ "α", index: 18, input: "symbols à á â ⊕ Δ α β", groups: undefined ],
  [ "β", index: 20, input: "symbols à á â ⊕ Δ α β", groups: undefined ]
]
*/

Substraction of unicode character class sets

// Match any letter that is NOT ASCII (i.e. non-English letters)
const rgx = /[\p{Letter}--\p{ASCII}]/gv;
const xtext = "some á Δ α β";
const xresult = xtext.matchAll(rgx);
console.log(Array.from(xresult));
/*
[
  [ "á", index: 5, input: "some á Δ α β", groups: undefined ],
  [ "Δ", index: 7, input: "some á Δ α β", groups: undefined ],
  [ "α", index: 9, input: "some á Δ α β", groups: undefined ],
  [ "β", index: 11, input: "some á Δ α β", groups: undefined ]
]
*/

Unicode string properties

in JavaScript regex v flag, what does this mean \p{...} can match properties of strings (not just single characters).

(ai answer)

With the v flag, \p{…} can match properties of strings (multi-code-point sequences), not only single characters.

This is mainly useful for emoji. Properties like these match complete sequences in one go:

Example

// flag of united nations. made up of 2 code points.
const xtext = "🇺🇳";
const rgx = /\p{RGI_Emoji_Flag_Sequence}/gv;
const xresult = xtext.matchAll(rgx);

console.log(Array.from(xresult));
// [ [ "🇺🇳", index: 0, input: "🇺🇳", groups: undefined ] ]

You do not need + for these string properties. The property itself already represents the full sequence.

Important distinctions

So: the “no plus needed” behavior applies only to the special multi-code-point string properties, not to ordinary character properties.

is the 'multi-code-point string properties' concept from unicode spec?

Yes. The concept of properties of strings (including multi-code-point ones) comes from the Unicode Standard.

Unicode distinguishes:

This is covered in:

So the multi-code-point behavior you see with \p{RGI_Emoji} etc. is not a JavaScript invention — it is directly based on Unicode’s definition of those string properties.

what's RGI_Emoji

RGI_Emoji = Recommended for General Interchange emoji.

It is a Unicode property of strings (defined in UTS #51) that matches the set of emoji characters and sequences that Unicode recommends for general use/interchange.

It includes:

In JavaScript with the v flag:

/\p{RGI_Emoji}/v

This matches complete emoji (whether one code point or many) in one match, which is usually what you want instead of the broader/older \p{Emoji} property.

Property regexp.prototype.unicodesets

const rgx = /some/v;
console.assert(rgx.unicodeSets === true);