-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
module: refactor to use iterable-weak-map #35915
Conversation
Review requested:
|
class IterableWeakMap { | ||
#weakMap = new WeakMap(); | ||
#refSet = new Set(); | ||
#finalizationGroup = new global.FinalizationRegistry(cleanup); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joyeecheung @addaleax when I try to define FinalizationRegistry
and WeakRef
in primordials, I get a compilation error because the WeakRef
and FinalizationRegistry
are undefined
at the time when primordials
is initially loaded.
Any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WeakRef and FinalizationRegistry cannot be used with snapshots because they can be disabled using a flag at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this means we can't use them for a utility like this?
We don't want source maps to stop working because the flag isn't set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a V8 --harmony
flag, that's not supported and undocumented in Node.js. I'd say it's fine to use them.
#refSet = new Set(); | ||
#finalizationGroup = new global.FinalizationRegistry(cleanup); | ||
|
||
set(key, value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how this works - this appears to create a new WeakRef
each time the key is set even if the key "value" already exists in the map? Is this intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var m = new Map();
var o = {};
var r1 = new WeakRef(o);
var r2 = new WeakRef(o);
m.set(r1, "foo");
console.log(m.get(r1)); // foo
console.log(m.get(r2)); // undefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this appears to create a new WeakRef each time the key is set even if the key "value" already exists in the map? Is this intentional
I'll add unit tests for the IterableWeakMap
implementation, and will make sure this case is covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm saying - I don't understand how it works and to my understanding it's not supposed to. A test is fine, but a "this works because X" is also fine :]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benjamingr I'm pretty sure you've identified a bug in the IterableWeakMap
shared on the TC39 spec page -- we should only create a new WeakRef
if there's not already an entry, otherwise we should perform an update.
Once I've fixed this, I'll share the updated code, and can provide a walk through of the logic if it's still confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, feel free to ping me when updated and I'll take a look :]
CC: @mcollina, I noticed a conversation you had on Twitter contemplating using IterableWeakMaps for a similar purpose. |
6674141
to
8fe7828
Compare
class IterableWeakMap { | ||
#weakMap = new SafeWeakMap(); | ||
#refSet = new SafeSet(); | ||
// TODO(aduh95): Add FinalizationRegistry to primordials |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to call it out explicitly: i think these primordials todos should be considered blockers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb @aduh95, how about the approach of exposing the makeSafe
from primordials, and freezing WeakRef
and FinalizationRegistry
when iterable-weak-map.js
is loaded:
// TODO(aduh95): Add WeakRef to primordials
const SafeWeakRef = makeSafe(
globalThis.WeakRef,
class SafeWeakRef extends globalThis.WeakRef {}
);
// This class is modified from the example code in the WeakRefs specification:
// https://github.com/tc39/proposal-weakrefs
// Licensed under ECMA's MIT-style license, see:
// https://github.com/tc39/ecma262/blob/master/LICENSE.md
class IterableWeakMap {
// ...
}}
source_map_cache.js
pretty early on in the application lifecycle, _I think, before any userland code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems fine, but I’m not sure what’s wrong with eagerly freezing it, like all the other primordials?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the primordials are prepared, we only have access to a subset of builtins. V8 does not provide us the ones that can be disabled with flags by the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhhh thanks, that makes sense.
Generally look fine, lmk when it's ready and I'll check the branch out and play with it a bit :] |
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Antoine du Hamel <[email protected]>
Co-authored-by: Antoine du Hamel <[email protected]>
Co-authored-by: Antoine du Hamel <[email protected]>
8ba5609
to
f1d088a
Compare
This comment has been minimized.
This comment has been minimized.
@benjamingr happy with how this is looking? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Using an iterable WeakMap (a data-structure that uses WeakRef and WeakMap), we are able to: stop relying on Module._cache to serialize source maps; stop requiring an error object when calling findSourceMap(). PR-URL: #35915 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
Landed in 8fa9035 |
Using an iterable WeakMap (a data-structure that uses WeakRef and WeakMap), we are able to: stop relying on Module._cache to serialize source maps; stop requiring an error object when calling findSourceMap(). PR-URL: #35915 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
Using an iterable WeakMap (a data-structure that uses WeakRef and WeakMap), we are able to: stop relying on Module._cache to serialize source maps; stop requiring an error object when calling findSourceMap(). PR-URL: nodejs#35915 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
Using an iterable WeakMap (a data-structure that uses WeakRef and WeakMap), we are able to: stop relying on Module._cache to serialize source maps; stop requiring an error object when calling findSourceMap(). PR-URL: nodejs#35915 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
Using an iterable WeakMap (a data-structure that uses WeakRef and WeakMap), we are able to: stop relying on Module._cache to serialize source maps; stop requiring an error object when calling findSourceMap(). PR-URL: #35915 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
Using an iterable WeakMap (a data-structure that uses WeakRef and
WeakMap), we are able to: stop relying on Module._cache to
serialize source maps; stop requiring an error object when calling
findSourceMap().
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes