From eb98a7f2f38f5de16b50560199ee7ec719a1e945 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 5 Mar 2017 12:16:02 +0800 Subject: [PATCH] fix handling of shebang and preamble (#1545) fixes #1332 --- lib/output.js | 38 +++++++++++++++--------------------- lib/parse.js | 12 +++++------- test/mocha/comment-filter.js | 8 ++++++++ 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/output.js b/lib/output.js index 4a0a1e0e..10fed135 100644 --- a/lib/output.js +++ b/lib/output.js @@ -46,17 +46,8 @@ var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/; function is_some_comments(comment) { - var text = comment.value; - var type = comment.type; - if (type == "comment2") { - // multiline comment - return /@preserve|@license|@cc_on/i.test(text); - } - return type == "comment5"; -} - -function is_comment5(comment) { - return comment.type == "comment5"; + // multiline comment + return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value); } function OutputStream(options) { @@ -86,7 +77,7 @@ function OutputStream(options) { }, true); // Convert comment option to RegExp if neccessary and set up comments filter - var comment_filter = options.shebang ? is_comment5 : return_false; // Default case, throw all comments away except shebangs + var comment_filter = return_false; // Default case, throw all comments away if (options.comments) { var comments = options.comments; if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) { @@ -98,12 +89,12 @@ function OutputStream(options) { } if (comments instanceof RegExp) { comment_filter = function(comment) { - return comment.type == "comment5" || comments.test(comment.value); + return comment.type != "comment5" && comments.test(comment.value); }; } else if (typeof comments === "function") { comment_filter = function(comment) { - return comment.type == "comment5" || comments(this, comment); + return comment.type != "comment5" && comments(this, comment); }; } else if (comments === "some") { @@ -400,10 +391,6 @@ function OutputStream(options) { return OUTPUT; }; - if (options.preamble) { - print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n")); - } - var stack = []; return { get : get, @@ -523,6 +510,17 @@ function OutputStream(options) { })); } + if (comments.length > 0 && output.pos() == 0) { + if (output.option("shebang") && comments[0].type == "comment5") { + output.print("#!" + comments.shift().value + "\n"); + output.indent(); + } + var preamble = output.option("preamble"); + if (preamble) { + output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n")); + } + } + comments = comments.filter(output.comment_filter, self); // Keep single line comments after nlb, after nlb @@ -547,10 +545,6 @@ function OutputStream(options) { output.space(); } } - else if (output.pos() === 0 && c.type == "comment5" && output.option("shebang")) { - output.print("#!" + c.value + "\n"); - output.indent(); - } }); } }); diff --git a/lib/parse.js b/lib/parse.js index 9b198ccd..9aadc9f5 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -558,6 +558,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { function next_token(force_regexp) { if (force_regexp != null) return read_regexp(force_regexp); + if (shebang && S.pos == 0 && looking_at("#!")) { + start_token(); + forward(2); + skip_line_comment("comment5"); + } for (;;) { skip_whitespace(); start_token(); @@ -589,13 +594,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) { 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/comment-filter.js b/test/mocha/comment-filter.js index 01580c87..9474e732 100644 --- a/test/mocha/comment-filter.js +++ b/test/mocha/comment-filter.js @@ -72,4 +72,12 @@ describe("comment filters", function() { assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}"); assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}"); }); + + it("Should handle shebang and preamble correctly", function() { + var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", { + fromString: true, + output: { preamble: "/* Build */" } + }).code; + assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;"); + }) }); -- 2.34.1