feat: pack and unpack 64-bit integers as BigInt (#37) - #25689
Merged
Merged
Conversation
Integers outside Number.MAX_SAFE_INTEGER unpack as bigint instead of a rounded number. Values that fit stay number regardless of wire width. pack() accepts bigint in the int64/uint64 range and throws for anything larger. Closes msgpack#37.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
unpack()returnsbigintfor int64/uint64 values outsideNumber.MAX_SAFE_INTEGER.numberregardless of MessagePack wire width (a uint64 of1is still Number1).pack()acceptsbigintin the int64/uint64 range and throws a catchable error outside that range.Motivation
Closes #37.
A uint64 such as
18446464814936021036cannot be a JavaScript Number without rounding. Callers that already have the exact value as BigInt, or that receive that wire, now round-trip losslessly. A Number that is already rounded is still packed as today's number path; lost bits are not recovered.This is a breaking change for anyone who unpacked an unsafe 64-bit integer and got a rounded Number. Bump is 2.0.0 → 3.0.0.
Changes
src/msgpack.cc: packIsBigInt()viaInt64Value/Uint64Value; unpack POSITIVE/NEGATIVE integer to Number iff it fitsMAX_SAFE_INTEGER/MIN_SAFE_INTEGER, elsev8::BigInt.index.d.ts:packacceptsbigint;unpackmay returnbigint.test/bigint.test.jsplus updates to coverage-native and regression integer-edge cases.Test Plan
npm test— 137 tests, 0 fail (Node 20.20.2 linux arm64, rebuilt native addon).cf ff ff 02 04 00 00 d8 2cunpacks as18446464814936021036n.Number.MAX_SAFE_INTEGERstaynumber.pack(2n ** 64n)andpack(-(2n ** 63n) - 1n)throw.Notes for Reviewers
windows-2022in.github/workflows/ci.yml).