fix comments output & improve /*@__PURE__*/

- fix whitespace around comments
- fix comment parsing around parentheses
- consider parentheses when parsing `/*@__PURE__*/`
- remove all `/*@__PURE__*/` on output

fixes #2638
This commit is contained in:
Alex Lam S.L
2017-12-24 12:38:45 +08:00
committed by GitHub
parent 202f90ef8f
commit efffb81735
5 changed files with 116 additions and 47 deletions

View File

@@ -2292,29 +2292,13 @@ merge(Compressor.prototype, {
}); });
}); });
AST_Call.DEFMETHOD("has_pure_annotation", function(compressor) {
if (!compressor.option("side_effects")) return false;
if (this.pure !== undefined) return this.pure;
var pure = false;
var comments, pure_comment;
if (this.start
&& (comments = this.start.comments_before)
&& comments.length
&& (pure_comment = find_if(function (comment) {
return /[@#]__PURE__/.test(comment.value);
}, comments))) {
pure = pure_comment;
}
return this.pure = pure;
});
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError"); var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
AST_Call.DEFMETHOD("is_expr_pure", function(compressor) { AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
if (compressor.option("unsafe")) { if (compressor.option("unsafe")) {
var expr = this.expression; var expr = this.expression;
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true; if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
} }
return this.has_pure_annotation(compressor) || !compressor.pure_funcs(this); return this.pure || !compressor.pure_funcs(this);
}); });
// determine if expression has side effects // determine if expression has side effects
@@ -3164,7 +3148,6 @@ merge(Compressor.prototype, {
} }
if (this.pure) { if (this.pure) {
compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start); compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
this.pure.value = this.pure.value.replace(/[@#]__PURE__/g, ' ');
} }
var args = trim(this.args, compressor, first_in_statement); var args = trim(this.args, compressor, first_in_statement);
return args && make_sequence(this, args); return args && make_sequence(this, args);
@@ -3961,7 +3944,7 @@ merge(Compressor.prototype, {
&& (def = exp.definition()).references.length == 1 && (def = exp.definition()).references.length == 1
&& !recursive_ref(compressor, def) && !recursive_ref(compressor, def)
&& fn.is_constant_expression(exp.scope)) && fn.is_constant_expression(exp.scope))
&& !self.has_pure_annotation(compressor) && !self.pure
&& !fn.contains_this() && !fn.contains_this()
&& (scope = can_flatten_args(fn)) && (scope = can_flatten_args(fn))
&& (value = flatten_body(stat))) { && (value = flatten_body(stat))) {

View File

@@ -201,6 +201,8 @@ function OutputStream(options) {
var might_need_semicolon = false; var might_need_semicolon = false;
var might_add_newline = 0; var might_add_newline = 0;
var need_newline_indented = false; var need_newline_indented = false;
var need_space = false;
var newline_insert = -1;
var last = ""; var last = "";
var mapping_token, mapping_name, mappings = options.source_map && []; var mapping_token, mapping_name, mappings = options.source_map && [];
@@ -266,6 +268,13 @@ function OutputStream(options) {
indent(); indent();
} }
} }
if (need_space && ch) {
need_space = false;
if (!/[\s;})]/.test(ch)) {
space();
}
}
newline_insert = -1;
var prev = last.charAt(last.length - 1); var prev = last.charAt(last.length - 1);
if (might_need_semicolon) { if (might_need_semicolon) {
might_need_semicolon = false; might_need_semicolon = false;
@@ -364,7 +373,13 @@ function OutputStream(options) {
} : function(col, cont) { return cont() }; } : function(col, cont) { return cont() };
var newline = options.beautify ? function() { var newline = options.beautify ? function() {
print("\n"); if (newline_insert < 0) return print("\n");
if (OUTPUT[newline_insert] != "\n") {
OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
current_pos++;
current_line++;
}
newline_insert++;
} : options.max_line_len ? function() { } : options.max_line_len ? function() {
ensure_line_len(); ensure_line_len();
might_add_newline = OUTPUT.length; might_add_newline = OUTPUT.length;
@@ -495,11 +510,11 @@ function OutputStream(options) {
} }
} }
if (/comment[134]/.test(c.type)) { if (/comment[134]/.test(c.type)) {
print("//" + c.value + "\n"); print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
indent(); indent();
last_nlb = true; last_nlb = true;
} else if (c.type == "comment2") { } else if (c.type == "comment2") {
print("/*" + c.value + "*/"); print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
last_nlb = false; last_nlb = false;
} }
}); });
@@ -521,21 +536,28 @@ function OutputStream(options) {
var comments = token[tail ? "comments_before" : "comments_after"]; var comments = token[tail ? "comments_before" : "comments_after"];
if (comments && comments._dumped !== self) { if (comments && comments._dumped !== self) {
comments._dumped = self; comments._dumped = self;
var insert = OUTPUT.length;
comments.filter(comment_filter, node).forEach(function(c, i) { comments.filter(comment_filter, node).forEach(function(c, i) {
if (need_newline_indented || c.nlb) { need_space = false;
if (need_newline_indented) {
print("\n"); print("\n");
indent(); indent();
need_newline_indented = false; need_newline_indented = false;
} else if (c.nlb && (i > 0 || !/(^|\n) *$/.test(OUTPUT))) {
print("\n");
indent();
} else if (i > 0 || !tail) { } else if (i > 0 || !tail) {
space(); space();
} }
if (/comment[134]/.test(c.type)) { if (/comment[134]/.test(c.type)) {
print("//" + c.value); print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
need_newline_indented = true; need_newline_indented = true;
} else if (c.type == "comment2") { } else if (c.type == "comment2") {
print("/*" + c.value + "*/"); print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
need_space = true;
} }
}); });
if (OUTPUT.length > insert) newline_insert = insert;
} }
} }

View File

@@ -1276,8 +1276,17 @@ function parse($TEXT, options) {
case "(": case "(":
next(); next();
var ex = expression(true); var ex = expression(true);
[].push.apply(start.comments_before, ex.start.comments_before); var len = start.comments_before.length;
ex.start.comments_before = start.comments_before; [].unshift.apply(ex.start.comments_before, start.comments_before);
start.comments_before = ex.start.comments_before;
start.comments_before_length = len;
if (len == 0 && start.comments_before.length > 0) {
var comment = start.comments_before[0];
if (!comment.nlb) {
comment.nlb = start.nlb;
start.nlb = false;
}
}
start.comments_after = ex.start.comments_after; start.comments_after = ex.start.comments_after;
ex.start = start; ex.start = start;
expect(")"); expect(")");
@@ -1286,6 +1295,7 @@ function parse($TEXT, options) {
[].push.apply(ex.end.comments_after, end.comments_after); [].push.apply(ex.end.comments_after, end.comments_after);
end.comments_after = ex.end.comments_after; end.comments_after = ex.end.comments_after;
ex.end = end; ex.end = end;
if (ex instanceof AST_Call) mark_pure(ex);
return subscripts(ex, allow_calls); return subscripts(ex, allow_calls);
case "[": case "[":
return subscripts(array_(), allow_calls); return subscripts(array_(), allow_calls);
@@ -1433,6 +1443,19 @@ function parse($TEXT, options) {
return sym; return sym;
}; };
function mark_pure(call) {
var start = call.start;
var comments = start.comments_before;
var i = HOP(start, "comments_before_length") ? start.comments_before_length : comments.length;
while (--i >= 0) {
var comment = comments[i];
if (/[@#]__PURE__/.test(comment.value)) {
call.pure = comment;
break;
}
}
}
var subscripts = function(expr, allow_calls) { var subscripts = function(expr, allow_calls) {
var start = expr.start; var start = expr.start;
if (is("punc", ".")) { if (is("punc", ".")) {
@@ -1457,12 +1480,14 @@ function parse($TEXT, options) {
} }
if (allow_calls && is("punc", "(")) { if (allow_calls && is("punc", "(")) {
next(); next();
return subscripts(new AST_Call({ var call = new AST_Call({
start : start, start : start,
expression : expr, expression : expr,
args : expr_list(")"), args : expr_list(")"),
end : prev() end : prev()
}), true); });
mark_pure(call);
return subscripts(call, true);
} }
return expr; return expr;
}; };

View File

@@ -298,19 +298,27 @@ issue_2629_1: {
options = { options = {
side_effects: true, side_effects: true,
} }
beautify = {
comments: "all",
}
input: { input: {
/*@__PURE__*/ a(); /*@__PURE__*/ a();
/*@__PURE__*/ (b()); /*@__PURE__*/ (b());
(/*@__PURE__*/ c)(); (/*@__PURE__*/ c)();
(/*@__PURE__*/ d()); (/*@__PURE__*/ d());
} }
expect: {} expect_exact: [
"/* */c();",
]
} }
issue_2629_2: { issue_2629_2: {
options = { options = {
side_effects: true, side_effects: true,
} }
beautify = {
comments: "all",
}
input: { input: {
/*@__PURE__*/ a(1)(2)(3); /*@__PURE__*/ a(1)(2)(3);
/*@__PURE__*/ (b(1))(2)(3); /*@__PURE__*/ (b(1))(2)(3);
@@ -321,30 +329,44 @@ issue_2629_2: {
(/*@__PURE__*/ g(1)(2))(3); (/*@__PURE__*/ g(1)(2))(3);
(/*@__PURE__*/ h(1)(2)(3)); (/*@__PURE__*/ h(1)(2)(3));
} }
expect: {} expect_exact: [
"/* */e(1)(2)(3);",
"/* */f(1)(2)(3);",
"/* */g(1)(2)(3);",
]
} }
issue_2629_3: { issue_2629_3: {
options = { options = {
side_effects: true, side_effects: true,
} }
beautify = {
comments: "all",
}
input: { input: {
/*@__PURE__*/ a.x(1).y(2).z(3); /*@__PURE__*/ a.x(1).y(2).z(3);
/*@__PURE__*/ (a.x)(1).y(2).z(3); /*@__PURE__*/ (b.x)(1).y(2).z(3);
/*@__PURE__*/ (a.x(1)).y(2).z(3); /*@__PURE__*/ (c.x(1)).y(2).z(3);
/*@__PURE__*/ (a.x(1).y)(2).z(3); /*@__PURE__*/ (d.x(1).y)(2).z(3);
/*@__PURE__*/ (a.x(1).y(2)).z(3); /*@__PURE__*/ (e.x(1).y(2)).z(3);
/*@__PURE__*/ (a.x(1).y(2).z)(3); /*@__PURE__*/ (f.x(1).y(2).z)(3);
/*@__PURE__*/ (a.x(1).y(2).z(3)); /*@__PURE__*/ (g.x(1).y(2).z(3));
(/*@__PURE__*/ a).x(1).y(2).z(3); (/*@__PURE__*/ h).x(1).y(2).z(3);
(/*@__PURE__*/ a.x)(1).y(2).z(3); (/*@__PURE__*/ i.x)(1).y(2).z(3);
(/*@__PURE__*/ a.x(1)).y(2).z(3); (/*@__PURE__*/ j.x(1)).y(2).z(3);
(/*@__PURE__*/ a.x(1).y)(2).z(3); (/*@__PURE__*/ k.x(1).y)(2).z(3);
(/*@__PURE__*/ a.x(1).y(2)).z(3); (/*@__PURE__*/ l.x(1).y(2)).z(3);
(/*@__PURE__*/ a.x(1).y(2).z)(3); (/*@__PURE__*/ m.x(1).y(2).z)(3);
(/*@__PURE__*/ a.x(1).y(2).z(3)); (/*@__PURE__*/ n.x(1).y(2).z(3));
} }
expect: {} expect_exact: [
"/* */h.x(1).y(2).z(3);",
"/* */i.x(1).y(2).z(3);",
"/* */j.x(1).y(2).z(3);",
"/* */k.x(1).y(2).z(3);",
"/* */l.x(1).y(2).z(3);",
"/* */m.x(1).y(2).z(3);",
]
} }
issue_2629_4: { issue_2629_4: {
@@ -375,3 +397,20 @@ issue_2629_5: {
w(), y(); w(), y();
} }
} }
issue_2638: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/(g() || h())(x(), y());
(/*@__PURE__*/ (a() || b()))(c(), d());
}
expect_exact: [
"/* */x(),y();",
"/* */(a()||b())(c(),d());",
]
}

View File

@@ -247,7 +247,7 @@ describe("minify", function() {
var code = result.code; var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
}); });
it("should not drop #__PURE__ hint if function is retained", function() { it("should drop #__PURE__ hint if function is retained", function() {
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", { var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: { output: {
comments: "all", comments: "all",
@@ -255,7 +255,7 @@ describe("minify", function() {
} }
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=/*#__PURE__*/function(){foo()}();"); assert.strictEqual(code, "var a=/* */function(){foo()}();");
}) })
}); });