Parse comments without recursion to avoid RangeError.

Fixes #993
This commit is contained in:
kzc
2016-04-15 19:58:46 -04:00
parent 4b4528ee05
commit e4fa4b109a
2 changed files with 57 additions and 29 deletions

View File

@@ -421,7 +421,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
S.col = S.tokcol + (S.pos - S.tokpos); S.col = S.tokcol + (S.pos - S.tokpos);
S.comments_before.push(token(type, ret, true)); S.comments_before.push(token(type, ret, true));
S.regex_allowed = regex_allowed; S.regex_allowed = regex_allowed;
return next_token(); return next_token;
}; };
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ 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.comments_before.push(token("comment2", text, true));
S.regex_allowed = regex_allowed; S.regex_allowed = regex_allowed;
S.newline_before = nlb; S.newline_before = nlb;
return next_token(); return next_token;
}); });
function read_name() { function read_name() {
@@ -548,36 +548,45 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
function next_token(force_regexp) { function next_token(force_regexp) {
if (force_regexp != null) if (force_regexp != null)
return read_regexp(force_regexp); return read_regexp(force_regexp);
skip_whitespace(); for (;;) {
start_token(); skip_whitespace();
if (html5_comments) { start_token();
if (looking_at("<!--")) { if (html5_comments) {
forward(4); if (looking_at("<!--")) {
return skip_line_comment("comment3"); forward(4);
skip_line_comment("comment3");
continue;
}
if (looking_at("-->") && S.newline_before) {
forward(3);
skip_line_comment("comment4");
continue;
}
} }
if (looking_at("-->") && S.newline_before) { var ch = peek();
forward(3); if (!ch) return token("eof");
return skip_line_comment("comment4"); 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;
}
} }
} if (is_digit(code)) return read_num();
var ch = peek(); if (PUNC_CHARS(ch)) return token("punc", next());
if (!ch) return token("eof"); if (OPERATOR_CHARS(ch)) return read_operator();
var code = ch.charCodeAt(0); if (code == 92 || is_identifier_start(code)) return read_word();
switch (code) { if (shebang) {
case 34: case 39: return read_string(ch); if (S.pos == 0 && looking_at("#!")) {
case 46: return handle_dot(); forward(2);
case 47: return handle_slash(); skip_line_comment("comment5");
} continue;
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");
} }
break;
} }
parse_error("Unexpected character '" + ch + "'"); parse_error("Unexpected character '" + ch + "'");
}; };

View File

@@ -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}");
});
});