Skip to content

Commit 0572943

Browse files
jasnellcodebytere
authored andcommitted
doc: add warnings about transferring Buffers and ArrayBuffer
Signed-off-by: James M Snell <[email protected]> PR-URL: #33252 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Mathias Buus <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Juan José Arboleda <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent 4ae6130 commit 0572943

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

doc/api/worker_threads.md

+46
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,51 @@ posting without having side effects.
396396
For more information on the serialization and deserialization mechanisms
397397
behind this API, see the [serialization API of the `v8` module][v8.serdes].
398398

399+
#### Considerations when transferring TypedArrays and Buffers
400+
401+
All `TypedArray` and `Buffer` instances are views over an underlying
402+
`ArrayBuffer`. That is, it is the `ArrayBuffer` that actually stores
403+
the raw data while the `TypedArray` and `Buffer` objects provide a
404+
way of viewing and manipulating the data. It is possible and common
405+
for multiple views to be created over the same `ArrayBuffer` instance.
406+
Great care must be taken when using a transfer list to transfer an
407+
`ArrayBuffer` as doing so will cause all `TypedArray` and `Buffer`
408+
instances that share that same `ArrayBuffer` to become unusable.
409+
410+
```js
411+
const ab = new ArrayBuffer(10);
412+
413+
const u1 = new Uint8Array(ab);
414+
const u2 = new Uint16Array(ab);
415+
416+
console.log(u2.length); // prints 5
417+
418+
port.postMessage(u1, [u1.buffer]);
419+
420+
console.log(u2.length); // prints 0
421+
```
422+
423+
For `Buffer` instances, specifically, whether the underlying
424+
`ArrayBuffer` can be transferred or cloned depends entirely on how
425+
instances were created, which often cannot be reliably determined.
426+
427+
Depending on how a `Buffer` instance was created, it may or may
428+
not own its underlying `ArrayBuffer`. An `ArrayBuffer` must not
429+
be transferred unless it is known that the `Buffer` instance
430+
owns it. In particular, for `Buffer`s created from the internal
431+
`Buffer` pool (using, for instance `Buffer.from()` or `Buffer.alloc()`),
432+
transferring them is not possible and they will always be cloned,
433+
which sends a copy of the entire `Buffer` pool.
434+
This behavior may come with unintended higher memory
435+
usage and possible security concerns.
436+
437+
See [`Buffer.allocUnsafe()`][] for more details on `Buffer` pooling.
438+
439+
The `ArrayBuffer`s for `Buffer` instances created using
440+
`Buffer.alloc()` or `Buffer.allocUnsafeSlow()` can always be
441+
transferred but doing so will render all other existing views of
442+
those `ArrayBuffer`s unusable.
443+
399444
### `port.ref()`
400445
<!-- YAML
401446
added: v10.5.0
@@ -767,6 +812,7 @@ active handle in the event system. If the worker is already `unref()`ed calling
767812
[`'exit'` event]: #worker_threads_event_exit
768813
[`AsyncResource`]: async_hooks.html#async_hooks_class_asyncresource
769814
[`Buffer`]: buffer.html
815+
[`Buffer.allocUnsafe()`]: buffer.html#buffer_class_method_buffer_allocunsafe_size
770816
[`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.html#errors_err_missing_message_port_in_transfer_list
771817
[`ERR_WORKER_NOT_RUNNING`]: errors.html#ERR_WORKER_NOT_RUNNING
772818
[`EventEmitter`]: events.html

0 commit comments

Comments
 (0)