mirror of
https://github.com/nodejs/node.git
synced 2025-05-15 17:35:26 +00:00

Adds a new `makeTransferable()` utility that can construct a `JSTransferable` object that does not directly extend the `JSTransferable` JavaScript class. Because JavaScript does not support multiple inheritance, it is not possible (without help) to implement a class that extends both `JSTransferable` and, for instance, `EventTarget` without incurring a significant additional complexity and performance cost by making all `EventTarget` instances extend `JSTransferable`... That is, we *don't* want: ```js class EventTarget extends JSTransferable { ... } ``` The `makeTransferable()` allows us to create objects that are backed internally by `JSTransferable` without having to actually extend it by leveraging the magic of `Reflect.construct()`. ```js const { JSTransferable, kClone, kDeserialize, kConstructor, makeTransferable, } = require('internal/worker/js_transferable'); class E { constructor(b) { this.b = b; } } class F extends E { [kClone]() { /** ... **/ } [kDeserialize]() { /** ... **/ } static [kConstructor]() { return makeTransferable(F); } } const f = makeTransferable(F, 1); f instanceof F; // true f instanceof E; // true f instanceof JSTransferable; // false const mc = new MessageChannel(); mc.port1.onmessage = ({ data }) => { data instanceof F; // true data instanceof E; // true data instanceof JSTransferable; // false }; mc.port2.postMessage(f); // works! ``` The additional `internal/test/transfer.js` file is required for the test because successfully deserializing transferable classes requires that they be located in `lib/internal` for now. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/38383 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Khaidi Chu <i@2333.moe>
43 lines
782 B
JavaScript
43 lines
782 B
JavaScript
'use strict';
|
|
|
|
const {
|
|
makeTransferable,
|
|
kClone,
|
|
kDeserialize,
|
|
} = require('internal/worker/js_transferable');
|
|
|
|
process.emitWarning(
|
|
'These APIs are for internal testing only. Do not use them.',
|
|
'internal/test/transfer');
|
|
|
|
// Used as part of parallel/test-messaging-maketransferable.
|
|
// This has to exist within the lib/internal/ path in order
|
|
// for deserialization to work.
|
|
|
|
class E {
|
|
constructor(b) {
|
|
this.b = b;
|
|
}
|
|
}
|
|
|
|
class F extends E {
|
|
constructor(b) {
|
|
super(b);
|
|
/* eslint-disable-next-line no-constructor-return */
|
|
return makeTransferable(this);
|
|
}
|
|
|
|
[kClone]() {
|
|
return {
|
|
data: { b: this.b },
|
|
deserializeInfo: 'internal/test/transfer:F'
|
|
};
|
|
}
|
|
|
|
[kDeserialize]({ b }) {
|
|
this.b = b;
|
|
}
|
|
}
|
|
|
|
module.exports = { E, F };
|