75 lines
2.2 KiB
JavaScript
75 lines
2.2 KiB
JavaScript
var traverse = require("../../traverse");
|
|
var util = require("../../util");
|
|
var t = require("../../types");
|
|
|
|
exports.optional = true;
|
|
|
|
exports.Class = function (node) {
|
|
var superClass = node.superClass || t.identifier("Function");
|
|
|
|
var hasConstructor = false;
|
|
var body = node.body.body;
|
|
|
|
for (var i in body) {
|
|
var methodNode = body[i];
|
|
|
|
hasConstructor = hasConstructor || methodNode.key.name === "constructor";
|
|
|
|
traverse(methodNode, {
|
|
enter: function (node, parent) {
|
|
if (t.isIdentifier(node, { name: "super" })) {
|
|
return superIdentifier(superClass, methodNode, node, parent);
|
|
} else if (t.isCallExpression(node)) {
|
|
var callee = node.callee;
|
|
if (!t.isMemberExpression(callee)) return;
|
|
if (callee.object.name !== "super") return;
|
|
|
|
// super.test(); -> ClassName.prototype.MethodName.call(this);
|
|
t.appendToMemberExpression(callee, t.identifier("call"));
|
|
node.arguments.unshift(t.thisExpression());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
if (node.superClass && !hasConstructor) {
|
|
body.unshift(t.methodDefinition(
|
|
t.identifier("constructor"),
|
|
util.template("class-super-constructor-call-fast", {
|
|
SUPER_NAME: superClass
|
|
})
|
|
));
|
|
}
|
|
};
|
|
|
|
var superIdentifier = function (superClass, methodNode, id, parent) {
|
|
var methodName = methodNode.key;
|
|
|
|
if (parent.property === id) {
|
|
return;
|
|
} else if (t.isCallExpression(parent, { callee: id })) {
|
|
// super(); -> ClassName.prototype.MethodName.call(this);
|
|
parent.arguments.unshift(t.thisExpression());
|
|
|
|
if (methodName.name === "constructor") {
|
|
// constructor() { super(); }
|
|
return t.memberExpression(superClass, t.identifier("call"));
|
|
} else {
|
|
id = superClass;
|
|
|
|
// foo() { super(); }
|
|
if (!methodNode.static) {
|
|
id = t.memberExpression(id, t.identifier("prototype"));
|
|
}
|
|
|
|
id = t.memberExpression(id, methodName, methodNode.computed);
|
|
return t.memberExpression(id, t.identifier("call"));
|
|
}
|
|
} else if (t.isMemberExpression(parent) && !methodNode.static) {
|
|
// super.test -> ClassName.prototype.test
|
|
return t.memberExpression(superClass, t.identifier("prototype"));
|
|
} else {
|
|
return superClass;
|
|
}
|
|
};
|