Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Number.prototype.toExponential polyfill #995

Merged
merged 6 commits into from
Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Changelog
##### Unreleased
- Added `Number.prototype.toExponential` method polyfill with many different fixes for the most engines
- [`Array` grouping proposal](https://github.com/tc39/proposal-array-grouping):
- Moved to the stage 2
- Added `Array.prototype.groupByMap` method
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -895,10 +895,11 @@ Module [`es.number.constructor`](https://github.com/zloirock/core-js/blob/master
Number('0b1010101'); // => 85
Number('0o7654321'); // => 2054353
```
Modules [`es.number.epsilon`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.epsilon.js), [`es.number.is-finite`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-finite.js), [`es.number.is-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-integer.js), [`es.number.is-nan`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-nan.js), [`es.number.is-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-safe-integer.js), [`es.number.max-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.max-safe-integer.js), [`es.number.min-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.min-safe-integer.js), [`es.number.parse-float`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.parse-float.js), [`es.number.parse-int`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.parse-int.js), [`es.number.to-fixed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.to-fixed.js), [`es.number.to-precision`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.to-precision.js), [`es.parse-int`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.parse-int.js), [`es.parse-float`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.parse-float.js).
Modules [`es.number.epsilon`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.epsilon.js), [`es.number.is-finite`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-finite.js), [`es.number.is-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-integer.js), [`es.number.is-nan`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-nan.js), [`es.number.is-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.is-safe-integer.js), [`es.number.max-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.max-safe-integer.js), [`es.number.min-safe-integer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.min-safe-integer.js), [`es.number.parse-float`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.parse-float.js), [`es.number.parse-int`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.parse-int.js), [`es.number.to-exponential`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.to-exponential.js), [`es.number.to-fixed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.to-fixed.js), [`es.number.to-precision`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.number.to-precision.js), [`es.parse-int`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.parse-int.js), [`es.parse-float`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.parse-float.js).
```js
class Number {
constructor(value: any): number;
toExponential(digits: number): string;
toFixed(digits: number): string;
toPrecision(precision: number): string;
static isFinite(number: any): boolean;
Expand Down Expand Up @@ -928,6 +929,7 @@ core-js(-pure)/es|stable|features/number/parse-int
core-js(-pure)/es|stable|features/number/epsilon
core-js(-pure)/es|stable|features/number/max-safe-integer
core-js(-pure)/es|stable|features/number/min-safe-integer
core-js(-pure)/es|stable|features/number/to-exponential
core-js(-pure)/es|stable|features/number/to-fixed
core-js(-pure)/es|stable|features/number/to-precision
core-js(-pure)/es|stable|features/parse-float
Expand Down
6 changes: 6 additions & 0 deletions packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,12 @@ export const data = {
firefox: '39',
safari: '9.0',
},
'es.number.to-exponential': {
chrome: '26',
edge: '18',
firefox: '50',
safari: '11',
},
'es.number.to-fixed': {
chrome: '26',
firefox: '4',
Expand Down
1 change: 1 addition & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export default {
'esnext.typed-array.from-async',
],
'3.20': [
'es.number.to-exponential',
'esnext.array.group-by-map',
'esnext.array.to-reversed',
'esnext.array.to-sorted',
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/es/number/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require('../../modules/es.number.max-safe-integer');
require('../../modules/es.number.min-safe-integer');
require('../../modules/es.number.parse-float');
require('../../modules/es.number.parse-int');
require('../../modules/es.number.to-exponential');
require('../../modules/es.number.to-fixed');
require('../../modules/es.number.to-precision');
var path = require('../../internals/path');
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/es/number/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../modules/es.number.to-exponential');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Number', 'toExponential');
1 change: 1 addition & 0 deletions packages/core-js/es/number/virtual/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('../../../modules/es.number.to-exponential');
require('../../../modules/es.number.to-fixed');
require('../../../modules/es.number.to-precision');
var entryVirtual = require('../../../internals/entry-virtual');
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/es/number/virtual/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../../modules/es.number.to-exponential');
var entryVirtual = require('../../../internals/entry-virtual');

module.exports = entryVirtual('Number').toExponential;
3 changes: 3 additions & 0 deletions packages/core-js/features/number/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var parent = require('../../stable/number/to-exponential');

module.exports = parent;
3 changes: 3 additions & 0 deletions packages/core-js/features/number/virtual/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var parent = require('../../../stable/number/virtual/to-exponential');

module.exports = parent;
7 changes: 7 additions & 0 deletions packages/core-js/internals/math-log10.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var log = Math.log;
var LOG10E = Math.LOG10E;

// eslint-disable-next-line es/no-math-log10 -- safe
module.exports = Math.log10 || function log10(x) {
return log(x) * LOG10E;
};
8 changes: 2 additions & 6 deletions packages/core-js/modules/es.math.log10.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
var $ = require('../internals/export');

var log = Math.log;
var LOG10E = Math.LOG10E;
var log10 = require('../internals/math-log10');

// `Math.log10` method
// https://tc39.es/ecma262/#sec-math.log10
$({ target: 'Math', stat: true }, {
log10: function log10(x) {
return log(x) * LOG10E;
}
log10: log10
});
98 changes: 98 additions & 0 deletions packages/core-js/modules/es.number.to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use strict';
var $ = require('../internals/export');
var global = require('../internals/global');
var uncurryThis = require('../internals/function-uncurry-this');
var toIntegerOrInfinity = require('../internals/to-integer-or-infinity');
var thisNumberValue = require('../internals/this-number-value');
var $repeat = require('../internals/string-repeat');
var log10 = require('../internals/math-log10');
var fails = require('../internals/fails');

var RangeError = global.RangeError;
var String = global.String;
var isFinite = global.isFinite;
var abs = Math.abs;
var floor = Math.floor;
var pow = Math.pow;
var round = Math.round;
var un$ToExponential = uncurryThis(1.0.toExponential);
var repeat = uncurryThis($repeat);
var stringSlice = uncurryThis(''.slice);

// Edge 17-
var ROUNDS_PROPERLY = un$ToExponential(-6.9e-11, 4) === '-6.9000e-11'
// IE11- && Edge 14-
&& un$ToExponential(1.255, 2) === '1.25e+0';
// FF86-, enable after increasing maximum number of fraction digits in the implementation to 100
// && nativeToExponential.call(25, 0) === '3e+1';

// IE8-
var THROWS_ON_INFINITY_FRACTION = fails(function () {
un$ToExponential(1, Infinity);
}) && fails(function () {
un$ToExponential(1, -Infinity);
});

// Safari <11 && FF <50
var PROPER_NON_FINITE_THIS_CHECK = !fails(function () {
un$ToExponential(Infinity, Infinity);
}) && !fails(function () {
un$ToExponential(NaN, Infinity);
});

var FORCED = !ROUNDS_PROPERLY || !THROWS_ON_INFINITY_FRACTION || !PROPER_NON_FINITE_THIS_CHECK;

// `Number.prototype.toExponential` method
// https://tc39.es/ecma262/#sec-number.prototype.toexponential
$({ target: 'Number', proto: true, forced: FORCED }, {
toExponential: function toExponential(fractionDigits) {
var x = thisNumberValue(this);
if (fractionDigits === undefined) return un$ToExponential(x);
var f = toIntegerOrInfinity(fractionDigits);
if (!isFinite(x)) return String(x);
// TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation
if (f < 0 || f > 20) throw RangeError('Incorrect fraction digits');
if (ROUNDS_PROPERLY) return un$ToExponential(x, f);
var s = '';
var m = '';
var e = 0;
var c = '';
var d = '';
if (x < 0) {
s = '-';
x = -x;
}
if (x === 0) {
e = 0;
m = repeat('0', f + 1);
} else {
// this block is based on https://gist.github.com/SheetJSDev/1100ad56b9f856c95299ed0e068eea08
// TODO: improve accuracy with big fraction digits
var l = log10(x);
e = floor(l);
var n = 0;
var w = pow(10, e - f);
n = round(x / w);
if (2 * x >= (2 * n + 1) * w) {
n += 1;
}
if (n >= pow(10, f + 1)) {
n /= 10;
e += 1;
}
m = String(n);
}
if (f !== 0) {
m = stringSlice(m, 0, 1) + '.' + stringSlice(m, 1);
}
if (e === 0) {
c = '+';
d = '0';
} else {
c = e > 0 ? '+' : '-';
d = String(abs(e));
}
m += 'e' + c + d;
return s + m;
}
});
1 change: 1 addition & 0 deletions packages/core-js/modules/es.number.to-fixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ $({ target: 'Number', proto: true, forced: FORCED }, {
var result = '0';
var e, z, j, k;

// TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation
if (fractDigits < 0 || fractDigits > 20) throw RangeError('Incorrect fraction digits');
// eslint-disable-next-line no-self-compare -- NaN check
if (number != number) return 'NaN';
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js/stable/number/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var parent = require('../../es/number/to-exponential');

module.exports = parent;
3 changes: 3 additions & 0 deletions packages/core-js/stable/number/virtual/to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var parent = require('../../../es/number/virtual/to-exponential');

module.exports = parent;
2 changes: 2 additions & 0 deletions tests/commonjs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,12 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(load(NS, 'number/min-safe-integer') === -0x1FFFFFFFFFFFFF);
ok(load(NS, 'number/parse-float')('1.5') === 1.5);
ok(load(NS, 'number/parse-int')('2.1') === 2);
ok(load(NS, 'number/to-exponential')(1, 1) === '1.0e+0');
ok(load(NS, 'number/to-fixed')(1, 1) === '1.0');
ok(load(NS, 'number/to-precision')(1) === '1');
ok(load(NS, 'parse-float')('1.5') === 1.5);
ok(load(NS, 'parse-int')('2.1') === 2);
ok(load(NS, 'number/virtual/to-exponential').call(1, 1) === '1.0e+0');
ok(load(NS, 'number/virtual/to-fixed').call(1, 1) === '1.0');
ok(load(NS, 'number/virtual/to-precision').call(1) === '1');
ok('toPrecision' in load(NS, 'number/virtual'));
Expand Down
15 changes: 15 additions & 0 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,21 @@ GLOBAL.tests = {
&& parseInt(WHITESPACES + '0x16') === 22;
}
},
'es.number.to-exponential': function () {
try {
1.0.toExponential(Infinity);
} catch (error) {
try {
1.0.toExponential(-Infinity);
} catch (error2) {
Infinity.toExponential(Infinity);
NaN.toExponential(Infinity);
return (-6.9e-11).toExponential(4) === '-6.9000e-11'
&& 1.255.toExponential(2) === '1.25e+0';
// && 25.0.toExponential(0) === '3e+1';
}
}
},
'es.number.to-fixed': function () {
try {
Number.prototype.toFixed.call({});
Expand Down
135 changes: 135 additions & 0 deletions tests/pure/es.number.to-exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import toExponential from 'core-js-pure/features/number/virtual/to-exponential';

QUnit.test('Number#toExponential', assert => {
assert.isFunction(toExponential);

assert.same(toExponential.call(0.00008, 3), '8.000e-5');
assert.same(toExponential.call(0.9, 0), '9e-1');
assert.same(toExponential.call(1.255, 2), '1.25e+0');
assert.same(toExponential.call(1843654265.0774949, 5), '1.84365e+9');
assert.same(toExponential.call(1000000000000000128.0, 0), '1e+18');

assert.same(toExponential.call(1), '1e+0');
assert.same(toExponential.call(1, 0), '1e+0');
assert.same(toExponential.call(1, 1), '1.0e+0');
assert.same(toExponential.call(1, 1.1), '1.0e+0');
assert.same(toExponential.call(1, 0.9), '1e+0');
assert.same(toExponential.call(1, '0'), '1e+0');
assert.same(toExponential.call(1, '1'), '1.0e+0');
assert.same(toExponential.call(1, '1.1'), '1.0e+0');
assert.same(toExponential.call(1, '0.9'), '1e+0');
assert.same(toExponential.call(1, NaN), '1e+0');
assert.same(toExponential.call(1, 'some string'), '1e+0');
assert.notThrows(() => toExponential.call(1, -0.1) === '1e+0');
assert.same(toExponential.call(new Number(1)), '1e+0');
assert.same(toExponential.call(new Number(1), 0), '1e+0');
assert.same(toExponential.call(new Number(1), 1), '1.0e+0');
assert.same(toExponential.call(new Number(1), 1.1), '1.0e+0');
assert.same(toExponential.call(new Number(1), 0.9), '1e+0');
assert.same(toExponential.call(new Number(1), '0'), '1e+0');
assert.same(toExponential.call(new Number(1), '1'), '1.0e+0');
assert.same(toExponential.call(new Number(1), '1.1'), '1.0e+0');
assert.same(toExponential.call(new Number(1), '0.9'), '1e+0');
assert.same(toExponential.call(new Number(1), NaN), '1e+0');
assert.same(toExponential.call(new Number(1), 'some string'), '1e+0');
assert.notThrows(() => toExponential.call(new Number(1), -0.1) === '1e+0');
assert.same(toExponential.call(NaN), 'NaN');
assert.same(toExponential.call(NaN, 0), 'NaN');
assert.same(toExponential.call(NaN, 1), 'NaN');
assert.same(toExponential.call(NaN, 1.1), 'NaN');
assert.same(toExponential.call(NaN, 0.9), 'NaN');
assert.same(toExponential.call(NaN, '0'), 'NaN');
assert.same(toExponential.call(NaN, '1'), 'NaN');
assert.same(toExponential.call(NaN, '1.1'), 'NaN');
assert.same(toExponential.call(NaN, '0.9'), 'NaN');
assert.same(toExponential.call(NaN, NaN), 'NaN');
assert.same(toExponential.call(NaN, 'some string'), 'NaN');
assert.notThrows(() => toExponential.call(NaN, -0.1) === 'NaN');

assert.same(toExponential.call(new Number(1e21)), '1e+21');
assert.same(toExponential.call(new Number(1e21), 0), '1e+21');
assert.same(toExponential.call(new Number(1e21), 1), '1.0e+21');
assert.same(toExponential.call(new Number(1e21), 1.1), '1.0e+21');
assert.same(toExponential.call(new Number(1e21), 0.9), '1e+21');
assert.same(toExponential.call(new Number(1e21), '0'), '1e+21');
assert.same(toExponential.call(new Number(1e21), '1'), '1.0e+21');
assert.same(toExponential.call(new Number(1e21), '1.1'), '1.0e+21');
assert.same(toExponential.call(new Number(1e21), '0.9'), '1e+21');
assert.same(toExponential.call(new Number(1e21), NaN), '1e+21');
assert.same(toExponential.call(new Number(1e21), 'some string'), '1e+21');

assert.same(toExponential.call(5, 19), '5.0000000000000000000e+0');

// ported from tests262, the license: https://github.com/tc39/test262/blob/main/LICENSE
assert.same(toExponential.call(123.456, 0), '1e+2');
assert.same(toExponential.call(123.456, 1), '1.2e+2');
assert.same(toExponential.call(123.456, 2), '1.23e+2');
assert.same(toExponential.call(123.456, 3), '1.235e+2');
assert.same(toExponential.call(123.456, 4), '1.2346e+2');
assert.same(toExponential.call(123.456, 5), '1.23456e+2');
assert.same(toExponential.call(123.456, 6), '1.234560e+2');
assert.same(toExponential.call(123.456, 7), '1.2345600e+2');
// assert.same(toExponential.call(123.456, 17), '1.23456000000000003e+2');
// assert.same(toExponential.call(123.456, 20), '1.23456000000000003070e+2');

assert.same(toExponential.call(-123.456, 0), '-1e+2');
assert.same(toExponential.call(-123.456, 1), '-1.2e+2');
assert.same(toExponential.call(-123.456, 2), '-1.23e+2');
assert.same(toExponential.call(-123.456, 3), '-1.235e+2');
assert.same(toExponential.call(-123.456, 4), '-1.2346e+2');
assert.same(toExponential.call(-123.456, 5), '-1.23456e+2');
assert.same(toExponential.call(-123.456, 6), '-1.234560e+2');
assert.same(toExponential.call(-123.456, 7), '-1.2345600e+2');
// assert.same(toExponential.call(-123.456, 17), '-1.23456000000000003e+2');
// assert.same(toExponential.call(-123.456, 20), '-1.23456000000000003070e+2');

assert.same(toExponential.call(0.0001, 0), '1e-4');
assert.same(toExponential.call(0.0001, 1), '1.0e-4');
assert.same(toExponential.call(0.0001, 2), '1.00e-4');
assert.same(toExponential.call(0.0001, 3), '1.000e-4');
assert.same(toExponential.call(0.0001, 4), '1.0000e-4');
// assert.same(toExponential.call(0.0001, 16), '1.0000000000000000e-4');
// assert.same(toExponential.call(0.0001, 17), '1.00000000000000005e-4');
// assert.same(toExponential.call(0.0001, 18), '1.000000000000000048e-4');
// assert.same(toExponential.call(0.0001, 19), '1.0000000000000000479e-4');
// assert.same(toExponential.call(0.0001, 20), '1.00000000000000004792e-4');

assert.same(toExponential.call(0.9999, 0), '1e+0');
assert.same(toExponential.call(0.9999, 1), '1.0e+0');
assert.same(toExponential.call(0.9999, 2), '1.00e+0');
assert.same(toExponential.call(0.9999, 3), '9.999e-1');
assert.same(toExponential.call(0.9999, 4), '9.9990e-1');
// assert.same(toExponential.call(0.9999, 16), '9.9990000000000001e-1');
// assert.same(toExponential.call(0.9999, 17), '9.99900000000000011e-1');
// assert.same(toExponential.call(0.9999, 18), '9.999000000000000110e-1');
// assert.same(toExponential.call(0.9999, 19), '9.9990000000000001101e-1');
// assert.same(toExponential.call(0.9999, 20), '9.99900000000000011013e-1');

assert.same(toExponential.call(25, 0), '3e+1');
assert.same(toExponential.call(12345, 3), '1.235e+4');

assert.same(toExponential.call(Number.prototype, 0), '0e+0', 'Number.prototype, 0');
assert.same(toExponential.call(0, 0), '0e+0', '0, 0');
assert.same(toExponential.call(-0, 0), '0e+0', '-0, 0');
assert.same(toExponential.call(0, -0), '0e+0', '0, -0');
assert.same(toExponential.call(-0, -0), '0e+0', '-0, -0');
assert.same(toExponential.call(0, 1), '0.0e+0', '0 and 1');
assert.same(toExponential.call(0, 2), '0.00e+0', '0 and 2');
assert.same(toExponential.call(0, 7), '0.0000000e+0', '0 and 7');
assert.same(toExponential.call(0, 20), '0.00000000000000000000e+0', '0 and 20');
assert.same(toExponential.call(-0, 1), '0.0e+0', '-0 and 1');
assert.same(toExponential.call(-0, 2), '0.00e+0', '-0 and 2');
assert.same(toExponential.call(-0, 7), '0.0000000e+0', '-0 and 7');
assert.same(toExponential.call(-0, 20), '0.00000000000000000000e+0', '-0 and 20');

assert.same(toExponential.call(NaN, 1000), 'NaN', 'NaN check before fractionDigits check');
assert.same(toExponential.call(Infinity, 1000), 'Infinity', 'Infinity check before fractionDigits check');
assert.notThrows(() => toExponential.call(new Number(1e21), -0.1) === '1e+21');
assert.throws(() => toExponential.call(1.0, -101), RangeError, 'If f < 0 or f > 20 (100), throw a RangeError exception.');
assert.throws(() => toExponential.call(1.0, 101), RangeError, 'If f < 0 or f > 20 (100), throw a RangeError exception.');
assert.throws(() => toExponential.call({}, 1), TypeError, '? thisNumberValue(this value)');
assert.throws(() => toExponential.call('123', 1), TypeError, '? thisNumberValue(this value)');
assert.throws(() => toExponential.call(false, 1), TypeError, '? thisNumberValue(this value)');
assert.throws(() => toExponential.call(null, 1), TypeError, '? thisNumberValue(this value)');
assert.throws(() => toExponential.call(undefined, 1), TypeError, '? thisNumberValue(this value)');
});