From 9b68d08604911b215b4abac9e6de7e26dce4d875 Mon Sep 17 00:00:00 2001 From: Kurt Ruppel Date: Thu, 22 Jan 2015 17:06:04 -0800 Subject: [PATCH 1/3] Add test for failing assignment to super setter. --- .../esnext/es6-classes/getter-setter-super.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/fixtures/esnext/es6-classes/getter-setter-super.js b/test/fixtures/esnext/es6-classes/getter-setter-super.js index a1974f8335..76004a0881 100644 --- a/test/fixtures/esnext/es6-classes/getter-setter-super.js +++ b/test/fixtures/esnext/es6-classes/getter-setter-super.js @@ -2,6 +2,14 @@ class Base { get sound() { return 'I am a ' + this.type + '.'; } + + get name() { + return this._name; + } + + set name(val) { + this._name = val; + } } class Animal extends Base {} @@ -12,6 +20,15 @@ class Cat extends Animal { get sound() { return super.sound + ' MEOW!'; } + + set name(val) { + super.name = val; + this._name += ' Cat'; + } } -assert.equal(new Cat().sound, 'I am a cat. MEOW!'); +var cat = new Cat(); + +assert.equal(cat.sound, 'I am a cat. MEOW!'); +cat.name = 'Nyan'; +assert.equal(new Cat().name, 'Nyan Cat'); From bbfb297d73bfea4b1a004206ff19f5fe51114af4 Mon Sep 17 00:00:00 2001 From: Kurt Ruppel Date: Fri, 23 Jan 2015 17:22:54 -0800 Subject: [PATCH 2/3] Support use of super inside instance setter. --- lib/6to5/file.js | 3 +- .../transformation/helpers/replace-supers.js | 40 ++++++++++++++++++- lib/6to5/transformation/templates/set.js | 24 +++++++++++ .../esnext/es6-classes/getter-setter-super.js | 6 ++- 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 lib/6to5/transformation/templates/set.js diff --git a/lib/6to5/file.js b/lib/6to5/file.js index f9a6eb7d5e..a9777e7b91 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -39,7 +39,8 @@ File.helpers = [ "interop-require-wildcard", "typeof", "extends", - "get" + "get", + "set" ]; File.excludeHelpersFromRuntime = [ diff --git a/lib/6to5/transformation/helpers/replace-supers.js b/lib/6to5/transformation/helpers/replace-supers.js index 2403e878cb..d15d9c4f28 100644 --- a/lib/6to5/transformation/helpers/replace-supers.js +++ b/lib/6to5/transformation/helpers/replace-supers.js @@ -24,6 +24,36 @@ function ReplaceSupers(methodNode, className, superName, isLoose, file) { this.file = file; } +/** + * Sets a super class value of the named property. + * + * @example + * + * _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this) + * + * @param {Node} property + * @param {boolean} isStatic + * @param {boolean} isComputed + * + * @returns {Node} + */ +ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, isComputed, thisExpression) { + 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")) + ] + ), + isComputed ? property : t.literal(property.name), + t.identifier(value.name), + thisExpression + ] + ); +}; + /** * Gets a node representing the super class value of the named property. * @@ -194,6 +224,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) { var property; var computed; var args; + var thisReference; if (t.isIdentifier(node, { name: "super" })) { if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) { @@ -221,11 +252,18 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) { // super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this); property = node.property; computed = node.computed; + } else if (t.isAssignmentExpression(node)) { + if (!t.isIdentifier(node.left.object, { name: "super" })) return; + if (methodNode.kind !== 'set') return; + + thisReference = getThisReference(); + // super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this); + return this.setSuperProperty(node.left.property, node.right, methodNode.static, node.left.computed, thisReference); } if (!property) return; - var thisReference = getThisReference(); + thisReference = getThisReference(); var superProperty = this.superProperty(property, methodNode.static, computed, thisReference); if (args) { if (args.length === 1 && t.isSpreadElement(args[0])) { diff --git a/lib/6to5/transformation/templates/set.js b/lib/6to5/transformation/templates/set.js new file mode 100644 index 0000000000..f00cb746a8 --- /dev/null +++ b/lib/6to5/transformation/templates/set.js @@ -0,0 +1,24 @@ +(function set(object, property, value, receiver) { + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return; + } else { + return set(parent, property, value, receiver); + } + } else if ("value" in desc && desc.writable) { + desc.value = value; + return; + } else { + var setter = desc.set; + + if (setter === undefined) { + return; + } + + return setter.call(receiver, value); + } +}); diff --git a/test/fixtures/esnext/es6-classes/getter-setter-super.js b/test/fixtures/esnext/es6-classes/getter-setter-super.js index 76004a0881..5b9693298c 100644 --- a/test/fixtures/esnext/es6-classes/getter-setter-super.js +++ b/test/fixtures/esnext/es6-classes/getter-setter-super.js @@ -21,6 +21,10 @@ class Cat extends Animal { return super.sound + ' MEOW!'; } + get name() { + return super.name; + } + set name(val) { super.name = val; this._name += ' Cat'; @@ -31,4 +35,4 @@ var cat = new Cat(); assert.equal(cat.sound, 'I am a cat. MEOW!'); cat.name = 'Nyan'; -assert.equal(new Cat().name, 'Nyan Cat'); +assert.equal(cat.name, 'Nyan Cat'); From d87b70b57efaeae9b1e4f30853c845a2cf45efd5 Mon Sep 17 00:00:00 2001 From: Kurt Ruppel Date: Sat, 24 Jan 2015 11:15:43 -0800 Subject: [PATCH 3/3] Use right side verbatim for ES6 class setter. --- lib/6to5/transformation/helpers/replace-supers.js | 2 +- test/fixtures/esnext/es6-classes/getter-setter-super.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/6to5/transformation/helpers/replace-supers.js b/lib/6to5/transformation/helpers/replace-supers.js index d15d9c4f28..44e48aca95 100644 --- a/lib/6to5/transformation/helpers/replace-supers.js +++ b/lib/6to5/transformation/helpers/replace-supers.js @@ -48,7 +48,7 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, ] ), isComputed ? property : t.literal(property.name), - t.identifier(value.name), + value, thisExpression ] ); diff --git a/test/fixtures/esnext/es6-classes/getter-setter-super.js b/test/fixtures/esnext/es6-classes/getter-setter-super.js index 5b9693298c..218ccbd2fe 100644 --- a/test/fixtures/esnext/es6-classes/getter-setter-super.js +++ b/test/fixtures/esnext/es6-classes/getter-setter-super.js @@ -26,8 +26,7 @@ class Cat extends Animal { } set name(val) { - super.name = val; - this._name += ' Cat'; + super.name = val + ' Cat'; } }