Skip to content

Making DOMException and AbortError cloneable #41038

Closed

Description

@jasnell

Currently, custom error objects implemented in JavaScript are not cloneable via postMessage / structuredClone with perfect fidelity.

e.g.

const d = new DOMException('foo', 'AbortErr');
const mc = new MessageChannel();
mc.port1.onmessage = ({data}) => {
  console.log(data is DOMException); // false
  console.log(data.name); // AbortErr
  console.log(data.message); // 'foo'
  console.log(data.code); // undefined
};
mc.port1.postMessage(d);

Likewise, AbortError is also not correctly cloneable.

The current way that DOMException is implemented (in JavaScript during the per_context bootstrap), it is not possible for us to use the existing internal/worker/js_transferable mechanisms to make it cloneable as the DOMException is loaded too early.

However, if we reimplement DOMException as a native host object (within a C++ binding extending BaseObject) then we can easily make it cloneable (likewise with AbortError). Before going through that effort, however, I wanted to see what folks thought.

/cc @addaleax @joyeecheung

Activity

  1. addaleax commented on Nov 30, 2021

    @addaleax
    Member

    Is it not possible to also load internal/worker/js_transferable early, before DOMException? It doesn’t really depend on anything else, I think.

  2. joyeecheung commented on Nov 30, 2021

    @joyeecheung
    Member

    Is it not possible to also load internal/worker/js_transferable early, before DOMException?

    That's probably not going to work, if it needs to have internalBinding to get the symbols and the bindings, because per-context scripts are run before internalBinding is created. I believe DOMException are in per-context scripts because they are needed in VM contexts, but for now it doesn't make sense to create a copy of internalBinding for every context, so rewriting it in C++ is probably still the way to go.

  3. joyeecheung commented on Nov 30, 2021

    @joyeecheung
    Member

    On a second thought, it might still be possible to keep this in JS if instead of using internalBinding to access stuff created in C++, you pass what it needs from the C++ layer directly into the scripts. Although for that to work you'd need to update InitializePrimordials in src/api/environment.cc and create a mechanism to pass different arguments into different per-context scripts (right now they all get [global, exports, primordials] as the arguments passed into the function wrapper), which would probably be like a poor-man's internalBinding.

  4. jasnell commented on Nov 30, 2021

    @jasnell
    MemberAuthor

    Looking through that code, just implementing DOMException as a BaseObject still seems like the easiest path unless there's some bit of code initialized before internalBinding() that needs the ability to create a DOMException?

  5. jasnell commented on Nov 30, 2021

    @jasnell
    MemberAuthor

    @addaleax :

    Is it not possible to also load internal/worker/js_transferable early, before DOMException? It doesn’t really depend on anything else, I think.

    Sadly no. We also can't load it lazily using require() as the require() that is in scope for per_context scripts is not internal aware.

  6. addaleax commented on Dec 3, 2021

    @addaleax
    Member

    @jasnell I think it would still be worth doing this the “right” way and making JSTransferable and its (very few) dependencies multi-context-aware, that feels like the most future-proof thing anyway

  7. jasnell commented on Dec 3, 2021

    @jasnell
    MemberAuthor

    It's likely that my brain is just fried from a week of bouncing back and forth between two different runtimes ... but it's not immediately clear to me how that helps with making error objects cloneable?

  8. 5 remaining items

  9. moved this to Pending triage in Node.js feature requestson Jan 16, 2022
  10. moved this from Pending triage to In Progress in Node.js feature requestson Jan 16, 2022
  11. github-actions commented on Jun 5, 2022

    @github-actions
    Contributor

    There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

    For more information on how the project manages feature requests, please consult the feature request management document.

  12. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jun 5, 2022
  13. github-actions commented on Jul 5, 2022

    @github-actions
    Contributor

    There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment.

    For more information on how the project manages feature requests, please consult the feature request management document.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions