@@ -844,6 +844,10 @@ namespace ts {
844844 return token = scanner . scanJsxIdentifier ( ) ;
845845 }
846846
847+ function scanJsxText ( ) : SyntaxKind {
848+ return token = scanner . scanJsxToken ( ) ;
849+ }
850+
847851 function speculationHelper < T > ( callback : ( ) => T , isLookAhead : boolean ) : T {
848852 // Keep track of the state we'll need to rollback to if lookahead fails (or if the
849853 // caller asked us to always reset our state).
@@ -913,9 +917,11 @@ namespace ts {
913917 return token > SyntaxKind . LastReservedWord ;
914918 }
915919
916- function parseExpected ( kind : SyntaxKind , diagnosticMessage ?: DiagnosticMessage ) : boolean {
920+ function parseExpected ( kind : SyntaxKind , diagnosticMessage ?: DiagnosticMessage , shouldAdvance = true ) : boolean {
917921 if ( token === kind ) {
918- nextToken ( ) ;
922+ if ( shouldAdvance ) {
923+ nextToken ( ) ;
924+ }
919925 return true ;
920926 }
921927
@@ -3178,7 +3184,7 @@ namespace ts {
31783184 return parseTypeAssertion ( ) ;
31793185 }
31803186 if ( lookAhead ( nextTokenIsIdentifierOrKeyword ) ) {
3181- return parseJsxElementOrSelfClosingElement ( ) ;
3187+ return parseJsxElementOrSelfClosingElement ( /*inExpressionContext*/ true ) ;
31823188 }
31833189 // Fall through
31843190 default :
@@ -3308,14 +3314,14 @@ namespace ts {
33083314 return finishNode ( node ) ;
33093315 }
33103316
3311- function parseJsxElementOrSelfClosingElement ( ) : JsxElement | JsxSelfClosingElement {
3312- let opening = parseJsxOpeningOrSelfClosingElement ( ) ;
3317+ function parseJsxElementOrSelfClosingElement ( inExpressionContext : boolean ) : JsxElement | JsxSelfClosingElement {
3318+ let opening = parseJsxOpeningOrSelfClosingElement ( inExpressionContext ) ;
33133319 if ( opening . kind === SyntaxKind . JsxOpeningElement ) {
33143320 let node = < JsxElement > createNode ( SyntaxKind . JsxElement , opening . pos ) ;
33153321 node . openingElement = opening ;
33163322
33173323 node . children = parseJsxChildren ( node . openingElement . tagName ) ;
3318- node . closingElement = parseJsxClosingElement ( ) ;
3324+ node . closingElement = parseJsxClosingElement ( inExpressionContext ) ;
33193325 return finishNode ( node ) ;
33203326 }
33213327 else {
@@ -3336,9 +3342,9 @@ namespace ts {
33363342 case SyntaxKind . JsxText :
33373343 return parseJsxText ( ) ;
33383344 case SyntaxKind . OpenBraceToken :
3339- return parseJsxExpression ( ) ;
3345+ return parseJsxExpression ( /*inExpressionContext*/ false ) ;
33403346 case SyntaxKind . LessThanToken :
3341- return parseJsxElementOrSelfClosingElement ( ) ;
3347+ return parseJsxElementOrSelfClosingElement ( /*inExpressionContext*/ false ) ;
33423348 }
33433349 Debug . fail ( "Unknown JSX child kind " + token ) ;
33443350 }
@@ -3368,7 +3374,7 @@ namespace ts {
33683374 return result ;
33693375 }
33703376
3371- function parseJsxOpeningOrSelfClosingElement ( ) : JsxOpeningElement | JsxSelfClosingElement {
3377+ function parseJsxOpeningOrSelfClosingElement ( inExpressionContext : boolean ) : JsxOpeningElement | JsxSelfClosingElement {
33723378 let fullStart = scanner . getStartPos ( ) ;
33733379
33743380 parseExpected ( SyntaxKind . LessThanToken ) ;
@@ -3378,12 +3384,22 @@ namespace ts {
33783384 let attributes = parseList ( ParsingContext . JsxAttributes , parseJsxAttribute ) ;
33793385 let node : JsxOpeningLikeElement ;
33803386
3381- if ( parseOptional ( SyntaxKind . GreaterThanToken ) ) {
3387+ if ( token === SyntaxKind . GreaterThanToken ) {
3388+ // Closing tag, so scan the immediately-following text with the JSX scanning instead
3389+ // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate
3390+ // scanning errors
33823391 node = < JsxOpeningElement > createNode ( SyntaxKind . JsxOpeningElement , fullStart ) ;
3392+ scanJsxText ( ) ;
33833393 }
33843394 else {
33853395 parseExpected ( SyntaxKind . SlashToken ) ;
3386- parseExpected ( SyntaxKind . GreaterThanToken ) ;
3396+ if ( inExpressionContext ) {
3397+ parseExpected ( SyntaxKind . GreaterThanToken ) ;
3398+ }
3399+ else {
3400+ parseExpected ( SyntaxKind . GreaterThanToken , /*diagnostic*/ undefined , /*advance*/ false ) ;
3401+ scanJsxText ( ) ;
3402+ }
33873403 node = < JsxSelfClosingElement > createNode ( SyntaxKind . JsxSelfClosingElement , fullStart ) ;
33883404 }
33893405
@@ -3406,14 +3422,20 @@ namespace ts {
34063422 return elementName ;
34073423 }
34083424
3409- function parseJsxExpression ( ) : JsxExpression {
3425+ function parseJsxExpression ( inExpressionContext : boolean ) : JsxExpression {
34103426 let node = < JsxExpression > createNode ( SyntaxKind . JsxExpression ) ;
34113427
34123428 parseExpected ( SyntaxKind . OpenBraceToken ) ;
34133429 if ( token !== SyntaxKind . CloseBraceToken ) {
34143430 node . expression = parseExpression ( ) ;
34153431 }
3416- parseExpected ( SyntaxKind . CloseBraceToken ) ;
3432+ if ( inExpressionContext ) {
3433+ parseExpected ( SyntaxKind . CloseBraceToken ) ;
3434+ }
3435+ else {
3436+ parseExpected ( SyntaxKind . CloseBraceToken , /*message*/ undefined , /*advance*/ false ) ;
3437+ scanJsxText ( ) ;
3438+ }
34173439
34183440 return finishNode ( node ) ;
34193441 }
@@ -3432,7 +3454,7 @@ namespace ts {
34323454 node . initializer = parseLiteralNode ( ) ;
34333455 break ;
34343456 default :
3435- node . initializer = parseJsxExpression ( ) ;
3457+ node . initializer = parseJsxExpression ( /*inExpressionContext*/ true ) ;
34363458 break ;
34373459 }
34383460 }
@@ -3448,11 +3470,17 @@ namespace ts {
34483470 return finishNode ( node ) ;
34493471 }
34503472
3451- function parseJsxClosingElement ( ) : JsxClosingElement {
3473+ function parseJsxClosingElement ( inExpressionContext : boolean ) : JsxClosingElement {
34523474 let node = < JsxClosingElement > createNode ( SyntaxKind . JsxClosingElement ) ;
34533475 parseExpected ( SyntaxKind . LessThanSlashToken ) ;
34543476 node . tagName = parseJsxElementName ( ) ;
3455- parseExpected ( SyntaxKind . GreaterThanToken ) ;
3477+ if ( inExpressionContext ) {
3478+ parseExpected ( SyntaxKind . GreaterThanToken ) ;
3479+ }
3480+ else {
3481+ parseExpected ( SyntaxKind . GreaterThanToken , /*diagnostic*/ undefined , /*advance*/ false ) ;
3482+ scanJsxText ( ) ;
3483+ }
34563484 return finishNode ( node ) ;
34573485 }
34583486
0 commit comments