Skip to content

Commit

Permalink
fix(parser): JSX attributes must only be assigned a non-empty 'expres…
Browse files Browse the repository at this point in the history
…sion'
  • Loading branch information
KFlash committed Jul 6, 2019
1 parent 6acf9ad commit 712d8e6
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
6 changes: 4 additions & 2 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ export const enum Errors {
TrailingNumericSeparator,
InvalidJSXAttributeValue,
ExpectedJSXClosingTag,
AdjacentJSXElements
AdjacentJSXElements,
InvalidNonEmptyJSXExpr
}

/*@internal*/
Expand Down Expand Up @@ -332,7 +333,8 @@ export const errorMessages: {
[Errors.ContinuousNumericSeparator]: 'Only one underscore is allowed as numeric separator',
[Errors.InvalidJSXAttributeValue]: 'JSX value should be either an expression or a quoted JSX text',
[Errors.ExpectedJSXClosingTag]: 'Expected corresponding JSX closing tag for %0',
[Errors.AdjacentJSXElements]: 'Adjacent JSX elements must be wrapped in an enclosing tag'
[Errors.AdjacentJSXElements]: 'Adjacent JSX elements must be wrapped in an enclosing tag',
[Errors.InvalidNonEmptyJSXExpr]: "JSX attributes must only be assigned a non-empty 'expression'"
};

export class ParseError extends SyntaxError {
Expand Down
18 changes: 16 additions & 2 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8155,7 +8155,7 @@ function parseJSXChild(parser: ParserState, context: Context, start: number, lin
case Token.Identifier:
return parseJSXText(parser, context, start, line, column);
case Token.LeftBrace:
return parseJSXExpressionContainer(parser, context, /*isJSXChild*/ 0, start, line, column);
return parseJSXExpressionContainer(parser, context, /*isJSXChild*/ 0, /* isAttr */ 0, start, line, column);
case Token.LessThan:
return parseJSXRootElementOrFragment(parser, context, /*isJSXChild*/ 0, start, line, column);
default:
Expand Down Expand Up @@ -8358,6 +8358,7 @@ function parseJsxAttribute(
name = parseJSXNamespacedName(parser, context, name, start, line, column);
}

// HTML empty attribute
if (parser.token === Token.Assign) {
const token = scanJSXAttributeValue(parser, context);
const { tokenIndex, linePos, colPos } = parser;
Expand All @@ -8369,7 +8370,15 @@ function parseJsxAttribute(
value = parseJSXRootElementOrFragment(parser, context, /*isJSXChild*/ 1, tokenIndex, linePos, colPos);
break;
case Token.LeftBrace:
value = parseJSXExpressionContainer(parser, context, /*isJSXChild*/ 1, tokenIndex, linePos, colPos);
value = parseJSXExpressionContainer(
parser,
context,
/*isJSXChild*/ 1,
/* isAttr */ 1,
tokenIndex,
linePos,
colPos
);
break;
default:
report(parser, Errors.InvalidJSXAttributeValue);
Expand Down Expand Up @@ -8424,6 +8433,7 @@ function parseJSXExpressionContainer(
parser: ParserState,
context: Context,
isJSXChild: 0 | 1,
isAttr: 0 | 1,
start: number,
line: number,
column: number
Expand All @@ -8437,6 +8447,10 @@ function parseJSXExpressionContainer(
if (parser.token !== Token.RightBrace) {
expression = parseExpression(parser, context, 1, 0, 0, tokenIndex, linePos, colPos);
} else {
// JSX attributes must only be assigned a non-empty 'expression'
if (isAttr) {
report(parser, Errors.InvalidNonEmptyJSXExpr);
}
expression = parseJSXEmptyExpression(parser, context, tokenIndex, linePos, colPos);
}
if (isJSXChild) {
Expand Down
1 change: 1 addition & 0 deletions test/parser/miscellaneous/jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('Miscellaneous - JSX', () => {
['<p></>', Context.OptionsJSX],
['<p><q></p>', Context.OptionsJSX],
['<1/>', Context.OptionsJSX],
[`<div id={}></div>`, Context.OptionsJSX],
['<div>one</div><div>two</div>', Context.OptionsJSX],
['</>', Context.OptionsJSX],
['<a/!', Context.OptionsJSX],
Expand Down

0 comments on commit 712d8e6

Please sign in to comment.