From 3a7d53f3cfa81fc8df3cd61c9adf0ce6c28ecd30 Mon Sep 17 00:00:00 2001 From: Anthony Van de Gejuchte Date: Thu, 23 Jun 2016 16:53:48 +0200 Subject: [PATCH] Move OctalEscapeSequence to read_escape_char This should simplify and improve implementation, make it easier to implement template strings, and keep master a bit more in sync with harmony. Previous implementation wasn't broken, though the loop gave me the impression it could read infinite numbers and annoyed me a bit. It was also slightly unnecessary because the lookup involved only 3 characters. --- lib/parse.js | 41 +++++++++++++++------------------ test/compress/string-literal.js | 10 ++++++++ test/mocha/string-literal.js | 2 +- 3 files changed, 30 insertions(+), 23 deletions(-) create mode 100644 test/compress/string-literal.js diff --git a/lib/parse.js b/lib/parse.js index a573234c..c7089b2d 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -365,7 +365,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { case 98 : return "\b"; case 118 : return "\u000b"; // \v case 102 : return "\f"; - case 48 : return "\0"; case 120 : return String.fromCharCode(hex_bytes(2)); // \x case 117 : return String.fromCharCode(hex_bytes(4)); // \u case 10 : return ""; // newline @@ -375,9 +374,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { return ""; } } + if (ch >= "0" && ch <= "7") + return read_octal_escape_sequence(ch); return ch; }; + function read_octal_escape_sequence(ch) { + // Read + var p = peek(); + if (p >= "0" && p <= "7") { + ch += next(true); + if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7") + ch += next(true); + } + + // Parse + if (ch === "0") return "\0"; + if (ch.length > 0 && next_token.has_directive("use strict")) + parse_error("SyntaxError: Octal literals are not allowed in strict mode"); + return String.fromCharCode(parseInt(ch, 8)); + } + function hex_bytes(n) { var num = 0; for (; n > 0; --n) { @@ -393,27 +410,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { var quote = next(), ret = ""; for (;;) { var ch = next(true, true); - if (ch == "\\") { - var octal_len = 0, first = null; - ch = read_while(function(ch){ - if (ch >= "0" && ch <= "7") { - if (!first) { - first = ch; - return ++octal_len; - } - else if (first <= "3" && octal_len <= 2) return ++octal_len; - else if (first >= "4" && octal_len <= 1) return ++octal_len; - } - return false; - }); - if (octal_len > 0) { - if (ch !== "0" && next_token.has_directive("use strict")) - parse_error("Octal literals are not allowed in strict mode"); - ch = String.fromCharCode(parseInt(ch, 8)); - } else { - ch = read_escaped_char(true); - } - } + if (ch == "\\") ch = read_escaped_char(true); else if ("\r\n\u2028\u2029".indexOf(ch) >= 0) parse_error("Unterminated string constant"); else if (ch == quote) break; ret += ch; diff --git a/test/compress/string-literal.js b/test/compress/string-literal.js new file mode 100644 index 00000000..8b93961c --- /dev/null +++ b/test/compress/string-literal.js @@ -0,0 +1,10 @@ +octal_escape_sequence: { + input: { + var boundaries = "\0\7\00\07\70\77\000\077\300\377"; + var border_check = "\400\700\0000\3000"; + } + expect: { + var boundaries = "\x00\x07\x00\x07\x38\x3f\x00\x3f\xc0\xff"; + var border_check = "\x20\x30\x38\x30\x00\x30\xc0\x30"; + } +} diff --git a/test/mocha/string-literal.js b/test/mocha/string-literal.js index ea984213..d427472f 100644 --- a/test/mocha/string-literal.js +++ b/test/mocha/string-literal.js @@ -49,7 +49,7 @@ describe("String literals", function() { var error = function(e) { return e instanceof UglifyJS.JS_Parse_Error && - e.message === "Octal literals are not allowed in strict mode"; + e.message === "SyntaxError: Octal literals are not allowed in strict mode"; } for (var input in inputs) { -- 2.34.1