@@ -20,7 +20,7 @@ const debug = globalThis.python.eval('__import__("pythonmonkey").bootstrap.requi
20
20
* @param {any } what The thing to truncate; must have a slice method and index property.
21
21
* Works with string, array, typedarray, etc.
22
22
* @param {number } maxlen The maximum length for truncation
23
- * @param {boolean } coerce Not false = coerce to printable character codes
23
+ * @param {boolean= } coerce Not false = coerce to printable character codes
24
24
* @returns {string }
25
25
*/
26
26
function trunc ( what , maxlen , coerce )
@@ -104,6 +104,34 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
104
104
/** @type {EventListenerFn } */
105
105
onreadystatechange = null ;
106
106
107
+ //
108
+ // debugging
109
+ //
110
+ /** The unique connection id to identify each XHR connection when debugging */
111
+ #connectionId = Math . random ( ) . toString ( 16 ) . slice ( 2 , 9 ) ; // random 7-character hex string
112
+
113
+ /**
114
+ * Wrapper to print debug logs with connection id information
115
+ * @param {string } selector
116
+ */
117
+ #debug( selector )
118
+ {
119
+ return ( ...args ) => debug ( selector ) ( `Conn<${ this . #connectionId} >:` , ...args ) ;
120
+ }
121
+
122
+ /**
123
+ * Allowing others to inspect the internal properties
124
+ */
125
+ get _requestMetadata ( )
126
+ {
127
+ return {
128
+ method : this . #requestMethod,
129
+ url : this . #requestURL. toString ( ) ,
130
+ headers : this . #requestHeaders,
131
+ body : this . #requestBody,
132
+ } ;
133
+ }
134
+
107
135
//
108
136
// states
109
137
//
@@ -142,7 +170,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
142
170
*/
143
171
open ( method , url , async = true , username = null , password = null )
144
172
{
145
- debug ( 'xhr:open' ) ( 'open start, method=' + method ) ;
173
+ this . # debug( 'xhr:open' ) ( 'open start, method=' + method ) ;
146
174
// Normalize the method.
147
175
// @ts -expect-error
148
176
method = method . toString ( ) . toUpperCase ( ) ;
@@ -156,7 +184,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
156
184
parsedURL . username = username ;
157
185
if ( password )
158
186
parsedURL . password = password ;
159
- debug ( 'xhr:open' ) ( 'url is ' + parsedURL . href ) ;
187
+ this . # debug( 'xhr:open' ) ( 'url is ' + parsedURL . href ) ;
160
188
161
189
// step 11
162
190
this . #sendFlag = false ;
@@ -176,7 +204,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
176
204
this . #state = XMLHttpRequest . OPENED ;
177
205
this . dispatchEvent ( new Event ( 'readystatechange' ) ) ;
178
206
}
179
- debug ( 'xhr:open' ) ( 'finished open, state is ' + this . #state) ;
207
+ this . # debug( 'xhr:open' ) ( 'finished open, state is ' + this . #state) ;
180
208
}
181
209
182
210
/**
@@ -186,7 +214,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
186
214
*/
187
215
setRequestHeader ( name , value )
188
216
{
189
- debug ( 'xhr:headers' ) ( `set header ${ name } =${ value } ` ) ;
217
+ this . # debug( 'xhr:headers' ) ( `set header ${ name } =${ value } ` ) ;
190
218
if ( this . #state !== XMLHttpRequest . OPENED )
191
219
throw new DOMException ( 'setRequestHeader can only be called when state is OPEN' , 'InvalidStateError' ) ;
192
220
if ( this . #sendFlag)
@@ -252,7 +280,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
252
280
*/
253
281
send ( body = null )
254
282
{
255
- debug ( 'xhr:send' ) ( `sending; body length=${ body ?. length } ` ) ;
283
+ this . # debug( 'xhr:send' ) ( `sending; body length=${ body ?. length } « ${ body ? trunc ( body , 100 ) : '' } » ` ) ;
256
284
if ( this . #state !== XMLHttpRequest . OPENED ) // step 1
257
285
throw new DOMException ( 'connection must be opened before send() is called' , 'InvalidStateError' ) ;
258
286
if ( this . #sendFlag) // step 2
@@ -285,7 +313,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
285
313
if ( ! originalAuthorContentType && extractedContentType )
286
314
this . #requestHeaders[ 'content-type' ] = extractedContentType ;
287
315
}
288
- debug ( 'xhr:send' ) ( `content-type=${ this . #requestHeaders[ 'content-type' ] } ` ) ;
316
+ this . # debug( 'xhr:send' ) ( `content-type=${ this . #requestHeaders[ 'content-type' ] } ` ) ;
289
317
290
318
// step 5
291
319
if ( this . #uploadObject. _hasAnyListeners ( ) )
@@ -310,7 +338,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
310
338
*/
311
339
#sendAsync( )
312
340
{
313
- debug ( 'xhr:send' ) ( 'sending in async mode' ) ;
341
+ this . # debug( 'xhr:send' ) ( 'sending in async mode' ) ;
314
342
this . dispatchEvent ( new ProgressEvent ( 'loadstart' , { loaded :0 , total :0 } ) ) ; // step 11.1
315
343
316
344
let requestBodyTransmitted = 0 ; // step 11.2
@@ -343,7 +371,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
343
371
let responseLength = 0 ;
344
372
const processResponse = ( response ) =>
345
373
{
346
- debug ( 'xhr:response' ) ( `response headers ----\n${ response . getAllResponseHeaders ( ) } ` ) ;
374
+ this . # debug( 'xhr:response' ) ( `response headers ----\n${ response . getAllResponseHeaders ( ) } ` ) ;
347
375
this . #response = response ; // step 11.9.1
348
376
this . #state = XMLHttpRequest . HEADERS_RECEIVED ; // step 11.9.4
349
377
this . dispatchEvent ( new Event ( 'readystatechange' ) ) ; // step 11.9.5
@@ -354,7 +382,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
354
382
355
383
const processBodyChunk = ( /** @type {Uint8Array } */ bytes ) =>
356
384
{
357
- debug ( 'xhr:response' ) ( `recv chunk, ${ bytes . length } bytes ( ${ trunc ( bytes , 100 ) } ) ` ) ;
385
+ this . # debug( 'xhr:response' ) ( `recv chunk, ${ bytes . length } bytes « ${ trunc ( bytes , 100 ) } » ` ) ;
358
386
this . #receivedBytes. push ( bytes ) ;
359
387
if ( this . #state === XMLHttpRequest . HEADERS_RECEIVED )
360
388
this . #state = XMLHttpRequest . LOADING ;
@@ -367,7 +395,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
367
395
*/
368
396
const processEndOfBody = ( ) =>
369
397
{
370
- debug ( 'xhr:response' ) ( `end of body, received ${ this . #receivedLength} bytes` ) ;
398
+ this . # debug( 'xhr:response' ) ( `end of body, received ${ this . #receivedLength} bytes` ) ;
371
399
const transmitted = this . #receivedLength; // step 3
372
400
const length = responseLength || 0 ; // step 4
373
401
@@ -380,8 +408,8 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
380
408
this . dispatchEvent ( new ProgressEvent ( eventType , { loaded :transmitted , total :length } ) ) ;
381
409
} ;
382
410
383
- debug ( 'xhr:send' ) ( `${ this . #requestMethod} ${ this . #requestURL. href } ` ) ;
384
- debug ( 'xhr:headers' ) ( 'headers=' + Object . entries ( this . #requestHeaders) ) ;
411
+ this . # debug( 'xhr:send' ) ( `${ this . #requestMethod} ${ this . #requestURL. href } ` ) ;
412
+ this . # debug( 'xhr:headers' ) ( 'headers=' + Object . entries ( this . #requestHeaders) ) ;
385
413
386
414
// send() step 6
387
415
request (
@@ -397,6 +425,7 @@ class XMLHttpRequest extends XMLHttpRequestEventTarget
397
425
processEndOfBody ,
398
426
( ) => ( this . #timedOutFlag = true ) , // onTimeoutError
399
427
( ) => ( this . #response = null /* network error */ ) , // onNetworkError
428
+ this . #debug. bind ( this ) ,
400
429
) . catch ( ( e ) => this . #handleErrors( e ) ) ;
401
430
}
402
431
0 commit comments