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();
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.
* Uses CLASS.__proto__ first for InternetExplorer <= 10 support
*
* @example <caption>isStatic === true</caption>
*
* CLASS.__proto__ || Object.getPrototypeOf(CLASS)
* helpers.getPrototypeOf(CLASS)
*
* @example <caption>isStatic === false</caption>
*
* CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype)
* helpers.getPrototypeOf(CLASS.prototype)
*/
function getPrototypeOfExpression(objectRef, isStatic, file) {
objectRef = t.cloneNode(objectRef);
const targetRef = isStatic
? objectRef
: t.memberExpression(objectRef, t.identifier("prototype"));
return t.callExpression(file.addHelper("getPrototypeOf"), [
t.cloneNode(targetRef),
]);
return t.callExpression(file.addHelper("getPrototypeOf"), [targetRef]);
}
const visitor = {
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();
// 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) {
@ -59,33 +66,15 @@ const visitor = {
}
},
enter(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) {
Super(path, state) {
state.hasSuper = true;
}
if (isBareSuper) {
state.bareSupers.push(path);
}
if (result === true) {
path.requeue();
}
if (result !== true && result) {
if (Array.isArray(result)) {
path.replaceWithMultiple(result);
} else {
path.replaceWith(result);
}
const { node, parentPath } = path;
if (parentPath.isCallExpression({ callee: node })) {
state.bareSupers.add(parentPath);
return;
}
state[state.isLoose ? "looseHandle" : "specHandle"](path);
},
};
@ -104,7 +93,7 @@ export default class ReplaceSupers {
this.file = opts.file;
this.opts = opts;
this.bareSupers = [];
this.bareSupers = new Set();
this.returns = [];
this.thises = [];
}
@ -141,8 +130,7 @@ export default class ReplaceSupers {
*
* @example
*
* _set(CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE",
* this, isStrict)
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this, isStrict)
*
*/
@ -166,7 +154,7 @@ export default class ReplaceSupers {
*
* @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);
}
getLooseSuperProperty(id: Object, parent: Object) {
const methodNode = this.methodNode;
const superRef = this.superRef || t.identifier("Function");
getLooseSuperProperty(path) {
const { isStatic, superRef } = this;
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
return;
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> objectRef.prototype.test
return t.memberExpression(
t.cloneNode(superRef),
let object;
if (isStatic) {
object = superRef
? t.cloneNode(superRef)
: t.memberExpression(
t.identifier("Function"),
t.identifier("prototype"),
);
} 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) {
const node = path.node;
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;
const { node, parentPath } = path;
// super.test(); -> objectRef.prototype.MethodName.call(this);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(t.thisExpression());
return true;
// super.test
if (parentPath.isMemberExpression({ object: node })) {
this.getLooseSuperProperty(parentPath);
}
// 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) {
if (node.operator === "=") {
specHandleAssignmentExpression(path) {
const { node } = path;
const { operator } = node;
const { computed, property } = node.left;
if (operator === "=") {
// super.name = "val"
// to
// _set(Object.getPrototypeOf(objectRef.prototype), "name", this, isStrict);
return this.setSuperProperty(
node.left.property,
// _set(Object.getPrototypeOf(CLASS.prototype), "name", this);
const setter = this.setSuperProperty(
property,
node.right,
node.left.computed,
computed,
path.isInStrictMode(),
);
} else {
// super.age += 2
return [setter];
}
// super.age += 2;
// to
// let _ref = super.age; super.age = _ref + 2;
ref = ref || path.scope.generateUidIdentifier("ref");
// _set(
// 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 [
t.variableDeclaration("var", [
t.variableDeclarator(t.cloneNode(ref), t.cloneNode(node.left)),
]),
t.expressionStatement(
t.assignmentExpression(
"=",
node.left,
t.binaryExpression(
node.operator.slice(0, -1),
t.cloneNode(ref),
node.right,
),
),
this.getSuperProperty(property, computed),
),
setter,
];
}
}
specHandle(path: NodePath) {
let property;
let computed;
let args;
const { node, parentPath } = path;
const grandParentPath = parentPath.parentPath;
let parent = parentPath.node;
const parent = path.parent;
const node = path.node;
if (isIllegalBareSuper(node, parent)) {
throw path.buildCodeFrameError("Illegal use of bare super");
}
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,
if (grandParentPath.isUpdateExpression({ argument: parent })) {
const { operator, prefix } = grandParentPath.node;
const assignment = t.assignmentExpression(
operator[0] + "=",
parent,
t.numericLiteral(1),
);
if (node.prefix) {
grandParentPath.replaceWith(assignment);
// ++super.foo;
// to
// super.foo += 1;
return this.specHandleAssignmentExpression(null, path, binary);
} else {
// _ref = Number(super.foo), super.foo = _ref + 1
// super.foo++;
// to
// let _ref = super.foo; super.foo = _ref + 1;
const ref = path.scope.generateUidIdentifier("ref");
return this.specHandleAssignmentExpression(ref, path, binary).concat(
t.expressionStatement(ref),
// _ref = Number(super.foo), super.foo = _ref + 1, _ref
const nodes = this.specHandleAssignmentExpression(grandParentPath);
const [first] = nodes;
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),
);
}
} else if (
t.isAssignmentExpression(node) &&
isMemberExpressionSuper(node.left)
) {
return this.specHandleAssignmentExpression(null, path, node);
return;
}
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) {
return this.optimiseCall(superProperty, args);
} else {
return superProperty;
if (grandParentPath.isCallExpression({ callee: parent })) {
// _get(Object.getPrototypeOf(CLASS.prototype), "test", this)();
// to
// _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: {},
staticPropBody: [],
body: [],
bareSupers: [],
bareSupers: new Set(),
superThises: [],
pushedConstructor: false,
pushedInherits: false,
@ -388,7 +388,7 @@ export default function transformClass(
path.traverse(findThisesVisitor);
let guaranteedSuperBeforeFinish = !!classState.bareSupers.length;
let guaranteedSuperBeforeFinish = !!classState.bareSupers.size;
const superRef = classState.superName || t.identifier("Function");
let thisRef = function() {

View File

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

View File

@ -29,7 +29,7 @@ function (_Point) {
babelHelpers.classCallCheck(this, ColorPoint);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(ColorPoint).call(this));
_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(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;
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, 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 _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 _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;
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, 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 _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 _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);