Correct infinity comparisons and toNumber

This commit is contained in:
Valerie R Young 2018-11-13 13:00:20 -05:00
parent 1b44841034
commit 43c5d5c053

View file

@ -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;
}
/**