Use spec-aligned process for resolving history handling during navigation (#34747)

Makes use of the is_initial_about_blank property on Document in order to
determine whether the navigation should create a history entry, or replace
the current history entry.

Signed-off-by: Shane Handley <shanehandley@fastmail.com>
This commit is contained in:
shanehandley 2024-12-27 13:45:53 +11:00 committed by GitHub
parent 398bafa25d
commit 08a3e61bb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 86 additions and 49 deletions

View file

@ -498,6 +498,8 @@ pub struct Document {
visibility_state: Cell<DocumentVisibilityState>,
/// <https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>
status_code: Option<u16>,
/// <https://html.spec.whatwg.org/multipage/#is-initial-about:blank>
is_initial_about_blank: Cell<bool>,
}
#[allow(non_snake_case)]
@ -3219,6 +3221,7 @@ impl Document {
referrer: Option<String>,
status_code: Option<u16>,
canceller: FetchCanceller,
is_initial_about_blank: bool,
) -> Document {
let url = url.unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap());
@ -3246,6 +3249,7 @@ impl Document {
.unwrap_or(UTF_8);
let has_browsing_context = has_browsing_context == HasBrowsingContext::Yes;
Document {
node: Node::new_document_node(),
document_or_shadow_root: DocumentOrShadowRoot::new(window),
@ -3366,6 +3370,7 @@ impl Document {
fonts: Default::default(),
visibility_state: Cell::new(DocumentVisibilityState::Hidden),
status_code,
is_initial_about_blank: Cell::new(is_initial_about_blank),
}
}
@ -3480,6 +3485,7 @@ impl Document {
referrer: Option<String>,
status_code: Option<u16>,
canceller: FetchCanceller,
is_initial_about_blank: bool,
can_gc: CanGc,
) -> DomRoot<Document> {
Self::new_with_proto(
@ -3497,6 +3503,7 @@ impl Document {
referrer,
status_code,
canceller,
is_initial_about_blank,
can_gc,
)
}
@ -3517,6 +3524,7 @@ impl Document {
referrer: Option<String>,
status_code: Option<u16>,
canceller: FetchCanceller,
is_initial_about_blank: bool,
can_gc: CanGc,
) -> DomRoot<Document> {
let document = reflect_dom_object_with_proto(
@ -3534,6 +3542,7 @@ impl Document {
referrer,
status_code,
canceller,
is_initial_about_blank,
)),
window,
proto,
@ -3657,6 +3666,7 @@ impl Document {
None,
None,
Default::default(),
false,
can_gc,
);
new_doc
@ -4178,6 +4188,11 @@ impl Document {
self.upcast::<EventTarget>()
.fire_bubbling_event(atom!("visibilitychange"), can_gc);
}
/// <https://html.spec.whatwg.org/multipage/#is-initial-about:blank>
pub fn is_initial_about_blank(&self) -> bool {
self.is_initial_about_blank.get()
}
}
impl ProfilerMetadataFactory for Document {
@ -4215,6 +4230,7 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
None,
None,
Default::default(),
false,
can_gc,
))
}
@ -5273,9 +5289,6 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
let entry_responsible_document = GlobalScope::entry().as_window().Document();
// Step 4
// This check is same-origin not same-origin-domain.
// https://github.com/whatwg/html/issues/2282
// https://github.com/whatwg/html/pull/2288
if !self.origin.same_origin(&entry_responsible_document.origin) {
return Err(Error::Security);
}
@ -5333,23 +5346,36 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
// WPT selection/Document-open.html wants us to not clear it
// as of Feb 1 2020
// Step 12
// Step 12. If document is fully active, then:
if self.is_fully_active() {
// Step 12.1. Let newURL be a copy of entryDocument's URL.
let mut new_url = entry_responsible_document.url();
// Step 12.2. If entryDocument is not document, then set newURL's fragment to null.
if entry_responsible_document != DomRoot::from_ref(self) {
new_url.set_fragment(None);
}
// Step 12.3. Run the URL and history update steps with document and newURL.
// TODO: https://github.com/servo/servo/issues/21939
self.set_url(new_url);
}
// Step 13
// Step 13. Set document's is initial about:blank to false.
self.is_initial_about_blank.set(false);
// Step 14. If document's iframe load in progress flag is set, then set document's mute
// iframe load flag.
// TODO: https://github.com/servo/servo/issues/21938
// Step 14
// Step 15: Set document to no-quirks mode.
self.set_quirks_mode(QuirksMode::NoQuirks);
// Step 15
// Step 16. Create a new HTML parser and associate it with document. This is a
// script-created parser (meaning that it can be closed by the document.open() and
// document.close() methods, and that the tokenizer will wait for an explicit call to
// document.close() before emitting an end-of-file token). The encoding confidence is
// irrelevant.
let resource_threads = self
.window
.upcast::<GlobalScope>()
@ -5359,13 +5385,14 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
DocumentLoader::new_with_threads(resource_threads, Some(self.url()));
ServoParser::parse_html_script_input(self, self.url());
// Step 16
// Step 17. Set the insertion point to point at just before the end of the input stream
// (which at this point will be empty).
// Handled when creating the parser in step 16
// Step 18. Update the current document readiness of document to "loading".
self.ready_state.set(DocumentReadyState::Loading);
// Step 17
// Handled when creating the parser in step 15
// Step 18
// Step 19. Return document.
Ok(DomRoot::from_ref(self))
}