diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 4e6c77d..f5d615c 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -113,6 +113,15 @@ * @private */ this._mask = null; + + /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; } /** @@ -403,6 +412,8 @@ this.interactive = false; this.interactiveChildren = false; + + this._destroyed = true; } /** diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 4e6c77d..f5d615c 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -113,6 +113,15 @@ * @private */ this._mask = null; + + /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; } /** @@ -403,6 +412,8 @@ this.interactive = false; this.interactiveChildren = false; + + this._destroyed = true; } /** diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..bbee141 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -203,6 +203,15 @@ } /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; + + /** * Fired when a not-immediately-available source finishes loading. * * @protected @@ -598,6 +607,8 @@ this.source = null; this.dispose(); + + this._destroyed = true; } /** diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 4e6c77d..f5d615c 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -113,6 +113,15 @@ * @private */ this._mask = null; + + /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; } /** @@ -403,6 +412,8 @@ this.interactive = false; this.interactiveChildren = false; + + this._destroyed = true; } /** diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..bbee141 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -203,6 +203,15 @@ } /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; + + /** * Fired when a not-immediately-available source finishes loading. * * @protected @@ -598,6 +607,8 @@ this.source = null; this.dispose(); + + this._destroyed = true; } /** diff --git a/src/prepare/BasePrepare.js b/src/prepare/BasePrepare.js index 09eb5e5..a4aae2f 100644 --- a/src/prepare/BasePrepare.js +++ b/src/prepare/BasePrepare.js @@ -172,13 +172,16 @@ const item = this.queue[0]; let uploaded = false; - for (let i = 0, len = this.uploadHooks.length; i < len; i++) + if (item && !item._destroyed) { - if (this.uploadHooks[i](this.uploadHookHelper, item)) + for (let i = 0, len = this.uploadHooks.length; i < len; i++) { - this.queue.shift(); - uploaded = true; - break; + if (this.uploadHooks[i](this.uploadHookHelper, item)) + { + this.queue.shift(); + uploaded = true; + break; + } } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 4e6c77d..f5d615c 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -113,6 +113,15 @@ * @private */ this._mask = null; + + /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; } /** @@ -403,6 +412,8 @@ this.interactive = false; this.interactiveChildren = false; + + this._destroyed = true; } /** diff --git a/src/core/textures/BaseTexture.js b/src/core/textures/BaseTexture.js index aeccf39..bbee141 100644 --- a/src/core/textures/BaseTexture.js +++ b/src/core/textures/BaseTexture.js @@ -203,6 +203,15 @@ } /** + * If the object has been destroyed via destroy(). If true, it should not be used. + * + * @member {boolean} + * @private + * @readonly + */ + this._destroyed = false; + + /** * Fired when a not-immediately-available source finishes loading. * * @protected @@ -598,6 +607,8 @@ this.source = null; this.dispose(); + + this._destroyed = true; } /** diff --git a/src/prepare/BasePrepare.js b/src/prepare/BasePrepare.js index 09eb5e5..a4aae2f 100644 --- a/src/prepare/BasePrepare.js +++ b/src/prepare/BasePrepare.js @@ -172,13 +172,16 @@ const item = this.queue[0]; let uploaded = false; - for (let i = 0, len = this.uploadHooks.length; i < len; i++) + if (item && !item._destroyed) { - if (this.uploadHooks[i](this.uploadHookHelper, item)) + for (let i = 0, len = this.uploadHooks.length; i < len; i++) { - this.queue.shift(); - uploaded = true; - break; + if (this.uploadHooks[i](this.uploadHookHelper, item)) + { + this.queue.shift(); + uploaded = true; + break; + } } } diff --git a/test/prepare/BasePrepare.js b/test/prepare/BasePrepare.js index 03cf2fa..3cfa476 100644 --- a/test/prepare/BasePrepare.js +++ b/test/prepare/BasePrepare.js @@ -121,6 +121,40 @@ prep.destroy(); }); + it('should remove destroyed items from queue', function () + { + const prep = new PIXI.prepare.BasePrepare(); + + const addHook = sinon.spy(function (item, queue) + { + queue.push(item); + + return true; + }); + const uploadHook = sinon.spy(function () + { + return false; + }); + const complete = sinon.spy(function () { /* empty */ }); + + prep.register(addHook, uploadHook); + const item = {}; + + prep.upload(item, complete); + + expect(prep.queue).to.have.lengthOf(1); + + item._destroyed = true; + prep.prepareItems(); + + expect(prep.queue).to.be.empty; + expect(addHook.calledOnce).to.be.true; + expect(uploadHook.called).to.be.false; + expect(complete.calledOnce).to.be.true; + + prep.destroy(); + }); + it('should attach to SharedTicker', function (done) { const prep = new PIXI.prepare.BasePrepare();