@@ -138,7 +138,7 @@ const Sequences = {
138138 Empty : new Uint8Array ( 0 ) ,
139139 Cdata : new Uint8Array ( [ 0x43 , 0x44 , 0x41 , 0x54 , 0x41 , 0x5b ] ) , // CDATA[
140140 CdataEnd : new Uint8Array ( [ 0x5d , 0x5d , 0x3e ] ) , // ]]>
141- CommentEnd : new Uint8Array ( [ 0x2d , 0x2d , 0x3e ] ) , // `-->`
141+ CommentEnd : new Uint8Array ( [ 0x2d , 0x2d , 0x21 , 0x3e ] ) , // `--! >`
142142 ScriptEnd : new Uint8Array ( [ 0x3c , 0x2f , 0x73 , 0x63 , 0x72 , 0x69 , 0x70 , 0x74 ] ) , // `</script`
143143 StyleEnd : new Uint8Array ( [ 0x3c , 0x2f , 0x73 , 0x74 , 0x79 , 0x6c , 0x65 ] ) , // `</style`
144144 TitleEnd : new Uint8Array ( [ 0x3c , 0x2f , 0x74 , 0x69 , 0x74 , 0x6c , 0x65 ] ) , // `</title`
@@ -196,7 +196,9 @@ export default class Tokenizer {
196196 this . sectionStart = 0 ;
197197 this . index = 0 ;
198198 this . baseState = State . Text ;
199+ this . isSpecial = false ;
199200 this . currentSequence = Sequences . Empty ;
201+ this . sequenceIndex = 0 ;
200202 this . running = true ;
201203 this . offset = 0 ;
202204 }
@@ -265,7 +267,7 @@ export default class Tokenizer {
265267 */
266268 private stateInSpecialTag ( c : number ) : void {
267269 if ( this . sequenceIndex === this . currentSequence . length ) {
268- if ( c === CharCodes . Gt || isWhitespace ( c ) ) {
270+ if ( isEndOfTagSection ( c ) ) {
269271 const endOfText = this . index - this . currentSequence . length ;
270272
271273 if ( this . sectionStart < endOfText ) {
@@ -352,12 +354,29 @@ export default class Tokenizer {
352354 * @param c Current character code point.
353355 */
354356 private stateInCommentLike ( c : number ) : void {
355- if ( c === this . currentSequence [ this . sequenceIndex ] ) {
357+ if (
358+ this . currentSequence === Sequences . CommentEnd &&
359+ this . sequenceIndex === 2 &&
360+ c === CharCodes . Gt
361+ ) {
362+ // `!` is optional here, so the same sequence also accepts `-->`.
363+ this . cbs . oncomment ( this . sectionStart , this . index , 2 ) ;
364+
365+ this . sequenceIndex = 0 ;
366+ this . sectionStart = this . index + 1 ;
367+ this . state = State . Text ;
368+ } else if (
369+ this . currentSequence === Sequences . CommentEnd &&
370+ this . sequenceIndex === this . currentSequence . length - 1 &&
371+ c !== CharCodes . Gt
372+ ) {
373+ this . sequenceIndex = Number ( c === CharCodes . Dash ) ;
374+ } else if ( c === this . currentSequence [ this . sequenceIndex ] ) {
356375 if ( ++ this . sequenceIndex === this . currentSequence . length ) {
357376 if ( this . currentSequence === Sequences . CdataEnd ) {
358377 this . cbs . oncdata ( this . sectionStart , this . index , 2 ) ;
359378 } else {
360- this . cbs . oncomment ( this . sectionStart , this . index , 2 ) ;
379+ this . cbs . oncomment ( this . sectionStart , this . index , 3 ) ;
361380 }
362381
363382 this . sequenceIndex = 0 ;
@@ -399,6 +418,7 @@ export default class Tokenizer {
399418 this . sectionStart = this . index + 1 ;
400419 } else if ( c === CharCodes . Questionmark ) {
401420 this . state = State . InProcessingInstruction ;
421+ this . sequenceIndex = 0 ;
402422 this . sectionStart = this . index + 1 ;
403423 } else if ( this . isTagStartChar ( c ) ) {
404424 const lower = c | 0x20 ;
@@ -443,7 +463,7 @@ export default class Tokenizer {
443463 }
444464 }
445465 private stateInClosingTagName ( c : number ) : void {
446- if ( c === CharCodes . Gt || isWhitespace ( c ) ) {
466+ if ( isEndOfTagSection ( c ) ) {
447467 this . cbs . onclosetag ( this . sectionStart , this . index ) ;
448468 this . sectionStart = - 1 ;
449469 this . state = State . AfterClosingTagName ;
@@ -574,7 +594,25 @@ export default class Tokenizer {
574594 }
575595 }
576596 private stateInProcessingInstruction ( c : number ) : void {
577- if ( c === CharCodes . Gt || this . fastForwardTo ( CharCodes . Gt ) ) {
597+ if ( this . xmlMode ) {
598+ if ( c === CharCodes . Questionmark ) {
599+ // Remember that we just consumed `?`, so the next `>` closes the PI.
600+ this . sequenceIndex = 1 ;
601+ } else if ( c === CharCodes . Gt && this . sequenceIndex === 1 ) {
602+ this . cbs . onprocessinginstruction (
603+ this . sectionStart ,
604+ this . index - 1 ,
605+ ) ;
606+ this . sequenceIndex = 0 ;
607+ this . state = State . Text ;
608+ this . sectionStart = this . index + 1 ;
609+ } else {
610+ // Keep scanning for the next `?`, which can start a closing `?>`.
611+ this . sequenceIndex = Number (
612+ this . fastForwardTo ( CharCodes . Questionmark ) ,
613+ ) ;
614+ }
615+ } else if ( c === CharCodes . Gt || this . fastForwardTo ( CharCodes . Gt ) ) {
578616 this . cbs . onprocessinginstruction ( this . sectionStart , this . index ) ;
579617 this . state = State . Text ;
580618 this . sectionStart = this . index + 1 ;
0 commit comments