phaserjs / phaser-ce

Phaser CE is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
http://phaser.io
MIT License
1.34k stars 491 forks source link

Error thrown when destroying the game too early and using WebAudio #684

Closed jf-m closed 3 years ago

jf-m commented 3 years ago

This Issue is about


Hello there and thank you for maintaining this repo !

Several errors may occurs when destroying the game too early. These errors are all related to WebAudio.

Note that these errors occurred in a single page app where window.PhaserGlobal = {}; has been set as suggested in the doc.

1. Cannot set property 'onended' of null

Stacktrace:

phaser.js:59104 Uncaught TypeError: Cannot set property 'onended' of null
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Sound._removeOnEndedHandler (phaser.js:59104)
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Sound.onEndedHandler (phaser.js:58397)

Concerned line of code:

https://github.com/photonstorm/phaser-ce/blob/585160726bf3be112d7a37c8469171a3203e1ae5/src/sound/Sound.js#L1135-L1138

Comment: I guess this._sound is null or undefined at this stage, when the whole game has been destroyed.

2. Cannot read property 'noAudio' of null

Stacktrace:

phaser.js:56719 Uncaught TypeError: Cannot read property 'noAudio' of null
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Loader.getAudioURL (phaser.js:56719)
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Loader.loadFile (phaser.js:56269)
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Loader.processLoadQueue (phaser.js:56008)
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Loader.asyncComplete (phaser.js:56110)
    at XMLHttpRequest.xhr.onload (phaser.js:56619)

Concerned line of code: https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L1271-L1276

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2850-L2855

Comment: We should check the existence of this.game and this.game.sound beforehand.

3. Cannot read property 'usingWebAudio' of null

This one is a warning, not an error so it's less important but still.

Stacktrace:

Cannot read property 'usingWebAudio' of null
asyncComplete | @ | phaser.js:56107

Concerned line of code:

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2407-L2410

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L3051-L3061

Being catch and log as a warning here: https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2240

4. Cannot read property 'decodedSound' of null

Stacktrace:

Uncaught TypeError: Cannot read property 'decodedSound' of null
    at AudioContext.<anonymous> (phaser.js:59771)

Concerned line of code: https://github.com/photonstorm/phaser-ce/blob/ccbe5d7277194a4607492928ff26997ebc34c9ed/src/sound/SoundManager.js#L527-L534

5. Cannot read property 'update' of null

Stacktrace:

phaser.js:14822 Uncaught TypeError: Cannot read property 'update' of null
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.Game.update (phaser.js:14822)
    at push../resources/assets/js/plugins/phaser.js?a3d3.Phaser.RequestAnimationFrame.updateRAF (phaser.js:43150)
    at _onLoop (phaser.js:43134)
    at __trace__ (bugsnag.js:2613)

Concerned line of code: https://github.com/photonstorm/phaser-ce/blob/585160726bf3be112d7a37c8469171a3203e1ae5/src/core/Game.js#L982-L991

Comment: I guess that one is not related to the use of WebAudio

Most of this should be solved by adding some conditional check I suppose.

Once again, thank you for maintaining this repo, have a good day. 👍

samme commented 3 years ago

Thanks for this report. Did you use game.destroy() or game.pendingDestroy = true?

samme commented 3 years ago
  1. Cannot read property 'update' of null

I'm not sure what to do about this one, since setting pendingDestroy would avoid the error. I guess a second check could be added.

jf-m commented 3 years ago

I'm using game.destroy() to destroy the game.

The game is located in a vueJS Component, when the VueJS component unloads, right before removing the canvas from the dom (VueJS's beforeDestroy method) , I call game.destroy().

I was using Phaser-ce 2.16.0 before that, with no sound at all in the game. I just recently added the sound effects and updated to 2.16.2 at the same time. This is when all of these 5 errors occured.

Before that, I had no issues when destroying the game. Even the 5th one reported here wasn't there before. (but oddly it does not seems to be related to WebAudio...).

samme commented 3 years ago

Could you try this build and see if it avoids the errors? phaser-test.js.zip

jf-m commented 3 years ago

@samme this build seems to solves the errors : 1, 2, 4 and 5

The number 3 (a warning) is not solved though, it still says Cannot read property 'usingWebAudio' of null in a console warning message.

To give you more informations, the exception is thrown from here:

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L3051

Then it's caught here:

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2743-L2753

Then it's in the asyncComplete that it's logged as a warning.

But this exception is all inside a FileComplete event inside a xhrLoad request. This original xhrLoad has been initiated here:

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2409

So I guess that inside the loadFile, the isBooted is still true because the game is here, but I assume that the game is destroyed during the xhr request, and the isBooted is false when the xhr request is completed. We should probably add a conditional on isBooted inside the fileComplete method.

If I add the following

      if (!this.game.isBooted)
      {
        return;
      }

Right at the beginning of:

https://github.com/photonstorm/phaser-ce/blob/c7f5f4345530fea0ad5a2d578b1c7fc26513380a/src/loader/Loader.js#L2934-L2936

The warning goes away

Hope this helps 👍

samme commented 3 years ago

We should probably add a conditional on isBooted inside the fileComplete method.

I think phaser-test.js has that.

jf-m commented 3 years ago

@samme My bad, you're right !

I actually couldn't use directly your build and had to show the diff and impact it one by one, seems like I missed that one.

I tested it once again, and it seems to be perfectly working, thank you !

samme commented 3 years ago

Fixed in https://github.com/photonstorm/phaser-ce/releases/tag/v2.17.0