parse octal literals correctly (#4843)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 6 Apr 2021 18:23:35 +0000 (19:23 +0100)
committerGitHub <noreply@github.com>
Tue, 6 Apr 2021 18:23:35 +0000 (02:23 +0800)
lib/parse.js
test/compress/numbers.js

index 41b61b5..bc13b60 100644 (file)
@@ -351,7 +351,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
 
     function read_while(pred) {
         var ret = "", ch;
-        while ((ch = peek()) && pred(ch)) ret += next();
+        while ((ch = peek()) && pred(ch, ret)) ret += next();
         return ret;
     }
 
@@ -359,24 +359,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
         js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
     }
 
+    function is_octal(num) {
+        return /^0[0-7_]+$/.test(num);
+    }
+
     function read_num(prefix) {
         var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
-        var num = read_while(function(ch) {
-            var code = ch.charCodeAt(0);
-            switch (code) {
-              case 120: case 88: // xX
+        var num = read_while(function(ch, str) {
+            switch (ch) {
+              case "x": case "X":
                 return has_x ? false : (has_x = true);
-              case 101: case 69: // eE
+              case "e": case "E":
                 return has_x ? true : has_e ? false : (has_e = after_e = true);
-              case 43: case 45: // +-
+              case "+": case "-":
                 return after_e;
-              case (after_e = false, 46): // .
-                return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
+              case (after_e = false, "."):
+                return has_dot || has_e || has_x || is_octal(str) ? false : (has_dot = true);
             }
-            return is_digit(code) || /[_0-9a-fo]/i.test(ch);
+            return /[_0-9a-dfo]/i.test(ch);
         });
         if (prefix) num = prefix + num;
-        if (/^0[0-7_]+$/.test(num)) {
+        if (is_octal(num)) {
             if (next_token.has_directive("use strict")) parse_error("Legacy octal literals are not allowed in strict mode");
         } else {
             num = num.replace(has_x ? /([1-9a-f]|.0)_(?=[0-9a-f])/gi : /([1-9]|.0)_(?=[0-9])/gi, "$1");
index dced3f1..124d86c 100644 (file)
@@ -104,6 +104,40 @@ parentheses_for_prototype_functions_galio: {
     expect_stdout: true
 }
 
+octal: {
+    beautify = {
+        beautify: true,
+    }
+    input: {
+        (function() {
+            console.log(052);
+            console.log(-052);
+
+            console.log(018);
+            console.log(-018);
+
+            console.log(052.toFixed(0));
+            console.log(-052.toFixed(0));
+
+            console.log(018..toFixed(0));
+            console.log(-018..toFixed(0));
+        })();
+    }
+    expect_exact: [
+        "(function() {",
+        "    console.log(42);",
+        "    console.log(-42);",
+        "    console.log(18);",
+        "    console.log(-18);",
+        "    console.log(42..toFixed(0));",
+        "    console.log(-42..toFixed(0));",
+        "    console.log(18..toFixed(0));",
+        "    console.log(-18..toFixed(0));",
+        "})();",
+    ]
+    expect_stdout: true
+}
+
 comparisons: {
     options = {
         comparisons: true,