Skip to content

feat: pack and unpack 64-bit integers as BigInt (#37) - #25689

Merged
godsflaw merged 1 commit into
msgpack:masterfrom
enochgroot:feat/bigint-64bit
Sep 19, 2026
Merged

godsflaw merged 1 commit into
msgpack:masterfrom
enochgroot:feat/bigint-64bit

Conversation

@enochgroot

Copy link
Copy Markdown
Collaborator

Summary

  • unpack() returns bigint for int64/uint64 values outside Number.MAX_SAFE_INTEGER.
  • Values that fit stay number regardless of MessagePack wire width (a uint64 of 1 is still Number 1).
  • pack() accepts bigint in the int64/uint64 range and throws a catchable error outside that range.

Motivation

Closes #37.

A uint64 such as 18446464814936021036 cannot 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: pack IsBigInt() via Int64Value/Uint64Value; unpack POSITIVE/NEGATIVE integer to Number iff it fits MAX_SAFE_INTEGER/MIN_SAFE_INTEGER, else v8::BigInt.
  • index.d.ts: pack accepts bigint; unpack may return bigint.
  • README type mapping, CHANGELOG 3.0.0, COVERAGE.md.
  • Tests: test/bigint.test.js plus 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).
  • Reporter uint64 cf ff ff 02 04 00 00 d8 2c unpacks as 18446464814936021036n.
  • uint64 of 1 and Number.MAX_SAFE_INTEGER stay number.
  • pack(2n ** 64n) and pack(-(2n ** 63n) - 1n) throw.
  • Existing suite green (workers, DoS limits, depth, prototype pollution, CLI).

Notes for Reviewers

  • Semver 3.0.0 because unpack type of unsafe integers changes from Number to BigInt.
  • No new dependencies. msgpack-c is not re-vendored.
  • Windows CI is unchanged (windows-2022 in .github/workflows/ci.yml).

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.
@godsflaw
godsflaw merged commit 1efff3d into msgpack:master Sep 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

64-bit number encoding/decoding in msgpack does not work

2 participants