in src/scanner.ts [1092:1144]
private testRegExp(pattern: string, flags: string): RegExp | null {
// The BMP character to use as a replacement for astral symbols when
// translating an ES6 "u"-flagged pattern to an ES5-compatible
// approximation.
// Note: replacing with '\uFFFF' enables false positives in unlikely
// scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
// pattern that would not be detected by this substitution.
const astralSubstitute = '\uFFFF';
let tmp = pattern;
const self = this;
if (flags.indexOf('u') >= 0) {
tmp = tmp
// Replace every Unicode escape sequence with the equivalent
// BMP character or a constant ASCII code point in the case of
// astral symbols. (See the above note on `astralSubstitute`
// for more information.)
.replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, ($0, $1, $2) => {
const codePoint = parseInt($1 || $2, 16);
if (codePoint > 0x10FFFF) {
self.throwUnexpectedToken(Messages.InvalidRegExp);
}
if (codePoint <= 0xFFFF) {
return String.fromCharCode(codePoint);
}
return astralSubstitute;
})
// Replace each paired surrogate with a single ASCII symbol to
// avoid throwing on regular expressions that are only valid in
// combination with the "u" flag.
.replace(
/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
astralSubstitute
);
}
// First, detect invalid regular expressions.
try {
RegExp(tmp);
} catch (e) {
this.throwUnexpectedToken(Messages.InvalidRegExp);
}
// Return a regular expression object for this pattern-flag pair, or
// `null` in case the current environment doesn't support the flags it
// uses.
try {
return new RegExp(pattern, flags);
} catch (exception) {
/* istanbul ignore next */
return null;
}
}