Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's basically:

  1. Removing an iframe.
  2. Navigating an iframe.

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).

However, references to objects from that document
can remain reachable from other documents
or from other realms.
Comment on lines +871 to +876
Copy link
Contributor

Choose a reason for hiding this comment

The 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:

Avoid doing work, and usually cancel ongoing work, on non-[=fully active=] documents and destroyed execution contexts.

(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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should link to the algorithm to patch for every asynchronous operation.

Copy link
Contributor Author

@marcoscaceres marcoscaceres Oct 21, 2025

Choose a reason for hiding this comment

The 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, iframe.remove()), they generally intended (or should be interpreted by the UA) as them wanting to abort all ongoing operations.

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}}.
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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)) {
Expand Down