add class property initializers, add more TraversalPath flexibility with additional node injection method
This commit is contained in:
@@ -710,27 +710,29 @@ acorn.plugins.flow = function (instance) {
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassProperty", function (inner) {
|
||||
return function (node) {
|
||||
if (this.type === tt.colon) {
|
||||
node.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
}
|
||||
return inner.call(this, node)
|
||||
}
|
||||
})
|
||||
instance.extend("isClassProperty", function (inner) {
|
||||
return function () {
|
||||
return this.type === tt.colon || inner.call(this)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassMethod", function (inner) {
|
||||
return function (classBody, method, isGenerator, isAsync) {
|
||||
var classProperty = false
|
||||
|
||||
if (this.type === tt.colon) {
|
||||
method.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
classProperty = true
|
||||
}
|
||||
|
||||
if (classProperty) {
|
||||
this.semicolon()
|
||||
classBody.body.push(this.finishNode(method, "ClassProperty"))
|
||||
} else {
|
||||
var typeParameters
|
||||
if (this.isRelational("<")) {
|
||||
typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
method.value = this.parseMethod(isGenerator, isAsync)
|
||||
method.value.typeParameters = typeParameters
|
||||
classBody.body.push(this.finishNode(method, "MethodDefinition"))
|
||||
var typeParameters
|
||||
if (this.isRelational("<")) {
|
||||
typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
method.value = this.parseMethod(isGenerator, isAsync)
|
||||
method.value.typeParameters = typeParameters
|
||||
classBody.body.push(this.finishNode(method, "MethodDefinition"))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -418,6 +418,7 @@ pp.parseParenAndDistinguishExpression = function(start, isAsync) {
|
||||
par.expression = val
|
||||
return this.finishNode(par, "ParenthesizedExpression")
|
||||
} else {
|
||||
val.parenthesizedExpression = true
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,14 @@ const pp = Parser.prototype
|
||||
// if possible.
|
||||
|
||||
pp.toAssignable = function(node, isBinding) {
|
||||
if (node.parenthesizedExpression) {
|
||||
if (node.type === "ObjectExpression") {
|
||||
this.raise(node.start, "You're trying to assign to a parenthesized expression, instead of `({ foo }) = {}` use `({ foo } = {})`");
|
||||
} else {
|
||||
this.raise(node.start, "Parenthesized left hand expressions are illegal");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ecmaVersion >= 6 && node) {
|
||||
switch (node.type) {
|
||||
case "Identifier":
|
||||
|
||||
@@ -150,10 +150,17 @@ pp.parseDebuggerStatement = function(node) {
|
||||
}
|
||||
|
||||
pp.parseDoStatement = function(node) {
|
||||
let start = this.markPosition()
|
||||
this.next()
|
||||
this.labels.push(loopLabel)
|
||||
node.body = this.parseStatement(false)
|
||||
this.labels.pop()
|
||||
if (this.options.features["es7.doExpressions"] && this.type !== tt._while) {
|
||||
let container = this.startNodeAt(start)
|
||||
container.expression = this.finishNode(node, "DoExpression")
|
||||
this.semicolon()
|
||||
return this.finishNode(container, "ExpressionStatement")
|
||||
}
|
||||
this.expect(tt._while)
|
||||
node.test = this.parseParenExpression()
|
||||
if (this.options.ecmaVersion >= 6)
|
||||
@@ -455,13 +462,17 @@ pp.parseClass = function(node, isStatement) {
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (this.eat(tt.semi)) continue
|
||||
if (this.options.features["es7.decorators"] && this.type === tt.at) {
|
||||
decorators.push(this.parseDecorator());
|
||||
decorators.push(this.parseDecorator())
|
||||
continue;
|
||||
}
|
||||
var method = this.startNode()
|
||||
if (this.options.features["es7.decorators"] && decorators.length) {
|
||||
method.decorators = decorators
|
||||
decorators = []
|
||||
}
|
||||
var isGenerator = this.eat(tt.star), isAsync = false
|
||||
this.parsePropertyName(method)
|
||||
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
||||
if (this.options.features["es7.classProperties"] && this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
||||
method.key.name === "static") {
|
||||
if (isGenerator) this.unexpected()
|
||||
method['static'] = true
|
||||
@@ -470,6 +481,10 @@ pp.parseClass = function(node, isStatement) {
|
||||
} else {
|
||||
method['static'] = false
|
||||
}
|
||||
if (!isGenerator && method.key.type === "Identifier" && !method.computed && this.isClassProperty()) {
|
||||
classBody.body.push(this.parseClassProperty(method))
|
||||
continue
|
||||
}
|
||||
if (this.options.features["es7.asyncFunctions"] && this.type !== tt.parenL &&
|
||||
!method.computed && method.key.type === "Identifier" && method.key.name === "async") {
|
||||
isAsync = true
|
||||
@@ -488,9 +503,8 @@ pp.parseClass = function(node, isStatement) {
|
||||
method.kind = "constructor"
|
||||
}
|
||||
}
|
||||
if (this.options.features["es7.decorators"] && decorators.length) {
|
||||
method.decorators = decorators
|
||||
decorators = []
|
||||
if (method.kind === "constructor" && method.decorators) {
|
||||
this.raise(method.start, "You can't attach decorators to a class constructor")
|
||||
}
|
||||
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
||||
}
|
||||
@@ -501,16 +515,32 @@ pp.parseClass = function(node, isStatement) {
|
||||
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
|
||||
}
|
||||
|
||||
pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
|
||||
pp.isClassProperty = function() {
|
||||
return this.type === tt.eq || (this.type === tt.semi || this.canInsertSemicolon())
|
||||
}
|
||||
|
||||
pp.parseClassProperty = function(node) {
|
||||
if (this.type === tt.eq) {
|
||||
if (!this.options.features["es7.classProperties"]) this.unexpected()
|
||||
this.next()
|
||||
node.value = this.parseMaybeAssign();
|
||||
} else {
|
||||
node.value = null;
|
||||
}
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "ClassProperty")
|
||||
}
|
||||
|
||||
pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
|
||||
method.value = this.parseMethod(isGenerator, isAsync)
|
||||
classBody.body.push(this.finishNode(method, "MethodDefinition"))
|
||||
}
|
||||
|
||||
pp.parseClassId = function (node, isStatement) {
|
||||
pp.parseClassId = function(node, isStatement) {
|
||||
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null
|
||||
}
|
||||
|
||||
pp.parseClassSuper = function (node) {
|
||||
pp.parseClassSuper = function(node) {
|
||||
node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,12 @@ export function UnaryExpression(node, print) {
|
||||
print(node.argument);
|
||||
}
|
||||
|
||||
export function DoExpression(node, print) {
|
||||
this.push("do");
|
||||
this.space();
|
||||
print(node.body);
|
||||
}
|
||||
|
||||
export function UpdateExpression(node, print) {
|
||||
if (node.prefix) {
|
||||
this.push(node.operator);
|
||||
|
||||
@@ -51,7 +51,7 @@ export function toClassObject(mutatorMap) {
|
||||
if (key[0] === "_") return;
|
||||
|
||||
var inheritNode = node;
|
||||
if (t.isMethodDefinition(node)) node = node.value;
|
||||
if (t.isMethodDefinition(node) || t.isClassProperty(node)) node = node.value;
|
||||
|
||||
var prop = t.property("init", t.identifier(key), node);
|
||||
t.inheritsComments(prop, inheritNode);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
this.KEY = INITIALIZERS.KEY.call(this);
|
||||
@@ -0,0 +1 @@
|
||||
CONSTRUCTOR.KEY = INITIALIZERS.KEY.call(CONSTRUCTOR);
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
function defineProperties(target, descriptors) {
|
||||
function defineProperties(target, descriptors, initializers) {
|
||||
for (var i = 0; i < descriptors.length; i ++) {
|
||||
var descriptor = descriptors[i];
|
||||
var decorators = descriptor.decorators;
|
||||
@@ -23,15 +23,16 @@
|
||||
throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator);
|
||||
}
|
||||
}
|
||||
initializers[key] = descriptor.initializer;
|
||||
}
|
||||
|
||||
Object.defineProperty(target, key, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return function (Constructor, protoProps, staticProps) {
|
||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||
if (staticProps) defineProperties(Constructor, staticProps);
|
||||
return function (Constructor, protoProps, staticProps, protoInitializers, staticInitializers) {
|
||||
if (protoProps) defineProperties(Constructor.prototype, protoProps, protoInitializers);
|
||||
if (staticProps) defineProperties(Constructor, staticProps, staticInitializers);
|
||||
return Constructor;
|
||||
};
|
||||
})()
|
||||
|
||||
@@ -375,7 +375,7 @@ class BlockScoping {
|
||||
var hasAsync = traverse.hasType(fn.body, this.scope, "AwaitExpression", t.FUNCTION_TYPES);
|
||||
if (hasAsync) {
|
||||
fn.async = true;
|
||||
call = t.awaitExpression(call, true);
|
||||
call = t.awaitExpression(call);
|
||||
}
|
||||
|
||||
this.build(ret, call);
|
||||
|
||||
@@ -4,6 +4,8 @@ import * as defineMap from "../../helpers/define-map";
|
||||
import * as messages from "../../../messages";
|
||||
import * as util from "../../../util";
|
||||
import traverse from "../../../traversal";
|
||||
import each from "lodash/collection/each";
|
||||
import has from "lodash/object/has";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isClass;
|
||||
@@ -35,6 +37,7 @@ var verifyConstructorVisitor = traverse.explode({
|
||||
enter(node, parent, scope, state) {
|
||||
if (this.get("callee").isSuper()) {
|
||||
state.hasBareSuper = true;
|
||||
state.bareSuper = this;
|
||||
|
||||
if (!state.hasSuper) {
|
||||
throw this.errorWithNode("super call is only allowed in derived constructor");
|
||||
@@ -65,14 +68,18 @@ class ClassTransformer {
|
||||
this.path = path;
|
||||
this.file = file;
|
||||
|
||||
this.hasInstanceMutators = false;
|
||||
this.hasStaticMutators = false;
|
||||
this.hasDecorators = false;
|
||||
this.hasInstanceDescriptors = false;
|
||||
this.hasStaticDescriptors = false;
|
||||
|
||||
this.instanceMutatorMap = {};
|
||||
this.staticMutatorMap = {};
|
||||
|
||||
this.instancePropBody = [];
|
||||
this.staticPropBody = [];
|
||||
this.body = [];
|
||||
|
||||
this.hasConstructor = false;
|
||||
this.hasDecorators = false;
|
||||
this.className = this.node.id;
|
||||
this.classRef = this.node.id || this.scope.generateUidIdentifier("class");
|
||||
|
||||
@@ -97,17 +104,11 @@ class ClassTransformer {
|
||||
|
||||
//
|
||||
|
||||
var body = this.body = [];
|
||||
var body = this.body;
|
||||
|
||||
//
|
||||
|
||||
var constructorBody = t.blockStatement([
|
||||
t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [
|
||||
t.thisExpression(),
|
||||
classRef
|
||||
]))
|
||||
]);
|
||||
|
||||
var constructorBody = this.constructorBody = t.blockStatement([]);
|
||||
var constructor;
|
||||
|
||||
if (this.className) {
|
||||
@@ -140,6 +141,13 @@ class ClassTransformer {
|
||||
|
||||
this.buildBody();
|
||||
|
||||
constructorBody.body.unshift(t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [
|
||||
t.thisExpression(),
|
||||
classRef
|
||||
])));
|
||||
|
||||
//
|
||||
|
||||
var decorators = this.node.decorators;
|
||||
if (decorators) {
|
||||
for (var i = 0; i < decorators.length; i++) {
|
||||
@@ -165,6 +173,8 @@ class ClassTransformer {
|
||||
t.inheritsComments(body[0], this.node);
|
||||
}
|
||||
|
||||
body = body.concat(this.staticPropBody);
|
||||
|
||||
//
|
||||
|
||||
body.push(t.returnStatement(classRef));
|
||||
@@ -175,16 +185,69 @@ class ClassTransformer {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
pushToMap(node, enumerable, kind = "value") {
|
||||
var mutatorMap;
|
||||
if (node.static) {
|
||||
this.hasStaticDescriptors = true;
|
||||
mutatorMap = this.staticMutatorMap;
|
||||
} else {
|
||||
this.hasInstanceDescriptors = true;
|
||||
mutatorMap = this.instanceMutatorMap;
|
||||
}
|
||||
|
||||
var alias = t.toKeyAlias(node);
|
||||
|
||||
//
|
||||
|
||||
var map = {};
|
||||
if (has(mutatorMap, alias)) map = mutatorMap[alias];
|
||||
mutatorMap[alias] = map;
|
||||
|
||||
//
|
||||
|
||||
map._inherits ||= [];
|
||||
map._inherits.push(node);
|
||||
|
||||
map._key = node.key;
|
||||
|
||||
if (enumerable) {
|
||||
map.enumerable = t.literal(true)
|
||||
}
|
||||
|
||||
if (node.computed) {
|
||||
map._computed = true;
|
||||
}
|
||||
|
||||
if (node.decorators) {
|
||||
this.hasDecorators = true;
|
||||
var decorators = map.decorators ||= t.arrayExpression([]);
|
||||
decorators.elements = decorators.elements.concat(node.decorators.map(dec => dec.expression));
|
||||
}
|
||||
|
||||
if (map.value || map.initializer) {
|
||||
throw this.file.errorWithNode(node, "Key conflict with sibling node");
|
||||
}
|
||||
|
||||
if (node.kind === "get") kind = "get";
|
||||
if (node.kind === "set") kind = "set";
|
||||
map[kind] = node.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
buildBody() {
|
||||
var constructor = this.constructor;
|
||||
var className = this.className;
|
||||
var superName = this.superName;
|
||||
var classBody = this.node.body.body;
|
||||
var body = this.body;
|
||||
var constructorBody = this.constructorBody;
|
||||
var constructor = this.constructor;
|
||||
var className = this.className;
|
||||
var superName = this.superName;
|
||||
var classBody = this.node.body.body;
|
||||
var body = this.body;
|
||||
|
||||
var classBodyPaths = this.path.get("body").get("body");
|
||||
|
||||
@@ -220,22 +283,30 @@ class ClassTransformer {
|
||||
if (!this.hasConstructor && this.hasSuper) {
|
||||
var helperName = "class-super-constructor-call";
|
||||
if (this.isLoose) helperName += "-loose";
|
||||
constructor.body.body.push(util.template(helperName, {
|
||||
constructorBody.body.push(util.template(helperName, {
|
||||
CLASS_NAME: className,
|
||||
SUPER_NAME: this.superName
|
||||
}, true));
|
||||
}
|
||||
|
||||
//
|
||||
this.placePropertyInitializers();
|
||||
|
||||
//
|
||||
if (this.userConstructor) {
|
||||
constructorBody.body = constructorBody.body.concat(this.userConstructor.body.body);
|
||||
}
|
||||
|
||||
var instanceProps;
|
||||
var staticProps;
|
||||
var classHelper = "create-class";
|
||||
if (this.hasDecorators) classHelper = "create-decorated-class";
|
||||
|
||||
if (this.hasInstanceMutators) {
|
||||
if (this.hasInstanceDescriptors) {
|
||||
instanceProps = defineMap.toClassObject(this.instanceMutatorMap);
|
||||
}
|
||||
|
||||
if (this.hasStaticMutators) {
|
||||
if (this.hasStaticDescriptors) {
|
||||
staticProps = defineMap.toClassObject(this.staticMutatorMap);
|
||||
}
|
||||
|
||||
@@ -243,10 +314,30 @@ class ClassTransformer {
|
||||
if (instanceProps) instanceProps = defineMap.toComputedObjectFromClass(instanceProps);
|
||||
if (staticProps) staticProps = defineMap.toComputedObjectFromClass(staticProps);
|
||||
|
||||
instanceProps ||= t.literal(null);
|
||||
var nullNode = t.literal(null);
|
||||
|
||||
// (Constructor, instanceDescriptors, staticDescriptors, instanceInitializers, staticInitializers)
|
||||
var args = [this.classRef, nullNode, nullNode, nullNode, nullNode];
|
||||
|
||||
if (instanceProps) args[1] = instanceProps;
|
||||
if (staticProps) args[2] = staticProps;
|
||||
|
||||
if (this.instanceInitializersId) {
|
||||
args[3] = this.instanceInitializersId;
|
||||
body.unshift(this.buildObjectAssignment(this.instanceInitializersId));
|
||||
}
|
||||
|
||||
if (this.staticInitializersId) {
|
||||
args[4] = this.staticInitializersId;
|
||||
body.unshift(this.buildObjectAssignment(this.staticInitializersId));
|
||||
}
|
||||
|
||||
var lastNonNullIndex = 0;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (args[i] !== nullNode) lastNonNullIndex = i;
|
||||
}
|
||||
args = args.slice(0, lastNonNullIndex + 1);
|
||||
|
||||
var args = [this.classRef, instanceProps];
|
||||
if (staticProps) args.push(staticProps);
|
||||
|
||||
body.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper(classHelper), args)
|
||||
@@ -254,6 +345,32 @@ class ClassTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
buildObjectAssignment(id) {
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(id, t.objectExpression([]))
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
placePropertyInitializers() {
|
||||
var body = this.instancePropBody;
|
||||
if (body.length) {
|
||||
// todo: check for scope conflicts and shift into a method
|
||||
if (this.hasSuper) {
|
||||
if (this.bareSuper) {
|
||||
this.bareSuper.insertAfter(body);
|
||||
} else {
|
||||
this.constructorBody.body = this.constructorBody.body.concat(body);
|
||||
}
|
||||
} else {
|
||||
this.constructorBody.body = body.concat(this.constructorBody.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
@@ -261,12 +378,15 @@ class ClassTransformer {
|
||||
verifyConstructor(path: TraversalPath) {
|
||||
var state = {
|
||||
hasBareSuper: false,
|
||||
bareSuper: null,
|
||||
hasSuper: this.hasSuper,
|
||||
file: this.file
|
||||
};
|
||||
|
||||
path.traverse(verifyConstructorVisitor, state);
|
||||
|
||||
this.bareSuper = state.bareSuper;
|
||||
|
||||
if (!state.hasBareSuper && this.hasSuper) {
|
||||
throw path.errorWithNode("Derived constructor must call super()");
|
||||
}
|
||||
@@ -277,11 +397,7 @@ class ClassTransformer {
|
||||
*/
|
||||
|
||||
pushMethod(node: { type: "MethodDefinition" }) {
|
||||
var methodName = node.key;
|
||||
|
||||
var kind = node.kind;
|
||||
|
||||
if (kind === "method") {
|
||||
if (node.kind === "method") {
|
||||
nameMethod.property(node, this.file, this.scope);
|
||||
|
||||
if (this.isLoose) {
|
||||
@@ -289,56 +405,56 @@ class ClassTransformer {
|
||||
|
||||
var classRef = this.classRef;
|
||||
if (!node.static) classRef = t.memberExpression(classRef, t.identifier("prototype"));
|
||||
methodName = t.memberExpression(classRef, methodName, node.computed);
|
||||
var methodName = t.memberExpression(classRef, node.key, node.computed);
|
||||
|
||||
var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
|
||||
t.inheritsComments(expr, node);
|
||||
this.body.push(expr);
|
||||
return;
|
||||
}
|
||||
|
||||
kind = "value";
|
||||
}
|
||||
|
||||
var mutatorMap = this.instanceMutatorMap;
|
||||
if (node.static) {
|
||||
this.hasStaticMutators = true;
|
||||
mutatorMap = this.staticMutatorMap;
|
||||
} else {
|
||||
this.hasInstanceMutators = true;
|
||||
}
|
||||
|
||||
defineMap.push(mutatorMap, methodName, kind, node.computed, node);
|
||||
|
||||
var decorators = node.decorators;
|
||||
if (decorators && decorators.length) {
|
||||
for (var i = 0; i < decorators.length; i++) {
|
||||
decorators[i] = decorators[i].expression;
|
||||
}
|
||||
defineMap.push(mutatorMap, methodName, "decorators", node.computed, t.arrayExpression(decorators));
|
||||
this.hasDecorators = true;
|
||||
}
|
||||
this.pushToMap(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
pushProperty(node: Object) {
|
||||
if (!node.value) return;
|
||||
pushProperty(node: { type: "ClassProperty" }) {
|
||||
if (!node.value && !node.decorators) return;
|
||||
|
||||
var key;
|
||||
|
||||
if (node.static) {
|
||||
key = t.memberExpression(this.classRef, node.key);
|
||||
this.body.push(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
if (node.decorators) {
|
||||
var body = [];
|
||||
if (node.value) body.push(t.returnStatement(node.value));
|
||||
node.value = t.functionExpression(null, [], t.blockStatement(body));
|
||||
this.pushToMap(node, true, "initializer");
|
||||
|
||||
if (node.static) {
|
||||
this.staticPropBody.push(util.template("call-static-decorator", {
|
||||
INITIALIZERS: this.staticInitializersId ||= this.scope.generateUidIdentifier("staticInitializers"),
|
||||
CONSTRUCTOR: this.classRef,
|
||||
KEY: node.key,
|
||||
}, true));
|
||||
} else {
|
||||
this.instancePropBody.push(util.template("call-instance-decorator", {
|
||||
INITIALIZERS: this.instanceInitializersId ||= this.scope.generateUidIdentifier("instanceInitializers"),
|
||||
KEY: node.key
|
||||
}, true));
|
||||
}
|
||||
} else {
|
||||
key = t.memberExpression(t.thisExpression(), node.key);
|
||||
this.constructor.body.body.unshift(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
if (node.static) {
|
||||
// can just be added to the static map
|
||||
this.pushToMap(node, true);
|
||||
} else {
|
||||
// add this to the instancePropBody which will be added after the super call in a derived constructor
|
||||
// or at the start of a constructor for a non-derived constructor
|
||||
this.instancePropBody.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", t.memberExpression(t.thisExpression(), node.key), node.value)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,7 +466,8 @@ class ClassTransformer {
|
||||
var construct = this.constructor;
|
||||
var fn = method.value;
|
||||
|
||||
this.hasConstructor = true;
|
||||
this.userConstructor = fn;
|
||||
this.hasConstructor = true;
|
||||
|
||||
t.inherits(construct, fn);
|
||||
t.inheritsComments(construct, method);
|
||||
@@ -359,6 +476,5 @@ class ClassTransformer {
|
||||
construct.params = fn.params;
|
||||
|
||||
t.inherits(construct.body, fn.body);
|
||||
construct.body.body = construct.body.body.concat(fn.body.body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export var metadata = {
|
||||
experimental: true,
|
||||
optional: true
|
||||
};
|
||||
|
||||
export function check() {
|
||||
return false;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ export var metadata = {
|
||||
optional: true
|
||||
};
|
||||
|
||||
export var check = t.isDoExpression;
|
||||
|
||||
export function DoExpression(node) {
|
||||
var body = node.body.body;
|
||||
if (body.length) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
"es7.classProperties": require("./es7/class-properties"),
|
||||
"es7.asyncFunctions": require("./es7/async-functions"),
|
||||
"es7.decorators": require("./es7/decorators"),
|
||||
|
||||
@@ -89,7 +90,7 @@ export default {
|
||||
// needs to be before `_shadowFunctions`
|
||||
"es6.arrowFunctions": require("./es6/arrow-functions"),
|
||||
|
||||
_shadowFunctions: require("./internal/alias-functions"),
|
||||
_shadowFunctions: require("./internal/shadow-functions"),
|
||||
|
||||
"es7.doExpressions": require("./es7/do-expressions"),
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ import * as t from "../../../types";
|
||||
|
||||
var functionChildrenVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (this.isClass(node)) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
if (this.isFunction() && !node.shadow) {
|
||||
return this.skip();
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export function FunctionExpression() {
|
||||
}
|
||||
|
||||
export { FunctionExpression as FunctionDeclaration };
|
||||
export { FunctionExpression as Class };
|
||||
|
||||
export function ThisExpression() {
|
||||
return t.identifier("undefined");
|
||||
|
||||
@@ -34,6 +34,7 @@ export default class TraversalContext {
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: handle nodes popping in and out of existence
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i] && this.visitNode(node, nodes, i)) {
|
||||
return true;
|
||||
|
||||
@@ -78,12 +78,41 @@ export default class TraversalPath {
|
||||
return ourScope;
|
||||
}
|
||||
|
||||
insertBefore(node) {
|
||||
|
||||
getParentArrayPath() {
|
||||
var path = this;
|
||||
while (!Array.isArray(path.container)) {
|
||||
path = path.parentPath;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
insertAfter(node) {
|
||||
insertBefore(nodes) {
|
||||
this.getParentArrayPath()._insertBefore(nodes);
|
||||
}
|
||||
|
||||
insertAfter(nodes) {
|
||||
this.getParentArrayPath()._insertAfter(nodes);
|
||||
}
|
||||
|
||||
_insertBefore(nodes) {
|
||||
throw new Error("to be implemented");
|
||||
}
|
||||
|
||||
_insertAfter(nodes) {
|
||||
// todo: in a statement context ie. BlockStatement or Program create individual statements instead
|
||||
// of trying to join them
|
||||
|
||||
var key = this.key + 1;
|
||||
this.container.splice(key, 0, null);
|
||||
|
||||
var paths = this.container._paths;
|
||||
for (var i = 0; i > paths.length; i++) {
|
||||
let path = paths[path];
|
||||
if (path.key >= key) path.key++;
|
||||
}
|
||||
|
||||
var path = TraversalPath.get(this.parentPath, null, this.parent, this.container, key, this.file);
|
||||
path.setStatementsToExpression(nodes);
|
||||
}
|
||||
|
||||
setData(key, val) {
|
||||
@@ -172,7 +201,7 @@ export default class TraversalPath {
|
||||
|
||||
// inherit comments from original node to the first replacement node
|
||||
var inheritTo = replacements[0];
|
||||
if (inheritTo) t.inheritsComments(inheritTo, oldNode);
|
||||
if (inheritTo && oldNode) t.inheritsComments(inheritTo, oldNode);
|
||||
|
||||
//
|
||||
if (t.isStatement(replacements[0]) && t.isType(this.type, "Expression")) {
|
||||
@@ -314,7 +343,12 @@ export default class TraversalPath {
|
||||
} else { // "foo"
|
||||
var path = this;
|
||||
for (var i = 0; i > parts.length; i++) {
|
||||
path = path.get(parts[i]);
|
||||
var part = parts[i];
|
||||
if (part === ".") {
|
||||
path = path.parentPath;
|
||||
} else {
|
||||
path = path.get(parts[i]);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
"id": null,
|
||||
"params": null,
|
||||
"body": null,
|
||||
"generator": false
|
||||
"generator": false,
|
||||
"async": false
|
||||
},
|
||||
|
||||
"FunctionDeclaration": {
|
||||
|
||||
@@ -72,8 +72,11 @@ export function getLastStatements(node: Object): Array<Object> {
|
||||
if (t.isIfStatement(node)) {
|
||||
add(node.consequent);
|
||||
add(node.alternate);
|
||||
} else if (t.isFor(node) || t.isWhile(node)) {
|
||||
add(node.body);
|
||||
} else if (t.isProgram(node) || t.isBlockStatement(node)) {
|
||||
add(node.body[node.body.length - 1]);
|
||||
} else if (t.isLoop()) {
|
||||
} else if (node) {
|
||||
nodes.push(node);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ArrayExpression": ["elements"],
|
||||
"ArrayPattern": ["elements", "typeAnnotation"],
|
||||
"ArrowFunctionExpression": ["params", "defaults", "rest", "body", "returnType"],
|
||||
"ArrowFunctionExpression": ["params", "body", "returnType"],
|
||||
"AssignmentExpression": ["left", "right"],
|
||||
"AssignmentPattern": ["left", "right"],
|
||||
"AwaitExpression": ["argument"],
|
||||
@@ -31,8 +31,8 @@
|
||||
"ForInStatement": ["left", "right", "body"],
|
||||
"ForOfStatement": ["left", "right", "body"],
|
||||
"ForStatement": ["init", "test", "update", "body"],
|
||||
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body", "returnType", "typeParameters"],
|
||||
"FunctionExpression": ["id", "params", "defaults", "rest", "body", "returnType", "typeParameters"],
|
||||
"FunctionDeclaration": ["id", "params", "body", "returnType", "typeParameters"],
|
||||
"FunctionExpression": ["id", "params", "body", "returnType", "typeParameters"],
|
||||
"Identifier": ["typeAnnotation"],
|
||||
"IfStatement": ["test", "consequent", "alternate"],
|
||||
"ImportDefaultSpecifier": ["local"],
|
||||
|
||||
Reference in New Issue
Block a user