@@ -506,6 +506,10 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
506506 * - OSC_STRING:OSC_PUT
507507 * - DCS_PASSTHROUGH:DCS_PUT
508508 *
509+ * Additionally the following fast paths exist before the table lookup:
510+ * - EXE bytes < 0x18 in non-payload states (avoids table lookup entirely)
511+ * - 7-bit CSI sequences without intermediates (ESC [ params final)
512+ *
509513 * Note on asynchronous handler support:
510514 * Any handler returning a promise will be treated as asynchronous.
511515 * To keep the in-band blocking working for async handlers, `parse` pauses execution,
@@ -649,34 +653,89 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
649653 for ( let i = start ; i < length ; ++ i ) {
650654 code = data [ i ] ;
651655
656+ // EXE fast-path: common control bytes (0x00-0x17) in non-payload states
657+ if ( code < 0x18 && this . currentState <= ParserState . CSI_IGNORE ) {
658+ if ( this . _executeHandlers [ code ] ) this . _executeHandlers [ code ] ( ) ;
659+ else this . _executeHandlerFb ( code ) ;
660+ this . precedingJoinState = 0 ;
661+ continue ;
662+ }
663+
664+ // CSI fast-path: collapse ESC [ into a single entry, parse params+final in a tight loop
665+ if ( code === 0x1b
666+ && this . currentState < ParserState . OSC_STRING
667+ && i + 2 < length && data [ i + 1 ] === 0x5b
668+ ) {
669+ this . _params . reset ( ) ;
670+ this . _params . addParam ( 0 ) ; // ZDM
671+ this . _collect = 0 ;
672+ let k = i + 2 ;
673+ let ch = data [ k ] ;
674+ if ( ch >= 0x3c && ch <= 0x3f ) {
675+ this . _collect = ch ;
676+ k ++ ;
677+ }
678+ let csiDone = false ;
679+ for ( ; k < length ; k ++ ) {
680+ ch = data [ k ] ;
681+ if ( ch >= 0x30 && ch <= 0x39 ) {
682+ this . _params . addDigit ( ch - 48 ) ;
683+ } else if ( ch === 0x3b ) {
684+ this . _params . addParam ( 0 ) ;
685+ } else if ( ch === 0x3a ) {
686+ this . _params . addSubParam ( - 1 ) ;
687+ } else if ( ch >= 0x40 && ch <= 0x7e ) {
688+ const handlers = this . _csiHandlers [ this . _collect << 8 | ch ] ;
689+ let j = handlers ? handlers . length - 1 : - 1 ;
690+ for ( ; j >= 0 ; j -- ) {
691+ handlerResult = handlers [ j ] ( this . _params ) ;
692+ if ( handlerResult === true ) {
693+ break ;
694+ } else if ( handlerResult instanceof Promise ) {
695+ transition = ParserAction . CSI_DISPATCH << TableAccess . TRANSITION_ACTION_SHIFT | ParserState . GROUND ;
696+ this . _preserveStack ( ParserStackType . CSI , handlers , j , transition , k ) ;
697+ return handlerResult ;
698+ }
699+ }
700+ if ( j < 0 ) {
701+ this . _csiHandlerFb ( this . _collect << 8 | ch , this . _params ) ;
702+ }
703+ this . precedingJoinState = 0 ;
704+ i = k ;
705+ this . currentState = ParserState . GROUND ;
706+ csiDone = true ;
707+ break ;
708+ } else {
709+ break ;
710+ }
711+ }
712+ if ( ! csiDone ) {
713+ i = k - 1 ;
714+ this . currentState = ParserState . CSI_PARAM ;
715+ }
716+ continue ;
717+ }
718+
652719 // normal transition & action lookup
653720 transition = this . _transitions . table [ this . currentState << TableAccess . INDEX_STATE_SHIFT | ( code < 0xa0 ? code : NON_ASCII_PRINTABLE ) ] ;
654721 switch ( transition >> TableAccess . TRANSITION_ACTION_SHIFT ) {
655722 case ParserAction . PRINT :
656- // read ahead with loop unrolling
657723 // Note: 0x20 (SP) is included, 0x7F (DEL) is excluded
658- for ( let j = i + 1 ; ; ++ j ) {
659- if ( j >= length || ( code = data [ j ] ) < 0x20 || ( code > 0x7e && code < NON_ASCII_PRINTABLE ) ) {
660- this . _printHandler ( data , i , j ) ;
661- i = j - 1 ;
662- break ;
663- }
664- if ( ++ j >= length || ( code = data [ j ] ) < 0x20 || ( code > 0x7e && code < NON_ASCII_PRINTABLE ) ) {
665- this . _printHandler ( data , i , j ) ;
666- i = j - 1 ;
667- break ;
668- }
669- if ( ++ j >= length || ( code = data [ j ] ) < 0x20 || ( code > 0x7e && code < NON_ASCII_PRINTABLE ) ) {
670- this . _printHandler ( data , i , j ) ;
671- i = j - 1 ;
672- break ;
673- }
674- if ( ++ j >= length || ( code = data [ j ] ) < 0x20 || ( code > 0x7e && code < NON_ASCII_PRINTABLE ) ) {
675- this . _printHandler ( data , i , j ) ;
676- i = j - 1 ;
677- break ;
724+ let c = i ;
725+ const l4 = length - 4 ;
726+ while ( c < l4
727+ && data [ ++ c ] >= 0x20 && ( data [ c ] <= 0x7e || data [ c ] >= NON_ASCII_PRINTABLE )
728+ && data [ ++ c ] >= 0x20 && ( data [ c ] <= 0x7e || data [ c ] >= NON_ASCII_PRINTABLE )
729+ && data [ ++ c ] >= 0x20 && ( data [ c ] <= 0x7e || data [ c ] >= NON_ASCII_PRINTABLE )
730+ && data [ ++ c ] >= 0x20 && ( data [ c ] <= 0x7e || data [ c ] >= NON_ASCII_PRINTABLE )
731+ ) { }
732+ if ( c >= l4 ) {
733+ while ( c < length && data [ c ] >= 0x20 && ( data [ c ] <= 0x7e || data [ c ] >= NON_ASCII_PRINTABLE ) ) {
734+ c ++ ;
678735 }
679736 }
737+ this . _printHandler ( data , i , c ) ;
738+ i = c - 1 ;
680739 break ;
681740 case ParserAction . EXECUTE :
682741 if ( this . _executeHandlers [ code ] ) this . _executeHandlers [ code ] ( ) ;
0 commit comments