mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 06:52:40 -05:00
Correct infinity comparisons and toNumber
This commit is contained in:
parent
1b44841034
commit
43c5d5c053
1 changed files with 41 additions and 6 deletions
|
@ -30,6 +30,7 @@ class Cast {
|
|||
static toNumber (value) {
|
||||
// If value is already a number we don't need to coerce it with
|
||||
// Number().
|
||||
|
||||
if (typeof value === 'number') {
|
||||
// Scratch treats NaN as 0, when needed as a number.
|
||||
// E.g., 0 + NaN -> 0.
|
||||
|
@ -38,8 +39,14 @@ class Cast {
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const n = Number(value);
|
||||
let n;
|
||||
if (Cast.isInfinity(value)) {
|
||||
n = Infinity;
|
||||
} else if (Cast.isNegativeInfinity(value)) {
|
||||
n = -Infinity;
|
||||
} else {
|
||||
n = Number(value);
|
||||
}
|
||||
if (_NumberIsNaN(n)) {
|
||||
// Scratch treats NaN as 0, when needed as a number.
|
||||
// E.g., 0 + NaN -> 0.
|
||||
|
@ -117,6 +124,24 @@ class Cast {
|
|||
return val === null || (typeof val === 'string' && val.trim().length === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a Scratch argument is infinity.
|
||||
* @param {*} val value to check.
|
||||
* @return {boolean} True if the argument is any capitalization of infinity.
|
||||
*/
|
||||
static isInfinity (val) {
|
||||
return val === Infinity || (typeof val === 'string' && val.toLowerCase() === 'infinity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a Scratch argument is negative infinity.
|
||||
* @param {*} val value to check.
|
||||
* @return {boolean} True if the argument is a '-' folled by any capitalization of infinity.
|
||||
*/
|
||||
static isNegativeInfinity (val) {
|
||||
return val === -Infinity || (typeof val === 'string' && val.toLowerCase() === '-infinity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two values, using Scratch cast, case-insensitive string compare, etc.
|
||||
* In Scratch 2.0, this is captured by `interp.compare.`
|
||||
|
@ -125,8 +150,10 @@ class Cast {
|
|||
* @returns {number} Negative number if v1 < v2; 0 if equal; positive otherwise.
|
||||
*/
|
||||
static compare (v1, v2) {
|
||||
let n1 = Number(v1);
|
||||
let n2 = Number(v2);
|
||||
// If Cast.toNumber returns '0', then the value might be NaN. If the value is NaN,
|
||||
// this comparison algorithm needs to know.
|
||||
let n1 = Cast.toNumber(v1) || Number(v1);
|
||||
let n2 = Cast.toNumber(v2) || Number(v2);
|
||||
if (n1 === 0 && Cast.isWhiteSpace(v1)) {
|
||||
n1 = NaN;
|
||||
} else if (n2 === 0 && Cast.isWhiteSpace(v2)) {
|
||||
|
@ -145,8 +172,16 @@ class Cast {
|
|||
return 0;
|
||||
}
|
||||
// Compare as numbers.
|
||||
return n1 - n2;
|
||||
|
||||
const r = n1 - n2;
|
||||
if (isNaN(r)) {
|
||||
if (n1 === Infinity && n2 === Infinity) {
|
||||
return 0;
|
||||
}
|
||||
if (n1 === -Infinity && n2 === -Infinity) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue