From c69294c44929d728807bdeabac8a024f108f198b Mon Sep 17 00:00:00 2001 From: Anthony Van de Gejuchte Date: Fri, 20 Feb 2015 16:08:01 +0100 Subject: [PATCH] Implement shebang support --- lib/output.js | 111 +++++++++++++++++++++++++++----------------------- lib/parse.js | 12 +++++- 2 files changed, 69 insertions(+), 54 deletions(-) diff --git a/lib/output.js b/lib/output.js index 396c6a29..3b4c1469 100644 --- a/lib/output.js +++ b/lib/output.js @@ -60,6 +60,7 @@ function OutputStream(options) { bracketize : false, semicolons : true, comments : false, + shebang : true, preserve_line : false, screw_ie8 : false, preamble : null, @@ -403,63 +404,69 @@ function OutputStream(options) { AST_Node.DEFMETHOD("add_comments", function(output){ var c = output.option("comments"), self = this; - if (c) { - var start = self.start; - if (start && !start._comments_dumped) { - start._comments_dumped = true; - var comments = start.comments_before || []; - - // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 - // and https://github.com/mishoo/UglifyJS2/issues/372 - if (self instanceof AST_Exit && self.value) { - self.value.walk(new TreeWalker(function(node){ - if (node.start && node.start.comments_before) { - comments = comments.concat(node.start.comments_before); - node.start.comments_before = []; - } - if (node instanceof AST_Function || - node instanceof AST_Array || - node instanceof AST_Object) - { - return true; // don't go inside. - } - })); - } + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before || []; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // and https://github.com/mishoo/UglifyJS2/issues/372 + if (self instanceof AST_Exit && self.value) { + self.value.walk(new TreeWalker(function(node){ + if (node.start && node.start.comments_before) { + comments = comments.concat(node.start.comments_before); + node.start.comments_before = []; + } + if (node instanceof AST_Function || + node instanceof AST_Array || + node instanceof AST_Object) + { + return true; // don't go inside. + } + })); + } - if (c.test) { - comments = comments.filter(function(comment){ - return c.test(comment.value); - }); - } else if (typeof c == "function") { - comments = comments.filter(function(comment){ - return c(self, comment); - }); - } + if (!c) { + comments = comments.filter(function(comment) { + return comment.type == "comment5"; + }); + } else if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value) || comment.type == "comment5"; + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment) || comment.type == "comment5"; + }); + } - // Keep single line comments after nlb, after nlb - if (!output.option("beautify") && comments.length > 0 && - /comment[134]/.test(comments[0].type) && - output.col() !== 0 && comments[0].nlb) - { - output.print("\n"); - } + // Keep single line comments after nlb, after nlb + if (!output.option("beautify") && comments.length > 0 && + /comment[134]/.test(comments[0].type) && + output.col() !== 0 && comments[0].nlb) + { + output.print("\n"); + } - comments.forEach(function(c){ - if (/comment[134]/.test(c.type)) { - output.print("//" + c.value + "\n"); + comments.forEach(function(c){ + if (/comment[134]/.test(c.type)) { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); output.indent(); + } else { + output.space(); } - else if (c.type == "comment2") { - output.print("/*" + c.value + "*/"); - if (start.nlb) { - output.print("\n"); - output.indent(); - } else { - 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 496a673f..cbfb5757 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -210,7 +210,7 @@ function is_token(token, type, val) { var EX_EOF = {}; -function tokenizer($TEXT, filename, html5_comments) { +function tokenizer($TEXT, filename, html5_comments, shebang) { var S = { text : $TEXT, @@ -568,6 +568,13 @@ function tokenizer($TEXT, filename, html5_comments) { 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"); + } + } parse_error("Unexpected character '" + ch + "'"); }; @@ -637,12 +644,13 @@ function parse($TEXT, options) { expression : false, html5_comments : true, bare_returns : false, + shebang : true, }); var S = { input : (typeof $TEXT == "string" ? tokenizer($TEXT, options.filename, - options.html5_comments) + options.html5_comments, options.shebang) : $TEXT), token : null, prev : null, -- 2.34.1