fetch api is broken due to spec violation
Opened this issue · 2 comments
What version of Bun is running?
1.2.22+6bafe2602
What platform is your computer?
Darwin 24.6.0 arm64 arm
What steps can reproduce the bug?
const x = await fetch('https://example.com')
Buffer.from(await x.clone().arrayBuffer()).fill('x')
console.log(await x.text())What is the expected behavior?
As in Node.js, Deno and browsers
What do you see instead?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Additional information
https://fetch.spec.whatwg.org/
The arrayBuffer() method steps are to return the result of running consume body with this and the following step given a byte sequence bytes: return the result of creating an ArrayBuffer from bytes in this’s relevant realm.
Spec says that arrayBuffer() should always make a copy of the underlying bytes:
creating an ArrayBuffer from bytes
"Creating an ArrayBuffer" says (https://webidl.spec.whatwg.org/#arraybuffer-create):
- Write bytes into arrayBuffer.
Which in turn says (https://webidl.spec.whatwg.org/#arraybuffer-write):
- For i in the range startingOffset to startingOffset + bytes’s length − 1, inclusive, perform SetValueInBuffer(jsArrayBuffer, i, Uint8, bytes[i - startingOffset], true, Unordered).
i.e. .arrayBuffer() must perform actual memory writes per the specification, it demands a full copy to be made on .arrayBuffer() call, regardless of .clone() or not, and any attempts to shortcut that are a violation of the spec
Not following the spec is what caused this bug
This also allows to create non-equal ArrayBuffer instances referencing the same memory:
const a = new ArrayBuffer(1024)
Buffer.from(a).fill('a')
const r = new Response(a)
const b = await r.clone().arrayBuffer()
const c = await r.clone().arrayBuffer()
const d = await r.arrayBuffer()
console.log(b, c, d, b === c, b === d, c === d)
Buffer.from(b).fill('x')
console.log(b, c, d, b === c, b === d, c === d)