diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 48c6d83eb34e..b65809651bfa 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -283,6 +283,7 @@ export default (superClass: Class): Class => } else { enforceOrder(startPos, modifier, modifier, "override"); enforceOrder(startPos, modifier, modifier, "static"); + enforceOrder(startPos, modifier, modifier, "readonly"); modified.accessibility = modifier; } @@ -1932,9 +1933,17 @@ export default (superClass: Class): Class => let readonly = false; let override = false; if (allowModifiers !== undefined) { - accessibility = this.parseAccessModifier(); - override = !!this.tsParseModifier(["override"]); - readonly = !!this.tsParseModifier(["readonly"]); + const modified = {}; + this.tsParseModifiers(modified, [ + "public", + "private", + "protected", + "override", + "readonly", + ]); + accessibility = modified.accessibility; + override = modified.override; + readonly = modified.readonly; if ( allowModifiers === false && (accessibility || readonly || override) diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/input.ts b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/input.ts new file mode 100644 index 000000000000..c431aaff84d5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/input.ts @@ -0,0 +1,3 @@ +class D extends B { + constructor(readonly override foo: string) {} +} diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/output.json b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/output.json new file mode 100644 index 000000000000..03050c7ad27f --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-1/output.json @@ -0,0 +1,78 @@ +{ + "type": "File", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: 'override' modifier must precede 'readonly' modifier. (2:23)" + ], + "program": { + "type": "Program", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"D"}, + "name": "D" + }, + "superClass": { + "type": "Identifier", + "start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"B"}, + "name": "B" + }, + "body": { + "type": "ClassBody", + "start":18,"end":69,"loc":{"start":{"line":1,"column":18},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":22,"end":67,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":47}}, + "static": false, + "key": { + "type": "Identifier", + "start":22,"end":33,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":13},"identifierName":"constructor"}, + "name": "constructor" + }, + "computed": false, + "kind": "constructor", + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "TSParameterProperty", + "start":34,"end":63,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":43}}, + "readonly": true, + "override": true, + "parameter": { + "type": "Identifier", + "start":52,"end":63,"loc":{"start":{"line":2,"column":32},"end":{"line":2,"column":43},"identifierName":"foo"}, + "name": "foo", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":55,"end":63,"loc":{"start":{"line":2,"column":35},"end":{"line":2,"column":43}}, + "typeAnnotation": { + "type": "TSStringKeyword", + "start":57,"end":63,"loc":{"start":{"line":2,"column":37},"end":{"line":2,"column":43}} + } + } + } + } + ], + "body": { + "type": "BlockStatement", + "start":65,"end":67,"loc":{"start":{"line":2,"column":45},"end":{"line":2,"column":47}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/input.ts b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/input.ts new file mode 100644 index 000000000000..e291c585e55e --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/input.ts @@ -0,0 +1,3 @@ +class D extends B { + constructor(readonly public foo: string) {} +} diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/output.json b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/output.json new file mode 100644 index 000000000000..078fcbedf24f --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/output.json @@ -0,0 +1,78 @@ +{ + "type": "File", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: 'public' modifier must precede 'readonly' modifier. (2:23)" + ], + "program": { + "type": "Program", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"D"}, + "name": "D" + }, + "superClass": { + "type": "Identifier", + "start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"B"}, + "name": "B" + }, + "body": { + "type": "ClassBody", + "start":18,"end":67,"loc":{"start":{"line":1,"column":18},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":22,"end":65,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":45}}, + "static": false, + "key": { + "type": "Identifier", + "start":22,"end":33,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":13},"identifierName":"constructor"}, + "name": "constructor" + }, + "computed": false, + "kind": "constructor", + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "TSParameterProperty", + "start":34,"end":61,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":41}}, + "accessibility": "public", + "readonly": true, + "parameter": { + "type": "Identifier", + "start":50,"end":61,"loc":{"start":{"line":2,"column":30},"end":{"line":2,"column":41},"identifierName":"foo"}, + "name": "foo", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":53,"end":61,"loc":{"start":{"line":2,"column":33},"end":{"line":2,"column":41}}, + "typeAnnotation": { + "type": "TSStringKeyword", + "start":55,"end":61,"loc":{"start":{"line":2,"column":35},"end":{"line":2,"column":41}} + } + } + } + } + ], + "body": { + "type": "BlockStatement", + "start":63,"end":65,"loc":{"start":{"line":2,"column":43},"end":{"line":2,"column":45}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/input.ts b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/input.ts new file mode 100644 index 000000000000..1d9dd7d348ef --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/input.ts @@ -0,0 +1,3 @@ +class D extends B { + constructor(override readonly public foo: string) {} +} diff --git a/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/output.json b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/output.json new file mode 100644 index 000000000000..85f613b166d9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/output.json @@ -0,0 +1,80 @@ +{ + "type": "File", + "start":0,"end":76,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: 'public' modifier must precede 'override' modifier. (2:32)", + "SyntaxError: 'public' modifier must precede 'readonly' modifier. (2:32)" + ], + "program": { + "type": "Program", + "start":0,"end":76,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":76,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"D"}, + "name": "D" + }, + "superClass": { + "type": "Identifier", + "start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"B"}, + "name": "B" + }, + "body": { + "type": "ClassBody", + "start":18,"end":76,"loc":{"start":{"line":1,"column":18},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":22,"end":74,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":54}}, + "static": false, + "key": { + "type": "Identifier", + "start":22,"end":33,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":13},"identifierName":"constructor"}, + "name": "constructor" + }, + "computed": false, + "kind": "constructor", + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "TSParameterProperty", + "start":34,"end":70,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":50}}, + "accessibility": "public", + "readonly": true, + "override": true, + "parameter": { + "type": "Identifier", + "start":59,"end":70,"loc":{"start":{"line":2,"column":39},"end":{"line":2,"column":50},"identifierName":"foo"}, + "name": "foo", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":62,"end":70,"loc":{"start":{"line":2,"column":42},"end":{"line":2,"column":50}}, + "typeAnnotation": { + "type": "TSStringKeyword", + "start":64,"end":70,"loc":{"start":{"line":2,"column":44},"end":{"line":2,"column":50}} + } + } + } + } + ], + "body": { + "type": "BlockStatement", + "start":72,"end":74,"loc":{"start":{"line":2,"column":52},"end":{"line":2,"column":54}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file