@@ -189,6 +189,7 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
189189 protected _aborted = false ;
190190 protected _timedOut = false ;
191191 protected _paused = false ;
192+ protected _created = Date . now ( ) ;
192193
193194 // De-dupe result handling for two reasons so far:
194195 // 1. Various platforms have bugs where they double-resolves aborted xmlhttprequests
@@ -200,7 +201,8 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
200201
201202 constructor ( protected _action : string ,
202203 protected _url : string , options : TOptions ,
203- protected _getHeaders ?: ( ) => Headers ) {
204+ protected _getHeaders ?: ( ) => Headers ,
205+ protected _blockRequestUntil ?: ( ) => SyncTasks . Promise < void > | undefined ) {
204206 this . _options = _ . defaults ( options , DefaultOptions ) ;
205207 }
206208
@@ -213,8 +215,35 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
213215 protected static checkQueueProcessing ( ) {
214216 while ( requestQueue . length > 0 && executingList . length < SimpleWebRequestOptions . MaxSimultaneousRequests ) {
215217 const req = requestQueue . shift ( ) ! ! ! ;
216- executingList . push ( req ) ;
217- req . _fire ( ) ;
218+ const blockPromise = ( req . _blockRequestUntil && req . _blockRequestUntil ( ) ) || SyncTasks . Resolved ( ) ;
219+ blockPromise . then ( ( ) => {
220+ if ( executingList . length < SimpleWebRequestOptions . MaxSimultaneousRequests ) {
221+ executingList . push ( req ) ;
222+ req . _fire ( ) ;
223+ } else {
224+ req . _enqueue ( ) ;
225+ }
226+ } , err => {
227+ // fail the request if the block promise is rejected
228+ req . _respond ( '_blockRequestUntil rejected: ' + err ) ;
229+ } ) ;
230+ }
231+ }
232+
233+ protected _removeFromQueue ( ) : void {
234+ // Pull it out of whichever queue it's sitting in
235+ if ( this . _xhr ) {
236+ _ . pull ( executingList , this ) ;
237+ } else {
238+ _ . pull ( requestQueue , this ) ;
239+ }
240+ }
241+
242+ protected _assertAndClean ( expression : any , message : string ) : void {
243+ if ( ! expression ) {
244+ this . _removeFromQueue ( ) ;
245+ console . error ( message ) ;
246+ assert . ok ( expression , message ) ;
218247 }
219248 }
220249
@@ -240,7 +269,7 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
240269 const timeoutSupported = timeoutSupportStatus ;
241270 // Use manual timer if we don't know about timeout support
242271 if ( timeoutSupported !== FeatureSupportStatus . Supported ) {
243- assert . ok ( ! this . _requestTimeoutTimer , 'Double-fired requestTimeoutTimer' ) ;
272+ this . _assertAndClean ( ! this . _requestTimeoutTimer , 'Double-fired requestTimeoutTimer' ) ;
244273 this . _requestTimeoutTimer = SimpleWebRequestOptions . setTimeout ( ( ) => {
245274 this . _requestTimeoutTimer = undefined ;
246275
@@ -262,7 +291,7 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
262291 this . _timedOut = true ;
263292 // Set aborted flag to match simple timer approach, which aborts the request and results in an _respond call
264293 this . _aborted = true ;
265- this . _respond ( ) ;
294+ this . _respond ( 'TimedOut' ) ;
266295 } ;
267296 }
268297 }
@@ -325,7 +354,7 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
325354 // so make sure we know that this is an abort.
326355 this . _aborted = true ;
327356
328- this . _respond ( ) ;
357+ this . _respond ( 'Aborted' ) ;
329358 } ;
330359
331360 if ( this . _xhr . upload && this . _options . onProgress ) {
@@ -344,14 +373,14 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
344373 _ . forEach ( nextHeaders , ( val , key ) => {
345374 const headerLower = key . toLowerCase ( ) ;
346375 if ( headerLower === 'content-type' ) {
347- assert . ok ( false , 'Don\'t set Content-Type with options.headers -- use it with the options.contentType property' ) ;
376+ this . _assertAndClean ( false , 'Don\'t set Content-Type with options.headers -- use it with the options.contentType property' ) ;
348377 return ;
349378 }
350379 if ( headerLower === 'accept' ) {
351- assert . ok ( false , 'Don\'t set Accept with options.headers -- use it with the options.acceptType property' ) ;
380+ this . _assertAndClean ( false , 'Don\'t set Accept with options.headers -- use it with the options.acceptType property' ) ;
352381 return ;
353382 }
354- assert . ok ( ! headersCheck [ headerLower ] , 'Setting duplicate header key: ' + headersCheck [ headerLower ] + ' and ' + key ) ;
383+ this . _assertAndClean ( ! headersCheck [ headerLower ] , 'Setting duplicate header key: ' + headersCheck [ headerLower ] + ' and ' + key ) ;
355384
356385 if ( val === undefined || val === null ) {
357386 console . warn ( 'Tried to set header "' + key + '" on request with "' + val + '" value, header will be dropped' ) ;
@@ -499,11 +528,16 @@ export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions =
499528
500529 // Throw it on the queue
501530 const index = _ . findIndex ( requestQueue , request =>
502- request . getPriority ( ) < ( this . _options . priority || WebRequestPriority . DontCare ) ) ;
531+ // find a request with the same priority, but newer
532+ ( request . getPriority ( ) === this . getPriority ( ) && request . _created > this . _created ) ||
533+ // or a request with lower priority
534+ ( request . getPriority ( ) < this . getPriority ( ) ) ) ;
503535
504536 if ( index > - 1 ) {
537+ //add me before the found request
505538 requestQueue . splice ( index , 0 , this ) ;
506539 } else {
540+ //add me at the end
507541 requestQueue . push ( this ) ;
508542 }
509543
@@ -534,8 +568,9 @@ export class SimpleWebRequest<TBody, TOptions extends WebRequestOptions = WebReq
534568
535569 private _deferred : SyncTasks . Deferred < WebResponse < TBody , TOptions > > ;
536570
537- constructor ( action : string , url : string , options : TOptions , getHeaders ?: ( ) => Headers ) {
538- super ( action , url , options , getHeaders ) ;
571+ constructor ( action : string , url : string , options : TOptions , getHeaders ?: ( ) => Headers ,
572+ blockRequestUntil ?: ( ) => SyncTasks . Promise < void > | undefined ) {
573+ super ( action , url , options , getHeaders , blockRequestUntil ) ;
539574 }
540575
541576 abort ( ) : void {
@@ -562,7 +597,7 @@ export class SimpleWebRequest<TBody, TOptions extends WebRequestOptions = WebReq
562597 }
563598
564599 // Cannot rely on this._xhr.abort() to trigger this._xhr.onAbort() synchronously, thus we must trigger an early response here
565- this . _respond ( ) ;
600+ this . _respond ( 'Aborted' ) ;
566601
567602 if ( this . _xhr ) {
568603 // Abort the in-flight request
@@ -599,12 +634,7 @@ export class SimpleWebRequest<TBody, TOptions extends WebRequestOptions = WebReq
599634
600635 this . _finishHandled = true ;
601636
602- // Pull it out of whichever queue it's sitting in
603- if ( this . _xhr ) {
604- _ . pull ( executingList , this as SimpleWebRequestBase ) ;
605- } else {
606- _ . pull ( requestQueue , this as SimpleWebRequestBase ) ;
607- }
637+ this . _removeFromQueue ( ) ;
608638
609639 if ( this . _retryTimer ) {
610640 SimpleWebRequestOptions . clearTimeout ( this . _retryTimer ) ;
@@ -626,7 +656,7 @@ export class SimpleWebRequest<TBody, TOptions extends WebRequestOptions = WebReq
626656 // Some browsers error when you try to read status off aborted requests
627657 }
628658 } else {
629- statusText = 'Browser Error - Possible CORS or Connectivity Issue' ;
659+ statusText = errorStatusText || 'Browser Error - Possible CORS or Connectivity Issue' ;
630660 }
631661
632662 let headers : Headers = { } ;
0 commit comments