From 25c4dd7d40e66e394642706dfe667c4627dc71e0 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Sun, 6 Oct 2019 08:06:33 +0800 Subject: [PATCH] workaround V8 RegExp bug fixes #3434 --- lib/output.js | 27 ++++++-- test/compress/regexp.js | 137 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 5 deletions(-) diff --git a/lib/output.js b/lib/output.js index 2d0dc53fc8..af0cdc4bf1 100644 --- a/lib/output.js +++ b/lib/output.js @@ -136,8 +136,7 @@ function OutputStream(options) { function make_string(str, quote) { var dq = 0, sq = 0; - str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, - function(s, i) { + str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s, i) { switch (s) { case '"': ++dq; return '"'; case "'": ++sq; return "'"; @@ -599,7 +598,6 @@ function OutputStream(options) { } print(encoded); }, - encode_string : encode_string, next_indent : next_indent, with_indent : with_indent, with_block : with_block, @@ -1383,8 +1381,27 @@ function OutputStream(options) { if (regexp.raw_source) { str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/")); } - str = output.to_utf8(str); - output.print(str); + output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(seq) { + switch (seq[1]) { + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\t": return "\t"; + case "\b": return "\b"; + case "\f": return "\f"; + case "\0": return "\0"; + case "\x0B": return "\v"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + default: return seq; + } + }).replace(/[\n\r\u2028\u2029]/g, function(c) { + switch (c) { + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + } + })); var p = output.parent(); if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) output.print(" "); diff --git a/test/compress/regexp.js b/test/compress/regexp.js index ac834e5dfa..6b93faba80 100644 --- a/test/compress/regexp.js +++ b/test/compress/regexp.js @@ -35,3 +35,140 @@ regexp_2: { } expect_stdout: '["PASS","pass"]' } + +issue_3434_1: { + options = { + evaluate: true, + unsafe: true, + } + beautify = { + beautify: true, + } + input: { + var o = { + "\n": RegExp("\n"), + "\r": RegExp("\r"), + "\t": RegExp("\t"), + "\b": RegExp("\b"), + "\f": RegExp("\f"), + "\0": RegExp("\0"), + "\x0B": RegExp("\x0B"), + "\u2028": RegExp("\u2028"), + "\u2029": RegExp("\u2029"), + }; + for (var c in o) + console.log(o[c].test("\\"), o[c].test(c)); + } + expect_exact: [ + "var o = {", + ' "\\n": /\\n/,', + ' "\\r": /\\r/,', + ' "\\t": /\t/,', + ' "\\b": /\b/,', + ' "\\f": /\f/,', + ' "\\0": /\0/,', + ' "\\v": /\v/,', + ' "\\u2028": /\\u2028/,', + ' "\\u2029": /\\u2029/', + "};", + "", + 'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));', + ] + expect_stdout: [ + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + ] +} + +issue_3434_2: { + options = { + evaluate: true, + unsafe: true, + } + beautify = { + beautify: true, + } + input: { + var o = { + "\n": RegExp("\\\n"), + "\r": RegExp("\\\r"), + "\t": RegExp("\\\t"), + "\b": RegExp("\\\b"), + "\f": RegExp("\\\f"), + "\0": RegExp("\\\0"), + "\x0B": RegExp("\\\x0B"), + "\u2028": RegExp("\\\u2028"), + "\u2029": RegExp("\\\u2029"), + }; + for (var c in o) + console.log(o[c].test("\\"), o[c].test(c)); + } + expect_exact: [ + "var o = {", + ' "\\n": /\\n/,', + ' "\\r": /\\r/,', + ' "\\t": /\t/,', + ' "\\b": /\b/,', + ' "\\f": /\f/,', + ' "\\0": /\0/,', + ' "\\v": /\v/,', + ' "\\u2028": /\\u2028/,', + ' "\\u2029": /\\u2029/', + "};", + "", + 'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));', + ] + expect_stdout: [ + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + "false true", + ] +} + +issue_3434_3: { + options = { + evaluate: true, + unsafe: true, + } + input: { + RegExp("\n"); + RegExp("\r"); + RegExp("\\n"); + RegExp("\\\n"); + RegExp("\\\\n"); + RegExp("\\\\\n"); + RegExp("\\\\\\n"); + RegExp("\\\\\\\n"); + RegExp("\u2028"); + RegExp("\u2029"); + RegExp("\n\r\u2028\u2029"); + RegExp("\\\nfo\n[\n]o\\bbb"); + } + expect: { + /\n/; + /\r/; + /\n/; + /\n/; + /\\n/; + /\\\n/; + /\\\n/; + /\\\n/; + /\u2028/; + /\u2029/; + /\n\r\u2028\u2029/; + /\nfo\n[\n]o\bbb/; + } +}