escape consecutive unpaired surrogates (#2576)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 10 Dec 2017 17:15:44 +0000 (01:15 +0800)
committerGitHub <noreply@github.com>
Sun, 10 Dec 2017 17:15:44 +0000 (01:15 +0800)
fixes #2569

lib/output.js
lib/parse.js
test/compress/unicode.js

index 1aa6345..a4c41f1 100644 (file)
@@ -121,11 +121,16 @@ function OutputStream(options) {
             }
         });
     } : function(str) {
-        return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
-            return "\\u" + ch.charCodeAt(0).toString(16);
-        }).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
-            return prefix + "\\u" + ch.charCodeAt(0).toString(16);
-        });
+        var s = "";
+        for (var i = 0, len = str.length; i < len; i++) {
+            if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
+                || is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
+                s += "\\u" + str.charCodeAt(i).toString(16);
+            } else {
+                s += str[i];
+            }
+        }
+        return s;
     };
 
     function make_string(str, quote) {
index 099fc49..f0098c7 100644 (file)
@@ -132,6 +132,18 @@ function is_letter(code) {
         || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
 };
 
+function is_surrogate_pair_head(code) {
+    if (typeof code == "string")
+        code = code.charCodeAt(0);
+    return code >= 0xd800 && code <= 0xdbff;
+}
+
+function is_surrogate_pair_tail(code) {
+    if (typeof code == "string")
+        code = code.charCodeAt(0);
+    return code >= 0xdc00 && code <= 0xdfff;
+}
+
 function is_digit(code) {
     return code >= 48 && code <= 57;
 };
index 4dbc197..c4bd5de 100644 (file)
@@ -55,3 +55,10 @@ issue_2242_4: {
     }
     expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
 }
+
+issue_2569: {
+    input: {
+        new RegExp("[\udc42-\udcaa\udd74-\udd96\ude45-\ude4f\udea3-\udecc]");
+    }
+    expect_exact: 'new RegExp("[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]");'
+}