Repository: Rich-Harris/buble (js)

Issue:
Pure annotation for class tree-shaking
Inherited classes are transpiled to IIFE:

```
var Circle = (function (Shape) {
  function Circle () {
    Shape.apply(this, arguments);
  }if ( Shape ) Circle.__proto__ = Shape;
  Circle.prototype = Object.create( Shape && Shape.prototype );
  Circle.prototype.constructor = Circle;
  return Circle;
}(Shape));
```
IIFEs are considered side-effects, this prevents them from being dropped by a minifier when a class is unused.

This problem has been addressed in babel/babel#5632, the solution is to add `/*@__PURE__*/` comment annotation to transpiled class IIFE, so it could be properly interpreted by minifiers, namely UglifyJS and Terser:
```
var Circle = /*@__PURE__*/(function (Shape) {
/* ... */
}(Shape));
```

Pull request:
Class pure annotation
Adds `/*@__PURE__*/` annotation to class IIFEs to enable dead code removal in Uglify and Terser.
Closes #156 

Patch:
diff --git a/src/program/types/ClassDeclaration.js b/src/program/types/ClassDeclaration.js
index d3563b8..e3b2c67 100644
--- a/src/program/types/ClassDeclaration.js
+++ b/src/program/types/ClassDeclaration.js
@@ -42,13 +42,13 @@ export default class ClassDeclaration extends Node {
 			if (this.superClass) {
 				if (this.superClass.end === this.body.start) {
 					code.remove(c, this.superClass.start);
-					code.appendLeft(c, ` = (function (${superName}) {\n${i1}`);
+					code.appendLeft(c, ` = /*@__PURE__*/(function (${superName}) {\n${i1}`);
 				} else {
 					code.overwrite(c, this.superClass.start, ' = ');
 					code.overwrite(
 						this.superClass.end,
 						this.body.start,
-						`(function (${superName}) {\n${i1}`
+						`/*@__PURE__*/(function (${superName}) {\n${i1}`
 					);
 				}
 			} else {
diff --git a/src/program/types/ClassExpression.js b/src/program/types/ClassExpression.js
index 5c1f5f5..acade69 100644
--- a/src/program/types/ClassExpression.js
+++ b/src/program/types/ClassExpression.js
@@ -28,9 +28,9 @@ export default class ClassExpression extends Node {
 			if (this.superClass) {
 				code.remove(this.start, this.superClass.start);
 				code.remove(this.superClass.end, this.body.start);
-				code.appendLeft(this.start, `(function (${superName}) {\n${i1}`);
+				code.appendLeft(this.start, `/*@__PURE__*/(function (${superName}) {\n${i1}`);
 			} else {
-				code.overwrite(this.start, this.body.start, `(function () {\n${i1}`);
+				code.overwrite(this.start, this.body.start, `/*@__PURE__*/(function () {\n${i1}`);
 			}
 
 			this.body.transpile(code, transforms, true, superName);


Test patch:
diff --git a/test/samples/block-scoping.js b/test/samples/block-scoping.js
index 3600425..6a3f859 100644
--- a/test/samples/block-scoping.js
+++ b/test/samples/block-scoping.js
@@ -313,7 +313,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var bar = (function () {
+			var bar = /*@__PURE__*/(function () {
 				function foo () {}
 
 				return foo;
diff --git a/test/samples/classes-no-named-function-expressions.js b/test/samples/classes-no-named-function-expressions.js
index b3be24c..0cc7fd3 100644
--- a/test/samples/classes-no-named-function-expressions.js
+++ b/test/samples/classes-no-named-function-expressions.js
@@ -123,7 +123,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -157,7 +157,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo ( x ) {
 					Bar.call( this, x );
 					this.y = 'z';
@@ -196,7 +196,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -268,7 +268,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -300,7 +300,7 @@ module.exports = [
 			new Foo().bar();`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -335,7 +335,7 @@ module.exports = [
 			var Foo = class {};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo () {}
 
 				return Foo;
@@ -354,7 +354,7 @@ module.exports = [
 			};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo ( x ) {
 					this.x = x;
 				}
@@ -376,7 +376,7 @@ module.exports = [
 			};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo () {}
 
 				Foo.prototype.bar = function ( x ) {
@@ -517,7 +517,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Circle = (function (Shape) {
+			var Circle = /*@__PURE__*/(function (Shape) {
 				function Circle ( radius ) {
 					Shape.call(this);
 					this.radius = radius;
@@ -585,13 +585,13 @@ module.exports = [
 			}`,
 
 		output: `
-			var q = {a: (function () {
+			var q = {a: /*@__PURE__*/(function () {
 				function anonymous () {}
 
 				return anonymous;
 			}())};
 
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b () {
 					superclass.apply(this, arguments);
 				}
@@ -618,13 +618,13 @@ module.exports = [
 			};`,
 
 		output: `
-			var q = {a: (function () {
+			var q = {a: /*@__PURE__*/(function () {
 				function anonymous () {}
 
 				return anonymous;
 			}())};
 
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b () {
 					superclass.apply(this, arguments);
 				}
@@ -651,7 +651,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b() {
 					superclass.call(this);
 				}
@@ -676,7 +676,7 @@ module.exports = [
 			};`,
 
 		output: `
-			SubClass = (function (SuperClass) {
+			SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					SuperClass.call(this);
 				}
@@ -751,7 +751,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -794,7 +794,7 @@ module.exports = [
 
 			A.prototype.x = function (){};
 
-			var B = (function () {
+			var B = /*@__PURE__*/(function () {
 				function B () {}
 
 				B.prototype.x = function (){};
@@ -802,7 +802,7 @@ module.exports = [
 				return B;
 			}());
 
-			var C = (function (D) {
+			var C = /*@__PURE__*/(function (D) {
 				function C () {
 					D.apply(this, arguments);
 				}
@@ -816,7 +816,7 @@ module.exports = [
 				return C;
 			}(D));
 
-			var E = (function (F) {
+			var E = /*@__PURE__*/(function (F) {
 				function E () {
 					F.apply(this, arguments);
 				}
@@ -921,7 +921,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo ( options, ref ) {
 					var this$1 = this;
 					var a2 = ref.a2;
@@ -964,7 +964,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var SubClass = (function (SuperClass) {
+			var SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					var args = [], len = arguments.length;
 					while ( len-- ) args[ len ] = arguments[ len ];
@@ -992,7 +992,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var SubClass = (function (SuperClass) {
+			var SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					var args = [], len = arguments.length;
 					while ( len-- ) args[ len ] = arguments[ len ];
@@ -1125,7 +1125,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var A = (function (B) {
+			var A = /*@__PURE__*/(function (B) {
 				function A () {
 					var this$1 = this;
 
diff --git a/test/samples/classes.js b/test/samples/classes.js
index 704de9b..59fc2ca 100644
--- a/test/samples/classes.js
+++ b/test/samples/classes.js
@@ -117,7 +117,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -150,7 +150,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo ( x ) {
 					Bar.call( this, x );
 					this.y = 'z';
@@ -188,7 +188,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -254,7 +254,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -283,7 +283,7 @@ module.exports = [
 			new Foo().bar();`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -316,7 +316,7 @@ module.exports = [
 			var Foo = class {};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo () {}
 
 				return Foo;
@@ -334,7 +334,7 @@ module.exports = [
 			};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo ( x ) {
 					this.x = x;
 				}
@@ -355,7 +355,7 @@ module.exports = [
 			};`,
 
 		output: `
-			var Foo = (function () {
+			var Foo = /*@__PURE__*/(function () {
 				function Foo () {}
 
 				Foo.prototype.bar = function bar ( x ) {
@@ -380,7 +380,7 @@ module.exports = [
 		output: `
 			var q = {};
 
-			q.a = (function () {
+			q.a = /*@__PURE__*/(function () {
 				function a () {}
 
 				a.prototype.c = function c () {};
@@ -515,7 +515,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Circle = (function (Shape) {
+			var Circle = /*@__PURE__*/(function (Shape) {
 				function Circle ( radius ) {
 					Shape.call(this);
 					this.radius = radius;
@@ -579,13 +579,13 @@ module.exports = [
 			}`,
 
 		output: `
-			var q = {a: (function () {
+			var q = {a: /*@__PURE__*/(function () {
 				function anonymous () {}
 
 				return anonymous;
 			}())};
 
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b () {
 					superclass.apply(this, arguments);
 				}
@@ -611,13 +611,13 @@ module.exports = [
 			};`,
 
 		output: `
-			var q = {a: (function () {
+			var q = {a: /*@__PURE__*/(function () {
 				function anonymous () {}
 
 				return anonymous;
 			}())};
 
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b () {
 					superclass.apply(this, arguments);
 				}
@@ -643,7 +643,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var b = (function (superclass) {
+			var b = /*@__PURE__*/(function (superclass) {
 				function b() {
 					superclass.call(this);
 				}
@@ -667,7 +667,7 @@ module.exports = [
 			};`,
 
 		output: `
-			SubClass = (function (SuperClass) {
+			SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					SuperClass.call(this);
 				}
@@ -739,7 +739,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo () {
 					Bar.apply(this, arguments);
 				}
@@ -781,7 +781,7 @@ module.exports = [
 
 			A.prototype.x = function x (){};
 
-			var B = (function () {
+			var B = /*@__PURE__*/(function () {
 				function B () {}
 
 				B.prototype.x = function x (){};
@@ -789,7 +789,7 @@ module.exports = [
 				return B;
 			}());
 
-			var C = (function (D) {
+			var C = /*@__PURE__*/(function (D) {
 				function C () {
 					D.apply(this, arguments);
 				}
@@ -803,7 +803,7 @@ module.exports = [
 				return C;
 			}(D));
 
-			var E = (function (F) {
+			var E = /*@__PURE__*/(function (F) {
 				function E () {
 					F.apply(this, arguments);
 				}
@@ -905,7 +905,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var Foo = (function (Bar) {
+			var Foo = /*@__PURE__*/(function (Bar) {
 				function Foo ( options, ref ) {
 					var this$1 = this;
 					var a2 = ref.a2;
@@ -947,7 +947,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var SubClass = (function (SuperClass) {
+			var SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					var args = [], len = arguments.length;
 					while ( len-- ) args[ len ] = arguments[ len ];
@@ -974,7 +974,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var SubClass = (function (SuperClass) {
+			var SubClass = /*@__PURE__*/(function (SuperClass) {
 				function SubClass() {
 					var args = [], len = arguments.length;
 					while ( len-- ) args[ len ] = arguments[ len ];
@@ -1101,7 +1101,7 @@ module.exports = [
 			}`,
 
 		output: `
-			var A = (function (B) {
+			var A = /*@__PURE__*/(function (B) {
 				function A () {
 					var this$1 = this;
 
diff --git a/test/samples/misc.js b/test/samples/misc.js
index 5900ffd..b526386 100644
--- a/test/samples/misc.js
+++ b/test/samples/misc.js
@@ -150,7 +150,7 @@ module.exports = [
 				return foo * baz$1 - baz$1 * bar;
 			};
 
-			var a = (function () {
+			var a = /*@__PURE__*/(function () {
 				function Bar () {}
 
 				Bar.prototype.b = function b (a, b$3, c) {
@@ -160,7 +160,7 @@ module.exports = [
 				return Bar;
 			}());
 
-			var b = (function () {
+			var b = /*@__PURE__*/(function () {
 				function b () {}
 
 				b.prototype.b = function b (a, b$1, c) {