diff --git a/src/options.js b/src/options.js index 74ff079aeb..e78a7fe98d 100755 --- a/src/options.js +++ b/src/options.js @@ -54,7 +54,7 @@ export const defaultOptions: Options = { export function getOptions(opts: ?Options): Options { const options: any = {}; for (const key in defaultOptions) { - options[key] = opts && key in opts ? opts[key] : defaultOptions[key]; + options[key] = opts && opts[key] != null ? opts[key] : defaultOptions[key]; } return options; } diff --git a/src/parser/statement.js b/src/parser/statement.js index 8ab5f8d31c..5821248dfe 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -1424,7 +1424,8 @@ export default class StatementParser extends ExpressionParser { this.state.type.keyword === "let" || this.state.type.keyword === "function" || this.state.type.keyword === "class" || - this.isContextual("async") + this.isContextual("async") || + (this.match(tt.at) && this.expectPlugin("decorators2")) ); } diff --git a/src/parser/util.js b/src/parser/util.js index d17bad782b..03a2b764ec 100644 --- a/src/parser/util.js +++ b/src/parser/util.js @@ -110,7 +110,7 @@ export default class UtilParser extends Tokenizer { throw this.raise(pos != null ? pos : this.state.start, messageOrType); } - expectPlugin(name: string, pos?: ?number): void { + expectPlugin(name: string, pos?: ?number): true { if (!this.hasPlugin(name)) { throw this.raise( pos != null ? pos : this.state.start, @@ -118,6 +118,8 @@ export default class UtilParser extends Tokenizer { [name], ); } + + return true; } expectOnePlugin(names: Array, pos?: ?number): void { diff --git a/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/actual.js b/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/actual.js new file mode 100644 index 0000000000..54720fa385 --- /dev/null +++ b/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/actual.js @@ -0,0 +1 @@ +export @bar class Foo { } diff --git a/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/options.json b/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/options.json new file mode 100644 index 0000000000..1b76281985 --- /dev/null +++ b/test/fixtures/experimental/decorators-2/export-decorated-class-without-plugin/options.json @@ -0,0 +1,5 @@ +{ + "sourceType": "module", + "throws": "This experimental syntax requires enabling the parser plugin: 'decorators2' (1:7)", + "plugins": null +} diff --git a/test/fixtures/experimental/decorators-2/export-decorated-class/actual.js b/test/fixtures/experimental/decorators-2/export-decorated-class/actual.js index 80ba64f71a..54720fa385 100644 --- a/test/fixtures/experimental/decorators-2/export-decorated-class/actual.js +++ b/test/fixtures/experimental/decorators-2/export-decorated-class/actual.js @@ -1,2 +1 @@ -export default -@bar class Foo { } +export @bar class Foo { } diff --git a/test/fixtures/experimental/decorators-2/export-decorated-class/expected.json b/test/fixtures/experimental/decorators-2/export-decorated-class/expected.json index bbfcc7fcca..d3e6301bb2 100644 --- a/test/fixtures/experimental/decorators-2/export-decorated-class/expected.json +++ b/test/fixtures/experimental/decorators-2/export-decorated-class/expected.json @@ -1,88 +1,90 @@ { "type": "File", "start": 0, - "end": 34, + "end": 25, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 2, - "column": 18 + "line": 1, + "column": 25 } }, "program": { "type": "Program", "start": 0, - "end": 34, + "end": 25, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 2, - "column": 18 + "line": 1, + "column": 25 } }, "sourceType": "module", "body": [ { - "type": "ExportDefaultDeclaration", + "type": "ExportNamedDeclaration", "start": 0, - "end": 34, + "end": 25, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 2, - "column": 18 + "line": 1, + "column": 25 } }, + "specifiers": [], + "source": null, "declaration": { - "type": "ClassExpression", - "start": 16, - "end": 34, + "type": "ClassDeclaration", + "start": 7, + "end": 25, "loc": { "start": { - "line": 2, - "column": 0 + "line": 1, + "column": 7 }, "end": { - "line": 2, - "column": 18 + "line": 1, + "column": 25 } }, "decorators": [ { "type": "Decorator", - "start": 16, - "end": 20, + "start": 7, + "end": 11, "loc": { "start": { - "line": 2, - "column": 0 + "line": 1, + "column": 7 }, "end": { - "line": 2, - "column": 4 + "line": 1, + "column": 11 } }, "expression": { "type": "Identifier", - "start": 17, - "end": 20, + "start": 8, + "end": 11, "loc": { "start": { - "line": 2, - "column": 1 + "line": 1, + "column": 8 }, "end": { - "line": 2, - "column": 4 + "line": 1, + "column": 11 }, "identifierName": "bar" }, @@ -92,16 +94,16 @@ ], "id": { "type": "Identifier", - "start": 27, - "end": 30, + "start": 18, + "end": 21, "loc": { "start": { - "line": 2, - "column": 11 + "line": 1, + "column": 18 }, "end": { - "line": 2, - "column": 14 + "line": 1, + "column": 21 }, "identifierName": "Foo" }, @@ -110,16 +112,16 @@ "superClass": null, "body": { "type": "ClassBody", - "start": 31, - "end": 34, + "start": 22, + "end": 25, "loc": { "start": { - "line": 2, - "column": 15 + "line": 1, + "column": 22 }, "end": { - "line": 2, - "column": 18 + "line": 1, + "column": 25 } }, "body": [] diff --git a/test/fixtures/experimental/decorators-2/export-default-decorated-class/actual.js b/test/fixtures/experimental/decorators-2/export-default-decorated-class/actual.js new file mode 100644 index 0000000000..80ba64f71a --- /dev/null +++ b/test/fixtures/experimental/decorators-2/export-default-decorated-class/actual.js @@ -0,0 +1,2 @@ +export default +@bar class Foo { } diff --git a/test/fixtures/experimental/decorators-2/export-default-decorated-class/expected.json b/test/fixtures/experimental/decorators-2/export-default-decorated-class/expected.json new file mode 100644 index 0000000000..bbfcc7fcca --- /dev/null +++ b/test/fixtures/experimental/decorators-2/export-default-decorated-class/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ExportDefaultDeclaration", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "declaration": { + "type": "ClassExpression", + "start": 16, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "decorators": [ + { + "type": "Decorator", + "start": 16, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "expression": { + "type": "Identifier", + "start": 17, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 4 + }, + "identifierName": "bar" + }, + "name": "bar" + } + } + ], + "id": { + "type": "Identifier", + "start": 27, + "end": 30, + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 14 + }, + "identifierName": "Foo" + }, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 31, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "body": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/decorators-2/export-default-decorated-class/options.json b/test/fixtures/experimental/decorators-2/export-default-decorated-class/options.json new file mode 100644 index 0000000000..2104ca4328 --- /dev/null +++ b/test/fixtures/experimental/decorators-2/export-default-decorated-class/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +} diff --git a/test/fixtures/experimental/decorators/export-decorators-on-class/actual.js b/test/fixtures/experimental/decorators/export-decorators-on-class/actual.js index 51804c6056..9f9fdb307b 100644 --- a/test/fixtures/experimental/decorators/export-decorators-on-class/actual.js +++ b/test/fixtures/experimental/decorators/export-decorators-on-class/actual.js @@ -1,2 +1,2 @@ @foo -export default class {} \ No newline at end of file +export class A {} diff --git a/test/fixtures/experimental/decorators/export-decorators-on-class/expected.json b/test/fixtures/experimental/decorators/export-decorators-on-class/expected.json index 3fcaa85ea6..90463128b5 100644 --- a/test/fixtures/experimental/decorators/export-decorators-on-class/expected.json +++ b/test/fixtures/experimental/decorators/export-decorators-on-class/expected.json @@ -1,7 +1,7 @@ { "type": "File", "start": 0, - "end": 28, + "end": 22, "loc": { "start": { "line": 1, @@ -9,13 +9,13 @@ }, "end": { "line": 2, - "column": 23 + "column": 17 } }, "program": { "type": "Program", "start": 0, - "end": 28, + "end": 22, "loc": { "start": { "line": 1, @@ -23,15 +23,15 @@ }, "end": { "line": 2, - "column": 23 + "column": 17 } }, "sourceType": "module", "body": [ { - "type": "ExportDefaultDeclaration", + "type": "ExportNamedDeclaration", "start": 5, - "end": 28, + "end": 22, "loc": { "start": { "line": 2, @@ -39,13 +39,15 @@ }, "end": { "line": 2, - "column": 23 + "column": 17 } }, + "specifiers": [], + "source": null, "declaration": { "type": "ClassDeclaration", "start": 0, - "end": 28, + "end": 22, "loc": { "start": { "line": 1, @@ -53,7 +55,7 @@ }, "end": { "line": 2, - "column": 23 + "column": 17 } }, "decorators": [ @@ -90,20 +92,36 @@ } } ], - "id": null, - "superClass": null, - "body": { - "type": "ClassBody", - "start": 26, - "end": 28, + "id": { + "type": "Identifier", + "start": 18, + "end": 19, "loc": { "start": { "line": 2, - "column": 21 + "column": 13 }, "end": { "line": 2, - "column": 23 + "column": 14 + }, + "identifierName": "A" + }, + "name": "A" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 20, + "end": 22, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 17 } }, "body": [] diff --git a/test/fixtures/experimental/decorators/export-default-decorators-on-class/actual.js b/test/fixtures/experimental/decorators/export-default-decorators-on-class/actual.js new file mode 100644 index 0000000000..51804c6056 --- /dev/null +++ b/test/fixtures/experimental/decorators/export-default-decorators-on-class/actual.js @@ -0,0 +1,2 @@ +@foo +export default class {} \ No newline at end of file diff --git a/test/fixtures/experimental/decorators/export-default-decorators-on-class/expected.json b/test/fixtures/experimental/decorators/export-default-decorators-on-class/expected.json new file mode 100644 index 0000000000..3fcaa85ea6 --- /dev/null +++ b/test/fixtures/experimental/decorators/export-default-decorators-on-class/expected.json @@ -0,0 +1,116 @@ +{ + "type": "File", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ExportDefaultDeclaration", + "start": 5, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "declaration": { + "type": "ClassDeclaration", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "decorators": [ + { + "type": "Decorator", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "expression": { + "type": "Identifier", + "start": 1, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + }, + "identifierName": "foo" + }, + "name": "foo" + } + } + ], + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 26, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 21 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "body": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/decorators/export-default-decorators-on-class/options.json b/test/fixtures/experimental/decorators/export-default-decorators-on-class/options.json new file mode 100644 index 0000000000..2104ca4328 --- /dev/null +++ b/test/fixtures/experimental/decorators/export-default-decorators-on-class/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +}