From 0d20f67b03e0784bdd18eb88e0f76e6a53043404 Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Sat, 10 Feb 2018 23:22:20 +0900 Subject: [PATCH] Implement in-library regexp validation Add support for ES2018 regexp features. --- bin/run_test262.js | 5 +- src/loose/state.js | 4 + src/regexp.js | 1042 ++++++++++++++++++++++++++ src/state.js | 3 + src/tokenize.js | 79 +- src/unicode-property-data.js | 463 ++++++++++++ test/run.js | 2 + test/tests-regexp-2018.js | 150 ++++ test/tests-regexp.js | 1353 ++++++++++++++++++++++++++++++++++ 9 files changed, 3035 insertions(+), 66 deletions(-) create mode 100644 src/regexp.js create mode 100644 src/unicode-property-data.js create mode 100644 test/tests-regexp-2018.js create mode 100644 test/tests-regexp.js diff --git a/bin/run_test262.js b/bin/run_test262.js index 8dea71cc2..f52a478c7 100644 --- a/bin/run_test262.js +++ b/bin/run_test262.js @@ -9,10 +9,7 @@ const unsupportedFeatures = [ "class-fields-private", "class-fields-public", "numeric-separator-literal", - "optional-catch-binding", - "regexp-lookbehind", - "regexp-named-groups", - "regexp-unicode-property-escapes" + "optional-catch-binding" ]; run( diff --git a/src/loose/state.js b/src/loose/state.js index 571f472d6..da068edb5 100644 --- a/src/loose/state.js +++ b/src/loose/state.js @@ -1,5 +1,7 @@ import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from "../index" +function noop() {} + // Registered plugins export const pluginsLoose = {} @@ -9,6 +11,8 @@ export class LooseParser { this.options = this.toks.options this.input = this.toks.input this.tok = this.last = {type: tt.eof, start: 0, end: 0} + this.tok.validateRegExpFlags = noop + this.tok.validateRegExpPattern = noop if (this.options.locations) { let here = this.toks.curPosition() this.tok.loc = new SourceLocation(this.toks, here, here) diff --git a/src/regexp.js b/src/regexp.js new file mode 100644 index 000000000..c5953e301 --- /dev/null +++ b/src/regexp.js @@ -0,0 +1,1042 @@ +import {isIdentifierStart, isIdentifierChar} from "./identifier.js" +import {Parser} from "./state.js" +import UNICODE_PROPERTY_VALUES from "./unicode-property-data.js" + +const pp = Parser.prototype + +export class RegExpValidationState { + constructor(parser) { + this.parser = parser + this.validFlags = `gim${parser.options.ecmaVersion >= 6 ? "uy" : ""}${parser.options.ecmaVersion >= 9 ? "s" : ""}` + this.source = "" + this.flags = "" + this.start = 0 + this.switchU = false + this.switchN = false + this.pos = 0 + this.lastIntValue = 0 + this.lastStringValue = "" + this.lastAssertionIsQuantifiable = false + this.numCapturingParens = 0 + this.maxBackReference = 0 + this.groupNames = [] + this.backReferenceNames = [] + } + + reset(start, pattern, flags) { + const unicode = flags.indexOf("u") !== -1 + this.start = start | 0 + this.source = pattern + "" + this.flags = flags + this.switchU = unicode && this.parser.options.ecmaVersion >= 6 + this.switchN = unicode && this.parser.options.ecmaVersion >= 9 + } + + raise(message) { + this.parser.raiseRecoverable(this.start, `Invalid regular expression: /${this.source}/: ${message}`) + } + + // If u flag is given, this returns the code point at the index (it combines a surrogate pair). + // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). + at(i) { + const s = this.source + const l = s.length + if (i >= l) { + return -1 + } + const c = s.charCodeAt(i) + if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return c + } + return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 + } + + nextIndex(i) { + const s = this.source + const l = s.length + if (i >= l) { + return l + } + const c = s.charCodeAt(i) + if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return i + 1 + } + return i + 2 + } + + current() { + return this.at(this.pos) + } + + lookahead() { + return this.at(this.nextIndex(this.pos)) + } + + advance() { + this.pos = this.nextIndex(this.pos) + } + + eat(ch) { + if (this.current() === ch) { + this.advance() + return true + } + return false + } +} + +function codePointToString(ch) { + if (ch <= 0xFFFF) return String.fromCharCode(ch) + ch -= 0x10000 + return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) +} + +/** + * Validate the flags part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ +pp.validateRegExpFlags = function(state) { + const validFlags = state.validFlags + const flags = state.flags + + for (let i = 0; i < flags.length; i++) { + const flag = flags.charAt(i) + if (validFlags.indexOf(flag) == -1) { + this.raise(state.start, "Invalid regular expression flag") + } + if (flags.indexOf(flag, i + 1) > -1) { + this.raise(state.start, "Duplicate regular expression flag") + } + } +} + +/** + * Validate the pattern part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ +pp.validateRegExpPattern = function(state) { + this.regexp_pattern(state) + + // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of + // parsing contains a |GroupName|, reparse with the goal symbol + // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* + // exception if _P_ did not conform to the grammar, if any elements of _P_ + // were not matched by the parse, or if any Early Error conditions exist. + if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { + state.switchN = true + this.regexp_pattern(state) + } +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern +pp.regexp_pattern = function(state) { + state.pos = 0 + state.lastIntValue = 0 + state.lastStringValue = "" + state.lastAssertionIsQuantifiable = false + state.numCapturingParens = 0 + state.maxBackReference = 0 + state.groupNames.length = 0 + state.backReferenceNames.length = 0 + + this.regexp_disjunction(state) + + if (state.pos !== state.source.length) { + // Make the same messages as V8. + if (state.eat(0x29 /* ) */)) { + state.raise("Unmatched ')'") + } + if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) { + state.raise("Lone quantifier brackets") + } + } + if (state.maxBackReference > state.numCapturingParens) { + state.raise("Invalid escape") + } + for (const name of state.backReferenceNames) { + if (state.groupNames.indexOf(name) === -1) { + state.raise("Invalid named capture referenced") + } + } +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction +pp.regexp_disjunction = function(state) { + this.regexp_alternative(state) + while (state.eat(0x7C /* | */)) { + this.regexp_alternative(state) + } + + // Make the same message as V8. + if (this.regexp_eatQuantifier(state, true)) { + state.raise("Nothing to repeat") + } + if (state.eat(0x7B /* { */)) { + state.raise("Lone quantifier brackets") + } +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative +pp.regexp_alternative = function(state) { + while (state.pos < state.source.length && this.regexp_eatTerm(state)) + ; +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term +pp.regexp_eatTerm = function(state) { + if (this.regexp_eatAssertion(state)) { + // Handle `QuantifiableAssertion Quantifier` alternative. + // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion + // is a QuantifiableAssertion. + if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { + // Make the same message as V8. + if (state.switchU) { + state.raise("Invalid quantifier") + } + } + return true + } + + if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { + this.regexp_eatQuantifier(state) + return true + } + + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion +pp.regexp_eatAssertion = function(state) { + const start = state.pos + state.lastAssertionIsQuantifiable = false + + // ^, $ + if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { + return true + } + + // \b \B + if (state.eat(0x5C /* \ */)) { + if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { + return true + } + state.pos = start + } + + // Lookahead / Lookbehind + if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { + let lookbehind = false + if (this.options.ecmaVersion >= 9) { + lookbehind = state.eat(0x3C /* < */) + } + if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { + this.regexp_disjunction(state) + if (!state.eat(0x29 /* ) */)) { + state.raise("Unterminated group") + } + state.lastAssertionIsQuantifiable = !lookbehind + return true + } + } + + state.pos = start + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier +pp.regexp_eatQuantifier = function(state, noError = false) { + if (this.regexp_eatQuantifierPrefix(state, noError)) { + state.eat(0x3F /* ? */) + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix +pp.regexp_eatQuantifierPrefix = function(state, noError) { + return ( + state.eat(0x2A /* * */) || + state.eat(0x2B /* + */) || + state.eat(0x3F /* ? */) || + this.regexp_eatBracedQuantifier(state, noError) + ) +} +pp.regexp_eatBracedQuantifier = function(state, noError) { + const start = state.pos + if (state.eat(0x7B /* { */)) { + let min = 0, max = -1 + if (this.regexp_eatDecimalDigits(state)) { + min = state.lastIntValue + if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { + max = state.lastIntValue + } + if (state.eat(0x7D /* } */)) { + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term + if (max !== -1 && max < min && !noError) { + state.raise("numbers out of order in {} quantifier") + } + return true + } + } + if (state.switchU && !noError) { + state.raise("Incomplete quantifier") + } + state.pos = start + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom +pp.regexp_eatAtom = function(state) { + return ( + this.regexp_eatPatternCharacters(state) || + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) + ) +} +pp.regexp_eatReverseSolidusAtomEscape = function(state) { + const start = state.pos + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatAtomEscape(state)) { + return true + } + state.pos = start + } + return false +} +pp.regexp_eatUncapturingGroup = function(state) { + const start = state.pos + if (state.eat(0x28 /* ( */)) { + if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { + this.regexp_disjunction(state) + if (state.eat(0x29 /* ) */)) { + return true + } + state.raise("Unterminated group") + } + state.pos = start + } + return false +} +pp.regexp_eatCapturingGroup = function(state) { + if (state.eat(0x28 /* ( */)) { + if (this.options.ecmaVersion >= 9) { + this.regexp_groupSpecifier(state) + } else if (state.current() === 0x3F /* ? */) { + state.raise("Invalid group") + } + this.regexp_disjunction(state) + if (state.eat(0x29 /* ) */)) { + state.numCapturingParens += 1 + return true + } + state.raise("Unterminated group") + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom +pp.regexp_eatExtendedAtom = function(state) { + return ( + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) || + this.regexp_eatInvalidBracedQuantifier(state) || + this.regexp_eatExtendedPatternCharacter(state) + ) +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier +pp.regexp_eatInvalidBracedQuantifier = function(state) { + if (this.regexp_eatBracedQuantifier(state, true)) { + state.raise("Nothing to repeat") + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter +pp.regexp_eatSyntaxCharacter = function(state) { + const ch = state.current() + if (isSyntaxCharacter(ch)) { + state.lastIntValue = ch + state.advance() + return true + } + return false +} +function isSyntaxCharacter(ch) { + return ( + ch === 0x24 /* $ */ || + ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || + ch === 0x2E /* . */ || + ch === 0x3F /* ? */ || + ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || + ch >= 0x7B /* { */ && ch <= 0x7D /* } */ + ) +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter +// But eat eager. +pp.regexp_eatPatternCharacters = function(state) { + const start = state.pos + let ch = 0 + while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { + state.advance() + } + return state.pos !== start +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter +pp.regexp_eatExtendedPatternCharacter = function(state) { + const ch = state.current() + if ( + ch !== -1 && + ch !== 0x24 /* $ */ && + !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && + ch !== 0x2E /* . */ && + ch !== 0x3F /* ? */ && + ch !== 0x5B /* [ */ && + ch !== 0x5E /* ^ */ && + ch !== 0x7C /* | */ + ) { + state.advance() + return true + } + return false +} + +// GroupSpecifier[U] :: +// [empty] +// `?` GroupName[?U] +pp.regexp_groupSpecifier = function(state) { + if (state.eat(0x3F /* ? */)) { + if (this.regexp_eatGroupName(state)) { + if (state.groupNames.indexOf(state.lastStringValue) !== -1) { + state.raise("Duplicate capture group name") + } + state.groupNames.push(state.lastStringValue) + return + } + state.raise("Invalid group") + } +} + +// GroupName[U] :: +// `<` RegExpIdentifierName[?U] `>` +// Note: this updates `state.lastStringValue` property with the eaten name. +pp.regexp_eatGroupName = function(state) { + state.lastStringValue = "" + if (state.eat(0x3C /* < */)) { + if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { + return true + } + state.raise("Invalid capture group name") + } + return false +} + +// RegExpIdentifierName[U] :: +// RegExpIdentifierStart[?U] +// RegExpIdentifierName[?U] RegExpIdentifierPart[?U] +// Note: this updates `state.lastStringValue` property with the eaten name. +pp.regexp_eatRegExpIdentifierName = function(state) { + state.lastStringValue = "" + if (this.regexp_eatRegExpIdentifierStart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue) + while (this.regexp_eatRegExpIdentifierPart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue) + } + return true + } + return false +} + +// RegExpIdentifierStart[U] :: +// UnicodeIDStart +// `$` +// `_` +// `\` RegExpUnicodeEscapeSequence[?U] +pp.regexp_eatRegExpIdentifierStart = function(state) { + const start = state.pos + let ch = state.current() + state.advance() + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { + ch = state.lastIntValue + } + if (isRegExpIdentifierStart(ch)) { + state.lastIntValue = ch + return true + } + + state.pos = start + return false +} +function isRegExpIdentifierStart(ch) { + return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ +} + +// RegExpIdentifierPart[U] :: +// UnicodeIDContinue +// `$` +// `_` +// `\` RegExpUnicodeEscapeSequence[?U] +// +// +pp.regexp_eatRegExpIdentifierPart = function(state) { + const start = state.pos + let ch = state.current() + state.advance() + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { + ch = state.lastIntValue + } + if (isRegExpIdentifierPart(ch)) { + state.lastIntValue = ch + return true + } + + state.pos = start + return false +} +function isRegExpIdentifierPart(ch) { + return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* */ || ch === 0x200D /* */ +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape +pp.regexp_eatAtomEscape = function(state) { + if ( + this.regexp_eatBackReference(state) || + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) || + (state.switchN && this.regexp_eatKGroupName(state)) + ) { + return true + } + if (state.switchU) { + // Make the same message as V8. + if (state.current() === 0x63 /* c */) { + state.raise("Invalid unicode escape") + } + state.raise("Invalid escape") + } + return false +} +pp.regexp_eatBackReference = function(state) { + const start = state.pos + if (this.regexp_eatDecimalEscape(state)) { + const n = state.lastIntValue + if (state.switchU) { + // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (n > state.maxBackReference) { + state.maxBackReference = n + } + return true + } + if (n <= state.numCapturingParens) { + return true + } + state.pos = start + } + return false +} +pp.regexp_eatKGroupName = function(state) { + if (state.eat(0x6B /* k */)) { + if (this.regexp_eatGroupName(state)) { + state.backReferenceNames.push(state.lastStringValue) + return true + } + state.raise("Invalid named reference") + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape +pp.regexp_eatCharacterEscape = function(state) { + return ( + this.regexp_eatControlEscape(state) || + this.regexp_eatCControlLetter(state) || + this.regexp_eatZero(state) || + this.regexp_eatHexEscapeSequence(state) || + this.regexp_eatRegExpUnicodeEscapeSequence(state) || + (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || + this.regexp_eatIdentityEscape(state) + ) +} +pp.regexp_eatCControlLetter = function(state) { + const start = state.pos + if (state.eat(0x63 /* c */)) { + if (this.regexp_eatControlLetter(state)) { + return true + } + state.pos = start + } + return false +} +pp.regexp_eatZero = function(state) { + if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { + state.lastIntValue = 0 + state.advance() + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape +pp.regexp_eatControlEscape = function(state) { + const ch = state.current() + if (ch === 0x74 /* t */) { + state.lastIntValue = 0x09 /* \t */ + state.advance() + return true + } + if (ch === 0x6E /* n */) { + state.lastIntValue = 0x0A /* \n */ + state.advance() + return true + } + if (ch === 0x76 /* v */) { + state.lastIntValue = 0x0B /* \v */ + state.advance() + return true + } + if (ch === 0x66 /* f */) { + state.lastIntValue = 0x0C /* \f */ + state.advance() + return true + } + if (ch === 0x72 /* r */) { + state.lastIntValue = 0x0D /* \r */ + state.advance() + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter +pp.regexp_eatControlLetter = function(state) { + const ch = state.current() + if (isControlLetter(ch)) { + state.lastIntValue = ch % 0x20 + state.advance() + return true + } + return false +} +function isControlLetter(ch) { + return ( + (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || + (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) + ) +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence +pp.regexp_eatRegExpUnicodeEscapeSequence = function(state) { + const start = state.pos + + if (state.eat(0x75 /* u */)) { + if (this.regexp_eatFixedHexDigits(state, 4)) { + const lead = state.lastIntValue + if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) { + const leadSurrogateEnd = state.pos + if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { + const trail = state.lastIntValue + if (trail >= 0xDC00 && trail <= 0xDFFF) { + state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000 + return true + } + } + state.pos = leadSurrogateEnd + state.lastIntValue = lead + } + return true + } + if ( + state.switchU && + state.eat(0x7B /* { */) && + this.regexp_eatHexDigits(state) && + state.eat(0x7D /* } */) && + isValidUnicode(state.lastIntValue) + ) { + return true + } + if (state.switchU) { + state.raise("Invalid unicode escape") + } + state.pos = start + } + + return false +} +function isValidUnicode(ch) { + return ch >= 0 && ch <= 0x10FFFF +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape +pp.regexp_eatIdentityEscape = function(state) { + if (state.switchU) { + if (this.regexp_eatSyntaxCharacter(state)) { + return true + } + if (state.eat(0x2F /* / */)) { + state.lastIntValue = 0x2F /* / */ + return true + } + return false + } + + const ch = state.current() + if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { + state.lastIntValue = ch + state.advance() + return true + } + + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape +pp.regexp_eatDecimalEscape = function(state) { + state.lastIntValue = 0 + let ch = state.current() + if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { + do { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */) + state.advance() + } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape +pp.regexp_eatCharacterClassEscape = function(state) { + const ch = state.current() + + if (isCharacterClassEscape(ch)) { + state.lastIntValue = -1 + state.advance() + return true + } + + if ( + state.switchU && + this.options.ecmaVersion >= 9 && + (ch === 0x50 /* P */ || ch === 0x70 /* p */) + ) { + state.lastIntValue = -1 + state.advance() + if ( + state.eat(0x7B /* { */) && + this.regexp_eatUnicodePropertyValueExpression(state) && + state.eat(0x7D /* } */) + ) { + return true + } + state.raise("Invalid property name") + } + + return false +} +function isCharacterClassEscape(ch) { + return ( + ch === 0x64 /* d */ || + ch === 0x44 /* D */ || + ch === 0x73 /* s */ || + ch === 0x53 /* S */ || + ch === 0x77 /* w */ || + ch === 0x57 /* W */ + ) +} + +// UnicodePropertyValueExpression :: +// UnicodePropertyName `=` UnicodePropertyValue +// LoneUnicodePropertyNameOrValue +pp.regexp_eatUnicodePropertyValueExpression = function(state) { + const start = state.pos + + // UnicodePropertyName `=` UnicodePropertyValue + if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { + const name = state.lastStringValue + if (this.regexp_eatUnicodePropertyValue(state)) { + const value = state.lastStringValue + this.regexp_validateUnicodePropertyNameAndValue(state, name, value) + return true + } + } + state.pos = start + + // LoneUnicodePropertyNameOrValue + if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { + const nameOrValue = state.lastStringValue + this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue) + return true + } + return false +} +pp.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { + if (!UNICODE_PROPERTY_VALUES.hasOwnProperty(name) || UNICODE_PROPERTY_VALUES[name].indexOf(value) === -1) { + state.raise("Invalid property name") + } +} +pp.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { + if (UNICODE_PROPERTY_VALUES.$LONE.indexOf(nameOrValue) === -1) { + state.raise("Invalid property name") + } +} + +// UnicodePropertyName :: +// UnicodePropertyNameCharacters +pp.regexp_eatUnicodePropertyName = function(state) { + let ch = 0 + state.lastStringValue = "" + while (isUnicodePropertyNameCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch) + state.advance() + } + return state.lastStringValue !== "" +} +function isUnicodePropertyNameCharacter(ch) { + return isControlLetter(ch) || ch === 0x5F /* _ */ +} + +// UnicodePropertyValue :: +// UnicodePropertyValueCharacters +pp.regexp_eatUnicodePropertyValue = function(state) { + let ch = 0 + state.lastStringValue = "" + while (isUnicodePropertyValueCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch) + state.advance() + } + return state.lastStringValue !== "" +} +function isUnicodePropertyValueCharacter(ch) { + return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) +} + +// LoneUnicodePropertyNameOrValue :: +// UnicodePropertyValueCharacters +pp.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { + return this.regexp_eatUnicodePropertyValue(state) +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass +pp.regexp_eatCharacterClass = function(state) { + if (state.eat(0x5B /* [ */)) { + state.eat(0x5E /* ^ */) + this.regexp_classRanges(state) + if (state.eat(0x5D /* [ */)) { + return true + } + // Unreachable since it threw "unterminated regular expression" error before. + state.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 +pp.regexp_classRanges = function(state) { + while (this.regexp_eatClassAtom(state)) { + const left = state.lastIntValue + if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { + const right = state.lastIntValue + if (state.switchU && (left === -1 || right === -1)) { + state.raise("Invalid character class") + } + if (left !== -1 && right !== -1 && left > right) { + state.raise("Range out of order in character class") + } + } + } +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom +// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash +pp.regexp_eatClassAtom = function(state) { + const start = state.pos + + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatClassEscape(state)) { + return true + } + if (state.switchU) { + // Make the same message as V8. + const ch = state.current() + if (ch === 0x63 /* c */ || isOctalDigit(ch)) { + state.raise("Invalid class escape") + } + state.raise("Invalid escape") + } + state.pos = start + } + + const ch = state.current() + if (ch !== 0x5D /* [ */) { + state.lastIntValue = ch + state.advance() + return true + } + + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape +pp.regexp_eatClassEscape = function(state) { + const start = state.pos + + if (state.eat(0x62 /* b */)) { + state.lastIntValue = 0x08 /* */ + return true + } + + if (state.switchU && state.eat(0x2D /* - */)) { + state.lastIntValue = 0x2D /* - */ + return true + } + + if (!state.switchU && state.eat(0x63 /* c */)) { + if (this.regexp_eatClassControlLetter(state)) { + return true + } + state.pos = start + } + + return ( + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) + ) +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter +pp.regexp_eatClassControlLetter = function(state) { + const ch = state.current() + if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { + state.lastIntValue = ch % 0x20 + state.advance() + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence +pp.regexp_eatHexEscapeSequence = function(state) { + const start = state.pos + if (state.eat(0x78 /* x */)) { + if (this.regexp_eatFixedHexDigits(state, 2)) { + return true + } + if (state.switchU) { + state.raise("Invalid escape") + } + state.pos = start + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits +pp.regexp_eatDecimalDigits = function(state) { + const start = state.pos + let ch = 0 + state.lastIntValue = 0 + while (isDecimalDigit(ch = state.current())) { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */) + state.advance() + } + return state.pos !== start +} +function isDecimalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits +pp.regexp_eatHexDigits = function(state) { + const start = state.pos + let ch = 0 + state.lastIntValue = 0 + while (isHexDigit(ch = state.current())) { + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch) + state.advance() + } + return state.pos !== start +} +function isHexDigit(ch) { + return ( + (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || + (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || + (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) + ) +} +function hexToInt(ch) { + if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { + return 10 + (ch - 0x41 /* A */) + } + if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { + return 10 + (ch - 0x61 /* a */) + } + return ch - 0x30 /* 0 */ +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence +// Allows only 0-377(octal) i.e. 0-255(decimal). +pp.regexp_eatLegacyOctalEscapeSequence = function(state) { + if (this.regexp_eatOctalDigit(state)) { + const n1 = state.lastIntValue + if (this.regexp_eatOctalDigit(state)) { + const n2 = state.lastIntValue + if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { + state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue + } else { + state.lastIntValue = n1 * 8 + n2 + } + } else { + state.lastIntValue = n1 + } + return true + } + return false +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit +pp.regexp_eatOctalDigit = function(state) { + const ch = state.current() + if (isOctalDigit(ch)) { + state.lastIntValue = ch - 0x30 /* 0 */ + state.advance() + return true + } + state.lastIntValue = 0 + return false +} +function isOctalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ +} + +// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits +// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit +// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence +pp.regexp_eatFixedHexDigits = function(state, length) { + const start = state.pos + state.lastIntValue = 0 + for (let i = 0; i < length; ++i) { + const ch = state.current() + if (!isHexDigit(ch)) { + state.pos = start + return false + } + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch) + state.advance() + } + return true +} diff --git a/src/state.js b/src/state.js index b90403f96..185fe2864 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() + + // For RegExp validation + this.regexpState = 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..3dbaf67f1 100644 --- a/src/tokenize.js +++ b/src/tokenize.js @@ -2,6 +2,7 @@ import {isIdentifierStart, isIdentifierChar} from "./identifier" import {types as tt, keywords as keywordTypes} from "./tokentype" import {Parser} from "./state" import {SourceLocation} from "./locutil" +import {RegExpValidationState} from "./regexp" import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace" // Object type used to represent tokens. Note that normally, tokens @@ -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,28 @@ 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 state = this.regexpState || (this.regexpState = new RegExpValidationState(this)) + state.reset(start, pattern, flags) + this.validateRegExpFlags(state) + this.validateRegExpPattern(state) + + // 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/src/unicode-property-data.js b/src/unicode-property-data.js new file mode 100644 index 000000000..d44f1a2c1 --- /dev/null +++ b/src/unicode-property-data.js @@ -0,0 +1,463 @@ +const data = { + "$LONE": [ + "ASCII", + "ASCII_Hex_Digit", + "AHex", + "Alphabetic", + "Alpha", + "Any", + "Assigned", + "Bidi_Control", + "Bidi_C", + "Bidi_Mirrored", + "Bidi_M", + "Case_Ignorable", + "CI", + "Cased", + "Changes_When_Casefolded", + "CWCF", + "Changes_When_Casemapped", + "CWCM", + "Changes_When_Lowercased", + "CWL", + "Changes_When_NFKC_Casefolded", + "CWKCF", + "Changes_When_Titlecased", + "CWT", + "Changes_When_Uppercased", + "CWU", + "Dash", + "Default_Ignorable_Code_Point", + "DI", + "Deprecated", + "Dep", + "Diacritic", + "Dia", + "Emoji", + "Emoji_Component", + "Emoji_Modifier", + "Emoji_Modifier_Base", + "Emoji_Presentation", + "Extender", + "Ext", + "Grapheme_Base", + "Gr_Base", + "Grapheme_Extend", + "Gr_Ext", + "Hex_Digit", + "Hex", + "IDS_Binary_Operator", + "IDSB", + "IDS_Trinary_Operator", + "IDST", + "ID_Continue", + "IDC", + "ID_Start", + "IDS", + "Ideographic", + "Ideo", + "Join_Control", + "Join_C", + "Logical_Order_Exception", + "LOE", + "Lowercase", + "Lower", + "Math", + "Noncharacter_Code_Point", + "NChar", + "Pattern_Syntax", + "Pat_Syn", + "Pattern_White_Space", + "Pat_WS", + "Quotation_Mark", + "QMark", + "Radical", + "Regional_Indicator", + "RI", + "Sentence_Terminal", + "STerm", + "Soft_Dotted", + "SD", + "Terminal_Punctuation", + "Term", + "Unified_Ideograph", + "UIdeo", + "Uppercase", + "Upper", + "Variation_Selector", + "VS", + "White_Space", + "space", + "XID_Continue", + "XIDC", + "XID_Start", + "XIDS" + ], + "General_Category": [ + "Cased_Letter", + "LC", + "Close_Punctuation", + "Pe", + "Connector_Punctuation", + "Pc", + "Control", + "Cc", + "cntrl", + "Currency_Symbol", + "Sc", + "Dash_Punctuation", + "Pd", + "Decimal_Number", + "Nd", + "digit", + "Enclosing_Mark", + "Me", + "Final_Punctuation", + "Pf", + "Format", + "Cf", + "Initial_Punctuation", + "Pi", + "Letter", + "L", + "Letter_Number", + "Nl", + "Line_Separator", + "Zl", + "Lowercase_Letter", + "Ll", + "Mark", + "M", + "Combining_Mark", + "Math_Symbol", + "Sm", + "Modifier_Letter", + "Lm", + "Modifier_Symbol", + "Sk", + "Nonspacing_Mark", + "Mn", + "Number", + "N", + "Open_Punctuation", + "Ps", + "Other", + "C", + "Other_Letter", + "Lo", + "Other_Number", + "No", + "Other_Punctuation", + "Po", + "Other_Symbol", + "So", + "Paragraph_Separator", + "Zp", + "Private_Use", + "Co", + "Punctuation", + "P", + "punct", + "Separator", + "Z", + "Space_Separator", + "Zs", + "Spacing_Mark", + "Mc", + "Surrogate", + "Cs", + "Symbol", + "S", + "Titlecase_Letter", + "Lt", + "Unassigned", + "Cn", + "Uppercase_Letter", + "Lu" + ], + "Script": [ + "Adlam", + "Adlm", + "Ahom", + "Anatolian_Hieroglyphs", + "Hluw", + "Arabic", + "Arab", + "Armenian", + "Armn", + "Avestan", + "Avst", + "Balinese", + "Bali", + "Bamum", + "Bamu", + "Bassa_Vah", + "Bass", + "Batak", + "Batk", + "Bengali", + "Beng", + "Bhaiksuki", + "Bhks", + "Bopomofo", + "Bopo", + "Brahmi", + "Brah", + "Braille", + "Brai", + "Buginese", + "Bugi", + "Buhid", + "Buhd", + "Canadian_Aboriginal", + "Cans", + "Carian", + "Cari", + "Caucasian_Albanian", + "Aghb", + "Chakma", + "Cakm", + "Cham", + "Cherokee", + "Cher", + "Common", + "Zyyy", + "Coptic", + "Copt", + "Qaac", + "Cuneiform", + "Xsux", + "Cypriot", + "Cprt", + "Cyrillic", + "Cyrl", + "Deseret", + "Dsrt", + "Devanagari", + "Deva", + "Duployan", + "Dupl", + "Egyptian_Hieroglyphs", + "Egyp", + "Elbasan", + "Elba", + "Ethiopic", + "Ethi", + "Georgian", + "Geor", + "Glagolitic", + "Glag", + "Gothic", + "Goth", + "Grantha", + "Gran", + "Greek", + "Grek", + "Gujarati", + "Gujr", + "Gurmukhi", + "Guru", + "Han", + "Hani", + "Hangul", + "Hang", + "Hanunoo", + "Hano", + "Hatran", + "Hatr", + "Hebrew", + "Hebr", + "Hiragana", + "Hira", + "Imperial_Aramaic", + "Armi", + "Inherited", + "Zinh", + "Qaai", + "Inscriptional_Pahlavi", + "Phli", + "Inscriptional_Parthian", + "Prti", + "Javanese", + "Java", + "Kaithi", + "Kthi", + "Kannada", + "Knda", + "Katakana", + "Kana", + "Kayah_Li", + "Kali", + "Kharoshthi", + "Khar", + "Khmer", + "Khmr", + "Khojki", + "Khoj", + "Khudawadi", + "Sind", + "Lao", + "Laoo", + "Latin", + "Latn", + "Lepcha", + "Lepc", + "Limbu", + "Limb", + "Linear_A", + "Lina", + "Linear_B", + "Linb", + "Lisu", + "Lycian", + "Lyci", + "Lydian", + "Lydi", + "Mahajani", + "Mahj", + "Malayalam", + "Mlym", + "Mandaic", + "Mand", + "Manichaean", + "Mani", + "Marchen", + "Marc", + "Masaram_Gondi", + "Gonm", + "Meetei_Mayek", + "Mtei", + "Mende_Kikakui", + "Mend", + "Meroitic_Cursive", + "Merc", + "Meroitic_Hieroglyphs", + "Mero", + "Miao", + "Plrd", + "Modi", + "Mongolian", + "Mong", + "Mro", + "Mroo", + "Multani", + "Mult", + "Myanmar", + "Mymr", + "Nabataean", + "Nbat", + "New_Tai_Lue", + "Talu", + "Newa", + "Nko", + "Nkoo", + "Nushu", + "Nshu", + "Ogham", + "Ogam", + "Ol_Chiki", + "Olck", + "Old_Hungarian", + "Hung", + "Old_Italic", + "Ital", + "Old_North_Arabian", + "Narb", + "Old_Permic", + "Perm", + "Old_Persian", + "Xpeo", + "Old_South_Arabian", + "Sarb", + "Old_Turkic", + "Orkh", + "Oriya", + "Orya", + "Osage", + "Osge", + "Osmanya", + "Osma", + "Pahawh_Hmong", + "Hmng", + "Palmyrene", + "Palm", + "Pau_Cin_Hau", + "Pauc", + "Phags_Pa", + "Phag", + "Phoenician", + "Phnx", + "Psalter_Pahlavi", + "Phlp", + "Rejang", + "Rjng", + "Runic", + "Runr", + "Samaritan", + "Samr", + "Saurashtra", + "Saur", + "Sharada", + "Shrd", + "Shavian", + "Shaw", + "Siddham", + "Sidd", + "SignWriting", + "Sgnw", + "Sinhala", + "Sinh", + "Sora_Sompeng", + "Sora", + "Soyombo", + "Soyo", + "Sundanese", + "Sund", + "Syloti_Nagri", + "Sylo", + "Syriac", + "Syrc", + "Tagalog", + "Tglg", + "Tagbanwa", + "Tagb", + "Tai_Le", + "Tale", + "Tai_Tham", + "Lana", + "Tai_Viet", + "Tavt", + "Takri", + "Takr", + "Tamil", + "Taml", + "Tangut", + "Tang", + "Telugu", + "Telu", + "Thaana", + "Thaa", + "Thai", + "Tibetan", + "Tibt", + "Tifinagh", + "Tfng", + "Tirhuta", + "Tirh", + "Ugaritic", + "Ugar", + "Vai", + "Vaii", + "Warang_Citi", + "Wara", + "Yi", + "Yiii", + "Zanabazar_Square", + "Zanb" + ] +} +Array.prototype.push.apply(data.$LONE, data.General_Category) +data.gc = data.General_Category +data.sc = data.Script_Extensions = data.scx = data.Script + +export default data diff --git a/test/run.js b/test/run.js index 91ad384c7..025f6503d 100644 --- a/test/run.js +++ b/test/run.js @@ -12,6 +12,8 @@ require("./tests-directive.js"); require("./tests-rest-spread-properties.js"); require("./tests-async-iteration.js"); + require("./tests-regexp.js"); + require("./tests-regexp-2018.js"); acorn = require("../dist/acorn") require("../dist/acorn_loose") } else { diff --git a/test/tests-regexp-2018.js b/test/tests-regexp-2018.js new file mode 100644 index 000000000..0a48fabb7 --- /dev/null +++ b/test/tests-regexp-2018.js @@ -0,0 +1,150 @@ +if (typeof exports != "undefined") { + var test = require("./driver.js").test + var testFail = require("./driver.js").testFail +} + +//------------------------------------------------------------------------------ +// Named capture groups +//------------------------------------------------------------------------------ + +test("/(a)/", {}, { ecmaVersion: 2018 }) +test("/(?:a)/", {}, { ecmaVersion: 2018 }) +testFail("/(?a/", "Invalid regular expression: /(?a/: Invalid group (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)/", "Invalid regular expression: /(?a)/: Invalid group (1:1)", { ecmaVersion: 2018 }) +testFail("/(?)/", {}, { ecmaVersion: 2018 }) +test("/\\k/", {}, { ecmaVersion: 2017 }) +test("/\\k/", {}, { ecmaVersion: 2018 }) +testFail("/\\k/u", "Invalid regular expression: /\\k/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +testFail("/\\k/u", "Invalid regular expression: /\\k/: Invalid named reference (1:1)", { ecmaVersion: 2018 }) +test("/\\k/", {}, { ecmaVersion: 2017 }) +test("/\\k/", {}, { ecmaVersion: 2018 }) +testFail("/\\k/u", "Invalid regular expression: /\\k/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +testFail("/\\k/u", "Invalid regular expression: /\\k/: Invalid named capture referenced (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\ka)\\k/", "Invalid regular expression: /(?a)\\k/: Invalid group (1:1)", { ecmaVersion: 2017 }) +test("/(?a)\\k/", {}, { ecmaVersion: 2018 }) +testFail("/(?a)\\k/u", "Invalid regular expression: /(?a)\\k/: Invalid group (1:1)", { ecmaVersion: 2017 }) +test("/(?a)\\k/u", {}, { ecmaVersion: 2018 }) + +test("/(?a)\\1/", {}, { ecmaVersion: 2018 }) +test("/(?a)\\1/u", {}, { ecmaVersion: 2018 }) +test("/(?a)\\2/", {}, { ecmaVersion: 2018 }) +testFail("/(?a)\\2/u", "Invalid regular expression: /(?a)\\2/: Invalid escape (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)\\k/", "Invalid regular expression: /(?a)\\k/: Invalid named capture referenced (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)\\k/u", "Invalid regular expression: /(?a)\\k/: Invalid named capture referenced (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)(?a)/", "Invalid regular expression: /(?a)(?a)/: Duplicate capture group name (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)(?a)/u", "Invalid regular expression: /(?a)(?a)/: Duplicate capture group name (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)(?<\\u{61}>a)/u", "Invalid regular expression: /(?a)(?<\\u{61}>a)/: Duplicate capture group name (1:1)", { ecmaVersion: 2018 }) +testFail("/(?a)(?<\\u0061>a)/u", "Invalid regular expression: /(?a)(?<\\u0061>a)/: Duplicate capture group name (1:1)", { ecmaVersion: 2018 }) +test("/(?a)(?a)/", {}, { ecmaVersion: 2018 }) +test("/(?a)(?a)/u", {}, { ecmaVersion: 2018 }) + +test("/\\k(?a)/", {}, { ecmaVersion: 2018 }) +test("/\\k(?a)/u", {}, { ecmaVersion: 2018 }) +test("/\\1(?a)/", {}, { ecmaVersion: 2018 }) +test("/\\1(?a)/u", {}, { ecmaVersion: 2018 }) + +test("/(?<$abc>a)\\k<$abc>/u", {}, { ecmaVersion: 2018 }) +test("/(?<あ>a)\\k<あ>/u", {}, { ecmaVersion: 2018 }) +test("/(?<𠮷>a)\\k<\\u{20bb7}>/u", {}, { ecmaVersion: 2018 }) +test("/(?<\\uD842\\uDFB7>a)\\k<\\u{20bb7}>/u", {}, { ecmaVersion: 2018 }) +test("/(?<\\u{20bb7}>a)\\k<\\uD842\\uDFB7>/u", {}, { ecmaVersion: 2018 }) +testFail("/(?<☀>a)\\k<☀>/u", "Invalid regular expression: /(?<☀>a)\\k<☀>/: Invalid capture group name (1:1)", { ecmaVersion: 2018 }) +testFail("/(?<\\u0020>a)\\k<\\u0020>/u", "Invalid regular expression: /(?<\\u0020>a)\\k<\\u0020>/: Invalid capture group name (1:1)", { ecmaVersion: 2018 }) +test("/(?a)\\k<\\u0061\\u0062\\u0063>/u", {}, { ecmaVersion: 2018 }) +test("/(?<\\u0061\\u0062\\u0063>a)\\k/u", {}, { ecmaVersion: 2018 }) +test("/(?<\\u0061\\u0062\\u0063>a)\\k<\\u{61}\\u{62}\\u{63}>/u", {}, { ecmaVersion: 2018 }) +testFail("/(?<\\u0061\\u0062\\u0063>a)\\k/u", "Invalid regular expression: /(?<\\u0061\\u0062\\u0063>a)\\k/: Invalid named capture referenced (1:1)", { ecmaVersion: 2018 }) +testFail("/(?<11>a)\\k<11>/u", "Invalid regular expression: /(?<11>a)\\k<11>/: Invalid capture group name (1:1)", { ecmaVersion: 2018 }) +test("/(?a)\\k/u", {}, { ecmaVersion: 2018 }) + +//------------------------------------------------------------------------------ +// Unicode property escapes +//------------------------------------------------------------------------------ + +test("/\\p/", {}, { ecmaVersion: 2017 }) +testFail("/\\p/u", "Invalid regular expression: /\\p/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +test("/\\p/", {}, { ecmaVersion: 2018 }) +testFail("/\\p/u", "Invalid regular expression: /\\p/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +test("/\\p{/", {}, { ecmaVersion: 2017 }) +testFail("/\\p{/u", "Invalid regular expression: /\\p{/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +test("/\\p{/", {}, { ecmaVersion: 2018 }) +testFail("/\\p{/u", "Invalid regular expression: /\\p{/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +test("/\\p{ASCII/", {}, { ecmaVersion: 2017 }) +testFail("/\\p{ASCII/u", "Invalid regular expression: /\\p{ASCII/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +test("/\\p{ASCII/", {}, { ecmaVersion: 2018 }) +testFail("/\\p{ASCII/u", "Invalid regular expression: /\\p{ASCII/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +test("/\\p{ASCII}/", {}, { ecmaVersion: 2017 }) +testFail("/\\p{ASCII}/u", "Invalid regular expression: /\\p{ASCII}/: Invalid escape (1:1)", { ecmaVersion: 2017 }) +test("/\\p{ASCII}/", {}, { ecmaVersion: 2018 }) +test("/\\p{ASCII}/u", {}, { ecmaVersion: 2018 }) + +test("/\\p{Emoji}/u", {}, { ecmaVersion: 2018 }) +testFail("/\\p{General_Category}/u", "Invalid regular expression: /\\p{General_Category}/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +testFail("/\\p{General_Category=}/u", "Invalid regular expression: /\\p{General_Category=}/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +testFail("/\\p{General_Category/u", "Invalid regular expression: /\\p{General_Category/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +testFail("/\\p{General_Category=/u", "Invalid regular expression: /\\p{General_Category=/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +testFail("/\\p{General_Category=Letter/u", "Invalid regular expression: /\\p{General_Category=Letter/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +test("/\\p{General_Category=Letter}/u", {}, { ecmaVersion: 2018 }) +testFail("/\\p{General_Category=Hiragana}/u", "Invalid regular expression: /\\p{General_Category=Hiragana}/: Invalid property name (1:1)", { ecmaVersion: 2018 }) +test("/\\p{Script=Hiragana}/u", {}, { ecmaVersion: 2018 }) +testFail("/[\\p{Script=Hiragana}-\\p{Script=Katakana}]/u", "Invalid regular expression: /[\\p{Script=Hiragana}-\\p{Script=Katakana}]/: Invalid character class (1:1)", { ecmaVersion: 2018 }) +test("/[\\p{Script=Hiragana}\\-\\p{Script=Katakana}]/u", {}, { ecmaVersion: 2018 }) + +//------------------------------------------------------------------------------ +// Lookbehind assertions +//------------------------------------------------------------------------------ + +testFail("/(?\\w){3})f/u", {}, { ecmaVersion: 2018 }) +test("/((?<=\\w{3}))f/u", {}, { ecmaVersion: 2018 }) +test("/(?(?<=\\w{3}))f/u", {}, { ecmaVersion: 2018 }) +test("/(?\\d){3})f/u", {}, { ecmaVersion: 2018 }) +test("/(?\\D){3})f|f/u", {}, { ecmaVersion: 2018 }) +test("/(?(?\\w){3})f/", {}, { ecmaVersion: 2018 }) +test("/((?<=\\w{3}))f/", {}, { ecmaVersion: 2018 }) +test("/(?(?<=\\w{3}))f/", {}, { ecmaVersion: 2018 }) +test("/(?\\d){3})f/", {}, { ecmaVersion: 2018 }) +test("/(?(?.)|(?.))/u", {}, { ecmaVersion: 2018 }) diff --git a/test/tests-regexp.js b/test/tests-regexp.js new file mode 100644 index 000000000..6c4719486 --- /dev/null +++ b/test/tests-regexp.js @@ -0,0 +1,1353 @@ +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("/[\\u0000-🌸-\\u0000]/", "Invalid regular expression: /[\\u0000-🌸-\\u0000]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +testFail("/[\\u0000-\\ud83c\\udf38-\\u0000]/", "Invalid regular expression: /[\\u0000-\\ud83c\\udf38-\\u0000]/: Range out of order in character class (1:1)", { ecmaVersion: 2015 }) +test("/[\\u0000-🌸-\\u0000]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u0000-\\u{1f338}-\\u0000]/u", {}, { ecmaVersion: 2015 }) +test("/[\\u0000-\\ud83c\\udf38-\\u0000]/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 }) +test("/([a ]\\b)*\\b/", {}, { ecmaVersion: 5 }) + +/* +// 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")) + +*/