aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js20
-rw-r--r--test/compress/issue-1261.js118
-rw-r--r--test/mocha/minify.js15
3 files changed, 151 insertions, 2 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 4dfcdcfb..95e9c1b3 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -1360,6 +1360,22 @@ 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, last_comment;
+ if (this.start
+ && (comments = this.start.comments_before)
+ && comments.length
+ && /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) {
+ compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
+ last_comment.value = last_comment.value.replace(/[@#]__PURE__/g, ' ');
+ pure = true;
+ }
+ return this.pure = pure;
+ });
+
// determine if expression has side effects
(function(def){
def(AST_Node, return_true);
@@ -1369,7 +1385,7 @@ merge(Compressor.prototype, {
def(AST_This, return_false);
def(AST_Call, function(compressor){
- if (compressor.pure_funcs(this)) return true;
+ if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true;
for (var i = this.args.length; --i >= 0;) {
if (this.args[i].has_side_effects(compressor))
return true;
@@ -1904,7 +1920,7 @@ merge(Compressor.prototype, {
def(AST_Constant, return_null);
def(AST_This, return_null);
def(AST_Call, function(compressor, first_in_statement){
- if (compressor.pure_funcs(this)) return this;
+ if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return this;
var args = trim(this.args, compressor, first_in_statement);
return args && AST_Seq.from_array(args);
});
diff --git a/test/compress/issue-1261.js b/test/compress/issue-1261.js
new file mode 100644
index 00000000..dfbe2100
--- /dev/null
+++ b/test/compress/issue-1261.js
@@ -0,0 +1,118 @@
+pure_function_calls: {
+ options = {
+ evaluate : true,
+ conditionals : true,
+ comparisons : true,
+ side_effects : true,
+ booleans : true,
+ unused : true,
+ if_return : true,
+ join_vars : true,
+ cascade : true,
+ negate_iife : true,
+ }
+ input: {
+ // pure top-level IIFE will be dropped
+ // @__PURE__ - comment
+ (function() {
+ console.log("iife0");
+ })();
+
+ // pure top-level IIFE assigned to unreferenced var will not be dropped
+ var iife1 = /*@__PURE__*/(function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ })();
+
+ (function(){
+ // pure IIFE in function scope assigned to unreferenced var will be dropped
+ var iife2 = /*#__PURE__*/(function() {
+ console.log("iife2");
+ function iife2() {}
+ return iife2;
+ })();
+ })();
+
+ // comment #__PURE__ comment
+ bar(), baz(), quux();
+ a.b(), /* @__PURE__ */ c.d.e(), f.g();
+ }
+ expect: {
+ var iife1 = function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ }();
+
+ baz(), quux();
+ a.b(), f.g();
+ }
+ expect_warnings: [
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
+ "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
+ ]
+}
+
+pure_function_calls_toplevel: {
+ options = {
+ evaluate : true,
+ conditionals : true,
+ comparisons : true,
+ side_effects : true,
+ booleans : true,
+ unused : true,
+ if_return : true,
+ join_vars : true,
+ cascade : true,
+ negate_iife : true,
+ toplevel : true,
+ }
+ input: {
+ // pure top-level IIFE will be dropped
+ // @__PURE__ - comment
+ (function() {
+ console.log("iife0");
+ })();
+
+ // pure top-level IIFE assigned to unreferenced var will be dropped
+ var iife1 = /*@__PURE__*/(function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ })();
+
+ (function(){
+ // pure IIFE in function scope assigned to unreferenced var will be dropped
+ var iife2 = /*#__PURE__*/(function() {
+ console.log("iife2");
+ function iife2() {}
+ return iife2;
+ })();
+ })();
+
+ // comment #__PURE__ comment
+ bar(), baz(), quux();
+ a.b(), /* @__PURE__ */ c.d.e(), f.g();
+ }
+ expect: {
+ baz(), quux();
+ a.b(), f.g();
+ }
+ expect_warnings: [
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
+ "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
+ "WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
+ ]
+}
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index 70cf73ae..8fe1565f 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -95,4 +95,19 @@ describe("minify", function() {
assert.strictEqual(code, "var a=function(n){return n};");
});
});
+
+ describe("#__PURE__", function() {
+ it("should drop #__PURE__ hint after use", function() {
+ var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
+ fromString: true,
+ output: {
+ comments: "all",
+ beautify: false,
+ }
+ });
+ var code = result.code;
+ assert.strictEqual(code, "// comment1 comment2\nbar();");
+ });
+ });
+
});