From 0a4dcb2412c54d34ae9d6e25958dd4ac9b2d9314 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 7 Mar 2023 22:41:22 -0800 Subject: [PATCH] [Fix] `ES2020`+: `ToBigInt`: properly throw on anything besides string, bigint, boolean --- 2020/ToBigInt.js | 34 +++++++++++++++++++++++++++++++--- 2021/ToBigInt.js | 34 +++++++++++++++++++++++++++++++--- 2022/ToBigInt.js | 34 +++++++++++++++++++++++++++++++--- test/tests.js | 17 +++++++---------- 4 files changed, 100 insertions(+), 19 deletions(-) diff --git a/2020/ToBigInt.js b/2020/ToBigInt.js index aa24d7b7..d24e0fff 100644 --- a/2020/ToBigInt.js +++ b/2020/ToBigInt.js @@ -3,12 +3,15 @@ var GetIntrinsic = require('get-intrinsic'); var $BigInt = GetIntrinsic('%BigInt%', true); -var $asIntN = GetIntrinsic('%BigInt.asIntN%', true); var $Number = GetIntrinsic('%Number%'); +var $TypeError = GetIntrinsic('%TypeError%'); var $SyntaxError = GetIntrinsic('%SyntaxError%'); +var StringToBigInt = require('./StringToBigInt'); var ToPrimitive = require('./ToPrimitive'); +var isNaN = require('../helpers/isNaN'); + // https://262.ecma-international.org/11.0/#sec-tobigint module.exports = function ToBigInt(argument) { @@ -18,8 +21,33 @@ module.exports = function ToBigInt(argument) { var prim = ToPrimitive(argument, $Number); + if (prim == null) { + throw new $TypeError('Cannot convert null or undefined to a BigInt'); + } + + if (typeof prim === 'boolean') { + return prim ? $BigInt(1) : $BigInt(0); + } + if (typeof prim === 'number') { - return $asIntN(0, prim); + throw new $TypeError('Cannot convert a Number value to a BigInt'); + } + + if (typeof prim === 'string') { + var n = StringToBigInt(prim); + if (isNaN(n)) { + throw new $TypeError('Failed to parse String to BigInt'); + } + return n; + } + + if (typeof prim === 'symbol') { + throw new $TypeError('Cannot convert a Symbol value to a BigInt'); } - return $BigInt(prim); + + if (typeof prim !== 'bigint') { + throw new $SyntaxError('Assertion failed: unknown primitive type'); + } + + return prim; }; diff --git a/2021/ToBigInt.js b/2021/ToBigInt.js index aa24d7b7..d24e0fff 100644 --- a/2021/ToBigInt.js +++ b/2021/ToBigInt.js @@ -3,12 +3,15 @@ var GetIntrinsic = require('get-intrinsic'); var $BigInt = GetIntrinsic('%BigInt%', true); -var $asIntN = GetIntrinsic('%BigInt.asIntN%', true); var $Number = GetIntrinsic('%Number%'); +var $TypeError = GetIntrinsic('%TypeError%'); var $SyntaxError = GetIntrinsic('%SyntaxError%'); +var StringToBigInt = require('./StringToBigInt'); var ToPrimitive = require('./ToPrimitive'); +var isNaN = require('../helpers/isNaN'); + // https://262.ecma-international.org/11.0/#sec-tobigint module.exports = function ToBigInt(argument) { @@ -18,8 +21,33 @@ module.exports = function ToBigInt(argument) { var prim = ToPrimitive(argument, $Number); + if (prim == null) { + throw new $TypeError('Cannot convert null or undefined to a BigInt'); + } + + if (typeof prim === 'boolean') { + return prim ? $BigInt(1) : $BigInt(0); + } + if (typeof prim === 'number') { - return $asIntN(0, prim); + throw new $TypeError('Cannot convert a Number value to a BigInt'); + } + + if (typeof prim === 'string') { + var n = StringToBigInt(prim); + if (isNaN(n)) { + throw new $TypeError('Failed to parse String to BigInt'); + } + return n; + } + + if (typeof prim === 'symbol') { + throw new $TypeError('Cannot convert a Symbol value to a BigInt'); } - return $BigInt(prim); + + if (typeof prim !== 'bigint') { + throw new $SyntaxError('Assertion failed: unknown primitive type'); + } + + return prim; }; diff --git a/2022/ToBigInt.js b/2022/ToBigInt.js index aa24d7b7..d24e0fff 100644 --- a/2022/ToBigInt.js +++ b/2022/ToBigInt.js @@ -3,12 +3,15 @@ var GetIntrinsic = require('get-intrinsic'); var $BigInt = GetIntrinsic('%BigInt%', true); -var $asIntN = GetIntrinsic('%BigInt.asIntN%', true); var $Number = GetIntrinsic('%Number%'); +var $TypeError = GetIntrinsic('%TypeError%'); var $SyntaxError = GetIntrinsic('%SyntaxError%'); +var StringToBigInt = require('./StringToBigInt'); var ToPrimitive = require('./ToPrimitive'); +var isNaN = require('../helpers/isNaN'); + // https://262.ecma-international.org/11.0/#sec-tobigint module.exports = function ToBigInt(argument) { @@ -18,8 +21,33 @@ module.exports = function ToBigInt(argument) { var prim = ToPrimitive(argument, $Number); + if (prim == null) { + throw new $TypeError('Cannot convert null or undefined to a BigInt'); + } + + if (typeof prim === 'boolean') { + return prim ? $BigInt(1) : $BigInt(0); + } + if (typeof prim === 'number') { - return $asIntN(0, prim); + throw new $TypeError('Cannot convert a Number value to a BigInt'); + } + + if (typeof prim === 'string') { + var n = StringToBigInt(prim); + if (isNaN(n)) { + throw new $TypeError('Failed to parse String to BigInt'); + } + return n; + } + + if (typeof prim === 'symbol') { + throw new $TypeError('Cannot convert a Symbol value to a BigInt'); } - return $BigInt(prim); + + if (typeof prim !== 'bigint') { + throw new $SyntaxError('Assertion failed: unknown primitive type'); + } + + return prim; }; diff --git a/test/tests.js b/test/tests.js index c16cf848..d466ae9c 100644 --- a/test/tests.js +++ b/test/tests.js @@ -10754,16 +10754,13 @@ var es2020 = function ES2020(ES, ops, expectedMissing, skips) { }); test('ToBigInt', function (t) { - t['throws']( - function () { ES.ToBigInt(); }, - hasBigInts ? TypeError : SyntaxError, - 'undefined throws' - ); - t['throws']( - function () { ES.ToBigInt(null); }, - hasBigInts ? TypeError : SyntaxError, - 'null throws' - ); + forEach([null, undefined].concat(v.symbols, v.numbers), function (nonBigIntCoercible) { + t['throws']( + function () { ES.ToBigInt(nonBigIntCoercible); }, + hasBigInts ? TypeError : SyntaxError, + debug(nonBigIntCoercible) + ' throws' + ); + }); forEach(v.symbols, function (sym) { t['throws'](