diff --git a/packages/babylon/src/tokenizer/index.js b/packages/babylon/src/tokenizer/index.js index ba34eb3f5f..1396bf7d0b 100644 --- a/packages/babylon/src/tokenizer/index.js +++ b/packages/babylon/src/tokenizer/index.js @@ -20,6 +20,8 @@ import { } from "../util/whitespace"; import State from "./state"; +const VALID_REGEX_FLAGS = "gmsiyu"; + // The following character codes are forbidden from being // an immediate sibling of NumericLiteralSeparator _ @@ -834,19 +836,24 @@ export default class Tokenizer extends LocationParser { const content = this.input.slice(start, this.state.pos); ++this.state.pos; - const validFlags = /^[gmsiyu]$/; let mods = ""; + while (this.state.pos < this.input.length) { const char = this.input[this.state.pos]; const charCode = this.fullCharCodeAtPos(); - if (validFlags.test(char)) { + + if (VALID_REGEX_FLAGS.indexOf(char) > -1) { + if (mods.indexOf(char) > -1) { + this.raise(this.state.pos + 1, "Duplicate regular expression flag"); + } + ++this.state.pos; mods += char; } else if ( isIdentifierChar(charCode) || charCode === charCodes.backslash ) { - this.raise(this.state.pos, "Invalid regular expression flag"); + this.raise(this.state.pos + 1, "Invalid regular expression flag"); } else { break; } diff --git a/packages/babylon/test/fixtures/core/uncategorised/108/options.json b/packages/babylon/test/fixtures/core/uncategorised/108/options.json index adf556b0a3..080cb0eaaa 100644 --- a/packages/babylon/test/fixtures/core/uncategorised/108/options.json +++ b/packages/babylon/test/fixtures/core/uncategorised/108/options.json @@ -1,3 +1,3 @@ { - "throws": "Invalid regular expression flag (1:16)" + "throws": "Invalid regular expression flag (1:17)" } diff --git a/packages/babylon/test/fixtures/core/uncategorised/366/options.json b/packages/babylon/test/fixtures/core/uncategorised/366/options.json index d67d8472c0..adf556b0a3 100644 --- a/packages/babylon/test/fixtures/core/uncategorised/366/options.json +++ b/packages/babylon/test/fixtures/core/uncategorised/366/options.json @@ -1,3 +1,3 @@ { - "throws": "Invalid regular expression flag (1:15)" + "throws": "Invalid regular expression flag (1:16)" } diff --git a/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/input.js b/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/input.js new file mode 100644 index 0000000000..1c21dcd778 --- /dev/null +++ b/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/input.js @@ -0,0 +1 @@ +/./gii; diff --git a/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/options.json b/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/options.json new file mode 100644 index 0000000000..86670c5168 --- /dev/null +++ b/packages/babylon/test/fixtures/es2015/regex/duplicate-flags/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Duplicate regular expression flag (1:6)" +} diff --git a/scripts/tests/test262/test262_whitelist.txt b/scripts/tests/test262/test262_whitelist.txt index e10be4e105..3a65e6e492 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -1946,8 +1946,6 @@ language/global-code/new.target-arrow.js(default) language/global-code/new.target-arrow.js(strict mode) language/import/dup-bound-names.js(default) language/import/dup-bound-names.js(strict mode) -language/literals/regexp/early-err-dup-flag.js(default) -language/literals/regexp/early-err-dup-flag.js(strict mode) language/literals/regexp/early-err-pattern.js(default) language/literals/regexp/early-err-pattern.js(strict mode) language/literals/regexp/invalid-braced-quantifier-exact.js(default)