Skip to content

Commit f7b095e

Browse files
committed
fix handling of fractional number part and some special cases in Number.fromString
1 parent 79ea4a7 commit f7b095e

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- Simplified `structuredClone` polyfill, avoided second tree pass in cases of transferring
44
- Added support of `SuppressedError` to `structuredClone` polyfill
55
- Removed unspecified unnecessary `ArrayBuffer` and `DataView` dependencies of `structuredClone` lack of which could cause errors in some entries in IE10-
6+
- Fixed handling of fractional number part and some special cases in [`Number.fromString`](https://github.com/tc39/proposal-number-fromstring)
67
- Compat data improvements:
78
- Updated Opera Android 78 compat data mapping
89

packages/core-js/modules/esnext.number.from-string.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,35 @@ var INVALID_RADIX = 'Invalid radix';
99
var $RangeError = RangeError;
1010
var $SyntaxError = SyntaxError;
1111
var $TypeError = TypeError;
12-
var valid = /^[\da-z]+$/;
12+
var pow = Math.pow;
13+
var valid = /^[\d.a-z]+$/;
1314
var charAt = uncurryThis(''.charAt);
1415
var exec = uncurryThis(valid.exec);
1516
var numberToString = uncurryThis(1.0.toString);
1617
var stringSlice = uncurryThis(''.slice);
18+
var split = uncurryThis(''.split);
1719

1820
// `Number.fromString` method
1921
// https://github.com/tc39/proposal-number-fromstring
2022
$({ target: 'Number', stat: true, forced: true }, {
2123
fromString: function fromString(string, radix) {
2224
var sign = 1;
23-
var R, mathNum;
2425
if (typeof string != 'string') throw new $TypeError(INVALID_NUMBER_REPRESENTATION);
2526
if (!string.length) throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
27+
if (string === 'NaN') return NaN;
2628
if (charAt(string, 0) === '-') {
2729
sign = -1;
2830
string = stringSlice(string, 1);
29-
if (!string.length) throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
31+
if (!string.length || string === '0') throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
3032
}
31-
R = radix === undefined ? 10 : toIntegerOrInfinity(radix);
33+
if (string === 'Infinity') return sign * Infinity;
34+
var R = radix === undefined ? 10 : toIntegerOrInfinity(radix);
3235
if (R < 2 || R > 36) throw new $RangeError(INVALID_RADIX);
33-
if (!exec(valid, string) || numberToString(mathNum = parseInt(string, R), R) !== string) {
34-
throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
35-
}
36+
if (!exec(valid, string)) throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
37+
var parts = split(string, '.');
38+
var mathNum = parseInt(parts[0], R);
39+
if (parts.length > 1) mathNum += parseInt(parts[1], R) / pow(R, parts[1].length);
40+
if (numberToString(mathNum, R) !== string) throw new $SyntaxError(INVALID_NUMBER_REPRESENTATION);
3641
return sign * mathNum;
3742
}
3843
});

tests/unit-global/esnext.number.from-string.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,26 @@ QUnit.test('Number.fromString', assert => {
1616
assert.same(fromString('10', radix), radix, `Radix ${ radix }`);
1717
}
1818
assert.throws(() => fromString('10', -4294967294), RangeError, 'Radix uses ToInteger #1');
19+
20+
assert.same(fromString('NaN'), NaN);
21+
assert.same(fromString('NaN', 2), NaN);
22+
assert.same(fromString('Infinity'), Infinity);
23+
assert.same(fromString('Infinity', 2), Infinity);
24+
assert.same(fromString('-Infinity'), -Infinity);
25+
assert.same(fromString('-Infinity', 2), -Infinity);
26+
1927
assert.same(fromString('10', 2.5), 2, 'Radix uses ToInteger #2');
2028
assert.same(fromString('42'), 42);
2129
assert.same(fromString('42', 10), 42);
30+
assert.same(fromString('3.14159', 10), 3.14159);
31+
assert.same(fromString('-100.11', 2), -4.75);
32+
assert.same(fromString('202.1', 3), 20.333333333333332);
33+
34+
assert.same(fromString('0'), 0);
35+
assert.same(fromString('0', 2), 0);
36+
assert.throws(() => fromString('-0'), SyntaxError);
37+
assert.throws(() => fromString('-0', 2), SyntaxError);
38+
2239
assert.throws(() => fromString('0xc0ffee'), SyntaxError);
2340
assert.throws(() => fromString('0o755'), SyntaxError);
2441
assert.throws(() => fromString('0b00101010'), SyntaxError);

tests/unit-pure/esnext.number.from-string.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,26 @@ QUnit.test('Number.fromString', assert => {
1515
assert.same(fromString('10', radix), radix, `Radix ${ radix }`);
1616
}
1717
assert.throws(() => fromString('10', -4294967294), RangeError, 'Radix uses ToInteger #1');
18+
19+
assert.same(fromString('NaN'), NaN);
20+
assert.same(fromString('NaN', 2), NaN);
21+
assert.same(fromString('Infinity'), Infinity);
22+
assert.same(fromString('Infinity', 2), Infinity);
23+
assert.same(fromString('-Infinity'), -Infinity);
24+
assert.same(fromString('-Infinity', 2), -Infinity);
25+
1826
assert.same(fromString('10', 2.5), 2, 'Radix uses ToInteger #2');
1927
assert.same(fromString('42'), 42);
2028
assert.same(fromString('42', 10), 42);
29+
assert.same(fromString('3.14159', 10), 3.14159);
30+
assert.same(fromString('-100.11', 2), -4.75);
31+
assert.same(fromString('202.1', 3), 20.333333333333332);
32+
33+
assert.same(fromString('0'), 0);
34+
assert.same(fromString('0', 2), 0);
35+
assert.throws(() => fromString('-0'), SyntaxError);
36+
assert.throws(() => fromString('-0', 2), SyntaxError);
37+
2138
assert.throws(() => fromString('0xc0ffee'), SyntaxError);
2239
assert.throws(() => fromString('0o755'), SyntaxError);
2340
assert.throws(() => fromString('0b00101010'), SyntaxError);

0 commit comments

Comments
 (0)