From a4ca1cc645e02fb0d2965a63391e99fb7f2979d7 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Apr 2017 16:40:55 +0100 Subject: [PATCH 01/12] Cherry-pick #418 to 6.x (#476) * Add support for flow type spread (#418) * Add support for flow type spread * Broaden spreadable types from primary to all, more tests * Eliminate variance sigil for type spreads, better errors, fix tests # Conflicts: # src/plugins/flow.js * Fix tests --- src/plugins/flow.js | 56 ++-- .../flow/type-annotations/112/options.json | 2 +- .../flow/type-annotations/113/options.json | 2 +- .../flow/type-annotations/125/options.json | 2 +- .../flow/type-annotations/135/actual.js | 3 + .../flow/type-annotations/135/expected.json | 117 ++++++++ .../flow/type-annotations/136/actual.js | 4 + .../flow/type-annotations/136/expected.json | 175 +++++++++++ .../flow/type-annotations/137/actual.js | 3 + .../flow/type-annotations/137/options.json | 3 + .../flow/type-annotations/138/actual.js | 5 + .../flow/type-annotations/138/expected.json | 283 ++++++++++++++++++ .../flow/type-annotations/139/actual.js | 4 + .../flow/type-annotations/139/options.json | 3 + 14 files changed, 639 insertions(+), 23 deletions(-) create mode 100644 test/fixtures/flow/type-annotations/135/actual.js create mode 100644 test/fixtures/flow/type-annotations/135/expected.json create mode 100644 test/fixtures/flow/type-annotations/136/actual.js create mode 100644 test/fixtures/flow/type-annotations/136/expected.json create mode 100644 test/fixtures/flow/type-annotations/137/actual.js create mode 100644 test/fixtures/flow/type-annotations/137/options.json create mode 100644 test/fixtures/flow/type-annotations/138/actual.js create mode 100644 test/fixtures/flow/type-annotations/138/expected.json create mode 100644 test/fixtures/flow/type-annotations/139/actual.js create mode 100644 test/fixtures/flow/type-annotations/139/options.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index d30545b113..ab6003aa2a 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -194,7 +194,7 @@ pp.flowParseDeclareInterface = function (node) { // Interfaces -pp.flowParseInterfaceish = function (node, allowStatic) { +pp.flowParseInterfaceish = function (node) { node.id = this.parseIdentifier(); if (this.isRelational("<")) { @@ -219,7 +219,7 @@ pp.flowParseInterfaceish = function (node, allowStatic) { } while (this.eat(tt.comma)); } - node.body = this.flowParseObjectType(allowStatic); + node.body = this.flowParseObjectType(true, false, false); }; pp.flowParseInterfaceExtends = function () { @@ -400,7 +400,7 @@ pp.flowParseObjectTypeCallProperty = function (node, isStatic) { return this.finishNode(node, "ObjectTypeCallProperty"); }; -pp.flowParseObjectType = function (allowStatic, allowExact) { +pp.flowParseObjectType = function (allowStatic, allowExact, allowSpread) { const oldInType = this.state.inType; this.state.inType = true; @@ -448,24 +448,40 @@ pp.flowParseObjectType = function (allowStatic, allowExact) { } nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, isStatic)); } else { - propertyKey = this.flowParseObjectPropertyKey(); - if (this.isRelational("<") || this.match(tt.parenL)) { - // This is a method property + if (this.match(tt.ellipsis)) { + if (!allowSpread) { + this.unexpected( + null, + "Spread operator cannnot appear in class or interface definitions" + ); + } if (variance) { - this.unexpected(variancePos); + this.unexpected(variance.start, "Spread properties cannot have variance"); } - nodeStart.properties.push(this.flowParseObjectTypeMethod(startPos, startLoc, isStatic, propertyKey)); - } else { - if (this.eat(tt.question)) { - optional = true; - } - node.key = propertyKey; - node.value = this.flowParseTypeInitialiser(); - node.optional = optional; - node.static = isStatic; - node.variance = variance; + this.expect(tt.ellipsis); + node.argument = this.flowParseType(); this.flowObjectTypeSemicolon(); - nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty")); + nodeStart.properties.push(this.finishNode(node, "ObjectTypeSpreadProperty")); + } else { + propertyKey = this.flowParseObjectPropertyKey(); + if (this.isRelational("<") || this.match(tt.parenL)) { + // This is a method property + if (variance) { + this.unexpected(variance.start); + } + nodeStart.properties.push(this.flowParseObjectTypeMethod(startPos, startLoc, isStatic, propertyKey)); + } else { + if (this.eat(tt.question)) { + optional = true; + } + node.key = propertyKey; + node.value = this.flowParseTypeInitialiser(); + node.optional = optional; + node.static = isStatic; + node.variance = variance; + this.flowObjectTypeSemicolon(); + nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty")); + } } } @@ -627,10 +643,10 @@ pp.flowParsePrimaryType = function () { return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier()); case tt.braceL: - return this.flowParseObjectType(false, false); + return this.flowParseObjectType(false, false, true); case tt.braceBarL: - return this.flowParseObjectType(false, true); + return this.flowParseObjectType(false, true, true); case tt.bracketL: return this.flowParseTupleType(); diff --git a/test/fixtures/flow/type-annotations/112/options.json b/test/fixtures/flow/type-annotations/112/options.json index 89bfc2d73f..9e093bfdcd 100644 --- a/test/fixtures/flow/type-annotations/112/options.json +++ b/test/fixtures/flow/type-annotations/112/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:10)" + "throws": "Unexpected token (1:12)" } diff --git a/test/fixtures/flow/type-annotations/113/options.json b/test/fixtures/flow/type-annotations/113/options.json index 89bfc2d73f..9e093bfdcd 100644 --- a/test/fixtures/flow/type-annotations/113/options.json +++ b/test/fixtures/flow/type-annotations/113/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:10)" + "throws": "Unexpected token (1:12)" } diff --git a/test/fixtures/flow/type-annotations/125/options.json b/test/fixtures/flow/type-annotations/125/options.json index 2e4647b080..6079f138a6 100644 --- a/test/fixtures/flow/type-annotations/125/options.json +++ b/test/fixtures/flow/type-annotations/125/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:26)" + "throws": "Unexpected token (1:29)" } diff --git a/test/fixtures/flow/type-annotations/135/actual.js b/test/fixtures/flow/type-annotations/135/actual.js new file mode 100644 index 0000000000..b79dc870ee --- /dev/null +++ b/test/fixtures/flow/type-annotations/135/actual.js @@ -0,0 +1,3 @@ +type A = { + ...any, +}; diff --git a/test/fixtures/flow/type-annotations/135/expected.json b/test/fixtures/flow/type-annotations/135/expected.json new file mode 100644 index 0000000000..6f973de0f6 --- /dev/null +++ b/test/fixtures/flow/type-annotations/135/expected.json @@ -0,0 +1,117 @@ +{ + "type": "File", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 2 + } + }, + "sourceType": "module", + "body": [ + { + "type": "TypeAlias", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 2 + } + }, + "id": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "A" + }, + "name": "A" + }, + "typeParameters": null, + "right": { + "type": "ObjectTypeAnnotation", + "start": 9, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "callProperties": [], + "properties": [ + { + "type": "ObjectTypeSpreadProperty", + "start": 12, + "end": 19, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "argument": { + "type": "AnyTypeAnnotation", + "start": 15, + "end": 18, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 7 + } + } + } + } + ], + "indexers": [], + "exact": false + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/type-annotations/136/actual.js b/test/fixtures/flow/type-annotations/136/actual.js new file mode 100644 index 0000000000..09c0a04398 --- /dev/null +++ b/test/fixtures/flow/type-annotations/136/actual.js @@ -0,0 +1,4 @@ +type A = { + p: {}, + ...{}, +}; diff --git a/test/fixtures/flow/type-annotations/136/expected.json b/test/fixtures/flow/type-annotations/136/expected.json new file mode 100644 index 0000000000..18d746c433 --- /dev/null +++ b/test/fixtures/flow/type-annotations/136/expected.json @@ -0,0 +1,175 @@ +{ + "type": "File", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 2 + } + }, + "sourceType": "module", + "body": [ + { + "type": "TypeAlias", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 2 + } + }, + "id": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "A" + }, + "name": "A" + }, + "typeParameters": null, + "right": { + "type": "ObjectTypeAnnotation", + "start": 9, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "callProperties": [], + "properties": [ + { + "type": "ObjectTypeProperty", + "start": 12, + "end": 18, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 7 + } + }, + "key": { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 2 + }, + "identifierName": "p" + }, + "name": "p" + }, + "value": { + "type": "ObjectTypeAnnotation", + "start": 15, + "end": 17, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "callProperties": [], + "properties": [], + "indexers": [], + "exact": false + }, + "optional": false, + "static": false, + "variance": null + }, + { + "type": "ObjectTypeSpreadProperty", + "start": 20, + "end": 26, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "argument": { + "type": "ObjectTypeAnnotation", + "start": 23, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 6 + } + }, + "callProperties": [], + "properties": [], + "indexers": [], + "exact": false + } + } + ], + "indexers": [], + "exact": false + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/type-annotations/137/actual.js b/test/fixtures/flow/type-annotations/137/actual.js new file mode 100644 index 0000000000..b039a41ed2 --- /dev/null +++ b/test/fixtures/flow/type-annotations/137/actual.js @@ -0,0 +1,3 @@ +interface A { + ...any, +}; diff --git a/test/fixtures/flow/type-annotations/137/options.json b/test/fixtures/flow/type-annotations/137/options.json new file mode 100644 index 0000000000..79756f8c33 --- /dev/null +++ b/test/fixtures/flow/type-annotations/137/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Spread operator cannnot appear in class or interface definitions (2:1)" +} diff --git a/test/fixtures/flow/type-annotations/138/actual.js b/test/fixtures/flow/type-annotations/138/actual.js new file mode 100644 index 0000000000..9a607c669f --- /dev/null +++ b/test/fixtures/flow/type-annotations/138/actual.js @@ -0,0 +1,5 @@ +class A {} +class B {} +type C = { + ...A&B +}; diff --git a/test/fixtures/flow/type-annotations/138/expected.json b/test/fixtures/flow/type-annotations/138/expected.json new file mode 100644 index 0000000000..3aabc9dfd3 --- /dev/null +++ b/test/fixtures/flow/type-annotations/138/expected.json @@ -0,0 +1,283 @@ +{ + "type": "File", + "start": 0, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "A" + }, + "name": "A" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 8, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "body": [] + } + }, + { + "type": "ClassDeclaration", + "start": 11, + "end": 21, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 10 + } + }, + "id": { + "type": "Identifier", + "start": 17, + "end": 18, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + }, + "identifierName": "B" + }, + "name": "B" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 19, + "end": 21, + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 10 + } + }, + "body": [] + } + }, + { + "type": "TypeAlias", + "start": 22, + "end": 43, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "id": { + "type": "Identifier", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + }, + "identifierName": "C" + }, + "name": "C" + }, + "typeParameters": null, + "right": { + "type": "ObjectTypeAnnotation", + "start": 31, + "end": 42, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "callProperties": [], + "properties": [ + { + "type": "ObjectTypeSpreadProperty", + "start": 34, + "end": 40, + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 7 + } + }, + "argument": { + "type": "IntersectionTypeAnnotation", + "start": 37, + "end": 40, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 7 + } + }, + "types": [ + { + "type": "GenericTypeAnnotation", + "start": 37, + "end": 38, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 37, + "end": 38, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + }, + "identifierName": "A" + }, + "name": "A" + } + }, + { + "type": "GenericTypeAnnotation", + "start": 39, + "end": 40, + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 7 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 39, + "end": 40, + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 7 + }, + "identifierName": "B" + }, + "name": "B" + } + } + ] + } + } + ], + "indexers": [], + "exact": false + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/type-annotations/139/actual.js b/test/fixtures/flow/type-annotations/139/actual.js new file mode 100644 index 0000000000..fbc1330612 --- /dev/null +++ b/test/fixtures/flow/type-annotations/139/actual.js @@ -0,0 +1,4 @@ +class A {} +type C = { + -...A +}; diff --git a/test/fixtures/flow/type-annotations/139/options.json b/test/fixtures/flow/type-annotations/139/options.json new file mode 100644 index 0000000000..fe5ad00277 --- /dev/null +++ b/test/fixtures/flow/type-annotations/139/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Spread properties cannot have variance (3:2)" +} From 2e17e5bc399b9615baa4017f792ab2bac41cae13 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Apr 2017 16:41:23 +0100 Subject: [PATCH 02/12] 6.17.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eb5642d926..a7adfa725b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babylon", - "version": "6.16.1", + "version": "6.17.0", "description": "A JavaScript parser", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", From a2c143299af5d259dd686ef0078d325f793a049f Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Apr 2017 16:43:47 +0100 Subject: [PATCH 03/12] Add changelog --- CHANGELOG.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb482fc5c7..dda35be878 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,15 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ See the [Babel Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) for the pre-6.8.0 version Changelog. +## 6.17.0 (2017-04-20) + + * Cherry-pick #418 to 6.x ([#476](https://github.com/babel/babylon/pull/476)) (Sebastian McKenzie) + * Add support for invalid escapes in tagged templates ([#274](https://github.com/babel/babylon/pull/274)) (Kevin Gibbons) + * Throw error if new.target is used outside of a function ([#402](https://github.com/babel/babylon/pull/402)) (Brian Ng) + * Fix parsing of class properties ([#351](https://github.com/babel/babylon/pull/351)) (Kevin Gibbons) + * Fix parsing yield with dynamicImport ([#383](https://github.com/babel/babylon/pull/383)) (Brian Ng) + * Ensure consistent start args for parseParenItem ([#386](https://github.com/babel/babylon/pull/386)) (Brian Ng) + ## 6.16.0 (2017-02-23) ### :rocket: New Feature @@ -172,7 +181,7 @@ Update API documentation ([#330](https://github.com/babel/babylon/pull/330)) (Ti Added keywords to package.json ([#323](https://github.com/babel/babylon/pull/323)) (Dmytro) AST spec: fix casing of `RegExpLiteral` ([#318](https://github.com/babel/babylon/pull/318)) (Mathias Bynens) - + ## 6.15.0 (2017-01-10) ### :eyeglasses: Spec Compliancy @@ -313,20 +322,20 @@ type C = { [string]: number }; ``` Parse flow nested array type annotations like `number[][]` ([#219](https://github.com/babel/babylon/pull/219)) (Bernhard Häussner) - + Supports these form now of specifying array types: ```js var a: number[][][][]; var b: string[][]; ``` - + ### :bug: Bug Fix Correctly eat semicolon at the end of `DelcareModuleExports` ([#223](https://github.com/babel/babylon/pull/223)) (Daniel Tschinder) ``` -declare module "foo" { declare module.exports: number } +declare module "foo" { declare module.exports: number } declare module "foo" { declare module.exports: number; } // also allowed now ``` @@ -414,7 +423,7 @@ Readd missin .eslinignore for IDEs (Daniel Tschinder) Error on missing expected.json fixture in CI ([#188](https://github.com/babel/babylon/pull/188)) (Moti Zilberman) Add .gitattributes and .editorconfig for LF line endings ([#179](https://github.com/babel/babylon/pull/179)) (Moti Zilberman) - + Fixes two tests that are failing after the merge of #172 ([#177](https://github.com/babel/babylon/pull/177)) (Moti Zilberman) ## v6.12.0 (2016-10-14) @@ -627,7 +636,7 @@ function something({ set = null, get = null }) {} ```js // regression with duplicate export check SyntaxError: ./typography.js: `undefined` has already been exported. Exported identifiers must be unique. (22:13) - 20 | + 20 | 21 | export const { rhythm } = typography; > 22 | export const { TypographyStyle } = typography ``` @@ -932,7 +941,7 @@ var obj = { There is also a new node type, `ForAwaitStatement`. -> [Async generators and for-await](https://github.com/tc39/proposal-async-iteration) are now a [stage 2 proposal](https://github.com/tc39/ecma262#current-proposals). +> [Async generators and for-await](https://github.com/tc39/proposal-async-iteration) are now a [stage 2 proposal](https://github.com/tc39/ecma262#current-proposals). Example: From 63412e54f406664116165ee48b25f067402f8fa8 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Wed, 10 May 2017 09:18:08 -0500 Subject: [PATCH 04/12] Allow flow class field to be named constructor (#510) --- src/plugins/flow.js | 6 + .../actual.js | 3 + .../expected.json | 169 +++++++++++++ .../options.json | 3 + .../actual.js | 5 + .../expected.json | 222 ++++++++++++++++++ .../options.json | 3 + 7 files changed, 411 insertions(+) create mode 100644 test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/actual.js create mode 100644 test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/expected.json create mode 100644 test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/options.json create mode 100644 test/fixtures/flow/classes/constructor-with-class-prop-plugin/actual.js create mode 100644 test/fixtures/flow/classes/constructor-with-class-prop-plugin/expected.json create mode 100644 test/fixtures/flow/classes/constructor-with-class-prop-plugin/options.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index ab6003aa2a..996f492993 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1139,6 +1139,12 @@ export default function (instance) { }; }); + instance.extend("isNonstaticConstructor", function(inner) { + return function (method) { + return !this.match(tt.colon) && inner.call(this, method); + }; + }); + // parse type parameters for class methods instance.extend("parseClassMethod", function (inner) { return function (classBody, method, ...args) { diff --git a/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/actual.js b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/actual.js new file mode 100644 index 0000000000..1db4f60888 --- /dev/null +++ b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/actual.js @@ -0,0 +1,3 @@ +class Foo { + constructor: () => this; +} diff --git a/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/expected.json b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/expected.json new file mode 100644 index 0000000000..721399cff9 --- /dev/null +++ b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/expected.json @@ -0,0 +1,169 @@ +{ + "type": "File", + "start": 0, + "end": 40, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 40, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 40, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 9 + }, + "identifierName": "Foo" + }, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 10, + "end": 40, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ClassProperty", + "start": 14, + "end": 38, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 26 + } + }, + "static": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 14, + "end": 25, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 13 + }, + "identifierName": "constructor" + }, + "name": "constructor" + }, + "variance": null, + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 25, + "end": 37, + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "typeAnnotation": { + "type": "FunctionTypeAnnotation", + "start": 27, + "end": 37, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "params": [], + "rest": null, + "returnType": { + "type": "ThisTypeAnnotation", + "start": 33, + "end": 37, + "loc": { + "start": { + "line": 2, + "column": 21 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "value": true + }, + "typeParameters": null + } + }, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/options.json b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/options.json new file mode 100644 index 0000000000..3c8f72c900 --- /dev/null +++ b/test/fixtures/flow/classes/constructor-override-with-class-prop-plugin/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["jsx", "flow", "classProperties"] +} diff --git a/test/fixtures/flow/classes/constructor-with-class-prop-plugin/actual.js b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/actual.js new file mode 100644 index 0000000000..90c635b7b7 --- /dev/null +++ b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/actual.js @@ -0,0 +1,5 @@ +class A { + constructor(): Object { + return {}; + } +} diff --git a/test/fixtures/flow/classes/constructor-with-class-prop-plugin/expected.json b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/expected.json new file mode 100644 index 0000000000..1424dbc6ba --- /dev/null +++ b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/expected.json @@ -0,0 +1,222 @@ +{ + "type": "File", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "A" + }, + "name": "A" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 8, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ClassMethod", + "start": 12, + "end": 54, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "static": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 12, + "end": 23, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 13 + }, + "identifierName": "constructor" + }, + "name": "constructor" + }, + "kind": "constructor", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "returnType": { + "type": "TypeAnnotation", + "start": 25, + "end": 33, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 27, + "end": 33, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 27, + "end": 33, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 23 + }, + "identifierName": "Object" + }, + "name": "Object" + } + }, + "predicate": null + }, + "body": { + "type": "BlockStatement", + "start": 34, + "end": 54, + "loc": { + "start": { + "line": 2, + "column": 24 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 40, + "end": 50, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "argument": { + "type": "ObjectExpression", + "start": 47, + "end": 49, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "properties": [] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/classes/constructor-with-class-prop-plugin/options.json b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/options.json new file mode 100644 index 0000000000..3c8f72c900 --- /dev/null +++ b/test/fixtures/flow/classes/constructor-with-class-prop-plugin/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["jsx", "flow", "classProperties"] +} From 4a29ccdd1aa84df293c3b334d6ee1c578ccba425 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Tue, 2 May 2017 13:41:10 -0500 Subject: [PATCH 05/12] Allow super in class properties (#499) --- src/parser/expression.js | 6 +- src/parser/statement.js | 2 + src/tokenizer/state.js | 2 + .../class-properties/super/actual.js | 3 + .../class-properties/super/expected.json | 272 ++++++++++++++++++ .../class-properties/super/options.json | 3 + 6 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/experimental/class-properties/super/actual.js create mode 100644 test/fixtures/experimental/class-properties/super/expected.json create mode 100644 test/fixtures/experimental/class-properties/super/options.json diff --git a/src/parser/expression.js b/src/parser/expression.js index 775d658f32..d92b9db2f8 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -382,7 +382,11 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { switch (this.state.type) { case tt._super: - if (!this.state.inMethod && !this.options.allowSuperOutsideMethod) { + if ( + !this.state.inMethod && + !this.state.inClassProperty && + !this.options.allowSuperOutsideMethod + ) { this.raise(this.state.start, "'super' outside of function or class"); } diff --git a/src/parser/statement.js b/src/parser/statement.js index 03fc2aaac3..488a554b94 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -783,6 +783,7 @@ pp.parseClassBody = function (node) { }; pp.parseClassProperty = function (node) { + this.state.inClassProperty = true; if (this.match(tt.eq)) { if (!this.hasPlugin("classProperties")) this.unexpected(); this.next(); @@ -791,6 +792,7 @@ pp.parseClassProperty = function (node) { node.value = null; } this.semicolon(); + this.state.inClassProperty = false; return this.finishNode(node, "ClassProperty"); }; diff --git a/src/tokenizer/state.js b/src/tokenizer/state.js index 2e35b3ac4f..1bbfbda23d 100644 --- a/src/tokenizer/state.js +++ b/src/tokenizer/state.js @@ -18,6 +18,7 @@ export default class State { this.inAsync = this.inPropertyName = this.inType = + this.inClassProperty = this.noAnonFunctionType = false; @@ -73,6 +74,7 @@ export default class State { inAsync: boolean; inType: boolean; inPropertyName: boolean; + inClassProperty: boolean; // Labels in scope. labels: Array; diff --git a/test/fixtures/experimental/class-properties/super/actual.js b/test/fixtures/experimental/class-properties/super/actual.js new file mode 100644 index 0000000000..9c760b0bb1 --- /dev/null +++ b/test/fixtures/experimental/class-properties/super/actual.js @@ -0,0 +1,3 @@ +class Fails extends class { c(){} } { + c = super.c(); +} diff --git a/test/fixtures/experimental/class-properties/super/expected.json b/test/fixtures/experimental/class-properties/super/expected.json new file mode 100644 index 0000000000..3460702b3b --- /dev/null +++ b/test/fixtures/experimental/class-properties/super/expected.json @@ -0,0 +1,272 @@ +{ + "type": "File", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "Fails" + }, + "name": "Fails" + }, + "superClass": { + "type": "ClassExpression", + "start": 20, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 26, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "body": [ + { + "type": "ClassMethod", + "start": 28, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "static": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 29 + }, + "identifierName": "c" + }, + "name": "c" + }, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 31, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "body": [], + "directives": [] + } + } + ] + } + }, + "body": { + "type": "ClassBody", + "start": 36, + "end": 56, + "loc": { + "start": { + "line": 1, + "column": 36 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ClassProperty", + "start": 40, + "end": 54, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "static": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 3 + }, + "identifierName": "c" + }, + "name": "c" + }, + "value": { + "type": "CallExpression", + "start": 44, + "end": 53, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 15 + } + }, + "callee": { + "type": "MemberExpression", + "start": 44, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "object": { + "type": "Super", + "start": 44, + "end": 49, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 11 + } + } + }, + "property": { + "type": "Identifier", + "start": 50, + "end": 51, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 13 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false + }, + "arguments": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-properties/super/options.json b/test/fixtures/experimental/class-properties/super/options.json new file mode 100644 index 0000000000..9c27576d4a --- /dev/null +++ b/test/fixtures/experimental/class-properties/super/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties"] +} From 67db275c94f97da3362f05f35404383c1531f0b2 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Sun, 23 Apr 2017 17:45:19 -0500 Subject: [PATCH 06/12] Remove jsx context when parsing arrow functions (#475) --- src/plugins/flow.js | 11 +- test/fixtures/flow/type-generics/1/actual.js | 1 + .../flow/type-generics/1/expected.json | 346 ++++++++++++++++++ test/fixtures/flow/type-generics/2/actual.js | 2 + .../flow/type-generics/2/expected.json | 340 +++++++++++++++++ 5 files changed, 695 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/flow/type-generics/1/actual.js create mode 100644 test/fixtures/flow/type-generics/1/expected.json create mode 100644 test/fixtures/flow/type-generics/2/actual.js create mode 100644 test/fixtures/flow/type-generics/2/expected.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 996f492993..8b63c97207 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1,7 +1,6 @@ /* eslint max-len: 0 */ import { types as tt } from "../tokenizer/types"; -import { types as ct } from "../tokenizer/context"; import Parser from "../parser"; const primitiveTypes = [ @@ -1392,6 +1391,12 @@ export default function (instance) { } catch (err) { if (err instanceof SyntaxError) { this.state = state; + + // Remove `tc.j_expr` and `tc.j_oTag` from context added + // by parsing `jsxTagStart` to stop the JSX plugin from + // messing with the tokens + this.state.context.length -= 2; + jsxError = err; } else { // istanbul ignore next: no such error is expected @@ -1400,9 +1405,6 @@ export default function (instance) { } } - // Need to push something onto the context to stop - // the JSX plugin from messing with the tokens - this.state.context.push(ct.parenExpression); if (jsxError != null || this.isRelational("<")) { let arrowExpression; let typeParameters; @@ -1428,7 +1430,6 @@ export default function (instance) { ); } } - this.state.context.pop(); return inner.apply(this, args); }; diff --git a/test/fixtures/flow/type-generics/1/actual.js b/test/fixtures/flow/type-generics/1/actual.js new file mode 100644 index 0000000000..f27ba81379 --- /dev/null +++ b/test/fixtures/flow/type-generics/1/actual.js @@ -0,0 +1 @@ +const functionReturningIdentityAsAField = () => ({ id: (value: T): T => value }); diff --git a/test/fixtures/flow/type-generics/1/expected.json b/test/fixtures/flow/type-generics/1/expected.json new file mode 100644 index 0000000000..48f4ddd650 --- /dev/null +++ b/test/fixtures/flow/type-generics/1/expected.json @@ -0,0 +1,346 @@ +{ + "type": "File", + "start": 0, + "end": 84, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 84 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 84, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 84 + } + }, + "sourceType": "module", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 84, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 84 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 6, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 83 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 39 + }, + "identifierName": "functionReturningIdentityAsAField" + }, + "name": "functionReturningIdentityAsAField" + }, + "init": { + "type": "ArrowFunctionExpression", + "start": 42, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 42 + }, + "end": { + "line": 1, + "column": 83 + } + }, + "id": null, + "generator": false, + "expression": true, + "async": false, + "params": [], + "body": { + "type": "ObjectExpression", + "start": 49, + "end": 82, + "loc": { + "start": { + "line": 1, + "column": 49 + }, + "end": { + "line": 1, + "column": 82 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 51, + "end": 80, + "loc": { + "start": { + "line": 1, + "column": 51 + }, + "end": { + "line": 1, + "column": 80 + } + }, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 51, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 51 + }, + "end": { + "line": 1, + "column": 53 + }, + "identifierName": "id" + }, + "name": "id" + }, + "value": { + "type": "ArrowFunctionExpression", + "start": 55, + "end": 80, + "loc": { + "start": { + "line": 1, + "column": 55 + }, + "end": { + "line": 1, + "column": 80 + } + }, + "returnType": { + "type": "TypeAnnotation", + "start": 68, + "end": 71, + "loc": { + "start": { + "line": 1, + "column": 68 + }, + "end": { + "line": 1, + "column": 71 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 70, + "end": 71, + "loc": { + "start": { + "line": 1, + "column": 70 + }, + "end": { + "line": 1, + "column": 71 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 70, + "end": 71, + "loc": { + "start": { + "line": 1, + "column": 70 + }, + "end": { + "line": 1, + "column": 71 + }, + "identifierName": "T" + }, + "name": "T" + } + }, + "predicate": null + }, + "id": null, + "generator": false, + "expression": true, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 59, + "end": 67, + "loc": { + "start": { + "line": 1, + "column": 59 + }, + "end": { + "line": 1, + "column": 67 + }, + "identifierName": "value" + }, + "name": "value", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 64, + "end": 67, + "loc": { + "start": { + "line": 1, + "column": 64 + }, + "end": { + "line": 1, + "column": 67 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 66, + "end": 67, + "loc": { + "start": { + "line": 1, + "column": 66 + }, + "end": { + "line": 1, + "column": 67 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 66, + "end": 67, + "loc": { + "start": { + "line": 1, + "column": 66 + }, + "end": { + "line": 1, + "column": 67 + }, + "identifierName": "T" + }, + "name": "T" + } + } + } + } + ], + "body": { + "type": "Identifier", + "start": 75, + "end": 80, + "loc": { + "start": { + "line": 1, + "column": 75 + }, + "end": { + "line": 1, + "column": 80 + }, + "identifierName": "value" + }, + "name": "value" + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 55, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 55 + }, + "end": { + "line": 1, + "column": 58 + } + }, + "params": [ + { + "type": "TypeParameter", + "start": 56, + "end": 57, + "loc": { + "start": { + "line": 1, + "column": 56 + }, + "end": { + "line": 1, + "column": 57 + } + }, + "name": "T", + "variance": null + } + ] + } + } + } + ], + "extra": { + "parenthesized": true, + "parenStart": 48 + } + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/type-generics/2/actual.js b/test/fixtures/flow/type-generics/2/actual.js new file mode 100644 index 0000000000..e3a4739249 --- /dev/null +++ b/test/fixtures/flow/type-generics/2/actual.js @@ -0,0 +1,2 @@ +const identity = (t: T): T => t; +const a = 1; diff --git a/test/fixtures/flow/type-generics/2/expected.json b/test/fixtures/flow/type-generics/2/expected.json new file mode 100644 index 0000000000..6f8bda5539 --- /dev/null +++ b/test/fixtures/flow/type-generics/2/expected.json @@ -0,0 +1,340 @@ +{ + "type": "File", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 12 + } + }, + "sourceType": "module", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 6, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 14 + }, + "identifierName": "identity" + }, + "name": "identity" + }, + "init": { + "type": "ArrowFunctionExpression", + "start": 17, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "returnType": { + "type": "TypeAnnotation", + "start": 26, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 29 + }, + "identifierName": "T" + }, + "name": "T" + } + }, + "predicate": null + }, + "id": null, + "generator": false, + "expression": true, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 21, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 25 + }, + "identifierName": "t" + }, + "name": "t", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 22, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 25 + }, + "identifierName": "T" + }, + "name": "T" + } + } + } + } + ], + "body": { + "type": "Identifier", + "start": 33, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 34 + }, + "identifierName": "t" + }, + "name": "t" + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 17, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "params": [ + { + "type": "TypeParameter", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "name": "T", + "variance": null + } + ] + } + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "start": 36, + "end": 48, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 12 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 42, + "end": 47, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "id": { + "type": "Identifier", + "start": 42, + "end": 43, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + }, + "identifierName": "a" + }, + "name": "a" + }, + "init": { + "type": "NumericLiteral", + "start": 46, + "end": 47, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file From 7c56c24bb0ddf8e710dbfe145dcbca5508550faf Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Fri, 21 Apr 2017 09:25:34 -0500 Subject: [PATCH 07/12] Ensure non pattern shorthand props are checked for reserved words (#479) --- src/parser/expression.js | 3 ++- test/fixtures/es2015/shorthand/1/actual.js | 1 + test/fixtures/es2015/shorthand/1/options.json | 3 +++ test/fixtures/es2015/shorthand/2/actual.js | 1 + test/fixtures/es2015/shorthand/2/options.json | 3 +++ 5 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/es2015/shorthand/1/actual.js create mode 100644 test/fixtures/es2015/shorthand/1/options.json create mode 100644 test/fixtures/es2015/shorthand/2/actual.js create mode 100644 test/fixtures/es2015/shorthand/2/options.json diff --git a/src/parser/expression.js b/src/parser/expression.js index d92b9db2f8..7048f01c56 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -884,8 +884,9 @@ pp.parseObjectProperty = function (prop, startPos, startLoc, isPattern, refShort } if (!prop.computed && prop.key.type === "Identifier") { + this.checkReservedWord(prop.key.name, prop.key.start, true, true); + if (isPattern) { - this.checkReservedWord(prop.key.name, prop.key.start, true, true); prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); } else if (this.match(tt.eq) && refShorthandDefaultPos) { if (!refShorthandDefaultPos.start) { diff --git a/test/fixtures/es2015/shorthand/1/actual.js b/test/fixtures/es2015/shorthand/1/actual.js new file mode 100644 index 0000000000..5ce7c9deac --- /dev/null +++ b/test/fixtures/es2015/shorthand/1/actual.js @@ -0,0 +1 @@ +var x = ({ const }); diff --git a/test/fixtures/es2015/shorthand/1/options.json b/test/fixtures/es2015/shorthand/1/options.json new file mode 100644 index 0000000000..a618f5e2ef --- /dev/null +++ b/test/fixtures/es2015/shorthand/1/options.json @@ -0,0 +1,3 @@ +{ + "throws": "const is a reserved word (1:11)" +} diff --git a/test/fixtures/es2015/shorthand/2/actual.js b/test/fixtures/es2015/shorthand/2/actual.js new file mode 100644 index 0000000000..fabf36837d --- /dev/null +++ b/test/fixtures/es2015/shorthand/2/actual.js @@ -0,0 +1 @@ +({ get, this, if }); diff --git a/test/fixtures/es2015/shorthand/2/options.json b/test/fixtures/es2015/shorthand/2/options.json new file mode 100644 index 0000000000..7691eb820f --- /dev/null +++ b/test/fixtures/es2015/shorthand/2/options.json @@ -0,0 +1,3 @@ +{ + "throws": "this is a reserved word (1:8)" +} From 406c3dabc025f5ca89fa3ac1c81200853aa4b3b4 Mon Sep 17 00:00:00 2001 From: Alex Kuzmenko Date: Mon, 3 Apr 2017 23:25:29 +0300 Subject: [PATCH 08/12] Fix number parser (#433) Fixed number parser #2 Added one more test --- src/tokenizer/index.js | 8 ++- .../core/uncategorised/355/expected.json | 69 +++++++++++++++++++ .../core/uncategorised/355/options.json | 3 - .../core/uncategorised/356/expected.json | 69 +++++++++++++++++++ .../core/uncategorised/356/options.json | 3 - .../fixtures/core/uncategorised/550/actual.js | 2 + .../core/uncategorised/550/options.json | 3 + .../fixtures/core/uncategorised/551/actual.js | 1 + .../core/uncategorised/551/expected.json | 69 +++++++++++++++++++ .../fixtures/core/uncategorised/552/actual.js | 2 + .../core/uncategorised/552/options.json | 3 + .../fixtures/core/uncategorised/553/actual.js | 1 + .../core/uncategorised/553/expected.json | 69 +++++++++++++++++++ 13 files changed, 293 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/core/uncategorised/355/expected.json delete mode 100644 test/fixtures/core/uncategorised/355/options.json create mode 100644 test/fixtures/core/uncategorised/356/expected.json delete mode 100644 test/fixtures/core/uncategorised/356/options.json create mode 100644 test/fixtures/core/uncategorised/550/actual.js create mode 100644 test/fixtures/core/uncategorised/550/options.json create mode 100644 test/fixtures/core/uncategorised/551/actual.js create mode 100644 test/fixtures/core/uncategorised/551/expected.json create mode 100644 test/fixtures/core/uncategorised/552/actual.js create mode 100644 test/fixtures/core/uncategorised/552/options.json create mode 100644 test/fixtures/core/uncategorised/553/actual.js create mode 100644 test/fixtures/core/uncategorised/553/expected.json diff --git a/src/tokenizer/index.js b/src/tokenizer/index.js index a058ba91a5..076b636381 100644 --- a/src/tokenizer/index.js +++ b/src/tokenizer/index.js @@ -564,7 +564,7 @@ export default class Tokenizer { readNumber(startsWithDot) { const start = this.state.pos; - const octal = this.input.charCodeAt(this.state.pos) === 48; + const firstIsZero = this.input.charCodeAt(start) === 48; // '0' let isFloat = false; if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number"); @@ -587,10 +587,12 @@ export default class Tokenizer { let val; if (isFloat) { val = parseFloat(str); - } else if (!octal || str.length === 1) { + } else if (!firstIsZero || str.length === 1) { val = parseInt(str, 10); - } else if (/[89]/.test(str) || this.state.strict) { + } else if (this.state.strict) { this.raise(start, "Invalid number"); + } else if (/[89]/.test(str)) { + val = parseInt(str, 10); } else { val = parseInt(str, 8); } diff --git a/test/fixtures/core/uncategorised/355/expected.json b/test/fixtures/core/uncategorised/355/expected.json new file mode 100644 index 0000000000..08de8c762b --- /dev/null +++ b/test/fixtures/core/uncategorised/355/expected.json @@ -0,0 +1,69 @@ +{ + "type": "File", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + } + }, + "extra": { + "rawValue": 9, + "raw": "09" + }, + "value": 9 + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/355/options.json b/test/fixtures/core/uncategorised/355/options.json deleted file mode 100644 index cf3086295c..0000000000 --- a/test/fixtures/core/uncategorised/355/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Invalid number (1:0)" -} \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/356/expected.json b/test/fixtures/core/uncategorised/356/expected.json new file mode 100644 index 0000000000..6d04954399 --- /dev/null +++ b/test/fixtures/core/uncategorised/356/expected.json @@ -0,0 +1,69 @@ +{ + "type": "File", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "extra": { + "rawValue": 18, + "raw": "018" + }, + "value": 18 + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/356/options.json b/test/fixtures/core/uncategorised/356/options.json deleted file mode 100644 index cf3086295c..0000000000 --- a/test/fixtures/core/uncategorised/356/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Invalid number (1:0)" -} \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/550/actual.js b/test/fixtures/core/uncategorised/550/actual.js new file mode 100644 index 0000000000..64dcf36896 --- /dev/null +++ b/test/fixtures/core/uncategorised/550/actual.js @@ -0,0 +1,2 @@ +'use strict'; +const a = 07; diff --git a/test/fixtures/core/uncategorised/550/options.json b/test/fixtures/core/uncategorised/550/options.json new file mode 100644 index 0000000000..f635fb88c5 --- /dev/null +++ b/test/fixtures/core/uncategorised/550/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Invalid number (2:10)" +} diff --git a/test/fixtures/core/uncategorised/551/actual.js b/test/fixtures/core/uncategorised/551/actual.js new file mode 100644 index 0000000000..524f32795d --- /dev/null +++ b/test/fixtures/core/uncategorised/551/actual.js @@ -0,0 +1 @@ +0111 \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/551/expected.json b/test/fixtures/core/uncategorised/551/expected.json new file mode 100644 index 0000000000..07311dd1eb --- /dev/null +++ b/test/fixtures/core/uncategorised/551/expected.json @@ -0,0 +1,69 @@ +{ + "type": "File", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "extra": { + "rawValue": 73, + "raw": "0111" + }, + "value": 73 + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/552/actual.js b/test/fixtures/core/uncategorised/552/actual.js new file mode 100644 index 0000000000..63f4544f72 --- /dev/null +++ b/test/fixtures/core/uncategorised/552/actual.js @@ -0,0 +1,2 @@ +'use strict'; +const a = 08; diff --git a/test/fixtures/core/uncategorised/552/options.json b/test/fixtures/core/uncategorised/552/options.json new file mode 100644 index 0000000000..f635fb88c5 --- /dev/null +++ b/test/fixtures/core/uncategorised/552/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Invalid number (2:10)" +} diff --git a/test/fixtures/core/uncategorised/553/actual.js b/test/fixtures/core/uncategorised/553/actual.js new file mode 100644 index 0000000000..6b07531279 --- /dev/null +++ b/test/fixtures/core/uncategorised/553/actual.js @@ -0,0 +1 @@ +0274134317073 \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/553/expected.json b/test/fixtures/core/uncategorised/553/expected.json new file mode 100644 index 0000000000..756da7f491 --- /dev/null +++ b/test/fixtures/core/uncategorised/553/expected.json @@ -0,0 +1,69 @@ +{ + "type": "File", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "extra": { + "rawValue": 25257156155, + "raw": "0274134317073" + }, + "value": 25257156155 + } + } + ], + "directives": [] + } +} \ No newline at end of file From b98f463aa759979bbed1dd7704e66c7616e89d07 Mon Sep 17 00:00:00 2001 From: Alex Kuzmenko Date: Fri, 21 Apr 2017 16:22:50 +0300 Subject: [PATCH 09/12] Fixed invalid number literal parsing (#473) * Fixed invalid number literal parsing * Don't ignore period or E characters after octal numbers cherry-pick fix from acorn * Fix tests --- src/tokenizer/index.js | 12 ++++++++---- test/fixtures/core/uncategorised/554/actual.js | 1 + test/fixtures/core/uncategorised/554/options.json | 3 +++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/core/uncategorised/554/actual.js create mode 100644 test/fixtures/core/uncategorised/554/options.json diff --git a/src/tokenizer/index.js b/src/tokenizer/index.js index 076b636381..4031b008b1 100644 --- a/src/tokenizer/index.js +++ b/src/tokenizer/index.js @@ -564,30 +564,34 @@ export default class Tokenizer { readNumber(startsWithDot) { const start = this.state.pos; - const firstIsZero = this.input.charCodeAt(start) === 48; // '0' + let octal = this.input.charCodeAt(start) === 48; // '0' let isFloat = false; if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number"); + if (octal && this.state.pos == start + 1) octal = false; // number === 0 + let next = this.input.charCodeAt(this.state.pos); - if (next === 46) { // '.' + if (next === 46 && !octal) { // '.' ++this.state.pos; this.readInt(10); isFloat = true; next = this.input.charCodeAt(this.state.pos); } - if (next === 69 || next === 101) { // 'eE' + + if ((next === 69 || next === 101) && !octal) { // 'eE' next = this.input.charCodeAt(++this.state.pos); if (next === 43 || next === 45) ++this.state.pos; // '+-' if (this.readInt(10) === null) this.raise(start, "Invalid number"); isFloat = true; } + if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number"); const str = this.input.slice(start, this.state.pos); let val; if (isFloat) { val = parseFloat(str); - } else if (!firstIsZero || str.length === 1) { + } else if (!octal || str.length === 1) { val = parseInt(str, 10); } else if (this.state.strict) { this.raise(start, "Invalid number"); diff --git a/test/fixtures/core/uncategorised/554/actual.js b/test/fixtures/core/uncategorised/554/actual.js new file mode 100644 index 0000000000..204735a64f --- /dev/null +++ b/test/fixtures/core/uncategorised/554/actual.js @@ -0,0 +1 @@ +var a = 0123.; \ No newline at end of file diff --git a/test/fixtures/core/uncategorised/554/options.json b/test/fixtures/core/uncategorised/554/options.json new file mode 100644 index 0000000000..e247a786c1 --- /dev/null +++ b/test/fixtures/core/uncategorised/554/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (1:13)" +} From 1077a7304ea923510e37744a2fba99fad2ae0d11 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Mon, 10 Apr 2017 10:48:51 -0500 Subject: [PATCH 10/12] Fix typo in flow spread operator error [skip ci] --- src/plugins/flow.js | 2 +- test/fixtures/flow/type-annotations/137/options.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 8b63c97207..eac336b2d2 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -451,7 +451,7 @@ pp.flowParseObjectType = function (allowStatic, allowExact, allowSpread) { if (!allowSpread) { this.unexpected( null, - "Spread operator cannnot appear in class or interface definitions" + "Spread operator cannot appear in class or interface definitions" ); } if (variance) { diff --git a/test/fixtures/flow/type-annotations/137/options.json b/test/fixtures/flow/type-annotations/137/options.json index 79756f8c33..786acad32a 100644 --- a/test/fixtures/flow/type-annotations/137/options.json +++ b/test/fixtures/flow/type-annotations/137/options.json @@ -1,3 +1,3 @@ { - "throws": "Spread operator cannnot appear in class or interface definitions (2:1)" + "throws": "Spread operator cannot appear in class or interface definitions (2:1)" } From 934a3a78b6e7115679be98d7bd27d9e5b236b8f4 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Wed, 10 May 2017 18:25:13 +0200 Subject: [PATCH 11/12] Update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dda35be878..e64c141cac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,16 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ See the [Babel Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) for the pre-6.8.0 version Changelog. +## 6.17.1 (2017-05-10) + + * Fix typo in flow spread operator error (Brian Ng) + * Fixed invalid number literal parsing ([#473](https://github.com/babel/babylon/pull/473)) (Alex Kuzmenko) + * Fix number parser ([#433](https://github.com/babel/babylon/pull/433)) (Alex Kuzmenko) + * Ensure non pattern shorthand props are checked for reserved words ([#479](https://github.com/babel/babylon/pull/479)) (Brian Ng) + * Remove jsx context when parsing arrow functions ([#475](https://github.com/babel/babylon/pull/475)) (Brian Ng) + * Allow super in class properties ([#499](https://github.com/babel/babylon/pull/499)) (Brian Ng) + * Allow flow class field to be named constructor ([#510](https://github.com/babel/babylon/pull/510)) (Brian Ng) + ## 6.17.0 (2017-04-20) * Cherry-pick #418 to 6.x ([#476](https://github.com/babel/babylon/pull/476)) (Sebastian McKenzie) From 28985e7acc4de4e68fde74311ddc47175fccfa22 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Wed, 10 May 2017 18:25:58 +0200 Subject: [PATCH 12/12] 6.17.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a7adfa725b..dab549eb7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babylon", - "version": "6.17.0", + "version": "6.17.1", "description": "A JavaScript parser", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/",