55import { IImageAddonOptions , IOscHandler , IResetHandler , ITerminalExt } from './Types' ;
66import { ImageRenderer } from './ImageRenderer' ;
77import { ImageStorage , CELL_SIZE_DEFAULT } from './ImageStorage' ;
8- import Base64Decoder from 'xterm-wasm-parts/lib/base64/Base64Decoder.wasm' ;
8+ import Base64Decoder , { type DecodeStatus } from 'xterm-wasm-parts/lib/base64/Base64Decoder.wasm' ;
99import { HeaderParser , IHeaderFields , HeaderState } from './IIPHeaderParser' ;
1010import { imageType , UNSUPPORTED_TYPE } from './IIPMetrics' ;
1111
12- // limit hold memory in base64 decoder
12+ // limit hold memory in base64 decoder (encoded bytes)
1313const KEEP_DATA = 4194304 ;
14+ const INITIAL_DATA = 1048576 ;
15+
16+ // Local mirror of const enum (esbuild can't inline const enums from external packages)
17+ const DECODER_OK : DecodeStatus . OK = 0 ;
1418
1519// default IIP header values
1620const DEFAULT_HEADER : IHeaderFields = {
@@ -27,15 +31,19 @@ export class IIPHandler implements IOscHandler, IResetHandler {
2731 private _aborted = false ;
2832 private _hp = new HeaderParser ( ) ;
2933 private _header : IHeaderFields = DEFAULT_HEADER ;
30- private _dec = new Base64Decoder ( KEEP_DATA ) ;
34+ private _dec : Base64Decoder ;
3135 private _metrics = UNSUPPORTED_TYPE ;
3236
3337 constructor (
3438 private readonly _opts : IImageAddonOptions ,
3539 private readonly _renderer : ImageRenderer ,
3640 private readonly _storage : ImageStorage ,
3741 private readonly _coreTerminal : ITerminalExt
38- ) { }
42+ ) {
43+ const maxEncodedBytes = Math . ceil ( this . _opts . iipSizeLimit * 4 / 3 ) ;
44+ const initialBytes = Math . min ( INITIAL_DATA , maxEncodedBytes ) ;
45+ this . _dec = new Base64Decoder ( KEEP_DATA , maxEncodedBytes , initialBytes ) ;
46+ }
3947
4048 public reset ( ) : void { }
4149
@@ -50,7 +58,7 @@ export class IIPHandler implements IOscHandler, IResetHandler {
5058 if ( this . _aborted ) return ;
5159
5260 if ( this . _hp . state === HeaderState . END ) {
53- if ( this . _dec . put ( data , start , end ) ) {
61+ if ( this . _dec . put ( data . subarray ( start , end ) ) !== DECODER_OK ) {
5462 this . _dec . release ( ) ;
5563 this . _aborted = true ;
5664 }
@@ -66,8 +74,8 @@ export class IIPHandler implements IOscHandler, IResetHandler {
6674 this . _aborted = true ;
6775 return ;
6876 }
69- this . _dec . init ( this . _header . size ) ;
70- if ( this . _dec . put ( data , dataPos , end ) ) {
77+ this . _dec . init ( ) ;
78+ if ( this . _dec . put ( data . subarray ( dataPos , end ) ) !== DECODER_OK ) {
7179 this . _dec . release ( ) ;
7280 this . _aborted = true ;
7381 }
@@ -85,13 +93,15 @@ export class IIPHandler implements IOscHandler, IResetHandler {
8593 let cond : number | boolean = true ;
8694 if ( cond = success ) {
8795 if ( cond = ! this . _dec . end ( ) ) {
88- this . _metrics = imageType ( this . _dec . data8 ) ;
89- if ( cond = this . _metrics . mime !== 'unsupported' ) {
90- w = this . _metrics . width ;
91- h = this . _metrics . height ;
92- if ( cond = w && h && w * h < this . _opts . pixelLimit ) {
93- [ w , h ] = this . _resize ( w , h ) . map ( Math . floor ) ;
94- cond = w && h && w * h < this . _opts . pixelLimit ;
96+ if ( cond = this . _dec . data8 . length === this . _header . size ) {
97+ this . _metrics = imageType ( this . _dec . data8 ) ;
98+ if ( cond = this . _metrics . mime !== 'unsupported' ) {
99+ w = this . _metrics . width ;
100+ h = this . _metrics . height ;
101+ if ( cond = w && h && w * h < this . _opts . pixelLimit ) {
102+ [ w , h ] = this . _resize ( w , h ) . map ( Math . floor ) ;
103+ cond = w && h && w * h < this . _opts . pixelLimit ;
104+ }
95105 }
96106 }
97107 }
0 commit comments