Przeglądaj źródła

LibWeb: Create and hook up a WindowProxy for each BrowsingContext

All the machinery for this was already in place, we just never created
the actual WindowProxy and installed it.
Andreas Kling 2 lat temu
rodzic
commit
3c548adf9c

+ 4 - 3
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -59,6 +59,7 @@
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
 #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
 #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/Window.h>
+#include <LibWeb/HTML/WindowProxy.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
 #include <LibWeb/Layout/BlockFormattingContext.h>
 #include <LibWeb/Layout/BlockFormattingContext.h>
 #include <LibWeb/Layout/InitialContainingBlock.h>
 #include <LibWeb/Layout/InitialContainingBlock.h>
@@ -177,9 +178,9 @@ JS::NonnullGCPtr<Document> Document::create_and_initialize(Type type, String con
                 window = HTML::Window::create(realm);
                 window = HTML::Window::create(realm);
                 return window;
                 return window;
             },
             },
-            [](JS::Realm&) -> JS::Object* {
-                // FIXME: - For the global this binding, use browsingContext's WindowProxy object.
-                return nullptr;
+            [&](JS::Realm&) -> JS::Object* {
+                // - For the global this binding, use browsingContext's WindowProxy object.
+                return browsing_context->window_proxy();
             });
             });
 
 
         // 6. Let topLevelCreationURL be creationURL.
         // 6. Let topLevelCreationURL be creationURL.

+ 27 - 10
Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp

@@ -19,6 +19,7 @@
 #include <LibWeb/HTML/SandboxingFlagSet.h>
 #include <LibWeb/HTML/SandboxingFlagSet.h>
 #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
 #include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/Window.h>
+#include <LibWeb/HTML/WindowProxy.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
 #include <LibWeb/Layout/BreakNode.h>
 #include <LibWeb/Layout/BreakNode.h>
 #include <LibWeb/Layout/InitialContainingBlock.h>
 #include <LibWeb/Layout/InitialContainingBlock.h>
@@ -136,13 +137,15 @@ NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Pa
     auto realm_execution_context = Bindings::create_a_new_javascript_realm(
     auto realm_execution_context = Bindings::create_a_new_javascript_realm(
         Bindings::main_thread_vm(),
         Bindings::main_thread_vm(),
         [&](JS::Realm& realm) -> JS::Object* {
         [&](JS::Realm& realm) -> JS::Object* {
+            browsing_context->m_window_proxy = realm.heap().allocate<WindowProxy>(realm, realm);
+
             // - For the global object, create a new Window object.
             // - For the global object, create a new Window object.
             window = HTML::Window::create(realm);
             window = HTML::Window::create(realm);
             return window.ptr();
             return window.ptr();
         },
         },
-        [](JS::Realm&) -> JS::Object* {
-            // FIXME: - For the global this binding, use browsingContext's WindowProxy object.
-            return nullptr;
+        [&](JS::Realm&) -> JS::Object* {
+            // - For the global this binding, use browsingContext's WindowProxy object.
+            return browsing_context->m_window_proxy;
         });
         });
 
 
     // 9. Let topLevelCreationURL be about:blank if embedder is null; otherwise embedder's relevant settings object's top-level creation URL.
     // 9. Let topLevelCreationURL be about:blank if embedder is null; otherwise embedder's relevant settings object's top-level creation URL.
@@ -299,7 +302,7 @@ void BrowsingContext::set_active_document(JS::NonnullGCPtr<DOM::Document> docume
     document->set_visibility_state({}, top_level_browsing_context().system_visibility_state());
     document->set_visibility_state({}, top_level_browsing_context().system_visibility_state());
 
 
     // 3. Set browsingContext's active window to window.
     // 3. Set browsingContext's active window to window.
-    m_active_window = window;
+    m_window_proxy->set_window({}, window);
 
 
     // 4. Set window's associated Document to document.
     // 4. Set window's associated Document to document.
     window.set_associated_document(document);
     window.set_associated_document(document);
@@ -792,26 +795,40 @@ bool BrowsingContext::still_on_its_initial_about_blank_document() const
 
 
 DOM::Document const* BrowsingContext::active_document() const
 DOM::Document const* BrowsingContext::active_document() const
 {
 {
-    if (!m_active_window)
+    auto* window = active_window();
+    if (!window)
         return nullptr;
         return nullptr;
-    return &m_active_window->associated_document();
+    return &window->associated_document();
 }
 }
 
 
 DOM::Document* BrowsingContext::active_document()
 DOM::Document* BrowsingContext::active_document()
 {
 {
-    if (!m_active_window)
+    auto* window = active_window();
+    if (!window)
         return nullptr;
         return nullptr;
-    return &m_active_window->associated_document();
+    return &window->associated_document();
 }
 }
 
 
+// https://html.spec.whatwg.org/multipage/browsers.html#active-window
 HTML::Window* BrowsingContext::active_window()
 HTML::Window* BrowsingContext::active_window()
 {
 {
-    return m_active_window;
+    return m_window_proxy->window();
 }
 }
 
 
+// https://html.spec.whatwg.org/multipage/browsers.html#active-window
 HTML::Window const* BrowsingContext::active_window() const
 HTML::Window const* BrowsingContext::active_window() const
 {
 {
-    return m_active_window;
+    return m_window_proxy->window();
+}
+
+HTML::WindowProxy* BrowsingContext::window_proxy()
+{
+    return m_window_proxy.ptr();
+}
+
+HTML::WindowProxy const* BrowsingContext::window_proxy() const
+{
+    return m_window_proxy.ptr();
 }
 }
 
 
 void BrowsingContext::scroll_offset_did_change()
 void BrowsingContext::scroll_offset_did_change()

+ 6 - 1
Userland/Libraries/LibWeb/HTML/BrowsingContext.h

@@ -49,6 +49,9 @@ public:
 
 
     void set_active_document(JS::NonnullGCPtr<DOM::Document>);
     void set_active_document(JS::NonnullGCPtr<DOM::Document>);
 
 
+    HTML::WindowProxy* window_proxy();
+    HTML::WindowProxy const* window_proxy() const;
+
     HTML::Window* active_window();
     HTML::Window* active_window();
     HTML::Window const* active_window() const;
     HTML::Window const* active_window() const;
 
 
@@ -202,10 +205,12 @@ private:
     Optional<HTML::Origin> m_creator_origin;
     Optional<HTML::Origin> m_creator_origin;
 
 
     WeakPtr<HTML::BrowsingContextContainer> m_container;
     WeakPtr<HTML::BrowsingContextContainer> m_container;
-    JS::Handle<HTML::Window> m_active_window;
     Gfx::IntSize m_size;
     Gfx::IntSize m_size;
     Gfx::IntPoint m_viewport_scroll_offset;
     Gfx::IntPoint m_viewport_scroll_offset;
 
 
+    // https://html.spec.whatwg.org/multipage/browsers.html#browsing-context
+    JS::Handle<HTML::WindowProxy> m_window_proxy;
+
     DOM::Position m_cursor_position;
     DOM::Position m_cursor_position;
     RefPtr<Platform::Timer> m_cursor_blink_timer;
     RefPtr<Platform::Timer> m_cursor_blink_timer;
     bool m_cursor_blink_state { false };
     bool m_cursor_blink_state { false };

+ 6 - 2
Userland/Libraries/LibWeb/HTML/WindowProxy.cpp

@@ -20,9 +20,8 @@
 namespace Web::HTML {
 namespace Web::HTML {
 
 
 // 7.4 The WindowProxy exotic object, https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object
 // 7.4 The WindowProxy exotic object, https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object
-WindowProxy::WindowProxy(JS::Realm& realm, Window& window)
+WindowProxy::WindowProxy(JS::Realm& realm)
     : JS::Object(realm, nullptr)
     : JS::Object(realm, nullptr)
-    , m_window(window)
 {
 {
 }
 }
 
 
@@ -256,4 +255,9 @@ void WindowProxy::visit_edges(JS::Cell::Visitor& visitor)
     visitor.visit(m_window.ptr());
     visitor.visit(m_window.ptr());
 }
 }
 
 
+void WindowProxy::set_window(Badge<BrowsingContext>, JS::NonnullGCPtr<Window> window)
+{
+    m_window = window;
+}
+
 }
 }

+ 3 - 6
Userland/Libraries/LibWeb/HTML/WindowProxy.h

@@ -31,14 +31,11 @@ public:
     virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override;
     virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const&) override;
     virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> internal_own_property_keys() const override;
     virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> internal_own_property_keys() const override;
 
 
-    Window& window() const { return const_cast<Window&>(*m_window); }
-
-    // NOTE: Someone will have to replace the wrapped window object as well:
-    // "When the browsing context is navigated, the Window object wrapped by the browsing context's associated WindowProxy object is changed."
-    // I haven't found where that actually happens yet. Make sure to use a Badge<T> guarded setter.
+    JS::GCPtr<Window> window() const { return m_window; }
+    void set_window(Badge<BrowsingContext>, JS::NonnullGCPtr<Window>);
 
 
 private:
 private:
-    WindowProxy(JS::Realm&, Window&);
+    explicit WindowProxy(JS::Realm&);
 
 
     virtual void visit_edges(JS::Cell::Visitor&) override;
     virtual void visit_edges(JS::Cell::Visitor&) override;