diff --git a/README.md b/README.md index b9dd9fd937..f74281f289 100644 --- a/README.md +++ b/README.md @@ -102,9 +102,9 @@ map embedded in a comment at the bottom. Compile the entire `src` directory and output it to the `lib` directory. $ 6to5 src --out-dir lib - + Compile the entire `src` directory and output it to the one concatenated file. - + $ 6to5 src --out-file script-compiled.js Pipe a file in via stdin and output it to `script-compiled.js` @@ -283,6 +283,23 @@ If you're inheriting from a class then static properties are inherited from it via [\_\_proto\_\_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto), this is widely supported but you may run into problems with much older browsers. +**NOTE:** `__proto__` is not supported on IE <= 9 so static properties +**will not** be inherited. A possible workaround is to use `super();`: + +```javascript +class Foo { + static foo() { + + } +} + +class Bar extends Foo { + static foo() { + super(); + } +} +``` + ### Generators The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) diff --git a/lib/6to5/templates/class-props.js b/lib/6to5/templates/class-props.js new file mode 100644 index 0000000000..2838803875 --- /dev/null +++ b/lib/6to5/templates/class-props.js @@ -0,0 +1,4 @@ +(function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}) diff --git a/lib/6to5/transformers/classes.js b/lib/6to5/transformers/classes.js index b1b90b37ff..6f17d417d3 100644 --- a/lib/6to5/transformers/classes.js +++ b/lib/6to5/transformers/classes.js @@ -107,16 +107,28 @@ var buildClassBody = function (file, construct, body, className, superName, node }, true)); } + var instanceProps; + var staticProps; + if (!_.isEmpty(instanceMutatorMap)) { var protoId = util.template("prototype-identifier", { CLASS_NAME: className }); - body.push(util.buildDefineProperties(instanceMutatorMap, protoId)); + instanceProps = util.buildDefineProperties(instanceMutatorMap, protoId); } if (!_.isEmpty(staticMutatorMap)) { - body.push(util.buildDefineProperties(staticMutatorMap, className)); + staticProps = util.buildDefineProperties(staticMutatorMap, className); + } + + if (instanceProps || staticProps) { + instanceProps = instanceProps || b.literal(null); + staticProps = staticProps || b.literal(null); + + body.push(b.expressionStatement( + b.callExpression(file.addDeclaration("class-props"), [className, staticProps, instanceProps]) + )); } }; diff --git a/lib/6to5/transformers/property-method-assignment.js b/lib/6to5/transformers/property-method-assignment.js index b6e77f23fb..5fbc5dac48 100644 --- a/lib/6to5/transformers/property-method-assignment.js +++ b/lib/6to5/transformers/property-method-assignment.js @@ -24,6 +24,9 @@ exports.ObjectExpression = function (node, parent, file) { return util.template("object-define-properties-closure", { KEY: objId, OBJECT: node, - CONTENT: util.buildDefineProperties(mutatorMap, objId).expression + CONTENT: util.template("object-define-properties", { + OBJECT: objId, + PROPS: util.buildDefineProperties(mutatorMap) + }) }); }; diff --git a/lib/6to5/util.js b/lib/6to5/util.js index 7c35633cf1..49faad6ce7 100644 --- a/lib/6to5/util.js +++ b/lib/6to5/util.js @@ -100,7 +100,7 @@ exports.pushMutatorMap = function (mutatorMap, key, kind, method) { } }; -exports.buildDefineProperties = function (mutatorMap, keyNode) { +exports.buildDefineProperties = function (mutatorMap) { var objExpr = b.objectExpression([]); _.each(mutatorMap, function (map, key) { @@ -117,10 +117,7 @@ exports.buildDefineProperties = function (mutatorMap, keyNode) { objExpr.properties.push(propNode); }); - return exports.template("object-define-properties", { - OBJECT: keyNode, - PROPS: objExpr - }, true); + return objExpr; }; exports.template = function (name, nodes, keepExpression) { diff --git a/test/fixtures/transformation/classes/accessing-super-class/expected.js b/test/fixtures/transformation/classes/accessing-super-class/expected.js index f9fa968043..95530b559d 100644 --- a/test/fixtures/transformation/classes/accessing-super-class/expected.js +++ b/test/fixtures/transformation/classes/accessing-super-class/expected.js @@ -1,5 +1,12 @@ "use strict"; + var _slice = Array.prototype.slice; + +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var _extends = function (child, parent) { child.prototype = Object.create(parent.prototype, { constructor: { @@ -27,7 +34,17 @@ var Test = function(Foo) { _extends(Test, Foo); - Object.defineProperties(Test.prototype, { + _classProps(Test, { + foo: { + writable: true, + + value: function() { + Foo.foo.call(this); + Foo.foo.call.apply(Foo.foo, [this].concat(_slice.call(arguments))); + Foo.foo.call.apply(Foo.foo, [this, "test"].concat(_slice.call(arguments))); + } + } + }, { test: { writable: true, @@ -39,17 +56,5 @@ var Test = function(Foo) { } }); - Object.defineProperties(Test, { - foo: { - writable: true, - - value: function() { - Foo.foo.call(this); - Foo.foo.call.apply(Foo.foo, [this].concat(_slice.call(arguments))); - Foo.foo.call.apply(Foo.foo, [this, "test"].concat(_slice.call(arguments))); - } - } - }); - return Test; }(Foo); diff --git a/test/fixtures/transformation/classes/calling-super-properties/expected.js b/test/fixtures/transformation/classes/calling-super-properties/expected.js index 5bbc5432d7..80824f88ae 100644 --- a/test/fixtures/transformation/classes/calling-super-properties/expected.js +++ b/test/fixtures/transformation/classes/calling-super-properties/expected.js @@ -1,5 +1,10 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var _extends = function (child, parent) { child.prototype = Object.create(parent.prototype, { constructor: { @@ -13,7 +18,6 @@ var _extends = function (child, parent) { child.__proto__ = parent; }; - var Test = function(Foo) { var Test = function Test() { Foo.prototype.test.whatever(); @@ -22,7 +26,7 @@ var Test = function(Foo) { _extends(Test, Foo); - Object.defineProperties(Test, { + _classProps(Test, { test: { writable: true, @@ -30,7 +34,7 @@ var Test = function(Foo) { return Foo.wow.call(this); } } - }); + }, null); return Test; }(Foo); diff --git a/test/fixtures/transformation/classes/instance-getter-and-setter/expected.js b/test/fixtures/transformation/classes/instance-getter-and-setter/expected.js index 9a769db762..5ab8570499 100644 --- a/test/fixtures/transformation/classes/instance-getter-and-setter/expected.js +++ b/test/fixtures/transformation/classes/instance-getter-and-setter/expected.js @@ -1,9 +1,14 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var Test = function() { var Test = function Test() {}; - Object.defineProperties(Test.prototype, { + _classProps(Test, null, { test: { get: function() { return 5 + 5; @@ -16,4 +21,4 @@ var Test = function() { }); return Test; -}(); \ No newline at end of file +}(); diff --git a/test/fixtures/transformation/classes/instance-getter/expected.js b/test/fixtures/transformation/classes/instance-getter/expected.js index 079333bb38..60aaf32f08 100644 --- a/test/fixtures/transformation/classes/instance-getter/expected.js +++ b/test/fixtures/transformation/classes/instance-getter/expected.js @@ -1,9 +1,14 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var Test = function() { var Test = function Test() {}; - Object.defineProperties(Test.prototype, { + _classProps(Test, null, { test: { get: function() { return 5 + 5; @@ -12,4 +17,4 @@ var Test = function() { }); return Test; -}(); \ No newline at end of file +}(); diff --git a/test/fixtures/transformation/classes/instance-method/expected.js b/test/fixtures/transformation/classes/instance-method/expected.js index 6c969044fb..50442620fa 100644 --- a/test/fixtures/transformation/classes/instance-method/expected.js +++ b/test/fixtures/transformation/classes/instance-method/expected.js @@ -1,9 +1,14 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var Test = function() { var Test = function Test() {}; - Object.defineProperties(Test.prototype, { + _classProps(Test, null, { test: { writable: true, @@ -14,4 +19,4 @@ var Test = function() { }); return Test; -}(); \ No newline at end of file +}(); diff --git a/test/fixtures/transformation/classes/instance-setter/expected.js b/test/fixtures/transformation/classes/instance-setter/expected.js index a1e757f281..fb1e58c8eb 100644 --- a/test/fixtures/transformation/classes/instance-setter/expected.js +++ b/test/fixtures/transformation/classes/instance-setter/expected.js @@ -1,9 +1,14 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var Test = function() { var Test = function Test() {}; - Object.defineProperties(Test.prototype, { + _classProps(Test, null, { test: { set: function(val) { this._test = val; @@ -12,4 +17,4 @@ var Test = function() { }); return Test; -}(); \ No newline at end of file +}(); diff --git a/test/fixtures/transformation/classes/static/expected.js b/test/fixtures/transformation/classes/static/expected.js index 75abf10471..52724c0c1b 100644 --- a/test/fixtures/transformation/classes/static/expected.js +++ b/test/fixtures/transformation/classes/static/expected.js @@ -1,9 +1,14 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; + var A = function() { var A = function A() {}; - Object.defineProperties(A, { + _classProps(A, { a: { writable: true, value: function() {} @@ -13,7 +18,7 @@ var A = function() { get: function() {}, set: function(b) {} } - }); + }, null); return A; -}(); \ No newline at end of file +}(); diff --git a/test/fixtures/transformation/source-maps/class/expected.js b/test/fixtures/transformation/source-maps/class/expected.js index c250bea2cb..0706f1a8d6 100644 --- a/test/fixtures/transformation/source-maps/class/expected.js +++ b/test/fixtures/transformation/source-maps/class/expected.js @@ -1,7 +1,11 @@ "use strict"; +var _classProps = function (child, staticProps, instanceProps) { + if (staticProps) Object.defineProperties(child, staticProps); + if (instanceProps) Object.defineProperties(child.prototype, instanceProps); +}; var Test = (function () { var Test = function Test() {}; - Object.defineProperties(Test.prototype, { bar: { get: function () { + _classProps(Test, null, { bar: { get: function () { throw new Error("wow"); } } }); return Test; diff --git a/test/fixtures/transformation/source-maps/class/source-mappings.json b/test/fixtures/transformation/source-maps/class/source-mappings.json index 4a222cd380..9632b0c4eb 100644 --- a/test/fixtures/transformation/source-maps/class/source-mappings.json +++ b/test/fixtures/transformation/source-maps/class/source-mappings.json @@ -4,7 +4,7 @@ "column": 11 }, "generated": { - "line": 5, + "line": 9, "column": 11 } }]