Fix super nested class bugs (#7691)

* Properly traverse nested class for supers

* Add object nested in class cases

* Add object nested object cases

* Test class properties

* Undo changes to lerna.json

* Add tests arournd prefix/postfix super increment

* tmp

* Use sets
This commit is contained in:
Justin Ridgewell 2018-04-12 13:02:26 -04:00 committed by GitHub
parent af3d6526e7
commit ecbf0dd53c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 907 additions and 169 deletions

View File

@ -5,46 +5,53 @@ import * as t from "@babel/types";
// ✌️ // ✌️
const HARDCORE_THIS_REF = new WeakSet(); const HARDCORE_THIS_REF = new WeakSet();
function isIllegalBareSuper(node, parent) {
if (!t.isSuper(node)) return false;
if (t.isMemberExpression(parent, { computed: false })) return false;
if (t.isCallExpression(parent, { callee: node })) return false;
return true;
}
function isMemberExpressionSuper(node) {
return t.isMemberExpression(node) && t.isSuper(node.object);
}
/** /**
* Creates an expression which result is the proto of objectRef. * Creates an expression which result is the proto of objectRef.
* Uses CLASS.__proto__ first for InternetExplorer <= 10 support
* *
* @example <caption>isStatic === true</caption> * @example <caption>isStatic === true</caption>
* *
* CLASS.__proto__ || Object.getPrototypeOf(CLASS) * helpers.getPrototypeOf(CLASS)
* *
* @example <caption>isStatic === false</caption> * @example <caption>isStatic === false</caption>
* *
* CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype) * helpers.getPrototypeOf(CLASS.prototype)
*/ */
function getPrototypeOfExpression(objectRef, isStatic, file) { function getPrototypeOfExpression(objectRef, isStatic, file) {
objectRef = t.cloneNode(objectRef);
const targetRef = isStatic const targetRef = isStatic
? objectRef ? objectRef
: t.memberExpression(objectRef, t.identifier("prototype")); : t.memberExpression(objectRef, t.identifier("prototype"));
return t.callExpression(file.addHelper("getPrototypeOf"), [ return t.callExpression(file.addHelper("getPrototypeOf"), [targetRef]);
t.cloneNode(targetRef),
]);
} }
const visitor = { const visitor = {
Function(path) { Function(path) {
if (!path.isArrowFunctionExpression()) path.skip(); if (path.isMethod()) return;
if (path.isArrowFunctionExpression()) return;
path.skip();
}, },
ClassProperty(path) { Method(path, state) {
// Don't traverse ClassMethod's body
path.skip();
// We do have to traverse the key, since it's evaluated in the outer class
// context.
if (path.node.computed) {
path.get("key").traverse(visitor, state);
}
},
"ClassProperty|ClassPrivateProperty"(path, state) {
// Don't traverse the ClassProp's value.
if (!path.node.static) path.skip(); if (!path.node.static) path.skip();
// We do have to traverse the key, since it's evaluated in the outer class
// context.
if (path.node.computed) {
path.get("key").traverse(visitor, state);
}
}, },
ReturnStatement(path, state) { ReturnStatement(path, state) {
@ -59,33 +66,15 @@ const visitor = {
} }
}, },
enter(path, state) { Super(path, state) {
let callback = state.specHandle;
if (state.isLoose) callback = state.looseHandle;
const isBareSuper = path.isCallExpression() && path.get("callee").isSuper();
const result = callback.call(state, path);
if (result) {
state.hasSuper = true; state.hasSuper = true;
}
if (isBareSuper) { const { node, parentPath } = path;
state.bareSupers.push(path); if (parentPath.isCallExpression({ callee: node })) {
} state.bareSupers.add(parentPath);
return;
if (result === true) {
path.requeue();
}
if (result !== true && result) {
if (Array.isArray(result)) {
path.replaceWithMultiple(result);
} else {
path.replaceWith(result);
}
} }
state[state.isLoose ? "looseHandle" : "specHandle"](path);
}, },
}; };
@ -104,7 +93,7 @@ export default class ReplaceSupers {
this.file = opts.file; this.file = opts.file;
this.opts = opts; this.opts = opts;
this.bareSupers = []; this.bareSupers = new Set();
this.returns = []; this.returns = [];
this.thises = []; this.thises = [];
} }
@ -141,8 +130,7 @@ export default class ReplaceSupers {
* *
* @example * @example
* *
* _set(CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", * _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this, isStrict)
* this, isStrict)
* *
*/ */
@ -166,7 +154,7 @@ export default class ReplaceSupers {
* *
* @example * @example
* *
* _get(CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype), "METHOD", this) * _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
* *
*/ */
@ -190,144 +178,146 @@ export default class ReplaceSupers {
this.methodPath.traverse(visitor, this); this.methodPath.traverse(visitor, this);
} }
getLooseSuperProperty(id: Object, parent: Object) { getLooseSuperProperty(path) {
const methodNode = this.methodNode; const { isStatic, superRef } = this;
const superRef = this.superRef || t.identifier("Function");
if (parent.property === id) { let object;
return; if (isStatic) {
} else if (t.isCallExpression(parent, { callee: id })) { object = superRef
return; ? t.cloneNode(superRef)
} else if (t.isMemberExpression(parent) && !methodNode.static) { : t.memberExpression(
// super.test -> objectRef.prototype.test t.identifier("Function"),
return t.memberExpression(
t.cloneNode(superRef),
t.identifier("prototype"), t.identifier("prototype"),
); );
} else { } else {
return t.cloneNode(superRef); object = superRef
? t.memberExpression(t.cloneNode(superRef), t.identifier("prototype"))
: t.memberExpression(t.identifier("Object"), t.identifier("prototype"));
} }
path.get("object").replaceWith(object);
} }
looseHandle(path: NodePath) { looseHandle(path: NodePath) {
const node = path.node; const { node, parentPath } = path;
if (path.isSuper()) {
return this.getLooseSuperProperty(node, path.parent);
} else if (path.isCallExpression()) {
const callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (!t.isSuper(callee.object)) return;
// super.test(); -> objectRef.prototype.MethodName.call(this); // super.test
t.appendToMemberExpression(callee, t.identifier("call")); if (parentPath.isMemberExpression({ object: node })) {
node.arguments.unshift(t.thisExpression()); this.getLooseSuperProperty(parentPath);
return true; }
// super.test()
// though, it's SUPER.prototype.test() after the above.
const grandParentPath = parentPath.parentPath;
const callee = parentPath.node;
if (grandParentPath.isCallExpression({ callee })) {
grandParentPath
.get("callee")
.replaceWith(t.memberExpression(callee, t.identifier("call")));
grandParentPath.node.arguments.unshift(t.thisExpression());
} }
} }
specHandleAssignmentExpression(ref, path, node) { specHandleAssignmentExpression(path) {
if (node.operator === "=") { const { node } = path;
const { operator } = node;
const { computed, property } = node.left;
if (operator === "=") {
// super.name = "val" // super.name = "val"
// to // to
// _set(Object.getPrototypeOf(objectRef.prototype), "name", this, isStrict); // _set(Object.getPrototypeOf(CLASS.prototype), "name", this);
return this.setSuperProperty( const setter = this.setSuperProperty(
node.left.property, property,
node.right, node.right,
node.left.computed, computed,
path.isInStrictMode(), path.isInStrictMode(),
); );
} else { return [setter];
// super.age += 2 }
// super.age += 2;
// to // to
// let _ref = super.age; super.age = _ref + 2; // _set(
ref = ref || path.scope.generateUidIdentifier("ref"); // Object.getPrototypeOf(CLASS.prototype),
// "name",
// _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) + 2,
// this,
// true,
// );
// TODO this needs cleanup. Should be a single proto lookup
const ref = path.scope.generateDeclaredUidIdentifier("ref");
const setter = this.setSuperProperty(
property,
t.binaryExpression(operator.slice(0, -1), t.cloneNode(ref), node.right),
computed,
path.isInStrictMode(),
);
return [ return [
t.variableDeclaration("var", [
t.variableDeclarator(t.cloneNode(ref), t.cloneNode(node.left)),
]),
t.expressionStatement(
t.assignmentExpression( t.assignmentExpression(
"=", "=",
node.left,
t.binaryExpression(
node.operator.slice(0, -1),
t.cloneNode(ref), t.cloneNode(ref),
node.right, this.getSuperProperty(property, computed),
),
),
), ),
setter,
]; ];
} }
}
specHandle(path: NodePath) { specHandle(path: NodePath) {
let property; const { node, parentPath } = path;
let computed; const grandParentPath = parentPath.parentPath;
let args; let parent = parentPath.node;
const parent = path.parent; if (grandParentPath.isUpdateExpression({ argument: parent })) {
const node = path.node; const { operator, prefix } = grandParentPath.node;
const assignment = t.assignmentExpression(
if (isIllegalBareSuper(node, parent)) { operator[0] + "=",
throw path.buildCodeFrameError("Illegal use of bare super"); parent,
}
if (t.isCallExpression(node)) {
const callee = node.callee;
if (t.isSuper(callee)) {
return;
} else if (isMemberExpressionSuper(callee)) {
// super.test();
// to
// _get(Object.getPrototypeOf(objectRef.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node) && t.isSuper(node.object)) {
// super.name;
// to
// _get(Object.getPrototypeOf(objectRef.prototype), "name", this);
property = node.property;
computed = node.computed;
} else if (
t.isUpdateExpression(node) &&
isMemberExpressionSuper(node.argument)
) {
const binary = t.assignmentExpression(
node.operator[0] + "=",
node.argument,
t.numericLiteral(1), t.numericLiteral(1),
); );
if (node.prefix) { grandParentPath.replaceWith(assignment);
// ++super.foo; // ++super.foo;
// to // to
// super.foo += 1; // _ref = Number(super.foo), super.foo = _ref + 1
return this.specHandleAssignmentExpression(null, path, binary);
} else {
// super.foo++; // super.foo++;
// to // to
// let _ref = super.foo; super.foo = _ref + 1; // _ref = Number(super.foo), super.foo = _ref + 1, _ref
const ref = path.scope.generateUidIdentifier("ref"); const nodes = this.specHandleAssignmentExpression(grandParentPath);
return this.specHandleAssignmentExpression(ref, path, binary).concat( const [first] = nodes;
t.expressionStatement(ref), first.right = t.callExpression(t.identifier("Number"), [first.right]);
// Postfix returns the old value, not the new.
if (!prefix) {
nodes.push(t.cloneNode(first.left));
}
grandParentPath.replaceWith(t.sequenceExpression(nodes));
return;
}
if (grandParentPath.isAssignmentExpression({ left: parent })) {
grandParentPath.replaceWithMultiple(
this.specHandleAssignmentExpression(grandParentPath),
); );
} return;
} else if (
t.isAssignmentExpression(node) &&
isMemberExpressionSuper(node.left)
) {
return this.specHandleAssignmentExpression(null, path, node);
} }
if (!property) return; if (parentPath.isMemberExpression({ object: node })) {
// super.name;
// to
// _get(Object.getPrototypeOf(CLASS.prototype), "name", this);
const { node } = parentPath;
const { computed, property } = node;
const superProperty = this.getSuperProperty(property, computed); parent = this.getSuperProperty(property, computed);
parentPath.replaceWith(parent);
}
if (args) { if (grandParentPath.isCallExpression({ callee: parent })) {
return this.optimiseCall(superProperty, args); // _get(Object.getPrototypeOf(CLASS.prototype), "test", this)();
} else { // to
return superProperty; // _get(Object.getPrototypeOf(CLASS.prototype), "test", this).call(this);
const call = this.optimiseCall(parent, grandParentPath.node.arguments);
grandParentPath.replaceWith(call);
return;
} }
} }

View File

@ -0,0 +1,3 @@
{
"plugins": ["external-helpers", "proposal-class-properties", "transform-classes"]
}

View File

@ -0,0 +1,22 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
class Inner {
[super()] = "hello";
}
return new Inner();
}
}
assert.equal(new Outer().hello, 'hello');

View File

@ -0,0 +1,22 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
class Inner {
[super()] = "hello";
}
return new Inner();
}
}
assert.equal(new Outer().hello, 'hello');

View File

@ -0,0 +1,41 @@
"use strict";
let Hello = function Hello() {
babelHelpers.classCallCheck(this, Hello);
return {
toString() {
return 'hello';
}
};
};
let Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this;
babelHelpers.classCallCheck(this, Outer);
var _this2 = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this));
let Inner = function Inner() {
babelHelpers.classCallCheck(this, Inner);
Object.defineProperty(this, _this2, {
configurable: true,
enumerable: true,
writable: true,
value: "hello"
});
};
return babelHelpers.possibleConstructorReturn(_this, new Inner());
}
return Outer;
}(Hello);
assert.equal(new Outer().hello, 'hello');

View File

@ -0,0 +1,19 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
class Inner {
[super.toString()] = 'hello';
}
return new Inner();
}
}
assert.equal(new Outer().hello, 'hello');

View File

@ -0,0 +1,19 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
class Inner {
[super.toString()] = 'hello';
}
return new Inner();
}
}
assert.equal(new Outer().hello, 'hello');

View File

@ -0,0 +1,48 @@
"use strict";
let Hello =
/*#__PURE__*/
function () {
function Hello() {
babelHelpers.classCallCheck(this, Hello);
}
babelHelpers.createClass(Hello, [{
key: "toString",
value: function toString() {
return 'hello';
}
}]);
return Hello;
}();
let Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this;
babelHelpers.classCallCheck(this, Outer);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this));
var _babelHelpers$get$cal = babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this)).call(_this);
let Inner = function Inner() {
babelHelpers.classCallCheck(this, Inner);
Object.defineProperty(this, _babelHelpers$get$cal, {
configurable: true,
enumerable: true,
writable: true,
value: 'hello'
});
};
return babelHelpers.possibleConstructorReturn(_this, new Inner());
}
return Outer;
}(Hello);
assert.equal(new Outer().hello, 'hello');

View File

@ -57,7 +57,7 @@ export default function transformClass(
instancePropRefs: {}, instancePropRefs: {},
staticPropBody: [], staticPropBody: [],
body: [], body: [],
bareSupers: [], bareSupers: new Set(),
superThises: [], superThises: [],
pushedConstructor: false, pushedConstructor: false,
pushedInherits: false, pushedInherits: false,
@ -388,7 +388,7 @@ export default function transformClass(
path.traverse(findThisesVisitor); path.traverse(findThisesVisitor);
let guaranteedSuperBeforeFinish = !!classState.bareSupers.length; let guaranteedSuperBeforeFinish = !!classState.bareSupers.size;
const superRef = classState.superName || t.identifier("Function"); const superRef = classState.superName || t.identifier("Function");
let thisRef = function() { let thisRef = function() {

View File

@ -9,12 +9,12 @@ class ColorPoint extends Point {
super(); super();
this.x = 2; this.x = 2;
super.x = 3; super.x = 3;
assert.equal(this.x, 3) // A assert.equal(this.x, 3); // A
assert.equal(super.x, undefined) // B assert.equal(super.x, undefined); // B
} }
m() { m() {
this.getX() this.getX();
} }
} }

View File

@ -29,7 +29,7 @@ function (_Point) {
babelHelpers.classCallCheck(this, ColorPoint); babelHelpers.classCallCheck(this, ColorPoint);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(ColorPoint).call(this)); _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(ColorPoint).call(this));
_this.x = 2; _this.x = 2;
babelHelpers.set(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", 3, _this, true); babelHelpers.set(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", 3, _this, true)
assert.equal(_this.x, 3); // A assert.equal(_this.x, 3); // A
assert.equal(babelHelpers.get(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", babelHelpers.assertThisInitialized(_this)), undefined); // B assert.equal(babelHelpers.get(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", babelHelpers.assertThisInitialized(_this)), undefined); // B

View File

@ -0,0 +1,24 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
class Inner {
[super()]() {
return 'hello';
}
}
return new Inner();
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,24 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
class Inner {
[super()]() {
return 'hello';
}
}
return new Inner();
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,47 @@
"use strict";
var Hello = function Hello() {
babelHelpers.classCallCheck(this, Hello);
return {
toString() {
return 'hello';
}
};
};
var Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this2 = this;
var _this;
babelHelpers.classCallCheck(this, Outer);
var Inner =
/*#__PURE__*/
function () {
function Inner() {
babelHelpers.classCallCheck(this, Inner);
}
babelHelpers.createClass(Inner, [{
key: _this = babelHelpers.possibleConstructorReturn(_this2, babelHelpers.getPrototypeOf(Outer).call(_this2)),
value: function value() {
return 'hello';
}
}]);
return Inner;
}();
return babelHelpers.possibleConstructorReturn(_this, new Inner());
}
return Outer;
}(Hello);
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
class Inner {
[super.toString()]() {
return 'hello';
}
}
return new Inner();
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
class Inner {
[super.toString()]() {
return 'hello';
}
}
return new Inner();
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,54 @@
"use strict";
var Hello =
/*#__PURE__*/
function () {
function Hello() {
babelHelpers.classCallCheck(this, Hello);
}
babelHelpers.createClass(Hello, [{
key: "toString",
value: function toString() {
return 'hello';
}
}]);
return Hello;
}();
var Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this2 = this;
var _this;
babelHelpers.classCallCheck(this, Outer);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this));
var Inner =
/*#__PURE__*/
function () {
function Inner() {
babelHelpers.classCallCheck(this, Inner);
}
babelHelpers.createClass(Inner, [{
key: babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this2)).call(_this2),
value: function value() {
return 'hello';
}
}]);
return Inner;
}();
return babelHelpers.possibleConstructorReturn(_this, new Inner());
}
return Outer;
}(Hello);
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,24 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
const Inner = {
[super()]() {
return 'hello';
},
};
return Inner;
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,24 @@
"use strict";
class Hello {
constructor() {
return {
toString() {
return 'hello';
},
};
}
}
class Outer extends Hello {
constructor() {
const Inner = {
[super()]() {
return 'hello';
},
};
return Inner;
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,34 @@
"use strict";
var Hello = function Hello() {
babelHelpers.classCallCheck(this, Hello);
return {
toString() {
return 'hello';
}
};
};
var Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this;
babelHelpers.classCallCheck(this, Outer);
var Inner = {
[_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this))]() {
return 'hello';
}
};
return babelHelpers.possibleConstructorReturn(_this, Inner);
}
return Outer;
}(Hello);
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
const Inner = {
[super.toString()]() {
return 'hello';
},
};
return Inner;
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
class Hello {
toString() {
return 'hello';
}
}
class Outer extends Hello {
constructor() {
super();
const Inner = {
[super.toString()]() {
return 'hello';
},
};
return Inner;
}
}
assert.equal(new Outer().hello(), 'hello');

View File

@ -0,0 +1,41 @@
"use strict";
var Hello =
/*#__PURE__*/
function () {
function Hello() {
babelHelpers.classCallCheck(this, Hello);
}
babelHelpers.createClass(Hello, [{
key: "toString",
value: function toString() {
return 'hello';
}
}]);
return Hello;
}();
var Outer =
/*#__PURE__*/
function (_Hello) {
babelHelpers.inherits(Outer, _Hello);
function Outer() {
var _this;
babelHelpers.classCallCheck(this, Outer);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this));
var Inner = {
[babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(this)).call(this)]() {
return 'hello';
}
};
return babelHelpers.possibleConstructorReturn(_this, Inner);
}
return Outer;
}(Hello);
assert.equal(new Outer().hello(), 'hello');

View File

@ -1,13 +1,13 @@
var _obj; var _obj;
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); } function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); }
function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; } function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); } function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); }

View File

@ -0,0 +1,21 @@
"use strict";
const Hello = {
toString() {
return 'hello';
}
};
const Outer = {
constructor() {
class Inner {
[super.toString()]() {
return 'hello';
}
}
return new Inner();
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
const Hello = {
toString() {
return 'hello';
}
};
const Outer = {
constructor() {
class Inner {
[super.toString()]() {
return 'hello';
}
}
return new Inner();
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -0,0 +1,23 @@
"use strict";
var _obj;
const Hello = {
toString: function () {
return 'hello';
}
};
const Outer = _obj = {
constructor: function () {
class Inner {
[babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "toString", this).call(this)]() {
return 'hello';
}
}
return new Inner();
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
const Hello = {
toString() {
return 'hello';
}
};
const Outer = {
constructor() {
const Inner = {
[super.toString()]() {
return 'hello';
},
};
return Inner;
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
const Hello = {
toString() {
return 'hello';
}
};
const Outer = {
constructor() {
const Inner = {
[super.toString()]() {
return 'hello';
},
};
return Inner;
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -0,0 +1,21 @@
"use strict";
var _obj;
const Hello = {
toString: function () {
return 'hello';
}
};
const Outer = _obj = {
constructor: function () {
const Inner = {
[babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "toString", this).call(this)]: function () {
return 'hello';
}
};
return Inner;
}
};
Object.setPrototypeOf(Outer, Hello);
assert.equal(Outer.constructor().hello(), 'hello');

View File

@ -1,13 +1,13 @@
var _obj; var _obj;
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); } function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); }
function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; } function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); } function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); }

View File

@ -0,0 +1,15 @@
var Base = {
test: '1',
};
var obj = {
bar() {
return super.test++;
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 1);
assert.strictEqual(Base.test, '1');
// TODO(jridgewell): Post #7687, uncomment this.
// assert.strictEqual(obj.test, 2);

View File

@ -0,0 +1,14 @@
var Base = {
test: '1',
};
var obj = {
bar() {
return super.test++;
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 1);
assert.strictEqual(Base.test, '1');
assert.strictEqual(obj.test, 2);

View File

@ -0,0 +1,16 @@
var _obj;
var Base = {
test: '1'
};
var obj = _obj = {
bar: function () {
var _ref;
return _ref = Number(babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this)), babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", _ref + 1, this, false), _ref;
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 1);
assert.strictEqual(Base.test, '1');
assert.strictEqual(obj.test, 2);

View File

@ -0,0 +1,15 @@
var Base = {
test: '1',
};
var obj = {
bar() {
return ++super.test;
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 2);
assert.strictEqual(Base.test, '1');
// TODO(jridgewell): Post #7687, uncomment this.
// assert.strictEqual(obj.test, 2);

View File

@ -0,0 +1,14 @@
var Base = {
test: '1',
};
var obj = {
bar() {
return ++super.test;
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 2);
assert.strictEqual(Base.test, '1');
assert.strictEqual(obj.test, 2);

View File

@ -0,0 +1,16 @@
var _obj;
var Base = {
test: '1'
};
var obj = _obj = {
bar: function () {
var _ref;
return _ref = Number(babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this)), babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", _ref + 1, this, false);
}
};
Object.setPrototypeOf(obj, Base);
assert.strictEqual(obj.bar(), 2);
assert.strictEqual(Base.test, '1');
assert.strictEqual(obj.test, 2);