Browse Source

LibWeb: Ignore window-forwarded document.body.onfoo in detached DOM

Normally, assigning to e.g document.body.onload will forward to
window.onload. However, in a detached DOM tree, there is no associated
window, so we have nowhere to forward to, making this a no-op.

The bulk of this change is making Document::window() return a nullable
pointer, as documents created by DOMParser or DOMImplementation do not
have an associated window object, and so must be able to return null
from here.
Andreas Kling 1 year ago
parent
commit
b98a2be96b
28 changed files with 92 additions and 61 deletions
  1. 1 0
      Tests/LibWeb/Text/expected/HTML/Window-event-handler-in-detached-DOM.txt
  2. 10 0
      Tests/LibWeb/Text/input/HTML/Window-event-handler-in-detached-DOM.html
  3. 1 1
      Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp
  4. 5 1
      Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp
  5. 3 1
      Userland/Libraries/LibWeb/CSS/Parser/ParsingContext.cpp
  6. 14 6
      Userland/Libraries/LibWeb/DOM/Document.cpp
  7. 2 2
      Userland/Libraries/LibWeb/DOM/Document.h
  8. 3 3
      Userland/Libraries/LibWeb/DOM/EventTarget.cpp
  9. 2 2
      Userland/Libraries/LibWeb/HTML/Focus.cpp
  10. 11 8
      Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp
  11. 1 1
      Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h
  12. 2 2
      Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp
  13. 2 2
      Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h
  14. 1 1
      Userland/Libraries/LibWeb/HTML/HTMLElement.h
  15. 2 2
      Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp
  16. 2 2
      Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h
  17. 1 1
      Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
  18. 1 1
      Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp
  19. 3 3
      Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
  20. 1 1
      Userland/Libraries/LibWeb/HTML/Window.cpp
  21. 2 2
      Userland/Libraries/LibWeb/HTML/Window.h
  22. 11 8
      Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp
  23. 1 1
      Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h
  24. 1 1
      Userland/Libraries/LibWeb/MathML/MathMLElement.h
  25. 1 1
      Userland/Libraries/LibWeb/ResizeObserver/ResizeObserverSize.cpp
  26. 4 4
      Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp
  27. 1 1
      Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp
  28. 3 3
      Userland/Services/WebContent/ConnectionFromClient.cpp

+ 1 - 0
Tests/LibWeb/Text/expected/HTML/Window-event-handler-in-detached-DOM.txt

@@ -0,0 +1 @@
+PASS (didn't crash)

+ 10 - 0
Tests/LibWeb/Text/input/HTML/Window-event-handler-in-detached-DOM.html

@@ -0,0 +1,10 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        var parser = new DOMParser();
+        var doc = parser.parseFromString("", "text/html");
+        var body = doc.createElement("body");
+        body.onblur = null;
+        println("PASS (didn't crash)");
+    });
+</script>

+ 1 - 1
Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp

@@ -19,7 +19,7 @@ JS_DEFINE_ALLOCATOR(DocumentTimeline);
 JS::NonnullGCPtr<DocumentTimeline> DocumentTimeline::create(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time)
 {
     auto timeline = realm.heap().allocate<DocumentTimeline>(realm, realm, document, origin_time);
-    timeline->set_current_time(document.window().performance()->now());
+    timeline->set_current_time(document.window()->performance()->now());
     return timeline;
 }
 

+ 5 - 1
Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp

@@ -60,9 +60,13 @@ bool MediaQueryList::matches() const
 
 bool MediaQueryList::evaluate()
 {
+    auto window = m_document->window();
+    if (!window)
+        return false;
+
     bool now_matches = false;
     for (auto& media : m_media) {
-        now_matches = now_matches || media->evaluate(m_document->window());
+        now_matches = now_matches || media->evaluate(*window);
     }
 
     return now_matches;

+ 3 - 1
Userland/Libraries/LibWeb/CSS/Parser/ParsingContext.cpp

@@ -56,7 +56,9 @@ URL ParsingContext::complete_url(StringView relative_url) const
 
 HTML::Window const* ParsingContext::window() const
 {
-    return m_document && m_document->default_view() ? &m_document->window() : nullptr;
+    if (!m_document)
+        return nullptr;
+    return m_document->window();
 }
 
 }

+ 14 - 6
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -638,7 +638,7 @@ WebIDL::ExceptionOr<JS::GCPtr<HTML::WindowProxy>> Document::open(StringView url,
         return WebIDL::InvalidAccessError::create(realm(), "Cannot perform open on a document that isn't fully active."_fly_string);
 
     // 2. Return the result of running the window open steps with url, name, and features.
-    return window().open_impl(url, name, features);
+    return window()->open_impl(url, name, features);
 }
 
 // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#closing-the-input-stream
@@ -2273,7 +2273,7 @@ JS::GCPtr<HTML::Location> Document::location()
     if (!is_fully_active())
         return nullptr;
 
-    return window().location();
+    return window()->location();
 }
 
 // https://html.spec.whatwg.org/multipage/interaction.html#dom-document-hidden
@@ -2330,7 +2330,7 @@ void Document::run_the_resize_steps()
         return;
     m_last_viewport_size = viewport_size;
 
-    window().dispatch_event(DOM::Event::create(realm(), UIEvents::EventNames::resize));
+    window()->dispatch_event(DOM::Event::create(realm(), UIEvents::EventNames::resize));
 
     schedule_layout_update();
 }
@@ -2401,9 +2401,13 @@ void Document::evaluate_media_queries_and_report_changes()
 
 void Document::evaluate_media_rules()
 {
+    auto window = this->window();
+    if (!window)
+        return;
+
     bool any_media_queries_changed_match_state = false;
     for (auto& style_sheet : style_sheets().sheets()) {
-        if (style_sheet->evaluate_media_queries(window()))
+        if (style_sheet->evaluate_media_queries(*window))
             any_media_queries_changed_match_state = true;
     }
 
@@ -3305,6 +3309,10 @@ void Document::unregister_resize_observer(Badge<ResizeObserver::ResizeObserver>,
 // https://www.w3.org/TR/intersection-observer/#queue-an-intersection-observer-task
 void Document::queue_intersection_observer_task()
 {
+    auto window = this->window();
+    if (!window)
+        return;
+
     // 1. If document’s IntersectionObserverTaskQueued flag is set to true, return.
     if (m_intersection_observer_task_queued)
         return;
@@ -3313,7 +3321,7 @@ void Document::queue_intersection_observer_task()
     m_intersection_observer_task_queued = true;
 
     // 3. Queue a task on the IntersectionObserver task source associated with the document's event loop to notify intersection observers.
-    HTML::queue_global_task(HTML::Task::Source::IntersectionObserver, window(), [this]() {
+    HTML::queue_global_task(HTML::Task::Source::IntersectionObserver, *window, [this]() {
         auto& realm = this->realm();
 
         // https://www.w3.org/TR/intersection-observer/#notify-intersection-observers
@@ -4039,7 +4047,7 @@ void Document::ensure_animation_timer()
                 return;
             }
 
-            update_animations_and_send_events(window().performance()->now());
+            update_animations_and_send_events(window()->performance()->now());
 
             for (auto& timeline : m_associated_animation_timelines) {
                 for (auto& animation : timeline->associated_animations())

+ 2 - 2
Userland/Libraries/LibWeb/DOM/Document.h

@@ -317,7 +317,7 @@ public:
     HTML::DocumentReadyState readiness() const { return m_readiness; }
     void update_readiness(HTML::DocumentReadyState);
 
-    HTML::Window& window() const { return const_cast<HTML::Window&>(*m_window); }
+    [[nodiscard]] JS::GCPtr<HTML::Window> window() const { return m_window; }
 
     void set_window(HTML::Window&);
 
@@ -616,7 +616,7 @@ protected:
 
 private:
     // ^HTML::GlobalEventHandlers
-    virtual EventTarget& global_event_handlers_to_event_target(FlyString const&) final { return *this; }
+    virtual JS::GCPtr<EventTarget> global_event_handlers_to_event_target(FlyString const&) final { return *this; }
 
     void tear_down_layout_tree();
 

+ 3 - 3
Userland/Libraries/LibWeb/DOM/EventTarget.cpp

@@ -327,7 +327,7 @@ static EventTarget* determine_target_of_event_handler(EventTarget& event_target,
         return nullptr;
 
     // 4. Return eventTarget's node document's relevant global object.
-    return &event_target_element.document().window();
+    return &verify_cast<EventTarget>(HTML::relevant_global_object(event_target_element.document()));
 }
 
 // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes:event-handler-idl-attributes-2
@@ -807,8 +807,8 @@ bool EventTarget::dispatch_event(Event& event)
             static_cast<HTML::Window*>(this)->set_last_activation_timestamp(current_time);
         } else if (is<DOM::Element>(this)) {
             auto const* element = static_cast<DOM::Element const*>(this);
-            auto& window = element->document().window();
-            window.set_last_activation_timestamp(current_time);
+            if (auto window = element->document().window())
+                window->set_last_activation_timestamp(current_time);
         }
     }
 

+ 2 - 2
Userland/Libraries/LibWeb/HTML/Focus.cpp

@@ -55,7 +55,7 @@ static void run_focus_update_steps(Vector<JS::Handle<DOM::Node>> old_chain, Vect
             blur_event_target = entry.ptr();
         } else if (is<DOM::Document>(*entry)) {
             // If entry is a Document object, let blur event target be that Document object's relevant global object.
-            blur_event_target = &static_cast<DOM::Document&>(*entry).window();
+            blur_event_target = static_cast<DOM::Document&>(*entry).window();
         }
 
         // 3. If entry is the last entry in old chain, and entry is an Element,
@@ -105,7 +105,7 @@ static void run_focus_update_steps(Vector<JS::Handle<DOM::Node>> old_chain, Vect
             focus_event_target = entry.ptr();
         } else if (is<DOM::Document>(*entry)) {
             // If entry is a Document object, let focus event target be that Document object's relevant global object.
-            focus_event_target = &static_cast<DOM::Document&>(*entry).window();
+            focus_event_target = static_cast<DOM::Document&>(*entry).window();
         }
 
         // 3. If entry is the last entry in new chain, and entry is an Element,

+ 11 - 8
Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp

@@ -12,14 +12,17 @@
 namespace Web::HTML {
 
 #undef __ENUMERATE
-#define __ENUMERATE(attribute_name, event_name)                                                           \
-    void GlobalEventHandlers::set_##attribute_name(WebIDL::CallbackType* value)                           \
-    {                                                                                                     \
-        global_event_handlers_to_event_target(event_name).set_event_handler_attribute(event_name, value); \
-    }                                                                                                     \
-    WebIDL::CallbackType* GlobalEventHandlers::attribute_name()                                           \
-    {                                                                                                     \
-        return global_event_handlers_to_event_target(event_name).event_handler_attribute(event_name);     \
+#define __ENUMERATE(attribute_name, event_name)                                    \
+    void GlobalEventHandlers::set_##attribute_name(WebIDL::CallbackType* value)    \
+    {                                                                              \
+        if (auto event_target = global_event_handlers_to_event_target(event_name)) \
+            event_target->set_event_handler_attribute(event_name, value);          \
+    }                                                                              \
+    WebIDL::CallbackType* GlobalEventHandlers::attribute_name()                    \
+    {                                                                              \
+        if (auto event_target = global_event_handlers_to_event_target(event_name)) \
+            return event_target->event_handler_attribute(event_name);              \
+        return nullptr;                                                            \
     }
 ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
 #undef __ENUMERATE

+ 1 - 1
Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h

@@ -94,7 +94,7 @@ public:
 #undef __ENUMERATE
 
 protected:
-    virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) = 0;
+    virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) = 0;
 };
 
 }

+ 2 - 2
Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp

@@ -94,7 +94,7 @@ void HTMLBodyElement::attribute_changed(FlyString const& name, Optional<String>
 #undef __ENUMERATE
 }
 
-DOM::EventTarget& HTMLBodyElement::global_event_handlers_to_event_target(FlyString const& event_name)
+JS::GCPtr<DOM::EventTarget> HTMLBodyElement::global_event_handlers_to_event_target(FlyString const& event_name)
 {
     // NOTE: This is a little weird, but IIUC document.body.onload actually refers to window.onload
     // NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
@@ -104,7 +104,7 @@ DOM::EventTarget& HTMLBodyElement::global_event_handlers_to_event_target(FlyStri
     return *this;
 }
 
-DOM::EventTarget& HTMLBodyElement::window_event_handlers_to_event_target()
+JS::GCPtr<DOM::EventTarget> HTMLBodyElement::window_event_handlers_to_event_target()
 {
     // All WindowEventHandlers on HTMLFrameSetElement (e.g. document.body.onrejectionhandled) are mapped to window.on{event}.
     // NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.

+ 2 - 2
Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h

@@ -38,10 +38,10 @@ private:
     virtual void initialize(JS::Realm&) override;
 
     // ^HTML::GlobalEventHandlers
-    virtual EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) override;
+    virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) override;
 
     // ^HTML::WindowEventHandlers
-    virtual EventTarget& window_event_handlers_to_event_target() override;
+    virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() override;
 
     RefPtr<CSS::ImageStyleValue> m_background_style_value;
 };

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLElement.h

@@ -82,7 +82,7 @@ private:
     virtual bool is_html_element() const final { return true; }
 
     // ^HTML::GlobalEventHandlers
-    virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; }
+    virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }
     virtual void did_receive_focus() override;
 
     JS::GCPtr<DOMStringMap> m_dataset;

+ 2 - 2
Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.cpp

@@ -38,7 +38,7 @@ void HTMLFrameSetElement::attribute_changed(FlyString const& name, Optional<Stri
 #undef __ENUMERATE
 }
 
-DOM::EventTarget& HTMLFrameSetElement::global_event_handlers_to_event_target(FlyString const& event_name)
+JS::GCPtr<DOM::EventTarget> HTMLFrameSetElement::global_event_handlers_to_event_target(FlyString const& event_name)
 {
     // NOTE: This is a little weird, but IIUC document.body.onload actually refers to window.onload
     // NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.
@@ -48,7 +48,7 @@ DOM::EventTarget& HTMLFrameSetElement::global_event_handlers_to_event_target(Fly
     return *this;
 }
 
-DOM::EventTarget& HTMLFrameSetElement::window_event_handlers_to_event_target()
+JS::GCPtr<DOM::EventTarget> HTMLFrameSetElement::window_event_handlers_to_event_target()
 {
     // All WindowEventHandlers on HTMLFrameSetElement (e.g. document.body.onrejectionhandled) are mapped to window.on{event}.
     // NOTE: document.body can return either a HTMLBodyElement or HTMLFrameSetElement, so both these elements must support this mapping.

+ 2 - 2
Userland/Libraries/LibWeb/HTML/HTMLFrameSetElement.h

@@ -28,10 +28,10 @@ private:
     virtual void attribute_changed(FlyString const&, Optional<String> const&) override;
 
     // ^HTML::GlobalEventHandlers
-    virtual EventTarget& global_event_handlers_to_event_target(FlyString const& event_name) override;
+    virtual JS::GCPtr<EventTarget> global_event_handlers_to_event_target(FlyString const& event_name) override;
 
     // ^HTML::WindowEventHandlers
-    virtual EventTarget& window_event_handlers_to_event_target() override;
+    virtual JS::GCPtr<EventTarget> window_event_handlers_to_event_target() override;
 };
 
 }

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp

@@ -941,7 +941,7 @@ static void update_the_source_set(DOM::Element& element)
         if (child->has_attribute(HTML::AttributeNames::media)) {
             auto media_query = parse_media_query(CSS::Parser::ParsingContext { element.document() },
                 child->get_attribute_value(HTML::AttributeNames::media));
-            if (!media_query || !media_query->evaluate(element.document().window())) {
+            if (!media_query || !element.document().window() || !media_query->evaluate(*element.document().window())) {
                 continue;
             }
         }

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp

@@ -64,7 +64,7 @@ void HTMLMetaElement::inserted()
         auto media = attribute(AttributeNames::media);
         if (media.has_value()) {
             auto query = parse_media_query(context, media.value());
-            if (!query->evaluate(document().window()))
+            if (document().window() && !query->evaluate(*document().window()))
                 return;
         }
 

+ 3 - 3
Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp

@@ -328,7 +328,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
             return;
 
         // 3. Let window be the Document's relevant global object.
-        JS::NonnullGCPtr<Window> window = document->window();
+        auto& window = verify_cast<Window>(relevant_global_object(*document));
 
         // 4. Set the Document's load timing info's load event start time to the current high resolution time given window.
         document->load_timing_info().load_event_start_time = HighResolutionTime::unsafe_shared_current_time();
@@ -336,7 +336,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
         // 5. Fire an event named load at window, with legacy target override flag set.
         // FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
         //        We should reorganize this so that the flag appears explicitly here instead.
-        window->dispatch_event(DOM::Event::create(document->realm(), HTML::EventNames::load));
+        window.dispatch_event(DOM::Event::create(document->realm(), HTML::EventNames::load));
 
         // FIXME: 6. Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL.
 
@@ -352,7 +352,7 @@ void HTMLParser::the_end(JS::NonnullGCPtr<DOM::Document> document, JS::GCPtr<HTM
         document->set_page_showing(true);
 
         // 11. Fire a page transition event named pageshow at window with false.
-        window->fire_a_page_transition_event(HTML::EventNames::pageshow, false);
+        window.fire_a_page_transition_event(HTML::EventNames::pageshow, false);
 
         // 12. Completely finish loading the Document.
         document->completely_finish_loading();

+ 1 - 1
Userland/Libraries/LibWeb/HTML/Window.cpp

@@ -79,7 +79,7 @@ JS_DEFINE_ALLOCATOR(Window);
 void run_animation_frame_callbacks(DOM::Document& document, double now)
 {
     // FIXME: Bring this closer to the spec.
-    document.window().animation_frame_callback_driver().run(now);
+    document.window()->animation_frame_callback_driver().run(now);
 }
 
 class IdleCallback : public RefCounted<IdleCallback> {

+ 2 - 2
Userland/Libraries/LibWeb/HTML/Window.h

@@ -218,10 +218,10 @@ private:
     virtual void finalize() override;
 
     // ^HTML::GlobalEventHandlers
-    virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; }
+    virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }
 
     // ^HTML::WindowEventHandlers
-    virtual DOM::EventTarget& window_event_handlers_to_event_target() override { return *this; }
+    virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() override { return *this; }
 
     void invoke_idle_callbacks();
 

+ 11 - 8
Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp

@@ -11,14 +11,17 @@
 namespace Web::HTML {
 
 #undef __ENUMERATE
-#define __ENUMERATE(attribute_name, event_name)                                                 \
-    void WindowEventHandlers::set_##attribute_name(WebIDL::CallbackType* value)                 \
-    {                                                                                           \
-        window_event_handlers_to_event_target().set_event_handler_attribute(event_name, value); \
-    }                                                                                           \
-    WebIDL::CallbackType* WindowEventHandlers::attribute_name()                                 \
-    {                                                                                           \
-        return window_event_handlers_to_event_target().event_handler_attribute(event_name);     \
+#define __ENUMERATE(attribute_name, event_name)                                 \
+    void WindowEventHandlers::set_##attribute_name(WebIDL::CallbackType* value) \
+    {                                                                           \
+        if (auto event_target = window_event_handlers_to_event_target())        \
+            event_target->set_event_handler_attribute(event_name, value);       \
+    }                                                                           \
+    WebIDL::CallbackType* WindowEventHandlers::attribute_name()                 \
+    {                                                                           \
+        if (auto event_target = window_event_handlers_to_event_target())        \
+            return event_target->event_handler_attribute(event_name);           \
+        return nullptr;                                                         \
     }
 ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE)
 #undef __ENUMERATE

+ 1 - 1
Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h

@@ -41,7 +41,7 @@ public:
 #undef __ENUMERATE
 
 protected:
-    virtual DOM::EventTarget& window_event_handlers_to_event_target() = 0;
+    virtual JS::GCPtr<DOM::EventTarget> window_event_handlers_to_event_target() = 0;
 };
 
 }

+ 1 - 1
Userland/Libraries/LibWeb/MathML/MathMLElement.h

@@ -29,7 +29,7 @@ public:
     void blur();
 
 protected:
-    virtual DOM::EventTarget& global_event_handlers_to_event_target(FlyString const&) override { return *this; }
+    virtual JS::GCPtr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }
 
 private:
     MathMLElement(DOM::Document&, DOM::QualifiedName);

+ 1 - 1
Userland/Libraries/LibWeb/ResizeObserver/ResizeObserverSize.cpp

@@ -44,7 +44,7 @@ JS::NonnullGCPtr<ResizeObserverSize> ResizeObserverSize::calculate_box_size(JS::
             computed_size->set_block_size(paintable_box.content_height().to_double());
             break;
         case Bindings::ResizeObserverBoxOptions::DevicePixelContentBox: {
-            auto device_pixel_ratio = target.document().window().device_pixel_ratio();
+            auto device_pixel_ratio = target.document().window()->device_pixel_ratio();
             // 1. Set computedSize’s inlineSize attribute to target’s content area inline length, in integral device pixels.
             computed_size->set_inline_size(paintable_box.border_box_width().to_double() * device_pixel_ratio);
             // 2. Set computedSize’s blockSize attribute to target’s content area block length, in integral device pixels.

+ 4 - 4
Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp

@@ -227,15 +227,15 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(Web::Page& page,
 
     // 1. Let window be the associated window of the current browsing context’s active document.
     // FIXME: This will need adjusting when WebDriver supports frames.
-    auto& window = page.top_level_browsing_context().active_document()->window();
+    auto window = page.top_level_browsing_context().active_document()->window();
 
     // 2. Let environment settings be the environment settings object for window.
-    auto& environment_settings = Web::HTML::relevant_settings_object(window);
+    auto& environment_settings = Web::HTML::relevant_settings_object(*window);
 
     // 3. Let global scope be environment settings realm’s global environment.
     auto& global_scope = environment_settings.realm().global_environment();
 
-    auto& realm = window.realm();
+    auto& realm = window->realm();
 
     bool contains_direct_call_to_eval = false;
     auto source_text = ByteString::formatted("function() {{ {} }}", body);
@@ -271,7 +271,7 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(Web::Page& page,
     // 9. Let completion be Function.[[Call]](window, parameters) with function as the this value.
     // NOTE: This is not entirely clear, but I don't think they mean actually passing `function` as
     // the this value argument, but using it as the object [[Call]] is executed on.
-    auto completion = function->internal_call(&window, move(parameters));
+    auto completion = function->internal_call(window, move(parameters));
 
     // 10. Clean up after running a callback with environment settings.
     environment_settings.clean_up_after_running_callback();

+ 1 - 1
Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp

@@ -54,7 +54,7 @@ Response capture_element_screenshot(Painter const& painter, Page& page, DOM::Ele
 {
     Optional<Response> encoded_string_or_error;
 
-    element.document().window().animation_frame_callback_driver().add([&](auto) {
+    element.document().window()->animation_frame_callback_driver().add([&](auto) {
         auto viewport_rect = page.top_level_traversable()->viewport_rect();
         rect.intersect(page.enclosing_device_rect(viewport_rect).to_type<int>());
 

+ 3 - 3
Userland/Services/WebContent/ConnectionFromClient.cpp

@@ -436,7 +436,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString const& request,
 
     if (request == "dump-local-storage") {
         if (auto* document = page.page().top_level_browsing_context().active_document())
-            document->window().local_storage().release_value_but_fixme_should_propagate_errors()->dump();
+            document->window()->local_storage().release_value_but_fixme_should_propagate_errors()->dump();
         return;
     }
 
@@ -1086,7 +1086,7 @@ Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient:
     auto& page = maybe_page.release_value();
 
     auto* document = page.page().top_level_browsing_context().active_document();
-    auto local_storage = document->window().local_storage().release_value_but_fixme_should_propagate_errors();
+    auto local_storage = document->window()->local_storage().release_value_but_fixme_should_propagate_errors();
     return local_storage->map();
 }
 
@@ -1100,7 +1100,7 @@ Messages::WebContentServer::GetSessionStorageEntriesResponse ConnectionFromClien
     auto& page = maybe_page.release_value();
 
     auto* document = page.page().top_level_browsing_context().active_document();
-    auto session_storage = document->window().session_storage().release_value_but_fixme_should_propagate_errors();
+    auto session_storage = document->window()->session_storage().release_value_but_fixme_should_propagate_errors();
     return session_storage->map();
 }