better parsing of decorators - support class expressions
This commit is contained in:
parent
e52af24999
commit
f5f77d4720
@ -335,8 +335,13 @@ pp.parseExprAtom = function(refShorthandDefaultPos) {
|
|||||||
this.next()
|
this.next()
|
||||||
return this.parseFunction(node, false)
|
return this.parseFunction(node, false)
|
||||||
|
|
||||||
|
case tt.at:
|
||||||
|
this.parseDecorators()
|
||||||
|
|
||||||
case tt._class:
|
case tt._class:
|
||||||
return this.parseClass(this.startNode(), false)
|
node = this.startNode()
|
||||||
|
this.takeDecorators(node)
|
||||||
|
return this.parseClass(node, false)
|
||||||
|
|
||||||
case tt._new:
|
case tt._new:
|
||||||
return this.parseNew()
|
return this.parseNew()
|
||||||
|
|||||||
@ -53,19 +53,11 @@ pp.parseStatement = function(declaration, topLevel) {
|
|||||||
return this.parseFunctionStatement(node)
|
return this.parseFunctionStatement(node)
|
||||||
|
|
||||||
case tt.at:
|
case tt.at:
|
||||||
while (this.type === tt.at) {
|
this.parseDecorators()
|
||||||
this.decorators.push(this.parseDecorator());
|
|
||||||
}
|
|
||||||
if (this.type !== tt._class) {
|
|
||||||
this.raise(this.start, "Leading decorators must be attached to a class declaration");
|
|
||||||
}
|
|
||||||
|
|
||||||
case tt._class:
|
case tt._class:
|
||||||
if (!declaration) this.unexpected()
|
if (!declaration) this.unexpected()
|
||||||
if (this.decorators.length) {
|
this.takeDecorators(node)
|
||||||
node.decorators = this.decorators
|
|
||||||
this.decorators = []
|
|
||||||
}
|
|
||||||
return this.parseClass(node, true)
|
return this.parseClass(node, true)
|
||||||
|
|
||||||
case tt._if: return this.parseIfStatement(node)
|
case tt._if: return this.parseIfStatement(node)
|
||||||
@ -90,14 +82,10 @@ pp.parseStatement = function(declaration, topLevel) {
|
|||||||
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node)
|
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node)
|
||||||
|
|
||||||
case tt.name:
|
case tt.name:
|
||||||
if (this.options.features["es7.asyncFunctions"] && this.value === "async") {
|
if (this.options.features["es7.asyncFunctions"] && this.value === "async" && this.lookahead().type === tt._function) {
|
||||||
// check to see if `function ` appears after this token, this is
|
this.next();
|
||||||
// pretty hacky
|
this.expect(tt._function);
|
||||||
if (this.lookahead().type === tt._function) {
|
return this.parseFunction(node, true, false, true);
|
||||||
this.next();
|
|
||||||
this.expect(tt._function);
|
|
||||||
return this.parseFunction(node, true, false, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the statement does not start with a statement keyword or a
|
// If the statement does not start with a statement keyword or a
|
||||||
@ -113,7 +101,26 @@ pp.parseStatement = function(declaration, topLevel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp.takeDecorators = function(node) {
|
||||||
|
if (this.decorators.length) {
|
||||||
|
node.decorators = this.decorators
|
||||||
|
this.decorators = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pp.parseDecorators = function() {
|
||||||
|
while (this.type === tt.at) {
|
||||||
|
this.decorators.push(this.parseDecorator());
|
||||||
|
}
|
||||||
|
if (this.type !== tt._class) {
|
||||||
|
this.raise(this.start, "Leading decorators must be attached to a class declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pp.parseDecorator = function() {
|
pp.parseDecorator = function() {
|
||||||
|
if (!this.options.features["es7.decorators"]) {
|
||||||
|
this.unexpected()
|
||||||
|
}
|
||||||
let node = this.startNode()
|
let node = this.startNode()
|
||||||
this.next()
|
this.next()
|
||||||
node.expression = this.parseMaybeAssign()
|
node.expression = this.parseMaybeAssign()
|
||||||
@ -466,10 +473,7 @@ pp.parseClass = function(node, isStatement) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var method = this.startNode()
|
var method = this.startNode()
|
||||||
if (this.options.features["es7.decorators"] && decorators.length) {
|
this.takeDecorators(method)
|
||||||
method.decorators = decorators
|
|
||||||
decorators = []
|
|
||||||
}
|
|
||||||
var isGenerator = this.eat(tt.star), isAsync = false
|
var isGenerator = this.eat(tt.star), isAsync = false
|
||||||
this.parsePropertyName(method)
|
this.parsePropertyName(method)
|
||||||
if (this.options.features["es7.classProperties"] && 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" &&
|
||||||
@ -509,7 +513,7 @@ pp.parseClass = function(node, isStatement) {
|
|||||||
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
||||||
}
|
}
|
||||||
if (decorators.length) {
|
if (decorators.length) {
|
||||||
raise(this.start, "You have trailing decorators with no method");
|
this.raise(this.start, "You have trailing decorators with no method");
|
||||||
}
|
}
|
||||||
node.body = this.finishNode(classBody, "ClassBody")
|
node.body = this.finishNode(classBody, "ClassBody")
|
||||||
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
|
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user