diff --git a/lib/6to5/file.js b/lib/6to5/file.js index cd2d34a6ac..59ec12ef3f 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -183,6 +183,7 @@ File.prototype.buildTransformers = function () { if (pass.canRun(file)) { stack.push(pass); + if (transformer.secondPass) { secondaryStack.push(pass); } diff --git a/lib/6to5/transformation/helpers/replace-supers.js b/lib/6to5/transformation/helpers/replace-supers.js index 12d894d764..0931e52e64 100644 --- a/lib/6to5/transformation/helpers/replace-supers.js +++ b/lib/6to5/transformation/helpers/replace-supers.js @@ -38,12 +38,7 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, return t.callExpression( this.file.addHelper("set"), [ - t.callExpression( - t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")), - [ - isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype")) - ] - ), + isStatic ? this.superName : t.memberExpression(this.superName, t.identifier("prototype")), isComputed ? property : t.literal(property.name), value, thisExpression @@ -65,63 +60,17 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, * @returns {Node} */ -ReplaceSupers.prototype.superProperty = function (property, isStatic, isComputed, thisExpression) { +ReplaceSupers.prototype.getSuperProperty = function (property, isStatic, isComputed, thisExpression) { return t.callExpression( this.file.addHelper("get"), [ - t.callExpression( - t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")), - [ - isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype")) - ] - ), + isStatic ? this.superName : t.memberExpression(this.superName, t.identifier("prototype")), isComputed ? property : t.literal(property.name), thisExpression ] ); }; -/** - * Description - * - * @param {Object} node - * @param {Object} id - * @param {Object} parent - * @returns {Object} - */ - -ReplaceSupers.prototype.looseSuperProperty = function (methodNode, id, parent) { - var methodName = methodNode.key; - var superName = this.superName || t.identifier("Function"); - - if (parent.property === id) { - return; - } else if (t.isCallExpression(parent, { callee: id })) { - // super(); -> ClassName.prototype.MethodName.call(this); - parent.arguments.unshift(t.thisExpression()); - - if (methodName.name === "constructor") { - // constructor() { super(); } - return t.memberExpression(superName, t.identifier("call")); - } else { - id = superName; - - // foo() { super(); } - if (!methodNode.static) { - id = t.memberExpression(id, t.identifier("prototype")); - } - - id = t.memberExpression(id, methodName, methodNode.computed); - return t.memberExpression(id, t.identifier("call")); - } - } else if (t.isMemberExpression(parent) && !methodNode.static) { - // super.test -> ClassName.prototype.test - return t.memberExpression(superName, t.identifier("prototype")); - } else { - return superName; - } -}; - /** * Description */ @@ -186,6 +135,47 @@ ReplaceSupers.prototype.getThisReference = function () { } }; +/** + * Description + * + * @param {Object} node + * @param {Object} id + * @param {Object} parent + * @returns {Object} + */ + +ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent) { + var methodName = methodNode.key; + var superName = this.superName || t.identifier("Function"); + + if (parent.property === id) { + return; + } else if (t.isCallExpression(parent, { callee: id })) { + // super(); -> ClassName.prototype.MethodName.call(this); + parent.arguments.unshift(t.thisExpression()); + + if (methodName.name === "constructor") { + // constructor() { super(); } + return t.memberExpression(superName, t.identifier("call")); + } else { + id = superName; + + // foo() { super(); } + if (!methodNode.static) { + id = t.memberExpression(id, t.identifier("prototype")); + } + + id = t.memberExpression(id, methodName, methodNode.computed); + return t.memberExpression(id, t.identifier("call")); + } + } else if (t.isMemberExpression(parent) && !methodNode.static) { + // super.test -> ClassName.prototype.test + return t.memberExpression(superName, t.identifier("prototype")); + } else { + return superName; + } +}; + /** * Description * @@ -196,7 +186,7 @@ ReplaceSupers.prototype.getThisReference = function () { ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) { if (t.isIdentifier(node, { name: "super" })) { - return this.looseSuperProperty(this.methodNode, node, parent); + return this.getLooseSuperProperty(this.methodNode, node, parent); } else if (t.isCallExpression(node)) { var callee = node.callee; if (!t.isMemberExpression(callee)) return; @@ -269,7 +259,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) { if (!property) return; thisReference = getThisReference(); - var superProperty = this.superProperty(property, methodNode.static, computed, thisReference); + var superProperty = this.getSuperProperty(property, methodNode.static, computed, thisReference); if (args) { if (args.length === 1 && t.isSpreadElement(args[0])) { // super(...arguments); diff --git a/lib/6to5/transformation/templates/class-super-constructor-call.js b/lib/6to5/transformation/templates/class-super-constructor-call.js index 21034b6201..ab957160f2 100644 --- a/lib/6to5/transformation/templates/class-super-constructor-call.js +++ b/lib/6to5/transformation/templates/class-super-constructor-call.js @@ -1,3 +1,3 @@ -if (Object.getPrototypeOf(CLASS_NAME) !== null) { - Object.getPrototypeOf(CLASS_NAME).apply(this, arguments); +if (SUPER_NAME != null) { + SUPER_NAME.apply(this, arguments); } diff --git a/lib/6to5/transformation/transformers/es6/classes.js b/lib/6to5/transformation/transformers/es6/classes.js index 61e906ca62..d45297f4d9 100644 --- a/lib/6to5/transformation/transformers/es6/classes.js +++ b/lib/6to5/transformation/transformers/es6/classes.js @@ -50,7 +50,8 @@ function Class(node, file, scope, isStatement) { this.staticMutatorMap = {}; this.hasConstructor = false; this.className = node.id || scope.generateUidIdentifier("class"); - this.superName = node.superClass; + this.superName = node.superClass || t.identifier("Function"); + this.hasSuper = !!node.superClass; this.isLoose = file.isLoose("es6.classes"); } @@ -93,7 +94,7 @@ Class.prototype.run = function () { // - if (superName) { + if (this.hasSuper) { closureArgs.push(superName); if (!t.isIdentifier(superName)) { @@ -169,7 +170,7 @@ Class.prototype.buildBody = function () { } // we have no constructor, we have a super, and the super doesn't appear to be falsy - if (!this.hasConstructor && superName && !t.isFalsyExpression(superName)) { + if (!this.hasConstructor && this.hasSuper && !t.isFalsyExpression(superName)) { var helperName = "class-super-constructor-call"; if (this.isLoose) helperName += "-loose"; constructor.body.body.push(util.template(helperName, { diff --git a/lib/6to5/transformation/transformers/es7/object-rest-spread.js b/lib/6to5/transformation/transformers/es7/object-rest-spread.js index 2667946edd..f70d9572e7 100644 --- a/lib/6to5/transformation/transformers/es7/object-rest-spread.js +++ b/lib/6to5/transformation/transformers/es7/object-rest-spread.js @@ -7,7 +7,7 @@ var t = require("../../../types"); exports.experimental = true; exports.manipulateOptions = function (opts) { - opts.whitelist.push("es6.destructuring"); + if (opts.whitelist.length) opts.whitelist.push("es6.destructuring"); }; var hasSpread = function (node) { diff --git a/test/fixtures/esnext/es6-classes/super-change-proto.js b/test/fixtures/esnext/es6-classes/super-change-proto.js deleted file mode 100644 index 01058549c9..0000000000 --- a/test/fixtures/esnext/es6-classes/super-change-proto.js +++ /dev/null @@ -1,21 +0,0 @@ -var log = ''; - -class Base { - p() { log += '[Base]'; } -} - -class OtherBase { - p() { log += '[OtherBase]'; } -} - -class Derived extends Base { - p() { - log += '[Derived]'; - super.p(); - Derived.prototype.__proto__ = OtherBase.prototype; - super.p(); - } -} - -new Derived().p(); -assert.equal(log, '[Derived][Base][OtherBase]'); diff --git a/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js b/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js index a8f74b0cb7..7f6a1389dc 100644 --- a/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js +++ b/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js @@ -15,14 +15,14 @@ var Test = (function (Foo) { _classCallCheck(this, Test); woops["super"].test(); - _get(Object.getPrototypeOf(Test.prototype), "constructor", this).call(this); - _get(Object.getPrototypeOf(Test.prototype), "test", this).call(this); + _get(Foo.prototype, "constructor", this).call(this); + _get(Foo.prototype, "test", this).call(this); - _get(Object.getPrototypeOf(Test.prototype), "constructor", this).apply(this, arguments); - (_get2 = _get(Object.getPrototypeOf(Test.prototype), "constructor", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); + _get(Foo.prototype, "constructor", this).apply(this, arguments); + (_get2 = _get(Foo.prototype, "constructor", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); - _get(Object.getPrototypeOf(Test.prototype), "test", this).apply(this, arguments); - (_get3 = _get(Object.getPrototypeOf(Test.prototype), "test", this)).call.apply(_get3, [this, "test"].concat(_slice.call(arguments))); + _get(Foo.prototype, "test", this).apply(this, arguments); + (_get3 = _get(Foo.prototype, "test", this)).call.apply(_get3, [this, "test"].concat(_slice.call(arguments))); } _inherits(Test, Foo); @@ -31,9 +31,9 @@ var Test = (function (Foo) { foo: { value: function foo() { var _get2; - _get(Object.getPrototypeOf(Test), "foo", this).call(this); - _get(Object.getPrototypeOf(Test), "foo", this).apply(this, arguments); - (_get2 = _get(Object.getPrototypeOf(Test), "foo", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); + _get(Foo, "foo", this).call(this); + _get(Foo, "foo", this).apply(this, arguments); + (_get2 = _get(Foo, "foo", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); }, writable: true, configurable: true @@ -42,9 +42,9 @@ var Test = (function (Foo) { test: { value: function test() { var _get2; - _get(Object.getPrototypeOf(Test.prototype), "test", this).call(this); - _get(Object.getPrototypeOf(Test.prototype), "test", this).apply(this, arguments); - (_get2 = _get(Object.getPrototypeOf(Test.prototype), "test", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); + _get(Foo.prototype, "test", this).call(this); + _get(Foo.prototype, "test", this).apply(this, arguments); + (_get2 = _get(Foo.prototype, "test", this)).call.apply(_get2, [this, "test"].concat(_slice.call(arguments))); }, writable: true, configurable: true diff --git a/test/fixtures/transformation/es6-classes/accessing-super-properties/expected.js b/test/fixtures/transformation/es6-classes/accessing-super-properties/expected.js index 7ee14a53f1..9112ab7d1d 100644 --- a/test/fixtures/transformation/es6-classes/accessing-super-properties/expected.js +++ b/test/fixtures/transformation/es6-classes/accessing-super-properties/expected.js @@ -10,8 +10,8 @@ var Test = (function (Foo) { function Test() { _classCallCheck(this, Test); - _get(Object.getPrototypeOf(Test.prototype), "test", this); - _get(Object.getPrototypeOf(Test.prototype), "test", this).whatever; + _get(Foo.prototype, "test", this); + _get(Foo.prototype, "test", this).whatever; } _inherits(Test, Foo); diff --git a/test/fixtures/transformation/es6-classes/calling-super-properties/expected.js b/test/fixtures/transformation/es6-classes/calling-super-properties/expected.js index 4ae369971d..e0fcb1292a 100644 --- a/test/fixtures/transformation/es6-classes/calling-super-properties/expected.js +++ b/test/fixtures/transformation/es6-classes/calling-super-properties/expected.js @@ -12,8 +12,8 @@ var Test = (function (Foo) { function Test() { _classCallCheck(this, Test); - _get(Object.getPrototypeOf(Test.prototype), "test", this).whatever(); - _get(Object.getPrototypeOf(Test.prototype), "test", this).call(this); + _get(Foo.prototype, "test", this).whatever(); + _get(Foo.prototype, "test", this).call(this); } _inherits(Test, Foo); @@ -21,7 +21,7 @@ var Test = (function (Foo) { _prototypeProperties(Test, { test: { value: function test() { - return _get(Object.getPrototypeOf(Test), "wow", this).call(this); + return _get(Foo, "wow", this).call(this); }, writable: true, configurable: true diff --git a/test/fixtures/transformation/es6-classes/super-class-id-member-expression/expected.js b/test/fixtures/transformation/es6-classes/super-class-id-member-expression/expected.js index 70caacde0a..e277b544fd 100644 --- a/test/fixtures/transformation/es6-classes/super-class-id-member-expression/expected.js +++ b/test/fixtures/transformation/es6-classes/super-class-id-member-expression/expected.js @@ -8,8 +8,8 @@ var BaseController = (function (_Chaplin$Controller) { function BaseController() { _classCallCheck(this, BaseController); - if (Object.getPrototypeOf(BaseController) !== null) { - Object.getPrototypeOf(BaseController).apply(this, arguments); + if (_Chaplin$Controller != null) { + _Chaplin$Controller.apply(this, arguments); } } @@ -22,12 +22,12 @@ var BaseController2 = (function (_Chaplin$Controller$Another) { function BaseController2() { _classCallCheck(this, BaseController2); - if (Object.getPrototypeOf(BaseController2) !== null) { - Object.getPrototypeOf(BaseController2).apply(this, arguments); + if (_Chaplin$Controller$Another != null) { + _Chaplin$Controller$Another.apply(this, arguments); } } _inherits(BaseController2, _Chaplin$Controller$Another); return BaseController2; -})(Chaplin.Controller.Another); +})(Chaplin.Controller.Another); \ No newline at end of file diff --git a/test/fixtures/transformation/es6-classes/super-class/expected.js b/test/fixtures/transformation/es6-classes/super-class/expected.js index aec7b613ab..338d66b696 100644 --- a/test/fixtures/transformation/es6-classes/super-class/expected.js +++ b/test/fixtures/transformation/es6-classes/super-class/expected.js @@ -8,12 +8,12 @@ var Test = (function (Foo) { function Test() { _classCallCheck(this, Test); - if (Object.getPrototypeOf(Test) !== null) { - Object.getPrototypeOf(Test).apply(this, arguments); + if (Foo != null) { + Foo.apply(this, arguments); } } _inherits(Test, Foo); return Test; -})(Foo); +})(Foo); \ No newline at end of file diff --git a/test/fixtures/transformation/es6-classes/super-function-fallback/expected.js b/test/fixtures/transformation/es6-classes/super-function-fallback/expected.js index e278a09b33..13bf3b8d41 100644 --- a/test/fixtures/transformation/es6-classes/super-function-fallback/expected.js +++ b/test/fixtures/transformation/es6-classes/super-function-fallback/expected.js @@ -7,5 +7,5 @@ var _classCallCheck = function (instance, Constructor) { if (!(instance instance var Test = function Test() { _classCallCheck(this, Test); - _get(Object.getPrototypeOf(Test.prototype), "hasOwnProperty", this).call(this, "test"); -}; \ No newline at end of file + _get(Function.prototype, "hasOwnProperty", this).call(this, "test"); +}; diff --git a/test/fixtures/transformation/spec-proto-to-assign/class/expected.js b/test/fixtures/transformation/spec-proto-to-assign/class/expected.js index 22b7ef21ef..4b47fef537 100644 --- a/test/fixtures/transformation/spec-proto-to-assign/class/expected.js +++ b/test/fixtures/transformation/spec-proto-to-assign/class/expected.js @@ -10,12 +10,12 @@ var Foo = (function (Bar) { function Foo() { _classCallCheck(this, Foo); - if (Object.getPrototypeOf(Foo) !== null) { - Object.getPrototypeOf(Foo).apply(this, arguments); + if (Bar != null) { + Bar.apply(this, arguments); } } _inherits(Foo, Bar); return Foo; -})(Bar); +})(Bar); \ No newline at end of file