浏览代码

LibWeb: Give the DOM Window object a (weak) pointer to its JS wrapper

Andreas Kling 5 年之前
父节点
当前提交
cc5cba90db

+ 1 - 0
Libraries/LibWeb/Bindings/WindowObject.cpp

@@ -45,6 +45,7 @@ namespace Bindings {
 WindowObject::WindowObject(Window& impl)
     : m_impl(impl)
 {
+    impl.set_wrapper({}, *this);
 }
 
 void WindowObject::initialize()

+ 4 - 1
Libraries/LibWeb/Bindings/WindowObject.h

@@ -26,13 +26,16 @@
 
 #pragma once
 
+#include <AK/Weakable.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Forward.h>
 
 namespace Web {
 namespace Bindings {
 
-class WindowObject final : public JS::GlobalObject {
+class WindowObject final
+    : public JS::GlobalObject
+    , public Weakable<WindowObject> {
 public:
     explicit WindowObject(Window&);
     virtual void initialize() override;

+ 9 - 6
Libraries/LibWeb/DOM/Window.cpp

@@ -51,6 +51,11 @@ Window::~Window()
 {
 }
 
+void Window::set_wrapper(Badge<Bindings::WindowObject>, Bindings::WindowObject& wrapper)
+{
+    m_wrapper = wrapper.make_weak_ptr();
+}
+
 void Window::alert(const String& message)
 {
     GUI::MessageBox::show(message, "Alert", GUI::MessageBox::Type::Information);
@@ -65,22 +70,20 @@ bool Window::confirm(const String& message)
 void Window::set_interval(JS::Function& callback, i32 interval)
 {
     // FIXME: This leaks the interval timer and makes it unstoppable.
-    (void)Core::Timer::construct(interval, [handle = make_handle(&callback)] {
+    (void)Core::Timer::construct(interval, [this, handle = make_handle(&callback)] {
         auto& function = const_cast<JS::Function&>(static_cast<const JS::Function&>(*handle.cell()));
         auto& interpreter = function.interpreter();
-        auto& window = static_cast<Bindings::WindowObject&>(interpreter.global_object());
-        interpreter.call(function, &window);
+        interpreter.call(function, wrapper());
     }).leak_ref();
 }
 
 void Window::set_timeout(JS::Function& callback, i32 interval)
 {
     // FIXME: This leaks the interval timer and makes it unstoppable.
-    auto& timer = Core::Timer::construct(interval, [handle = make_handle(&callback)] {
+    auto& timer = Core::Timer::construct(interval, [this, handle = make_handle(&callback)] {
         auto& function = const_cast<JS::Function&>(static_cast<const JS::Function&>(*handle.cell()));
         auto& interpreter = function.interpreter();
-        auto& window = static_cast<Bindings::WindowObject&>(interpreter.global_object());
-        interpreter.call(function, &window);
+        interpreter.call(function, wrapper());
     }).leak_ref();
     timer.set_single_shot(true);
 }

+ 6 - 0
Libraries/LibWeb/DOM/Window.h

@@ -52,10 +52,16 @@ public:
     void did_set_location_href(Badge<Bindings::LocationObject>, const String& new_href);
     void did_call_location_reload(Badge<Bindings::LocationObject>);
 
+    Bindings::WindowObject* wrapper() { return m_wrapper; }
+    const Bindings::WindowObject* wrapper() const { return m_wrapper; }
+
+    void set_wrapper(Badge<Bindings::WindowObject>, Bindings::WindowObject&);
+
 private:
     explicit Window(Document&);
 
     Document& m_document;
+    WeakPtr<Bindings::WindowObject> m_wrapper;
 };
 
 }