We don’t use C++17 as a baseline yet, but once we do, we can use
`std::variant` to make a few things more performant (and cleaner).
There is a similar TODO comment in the crypto source already.
PR-URL: https://github.com/nodejs/node/pull/38788
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Add `ev.ports` for spec compliancy.
Since we only emit the raw `data` value, and only create the
`MessageEvent` instance if there are EventTarget-style listeners,
we store the ports list temporarily on the MessagePort object itself,
so that we can look it up when we need to create the event object.
Fixes: https://github.com/nodejs/node/issues/37358
PR-URL: https://github.com/nodejs/node/pull/37538
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
When a Worker is terminated, its own handle and the public
`MessagePort` are `.ref()`’ed, so that all relevant events,
including the `'exit'` events, end up being received.
However, this is problematic if messages end up being queued
from the Worker between the beginning of the `.terminate()` call
and its completion, and there are no `'message'` event handlers
present at that time. In that situation, currently the messages
would not end up being processed, and since the MessagePort
is still `.ref()`’ed, it would keep the event loop alive
indefinitely.
To fix this:
- Make sure that all messages end up being received by
`drainMessagePort()`, including cases in which the port had
been stopped (i.e. there are no `'message'` listeners) and
cases in which we exceed the limit for messages being processed
in one batch.
- Unref the Worker’s internal ports manually after the Worker
has exited.
Either of these solutions should be solving this on its own,
but I think it makes sense to make sure that both of them
happen during cleanup.
PR-URL: https://github.com/nodejs/node/pull/37319
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Make sure that `SharedArrayBuffer`s can be deserialized on multiple
receiving ends. As a drive-by, also fix the condition of the
internal assertion that should occur if there are transferables
passed to multiple destinations.
PR-URL: https://github.com/nodejs/node/pull/36501
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Enable JS wrapper objects to be used as transferable or cloneable
objects in `postMessage()` calls, by having them extend a C++-backed
class.
This requires a few internal changes:
- This commit adds the possibility for transferred objects to
read/write JS values at the end of the serialization/deserialization
phases.
- This commit adds the possibility for transferred objects to list
sub-transferables, e.g. typically the public JS wrapper class
would list its C++ handle in there.
- This commit adds usage of `BaseObject` in a few more places, because
now during deserialization weakly held objects can also be involved,
in addition to `MessagePort`s.
PR-URL: https://github.com/nodejs/node/pull/33772
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Extend support for transferring objects à la `MessagePort` to other
types of `BaseObject` subclasses, as well as implement cloning
support for cases in which destructive transferring is not needed
or optional.
PR-URL: https://github.com/nodejs/node/pull/33772
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Remove custom tracking for `SharedArrayBuffer`s and their allocators
and instead let V8 do the tracking of both. This is required starting
in V8 7.9, because lifetime management for `ArrayBuffer::Allocator`s
differs from what was performed previously (i.e. it is no longer
easily possible for one Isolate to release an `ArrayBuffer` and another
to accept it into its own allocator), and the alternative would
have been adapting the `SharedArrayBuffer` tracking logic to also
apply to regular `ArrayBuffer` instances.
Refs: https://github.com/nodejs/node/pull/30044
PR-URL: https://github.com/nodejs/node/pull/30020
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Refactor the C++ code for creating `MessagePort`s to skip calling the
constructor and instead directly instantiating the `InstanceTemplate`,
and always throw an error from the `MessagePort` constructor.
This aligns behaviour with the web, and creating single `MessagePort`s
does not make sense anyway.
PR-URL: https://github.com/nodejs/node/pull/28032
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
In combination with Atomics, this makes it possible to implement
generic synchronous functionality, e.g. `importScript()`, in Workers
purely by communicating with other threads.
This is a continuation of https://github.com/nodejs/node/pull/26686,
where a preference for a solution was voiced that allowed reading
individual messages, rather than emitting all messages through events.
PR-URL: https://github.com/nodejs/node/pull/27294
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
When a `MessagePort` connected to another `MessagePort` closes, the
latter `MessagePort` will be closed as well. Until now, this is done
by testing whether the ports are still entangled after processing
messages. This leaves open a race condition window in which messages
sent just before the closure can be lost when timing is unfortunate.
(A description of the timing is in the test file.)
This can be addressed by using a special message instead, which is
the last message received by a `MessagePort`. This way, all previously
sent messages are processed first.
Fixes: https://github.com/nodejs/node/issues/22762
PR-URL: https://github.com/nodejs/node/pull/27705
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This is a property of the native object associated with the
`MessagePort`, not something that should be set on the
conceptual `MessagePort` that may be transferred around.
PR-URL: https://github.com/nodejs/node/pull/27705
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
The current mechanism of uses two async handles, one owned by the
creator of the worker thread to terminate a running worker,
and another one employed by the worker to interrupt its creator on its
natural termination. The force termination piggybacks on the message-
passing mechanism to inform the worker to quiesce.
Also there are few flags that represent the other thread's state /
request state because certain code path is shared by multiple
control flows, and there are certain code path where the async
handles may not have come to life.
Refactor into an AsyncRequest abstraction that exposes routines to
install a handle as well as to save a state.
PR-URL: https://github.com/nodejs/node/pull/26099
Refs: https://github.com/nodejs/node/pull/21283
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Enable in-memory transfer of WASM modules without recompilation.
Previously, the serialization step worked, but deserialization failed
because we did not explicitly enable decoding inline WASM modules,
and so the message was not successfully received.
PR-URL: https://github.com/nodejs/node/pull/25314
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This patch:
- Refactors the `MemoryRetainer` API so that the impementer no longer
calls `TrackThis()` that sets the size of node on the top of the
stack, which may be hard to understand. Instead now they implements
`SelfSize()` to provide their self sizes. Also documents
the API in the header.
- Refactors `MemoryTracker` so it calls `MemoryInfoName()` and
`SelfSize()` of `MemoryRetainer` to retrieve info about them, and
separate `node_names` and `edge_names` so the edges can be properly
named with reference names and the nodes can be named with class
names. (Previously the nodes are named with reference names while the
edges are all indexed and appear as array elements).
- Adds `SET_MEMORY_INFO_NAME()`, `SET_SELF_SIZE()` and
`SET_NO_MEMORY_INFO()` convenience macros
- Fixes a few `MemoryInfo` calls in some `MemoryRetainers` to track
their references properly.
- Refactors the heapdump tests to check both node names and edge names,
distinguishing between wrapped JS nodes (without prefixes)
and embedder wrappers (prefixed with `Node / `).
PR-URL: https://github.com/nodejs/node/pull/23072
Reviewed-By: Anna Henningsen <anna@addaleax.net>
- Use camel case names for memory retainers inherited from AsyncWrap
instead of their provider names (which are all in upper case)
- Assign class names to wraps so that they appear in the heap snapshot
as nodes with class names as node names. Previously some nodes are
named with reference names, which are supposed to be edge names
instead.
PR-URL: https://github.com/nodejs/node/pull/21939
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
This will enable more detailed heap snapshots based on
a newer V8 API.
This commit itself is not tied to that API and could
be backported.
PR-URL: https://github.com/nodejs/node/pull/21742
Reviewed-By: James M Snell <jasnell@gmail.com>
Currently, transferring the port on which postMessage is called causes a
segmentation fault, and transferring the target port causes a subsequent
port.onmessage setting to throw, or a deadlock if onmessage is set
before the postMessage. Fix both of these behaviors and align the
methods more closely with the normative definitions in the HTML
Standard.
Also, per spec postMessage must not throw just because the ports are
disentangled. Implement that behavior.
PR-URL: https://github.com/nodejs/node/pull/21540
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
At least one method on a native object is added as a getter,
namely `MessagePort.prototype.onmessage`. When a MessagePort
attempts to call this method from C++ in response to receiving
data, it will first invoke that getter and then call the function.
Since `worker.terminate()` interrupts execution, this means
that the getter may fail (without being faulty code on its own).
This means that at least one test exercising these methods in
combination has been flaky and could have crashed, because
we did not actually check that the getter returns a value
so far, resulting in dereferencing an empty `Local`.
The proper fix for this is to use the non-deprecated overload
of `Get()` and check the result like we should be doing.
Also, as a (related) fix, don’t crash if the method
is not a function but rather something else, like a getter
could provide.
Example test failure: https://ci.nodejs.org/job/node-test-commit-linux-containered/4976/nodes=ubuntu1604_sharedlibs_zlib_x64/console
17:56:56 not ok 1955 parallel/test-worker-dns-terminate
17:56:56 ---
17:56:56 duration_ms: 1.237
17:56:56 severity: crashed
17:56:56 exitcode: -11
17:56:56 stack: |-
PR-URL: https://github.com/nodejs/node/pull/21189
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>