-
Notifications
You must be signed in to change notification settings - Fork 15
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
Handle FinalizationRegistry #69
Conversation
I thought this PR was meant to fix the regression introduced in #41. However, before #41, FinalizationRegistry callbacks were called with the FR construction context, rather than with the context at the time the This is actually similar to some events in the web: const asyncVar = new AsyncContext.Variable();
const image = document.getElementById("image"); // <img id="image">
asyncVar.run("foo", () => {
image.addEventListener("load", () => {
console.log(asyncVar.get());
});
});
asyncVar.run("bar", () => {
image.src = "./some/image.jpg";
}); Here we have a registration-time context (the registration of the It's not clear to me which of the two is the right behavior, and it clearly ties into the behavior of events in the HTML integration. |
I remember this being discussed in Matrix. I believe register time is the correct one. Furthermore it's easy to do FR construction time by simply wrapping the callback. Edit: the other direction is more tricky, requiring to create a snapshot on registration, pass it in the held value, and run from the snapshot in the callback. |
I think I misunderstood you when this was discussed, so I didn't realize there was a difference wrt the previous behavior. By the way, the terminology gets confusing here because for events, "registration-time" is the time at which you register the event by e.g. calling
Spec-wise it's not more tricky, since the snapshot doesn't need to be held in the FR's |
Ah yes I meant FR
I was strictly taking the POV of the API consumer. It's harder to get the register time semantics manually.
I'm confused, if we want FR |
That's right, it would need to be stored in each cell. But I thought by "the other direction" you meant construction time. |
Co-authored-by: Andreu Botella <abotella@igalia.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
I'd rather use the construction-time AsyncContext snapshot here, just for simplicity. Are there any cases that we're aware of where it's important to have the semantics described in this PR? |
I think using construction-time is the incorrect choice, because observers like this (and DOM observers like I think choosing the context during the call to |
Not passing the callback at the time you register is a big difference from addEventListener. I think the consistency arguments can be made in both directions. Is there any actual utility to the semantics of this patch? If not, I really prefer the option which is simpler from an implementation and specification perspective. Note that it is always possible to build a wrapper around FinalizationRegistry which applies the semantics in this patch. If we can’t come to a conclusion on this thread, let’s discuss this at the next AsyncContext meeting. |
Other observers batch things anyway (which FinalizationRegistry was originally proposed to do as well, but was dropped at some point) so having a "registration time" for DOM observers is just a non-possibility anyway. |
That's interesting. I've always assumed it only batched mutations per-observe calls (so two So it really isn't possible to automatically maintain "registration" time per observe call, and users that need it would have to use a separate |
You don't even need to go that far. class FinalizationRegistryWithSnapshot extends FinalizationRegistry {
constructor(callback) {
super(({snapshot, value}) => {
snapshot.run(callback, value);
})
}
register(target, value, token) {
return super.register(target, {value, snapshot: new AsyncContext.Snapshot()}, token);
}
} |
In the AsyncContext call today, the group apparently decided on construction-time snapshot semantics. (Please correct me if I'm mistaken.) |
I was referencing |
Updated to use creation-time context. |
spec.html
Outdated
<dl class="header"> | ||
</dl> | ||
<emu-alg> | ||
1. Assert: _finalizationRegistry_ has [[Cells]], [[CleanupCallback]], and [[FinalizationRegistryAsyncContextSnapshot]] internal slots. |
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 needs an <ins>
.
This snapshots the ambient AC state when calling
fr.register()
, to be restored when invoking the FR's callback on that registered cell.I also removed our changes of
HostMakeJobCallback
. First, because it felt awkward to refer to theJobCallback
's[[AsyncContextSnapshot]]
insideNewPromiseReactionJob
andNewPromiseResolveThenableJob
. And second, because it actually causes a memory leak withFinalizationRegistry
.The FR calls
HostMakeJobCallback
(causing it to snapshot) during its constructor to prepare the callback to be used for jobs later on. But that snapshot will never be used, we'll only use the registration time snapshot. So I had to move the snapshotting closer intoPerformPromiseThen
.