mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-11 10:39:56 -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) {
|
static toNumber (value) {
|
||||||
// If value is already a number we don't need to coerce it with
|
// If value is already a number we don't need to coerce it with
|
||||||
// Number().
|
// Number().
|
||||||
|
|
||||||
if (typeof value === 'number') {
|
if (typeof value === 'number') {
|
||||||
// Scratch treats NaN as 0, when needed as a number.
|
// Scratch treats NaN as 0, when needed as a number.
|
||||||
// E.g., 0 + NaN -> 0.
|
// E.g., 0 + NaN -> 0.
|
||||||
|
@ -38,8 +39,14 @@ class Cast {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
let n;
|
||||||
const n = Number(value);
|
if (Cast.isInfinity(value)) {
|
||||||
|
n = Infinity;
|
||||||
|
} else if (Cast.isNegativeInfinity(value)) {
|
||||||
|
n = -Infinity;
|
||||||
|
} else {
|
||||||
|
n = Number(value);
|
||||||
|
}
|
||||||
if (_NumberIsNaN(n)) {
|
if (_NumberIsNaN(n)) {
|
||||||
// Scratch treats NaN as 0, when needed as a number.
|
// Scratch treats NaN as 0, when needed as a number.
|
||||||
// E.g., 0 + NaN -> 0.
|
// E.g., 0 + NaN -> 0.
|
||||||
|
@ -117,6 +124,24 @@ class Cast {
|
||||||
return val === null || (typeof val === 'string' && val.trim().length === 0);
|
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.
|
* Compare two values, using Scratch cast, case-insensitive string compare, etc.
|
||||||
* In Scratch 2.0, this is captured by `interp.compare.`
|
* 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.
|
* @returns {number} Negative number if v1 < v2; 0 if equal; positive otherwise.
|
||||||
*/
|
*/
|
||||||
static compare (v1, v2) {
|
static compare (v1, v2) {
|
||||||
let n1 = Number(v1);
|
// If Cast.toNumber returns '0', then the value might be NaN. If the value is NaN,
|
||||||
let n2 = Number(v2);
|
// 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)) {
|
if (n1 === 0 && Cast.isWhiteSpace(v1)) {
|
||||||
n1 = NaN;
|
n1 = NaN;
|
||||||
} else if (n2 === 0 && Cast.isWhiteSpace(v2)) {
|
} else if (n2 === 0 && Cast.isWhiteSpace(v2)) {
|
||||||
|
@ -145,8 +172,16 @@ class Cast {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Compare as numbers.
|
// 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