add support for decorators before class exports
This commit is contained in:
parent
f5f77d4720
commit
5f6a216809
@ -37,6 +37,10 @@ const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}
|
|||||||
// does not help.
|
// does not help.
|
||||||
|
|
||||||
pp.parseStatement = function(declaration, topLevel) {
|
pp.parseStatement = function(declaration, topLevel) {
|
||||||
|
if (this.type === tt.at) {
|
||||||
|
this.parseDecorators(true)
|
||||||
|
}
|
||||||
|
|
||||||
let starttype = this.type, node = this.startNode()
|
let starttype = this.type, node = this.startNode()
|
||||||
|
|
||||||
// Most types of statements are recognized by the keyword they
|
// Most types of statements are recognized by the keyword they
|
||||||
@ -52,9 +56,6 @@ pp.parseStatement = function(declaration, topLevel) {
|
|||||||
if (!declaration && this.options.ecmaVersion >= 6) this.unexpected()
|
if (!declaration && this.options.ecmaVersion >= 6) this.unexpected()
|
||||||
return this.parseFunctionStatement(node)
|
return this.parseFunctionStatement(node)
|
||||||
|
|
||||||
case tt.at:
|
|
||||||
this.parseDecorators()
|
|
||||||
|
|
||||||
case tt._class:
|
case tt._class:
|
||||||
if (!declaration) this.unexpected()
|
if (!declaration) this.unexpected()
|
||||||
this.takeDecorators(node)
|
this.takeDecorators(node)
|
||||||
@ -108,16 +109,21 @@ pp.takeDecorators = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pp.parseDecorators = function() {
|
pp.parseDecorators = function(allowExport) {
|
||||||
while (this.type === tt.at) {
|
while (this.type === tt.at) {
|
||||||
this.decorators.push(this.parseDecorator());
|
this.decorators.push(this.parseDecorator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allowExport && this.type === tt._export) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.type !== tt._class) {
|
if (this.type !== tt._class) {
|
||||||
this.raise(this.start, "Leading decorators must be attached to a class declaration");
|
this.raise(this.start, "Leading decorators must be attached to a class declaration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pp.parseDecorator = function() {
|
pp.parseDecorator = function(allowExport) {
|
||||||
if (!this.options.features["es7.decorators"]) {
|
if (!this.options.features["es7.decorators"]) {
|
||||||
this.unexpected()
|
this.unexpected()
|
||||||
}
|
}
|
||||||
@ -465,11 +471,10 @@ pp.parseClass = function(node, isStatement) {
|
|||||||
var classBody = this.startNode()
|
var classBody = this.startNode()
|
||||||
classBody.body = []
|
classBody.body = []
|
||||||
this.expect(tt.braceL)
|
this.expect(tt.braceL)
|
||||||
var decorators = []
|
|
||||||
while (!this.eat(tt.braceR)) {
|
while (!this.eat(tt.braceR)) {
|
||||||
if (this.eat(tt.semi)) continue
|
if (this.eat(tt.semi)) continue
|
||||||
if (this.options.features["es7.decorators"] && this.type === tt.at) {
|
if (this.type === tt.at) {
|
||||||
decorators.push(this.parseDecorator())
|
this.parseDecorator()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var method = this.startNode()
|
var method = this.startNode()
|
||||||
@ -512,7 +517,7 @@ pp.parseClass = function(node, isStatement) {
|
|||||||
}
|
}
|
||||||
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
||||||
}
|
}
|
||||||
if (decorators.length) {
|
if (this.decorators.length) {
|
||||||
this.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")
|
||||||
@ -557,18 +562,24 @@ pp.parseExport = function(node) {
|
|||||||
this.expectContextual("from")
|
this.expectContextual("from")
|
||||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected()
|
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected()
|
||||||
this.semicolon()
|
this.semicolon()
|
||||||
|
this.checkExport(node)
|
||||||
return this.finishNode(node, "ExportAllDeclaration")
|
return this.finishNode(node, "ExportAllDeclaration")
|
||||||
}
|
}
|
||||||
if (this.eat(tt._default)) { // export default ...
|
if (this.eat(tt._default)) { // export default ...
|
||||||
let expr = this.parseMaybeAssign()
|
let expr = this.parseMaybeAssign()
|
||||||
let needsSemi = true
|
let needsSemi = true
|
||||||
if (expr.id) switch (expr.type) {
|
if (expr.type == "FunctionExpression" ||
|
||||||
case "FunctionExpression": expr.type = "FunctionDeclaration"; break
|
expr.type == "ClassExpression") {
|
||||||
case "ClassExpression": expr.type = "ClassDeclaration"; break
|
needsSemi = false
|
||||||
default: needsSemi = false
|
if (expr.id) {
|
||||||
|
expr.type = expr.type == "FunctionExpression"
|
||||||
|
? "FunctionDeclaration"
|
||||||
|
: "ClassDeclaration"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node.declaration = expr
|
node.declaration = expr
|
||||||
if (needsSemi) this.semicolon()
|
if (needsSemi) this.semicolon()
|
||||||
|
this.checkExport(node)
|
||||||
return this.finishNode(node, "ExportDefaultDeclaration")
|
return this.finishNode(node, "ExportDefaultDeclaration")
|
||||||
}
|
}
|
||||||
// export var|const|let|function|class ...
|
// export var|const|let|function|class ...
|
||||||
@ -586,13 +597,24 @@ pp.parseExport = function(node) {
|
|||||||
}
|
}
|
||||||
this.semicolon()
|
this.semicolon()
|
||||||
}
|
}
|
||||||
|
this.checkExport(node)
|
||||||
return this.finishNode(node, "ExportNamedDeclaration")
|
return this.finishNode(node, "ExportNamedDeclaration")
|
||||||
}
|
}
|
||||||
|
|
||||||
pp.shouldParseExportDeclaration = function () {
|
pp.shouldParseExportDeclaration = function() {
|
||||||
return this.options.features["es7.asyncFunctions"] && this.isContextual("async")
|
return this.options.features["es7.asyncFunctions"] && this.isContextual("async")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp.checkExport = function(node) {
|
||||||
|
if (this.decorators.length) {
|
||||||
|
var isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression")
|
||||||
|
if (!node.declaration || !isClass) {
|
||||||
|
this.raise(node.start, "You can only use decorators on an export when exporting a class");
|
||||||
|
}
|
||||||
|
this.takeDecorators(node.declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parses a comma-separated list of module exports.
|
// Parses a comma-separated list of module exports.
|
||||||
|
|
||||||
pp.parseExportSpecifiers = function() {
|
pp.parseExportSpecifiers = function() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user