@@ -153,7 +153,7 @@ export class BgGMXhr {
153153 this . isConnDisconnected = false ;
154154 }
155155
156- onDataReceived ( param : { chunk : boolean ; type : string ; data : any } ) {
156+ private readonly onDataReceived = ( param : { chunk : boolean ; type : string ; data : any } ) => {
157157 stackAsyncTask ( this . taskId , async ( ) => {
158158 if ( this . isConnDisconnected ) return ;
159159 try {
@@ -211,7 +211,7 @@ export class BgGMXhr {
211211 console . error ( e ) ;
212212 }
213213 } ) ;
214- }
214+ } ;
215215
216216 callback ( result : BgGMXhrCallbackResult ) {
217217 const data = {
@@ -266,7 +266,7 @@ export class BgGMXhr {
266266 let rawData = ( details . data = await details . data ) ;
267267
268268 const baseXHR = useFetch
269- ? new FetchXHR ( isBufferStream , this . onDataReceived . bind ( this ) , ( opts : RequestInit ) => {
269+ ? new FetchXHR ( isBufferStream , this . onDataReceived , ( opts : RequestInit ) => {
270270 if ( redirect ) {
271271 opts . redirect = redirect ;
272272 }
@@ -283,113 +283,114 @@ export class BgGMXhr {
283283 } )
284284 : new XMLHttpRequest ( ) ;
285285
286- this . abort = ( ) => {
287- baseXHR . abort ( ) ;
288- } ;
286+ this . abort = baseXHR . abort . bind ( baseXHR ) ;
289287
290288 const url = details . url ;
291289 if ( details . overrideMimeType ) {
292290 baseXHR . overrideMimeType ( details . overrideMimeType ) ;
293291 }
294292
295- let contentType = "" ;
296- let responseHeaders : string | null = null ;
297- let finalStateChangeEvent : XHREvent | null = null ;
298- let canTriggerFinalStateChangeEvent = false ;
299- const callback = ( evt : XHREvent , err ?: Error | string ) => {
300- const xhr = baseXHR ;
301- const eventType = evt . type ;
302- // 对齐 TM 的实现:不处理 readyState 从 0 到 1 和 2 到 3 的 onreadystatechange 事件。
303- if ( useFetch && eventType === "readystatechange" && ( xhr . readyState === 1 || xhr . readyState === 3 ) ) {
304- return ;
305- }
306- const isProgressEvt = isProgressEvent ( evt ) ;
307-
308- if ( eventType === "load" ) {
309- canTriggerFinalStateChangeEvent = true ;
310- if ( finalStateChangeEvent ) callback ( finalStateChangeEvent ) ;
311- } else if ( eventType === "readystatechange" && xhr . readyState === 4 ) {
312- // readyState4 的readystatechange或会重复,见 https://github.com/violentmonkey/violentmonkey/issues/1862
313- if ( ! canTriggerFinalStateChangeEvent ) {
314- finalStateChangeEvent = evt ;
293+ {
294+ const localThis = baseXHR ;
295+ let contentType = "" ;
296+ let responseHeaders : string | null = null ;
297+ let finalStateChangeEvent : XHREvent | null = null ;
298+ let canTriggerFinalStateChangeEvent = false ;
299+ const callback = ( evt : XHREvent , err ?: Error | string ) => {
300+ const xhr = localThis ;
301+ const eventType = evt . type ;
302+ // 对齐 TM 的实现:不处理 readyState 从 0 到 1 和 2 到 3 的 onreadystatechange 事件。
303+ if ( useFetch && eventType === "readystatechange" && ( xhr . readyState === 1 || xhr . readyState === 3 ) ) {
315304 return ;
316305 }
317- }
318- canTriggerFinalStateChangeEvent = false ;
319- finalStateChangeEvent = null ;
320-
321- // contentType 和 responseHeaders 只读一次
322- contentType = contentType || xhr . getResponseHeader ( "Content-Type" ) || "" ;
323- if ( contentType && ! responseHeaders ) {
324- // TM兼容: 原生xhr有 \r\n 在尾,但TM的GMXhr没有;同时除去冒号后面的空白
325- responseHeaders = normalizeResponseHeaders ( xhr . getAllResponseHeaders ( ) ) ;
326- }
327- if ( ! ( xhr instanceof FetchXHR ) ) {
328- const response = xhr . response ;
329- if ( xhr . readyState === 4 && eventType === "readystatechange" ) {
330- if ( xhrResponseType === "" || xhrResponseType === "text" ) {
331- this . onDataReceived ( { chunk : false , type : "text" , data : xhr . responseText } ) ;
332- } else if ( xhrResponseType === "arraybuffer" && response instanceof ArrayBuffer ) {
333- this . onDataReceived ( { chunk : false , type : "arraybuffer" , data : response } ) ;
306+ const isProgressEvt = isProgressEvent ( evt ) ;
307+
308+ if ( eventType === "load" ) {
309+ canTriggerFinalStateChangeEvent = true ;
310+ if ( finalStateChangeEvent ) callback ( finalStateChangeEvent ) ;
311+ } else if ( eventType === "readystatechange" && xhr . readyState === 4 ) {
312+ // readyState4 的readystatechange或会重复,见 https://github.com/violentmonkey/violentmonkey/issues/1862
313+ if ( ! canTriggerFinalStateChangeEvent ) {
314+ finalStateChangeEvent = evt ;
315+ return ;
316+ }
317+ }
318+ canTriggerFinalStateChangeEvent = false ;
319+ finalStateChangeEvent = null ;
320+
321+ // contentType 和 responseHeaders 只读一次
322+ contentType = contentType || xhr . getResponseHeader ( "Content-Type" ) || "" ;
323+ if ( contentType && ! responseHeaders ) {
324+ // TM兼容: 原生xhr有 \r\n 在尾,但TM的GMXhr没有;同时除去冒号后面的空白
325+ responseHeaders = normalizeResponseHeaders ( xhr . getAllResponseHeaders ( ) ) ;
326+ }
327+ if ( ! ( xhr instanceof FetchXHR ) ) {
328+ const response = xhr . response ;
329+ if ( xhr . readyState === 4 && eventType === "readystatechange" ) {
330+ if ( xhrResponseType === "" || xhrResponseType === "text" ) {
331+ this . onDataReceived ( { chunk : false , type : "text" , data : xhr . responseText } ) ;
332+ } else if ( xhrResponseType === "arraybuffer" && response instanceof ArrayBuffer ) {
333+ this . onDataReceived ( { chunk : false , type : "arraybuffer" , data : response } ) ;
334+ }
334335 }
335336 }
336- }
337337
338- const result : BgGMXhrCallbackResult = {
339- /*
340-
341-
342- finalUrl: string; // sw handle
343- readyState: 0 | 4 | 2 | 3 | 1;
344- status: number;
345- statusText: string;
346- responseHeaders: string;
347- error?: string; // sw handle?
348-
349- useFetch: boolean,
350- eventType: string,
351- ok: boolean,
352- contentType: string,
353- error: undefined | string,
354-
355- */
356-
357- useFetch : useFetch ,
358- eventType : eventType ,
359- ok : xhr . status >= 200 && xhr . status < 300 ,
360- contentType,
361- // Always
362- readyState : xhr . readyState as GMTypes . ReadyState ,
363- // After response headers
364- status : xhr . status ,
365- statusText : xhr . statusText ,
366- // After load
367- // response: response,
368- // responseText: responseText,
369- // responseXML: responseXML,
370- // After headers received
371- responseHeaders : responseHeaders ,
372- responseURL : xhr . responseURL ,
373- // How to get the error message in native XHR ?
374- error : eventType !== "error" ? undefined : ( err as Error ) ?. message || err || "Unknown Error" ,
375- } satisfies BgGMXhrCallbackResult ;
376-
377- if ( isProgressEvt ) {
378- result . total = evt . total ;
379- result . loaded = evt . loaded ;
380- result . lengthComputable = evt . lengthComputable ;
381- }
338+ const result : BgGMXhrCallbackResult = {
339+ /*
340+
341+
342+ finalUrl: string; // sw handle
343+ readyState: 0 | 4 | 2 | 3 | 1;
344+ status: number;
345+ statusText: string;
346+ responseHeaders: string;
347+ error?: string; // sw handle?
348+
349+ useFetch: boolean,
350+ eventType: string,
351+ ok: boolean,
352+ contentType: string,
353+ error: undefined | string,
354+
355+ */
356+
357+ useFetch : useFetch ,
358+ eventType : eventType ,
359+ ok : xhr . status >= 200 && xhr . status < 300 ,
360+ contentType,
361+ // Always
362+ readyState : xhr . readyState as GMTypes . ReadyState ,
363+ // After response headers
364+ status : xhr . status ,
365+ statusText : xhr . statusText ,
366+ // After load
367+ // response: response,
368+ // responseText: responseText,
369+ // responseXML: responseXML,
370+ // After headers received
371+ responseHeaders : responseHeaders ,
372+ responseURL : xhr . responseURL ,
373+ // How to get the error message in native XHR ?
374+ error : eventType !== "error" ? undefined : ( err as Error ) ?. message || err || "Unknown Error" ,
375+ } satisfies BgGMXhrCallbackResult ;
376+
377+ if ( isProgressEvt ) {
378+ result . total = evt . total ;
379+ result . loaded = evt . loaded ;
380+ result . lengthComputable = evt . lengthComputable ;
381+ }
382382
383- this . callback ( result ) ;
384- } ;
385- baseXHR . onabort = callback ;
386- baseXHR . onloadstart = callback ;
387- baseXHR . onload = callback ;
388- baseXHR . onerror = callback ;
389- baseXHR . onprogress = callback ;
390- baseXHR . ontimeout = callback ;
391- baseXHR . onreadystatechange = callback ;
392- baseXHR . onloadend = callback ;
383+ this . callback ( result ) ;
384+ } ;
385+ baseXHR . onabort = callback ;
386+ baseXHR . onloadstart = callback ;
387+ baseXHR . onload = callback ;
388+ baseXHR . onerror = callback ;
389+ baseXHR . onprogress = callback ;
390+ baseXHR . ontimeout = callback ;
391+ baseXHR . onreadystatechange = callback ;
392+ baseXHR . onloadend = callback ;
393+ }
393394
394395 baseXHR . open ( details . method ?? "GET" , url , true , details . user , details . password ) ;
395396
@@ -482,15 +483,17 @@ export class BgGMXhr {
482483 await prepareXHR ( ) ;
483484 }
484485
486+ private readonly handleDisconnect = ( ) => {
487+ this . isConnDisconnected = true ;
488+ this . abort ?.( ) ;
489+ // console.warn("msgConn.onDisconnect");
490+ } ;
491+
485492 do ( ) {
486493 this . bgXhrRequestFn ( ) . catch ( ( e : any ) => {
487494 this . abort ?.( ) ;
488495 console . error ( e ) ;
489496 } ) ;
490- this . msgConn . onDisconnect ( ( ) => {
491- this . isConnDisconnected = true ;
492- this . abort ?.( ) ;
493- // console.warn("msgConn.onDisconnect");
494- } ) ;
497+ this . msgConn . onDisconnect ( this . handleDisconnect ) ;
495498 }
496499}
0 commit comments