MikeMcl / bignumber.js

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic
http://mikemcl.github.io/bignumber.js
MIT License
6.64k stars 741 forks source link

fix: allow object literals without _isBignumber flag #318

Closed florianbepunkt closed 1 year ago

florianbepunkt commented 2 years ago

Fixes Rehydration after structural cloning #317.

An obj { s: 1, e: -2, c: [ 50 ] } is not a BigNumber, hence BigNumber.isBigNumber(obj) is false, but you can construct a BigNumber from it: new BigNumber(obj).

This simplifies serialization/deserialization, since BigNumber values can be sent over the wire/inter process communication.

const someFn = (valueThatMightBeSerializedOrNot: BigNumber) => new BigNumber(valueThatMightBeSerializedOrNot).plus(1);
const bnValue = new BigNumber(1);
const fromJsonValue = JSON.parse(JSON.stringify(bnValue);

assert.strictEqual(someFn(bnValue).toString(), someFn(fromJsonValue).toString())
MikeMcl commented 1 year ago

I remain reluctant to replace the _isBigNumber === true test with your suggested typeof triplet on probably the hottest code path in the library (regardless of whether or not it would seem to make any significant difference in performance).

Deserialization after structured cloning is pretty straightforward as it is:

const serialize = bn => JSON.stringify(structuredClone(bn));
const deserialize = json => new BigNumber({ _isBigNumber: true, ...JSON.parse(json) });

const a = new BigNumber('1.23');
const b = deserialize(serialize(a));

console.log(a.eq(b));    // true

I apologise for the late response, and thank you for your efforts.

On second thoughts, maybe I'll add a BigNumber.fromObject method as suggested by #245. Anyway, I'll leave this open for now...