From 646126d9a4a9c193889f7473c5392f8d337f7315 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 8 Jan 2025 11:32:55 +0100 Subject: [PATCH 1/3] fix: #3342 hexadecimal input not turned into a bigint --- src/utils/number.js | 12 ++++++++++-- test/unit-tests/expression/parse.test.js | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/utils/number.js b/src/utils/number.js index 5095b71628..6d63570791 100644 --- a/src/utils/number.js +++ b/src/utils/number.js @@ -48,8 +48,16 @@ export function isIntegerStr (str) { * @returns {'number' | 'BigNumber' | 'bigint' | 'Fraction'} */ export function safeNumberType (numberStr, config) { - if (config.number === 'bigint' && !isIntegerStr(numberStr)) { - return config.numberFallback + if (config.number === 'bigint') { + const canParseIntoBigint = + isIntegerStr(numberStr) || + numberStr.startsWith('0x') || + numberStr.startsWith('0b') || + numberStr.startsWith('0o') + + if (!canParseIntoBigint) { + return config.numberFallback + } } return config.number diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index 92a1871b5f..51651a5adc 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -2248,6 +2248,12 @@ describe('parse', function () { assert.strictEqual(bigmath.evaluate('-2.3'), -2.3) }) + it('should parse hex, bin, oct numbers as bigint', function () { + assert.strictEqual(bigmath.evaluate('0xA2'), 162n) + assert.strictEqual(bigmath.evaluate('0b1011'), 11n) + assert.strictEqual(bigmath.evaluate('0o70'), 56n) + }) + it('should fallback on the configured numberFallback when parsing as bigint', function () { const bigmathFallback = math.create({ number: 'bigint', From d6866bd0df5b15eb03eab4d3772ab2bf6f4c9e31 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 8 Jan 2025 11:43:35 +0100 Subject: [PATCH 2/3] chore: more strict recognition of hex, bin, oct --- src/utils/number.js | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/utils/number.js b/src/utils/number.js index 6d63570791..bdcee13db5 100644 --- a/src/utils/number.js +++ b/src/utils/number.js @@ -20,15 +20,41 @@ export function isInteger (value) { } /** - * Check if a string contains an integer + * Check if a string contains an integer number like "123" and "-123" * @param {string} str * @return {boolean} isInteger */ export function isIntegerStr (str) { - // regex matching strings like "123" and "-123" return /^-?\d+$/.test(str) } +/** + * Check if a string contains a hex number like "0xA2" + * @param {string} str + * @return {boolean} isInteger + */ +export function isHexStr (str) { + return /^0x[0-9A-Fa-f]+$/.test(str) +} + +/** + * Check if a string contains a binary number like "0b1011" + * @param {string} str + * @return {boolean} isInteger + */ +export function isBinStr (str) { + return /^0b[01]+$/.test(str) +} + +/** + * Check if a string contains an octal number like "0o70" + * @param {string} str + * @return {boolean} isInteger + */ +export function isOctStr (str) { + return /^0o[0-7]+$/.test(str) +} + /** * Ensure the number type is compatible with the provided value. * If not, return 'number' instead. @@ -51,9 +77,9 @@ export function safeNumberType (numberStr, config) { if (config.number === 'bigint') { const canParseIntoBigint = isIntegerStr(numberStr) || - numberStr.startsWith('0x') || - numberStr.startsWith('0b') || - numberStr.startsWith('0o') + isHexStr(numberStr) || + isBinStr(numberStr) || + isOctStr(numberStr) if (!canParseIntoBigint) { return config.numberFallback From 9c2579b96c156c9f0b6de4bd9f5bf25b53a3526e Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Fri, 24 Jan 2025 10:35:16 +0100 Subject: [PATCH 3/3] chore: simplify the `safeNumberType` implementation --- src/utils/number.js | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/src/utils/number.js b/src/utils/number.js index bdcee13db5..9962b681f9 100644 --- a/src/utils/number.js +++ b/src/utils/number.js @@ -28,33 +28,6 @@ export function isIntegerStr (str) { return /^-?\d+$/.test(str) } -/** - * Check if a string contains a hex number like "0xA2" - * @param {string} str - * @return {boolean} isInteger - */ -export function isHexStr (str) { - return /^0x[0-9A-Fa-f]+$/.test(str) -} - -/** - * Check if a string contains a binary number like "0b1011" - * @param {string} str - * @return {boolean} isInteger - */ -export function isBinStr (str) { - return /^0b[01]+$/.test(str) -} - -/** - * Check if a string contains an octal number like "0o70" - * @param {string} str - * @return {boolean} isInteger - */ -export function isOctStr (str) { - return /^0o[0-7]+$/.test(str) -} - /** * Ensure the number type is compatible with the provided value. * If not, return 'number' instead. @@ -75,13 +48,9 @@ export function isOctStr (str) { */ export function safeNumberType (numberStr, config) { if (config.number === 'bigint') { - const canParseIntoBigint = - isIntegerStr(numberStr) || - isHexStr(numberStr) || - isBinStr(numberStr) || - isOctStr(numberStr) - - if (!canParseIntoBigint) { + try { + BigInt(numberStr) + } catch { return config.numberFallback } }