From 7d05b197ec50730b48d4e56ebc3e1d8e6fb43ac3 Mon Sep 17 00:00:00 2001 From: bing Date: Tue, 5 May 2026 19:27:58 +0800 Subject: [PATCH] fix: doc comments regarding safety for `Number.toU32()` Discovered this while working on https://github.com/ChainSafe/lodestar-z/pull/349. `napi_get_value_uint32` makes no guarantee of erroring on values out of bounds: > Let int32bit be int modulo 2**32. Source: https://tc39.es/ecma262/#sec-touint32 This little code snippet PoC when added to `BeaconStateView.test.ts` in lodestar-z passes: ```ts it("toU32 silently wraps around", () => { let i = 0; for (i = 0; i < 100; i++) { const a = state.getBalance(0 + i); const b = state.getBalance(2 ** 32 + i); expect(a).toBe(b); } }); ``` While this fails, but only because we're access the SSZ list index out of bounds: ```ts state.getBalance(-1) ``` ``` FAIL bindings/test/beaconStateView.test.ts > BeaconStateView > probe truncation behavior Error: IndexOutOfBounds ``` Other conversion methods might behave the same; i haven't fully checked, but we should be careful of this --- src/js/number.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/js/number.zig b/src/js/number.zig index 9b8315a..9dc04e0 100644 --- a/src/js/number.zig +++ b/src/js/number.zig @@ -34,7 +34,12 @@ pub const Number = struct { /// Attempts to convert the JavaScript number to a Zig `u32`. /// - /// Returns an error if the conversion fails (e.g., number is negative or too large). + /// Safety: The underlying napi implementation does not reject numbers out of + /// the range [0, 2^32). The caller is responsible for bounds checking. + /// + /// Returns an error if the given `self.val` is not a number. + /// + /// Source: https://tc39.es/ecma262/#sec-touint32 pub fn toU32(self: Number) !u32 { return self.val.getValueUint32(); }