Add JSX fragment syntax support (#755)

This commit is contained in:
Clement Hoang 2017-10-28 13:12:14 -07:00 committed by Henry Zhu
parent 55d5545614
commit a1125b26ce
22 changed files with 1596 additions and 5 deletions

View File

@ -37,6 +37,13 @@ tt.jsxTagEnd.updateContext = function(prevType) {
}
};
function isFragment(object: ?N.JSXElement): boolean {
return object
? object.type === "JSXOpeningFragment" ||
object.type === "JSXClosingFragment"
: false;
}
// Transforms JSX element name to string.
function getQualifiedJSXName(
@ -341,6 +348,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
startLoc: Position,
): N.JSXOpeningElement {
const node = this.startNodeAt(startPos, startLoc);
if (this.match(tt.jsxTagEnd)) {
this.expect(tt.jsxTagEnd);
return this.finishNode(node, "JSXOpeningFragment");
}
node.attributes = [];
node.name = this.jsxParseElementName();
while (!this.match(tt.slash) && !this.match(tt.jsxTagEnd)) {
@ -358,6 +369,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
startLoc: Position,
): N.JSXClosingElement {
const node = this.startNodeAt(startPos, startLoc);
if (this.match(tt.jsxTagEnd)) {
this.expect(tt.jsxTagEnd);
return this.finishNode(node, "JSXClosingFragment");
}
node.name = this.jsxParseElementName();
this.expect(tt.jsxTagEnd);
return this.finishNode(node, "JSXClosingElement");
@ -410,8 +425,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (
// $FlowIgnore
getQualifiedJSXName(closingElement.name) !==
getQualifiedJSXName(openingElement.name)
isFragment(openingElement) &&
!isFragment(closingElement)
) {
this.raise(
// $FlowIgnore
closingElement.start,
"Expected corresponding JSX closing tag for <>",
);
} else if (
// $FlowIgnore
!isFragment(openingElement) &&
isFragment(closingElement)
) {
this.raise(
// $FlowIgnore
@ -420,11 +445,35 @@ export default (superClass: Class<Parser>): Class<Parser> =>
getQualifiedJSXName(openingElement.name) +
">",
);
} else if (
// $FlowIgnore
!isFragment(openingElement) &&
!isFragment(closingElement)
) {
if (
// $FlowIgnore
getQualifiedJSXName(closingElement.name) !==
getQualifiedJSXName(openingElement.name)
) {
this.raise(
// $FlowIgnore
closingElement.start,
"Expected corresponding JSX closing tag for <" +
getQualifiedJSXName(openingElement.name) +
">",
);
}
}
}
node.openingElement = openingElement;
node.closingElement = closingElement;
// $FlowIgnore
if (isFragment(openingElement)) {
node.openingFragment = openingElement;
node.closingFragment = closingElement;
} else {
node.openingElement = openingElement;
node.closingElement = closingElement;
}
node.children = children;
if (this.match(tt.relational) && this.state.value === "<") {
this.raise(
@ -432,7 +481,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"Adjacent JSX elements must be wrapped in an enclosing tag",
);
}
return this.finishNode(node, "JSXElement");
// $FlowIgnore
return isFragment(openingElement)
? this.finishNode(node, "JSXFragment")
: this.finishNode(node, "JSXElement");
}
// Parses entire JSX element from current position.

View File

@ -799,6 +799,9 @@ export type JSXAttribute = Node;
export type JSXOpeningElement = Node;
export type JSXClosingElement = Node;
export type JSXElement = Node;
export type JSXOpeningFragment = Node;
export type JSXClosingFragment = Node;
export type JSXFragment = Node;
// Flow/TypeScript common (TODO: Not in spec)

View File

@ -0,0 +1 @@
<></>

View File

@ -0,0 +1,95 @@
{
"type": "File",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"program": {
"type": "Program",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 2,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 5
}
}
},
"children": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1 @@
<>Hi, I'm a string!</>

View File

@ -0,0 +1,116 @@
{
"type": "File",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"program": {
"type": "Program",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 22
}
}
},
"children": [
{
"type": "JSXText",
"start": 2,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 19
}
},
"extra": {
"rawValue": "Hi, I'm a string!",
"raw": "Hi, I'm a string!"
},
"value": "Hi, I'm a string!"
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,6 @@
< >
<span>
hi
</span>
<div>bye</div>
</>

View File

@ -0,0 +1,358 @@
{
"type": "File",
"start": 0,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
},
"program": {
"type": "Program",
"start": 0,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 3,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 3
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 47,
"end": 50,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
}
},
"children": [
{
"type": "JSXText",
"start": 3,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 3
},
"end": {
"line": 2,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXElement",
"start": 6,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 4,
"column": 9
}
},
"openingElement": {
"type": "JSXOpeningElement",
"start": 6,
"end": 12,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 8
}
},
"attributes": [],
"name": {
"type": "JSXIdentifier",
"start": 7,
"end": 11,
"loc": {
"start": {
"line": 2,
"column": 3
},
"end": {
"line": 2,
"column": 7
}
},
"name": "span"
},
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start": 22,
"end": 29,
"loc": {
"start": {
"line": 4,
"column": 2
},
"end": {
"line": 4,
"column": 9
}
},
"name": {
"type": "JSXIdentifier",
"start": 24,
"end": 28,
"loc": {
"start": {
"line": 4,
"column": 4
},
"end": {
"line": 4,
"column": 8
}
},
"name": "span"
}
},
"children": [
{
"type": "JSXText",
"start": 12,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 8
},
"end": {
"line": 4,
"column": 2
}
},
"extra": {
"rawValue": "\n hi\n ",
"raw": "\n hi\n "
},
"value": "\n hi\n "
}
]
},
{
"type": "JSXText",
"start": 29,
"end": 32,
"loc": {
"start": {
"line": 4,
"column": 9
},
"end": {
"line": 5,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXElement",
"start": 32,
"end": 46,
"loc": {
"start": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 16
}
},
"openingElement": {
"type": "JSXOpeningElement",
"start": 32,
"end": 37,
"loc": {
"start": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 7
}
},
"attributes": [],
"name": {
"type": "JSXIdentifier",
"start": 33,
"end": 36,
"loc": {
"start": {
"line": 5,
"column": 3
},
"end": {
"line": 5,
"column": 6
}
},
"name": "div"
},
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start": 40,
"end": 46,
"loc": {
"start": {
"line": 5,
"column": 10
},
"end": {
"line": 5,
"column": 16
}
},
"name": {
"type": "JSXIdentifier",
"start": 42,
"end": 45,
"loc": {
"start": {
"line": 5,
"column": 12
},
"end": {
"line": 5,
"column": 15
}
},
"name": "div"
}
},
"children": [
{
"type": "JSXText",
"start": 37,
"end": 40,
"loc": {
"start": {
"line": 5,
"column": 7
},
"end": {
"line": 5,
"column": 10
}
},
"extra": {
"rawValue": "bye",
"raw": "bye"
},
"value": "bye"
}
]
},
{
"type": "JSXText",
"start": 46,
"end": 47,
"loc": {
"start": {
"line": 5,
"column": 16
},
"end": {
"line": 6,
"column": 0
}
},
"extra": {
"rawValue": "\n",
"raw": "\n"
},
"value": "\n"
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,7 @@
<>
<>
<>
super deep
</>
</>
</>

View File

@ -0,0 +1,290 @@
{
"type": "File",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"program": {
"type": "Program",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 46,
"end": 49,
"loc": {
"start": {
"line": 7,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
}
},
"children": [
{
"type": "JSXText",
"start": 2,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 2,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXFragment",
"start": 5,
"end": 45,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 6,
"column": 5
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 5,
"end": 7,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 4
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 42,
"end": 45,
"loc": {
"start": {
"line": 6,
"column": 2
},
"end": {
"line": 6,
"column": 5
}
}
},
"children": [
{
"type": "JSXText",
"start": 7,
"end": 12,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 3,
"column": 4
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXFragment",
"start": 12,
"end": 39,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 5,
"column": 7
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 6
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 36,
"end": 39,
"loc": {
"start": {
"line": 5,
"column": 4
},
"end": {
"line": 5,
"column": 7
}
}
},
"children": [
{
"type": "JSXText",
"start": 14,
"end": 36,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 5,
"column": 4
}
},
"extra": {
"rawValue": "\n super deep\n ",
"raw": "\n super deep\n "
},
"value": "\n super deep\n "
}
]
},
{
"type": "JSXText",
"start": 39,
"end": 42,
"loc": {
"start": {
"line": 5,
"column": 7
},
"end": {
"line": 6,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
}
]
},
{
"type": "JSXText",
"start": 45,
"end": 46,
"loc": {
"start": {
"line": 6,
"column": 5
},
"end": {
"line": 7,
"column": 0
}
},
"extra": {
"rawValue": "\n",
"raw": "\n"
},
"value": "\n"
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,7 @@
<
// comment1
/* comment2 */
>
<div></div>
<div></div>
</>

View File

@ -0,0 +1,385 @@
{
"type": "File",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"program": {
"type": "Program",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 62,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"leadingComments": null,
"innerComments": [
{
"type": "CommentLine",
"value": " comment1",
"start": 2,
"end": 13,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 11
}
}
},
{
"type": "CommentBlock",
"value": " comment2 ",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 14
}
}
}
]
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 59,
"end": 62,
"loc": {
"start": {
"line": 7,
"column": 0
},
"end": {
"line": 7,
"column": 3
}
}
},
"children": [
{
"type": "JSXText",
"start": 30,
"end": 33,
"loc": {
"start": {
"line": 4,
"column": 1
},
"end": {
"line": 5,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXElement",
"start": 33,
"end": 44,
"loc": {
"start": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 13
}
},
"openingElement": {
"type": "JSXOpeningElement",
"start": 33,
"end": 38,
"loc": {
"start": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 7
}
},
"attributes": [],
"name": {
"type": "JSXIdentifier",
"start": 34,
"end": 37,
"loc": {
"start": {
"line": 5,
"column": 3
},
"end": {
"line": 5,
"column": 6
}
},
"name": "div"
},
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start": 38,
"end": 44,
"loc": {
"start": {
"line": 5,
"column": 7
},
"end": {
"line": 5,
"column": 13
}
},
"name": {
"type": "JSXIdentifier",
"start": 40,
"end": 43,
"loc": {
"start": {
"line": 5,
"column": 9
},
"end": {
"line": 5,
"column": 12
}
},
"name": "div"
}
},
"children": []
},
{
"type": "JSXText",
"start": 44,
"end": 47,
"loc": {
"start": {
"line": 5,
"column": 13
},
"end": {
"line": 6,
"column": 2
}
},
"extra": {
"rawValue": "\n ",
"raw": "\n "
},
"value": "\n "
},
{
"type": "JSXElement",
"start": 47,
"end": 58,
"loc": {
"start": {
"line": 6,
"column": 2
},
"end": {
"line": 6,
"column": 13
}
},
"openingElement": {
"type": "JSXOpeningElement",
"start": 47,
"end": 52,
"loc": {
"start": {
"line": 6,
"column": 2
},
"end": {
"line": 6,
"column": 7
}
},
"attributes": [],
"name": {
"type": "JSXIdentifier",
"start": 48,
"end": 51,
"loc": {
"start": {
"line": 6,
"column": 3
},
"end": {
"line": 6,
"column": 6
}
},
"name": "div"
},
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start": 52,
"end": 58,
"loc": {
"start": {
"line": 6,
"column": 7
},
"end": {
"line": 6,
"column": 13
}
},
"name": {
"type": "JSXIdentifier",
"start": 54,
"end": 57,
"loc": {
"start": {
"line": 6,
"column": 9
},
"end": {
"line": 6,
"column": 12
}
},
"name": "div"
}
},
"children": []
},
{
"type": "JSXText",
"start": 58,
"end": 59,
"loc": {
"start": {
"line": 6,
"column": 13
},
"end": {
"line": 7,
"column": 0
}
},
"extra": {
"rawValue": "\n",
"raw": "\n"
},
"value": "\n"
}
]
}
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " comment1",
"start": 2,
"end": 13,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 11
}
}
},
{
"type": "CommentBlock",
"value": " comment2 ",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 14
}
}
}
]
}

View File

@ -0,0 +1 @@
<><div>JSXElement</div>JSXText{'JSXExpressionContainer'}</>

View File

@ -0,0 +1,252 @@
{
"type": "File",
"start": 0,
"end": 59,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 59
}
},
"program": {
"type": "Program",
"start": 0,
"end": 59,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 59
}
},
"sourceType": "script",
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 59,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 59
}
},
"expression": {
"type": "JSXFragment",
"start": 0,
"end": 59,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 59
}
},
"openingFragment": {
"type": "JSXOpeningFragment",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
}
},
"closingFragment": {
"type": "JSXClosingFragment",
"start": 56,
"end": 59,
"loc": {
"start": {
"line": 1,
"column": 56
},
"end": {
"line": 1,
"column": 59
}
}
},
"children": [
{
"type": "JSXElement",
"start": 2,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 23
}
},
"openingElement": {
"type": "JSXOpeningElement",
"start": 2,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 7
}
},
"attributes": [],
"name": {
"type": "JSXIdentifier",
"start": 3,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 3
},
"end": {
"line": 1,
"column": 6
}
},
"name": "div"
},
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start": 17,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 23
}
},
"name": {
"type": "JSXIdentifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 22
}
},
"name": "div"
}
},
"children": [
{
"type": "JSXText",
"start": 7,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 17
}
},
"extra": {
"rawValue": "JSXElement",
"raw": "JSXElement"
},
"value": "JSXElement"
}
]
},
{
"type": "JSXText",
"start": 23,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 23
},
"end": {
"line": 1,
"column": 30
}
},
"extra": {
"rawValue": "JSXText",
"raw": "JSXText"
},
"value": "JSXText"
},
{
"type": "JSXExpressionContainer",
"start": 30,
"end": 56,
"loc": {
"start": {
"line": 1,
"column": 30
},
"end": {
"line": 1,
"column": 56
}
},
"expression": {
"type": "StringLiteral",
"start": 31,
"end": 55,
"loc": {
"start": {
"line": 1,
"column": 31
},
"end": {
"line": 1,
"column": 55
}
},
"extra": {
"rawValue": "JSXExpressionContainer",
"raw": "'JSXExpressionContainer'"
},
"value": "JSXExpressionContainer"
}
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1 @@
< key="nope"></>

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected token (1:5)"
}

View File

@ -0,0 +1 @@
<><></>

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected token (1:7)"
}

View File

@ -0,0 +1 @@
<></something>

View File

@ -0,0 +1,3 @@
{
"throws": "Expected corresponding JSX closing tag for <> (1:2)"
}

View File

@ -0,0 +1 @@
<something></>

View File

@ -0,0 +1,3 @@
{
"throws": "Expected corresponding JSX closing tag for <something> (1:11)"
}