forked from CoreBunch/Instatic
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary.ts
More file actions
36 lines (35 loc) · 1.58 KB
/
Copy pathbinary.ts
File metadata and controls
36 lines (35 loc) · 1.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Copy a `Uint8Array` (or any view/Buffer) into a freshly allocated,
* exactly-sized, definite `ArrayBuffer`.
*
* Why the copy is necessary — a `Uint8Array` is only a *view*. Handing its
* `.buffer` straight to a `Response`/`fetch` body or a worker `postMessage`
* transfer is wrong on two counts:
*
* 1. **Oversized / shared backing store.** The view may start at a non-zero
* `byteOffset` and cover only part of a larger buffer (a slice, a pooled
* Node `Buffer`, a sub-view). The consumer would then see sibling bytes
* past the declared range, or take ownership of (and detach) memory that
* other views still reference.
* 2. **Type widening.** `view.buffer` resolves to `ArrayBuffer |
* SharedArrayBuffer` under modern lib.dom types; body/transfer slots want
* a definite `ArrayBuffer`.
*
* Allocating a clean buffer of exactly `byteLength` and copying the logical
* bytes (via `.set`, which respects the source's offset) sidesteps both. The
* copy is cheap relative to the I/O it precedes (HTTP response, network upload,
* cross-thread transfer).
*/
export function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {
const out = new ArrayBuffer(bytes.byteLength)
new Uint8Array(out).set(bytes)
return out
}
/**
* Build a `Response` whose body is the bytes copied into a fresh `ArrayBuffer`
* (see {@link toArrayBuffer} for why the copy is required). Convenience for the
* common "serve raw bytes" path.
*/
export function binaryResponse(bytes: Uint8Array, init?: ResponseInit): Response {
return new Response(toArrayBuffer(bytes), init)
}