This allows us to perform cleanups of cppgc wrappers that rely on a
living Realm during Realm shutdown. Otherwise the cleanup may happen
during object destruction, which can be triggered by GC after Realm
shutdown, leading to invalid access to Realm.
The general pattern for this type of non-trivial destruction is
designed to be:
```
class MyWrap final : CPPGC_MIXIN(MyWrap) {
public:
~MyWrap() { this->Finalize(); }
void Clean(Realm* realm) override {
// Do cleanup that relies on a living Realm. This would be
// called by CppgcMixin::Finalize() first during Realm
// shutdown, while the Realm is still alive. If the destructor
// calls Finalize() again later during garbage collection that
// happens after Realm shutdown, Clean() would be skipped,
// preventing invalid access to the Realm.
}
}
```
In addition, this allows us to trace external memory held by the
wrappers in the heap snapshots if we add synthethic edges between the
wrappers and other nodes in the embdder graph callback, or to perform
snapshot serialization for them.
PR-URL: https://github.com/nodejs/node/pull/56534
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
The binding data must be weak so that it won't keep the realm reachable
from strong GC roots indefinitely. The wrapper object of binding data
should be referenced from JavaScript, thus the binding data should be
reachable throughout the lifetime of the realm.
PR-URL: https://github.com/nodejs/node/pull/47688
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
The binding data holds references to the AliasedBuffers directly
from their wrappers which already ensures that the AliasedBuffers
won't be accessed when the wrappers are GC'ed. So we can just
make the global references to the AliasedBuffers weak. This way
we can simply deserialize the typed arrays when deserialize the
binding data and avoid the extra Object::Set() calls. It also
eliminates the caveat in the JS land where aliased buffers must
be dynamically read from the binding.
PR-URL: https://github.com/nodejs/node/pull/47354
Refs: https://github.com/nodejs/node/issues/47353
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Previously the native ShadowRealm objects were never actually tracked
in the heap snapshot - the tracking starts with the Environment,
we don't call the tracking methods unless it's reachable natively from
the Environment. This patch adds a set in the Environment for tracking
shadow realms in the heap snapshot.
Drive-by: remove redundant MemoryInfo() overrides from the derived
classes of Realm and remove the tracking of `env` from
`Realm::MemoryInfo()` because the realms don't hold the Environment
alive (even for the principal realm, it's the other way around).
PR-URL: https://github.com/nodejs/node/pull/47389
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Instead of returning the internal loaders from the bootstrap script,
we can simply call a binding to store them in C++. This eliminates
the need for specializing the handling of this script.
PR-URL: https://github.com/nodejs/node/pull/47215
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This is the initial work to bootstrap Web interfaces that are defined
with extended attributes `[Exposed=*]`.
The ShadowRealm instances are garbage-collected once it is
unreachable. However, V8 can not infer the reference cycles between
the per-realm strong persistent function handles and the realm's
context handle. To allow the context to be gc-ed once it is not
reachable, the per-realm persistent handles are attached to the
context's global object and the persistent handles are set as weak.
PR-URL: https://github.com/nodejs/node/pull/46809
Refs: https://github.com/nodejs/node/issues/42528
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Locally the hashing of the binding names sometimes has significant
presence in the profile of bindings, because there can be collisions,
which makes the cost of adding a new binding data non-trivial,
but it's wasteful to spend time on hashing them or dealing with
collisions at all, since we can just use the EmbedderObjectType
enum as the key, as the string names are not actually used beyond
debugging purposes and can be easily matched with a macro.
And since we can just use the enum as the key, we do not even
need the map and can just use an array with the enum as indices
for the lookup.
PR-URL: https://github.com/nodejs/node/pull/46620
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Bindings that need to be loaded in distinct contexts of node::Realm in
the same node::Environment instance needs to share the per-isolate
templates.
Add a new binding registration callback, which is called with
per-IsolateData. This allows bindings to define templates and
share them across realms eagerly, and avoid accidental modification on
the templates when the per-context callback is called multiple times.
This also tracks loaded bindings and built-in modules with node::Realm.
PR-URL: https://github.com/nodejs/node/pull/45547
Refs: https://github.com/nodejs/node/issues/42528
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>