Skip to content

SafeRange bug restricts certain ranges #5979

@ksritharan

Description

@ksritharan

Version

  • Phaser Version: 3.55.2
  • Operating system:
  • Browser:

Description

The condition startIndex + endIndex > len, in SafeRange.js is not necessary, and it restricts valid ranges.

/* src/utils/arrays/SafeRange.js */
var SafeRange = function (array, startIndex, endIndex, throwError)
{
    var len = array.length;

    if (startIndex < 0 ||
        startIndex > len ||
        startIndex >= endIndex ||
        endIndex > len ||
        startIndex + endIndex > len)
    {

The purpose of this function is to validate ranges in the form of [startIndex, endIndex). Where [ includes startIndex and ) excludes endIndex.
The fix will allow the following ranges to be validated:

[n, Array.length), n = {1, ..., Array.length-1}, Array.length > 1
[n, m), n = {1, ..., Array.length - 1}, m = {n+1, ..., Array.length}, Array.length > 1

For example,

var arr = [0, 1, 2, 3, 4];
console.log(Phaser.Utils.Array.SafeRange(arr, 0, arr.length)); // true, since [0, 5) is a valid range for arr that gives [0, 1, 2, 3, 4]
console.log(Phaser.Utils.Array.SafeRange(arr, 1, arr.length)); // false, but should be true since [1, 5) is a valid range for arr that gives [1, 2, 3, 4]
console.log(Phaser.Utils.Array.SafeRange(arr, 2, 4)); // false, but should be true since [2, 4) is a valid range for arr that gives [2, 3]

It restricts the following static methods in Phaser.Utils.Arrays: CountAllMatching, EachInRange, GetAll, GetFirst, RemoveBetween, SetAll.
The proposed fix will allow these methods to be able to operate on the aforementioned ranges.
For example, this code snippet demonstrates the change for GetAll (Phaser.GameObjects.Group::getMatching)
https://jsfiddle.net/z7w96k53/1/

  create() {
    var gameObjects = [];
    for (let i = 0; i < 5; i++) {
      var gameObject = new Phaser.GameObjects.Container(this);
      gameObject.setData('num', i);
      gameObjects.push(gameObject);
    }
    var group = new Phaser.GameObjects.Group(this, gameObjects);
    var newGroup = new NewGroup(this, gameObjects)
    console.log("Before");
    console.log(group.getMatching('active', true, 0).map(element => element.getData('num'))); // [0, 1, 2, 3, 4]
    console.log(group.getMatching('active', true, 1).map(element => element.getData('num'))); // []
    console.log(group.getMatching('active', true, 2, 4).map(element => element.getData('num'))); // []
    console.log("After");
    console.log(newGroup.getMatching('active', true, 0).map(element => element.getData('num')));  // [0, 1, 2, 3, 4]
    console.log(newGroup.getMatching('active', true, 1).map(element => element.getData('num'))); // [1, 2, 3, 4]
    console.log(newGroup.getMatching('active', true, 2, 4).map(element => element.getData('num'))); // [2, 3]
  }

Example Test Code

This snippet contains the unit tests: https://jsfiddle.net/7x5Lpse1/16/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions