workaround V8 RegExp bug (#3453)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 6 Oct 2019 03:49:39 +0000 (11:49 +0800)
committerGitHub <noreply@github.com>
Sun, 6 Oct 2019 03:49:39 +0000 (11:49 +0800)
fixes #3434

lib/output.js
test/compress/regexp.js

index 2d0dc53..af0cdc4 100644 (file)
@@ -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(" ");
index ac834e5..6b93fab 100644 (file)
@@ -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/;
+    }
+}