-
Couldn't load subscription status.
- Fork 54
Handle non-fully-active documents (and destroyed execution contexts) #597
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -866,6 +866,44 @@ it is not always *sufficient* | |
| to protect users from invasive behaviours, | ||
| and seeking [meaningful consent](#consent) is also important. | ||
|
|
||
| <h3 id="handle-destroyed-contexts">Handle non-fully active documents (and destroyed execution contexts)</h3> | ||
|
|
||
| When an <{iframe}> (or similar) is removed or navigated, | ||
| its document stops being [=Document/fully active=] | ||
| and its [=ECMAScript/execution contexts=] can get destroyed. | ||
| However, references to objects from that document | ||
| can remain reachable from other documents | ||
| or from other realms. | ||
|
Comment on lines
+871
to
+876
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As in other PRs, sections should start with the main, positive, advice. Maybe:
(With a link to the specification terms that should be used to detect a destroyed execution context.) |
||
|
|
||
| Specifications should say what happens both at call time | ||
| and after an operation has begun: | ||
| otherwise background work may keep running after a page is gone, | ||
| UI can hang, and user agents diverge in abort/cleanup behavior. | ||
|
|
||
| If the [=relevant global object=]'s [=associated Document=] | ||
| is not [=Document/fully active=] at call time, | ||
| then [=throw=] or return [=a promise rejected with=] | ||
| with {{InvalidStateError}}. | ||
|
|
||
| If, after starting an asynchronous operation, | ||
| that [=associated Document=] becomes non-[=Document/fully active=] | ||
| or the [=relevant global object=]'s [=ECMAScript/execution context=] is destroyed by script, | ||
|
Comment on lines
+889
to
+890
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should link to the algorithm to patch for every asynchronous operation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might say "As a general rule, ..." and maybe mention that special case. The intent here is that if the developer destroys the execution context (e..g, The case you are talking about is different: when it's a user initiated action that forces a document into the BFCache, and hence the document becomes non-fully active. In that case, it makes sense to continue/resume loading things like images or other media (i.e., user needs VS developer wants). |
||
| abort the operation and reject with {{AbortError}}. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem to always be the right advice. E.g. https://html.spec.whatwg.org/multipage/images.html#update-the-image-data just waits for the document to become fully active again. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, but this is a special case... document cannot be made non-fully active by script in way that is recoverable to make them fully active again (i.e., AFAIK, only user action can put a document into a recoverable state, but never via script). |
||
| If the operation presents UI (e.g., a picker, chooser, or prompt), | ||
| dismiss it when the context becomes non-[=Document/fully active=] | ||
| and settle with {{AbortError}}. | ||
|
|
||
| When [=queue a task|queueing=] subsequent work | ||
| (e.g., for an event, settling a promise, a time-based operation), | ||
| include an early exit: | ||
| if the [=associated Document=] is not [=Document/fully active=], | ||
| gracefully terminate the [=task=]. | ||
|
Comment on lines
+896
to
+900
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This paragraph seems to be saying how to accomplish the previous paragraph. Do folks struggle enough with figuring out how to abort an operation that we need to spend words on it? Is this even always the right strategy? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My experience is that yes, and also because there are the tricky edge cases, even implementers might have not thought of these cases. These are where you get weird situations around unspecified behavior. |
||
| Do not rely on garbage collection to define these semantics. | ||
|
|
||
| See also: [[#support-non-fully-active]] for the BFCache case; | ||
| most of the same principles apply to detached iframes | ||
| and other torn-down [=All Execution Contexts/realms=]. | ||
|
Comment on lines
+903
to
+905
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like these sections need to be integrated. Is there a set of instructions that works for all non-fully-active documents, with small extensions that could live in subsections for the bfcache and iframe cases? |
||
|
|
||
| <h3 id="support-non-fully-active">Support non-fully active BFCached documents</h3> | ||
|
|
||
| Specify how your feature behaves | ||
|
|
@@ -1615,7 +1653,7 @@ Unlike dictionaries, interfaces: | |
| (i.e., one can check if it is an `instanceof` a particular class on the global scope), | ||
|
|
||
| Defining an interface also exposes it on the global scope, allowing for the specification of static methods. | ||
| For example, the `canParse()` static method of the URL interface. | ||
| For example, the `canParse()` static method of the URL interface. | ||
|
|
||
| ```JS | ||
| if (URL.canParse(someURL)) { | ||
|
|
||
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.
Is a "destroyed" execution context a concept that can appear in specifications? If not, we should only mention the spec-visible conditions that cause this to happen in implementations.
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.
Yeah, it's basically:
Both destroy the script execution context, causing all the destructors to run... and some of those would resolve pending promises with AbortError, and tear down UIs (e.g., payment sheet, a credential chooser, and so on).