From d027786c8050e35d239f0a5188fdbe5df46dc17a Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Thu, 22 Oct 2026 23:29:34 -0500 Subject: [PATCH] Convert Buffers and DataViews to BigInt through their own text BigInt of byte storage joined the elements with "," for every kind, so a Buffer, whose text is its UTF-8 decoding, and a DataView, whose text is "[object DataView]", converted as typed arrays. BigInt now parses the value's ToString, which the runtime value decides, as String does. This also covers a Buffer held in a Uint8Array slot. Corpus 7403 adds Buffers, a DataView, and a Buffer in a typed array slot. Refs #1647 --- .../src/frontend/lowering/lower-calls.ts | 14 +++++++------- tests/corpus/7403-bigint-of-typed-arrays.mjs | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/compiler/src/frontend/lowering/lower-calls.ts b/packages/compiler/src/frontend/lowering/lower-calls.ts index 8424f28c4..e44f0a2bc 100644 --- a/packages/compiler/src/frontend/lowering/lower-calls.ts +++ b/packages/compiler/src/frontend/lowering/lower-calls.ts @@ -2400,15 +2400,15 @@ function lowerBigIntConstructorValue(lowerer: Lowerer, arg: IrExpr, loc: SrcLoc) return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc }; if (arg.type.kind === "f64") return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc }; - // A typed array converts through ToPrimitive to its elements joined with - // ",", which BigInt then parses: one element reads as that element, none - // as 0n, and several throw the SyntaxError for the joined text. + // Byte storage converts through ToPrimitive, which BigInt then parses: a + // typed array's text is its elements joined with "," (one element reads + // as that element, none as 0n, several throw the SyntaxError for the + // joined text), a Buffer's is its UTF-8 decoding and a DataView's is + // "[object DataView]". The runtime value tells them apart, as for String. if (arg.type.kind === "bytes") { const text: IrExpr = { - kind: "bytesIntrinsic", - method: "join", - receiver: arg, - args: [{ kind: "strLit", value: ",", type: STRING, loc }], + kind: "toString", + operand: { kind: "dynFrom", value: arg, type: DYN, loc }, type: STRING, loc, }; diff --git a/tests/corpus/7403-bigint-of-typed-arrays.mjs b/tests/corpus/7403-bigint-of-typed-arrays.mjs index 77ef0cd2e..9cf813d9a 100644 --- a/tests/corpus/7403-bigint-of-typed-arrays.mjs +++ b/tests/corpus/7403-bigint-of-typed-arrays.mjs @@ -2,7 +2,9 @@ // "," and parses that text, as in Node: one element reads as its value, // an empty array as 0n, and anything else throws the SyntaxError for the // joined text. Every element kind, negative and clamped values, float -// formatting, views and the results in arithmetic. +// formatting, views and the results in arithmetic. A Buffer converts +// through its UTF-8 text instead, also when a typed array slot holds it, +// and a DataView through "[object DataView]". const one = [ new Int8Array([-5]), @@ -44,3 +46,17 @@ for (let i = 0; i < 100; i++) { total += BigInt(window) * 3n; } console.log("window", BigInt(window), total, BigInt(bytes.subarray(2)) ** 2n); + +function convert(label, make) { + try { + console.log(label, BigInt(make())); + } catch (e) { + console.log(label, e instanceof SyntaxError, e.message); + } +} +convert("buffer", () => Buffer.from("12")); +convert("spaced buffer", () => Buffer.from(" -7 ")); +convert("empty buffer", () => Buffer.alloc(0)); +convert("fraction buffer", () => Buffer.from("1.5")); +convert("data view", () => new DataView(new ArrayBuffer(2))); +for (const view of [new Uint8Array([5]), Buffer.from("64")]) console.log("slot", BigInt(view));