From e4fa4b109a0db5691d91b3dfba0eac41ac21c0ef Mon Sep 17 00:00:00 2001 From: kzc Date: Fri, 15 Apr 2016 19:58:46 -0400 Subject: [PATCH] Parse comments without recursion to avoid RangeError. Fixes #993 --- lib/parse.js | 67 +++++++++++++++------------ test/mocha/huge-number-of-comments.js | 19 ++++++++ 2 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 test/mocha/huge-number-of-comments.js diff --git a/lib/parse.js b/lib/parse.js index f16d092b..18d071f3 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -421,7 +421,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { S.col = S.tokcol + (S.pos - S.tokpos); S.comments_before.push(token(type, ret, true)); S.regex_allowed = regex_allowed; - return next_token(); + return next_token; }; var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ @@ -439,7 +439,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { S.comments_before.push(token("comment2", text, true)); S.regex_allowed = regex_allowed; S.newline_before = nlb; - return next_token(); + return next_token; }); function read_name() { @@ -548,36 +548,45 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { function next_token(force_regexp) { if (force_regexp != null) return read_regexp(force_regexp); - skip_whitespace(); - start_token(); - if (html5_comments) { - if (looking_at("") && S.newline_before) { + forward(3); + skip_line_comment("comment4"); + continue; + } } - if (looking_at("-->") && S.newline_before) { - forward(3); - return skip_line_comment("comment4"); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(ch); + case 46: return handle_dot(); + case 47: { + var tok = handle_slash(); + if (tok === next_token) continue; + return tok; + } } - } - var ch = peek(); - if (!ch) return token("eof"); - var code = ch.charCodeAt(0); - switch (code) { - case 34: case 39: return read_string(ch); - case 46: return handle_dot(); - case 47: return handle_slash(); - } - if (is_digit(code)) return read_num(); - if (PUNC_CHARS(ch)) return token("punc", next()); - if (OPERATOR_CHARS(ch)) return read_operator(); - if (code == 92 || is_identifier_start(code)) return read_word(); - - if (shebang) { - if (S.pos == 0 && looking_at("#!")) { - forward(2); - return skip_line_comment("comment5"); + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + if (shebang) { + if (S.pos == 0 && looking_at("#!")) { + forward(2); + skip_line_comment("comment5"); + continue; + } } + break; } parse_error("Unexpected character '" + ch + "'"); }; diff --git a/test/mocha/huge-number-of-comments.js b/test/mocha/huge-number-of-comments.js new file mode 100644 index 00000000..3b90bc0e --- /dev/null +++ b/test/mocha/huge-number-of-comments.js @@ -0,0 +1,19 @@ +var Uglify = require('../../'); +var assert = require("assert"); + +describe("Huge number of comments.", function() { + it("Should parse and compress code with thousands of consecutive comments", function() { + var js = 'function lots_of_comments(x) { return 7 -'; + var i; + for (i = 1; i <= 5000; ++i) { js += "// " + i + "\n"; } + for (; i <= 10000; ++i) { js += "/* " + i + " */ /**/"; } + js += "x; }"; + var result = Uglify.minify(js, { + fromString: true, + mangle: false, + compress: {} + }); + assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}"); + }); +}); + -- 2.34.1