From 5b4d6d7ba9ecc7c0ea02b6422573145c23711dfd Mon Sep 17 00:00:00 2001 From: Brian Donovan Date: Thu, 8 Jan 2015 08:36:16 -0800 Subject: [PATCH] Replace superIdentifier with superProperty. This also disallows the usage of bare `super` that is not part of a member expression, call expression, or new expression. --- .../transformers/es6-classes.js | 136 +++++------------- .../accessing-super-class/actual.js | 1 - .../accessing-super-class/expected.js | 1 - .../es6-classes/bare-super/actual.js | 5 + .../es6-classes/bare-super/options.json | 3 + 5 files changed, 45 insertions(+), 101 deletions(-) create mode 100644 test/fixtures/transformation/es6-classes/bare-super/actual.js create mode 100644 test/fixtures/transformation/es6-classes/bare-super/options.json diff --git a/lib/6to5/transformation/transformers/es6-classes.js b/lib/6to5/transformation/transformers/es6-classes.js index ca56cc687d..593164be90 100644 --- a/lib/6to5/transformation/transformers/es6-classes.js +++ b/lib/6to5/transformation/transformers/es6-classes.js @@ -215,67 +215,45 @@ Class.prototype.pushMethod = function (node) { }; /** - * Given a `methodNode`, produce a `MemberExpression` super class reference. + * Gets a node representing the super class value of the named property. * - * @param {Node} methodNode MethodDefinition - * @param {Node} id Identifier - * @param {Node} parent + * @example + * + * _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) + * + * @param {Node} property + * @param {boolean} isStatic + * @param {boolean} isComputed * * @returns {Node} */ -Class.prototype.superIdentifier = function (methodNode, id, parent) { - var methodName = methodNode.key; - var superName = this.superName || t.identifier("Function"); - var className = this.className; - - if (parent.property === id) { - return; - } else if (t.isCallExpression(parent, { callee: id })) { - // super(); -> _get(Object.getPrototypeOf(ClassName.prototype), "MethodName", this).call(this); - var superProto = t.callExpression( - t.memberExpression( - t.identifier("Object"), - t.identifier("getPrototypeOf"), - false +Class.prototype.superProperty = function (property, isStatic, isComputed) { + return t.callExpression( + this.file.addHelper("get"), + [ + t.callExpression( + t.memberExpression( + t.identifier("Object"), + t.identifier("getPrototypeOf"), + false + ), + [ + isStatic ? + this.className : + t.memberExpression( + this.className, + t.identifier("prototype"), + false + ) + ] ), - [ - methodNode.static ? - className : - t.memberExpression(className, t.identifier("prototype")) - ] - ); - var superCallee = t.callExpression( - this.file.addHelper("get"), - [ - superProto, - methodNode.computed ? methodName : t.literal(methodName.name), - t.thisExpression() - ] - ); - - parent.arguments.unshift(t.thisExpression()); - - if (methodName.name === "constructor") { - // constructor() { super(); } - return t.memberExpression(superCallee, 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(superCallee, 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; - } + isComputed ? + property : + t.literal(property.name), + t.thisExpression() + ] + ); }; /** @@ -295,7 +273,9 @@ Class.prototype.replaceInstanceSuperReferences = function (methodNode) { var args; if (t.isIdentifier(node, { name: "super" })) { - return self.superIdentifier(methodNode, node, parent); + if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) { + throw self.file.errorWithNode(node, "illegal use of bare super"); + } } else if (t.isCallExpression(node)) { var callee = node.callee; if (t.isIdentifier(callee) && callee.name === "super") { @@ -324,7 +304,7 @@ Class.prototype.replaceInstanceSuperReferences = function (methodNode) { var superProperty = self.superProperty(property, methodNode.static, computed); if (args) { return t.callExpression( - t.memberExpression(superProperty, t.identifier('call'), false), + t.memberExpression(superProperty, t.identifier("call"), false), [t.thisExpression()].concat(args) ); } else { @@ -335,48 +315,6 @@ Class.prototype.replaceInstanceSuperReferences = function (methodNode) { }); }; -/** - * Gets a node representing the super class value of the named property. - * - * @example - * - * _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) - * - * @param {Node} property - * @param {boolean} isStatic - * @param {boolean} isComputed - * - * @returns {Node} - */ - -Class.prototype.superProperty = function (property, isStatic, isComputed) { - return t.callExpression( - this.file.addHelper('get'), - [ - t.callExpression( - t.memberExpression( - t.identifier('Object'), - t.identifier('getPrototypeOf'), - false - ), - [ - isStatic ? - this.className : - t.memberExpression( - this.className, - t.identifier('prototype'), - false - ) - ] - ), - isComputed ? - property : - t.literal(property.name), - t.thisExpression() - ] - ); -}; - /** * Replace the constructor body of our class. * diff --git a/test/fixtures/transformation/es6-classes/accessing-super-class/actual.js b/test/fixtures/transformation/es6-classes/accessing-super-class/actual.js index 64b349152c..154d85730b 100644 --- a/test/fixtures/transformation/es6-classes/accessing-super-class/actual.js +++ b/test/fixtures/transformation/es6-classes/accessing-super-class/actual.js @@ -3,7 +3,6 @@ class Test extends Foo { woops.super.test(); super(); super.test(); - foob(super); super(...arguments); super("test", ...arguments); 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 b7ba571c53..6c99bfd509 100644 --- a/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js +++ b/test/fixtures/transformation/es6-classes/accessing-super-class/expected.js @@ -45,7 +45,6 @@ var Test = (function () { woops["super"].test(); _get(Object.getPrototypeOf(Test.prototype), "constructor", this).call(this); _get(Object.getPrototypeOf(Test.prototype), "test", this).call(this); - foob(_Foo); (_get2 = _get(Object.getPrototypeOf(Test.prototype), "constructor", this)).call.apply(_get2, [this].concat(_slice.call(arguments))); (_get3 = _get(Object.getPrototypeOf(Test.prototype), "constructor", this)).call.apply(_get3, [this, "test"].concat(_slice.call(arguments))); diff --git a/test/fixtures/transformation/es6-classes/bare-super/actual.js b/test/fixtures/transformation/es6-classes/bare-super/actual.js new file mode 100644 index 0000000000..6e053ecf76 --- /dev/null +++ b/test/fixtures/transformation/es6-classes/bare-super/actual.js @@ -0,0 +1,5 @@ +class Test { + constructor() { + console.log(super); + } +} diff --git a/test/fixtures/transformation/es6-classes/bare-super/options.json b/test/fixtures/transformation/es6-classes/bare-super/options.json new file mode 100644 index 0000000000..f878b7f9cd --- /dev/null +++ b/test/fixtures/transformation/es6-classes/bare-super/options.json @@ -0,0 +1,3 @@ +{ + "throws": "illegal use of bare super" +}