Skip to content

Conversation

@aomsir
Copy link

@aomsir aomsir commented Oct 29, 2025

Description

Fixes a crash in TweenBuilder when the targets array contains null or undefined elements.

Problem

When creating a tween with destroyed game objects or explicitly passing null/undefined in the targets array, TweenBuilder throws:

TypeError: Cannot read properties of null (reading 'hasOwnProperty')
at TweenBuilder (src/tweens/builders/TweenBuilder.js:159:58)

This happens because the code directly accesses targets[targetIndex].hasOwnProperty() without checking if the target exists.


Root Cause

This bug was introduced in commit faec522e1 (Aug 19, 2022) when the special-case handling for the scale shortcut was added.

Before (3.55.2 and earlier):

  • No hasOwnProperty check on targets
  • Null targets were passed to TweenData but didn't cause crashes

After (3.60.0+):

  • Added check: if (key === 'scale' && !targets[targetIndex].hasOwnProperty('scale'))
  • This line crashes if targets[targetIndex] is null/undefined
  • Bug exists in all versions from 3.60.0 to 3.90.0

The fix adds a null check before the hasOwnProperty call, preventing the crash while maintaining the scale shortcut feature.


Reproduction

// Case 1: Destroyed sprite
const sprite = scene.add.sprite(100, 100, 'key');
sprite.destroy();

scene.tweens.add({
    targets: sprite,
    scale: { from: 1, to: 0.95 },
    duration: 100
});
// → TypeError

// Case 2: Null in array
scene.tweens.add({
    targets: [sprite1, null, sprite2],
    scale: { from: 1, to: 0.95 },
    duration: 100
});
// → TypeError

Solution

Added a null check in the target iteration loop:

1. Cache targets[targetIndex] in a target variable
2. Skip null/undefined targets with continue
3. Use the cached target variable in subsequent checks

This allows tweens to gracefully skip invalid targets instead of crashing.

Changes

for (var targetIndex = 0; targetIndex < targets.length; targetIndex++)
{
+   var target = targets[targetIndex];
+
+   //  Skip null or undefined targets
+   if (!target)
+   {
+       continue;
+   }
+
    //  Special-case for scale short-cut:
-   if (key === 'scale' && !targets[targetIndex].hasOwnProperty('scale'))
+   if (key === 'scale' && !target.hasOwnProperty('scale'))
    {
        addTarget(tween, targetIndex, 'scaleX', value);
        addTarget(tween, targetIndex, 'scaleY', value);
    }

Testing

Tested with the following scenarios:

  • ✅ Normal case with valid targets (works as before)
  • ✅ Null in targets array (now skips gracefully)
  • ✅ Undefined in targets array (now skips gracefully)
  • ✅ Multiple nulls (now skips gracefully)
  • ✅ Destroyed game objects (now skips gracefully)

Impact

  • No breaking changes: Existing code continues to work exactly as before
  • Backward compatible: Valid targets are processed the same way
  • Defensive programming: Invalid targets are now handled gracefully instead of crashing

Checklist

  • Bug fix (non-breaking change that fixes an issue)
  • My code follows the style of this project
  • Self-reviewed my code
  • Tested with multiple scenarios
  • No new warnings introduced

- Add null check in the target loop to skip null or undefined targets
- Prevents 'Cannot read properties of null' TypeError
- Fixes crash when targets are destroyed before tween creation
- Cache target in variable for cleaner code
@aomsir aomsir changed the title Fix: TweenBuilder crashes when targets array contains null fix(tweens): TweenBuilder crashes when targets array contains null Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant