diff --git a/acorn.js b/acorn.js index 7caacb8377..122c8729e9 100644 --- a/acorn.js +++ b/acorn.js @@ -1089,13 +1089,15 @@ if (this.options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/; if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag"); if (mods.indexOf('u') >= 0 && !regexpUnicodeSupport) { - // Replace each astral symbol and every Unicode code point - // escape sequence that represents such a symbol with a single - // ASCII symbol to avoid throwing on regular expressions that + // 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. - tmp = tmp - .replace(/\\u\{([0-9a-fA-F]+)\}/g, "x") - .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x"); + // 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([a-fA-F0-9]{4})|\\u\{([0-9a-fA-F]+)\}|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x") } } // Detect invalid regular expressions. diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 4f2480e12a..75019ce3af 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13861,6 +13861,34 @@ test("/[a-z]/u", { ecmaVersion: 6 }); +test("/[\\uD834\\uDF06-\\uD834\\uDF08a-z]/u", { + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "Literal", + regex: { + pattern: "[\\uD834\\uDF06-\\uD834\\uDF08a-z]", + flags: "u" + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 33 + } + } + } + } + ] +}, { + locations: true, + ecmaVersion: 6 +}); test("do {} while (false) foo();", { type: "Program",