Skip to content

Commit

Permalink
Destroying a Game object during its pointerup event handler on a to…
Browse files Browse the repository at this point in the history
…uch device will no longer cause `Uncaught TypeError: Cannot read property 'localX' of undefined`. All InputPlugin process handlers now check to see if the Game Object has been destroyed at any stage and abort if it has. Fix #4463
  • Loading branch information
photonstorm committed Apr 24, 2019
1 parent a47019b commit 00dbf8b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ Notes:
* Keys would lose track of the state of a Scene when the Scene became paused. They're now updated regardless, stopping them from getting stuck if you pause and resume a Scene while holding them down. Fix #3822 (thanks @DannyT)
* Changing any aspect of a Text object, such as the font size or content, wouldn't update its `hitArea` if it had been enabled for input, causing it to carry on using the old hit area size. Now, as long as the Text was created _without_ a custom hitArea, the hitArea size will be changed to match the new texture size on update. If you have provided your own custom hitArea shape, you need to modify it when the Text changes size yourself. Fix #4456 (thanks @thanh-taro and @rexrainbow)
* `Camera.clearRenderToTexture` will check to see if the Scene is available before proceeding, avoiding potential errors when a Camera is destroyed multiple times during a Scene shutdown.
* Destroying a Game object during its `pointerup` event handler on a touch device will no longer cause `Uncaught TypeError: Cannot read property 'localX' of undefined`. All InputPlugin process handlers now check to see if the Game Object has been destroyed at any stage and abort if it has. Fix #4463 (thanks @PatrickSachs)

### Examples, Documentation and TypeScript

Expand Down
81 changes: 48 additions & 33 deletions src/input/InputPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,15 +878,15 @@ var InputPlugin = new Class({

gameObject.emit(Events.GAMEOBJECT_POINTER_DOWN, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
}

this.emit(Events.GAMEOBJECT_DOWN, pointer, gameObject, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
Expand Down Expand Up @@ -1109,6 +1109,8 @@ var InputPlugin = new Class({
return list.length;
}

var target;

// 4 = Pointer actively dragging the draglist and has moved
if (this.getDragState(pointer) === 4 && pointer.justMoved && !pointer.justUp)
{
Expand All @@ -1122,48 +1124,54 @@ var InputPlugin = new Class({

input = gameObject.input;

target = input.target;

// If this GO has a target then let's check it
if (input.target)
if (target)
{
var index = dropZones.indexOf(input.target);
var index = dropZones.indexOf(target);

// Got a target, are we still over it?
if (index === 0)
{
// We're still over it, and it's still the top of the display list, phew ...
gameObject.emit(Events.GAMEOBJECT_DRAG_OVER, pointer, input.target);
gameObject.emit(Events.GAMEOBJECT_DRAG_OVER, pointer, target);

this.emit(Events.DRAG_OVER, pointer, gameObject, input.target);
this.emit(Events.DRAG_OVER, pointer, gameObject, target);
}
else if (index > 0)
{
// Still over it but it's no longer top of the display list (targets must always be at the top)
gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, input.target);
gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, target);

this.emit(Events.DRAG_LEAVE, pointer, gameObject, input.target);
this.emit(Events.DRAG_LEAVE, pointer, gameObject, target);

input.target = dropZones[0];

gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, input.target);
target = input.target;

this.emit(Events.DRAG_ENTER, pointer, gameObject, input.target);
gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target);

this.emit(Events.DRAG_ENTER, pointer, gameObject, target);
}
else
{
// Nope, we've moved on (or the target has!), leave the old target
gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, input.target);
gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, target);

this.emit(Events.DRAG_LEAVE, pointer, gameObject, input.target);
this.emit(Events.DRAG_LEAVE, pointer, gameObject, target);

// Anything new to replace it?
// Yup!
if (dropZones[0])
{
input.target = dropZones[0];

gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, input.target);
target = input.target;

gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target);

this.emit(Events.DRAG_ENTER, pointer, gameObject, input.target);
this.emit(Events.DRAG_ENTER, pointer, gameObject, target);
}
else
{
Expand All @@ -1172,13 +1180,15 @@ var InputPlugin = new Class({
}
}
}
else if (!input.target && dropZones[0])
else if (!target && dropZones[0])
{
input.target = dropZones[0];

gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, input.target);
target = input.target;

this.emit(Events.DRAG_ENTER, pointer, gameObject, input.target);
gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target);

this.emit(Events.DRAG_ENTER, pointer, gameObject, target);
}

var dragX = pointer.x - gameObject.input.dragX;
Expand All @@ -1203,7 +1213,7 @@ var InputPlugin = new Class({

input = gameObject.input;

if (input.dragState === 2)
if (input && input.dragState === 2)
{
input.dragState = 0;

Expand All @@ -1212,11 +1222,13 @@ var InputPlugin = new Class({

var dropped = false;

if (input.target)
target = input.target;

if (target)
{
gameObject.emit(Events.GAMEOBJECT_DROP, pointer, input.target);
gameObject.emit(Events.GAMEOBJECT_DROP, pointer, target);

this.emit(Events.DROP, pointer, gameObject, input.target);
this.emit(Events.DROP, pointer, gameObject, target);

input.target = null;

Expand All @@ -1225,9 +1237,12 @@ var InputPlugin = new Class({

// And finally the dragend event

gameObject.emit(Events.GAMEOBJECT_DRAG_END, pointer, input.dragX, input.dragY, dropped);
if (gameObject.input)
{
gameObject.emit(Events.GAMEOBJECT_DRAG_END, pointer, input.dragX, input.dragY, dropped);

this.emit(Events.DRAG_END, pointer, gameObject, dropped);
this.emit(Events.DRAG_END, pointer, gameObject, dropped);
}
}
}

Expand Down Expand Up @@ -1279,15 +1294,15 @@ var InputPlugin = new Class({

gameObject.emit(Events.GAMEOBJECT_POINTER_MOVE, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
}

this.emit(Events.GAMEOBJECT_MOVE, pointer, gameObject, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
Expand Down Expand Up @@ -1405,15 +1420,15 @@ var InputPlugin = new Class({

totalInteracted++;

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
}

this.emit(Events.GAMEOBJECT_OUT, pointer, gameObject, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
Expand Down Expand Up @@ -1453,15 +1468,15 @@ var InputPlugin = new Class({

totalInteracted++;

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
}

this.emit(Events.GAMEOBJECT_OVER, pointer, gameObject, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
Expand Down Expand Up @@ -1521,23 +1536,23 @@ var InputPlugin = new Class({

gameObject.emit(Events.GAMEOBJECT_POINTER_UP, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);

// Clear over and emit 'pointerout' on touch.
if (pointer.wasTouch)
// Clear over and emit 'pointerout' on touch.
if (pointer.wasTouch && gameObject.input)
{
this._over[pointer.id] = [];

gameObject.emit(Events.GAMEOBJECT_POINTER_OUT, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);
}

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
}

this.emit(Events.GAMEOBJECT_UP, pointer, gameObject, _eventContainer);

if (_eventData.cancelled)
if (_eventData.cancelled || !gameObject.input)
{
aborted = true;
break;
Expand Down

0 comments on commit 00dbf8b

Please sign in to comment.