From 996ab6976f04c9b5927cc725fd11d01c11d38d27 Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Sat, 10 Feb 2018 23:22:20 +0900 Subject: [PATCH] replace RegExp validation --- src/regexp.js | 880 +++++++++++++++++++++++++++ src/state.js | 3 + src/tokenize.js | 78 +-- test/run.js | 1 + test/tests-regexp.js | 1347 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 2247 insertions(+), 62 deletions(-) create mode 100644 src/regexp.js create mode 100644 test/tests-regexp.js diff --git a/src/regexp.js b/src/regexp.js new file mode 100644 index 000000000..b75a311e1 --- /dev/null +++ b/src/regexp.js @@ -0,0 +1,880 @@ +const BACKSPACE = 0x08 +const CHARACTER_TABULATION = 0x09 +const LINE_FEED = 0x0A +const LINE_TABULATION = 0x0B +const FORM_FEED = 0x0C +const CARRIAGE_RETURN = 0x0D +const EXCLAMATION_MARK = 0x21 // ! +const DOLLAR_SIGN = 0x24 // $ +const LEFT_PARENTHESIS = 0x28 // ( +const RIGHT_PARENTHESIS = 0x29 // ) +const ASTERISK = 0x2A // * +const PLUS_SIGN = 0x2B // + +const COMMA = 0x2C // , +const HYPHEN_MINUS = 0x2D // - +const FULL_STOP = 0x2E // . +const SOLIDUS = 0x2F // / +const DIGIT_ZERO = 0x30 // 0 +const DIGIT_ONE = 0x31 // 1 +const DIGIT_THREE = 0x33 // 3 +const DIGIT_SEVEN = 0x37 // 7 +const DIGIT_NINE = 0x39 // 9 +const COLON = 0x3A // : +const EQUALS_SIGN = 0x3D // = +const QUESTION_MARK = 0x3F // ? +const LATIN_CAPITAL_LETTER_A = 0x41 // A +const LATIN_CAPITAL_LETTER_B = 0x42 // B +const LATIN_CAPITAL_LETTER_D = 0x44 // D +const LATIN_CAPITAL_LETTER_F = 0x46 // F +const LATIN_CAPITAL_LETTER_S = 0x53 // S +const LATIN_CAPITAL_LETTER_W = 0x57 // W +const LATIN_CAPITAL_LETTER_Z = 0x5A // Z +const LOW_LINE = 0x5F // _ +const LATIN_SMALL_LETTER_A = 0x61 // a +const LATIN_SMALL_LETTER_B = 0x62 // b +const LATIN_SMALL_LETTER_C = 0x63 // c +const LATIN_SMALL_LETTER_D = 0x64 // d +const LATIN_SMALL_LETTER_F = 0x66 // f +const LATIN_SMALL_LETTER_N = 0x6E // n +const LATIN_SMALL_LETTER_R = 0x72 // r +const LATIN_SMALL_LETTER_S = 0x73 // s +const LATIN_SMALL_LETTER_T = 0x74 // t +const LATIN_SMALL_LETTER_U = 0x75 // u +const LATIN_SMALL_LETTER_V = 0x76 // v +const LATIN_SMALL_LETTER_W = 0x77 // w +const LATIN_SMALL_LETTER_X = 0x78 // x +const LATIN_SMALL_LETTER_Z = 0x7A // z +const LEFT_SQUARE_BRACKET = 0x5B // [ +const REVERSE_SOLIDUS = 0x5C // \ +const RIGHT_SQUARE_BRACKET = 0x5D // [ +const CIRCUMFLEX_ACCENT = 0x5E // ^ +const LEFT_CURLY_BRACKET = 0x7B // { +const VERTICAL_LINE = 0x7C // | +const RIGHT_CURLY_BRACKET = 0x7D // } + +function isSyntaxCharacter(ch) { + return ( + ch === CIRCUMFLEX_ACCENT || + ch === DOLLAR_SIGN || + ch === REVERSE_SOLIDUS || + ch === FULL_STOP || + ch === ASTERISK || + ch === PLUS_SIGN || + ch === QUESTION_MARK || + ch === LEFT_PARENTHESIS || + ch === RIGHT_PARENTHESIS || + ch === LEFT_SQUARE_BRACKET || + ch === RIGHT_SQUARE_BRACKET || + ch === LEFT_CURLY_BRACKET || + ch === RIGHT_CURLY_BRACKET || + ch === VERTICAL_LINE + ) +} + +function isControlEscape(ch) { + return ( + ch === LATIN_SMALL_LETTER_F || + ch === LATIN_SMALL_LETTER_N || + ch === LATIN_SMALL_LETTER_R || + ch === LATIN_SMALL_LETTER_T || + ch === LATIN_SMALL_LETTER_V + ) +} + +function isControlLetter(ch) { + return ( + (ch >= LATIN_CAPITAL_LETTER_A && ch <= LATIN_CAPITAL_LETTER_Z) || + (ch >= LATIN_SMALL_LETTER_A && ch <= LATIN_SMALL_LETTER_Z) + ) +} + +function isCharacterClassEscape(ch) { + return ( + ch === LATIN_SMALL_LETTER_D || + ch === LATIN_CAPITAL_LETTER_D || + ch === LATIN_SMALL_LETTER_S || + ch === LATIN_CAPITAL_LETTER_S || + ch === LATIN_SMALL_LETTER_W || + ch === LATIN_CAPITAL_LETTER_W + ) +} + +function isValidUnicode(ch) { + return ch >= 0 && ch <= 0x10FFFF +} + +function isDecimalDigit(ch) { + return ch >= DIGIT_ZERO && ch <= DIGIT_NINE +} + +function isHexDigit(ch) { + return ( + (ch >= DIGIT_ZERO && ch <= DIGIT_NINE) || + (ch >= LATIN_CAPITAL_LETTER_A && ch <= LATIN_CAPITAL_LETTER_F) || + (ch >= LATIN_SMALL_LETTER_A && ch <= LATIN_SMALL_LETTER_F) + ) +} + +function isOctalDigit(ch) { + return ch >= DIGIT_ZERO && ch <= DIGIT_SEVEN +} + +export class RegExpValidator { + /** + * Initialize this validator. + * @param {Parser} parser The parser. + */ + constructor(parser) { + this.parser = parser + this.ecmaVersion = parser.options.ecmaVersion + this.validFlags = `gim${this.ecmaVersion >= 6 ? "uy" : ""}${this.ecmaVersion >= 9 ? "s" : ""}` + this.pattern = "" + this.start = 0 + this.pos = 0 + this.numCapturingParens = 0 + this.maxBackReference = 0 + } + + /** + * Validate the flags part of a given RegExpLiteral. + * + * @param {number} start The index of the start location of the RegExp literal. + * @param {string} flags The flags part of the RegExpLiteral. + * @returns {void} + */ + validateFlags(start, flags) { + const validFlags = this.validFlags + for (let i = 0; i < flags.length; i++) { + const flag = flags.charAt(i) + if (validFlags.indexOf(flag) == -1) { + this.parser.raise(start, "Invalid regular expression flag") + } + if (flags.indexOf(flag, i + 1) > -1) { + this.parser.raise(start, "Duplicate regular expression flag") + } + } + } + + /** + * Validate the pattern part of a given RegExpLiteral. + * + * This is syntax: + * https://www.ecma-international.org/ecma-262/8.0/#sec-regular-expressions-patterns + * + * @param {number} start The index of the start location of the RegExp literal. + * @param {string} pattern The pattern part of the RegExpLiteral. + * @param {boolean} unicode `true` if the RegExp has `u` flag. + * @returns {void} + */ + validatePattern(start, pattern, unicode) { + this.start = start | 0 + this.pattern = pattern + "" + this.pos = 0 + this.numCapturingParens = 0 + this.maxBackReference = 0 + + this.disjunction(unicode) + if (this.pos !== this.pattern.length) { + // Make the same messages as V8. + if (this.eat(RIGHT_PARENTHESIS)) { + this.raise("Unmatched ')'") + } + if (this.eat(RIGHT_SQUARE_BRACKET) || this.eat(RIGHT_CURLY_BRACKET)) { + this.raise("Lone quantifier brackets") + } + } + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (this.maxBackReference > this.numCapturingParens) { + this.raise("Invalid escape") + } + } + + raise(message) { + this.parser.raise(this.start, `Invalid regular expression: /${this.pattern}/: ${message}`) + } + + // Node.js 0.12/0.10 don't support String.prototype.codePointAt(). + codePointAt(i) { + const s = this.pattern + const l = s.length + if (i >= l) { + return -1 + } + const c = s.charCodeAt(i) + if (c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return c + } + return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 + } + + nextIndex(i) { + const s = this.pattern + const l = s.length + if (i >= l) { + return l + } + const c = s.charCodeAt(i) + if (c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return i + 1 + } + return i + 2 + } + + current() { + return this.codePointAt(this.pos) + } + + lookahead() { + return this.codePointAt(this.nextIndex(this.pos)) + } + + advance() { + this.pos = this.nextIndex(this.pos) + } + + eat(ch) { + if (this.codePointAt(this.pos) === ch) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction + disjunction(unicode) { + this.alternative(unicode) + while (this.eat(VERTICAL_LINE)) { + this.alternative(unicode) + } + + // Make the same message as V8. + if (this.eatQuantifier(unicode, true)) { + this.raise("Nothing to repeat") + } + if (this.eat(LEFT_CURLY_BRACKET)) { + this.raise("Lone quantifier brackets") + } + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative + alternative(unicode) { + while (this.pos < this.pattern.length && this.eatTerm(unicode)) + ; + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term + eatTerm(unicode) { + const start = this.pos + + if (this.eatQuantifiableAssertion()) { + if (this.eatQuantifier(unicode)) { + // Make the same message as V8. + if (unicode) { + this.raise("Invalid quantifier") + } + return true + } + this.pos = start + } + + if (this.eatAssertion(unicode)) { + return true + } + + if (unicode ? this.eatAtom(true) : this.eatExtendedAtom()) { + this.eatQuantifier(unicode) + return true + } + + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion + eatAssertion(unicode) { + return ( + this.eat(CIRCUMFLEX_ACCENT) || + this.eat(DOLLAR_SIGN) || + this._eatWordBoundary() || + this._eatLookaheadAssertion(unicode) + ) + } + _eatWordBoundary() { + const start = this.pos + if (this.eat(REVERSE_SOLIDUS)) { + if (this.eat(LATIN_CAPITAL_LETTER_B) || this.eat(LATIN_SMALL_LETTER_B)) { + return true + } + this.pos = start + } + return false + } + _eatLookaheadAssertion(unicode) { + const start = this.pos + if (this.eat(LEFT_PARENTHESIS)) { + if (this.eat(QUESTION_MARK) && (this.eat(EQUALS_SIGN) || this.eat(EXCLAMATION_MARK))) { + this.disjunction(unicode) + if (!this.eat(RIGHT_PARENTHESIS)) { + this.raise("Unterminated group") + } + return true + } + this.pos = start + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-QuantifiableAssertion + eatQuantifiableAssertion() { + return this._eatLookaheadAssertion(false) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier + eatQuantifier(unicode, noError = false) { + if (this.eatQuantifierPrefix(unicode, noError)) { + this.eat(QUESTION_MARK) + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix + eatQuantifierPrefix(unicode, noError) { + return ( + this.eat(ASTERISK) || + this.eat(PLUS_SIGN) || + this.eat(QUESTION_MARK) || + this._eatBracedQuantifier(unicode, noError) + ) + } + _eatBracedQuantifier(unicode, noError) { + const start = this.pos + if (this.eat(LEFT_CURLY_BRACKET)) { + let i = this.pos, min = 0, max = -1 + if (this.eatDecimalDigits()) { + min = this._parseDecimalInt(i, this.pos) + if (this.eat(COMMA)) { + i = this.pos + if (this.eatDecimalDigits()) { + max = this._parseDecimalInt(i, this.pos) + } + } + if (this.eat(RIGHT_CURLY_BRACKET)) { + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term + if (max !== -1 && max < min && !noError) { + this.raise("numbers out of order in {} quantifier") + } + return true + } + } + if (unicode && !noError) { + this.raise("Incomplete quantifier") + } + this.pos = start + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom + eatAtom(unicode) { + return ( + this.eatPatternCharacters() || + this.eat(FULL_STOP) || + this._eatReverseSolidusAtomEscape(unicode) || + this.eatCharacterClass(unicode) || + this._eatCapturingOrUncapturingGroup(unicode) + ) + } + _eatReverseSolidusAtomEscape(unicode) { + const start = this.pos + if (this.eat(REVERSE_SOLIDUS)) { + if (this.eatAtomEscape(unicode)) { + return true + } + this.pos = start + } + return false + } + _eatCapturingOrUncapturingGroup(unicode) { + if (this.eat(LEFT_PARENTHESIS)) { + const uncaptured = this.eat(QUESTION_MARK) + if (uncaptured && !this.eat(COLON)) { + this.raise("Invalid group") + } + this.disjunction(unicode) + if (!this.eat(RIGHT_PARENTHESIS)) { + this.raise("Unterminated group") + } + if (!uncaptured) { + this.numCapturingParens += 1 + } + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom + eatExtendedAtom() { + return ( + this.eat(FULL_STOP) || + this._eatReverseSolidusAtomEscape(false) || + this.eatCharacterClass(false) || + this._eatCapturingOrUncapturingGroup(false) || + this.eatInvalidBracedQuantifier() || + this.eatExtendedPatternCharacter() + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier + eatInvalidBracedQuantifier() { + if (this._eatBracedQuantifier(false, true)) { + this.raise("Nothing to repeat") + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter + eatSyntaxCharacter() { + if (isSyntaxCharacter(this.current())) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter + // But eat eager. + eatPatternCharacters() { + const start = this.pos + let ch = 0 + while ((ch = this.current()) !== -1 && !isSyntaxCharacter(ch)) { + this.advance() + } + return this.pos !== start + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter + eatExtendedPatternCharacter() { + const ch = this.current() + if ( + ch !== -1 && + ch !== CIRCUMFLEX_ACCENT && + ch !== DOLLAR_SIGN && + ch !== FULL_STOP && + ch !== ASTERISK && + ch !== PLUS_SIGN && + ch !== QUESTION_MARK && + ch !== LEFT_PARENTHESIS && + ch !== RIGHT_PARENTHESIS && + ch !== LEFT_SQUARE_BRACKET && + ch !== VERTICAL_LINE + ) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape + eatAtomEscape(unicode) { + const start = this.pos + if (this.eatDecimalEscape()) { + const n = this._parseDecimalInt(start, this.pos) + if (unicode) { + // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (n > this.maxBackReference) { + this.maxBackReference = n + } + return true + } + if (n <= this.numCapturingParens) { + return true + } + this.pos = start + } + if (this.eatCharacterClassEscape(unicode) || this.eatCharacterEscape(unicode)) { + return true + } + if (unicode) { + // Make the same message as V8. + if (this.current() === LATIN_SMALL_LETTER_C) { + this.raise("Invalid unicode escape") + } + this.raise("Invalid escape") + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape + eatCharacterEscape(unicode) { + return ( + this.eatControlEscape() || + this._eatCControlLetter() || + this._eatZero() || + this.eatHexEscapeSequence(unicode) || + this.eatRegExpUnicodeEscapeSequence(unicode) || + (!unicode && this.eatLegacyOctalEscapeSequence()) || + this.eatIdentityEscape(unicode) + ) + } + _eatCControlLetter() { + const start = this.pos + if (this.eat(LATIN_SMALL_LETTER_C)) { + if (this.eatControlLetter()) { + return true + } + this.pos = start + } + return false + } + _eatZero() { + if (this.current() === DIGIT_ZERO && !isDecimalDigit(this.lookahead())) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape + eatControlEscape() { + if (isControlEscape(this.current())) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter + eatControlLetter() { + if (isControlLetter(this.current())) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence + eatRegExpUnicodeEscapeSequence(unicode) { + const start = this.pos + + if (this.eat(LATIN_SMALL_LETTER_U)) { + if (this._eatFixedHexDigits(4)) { + const code = this._parseHexInt(this.pos - 4, this.pos) + if (unicode && code >= 0xD800 && code <= 0xDBFF) { + const leadSurrogateEnd = this.pos + if (this.eat(REVERSE_SOLIDUS) && this.eat(LATIN_SMALL_LETTER_U) && this._eatFixedHexDigits(4)) { + const codeT = this._parseHexInt(this.pos - 4, this.pos) + if (codeT >= 0xDC00 && codeT <= 0xDFFF) { + return true + } + } + this.pos = leadSurrogateEnd + } + return true + } + if ( + unicode && + this.eat(LEFT_CURLY_BRACKET) && + this.eatHexDigits() && + this.eat(RIGHT_CURLY_BRACKET) && + isValidUnicode(this._parseHexInt(start + 2, this.pos - 1)) + ) { + return true + } + if (unicode) { + this.raise("Invalid unicode escape") + } + this.pos = start + } + + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape + eatIdentityEscape(unicode) { + if (unicode) { + return ( + this.eatSyntaxCharacter() || + this.eat(SOLIDUS) + ) + } + + if (this.current() !== LATIN_SMALL_LETTER_C) { + this.advance() + return true + } + + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape + eatDecimalEscape() { + let ch = this.current() + if (ch >= DIGIT_ONE && ch <= DIGIT_NINE) { + do { + this.advance() + } while ((ch = this.current()) >= DIGIT_ZERO && ch <= DIGIT_NINE) + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape + eatCharacterClassEscape() { + if (isCharacterClassEscape(this.current())) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass + eatCharacterClass(unicode) { + if (this.eat(LEFT_SQUARE_BRACKET)) { + this.eat(CIRCUMFLEX_ACCENT) + this.classRanges(unicode) + if (this.eat(RIGHT_SQUARE_BRACKET)) { + return true + } + // Unreachable since it threw "unterminated regular expression" error before. + this.raise("Unterminated character class") + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash + classRanges(unicode) { + for (; ;) { + const leftStart = this.pos + if (this.eatClassAtom(unicode)) { + const leftEnd = this.pos + if (this.eat(HYPHEN_MINUS)) { + const rightStart = this.pos + if (this.eatClassAtom(unicode)) { + const rightEnd = this.pos + const left = this._parseClassAtom(leftStart, leftEnd, unicode, false) + const right = this._parseClassAtom(rightStart, rightEnd, unicode, true) + if (unicode && (left === -1 || right === -1)) { + this.raise("Invalid character class") + } + if (left !== -1 && right !== -1 && left > right) { + this.raise("Range out of order in character class") + } + } + } + } else { + break + } + } + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash + eatClassAtom(unicode) { + const start = this.pos + + if (this.eat(REVERSE_SOLIDUS)) { + if (this.eatClassEscape(unicode)) { + return true + } + if (unicode) { + // Make the same message as V8. + const ch = this.current() + if (ch === LATIN_SMALL_LETTER_C || isOctalDigit(ch)) { + this.raise("Invalid class escape") + } + this.raise("Invalid escape") + } + this.pos = start + } + + const ch = this.current() + if (ch !== RIGHT_SQUARE_BRACKET) { + this.advance() + return true + } + + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape + eatClassEscape(unicode) { + return ( + this.eat(LATIN_SMALL_LETTER_B) || + (unicode && this.eat(HYPHEN_MINUS)) || + (!unicode && this._eatCClassControlLetter(unicode)) || + this.eatCharacterClassEscape() || + this.eatCharacterEscape(unicode) + ) + } + _eatCClassControlLetter() { + const start = this.pos + if (this.eat(LATIN_SMALL_LETTER_C)) { + if (this.eatClassControlLetter()) { + return true + } + this.pos = start + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter + eatClassControlLetter() { + const ch = this.current() + if (isDecimalDigit(ch) || ch === LOW_LINE) { + this.advance() + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + eatHexEscapeSequence(unicode) { + const start = this.pos + + if (this.eat(LATIN_SMALL_LETTER_X)) { + if (this._eatFixedHexDigits(2)) { + return true + } + if (unicode) { + this.raise("Invalid escape") + } + this.pos = start + } + + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits + eatDecimalDigits() { + const start = this.pos + while (isDecimalDigit(this.current())) { + this.advance() + } + return this.pos !== start + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits + eatHexDigits() { + const start = this.pos + while (isHexDigit(this.current())) { + this.advance() + } + return this.pos !== start + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence + eatLegacyOctalEscapeSequence() { + const ch = this.current() + if (this.eatOctalDigit()) { + if (this.eatOctalDigit() && ch <= DIGIT_THREE) { + this.eatOctalDigit() + } + return true + } + return false + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit + eatOctalDigit() { + if (isOctalDigit(this.current())) { + this.advance() + return true + } + return false + } + + _eatFixedHexDigits(length) { + const start = this.pos + for (let i = 0; i < length; ++i) { + if (!isHexDigit(this.current())) { + this.pos = start + return false + } + this.advance() + } + return true + } + + _parseDecimalInt(start, end) { + return parseInt(this.pattern.slice(start, end), 10) + } + + _parseHexInt(start, end) { + return parseInt(this.pattern.slice(start, end), 16) + } + + _parseOctalInt(start, end) { + return parseInt(this.pattern.slice(start, end), 8) + } + + _parseClassAtom(start, end, unicode, isRight) { + const ch1 = this._getOneElementCharSetAt(start, unicode, isRight) + if (ch1 === REVERSE_SOLIDUS) { + const ch2 = this._getOneElementCharSetAt(start + 1, unicode, isRight) + switch (ch2) { + case LATIN_SMALL_LETTER_B: + return BACKSPACE + + // CharacterClassEscape + case LATIN_SMALL_LETTER_D: + case LATIN_CAPITAL_LETTER_D: + case LATIN_SMALL_LETTER_S: + case LATIN_CAPITAL_LETTER_S: + case LATIN_SMALL_LETTER_W: + case LATIN_CAPITAL_LETTER_W: + return -1 // Those are not single character. + + // CharacterEscape + case LATIN_SMALL_LETTER_T: + return CHARACTER_TABULATION + case LATIN_SMALL_LETTER_N: + return LINE_FEED + case LATIN_SMALL_LETTER_V: + return LINE_TABULATION + case LATIN_SMALL_LETTER_F: + return FORM_FEED + case LATIN_SMALL_LETTER_R: + return CARRIAGE_RETURN + case LATIN_SMALL_LETTER_C: + if (end - start === 3) { + return this.codePointAt(start + 2) % 32 + } + return LATIN_SMALL_LETTER_C + case LATIN_SMALL_LETTER_X: + if (end - start === 4) { + return this._parseHexInt(start + 2, end) + } + return LATIN_SMALL_LETTER_X + case LATIN_SMALL_LETTER_U: + if (end - start >= 5 && this.codePointAt(start + 2) === LEFT_CURLY_BRACKET) { + return this._parseHexInt(start + 3, end - 1) + } + if (end - start === 6) { + return this._parseHexInt(start + 2, end) + } + if (end - start === 12) { + const lead = this._parseHexInt(start + 2, start + 6) + const trail = this._parseHexInt(start + 10, start + 12) + return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000 + } + return LATIN_SMALL_LETTER_U + default: + if (!unicode && ch2 >= DIGIT_ZERO && ch2 <= DIGIT_SEVEN) { + return this._parseOctalInt(start + 1, end) + } + return ch2 + } + } + return ch1 + } + // https://www.ecma-international.org/ecma-262/8.0/#sec-notation + _getOneElementCharSetAt(i, unicode, isRight) { + const ch = this.codePointAt(i) + if (unicode || ch <= 0xFFFF) { + return ch + } + return this.pattern.charCodeAt(isRight ? i : i + 1) + } +} diff --git a/src/state.js b/src/state.js index b90403f96..583ed7b3f 100644 --- a/src/state.js +++ b/src/state.js @@ -89,6 +89,9 @@ export class Parser { // Scope tracking for duplicate variable names (see scope.js) this.scopeStack = [] this.enterFunctionScope() + + // Lazy initialization + this.regexpValidator = null } // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them diff --git a/src/tokenize.js b/src/tokenize.js index 71dd8403c..ef3302fe7 100644 --- a/src/tokenize.js +++ b/src/tokenize.js @@ -3,6 +3,7 @@ import {types as tt, keywords as keywordTypes} from "./tokentype" import {Parser} from "./state" import {SourceLocation} from "./locutil" import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace" +import {RegExpValidator} from "./regexp" // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only @@ -25,9 +26,6 @@ export class Token { const pp = Parser.prototype -// Are we running under Rhino? -const isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]" - // Move to the next token pp.next = function() { @@ -369,22 +367,6 @@ pp.finishOp = function(type, size) { return this.finishToken(type, str) } -// Parse a regular expression. Some context-awareness is necessary, -// since a '/' inside a '[]' set does not end the expression. - -function tryCreateRegexp(src, flags, throwErrorAt, parser) { - try { - return new RegExp(src, flags) - } catch (e) { - if (throwErrorAt !== undefined) { - if (e instanceof SyntaxError) parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message) - throw e - } - } -} - -const regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u") - pp.readRegexp = function() { let escaped, inClass, start = this.pos for (;;) { @@ -399,55 +381,27 @@ pp.readRegexp = function() { } else escaped = false ++this.pos } - let content = this.input.slice(start, this.pos) + let pattern = this.input.slice(start, this.pos) ++this.pos let flagsStart = this.pos - let mods = this.readWord1() + let flags = this.readWord1() if (this.containsEsc) this.unexpected(flagsStart) - let tmp = content, tmpFlags = "" - if (mods) { - let validFlags = "gim" - if (this.options.ecmaVersion >= 6) validFlags += "uy" - if (this.options.ecmaVersion >= 9) validFlags += "s" - for (let i = 0; i < mods.length; i++) { - let mod = mods.charAt(i) - if (validFlags.indexOf(mod) == -1) this.raise(start, "Invalid regular expression flag") - if (mods.indexOf(mod, i + 1) > -1) this.raise(start, "Duplicate regular expression flag") - } - if (mods.indexOf("u") >= 0) { - if (regexpUnicodeSupport) { - tmpFlags = "u" - } else { - // Replace each astral symbol and every Unicode escape sequence that - // possibly represents an astral symbol or a paired surrogate with a - // single ASCII symbol to avoid throwing on regular expressions that - // are only valid in combination with the `/u` flag. - // Note: replacing with the ASCII symbol `x` might cause false - // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a - // perfectly valid pattern that is equivalent to `[a-b]`, but it would - // be replaced by `[x-b]` which throws an error. - tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, (_match, code, offset) => { - code = Number("0x" + code) - if (code > 0x10FFFF) this.raise(start + offset + 3, "Code point out of bounds") - return "x" - }) - tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x") - tmpFlags = tmpFlags.replace("u", "") - } - } - } - // Detect invalid regular expressions. + // Validate pattern + const validator = this.regexpValidator || (this.regexpValidator = new RegExpValidator(this)) + validator.validateFlags(start, flags) + validator.validatePattern(start, pattern, flags.indexOf("u") !== -1) + + // Create Literal#value property value. let value = null - // Rhino's regular expression parser is flaky and throws uncatchable exceptions, - // so don't do detection if we are running under Rhino - if (!isRhino) { - tryCreateRegexp(tmp, tmpFlags, start, this) - // Get a regular expression object for this pattern-flag pair, or `null` in - // case the current environment doesn't support the flags it uses. - value = tryCreateRegexp(content, mods) + try { + value = new RegExp(pattern, flags) + } catch (e) { + // ESTree requires null if it failed to instantiate RegExp object. + // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral } - return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value}) + + return this.finishToken(tt.regexp, {pattern, flags, value}) } // Read an integer in the given radix. Return null if zero digits diff --git a/test/run.js b/test/run.js index 91ad384c7..3a94d85ea 100644 --- a/test/run.js +++ b/test/run.js @@ -12,6 +12,7 @@ require("./tests-directive.js"); require("./tests-rest-spread-properties.js"); require("./tests-async-iteration.js"); + require("./tests-regexp.js"); acorn = require("../dist/acorn") require("../dist/acorn_loose") } else { diff --git a/test/tests-regexp.js b/test/tests-regexp.js new file mode 100644 index 000000000..6b9b2656d --- /dev/null +++ b/test/tests-regexp.js @@ -0,0 +1,1347 @@ +if (typeof exports != "undefined") { + var test = require("./driver.js").test + var testFail = require("./driver.js").testFail +} + +test("/foo/", {}, { ecmaVersion: 5 }) +test("/foo/", {}, { ecmaVersion: 2015 }) +testFail("/foo/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/foo/u", {}, { ecmaVersion: 2015 }) +test("/foo|bar/", {}, { ecmaVersion: 5 }) +test("/foo|bar/", {}, { ecmaVersion: 2015 }) +testFail("/foo|bar/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/foo|bar/u", {}, { ecmaVersion: 2015 }) +test("/||||/", {}, { ecmaVersion: 5 }) +test("/||||/", {}, { ecmaVersion: 2015 }) +testFail("/||||/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/||||/u", {}, { ecmaVersion: 2015 }) +test("/^|$|\\b|\\B/", {}, { ecmaVersion: 5 }) +test("/^|$|\\b|\\B/", {}, { ecmaVersion: 2015 }) +testFail("/^|$|\\b|\\B/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^|$|\\b|\\B/u", {}, { ecmaVersion: 2015 }) +testFail("/(/", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(/", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(/u", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?/", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 5 }) +testFail("/(?/", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?/u", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?=/", "Invalid regular expression: /(?=/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?=/", "Invalid regular expression: /(?=/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?=/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=/u", "Invalid regular expression: /(?=/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?=)/", {}, { ecmaVersion: 5 }) +test("/(?=)/", {}, { ecmaVersion: 2015 }) +testFail("/(?=)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(?=)/u", {}, { ecmaVersion: 2015 }) +testFail("/(?=foo/", "Invalid regular expression: /(?=foo/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?=foo/", "Invalid regular expression: /(?=foo/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?=foo/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=foo/u", "Invalid regular expression: /(?=foo/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?=foo)/", {}, { ecmaVersion: 5 }) +test("/(?=foo)/", {}, { ecmaVersion: 2015 }) +testFail("/(?=foo)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(?=foo)/u", {}, { ecmaVersion: 2015 }) +testFail("/(?!/", "Invalid regular expression: /(?!/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?!/", "Invalid regular expression: /(?!/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?!/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?!/u", "Invalid regular expression: /(?!/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?!)/", {}, { ecmaVersion: 5 }) +test("/(?!)/", {}, { ecmaVersion: 2015 }) +testFail("/(?!)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(?!)/u", {}, { ecmaVersion: 2015 }) +testFail("/(?!foo/", "Invalid regular expression: /(?!foo/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?!foo/", "Invalid regular expression: /(?!foo/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?!foo/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?!foo/u", "Invalid regular expression: /(?!foo/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?!foo)/", {}, { ecmaVersion: 5 }) +test("/(?!foo)/", {}, { ecmaVersion: 2015 }) +testFail("/(?!foo)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(?!foo)/u", {}, { ecmaVersion: 2015 }) +test("/(?=a)*/", {}, { ecmaVersion: 5 }) +test("/(?=a)*/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a)*/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a)*/u", "Invalid regular expression: /(?=a)*/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a)+/", {}, { ecmaVersion: 5 }) +test("/(?=a)+/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a)+/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a)+/u", "Invalid regular expression: /(?=a)+/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a)?/", {}, { ecmaVersion: 5 }) +test("/(?=a)?/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a)?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a)?/u", "Invalid regular expression: /(?=a)?/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){/", {}, { ecmaVersion: 5 }) +test("/(?=a){/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){/u", "Invalid regular expression: /(?=a){/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){}/", {}, { ecmaVersion: 5 }) +test("/(?=a){}/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){}/u", "Invalid regular expression: /(?=a){}/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){a}/", {}, { ecmaVersion: 5 }) +test("/(?=a){a}/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){a}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){a}/u", "Invalid regular expression: /(?=a){a}/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){1}/", {}, { ecmaVersion: 5 }) +test("/(?=a){1}/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){1}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){1}/u", "Invalid regular expression: /(?=a){1}/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){1,}/", {}, { ecmaVersion: 5 }) +test("/(?=a){1,}/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){1,}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){1,}/u", "Invalid regular expression: /(?=a){1,}/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/(?=a){1,2}/", {}, { ecmaVersion: 5 }) +test("/(?=a){1,2}/", {}, { ecmaVersion: 2015 }) +testFail("/(?=a){1,2}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?=a){1,2}/u", "Invalid regular expression: /(?=a){1,2}/: Invalid quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a*/", {}, { ecmaVersion: 5 }) +test("/a*/", {}, { ecmaVersion: 2015 }) +testFail("/a*/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a*/u", {}, { ecmaVersion: 2015 }) +test("/a+/", {}, { ecmaVersion: 5 }) +test("/a+/", {}, { ecmaVersion: 2015 }) +testFail("/a+/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a+/u", {}, { ecmaVersion: 2015 }) +test("/a?/", {}, { ecmaVersion: 5 }) +test("/a?/", {}, { ecmaVersion: 2015 }) +testFail("/a?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a?/u", {}, { ecmaVersion: 2015 }) +test("/a{/", {}, { ecmaVersion: 5 }) +test("/a{/", {}, { ecmaVersion: 2015 }) +testFail("/a{/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{/u", "Invalid regular expression: /a{/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{}/", {}, { ecmaVersion: 5 }) +test("/a{}/", {}, { ecmaVersion: 2015 }) +testFail("/a{}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{}/u", "Invalid regular expression: /a{}/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{a}/", {}, { ecmaVersion: 5 }) +test("/a{a}/", {}, { ecmaVersion: 2015 }) +testFail("/a{a}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{a}/u", "Invalid regular expression: /a{a}/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1}/", {}, { ecmaVersion: 5 }) +test("/a{1}/", {}, { ecmaVersion: 2015 }) +testFail("/a{1}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1}/u", {}, { ecmaVersion: 2015 }) +test("/a{1/", {}, { ecmaVersion: 5 }) +test("/a{1/", {}, { ecmaVersion: 2015 }) +testFail("/a{1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1/u", "Invalid regular expression: /a{1/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1,}/", {}, { ecmaVersion: 5 }) +test("/a{1,}/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1,}/u", {}, { ecmaVersion: 2015 }) +test("/a{1,/", {}, { ecmaVersion: 5 }) +test("/a{1,/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1,/u", "Invalid regular expression: /a{1,/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1,2}/", {}, { ecmaVersion: 5 }) +test("/a{1,2}/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,2}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1,2}/u", {}, { ecmaVersion: 2015 }) +test("/a{1,2/", {}, { ecmaVersion: 5 }) +test("/a{1,2/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,2/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1,2/u", "Invalid regular expression: /a{1,2/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/a{2,1}/", "Invalid regular expression: /a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1}/", "Invalid regular expression: /a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/a{2,1}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1}/u", "Invalid regular expression: /a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{2,1/", {}, { ecmaVersion: 5 }) +test("/a{2,1/", {}, { ecmaVersion: 2015 }) +testFail("/a{2,1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1/u", "Invalid regular expression: /a{2,1/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/(a{2,1}/", "Invalid regular expression: /(a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 5 }) +testFail("/(a{2,1}/", "Invalid regular expression: /(a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/(a{2,1}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(a{2,1}/u", "Invalid regular expression: /(a{2,1}/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a*?/", {}, { ecmaVersion: 5 }) +test("/a*?/", {}, { ecmaVersion: 2015 }) +testFail("/a*?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a*?/u", {}, { ecmaVersion: 2015 }) +test("/a+?/", {}, { ecmaVersion: 5 }) +test("/a+?/", {}, { ecmaVersion: 2015 }) +testFail("/a+?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a+?/u", {}, { ecmaVersion: 2015 }) +test("/a??/", {}, { ecmaVersion: 5 }) +test("/a??/", {}, { ecmaVersion: 2015 }) +testFail("/a??/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a??/u", {}, { ecmaVersion: 2015 }) +test("/a{?/", {}, { ecmaVersion: 5 }) +test("/a{?/", {}, { ecmaVersion: 2015 }) +testFail("/a{?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{?/u", "Invalid regular expression: /a{?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{}?/", {}, { ecmaVersion: 5 }) +test("/a{}?/", {}, { ecmaVersion: 2015 }) +testFail("/a{}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{}?/u", "Invalid regular expression: /a{}?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{a}?/", {}, { ecmaVersion: 5 }) +test("/a{a}?/", {}, { ecmaVersion: 2015 }) +testFail("/a{a}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{a}?/u", "Invalid regular expression: /a{a}?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1}?/", {}, { ecmaVersion: 5 }) +test("/a{1}?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1}?/u", {}, { ecmaVersion: 2015 }) +test("/a{1?/", {}, { ecmaVersion: 5 }) +test("/a{1?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1?/u", "Invalid regular expression: /a{1?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1,}?/", {}, { ecmaVersion: 5 }) +test("/a{1,}?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1,}?/u", {}, { ecmaVersion: 2015 }) +test("/a{1,?/", {}, { ecmaVersion: 5 }) +test("/a{1,?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1,?/u", "Invalid regular expression: /a{1,?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{1,2}?/", {}, { ecmaVersion: 5 }) +test("/a{1,2}?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,2}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/a{1,2}?/u", {}, { ecmaVersion: 2015 }) +test("/a{1,2?/", {}, { ecmaVersion: 5 }) +test("/a{1,2?/", {}, { ecmaVersion: 2015 }) +testFail("/a{1,2?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{1,2?/u", "Invalid regular expression: /a{1,2?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/a{2,1}?/", "Invalid regular expression: /a{2,1}?/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1}?/", "Invalid regular expression: /a{2,1}?/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +testFail("/a{2,1}?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1}?/u", "Invalid regular expression: /a{2,1}?/: numbers out of order in {} quantifier (1:1)", { ecmaVersion: 2015 }) +test("/a{2,1?/", {}, { ecmaVersion: 5 }) +test("/a{2,1?/", {}, { ecmaVersion: 2015 }) +testFail("/a{2,1?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/a{2,1?/u", "Invalid regular expression: /a{2,1?/: Incomplete quantifier (1:1)", { ecmaVersion: 2015 }) +test("/πŸ‘πŸš€β‡οΈ/", {}, { ecmaVersion: 5 }) +test("/πŸ‘πŸš€β‡οΈ/", {}, { ecmaVersion: 2015 }) +testFail("/πŸ‘πŸš€β‡οΈ/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/πŸ‘πŸš€β‡οΈ/u", {}, { ecmaVersion: 2015 }) +test("/^/", {}, { ecmaVersion: 5 }) +test("/^/", {}, { ecmaVersion: 2015 }) +testFail("/^/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^/u", {}, { ecmaVersion: 2015 }) +test("/$/", {}, { ecmaVersion: 5 }) +test("/$/", {}, { ecmaVersion: 2015 }) +testFail("/$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/$/u", {}, { ecmaVersion: 2015 }) +test("/./", {}, { ecmaVersion: 5 }) +test("/./", {}, { ecmaVersion: 2015 }) +testFail("/./u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/./u", {}, { ecmaVersion: 2015 }) +testFail("/(*)/", "Invalid regular expression: /(*)/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/(*)/", "Invalid regular expression: /(*)/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/(*)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(*)/u", "Invalid regular expression: /(*)/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/+/", "Invalid regular expression: /+/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/+/", "Invalid regular expression: /+/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/+/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/+/u", "Invalid regular expression: /+/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/?/", "Invalid regular expression: /?/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/?/", "Invalid regular expression: /?/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/?/u", "Invalid regular expression: /?/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/(/", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(/", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(/u", "Invalid regular expression: /(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/)/", "Invalid regular expression: /)/: Unmatched ')' (1:1)", { ecmaVersion: 5 }) +testFail("/)/", "Invalid regular expression: /)/: Unmatched ')' (1:1)", { ecmaVersion: 2015 }) +testFail("/)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/)/u", "Invalid regular expression: /)/: Unmatched ')' (1:1)", { ecmaVersion: 2015 }) +testFail("/[/", "Unterminated regular expression (1:1)", { ecmaVersion: 5 }) +testFail("/[/", "Unterminated regular expression (1:1)", { ecmaVersion: 2015 }) +testFail("/[/u", "Unterminated regular expression (1:1)", { ecmaVersion: 5 }) +testFail("/[/u", "Unterminated regular expression (1:1)", { ecmaVersion: 2015 }) +test("/]/", {}, { ecmaVersion: 5 }) +test("/]/", {}, { ecmaVersion: 2015 }) +testFail("/]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/]/u", "Invalid regular expression: /]/: Lone quantifier brackets (1:1)", { ecmaVersion: 2015 }) +test("/{/", {}, { ecmaVersion: 5 }) +test("/{/", {}, { ecmaVersion: 2015 }) +testFail("/{/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/{/u", "Invalid regular expression: /{/: Lone quantifier brackets (1:1)", { ecmaVersion: 2015 }) +test("/}/", {}, { ecmaVersion: 5 }) +test("/}/", {}, { ecmaVersion: 2015 }) +testFail("/}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/}/u", "Invalid regular expression: /}/: Lone quantifier brackets (1:1)", { ecmaVersion: 2015 }) +test("/|/", {}, { ecmaVersion: 5 }) +test("/|/", {}, { ecmaVersion: 2015 }) +testFail("/|/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/|/u", {}, { ecmaVersion: 2015 }) +testFail("/^*/", "Invalid regular expression: /^*/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/^*/", "Invalid regular expression: /^*/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/^*/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/^*/u", "Invalid regular expression: /^*/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/$*/", "Invalid regular expression: /$*/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/$*/", "Invalid regular expression: /$*/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/$*/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/$*/u", "Invalid regular expression: /$*/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +test("/${1,2/", {}, { ecmaVersion: 5 }) +test("/${1,2/", {}, { ecmaVersion: 2015 }) +testFail("/${1,2/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/${1,2/u", "Invalid regular expression: /${1,2/: Lone quantifier brackets (1:1)", { ecmaVersion: 2015 }) +testFail("/${1,2}/", "Invalid regular expression: /${1,2}/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/${1,2}/", "Invalid regular expression: /${1,2}/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/${1,2}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/${1,2}/u", "Invalid regular expression: /${1,2}/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/${2,1}/", "Invalid regular expression: /${2,1}/: Nothing to repeat (1:1)", { ecmaVersion: 5 }) +testFail("/${2,1}/", "Invalid regular expression: /${2,1}/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +testFail("/${2,1}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/${2,1}/u", "Invalid regular expression: /${2,1}/: Nothing to repeat (1:1)", { ecmaVersion: 2015 }) +test("/\\1/", {}, { ecmaVersion: 5 }) +test("/\\1/", {}, { ecmaVersion: 2015 }) +testFail("/\\1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\1/u", "Invalid regular expression: /\\1/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/(a)\\1/", {}, { ecmaVersion: 5 }) +test("/(a)\\1/", {}, { ecmaVersion: 2015 }) +testFail("/(a)\\1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(a)\\1/u", {}, { ecmaVersion: 2015 }) +test("/\\1(a)/", {}, { ecmaVersion: 5 }) +test("/\\1(a)/", {}, { ecmaVersion: 2015 }) +testFail("/\\1(a)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\1(a)/u", {}, { ecmaVersion: 2015 }) +testFail("/\\2(a)(/", "Invalid regular expression: /\\2(a)(/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/\\2(a)(/", "Invalid regular expression: /\\2(a)(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/\\2(a)(/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\2(a)(/u", "Invalid regular expression: /\\2(a)(/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?:a)\\1/", {}, { ecmaVersion: 5 }) +test("/(?:a)\\1/", {}, { ecmaVersion: 2015 }) +testFail("/(?:a)\\1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?:a)\\1/u", "Invalid regular expression: /(?:a)\\1/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/(a)\\2/", {}, { ecmaVersion: 5 }) +test("/(a)\\2/", {}, { ecmaVersion: 2015 }) +testFail("/(a)\\2/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(a)\\2/u", "Invalid regular expression: /(a)\\2/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/(?:a)\\2/", {}, { ecmaVersion: 5 }) +test("/(?:a)\\2/", {}, { ecmaVersion: 2015 }) +testFail("/(?:a)\\2/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?:a)\\2/u", "Invalid regular expression: /(?:a)\\2/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\10/", {}, { ecmaVersion: 5 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\10/", {}, { ecmaVersion: 2015 }) +testFail("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\10/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\10/u", {}, { ecmaVersion: 2015 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/", {}, { ecmaVersion: 5 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/", {}, { ecmaVersion: 2015 }) +testFail("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/u", "Invalid regular expression: /(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/", {}, { ecmaVersion: 5 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/", {}, { ecmaVersion: 2015 }) +testFail("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11/u", {}, { ecmaVersion: 2015 }) +testFail("/(?/", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 5 }) +testFail("/(?/", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?/u", "Invalid regular expression: /(?/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?a/", "Invalid regular expression: /(?a/: Invalid group (1:1)", { ecmaVersion: 5 }) +testFail("/(?a/", "Invalid regular expression: /(?a/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?a/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?a/u", "Invalid regular expression: /(?a/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?a)/", "Invalid regular expression: /(?a)/: Invalid group (1:1)", { ecmaVersion: 5 }) +testFail("/(?a)/", "Invalid regular expression: /(?a)/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?a)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?a)/u", "Invalid regular expression: /(?a)/: Invalid group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?:/", "Invalid regular expression: /(?:/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?:/", "Invalid regular expression: /(?:/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?:/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?:/u", "Invalid regular expression: /(?:/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?:a/", "Invalid regular expression: /(?:a/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(?:a/", "Invalid regular expression: /(?:a/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(?:a/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(?:a/u", "Invalid regular expression: /(?:a/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/(?:a)/", {}, { ecmaVersion: 5 }) +test("/(?:a)/", {}, { ecmaVersion: 2015 }) +testFail("/(?:a)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/(?:a)/u", {}, { ecmaVersion: 2015 }) +testFail("/(:a/", "Invalid regular expression: /(:a/: Unterminated group (1:1)", { ecmaVersion: 5 }) +testFail("/(:a/", "Invalid regular expression: /(:a/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +testFail("/(:a/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/(:a/u", "Invalid regular expression: /(:a/: Unterminated group (1:1)", { ecmaVersion: 2015 }) +test("/\\d/", {}, { ecmaVersion: 5 }) +test("/\\d/", {}, { ecmaVersion: 2015 }) +testFail("/\\d/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\d/u", {}, { ecmaVersion: 2015 }) +test("/\\D/", {}, { ecmaVersion: 5 }) +test("/\\D/", {}, { ecmaVersion: 2015 }) +testFail("/\\D/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\D/u", {}, { ecmaVersion: 2015 }) +test("/\\s/", {}, { ecmaVersion: 5 }) +test("/\\s/", {}, { ecmaVersion: 2015 }) +testFail("/\\s/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\s/u", {}, { ecmaVersion: 2015 }) +test("/\\S/", {}, { ecmaVersion: 5 }) +test("/\\S/", {}, { ecmaVersion: 2015 }) +testFail("/\\S/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\S/u", {}, { ecmaVersion: 2015 }) +test("/\\w/", {}, { ecmaVersion: 5 }) +test("/\\w/", {}, { ecmaVersion: 2015 }) +testFail("/\\w/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\w/u", {}, { ecmaVersion: 2015 }) +test("/\\W/", {}, { ecmaVersion: 5 }) +test("/\\W/", {}, { ecmaVersion: 2015 }) +testFail("/\\W/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\W/u", {}, { ecmaVersion: 2015 }) +test("/\\f/", {}, { ecmaVersion: 5 }) +test("/\\f/", {}, { ecmaVersion: 2015 }) +testFail("/\\f/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\f/u", {}, { ecmaVersion: 2015 }) +test("/\\n/", {}, { ecmaVersion: 5 }) +test("/\\n/", {}, { ecmaVersion: 2015 }) +testFail("/\\n/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\n/u", {}, { ecmaVersion: 2015 }) +test("/\\r/", {}, { ecmaVersion: 5 }) +test("/\\r/", {}, { ecmaVersion: 2015 }) +testFail("/\\r/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\r/u", {}, { ecmaVersion: 2015 }) +test("/\\t/", {}, { ecmaVersion: 5 }) +test("/\\t/", {}, { ecmaVersion: 2015 }) +testFail("/\\t/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\t/u", {}, { ecmaVersion: 2015 }) +test("/\\v/", {}, { ecmaVersion: 5 }) +test("/\\v/", {}, { ecmaVersion: 2015 }) +testFail("/\\v/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\v/u", {}, { ecmaVersion: 2015 }) +test("/\\cA/", {}, { ecmaVersion: 5 }) +test("/\\cA/", {}, { ecmaVersion: 2015 }) +testFail("/\\cA/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\cA/u", {}, { ecmaVersion: 2015 }) +test("/\\cz/", {}, { ecmaVersion: 5 }) +test("/\\cz/", {}, { ecmaVersion: 2015 }) +testFail("/\\cz/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\cz/u", {}, { ecmaVersion: 2015 }) +test("/\\c1/", {}, { ecmaVersion: 5 }) +test("/\\c1/", {}, { ecmaVersion: 2015 }) +testFail("/\\c1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\c1/u", "Invalid regular expression: /\\c1/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\c/", {}, { ecmaVersion: 5 }) +test("/\\c/", {}, { ecmaVersion: 2015 }) +testFail("/\\c/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\c/u", "Invalid regular expression: /\\c/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\0/", {}, { ecmaVersion: 5 }) +test("/\\0/", {}, { ecmaVersion: 2015 }) +testFail("/\\0/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\0/u", {}, { ecmaVersion: 2015 }) +test("/\\u/", {}, { ecmaVersion: 5 }) +test("/\\u/", {}, { ecmaVersion: 2015 }) +testFail("/\\u/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u/u", "Invalid regular expression: /\\u/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u1/", {}, { ecmaVersion: 5 }) +test("/\\u1/", {}, { ecmaVersion: 2015 }) +testFail("/\\u1/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u1/u", "Invalid regular expression: /\\u1/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u12/", {}, { ecmaVersion: 5 }) +test("/\\u12/", {}, { ecmaVersion: 2015 }) +testFail("/\\u12/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u12/u", "Invalid regular expression: /\\u12/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u123/", {}, { ecmaVersion: 5 }) +test("/\\u123/", {}, { ecmaVersion: 2015 }) +testFail("/\\u123/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u123/u", "Invalid regular expression: /\\u123/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u1234/", {}, { ecmaVersion: 5 }) +test("/\\u1234/", {}, { ecmaVersion: 2015 }) +testFail("/\\u1234/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u1234/u", {}, { ecmaVersion: 2015 }) +test("/\\u12345/", {}, { ecmaVersion: 5 }) +test("/\\u12345/", {}, { ecmaVersion: 2015 }) +testFail("/\\u12345/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u12345/u", {}, { ecmaVersion: 2015 }) +test("/\\u{/", {}, { ecmaVersion: 5 }) +test("/\\u{/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u{/u", "Invalid regular expression: /\\u{/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u{z/", {}, { ecmaVersion: 5 }) +test("/\\u{z/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{z/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u{z/u", "Invalid regular expression: /\\u{z/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u{a}/", {}, { ecmaVersion: 5 }) +test("/\\u{a}/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{a}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u{a}/u", {}, { ecmaVersion: 2015 }) +test("/\\u{20/", {}, { ecmaVersion: 5 }) +test("/\\u{20/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{20/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u{20/u", "Invalid regular expression: /\\u{20/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u{20}/", {}, { ecmaVersion: 5 }) +test("/\\u{20}/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{20}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u{20}/u", {}, { ecmaVersion: 2015 }) +test("/\\u{10FFFF}/", {}, { ecmaVersion: 5 }) +test("/\\u{10FFFF}/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{10FFFF}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u{10FFFF}/u", {}, { ecmaVersion: 2015 }) +test("/\\u{110000}/", {}, { ecmaVersion: 5 }) +test("/\\u{110000}/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{110000}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\u{110000}/u", "Invalid regular expression: /\\u{110000}/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/\\u{00000001}/", {}, { ecmaVersion: 5 }) +test("/\\u{00000001}/", {}, { ecmaVersion: 2015 }) +testFail("/\\u{00000001}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\u{00000001}/u", {}, { ecmaVersion: 2015 }) +test("/\\377/", {}, { ecmaVersion: 5 }) +test("/\\377/", {}, { ecmaVersion: 2015 }) +testFail("/\\377/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\377/u", "Invalid regular expression: /\\377/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/\\400/", {}, { ecmaVersion: 5 }) +test("/\\400/", {}, { ecmaVersion: 2015 }) +testFail("/\\400/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\400/u", "Invalid regular expression: /\\400/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/\\^/", {}, { ecmaVersion: 5 }) +test("/\\^/", {}, { ecmaVersion: 2015 }) +testFail("/\\^/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\^/u", {}, { ecmaVersion: 2015 }) +test("/\\$/", {}, { ecmaVersion: 5 }) +test("/\\$/", {}, { ecmaVersion: 2015 }) +testFail("/\\$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\$/u", {}, { ecmaVersion: 2015 }) +test("/\\./", {}, { ecmaVersion: 5 }) +test("/\\./", {}, { ecmaVersion: 2015 }) +testFail("/\\./u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\./u", {}, { ecmaVersion: 2015 }) +test("/\\+/", {}, { ecmaVersion: 5 }) +test("/\\+/", {}, { ecmaVersion: 2015 }) +testFail("/\\+/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\+/u", {}, { ecmaVersion: 2015 }) +test("/\\?/", {}, { ecmaVersion: 5 }) +test("/\\?/", {}, { ecmaVersion: 2015 }) +testFail("/\\?/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\?/u", {}, { ecmaVersion: 2015 }) +test("/\\(/", {}, { ecmaVersion: 5 }) +test("/\\(/", {}, { ecmaVersion: 2015 }) +testFail("/\\(/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\(/u", {}, { ecmaVersion: 2015 }) +test("/\\)/", {}, { ecmaVersion: 5 }) +test("/\\)/", {}, { ecmaVersion: 2015 }) +testFail("/\\)/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\)/u", {}, { ecmaVersion: 2015 }) +test("/\\[/", {}, { ecmaVersion: 5 }) +test("/\\[/", {}, { ecmaVersion: 2015 }) +testFail("/\\[/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\[/u", {}, { ecmaVersion: 2015 }) +test("/\\]/", {}, { ecmaVersion: 5 }) +test("/\\]/", {}, { ecmaVersion: 2015 }) +testFail("/\\]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\]/u", {}, { ecmaVersion: 2015 }) +test("/\\{/", {}, { ecmaVersion: 5 }) +test("/\\{/", {}, { ecmaVersion: 2015 }) +testFail("/\\{/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\{/u", {}, { ecmaVersion: 2015 }) +test("/\\}/", {}, { ecmaVersion: 5 }) +test("/\\}/", {}, { ecmaVersion: 2015 }) +testFail("/\\}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\}/u", {}, { ecmaVersion: 2015 }) +test("/\\|/", {}, { ecmaVersion: 5 }) +test("/\\|/", {}, { ecmaVersion: 2015 }) +testFail("/\\|/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\|/u", {}, { ecmaVersion: 2015 }) +test("/\\//", {}, { ecmaVersion: 5 }) +test("/\\//", {}, { ecmaVersion: 2015 }) +testFail("/\\//u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\//u", {}, { ecmaVersion: 2015 }) +test("/\\a/", {}, { ecmaVersion: 5 }) +test("/\\a/", {}, { ecmaVersion: 2015 }) +testFail("/\\a/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/\\a/u", "Invalid regular expression: /\\a/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/\\s/", {}, { ecmaVersion: 5 }) +test("/\\s/", {}, { ecmaVersion: 2015 }) +testFail("/\\s/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/\\s/u", {}, { ecmaVersion: 2015 }) +test("/[]/", {}, { ecmaVersion: 5 }) +test("/[]/", {}, { ecmaVersion: 2015 }) +testFail("/[]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[]/u", {}, { ecmaVersion: 2015 }) +test("/[^-a-b-]/", {}, { ecmaVersion: 5 }) +test("/[^-a-b-]/", {}, { ecmaVersion: 2015 }) +testFail("/[^-a-b-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[^-a-b-]/u", {}, { ecmaVersion: 2015 }) +test("/[-]/", {}, { ecmaVersion: 5 }) +test("/[-]/", {}, { ecmaVersion: 2015 }) +testFail("/[-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[-]/u", {}, { ecmaVersion: 2015 }) +test("/[a]/", {}, { ecmaVersion: 5 }) +test("/[a]/", {}, { ecmaVersion: 2015 }) +testFail("/[a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[a]/u", {}, { ecmaVersion: 2015 }) +test("/[--]/", {}, { ecmaVersion: 5 }) +test("/[--]/", {}, { ecmaVersion: 2015 }) +testFail("/[--]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[--]/u", {}, { ecmaVersion: 2015 }) +test("/[-a]/", {}, { ecmaVersion: 5 }) +test("/[-a]/", {}, { ecmaVersion: 2015 }) +testFail("/[-a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[-a]/u", {}, { ecmaVersion: 2015 }) +test("/[-a-]/", {}, { ecmaVersion: 5 }) +test("/[-a-]/", {}, { ecmaVersion: 2015 }) +testFail("/[-a-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[-a-]/u", {}, { ecmaVersion: 2015 }) +test("/[a-]/", {}, { ecmaVersion: 5 }) +test("/[a-]/", {}, { ecmaVersion: 2015 }) +testFail("/[a-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[a-]/u", {}, { ecmaVersion: 2015 }) +test("/[a-b]/", {}, { ecmaVersion: 5 }) +test("/[a-b]/", {}, { ecmaVersion: 2015 }) +testFail("/[a-b]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[a-b]/u", {}, { ecmaVersion: 2015 }) +test("/[-a-b-]/", {}, { ecmaVersion: 5 }) +test("/[-a-b-]/", {}, { ecmaVersion: 2015 }) +testFail("/[-a-b-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[-a-b-]/u", {}, { ecmaVersion: 2015 }) +test("/[---]/", {}, { ecmaVersion: 5 }) +test("/[---]/", {}, { ecmaVersion: 2015 }) +testFail("/[---]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[---]/u", {}, { ecmaVersion: 2015 }) +testFail("/[b-a]/", "Invalid regular expression: /[b-a]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[b-a]/", "Invalid regular expression: /[b-a]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[b-a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[b-a]/u", "Invalid regular expression: /[b-a]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +test("/[a-b--/]/", {}, { ecmaVersion: 5 }) +test("/[a-b--/]/", {}, { ecmaVersion: 2015 }) +testFail("/[a-b--/]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[a-b--/]/u", {}, { ecmaVersion: 2015 }) +testFail("/[a-b--+]/", "Invalid regular expression: /[a-b--+]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[a-b--+]/", "Invalid regular expression: /[a-b--+]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[a-b--+]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[a-b--+]/u", "Invalid regular expression: /[a-b--+]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\b-\\n]/", {}, { ecmaVersion: 5 }) +test("/[\\b-\\n]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\b-\\n]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\b-\\n]/u", {}, { ecmaVersion: 2015 }) +test("/[b\\-a]/", {}, { ecmaVersion: 5 }) +test("/[b\\-a]/", {}, { ecmaVersion: 2015 }) +testFail("/[b\\-a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[b\\-a]/u", {}, { ecmaVersion: 2015 }) +test("/[\\d]/", {}, { ecmaVersion: 5 }) +test("/[\\d]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\d]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\d]/u", {}, { ecmaVersion: 2015 }) +test("/[\\D]/", {}, { ecmaVersion: 5 }) +test("/[\\D]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\D]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\D]/u", {}, { ecmaVersion: 2015 }) +test("/[\\s]/", {}, { ecmaVersion: 5 }) +test("/[\\s]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\s]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\s]/u", {}, { ecmaVersion: 2015 }) +test("/[\\S]/", {}, { ecmaVersion: 5 }) +test("/[\\S]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\S]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\S]/u", {}, { ecmaVersion: 2015 }) +test("/[\\w]/", {}, { ecmaVersion: 5 }) +test("/[\\w]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\w]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\w]/u", {}, { ecmaVersion: 2015 }) +test("/[\\W]/", {}, { ecmaVersion: 5 }) +test("/[\\W]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\W]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\W]/u", {}, { ecmaVersion: 2015 }) +test("/[\\d]/", {}, { ecmaVersion: 5 }) +test("/[\\d]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\d]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\d]/u", {}, { ecmaVersion: 2015 }) +test("/[\\D]/", {}, { ecmaVersion: 5 }) +test("/[\\D]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\D]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\D]/u", {}, { ecmaVersion: 2015 }) +test("/[\\s]/", {}, { ecmaVersion: 5 }) +test("/[\\s]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\s]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\s]/u", {}, { ecmaVersion: 2015 }) +test("/[\\S]/", {}, { ecmaVersion: 5 }) +test("/[\\S]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\S]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\S]/u", {}, { ecmaVersion: 2015 }) +test("/[\\w]/", {}, { ecmaVersion: 5 }) +test("/[\\w]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\w]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\w]/u", {}, { ecmaVersion: 2015 }) +test("/[\\W]/", {}, { ecmaVersion: 5 }) +test("/[\\W]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\W]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\W]/u", {}, { ecmaVersion: 2015 }) +test("/[\\f]/", {}, { ecmaVersion: 5 }) +test("/[\\f]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\f]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\f]/u", {}, { ecmaVersion: 2015 }) +test("/[\\n]/", {}, { ecmaVersion: 5 }) +test("/[\\n]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\n]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\n]/u", {}, { ecmaVersion: 2015 }) +test("/[\\r]/", {}, { ecmaVersion: 5 }) +test("/[\\r]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\r]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\r]/u", {}, { ecmaVersion: 2015 }) +test("/[\\t]/", {}, { ecmaVersion: 5 }) +test("/[\\t]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\t]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\t]/u", {}, { ecmaVersion: 2015 }) +test("/[\\v]/", {}, { ecmaVersion: 5 }) +test("/[\\v]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\v]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\v]/u", {}, { ecmaVersion: 2015 }) +test("/[\\cA]/", {}, { ecmaVersion: 5 }) +test("/[\\cA]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\cA]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\cA]/u", {}, { ecmaVersion: 2015 }) +test("/[\\cz]/", {}, { ecmaVersion: 5 }) +test("/[\\cz]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\cz]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\cz]/u", {}, { ecmaVersion: 2015 }) +test("/[\\c1]/", {}, { ecmaVersion: 5 }) +test("/[\\c1]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\c1]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c1]/u", "Invalid regular expression: /[\\c1]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\c]/", {}, { ecmaVersion: 5 }) +test("/[\\c]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\c]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c]/u", "Invalid regular expression: /[\\c]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\0]/", {}, { ecmaVersion: 5 }) +test("/[\\0]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\0]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\0]/u", {}, { ecmaVersion: 2015 }) +test("/[\\x]/", {}, { ecmaVersion: 5 }) +test("/[\\x]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\x]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\x]/u", "Invalid regular expression: /[\\x]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\xz]/", {}, { ecmaVersion: 5 }) +test("/[\\xz]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\xz]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\xz]/u", "Invalid regular expression: /[\\xz]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\x1]/", {}, { ecmaVersion: 5 }) +test("/[\\x1]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\x1]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\x1]/u", "Invalid regular expression: /[\\x1]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\x12]/", {}, { ecmaVersion: 5 }) +test("/[\\x12]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\x12]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\x12]/u", {}, { ecmaVersion: 2015 }) +test("/[\\x123]/", {}, { ecmaVersion: 5 }) +test("/[\\x123]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\x123]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\x123]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u]/", {}, { ecmaVersion: 5 }) +test("/[\\u]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u]/u", "Invalid regular expression: /[\\u]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u1]/", {}, { ecmaVersion: 5 }) +test("/[\\u1]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u1]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u1]/u", "Invalid regular expression: /[\\u1]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u12]/", {}, { ecmaVersion: 5 }) +test("/[\\u12]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u12]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u12]/u", "Invalid regular expression: /[\\u12]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u123]/", {}, { ecmaVersion: 5 }) +test("/[\\u123]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u123]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u123]/u", "Invalid regular expression: /[\\u123]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u1234]/", {}, { ecmaVersion: 5 }) +test("/[\\u1234]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u1234]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u1234]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u12345]/", {}, { ecmaVersion: 5 }) +test("/[\\u12345]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u12345]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u12345]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u{]/", {}, { ecmaVersion: 5 }) +test("/[\\u{]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{]/u", "Invalid regular expression: /[\\u{]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u{z]/", {}, { ecmaVersion: 5 }) +test("/[\\u{z]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{z]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{z]/u", "Invalid regular expression: /[\\u{z]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u{a}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{a}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{a}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u{a}]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u{20]/", {}, { ecmaVersion: 5 }) +test("/[\\u{20]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{20]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{20]/u", "Invalid regular expression: /[\\u{20]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u{20}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{20}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{20}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u{20}]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u{10FFFF}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{10FFFF}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{10FFFF}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u{10FFFF}]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u{110000}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{110000}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{110000}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{110000}]/u", "Invalid regular expression: /[\\u{110000}]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\u{00000001}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{00000001}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{00000001}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u{00000001}]/u", {}, { ecmaVersion: 2015 }) +test("/[\\77]/", {}, { ecmaVersion: 5 }) +test("/[\\77]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\77]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\77]/u", "Invalid regular expression: /[\\77]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\377]/", {}, { ecmaVersion: 5 }) +test("/[\\377]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\377]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\377]/u", "Invalid regular expression: /[\\377]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\400]/", {}, { ecmaVersion: 5 }) +test("/[\\400]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\400]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\400]/u", "Invalid regular expression: /[\\400]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\^]/", {}, { ecmaVersion: 5 }) +test("/[\\^]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\^]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\^]/u", {}, { ecmaVersion: 2015 }) +test("/[\\$]/", {}, { ecmaVersion: 5 }) +test("/[\\$]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\$]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\$]/u", {}, { ecmaVersion: 2015 }) +test("/[\\.]/", {}, { ecmaVersion: 5 }) +test("/[\\.]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\.]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\.]/u", {}, { ecmaVersion: 2015 }) +test("/[\\+]/", {}, { ecmaVersion: 5 }) +test("/[\\+]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\+]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\+]/u", {}, { ecmaVersion: 2015 }) +test("/[\\?]/", {}, { ecmaVersion: 5 }) +test("/[\\?]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\?]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\?]/u", {}, { ecmaVersion: 2015 }) +test("/[\\(]/", {}, { ecmaVersion: 5 }) +test("/[\\(]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\(]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\(]/u", {}, { ecmaVersion: 2015 }) +test("/[\\)]/", {}, { ecmaVersion: 5 }) +test("/[\\)]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\)]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\)]/u", {}, { ecmaVersion: 2015 }) +test("/[\\[]/", {}, { ecmaVersion: 5 }) +test("/[\\[]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\[]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\[]/u", {}, { ecmaVersion: 2015 }) +test("/[\\]]/", {}, { ecmaVersion: 5 }) +test("/[\\]]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\]]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\]]/u", {}, { ecmaVersion: 2015 }) +test("/[\\{]/", {}, { ecmaVersion: 5 }) +test("/[\\{]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\{]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\{]/u", {}, { ecmaVersion: 2015 }) +test("/[\\}]/", {}, { ecmaVersion: 5 }) +test("/[\\}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\}]/u", {}, { ecmaVersion: 2015 }) +test("/[\\|]/", {}, { ecmaVersion: 5 }) +test("/[\\|]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\|]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\|]/u", {}, { ecmaVersion: 2015 }) +test("/[\\/]/", {}, { ecmaVersion: 5 }) +test("/[\\/]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\/]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\/]/u", {}, { ecmaVersion: 2015 }) +test("/[\\a]/", {}, { ecmaVersion: 5 }) +test("/[\\a]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\a]/u", "Invalid regular expression: /[\\a]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\s]/", {}, { ecmaVersion: 5 }) +test("/[\\s]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\s]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\s]/u", {}, { ecmaVersion: 2015 }) +test("/[\\d-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\d-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\d-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\d-\\uFFFF]/u", "Invalid regular expression: /[\\d-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\D-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\D-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\D-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\D-\\uFFFF]/u", "Invalid regular expression: /[\\D-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\s-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\s-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\s-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\s-\\uFFFF]/u", "Invalid regular expression: /[\\s-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\S-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\S-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\S-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\S-\\uFFFF]/u", "Invalid regular expression: /[\\S-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\w-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\w-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\w-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\w-\\uFFFF]/u", "Invalid regular expression: /[\\w-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\W-\\uFFFF]/", {}, { ecmaVersion: 5 }) +test("/[\\W-\\uFFFF]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\W-\\uFFFF]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\W-\\uFFFF]/u", "Invalid regular expression: /[\\W-\\uFFFF]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\d]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\d]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\d]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\d]/u", "Invalid regular expression: /[\\u0000-\\d]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\D]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\D]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\D]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\D]/u", "Invalid regular expression: /[\\u0000-\\D]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\s]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\s]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\s]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\s]/u", "Invalid regular expression: /[\\u0000-\\s]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\S]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\S]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\S]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\S]/u", "Invalid regular expression: /[\\u0000-\\S]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\w]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\w]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\w]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\w]/u", "Invalid regular expression: /[\\u0000-\\w]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\W]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\W]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\W]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0000-\\W]/u", "Invalid regular expression: /[\\u0000-\\W]/: Invalid character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-\\u0001]/", {}, { ecmaVersion: 5 }) +test("/[\\u0000-\\u0001]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\u0001]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u0000-\\u0001]/u", {}, { ecmaVersion: 2015 }) +testFail("/[\\u0001-\\u0000]/", "Invalid regular expression: /[\\u0001-\\u0000]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0001-\\u0000]/", "Invalid regular expression: /[\\u0001-\\u0000]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\u0001-\\u0000]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u0001-\\u0000]/u", "Invalid regular expression: /[\\u0001-\\u0000]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\u{1}-\\u{2}]/", "Invalid regular expression: /[\\u{1}-\\u{2}]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{1}-\\u{2}]/", "Invalid regular expression: /[\\u{1}-\\u{2}]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\u{1}-\\u{2}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\u{1}-\\u{2}]/u", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{2}-\\u{1}]/", "Invalid regular expression: /[\\u{2}-\\u{1}]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{2}-\\u{1}]/", "Invalid regular expression: /[\\u{2}-\\u{1}]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\u{2}-\\u{1}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{2}-\\u{1}]/u", "Invalid regular expression: /[\\u{2}-\\u{1}]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u{2-\\u{1}]/", {}, { ecmaVersion: 5 }) +test("/[\\u{2-\\u{1}]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\u{2-\\u{1}]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\u{2-\\u{1}]/u", "Invalid regular expression: /[\\u{2-\\u{1}]/: Invalid unicode escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\a-\\z]/", {}, { ecmaVersion: 5 }) +test("/[\\a-\\z]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\a-\\z]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\a-\\z]/u", "Invalid regular expression: /[\\a-\\z]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\z-\\a]/", "Invalid regular expression: /[\\z-\\a]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\z-\\a]/", "Invalid regular expression: /[\\z-\\a]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\z-\\a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\z-\\a]/u", "Invalid regular expression: /[\\z-\\a]/: Invalid escape (1:1)", { ecmaVersion: 2015 }) +test("/[0-9--/]/", {}, { ecmaVersion: 5 }) +test("/[0-9--/]/", {}, { ecmaVersion: 2015 }) +testFail("/[0-9--/]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[0-9--/]/u", {}, { ecmaVersion: 2015 }) +testFail("/[0-9--+]/", "Invalid regular expression: /[0-9--+]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[0-9--+]/", "Invalid regular expression: /[0-9--+]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[0-9--+]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[0-9--+]/u", "Invalid regular expression: /[0-9--+]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\c-a]/", "Invalid regular expression: /[\\c-a]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c-a]/", "Invalid regular expression: /[\\c-a]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\c-a]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c-a]/u", "Invalid regular expression: /[\\c-a]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\c0-]/", {}, { ecmaVersion: 5 }) +test("/[\\c0-]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\c0-]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c0-]/u", "Invalid regular expression: /[\\c0-]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +test("/[\\c_]/", {}, { ecmaVersion: 5 }) +test("/[\\c_]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\c_]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\c_]/u", "Invalid regular expression: /[\\c_]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) +testFail("/[🌷-🌸]/", "Invalid regular expression: /[🌷-🌸]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[🌷-🌸]/", "Invalid regular expression: /[🌷-🌸]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[🌷-🌸]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[🌷-🌸]/u", {}, { ecmaVersion: 2015 }) +testFail("/[🌸-🌷]/", "Invalid regular expression: /[🌸-🌷]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[🌸-🌷]/", "Invalid regular expression: /[🌸-🌷]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[🌸-🌷]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[🌸-🌷]/u", "Invalid regular expression: /[🌸-🌷]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\uD834\\uDF06-\\uD834\\uDF08a-z]/", "Invalid regular expression: /[\\uD834\\uDF06-\\uD834\\uDF08a-z]/: Range out of order in character class (1:1)", { ecmaVersion: 5 }) +testFail("/[\\uD834\\uDF06-\\uD834\\uDF08a-z]/", "Invalid regular expression: /[\\uD834\\uDF06-\\uD834\\uDF08a-z]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\uD834\\uDF06-\\uD834\\uDF08a-z]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/[\\uD834\\uDF06-\\uD834\\uDF08a-z]/u", {}, { ecmaVersion: 2015 }) +test("/^[0-9]*$/", {}, { ecmaVersion: 5 }) +test("/^[0-9]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[0-9]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[0-9]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[0-9]+$/", {}, { ecmaVersion: 5 }) +test("/^[0-9]+$/", {}, { ecmaVersion: 2015 }) +testFail("/^[0-9]+$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[0-9]+$/u", {}, { ecmaVersion: 2015 }) +test("/^[a-zA-Z]*$/", {}, { ecmaVersion: 5 }) +test("/^[a-zA-Z]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[a-zA-Z]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[a-zA-Z]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[a-zA-Z]+$/", {}, { ecmaVersion: 5 }) +test("/^[a-zA-Z]+$/", {}, { ecmaVersion: 2015 }) +testFail("/^[a-zA-Z]+$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[a-zA-Z]+$/u", {}, { ecmaVersion: 2015 }) +test("/^[0-9a-zA-Z]*$/", {}, { ecmaVersion: 5 }) +test("/^[0-9a-zA-Z]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[0-9a-zA-Z]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[0-9a-zA-Z]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[a-zA-Z0-9!-/:-@\\[-`{-~]*$/", {}, { ecmaVersion: 5 }) +test("/^[a-zA-Z0-9!-/:-@\\[-`{-~]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[a-zA-Z0-9!-/:-@\\[-`{-~]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[a-zA-Z0-9!-/:-@\\[-`{-~]*$/u", {}, { ecmaVersion: 2015 }) +test("/^([a-zA-Z0-9]{8,})$/", {}, { ecmaVersion: 5 }) +test("/^([a-zA-Z0-9]{8,})$/", {}, { ecmaVersion: 2015 }) +testFail("/^([a-zA-Z0-9]{8,})$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^([a-zA-Z0-9]{8,})$/u", {}, { ecmaVersion: 2015 }) +test("/^([a-zA-Z0-9]{6,8})$/", {}, { ecmaVersion: 5 }) +test("/^([a-zA-Z0-9]{6,8})$/", {}, { ecmaVersion: 2015 }) +testFail("/^([a-zA-Z0-9]{6,8})$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^([a-zA-Z0-9]{6,8})$/u", {}, { ecmaVersion: 2015 }) +test("/^([0-9]{0,8})$/", {}, { ecmaVersion: 5 }) +test("/^([0-9]{0,8})$/", {}, { ecmaVersion: 2015 }) +testFail("/^([0-9]{0,8})$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^([0-9]{0,8})$/u", {}, { ecmaVersion: 2015 }) +test("/^[0-9]{8}$/", {}, { ecmaVersion: 5 }) +test("/^[0-9]{8}$/", {}, { ecmaVersion: 2015 }) +testFail("/^[0-9]{8}$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[0-9]{8}$/u", {}, { ecmaVersion: 2015 }) +test("/^https?:\\/\\//", {}, { ecmaVersion: 5 }) +test("/^https?:\\/\\//", {}, { ecmaVersion: 2015 }) +testFail("/^https?:\\/\\//u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^https?:\\/\\//u", {}, { ecmaVersion: 2015 }) +test("/^\\d{3}-\\d{4}$/", {}, { ecmaVersion: 5 }) +test("/^\\d{3}-\\d{4}$/", {}, { ecmaVersion: 2015 }) +testFail("/^\\d{3}-\\d{4}$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^\\d{3}-\\d{4}$/u", {}, { ecmaVersion: 2015 }) +test("/^\\d{1,3}(.\\d{1,3}){3}$/", {}, { ecmaVersion: 5 }) +test("/^\\d{1,3}(.\\d{1,3}){3}$/", {}, { ecmaVersion: 2015 }) +testFail("/^\\d{1,3}(.\\d{1,3}){3}$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^\\d{1,3}(.\\d{1,3}){3}$/u", {}, { ecmaVersion: 2015 }) +test("/^([1-9][0-9]*|0)(\\.[0-9]+)?$/", {}, { ecmaVersion: 5 }) +test("/^([1-9][0-9]*|0)(\\.[0-9]+)?$/", {}, { ecmaVersion: 2015 }) +testFail("/^([1-9][0-9]*|0)(\\.[0-9]+)?$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^([1-9][0-9]*|0)(\\.[0-9]+)?$/u", {}, { ecmaVersion: 2015 }) +test("/^-?([1-9][0-9]*|0)(\\.[0-9]+)?$/", {}, { ecmaVersion: 5 }) +test("/^-?([1-9][0-9]*|0)(\\.[0-9]+)?$/", {}, { ecmaVersion: 2015 }) +testFail("/^-?([1-9][0-9]*|0)(\\.[0-9]+)?$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^-?([1-9][0-9]*|0)(\\.[0-9]+)?$/u", {}, { ecmaVersion: 2015 }) +test("/^[ぁ-γ‚“γƒΌ]*$/", {}, { ecmaVersion: 5 }) +test("/^[ぁ-γ‚“γƒΌ]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[ぁ-γ‚“γƒΌ]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[ぁ-γ‚“γƒΌ]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[γ‚‘-ンヴー]*$/", {}, { ecmaVersion: 5 }) +test("/^[γ‚‘-ンヴー]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[γ‚‘-ンヴー]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[γ‚‘-ンヴー]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[ァ-ン゙゚\\-]*$/", {}, { ecmaVersion: 5 }) +test("/^[ァ-ン゙゚\\-]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[ァ-ン゙゚\\-]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[ァ-ン゙゚\\-]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[^\\x20-\\x7e]*$/", {}, { ecmaVersion: 5 }) +test("/^[^\\x20-\\x7e]*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[^\\x20-\\x7e]*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[^\\x20-\\x7e]*$/u", {}, { ecmaVersion: 2015 }) +test("/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/", {}, { ecmaVersion: 5 }) +test("/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/", {}, { ecmaVersion: 2015 }) +testFail("/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/u", {}, { ecmaVersion: 2015 }) +test("/^((4\\d{3})|(5[1-5]\\d{2})|(6011))([- ])?\\d{4}([- ])?\\d{4}([- ])?\\d{4}|3[4,7]\\d{13}$/", {}, { ecmaVersion: 5 }) +test("/^((4\\d{3})|(5[1-5]\\d{2})|(6011))([- ])?\\d{4}([- ])?\\d{4}([- ])?\\d{4}|3[4,7]\\d{13}$/", {}, { ecmaVersion: 2015 }) +testFail("/^((4\\d{3})|(5[1-5]\\d{2})|(6011))([- ])?\\d{4}([- ])?\\d{4}([- ])?\\d{4}|3[4,7]\\d{13}$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^((4\\d{3})|(5[1-5]\\d{2})|(6011))([- ])?\\d{4}([- ])?\\d{4}([- ])?\\d{4}|3[4,7]\\d{13}$/u", {}, { ecmaVersion: 2015 }) +test("/^\\s*|\\s*$/", {}, { ecmaVersion: 5 }) +test("/^\\s*|\\s*$/", {}, { ecmaVersion: 2015 }) +testFail("/^\\s*|\\s*$/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +test("/^\\s*|\\s*$/u", {}, { ecmaVersion: 2015 }) +test("/[\\d][\\12-\\14]{1,}[^\\d]/", {}, { ecmaVersion: 5 }) +test("/[\\d][\\12-\\14]{1,}[^\\d]/", {}, { ecmaVersion: 2015 }) +testFail("/[\\d][\\12-\\14]{1,}[^\\d]/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 }) +testFail("/[\\d][\\12-\\14]{1,}[^\\d]/u", "Invalid regular expression: /[\\d][\\12-\\14]{1,}[^\\d]/: Invalid class escape (1:1)", { ecmaVersion: 2015 }) + +/* +// This is test case generator. +// The tests check whether those results are same as V8 native. + +function getErrorMessage(pattern, flags) { + try { + new RegExp(pattern, flags) + return undefined + } catch (err) { + return err.message + } +} + +const patterns = [ + ["foo"], + ["foo|bar"], + ["||||"], + ["^|$|\\b|\\B"], + ["("], + ["(?"], + ["(?="], + ["(?=)"], + ["(?=foo"], + ["(?=foo)"], + ["(?!"], + ["(?!)"], + ["(?!foo"], + ["(?!foo)"], + ["(?=a)*"], + ["(?=a)+"], + ["(?=a)?"], + ["(?=a){"], + ["(?=a){}"], + ["(?=a){a}"], + ["(?=a){1}"], + ["(?=a){1,}"], + ["(?=a){1,2}"], + ["a*"], + ["a+"], + ["a?"], + ["a{"], + ["a{}"], + ["a{a}"], + ["a{1}"], + ["a{1"], + ["a{1,}"], + ["a{1,"], + ["a{1,2}"], + ["a{1,2"], + ["a{2,1}"], + ["a{2,1"], + ["(a{2,1}"], + ["a*?"], + ["a+?"], + ["a??"], + ["a{?"], + ["a{}?"], + ["a{a}?"], + ["a{1}?"], + ["a{1?"], + ["a{1,}?"], + ["a{1,?"], + ["a{1,2}?"], + ["a{1,2?"], + ["a{2,1}?"], + ["a{2,1?"], + ["πŸ‘πŸš€β‡οΈ"], + ["^"], + ["$"], + ["."], + ["(*)"], + ["+"], + ["?"], + ["("], + [")"], + ["[", "Unterminated regular expression", "Unterminated regular expression"], + ["]"], + ["{"], + ["}"], + ["|"], + ["^*"], + ["$*"], + ["${1,2"], + ["${1,2}"], + ["${2,1}"], + ["\\1"], + ["(a)\\1"], + ["\\1(a)"], + ["\\2(a)("], + ["(?:a)\\1"], + ["(a)\\2"], + ["(?:a)\\2"], + ["(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\10"], + ["(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11"], + ["(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)\\11"], + ["(?"], + ["(?a"], + ["(?a)"], + ["(?:"], + ["(?:a"], + ["(?:a)"], + ["(:a"], + ["\\d"], + ["\\D"], + ["\\s"], + ["\\S"], + ["\\w"], + ["\\W"], + ["\\f"], + ["\\n"], + ["\\r"], + ["\\t"], + ["\\v"], + ["\\cA"], + ["\\cz"], + ["\\c1"], + ["\\c"], + ["\\0"], + ["\\u"], + ["\\u1"], + ["\\u12"], + ["\\u123"], + ["\\u1234"], + ["\\u12345"], + ["\\u{"], + ["\\u{z"], + ["\\u{a}"], + ["\\u{20"], + ["\\u{20}"], + ["\\u{10FFFF}"], + ["\\u{110000}"], + ["\\u{00000001}"], + ["\\377"], + ["\\400"], + ["\\^"], + ["\\$"], + ["\\."], + ["\\+"], + ["\\?"], + ["\\("], + ["\\)"], + ["\\["], + ["\\]"], + ["\\{"], + ["\\}"], + ["\\|"], + ["\\/"], + ["\\a"], + ["\\s"], + ["[]"], + ["[^-a-b-]"], + ["[-]"], + ["[a]"], + ["[--]"], + ["[-a]"], + ["[-a-]"], + ["[a-]"], + ["[a-b]"], + ["[-a-b-]"], + ["[---]"], + ["[b-a]"], + ["[a-b--/]"], + ["[a-b--+]"], + ["[\\b-\\n]"], + ["[b\\-a]"], + ["[\\d]"], + ["[\\D]"], + ["[\\s]"], + ["[\\S]"], + ["[\\w]"], + ["[\\W]"], + ["[\\d]"], + ["[\\D]"], + ["[\\s]"], + ["[\\S]"], + ["[\\w]"], + ["[\\W]"], + ["[\\f]"], + ["[\\n]"], + ["[\\r]"], + ["[\\t]"], + ["[\\v]"], + ["[\\cA]"], + ["[\\cz]"], + ["[\\c1]"], + ["[\\c]"], + ["[\\0]"], + ["[\\x]"], + ["[\\xz]"], + ["[\\x1]"], + ["[\\x12]"], + ["[\\x123]"], + ["[\\u]"], + ["[\\u1]"], + ["[\\u12]"], + ["[\\u123]"], + ["[\\u1234]"], + ["[\\u12345]"], + ["[\\u{]"], + ["[\\u{z]"], + ["[\\u{a}]"], + ["[\\u{20]"], + ["[\\u{20}]"], + ["[\\u{10FFFF}]"], + ["[\\u{110000}]"], + ["[\\u{00000001}]"], + ["[\\77]"], + ["[\\377]"], + ["[\\400]"], + ["[\\^]"], + ["[\\$]"], + ["[\\.]"], + ["[\\+]"], + ["[\\?]"], + ["[\\(]"], + ["[\\)]"], + ["[\\[]"], + ["[\\]]"], + ["[\\{]"], + ["[\\}]"], + ["[\\|]"], + ["[\\/]"], + ["[\\a]"], + ["[\\s]"], + ["[\\d-\\uFFFF]"], + ["[\\D-\\uFFFF]"], + ["[\\s-\\uFFFF]"], + ["[\\S-\\uFFFF]"], + ["[\\w-\\uFFFF]"], + ["[\\W-\\uFFFF]"], + ["[\\u0000-\\d]"], + ["[\\u0000-\\D]"], + ["[\\u0000-\\s]"], + ["[\\u0000-\\S]"], + ["[\\u0000-\\w]"], + ["[\\u0000-\\W]"], + ["[\\u0000-\\u0001]"], + ["[\\u0001-\\u0000]"], + ["[\\u{1}-\\u{2}]"], + ["[\\u{2}-\\u{1}]"], + ["[\\u{2-\\u{1}]"], + ["[\\a-\\z]"], + ["[\\z-\\a]"], + ["[0-9--/]"], + ["[0-9--+]"], + ["[\\c-a]"], + ["[\\c0-\u001F]"], + ["[\\c_]"], + ["[🌷-🌸]"], + ["[🌸-🌷]"], + ["[\\uD834\\uDF06-\\uD834\\uDF08a-z]"], + ["^[0-9]*$"], + ["^[0-9]+$"], + ["^[a-zA-Z]*$"], + ["^[a-zA-Z]+$"], + ["^[0-9a-zA-Z]*$"], + ["^[a-zA-Z0-9!-/:-@\\[-`{-~]*$"], + ["^([a-zA-Z0-9]{8,})$"], + ["^([a-zA-Z0-9]{6,8})$"], + ["^([0-9]{0,8})$"], + ["^[0-9]{8}$"], + ["^https?:\\/\\/"], + ["^\\d{3}-\\d{4}$"], + ["^\\d{1,3}(\.\\d{1,3}){3}$"], + ["^([1-9][0-9]*|0)(\\.[0-9]+)?$"], + ["^-?([1-9][0-9]*|0)(\\.[0-9]+)?$"], + ["^[ぁ-γ‚“γƒΌ]*$"], + ["^[γ‚‘-ンヴー]*$"], + ["^[ァ-ン゙゚\\-]*$"], + ["^[^\\x20-\\x7e]*$"], + ["^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"], + ["^((4\\d{3})|(5[1-5]\\d{2})|(6011))([- ])?\\d{4}([- ])?\\d{4}([- ])?\\d{4}|3[4,7]\\d{13}$"], + ["^\\s*|\\s*$"], + ["[\\d][\\12-\\14]{1,}[^\\d]"] +] + +const tests = [] +for (const [pattern, message, messageU] of patterns) { + // Without u flag + let msg = message || getErrorMessage(pattern, "") + if (msg === undefined) { + tests.push(`test("/${pattern.replace(/\\/g, "\\\\")}/", {}, { ecmaVersion: 5 })`) + tests.push(`test("/${pattern.replace(/\\/g, "\\\\")}/", {}, { ecmaVersion: 2015 })`) + } else { + tests.push(`testFail("/${pattern.replace(/\\/g, "\\\\")}/", "${msg.replace(/\\/g, "\\\\")} (1:1)", { ecmaVersion: 5 })`) + tests.push(`testFail("/${pattern.replace(/\\/g, "\\\\")}/", "${msg.replace(/\\/g, "\\\\")} (1:1)", { ecmaVersion: 2015 })`) + } + + // With u flag + msg = messageU || getErrorMessage(pattern, "u") + tests.push(`testFail("/${pattern.replace(/\\/g, "\\\\")}/u", "Invalid regular expression flag (1:1)", { ecmaVersion: 5 })`) + if (msg === undefined) { + tests.push(`test("/${pattern.replace(/\\/g, "\\\\")}/u", {}, { ecmaVersion: 2015 })`) + } else { + tests.push(`testFail("/${pattern.replace(/\\/g, "\\\\")}/u", "${msg.replace(/\\/g, "\\\\")} (1:1)", { ecmaVersion: 2015 })`) + } +} + +require("fs").writeFileSync("a.txt", tests.join("\n")) + +*/