@@ -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 , advance = true ) : boolean {
917921 if ( token === kind ) {
918- nextToken ( ) ;
922+ if ( advance ) {
923+ nextToken ( ) ;
924+ }
919925 return true ;
920926 }
921927
@@ -929,6 +935,13 @@ namespace ts {
929935 return false ;
930936 }
931937
938+ function parseOptionalWithoutAdvancing ( t : SyntaxKind ) : boolean {
939+ if ( token === t ) {
940+ return true ;
941+ }
942+ return false ;
943+ }
944+
932945 function parseOptional ( t : SyntaxKind ) : boolean {
933946 if ( token === t ) {
934947 nextToken ( ) ;
@@ -3178,7 +3191,7 @@ namespace ts {
31783191 return parseTypeAssertion ( ) ;
31793192 }
31803193 if ( lookAhead ( nextTokenIsIdentifierOrKeyword ) ) {
3181- return parseJsxElementOrSelfClosingElement ( ) ;
3194+ return parseJsxElementOrSelfClosingElement ( /*inExpressionContext*/ true ) ;
31823195 }
31833196 // Fall through
31843197 default :
@@ -3308,14 +3321,14 @@ namespace ts {
33083321 return finishNode ( node ) ;
33093322 }
33103323
3311- function parseJsxElementOrSelfClosingElement ( ) : JsxElement | JsxSelfClosingElement {
3312- let opening = parseJsxOpeningOrSelfClosingElement ( ) ;
3324+ function parseJsxElementOrSelfClosingElement ( inExpressionContext : boolean ) : JsxElement | JsxSelfClosingElement {
3325+ let opening = parseJsxOpeningOrSelfClosingElement ( inExpressionContext ) ;
33133326 if ( opening . kind === SyntaxKind . JsxOpeningElement ) {
33143327 let node = < JsxElement > createNode ( SyntaxKind . JsxElement , opening . pos ) ;
33153328 node . openingElement = opening ;
33163329
33173330 node . children = parseJsxChildren ( node . openingElement . tagName ) ;
3318- node . closingElement = parseJsxClosingElement ( ) ;
3331+ node . closingElement = parseJsxClosingElement ( inExpressionContext ) ;
33193332 return finishNode ( node ) ;
33203333 }
33213334 else {
@@ -3336,9 +3349,9 @@ namespace ts {
33363349 case SyntaxKind . JsxText :
33373350 return parseJsxText ( ) ;
33383351 case SyntaxKind . OpenBraceToken :
3339- return parseJsxExpression ( ) ;
3352+ return parseJsxExpression ( /*inExpression*/ false ) ;
33403353 case SyntaxKind . LessThanToken :
3341- return parseJsxElementOrSelfClosingElement ( ) ;
3354+ return parseJsxElementOrSelfClosingElement ( /*inExpression*/ false ) ;
33423355 }
33433356 Debug . fail ( "Unknown JSX child kind " + token ) ;
33443357 }
@@ -3368,7 +3381,7 @@ namespace ts {
33683381 return result ;
33693382 }
33703383
3371- function parseJsxOpeningOrSelfClosingElement ( ) : JsxOpeningElement | JsxSelfClosingElement {
3384+ function parseJsxOpeningOrSelfClosingElement ( inExpressionContext : boolean ) : JsxOpeningElement | JsxSelfClosingElement {
33723385 let fullStart = scanner . getStartPos ( ) ;
33733386
33743387 parseExpected ( SyntaxKind . LessThanToken ) ;
@@ -3378,12 +3391,22 @@ namespace ts {
33783391 let attributes = parseList ( ParsingContext . JsxAttributes , parseJsxAttribute ) ;
33793392 let node : JsxOpeningLikeElement ;
33803393
3381- if ( parseOptional ( SyntaxKind . GreaterThanToken ) ) {
3394+ if ( parseOptionalWithoutAdvancing ( SyntaxKind . GreaterThanToken ) ) {
3395+ // Closing tag, so scan the immediately-following text with the JSX scanning instead
3396+ // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate
3397+ // scanning errors
33823398 node = < JsxOpeningElement > createNode ( SyntaxKind . JsxOpeningElement , fullStart ) ;
3399+ scanJsxText ( ) ;
33833400 }
33843401 else {
33853402 parseExpected ( SyntaxKind . SlashToken ) ;
3386- parseExpected ( SyntaxKind . GreaterThanToken ) ;
3403+ if ( inExpressionContext ) {
3404+ parseExpected ( SyntaxKind . GreaterThanToken ) ;
3405+ }
3406+ else {
3407+ parseExpected ( SyntaxKind . GreaterThanToken , /*diagnostic*/ undefined , /*advance*/ false ) ;
3408+ scanJsxText ( ) ;
3409+ }
33873410 node = < JsxSelfClosingElement > createNode ( SyntaxKind . JsxSelfClosingElement , fullStart ) ;
33883411 }
33893412
@@ -3406,14 +3429,20 @@ namespace ts {
34063429 return elementName ;
34073430 }
34083431
3409- function parseJsxExpression ( ) : JsxExpression {
3432+ function parseJsxExpression ( inExpressionContext : boolean ) : JsxExpression {
34103433 let node = < JsxExpression > createNode ( SyntaxKind . JsxExpression ) ;
34113434
34123435 parseExpected ( SyntaxKind . OpenBraceToken ) ;
34133436 if ( token !== SyntaxKind . CloseBraceToken ) {
34143437 node . expression = parseExpression ( ) ;
34153438 }
3416- parseExpected ( SyntaxKind . CloseBraceToken ) ;
3439+ if ( inExpressionContext ) {
3440+ parseExpected ( SyntaxKind . CloseBraceToken ) ;
3441+ }
3442+ else {
3443+ parseExpected ( SyntaxKind . CloseBraceToken , /*message*/ undefined , /*advance*/ false ) ;
3444+ scanJsxText ( ) ;
3445+ }
34173446
34183447 return finishNode ( node ) ;
34193448 }
@@ -3432,7 +3461,7 @@ namespace ts {
34323461 node . initializer = parseLiteralNode ( ) ;
34333462 break ;
34343463 default :
3435- node . initializer = parseJsxExpression ( ) ;
3464+ node . initializer = parseJsxExpression ( /*inExpressionContext*/ true ) ;
34363465 break ;
34373466 }
34383467 }
@@ -3448,11 +3477,17 @@ namespace ts {
34483477 return finishNode ( node ) ;
34493478 }
34503479
3451- function parseJsxClosingElement ( ) : JsxClosingElement {
3480+ function parseJsxClosingElement ( inExpressionContext : boolean ) : JsxClosingElement {
34523481 let node = < JsxClosingElement > createNode ( SyntaxKind . JsxClosingElement ) ;
34533482 parseExpected ( SyntaxKind . LessThanSlashToken ) ;
34543483 node . tagName = parseJsxElementName ( ) ;
3455- parseExpected ( SyntaxKind . GreaterThanToken ) ;
3484+ if ( inExpressionContext ) {
3485+ parseExpected ( SyntaxKind . GreaterThanToken ) ;
3486+ }
3487+ else {
3488+ parseExpected ( SyntaxKind . GreaterThanToken , /*diagnostic*/ undefined , /*advance*/ false ) ;
3489+ scanJsxText ( ) ;
3490+ }
34563491 return finishNode ( node ) ;
34573492 }
34583493
0 commit comments