mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-19 19:15:19 +00:00
LibWeb/HTML: Use relevant global object's document in History
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Corresponds todba6e7b6c2
and4c0401186c
The spec algorithms now use "the relevant global object's associated document", so remove the concept of the History object itself having an associated document. The spec has also combined the implementations for forward/back/go so I've matched that too.
This commit is contained in:
parent
5b57856eae
commit
141f6cb392
Notes:
github-actions[bot]
2025-04-18 09:08:14 +00:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/141f6cb3929 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4324
3 changed files with 52 additions and 50 deletions
|
@ -3797,7 +3797,7 @@ CSS::StyleSheetList const& Document::style_sheets() const
|
|||
GC::Ref<HTML::History> Document::history()
|
||||
{
|
||||
if (!m_history)
|
||||
m_history = HTML::History::create(realm(), *this);
|
||||
m_history = HTML::History::create(realm());
|
||||
return *m_history;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -17,14 +18,13 @@ namespace Web::HTML {
|
|||
|
||||
GC_DEFINE_ALLOCATOR(History);
|
||||
|
||||
GC::Ref<History> History::create(JS::Realm& realm, DOM::Document& document)
|
||||
GC::Ref<History> History::create(JS::Realm& realm)
|
||||
{
|
||||
return realm.create<History>(realm, document);
|
||||
return realm.create<History>(realm);
|
||||
}
|
||||
|
||||
History::History(JS::Realm& realm, DOM::Document& document)
|
||||
History::History(JS::Realm& realm)
|
||||
: PlatformObject(realm)
|
||||
, m_associated_document(document)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ void History::initialize(JS::Realm& realm)
|
|||
void History::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_associated_document);
|
||||
visitor.visit(m_state);
|
||||
}
|
||||
|
||||
|
@ -61,7 +60,7 @@ WebIDL::ExceptionOr<void> History::replace_state(JS::Value data, String const&,
|
|||
WebIDL::ExceptionOr<u64> History::length() const
|
||||
{
|
||||
// 1. If this's relevant global object's associated Document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
if (!as<Window>(relevant_global_object(*this)).associated_document().is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot perform length on a document that isn't fully active."_string);
|
||||
|
||||
// 2. Return this's length.
|
||||
|
@ -72,7 +71,7 @@ WebIDL::ExceptionOr<u64> History::length() const
|
|||
WebIDL::ExceptionOr<JS::Value> History::state() const
|
||||
{
|
||||
// 1. If this's relevant global object's associated Document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
if (!as<Window>(relevant_global_object(*this)).associated_document().is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot perform state on a document that isn't fully active."_string);
|
||||
|
||||
// 2. Return this's state.
|
||||
|
@ -84,48 +83,49 @@ JS::Value History::unsafe_state() const
|
|||
return m_state;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#delta-traverse
|
||||
WebIDL::ExceptionOr<void> History::delta_traverse(WebIDL::Long delta)
|
||||
{
|
||||
// 1. Let document be history's relevant global object's associated Document.
|
||||
auto& document = as<Window>(relevant_global_object(*this)).associated_document();
|
||||
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!document.is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot perform go on a document that isn't fully active."_string);
|
||||
|
||||
// 3. If delta is 0, then reload document's node navigable, and return.
|
||||
if (delta == 0) {
|
||||
VERIFY(document.navigable());
|
||||
document.navigable()->reload();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 4. Traverse the history by a delta given document's node navigable's traversable navigable, delta, and with
|
||||
// sourceDocument set to document.
|
||||
document.navigable()->traversable_navigable()->traverse_the_history_by_delta(delta, document);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-history-go
|
||||
WebIDL::ExceptionOr<void> History::go(WebIDL::Long delta = 0)
|
||||
{
|
||||
// 1. Let document be this's associated Document.
|
||||
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot perform go on a document that isn't fully active."_string);
|
||||
|
||||
VERIFY(m_associated_document->navigable());
|
||||
|
||||
// 3. If delta is 0, then reload document's node navigable.
|
||||
if (delta == 0)
|
||||
m_associated_document->navigable()->reload();
|
||||
|
||||
// 4. Traverse the history by a delta given document's node navigable's traversable navigable, delta, and with sourceDocument set to document.
|
||||
auto traversable = m_associated_document->navigable()->traversable_navigable();
|
||||
traversable->traverse_the_history_by_delta(delta);
|
||||
|
||||
return {};
|
||||
// The go(delta) method steps are to delta traverse this given delta.
|
||||
return delta_traverse(delta);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-history-back
|
||||
WebIDL::ExceptionOr<void> History::back()
|
||||
{
|
||||
// 1. Let document be this's associated Document.
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
// NOTE: We already did this check in `go` method, so skip the fully active check here.
|
||||
|
||||
// 3. Traverse the history by a delta with −1 and document's browsing context.
|
||||
return go(-1);
|
||||
// The back() method steps are to delta traverse this given −1.
|
||||
return delta_traverse(-1);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-history-forward
|
||||
WebIDL::ExceptionOr<void> History::forward()
|
||||
{
|
||||
// 1. Let document be this's associated Document.
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
// NOTE: We already did this check in `go` method, so skip the fully active check here.
|
||||
|
||||
// 3. Traverse the history by a delta with +1 and document's browsing context.
|
||||
return go(1);
|
||||
// The forward() method steps are to delta traverse this given +1.
|
||||
return delta_traverse(1);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#can-have-its-url-rewritten
|
||||
|
@ -173,11 +173,11 @@ WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value d
|
|||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Let document be history's associated Document.
|
||||
auto& document = m_associated_document;
|
||||
// 1. Let document be history's relevant global object's associated Document.
|
||||
auto& document = as<Window>(relevant_global_object(*this)).associated_document();
|
||||
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!document->is_fully_active())
|
||||
if (!document.is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot perform pushState or replaceState on a document that isn't fully active."_string);
|
||||
|
||||
// 3. Optionally, throw a "SecurityError" DOMException. (For example, the user agent might disallow calls to these
|
||||
|
@ -191,7 +191,7 @@ WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value d
|
|||
auto serialized_data = serialized_data_or_error.is_error() ? MUST(structured_serialize_for_storage(vm, JS::js_null())) : serialized_data_or_error.release_value();
|
||||
|
||||
// 5. Let newURL be document's URL.
|
||||
auto new_url = document->url();
|
||||
auto new_url = document.url();
|
||||
|
||||
// 6. If url is not null or the empty string, then:
|
||||
if (url.has_value() && !url->is_empty()) {
|
||||
|
@ -234,11 +234,12 @@ WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value d
|
|||
WebIDL::ExceptionOr<Bindings::ScrollRestoration> History::scroll_restoration() const
|
||||
{
|
||||
// 1. If this's relevant global object's associated Document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
auto& this_relevant_global_object = as<Window>(relevant_global_object(*this));
|
||||
if (!this_relevant_global_object.associated_document().is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot obtain scroll restoration mode for a document that isn't fully active."_string);
|
||||
|
||||
// 2. Return this's node navigable's active session history entry's scroll restoration mode.
|
||||
auto scroll_restoration_mode = m_associated_document->navigable()->active_session_history_entry()->scroll_restoration_mode();
|
||||
// 2. Return this's relevant global object's navigable's active session history entry's scroll restoration mode.
|
||||
auto scroll_restoration_mode = this_relevant_global_object.navigable()->active_session_history_entry()->scroll_restoration_mode();
|
||||
switch (scroll_restoration_mode) {
|
||||
case ScrollRestorationMode::Auto:
|
||||
return Bindings::ScrollRestoration::Auto;
|
||||
|
@ -252,11 +253,12 @@ WebIDL::ExceptionOr<Bindings::ScrollRestoration> History::scroll_restoration() c
|
|||
WebIDL::ExceptionOr<void> History::set_scroll_restoration(Bindings::ScrollRestoration scroll_restoration)
|
||||
{
|
||||
// 1. If this's relevant global object's associated Document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
auto& this_relevant_global_object = as<Window>(relevant_global_object(*this));
|
||||
if (!this_relevant_global_object.associated_document().is_fully_active())
|
||||
return WebIDL::SecurityError::create(realm(), "Cannot set scroll restoration mode for a document that isn't fully active."_string);
|
||||
|
||||
// 2. Set this's node navigable's active session history entry's scroll restoration mode to the given value.
|
||||
auto active_session_history_entry = m_associated_document->navigable()->active_session_history_entry();
|
||||
// 2. Set this's relevant global object's navigable's active session history entry's scroll restoration mode to the given value.
|
||||
auto active_session_history_entry = this_relevant_global_object.navigable()->active_session_history_entry();
|
||||
switch (scroll_restoration) {
|
||||
case Bindings::ScrollRestoration::Auto:
|
||||
active_session_history_entry->set_scroll_restoration_mode(ScrollRestorationMode::Auto);
|
||||
|
|
|
@ -20,7 +20,7 @@ class History final : public Bindings::PlatformObject {
|
|||
GC_DECLARE_ALLOCATOR(History);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static GC::Ref<History> create(JS::Realm&, DOM::Document&);
|
||||
[[nodiscard]] static GC::Ref<History> create(JS::Realm&);
|
||||
|
||||
virtual ~History() override;
|
||||
|
||||
|
@ -41,14 +41,14 @@ public:
|
|||
void set_state(JS::Value s) { m_state = s; }
|
||||
|
||||
private:
|
||||
History(JS::Realm&, DOM::Document&);
|
||||
History(JS::Realm&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
WebIDL::ExceptionOr<void> delta_traverse(WebIDL::Long delta);
|
||||
|
||||
WebIDL::ExceptionOr<void> shared_history_push_replace_state(JS::Value data, Optional<String> const& url, HistoryHandlingBehavior);
|
||||
|
||||
GC::Ref<DOM::Document> m_associated_document;
|
||||
JS::Value m_state { JS::js_null() };
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue