Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: add support for JSTransferable as a mixin #38383

Closed
wants to merge 1 commit into from

Commits on Apr 25, 2021

  1. lib: add support for JSTransferable as a mixin

    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>
    jasnell committed Apr 25, 2021
    Configuration menu
    Copy the full SHA
    ad99a04 View commit details
    Browse the repository at this point in the history