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:
parent
af3d6526e7
commit
ecbf0dd53c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/options.json
vendored
Normal file
3
packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": ["external-helpers", "proposal-class-properties", "transform-classes"]
|
||||
}
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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); }
|
||||
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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');
|
||||
@ -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); }
|
||||
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
Loading…
x
Reference in New Issue
Block a user