diff --git a/src/loaders/LoadingManager.js b/src/loaders/LoadingManager.js index 69339f44ff2ed0..02c3991d488a38 100644 --- a/src/loaders/LoadingManager.js +++ b/src/loaders/LoadingManager.js @@ -72,9 +72,10 @@ class LoadingManager { /** * Used for aborting ongoing requests in loaders using this manager. * - * @type {AbortController} + * @private + * @type {AbortController | null} */ - this.abortController = new AbortController(); + this._abortController = null; /** * This should be called by any loader using the manager when the loader @@ -285,8 +286,9 @@ class LoadingManager { */ this.abort = function () { + this.abortController.abort(); - this.abortController = new AbortController(); + this._abortController = null; return this; @@ -294,6 +296,26 @@ class LoadingManager { } + // TODO: Revert this back to a single member variable once this issue has been fixed + // https://github.com/cloudflare/workerd/issues/3657 + + /** + * Used for aborting ongoing requests in loaders using this manager. + * + * @type {AbortController} + */ + get abortController() { + + if ( ! this._abortController ) { + + this._abortController = new AbortController(); + + } + + return this._abortController; + + } + } /** diff --git a/test/unit/src/loaders/LoadingManager.tests.js b/test/unit/src/loaders/LoadingManager.tests.js index 0c1fb6939b2afd..008e0aed550986 100644 --- a/test/unit/src/loaders/LoadingManager.tests.js +++ b/test/unit/src/loaders/LoadingManager.tests.js @@ -121,6 +121,56 @@ export default QUnit.module( 'Loaders', () => { } ); + QUnit.test( 'abortController - lazy instantiation', ( assert ) => { + + const loadingManager = new LoadingManager(); + + assert.equal( loadingManager._abortController, null, '_abortController is initially null.' ); + + const controller = loadingManager.abortController; + + assert.ok( controller instanceof AbortController, 'abortController returns an AbortController instance.' ); + assert.equal( loadingManager._abortController, controller, '_abortController is set after first access.' ); + + const controller2 = loadingManager.abortController; + assert.equal( controller, controller2, 'Subsequent accesses return the same AbortController instance.' ); + + } ); + + QUnit.test( 'abort() - aborts controller and resets', ( assert ) => { + + const loadingManager = new LoadingManager(); + + const controller = loadingManager.abortController; + + assert.ok( ! controller.signal.aborted, 'Controller signal is not aborted initially.' ); + + loadingManager.abort(); + + assert.ok( controller.signal.aborted, 'Controller signal is aborted after calling abort().' ); + assert.equal( loadingManager._abortController, null, '_abortController is reset to null after abort().' ); + + } ); + + QUnit.test( 'abortController - recreation after abort', ( assert ) => { + + const loadingManager = new LoadingManager(); + + const controller1 = loadingManager.abortController; + + loadingManager.abort(); + + assert.ok( controller1.signal.aborted, 'First controller is aborted.' ); + assert.equal( loadingManager._abortController, null, '_abortController is null after abort.' ); + + const controller2 = loadingManager.abortController; + + assert.ok( controller2 instanceof AbortController, 'New AbortController is created.' ); + assert.notEqual( controller1, controller2, 'New controller is a different instance from the aborted one.' ); + assert.ok( ! controller2.signal.aborted, 'New controller signal is not aborted.' ); + + } ); + } ); } );