@@ -396,6 +396,51 @@ posting without having side effects. |
396 | 396 | For more information on the serialization and deserialization mechanisms |
397 | 397 | behind this API, see the [serialization API of the `v8` module][v8.serdes]. |
398 | 398 |
|
| 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 | + |
399 | 444 | ### `port.ref()` |
400 | 445 | <!-- YAML |
401 | 446 | added: v10.5.0 |
@@ -767,6 +812,7 @@ active handle in the event system. If the worker is already `unref()`ed calling |
767 | 812 | [`'exit'` event]: #worker_threads_event_exit |
768 | 813 | [`AsyncResource`]: async_hooks.html#async_hooks_class_asyncresource |
769 | 814 | [`Buffer`]: buffer.html |
| 815 | +[`Buffer.allocUnsafe()`]: buffer.html#buffer_class_method_buffer_allocunsafe_size |
770 | 816 | [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.html#errors_err_missing_message_port_in_transfer_list |
771 | 817 | [`ERR_WORKER_NOT_RUNNING`]: errors.html#ERR_WORKER_NOT_RUNNING |
772 | 818 | [`EventEmitter`]: events.html |
|