Skip to content

Navigation API traversal: reject the finished promise when the traversable's navigate event is canceled (canceled-by-navigate) #13166

Open

Description

@jnjaeschke

What is the issue with the HTML Standard?

perform a navigation API traversal step 12.5 only handles canceled-by-beforeunload, and step 12.6 handles initiator-disallowed. Check if unloading is canceled can also return canceled-by-navigate. That happens when the traversable's traverse navigate event is canceled (step 4.3.4.5). Nothing in the algorithm handles that result.

The note after step 12.6 says the inner navigate event firing algorithm takes care of this case. It does so by aborting the ongoing navigation in step 28.2. That only reaches the Navigation object the event fired at, which is the traversable's. It does not reach the Navigation of the subframe that called traverseTo(), back() or forward().

Repro:

  1. A top-level page has an iframe, and both have a same-document entry.
  2. The top-level page sets navigation.onnavigate = e => e.preventDefault().
  3. The iframe calls iframe.navigation.traverseTo(key).
  4. The traversable's navigate event is canceled, so finalStatus is canceled-by-navigate.
  5. Step 12.5 does not match, so the iframe's committed and finished promises stay pending.
  6. The iframe's apiMethodTracker also stays in its upcoming traverse API method trackers. A later traverseTo() with the same key then returns the stale tracker's result at step 6, and never queues a new traversal.

Proposal: In step 12.5, also match canceled-by-navigate:

If result is "canceled-by-beforeunload" or "canceled-by-navigate", then queue a global task ... to reject the finished promise for apiMethodTracker with a new "AbortError" DOMException ...

The note should then say that the traversable's own tracker is aborted by the inner algorithm, and that the initiating subframe's tracker is rejected here.

An intercepted traverse navigate event (finalStatus is continue) is unaffected. The traversal resumes, and the promises settle when it commits.

WPT already expects the rejection: navigation-api/navigate-event/navigation-traverseTo-in-iframe-same-document-preventDefault.html has the parent call preventDefault() on the traverse navigate event, then asserts the iframe's committed and finished reject with AbortError ("When the top window blocks the traversal, it should be blocked in the iframe as well, and the traversal promises in the iframe should be rejected."). The spec as written leaves those promises pending, so it needs to follow the test.

cc @farre @theIDinside @noamr

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions