Browse Source

LibWeb: Expose the location object via Document.location

Both Window.location and Document.location use the same instance of the
Location object. Some sites use it via Window, some via Document.
Luke Wilde 3 years ago
parent
commit
678dd2d180

+ 6 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp

@@ -842,6 +842,11 @@ static void generate_return_statement(SourceGenerator& generator, IDL::Type cons
         return JS::js_null();
 
     return retval.callback.cell();
+)~~~");
+    } else if (return_type.name == "Location") {
+        // Location is special cased as it is already a JS::Object.
+        scoped_generator.append(R"~~~(
+    return JS::Value(retval);
 )~~~");
     } else {
         scoped_generator.append(R"~~~(
@@ -1440,6 +1445,7 @@ void generate_prototype_implementation(IDL::Interface const& interface)
 #include <LibWeb/Bindings/HTMLTableCaptionElementWrapper.h>
 #include <LibWeb/Bindings/HTMLTableSectionElementWrapper.h>
 #include <LibWeb/Bindings/ImageDataWrapper.h>
+#include <LibWeb/Bindings/LocationObject.h>
 #include <LibWeb/Bindings/NodeWrapperFactory.h>
 #include <LibWeb/Bindings/PerformanceTimingWrapper.h>
 #include <LibWeb/Bindings/RangeWrapper.h>

+ 6 - 1
Userland/Libraries/LibWeb/Bindings/WindowObject.cpp

@@ -92,8 +92,12 @@ void WindowObject::initialize_global_object()
     // Legacy
     define_native_accessor("event", event_getter, event_setter, JS::Attribute::Enumerable);
 
+    m_location_object = heap().allocate<LocationObject>(*this, *this);
+
     define_direct_property("navigator", heap().allocate<NavigatorObject>(*this, *this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
-    define_direct_property("location", heap().allocate<LocationObject>(*this, *this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
+
+    // NOTE: location is marked as [LegacyUnforgeable], meaning it isn't configurable.
+    define_direct_property("location", m_location_object, JS::Attribute::Enumerable);
 
     // WebAssembly "namespace"
     define_direct_property("WebAssembly", heap().allocate<WebAssemblyObject>(*this, *this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
@@ -108,6 +112,7 @@ WindowObject::~WindowObject()
 void WindowObject::visit_edges(Visitor& visitor)
 {
     GlobalObject::visit_edges(visitor);
+    visitor.visit(m_location_object);
     for (auto& it : m_prototypes)
         visitor.visit(it.value);
     for (auto& it : m_constructors)

+ 5 - 0
Userland/Libraries/LibWeb/Bindings/WindowObject.h

@@ -30,6 +30,9 @@ public:
 
     Origin origin() const;
 
+    LocationObject* location_object() { return m_location_object; }
+    LocationObject const* location_object() const { return m_location_object; }
+
     JS::Object* web_prototype(const String& class_name) { return m_prototypes.get(class_name).value_or(nullptr); }
     JS::NativeFunction* web_constructor(const String& class_name) { return m_constructors.get(class_name).value_or(nullptr); }
 
@@ -96,6 +99,8 @@ private:
 
     NonnullRefPtr<DOM::Window> m_impl;
 
+    LocationObject* m_location_object;
+
     HashMap<String, JS::Object*> m_prototypes;
     HashMap<String, JS::NativeFunction*> m_constructors;
 };

+ 12 - 0
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -979,4 +979,16 @@ bool Document::is_fully_active() const
     return browsing_context() && browsing_context()->active_document() == this && (browsing_context()->is_top_level() || browsing_context()->container_document()->is_fully_active());
 }
 
+// https://html.spec.whatwg.org/multipage/history.html#dom-document-location
+Bindings::LocationObject* Document::location()
+{
+    // The Document object's location attribute's getter must return this Document object's relevant global object's Location object,
+    // if this Document object is fully active, and null otherwise.
+
+    if (!is_fully_active())
+        return nullptr;
+
+    return window().wrapper()->location_object();
+}
+
 }

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

@@ -279,6 +279,8 @@ public:
 
     NonnullRefPtr<HTML::History> history() const { return m_history; }
 
+    Bindings::LocationObject* location();
+
 private:
     explicit Document(const URL&);
 

+ 3 - 0
Userland/Libraries/LibWeb/DOM/Document.idl

@@ -2,6 +2,9 @@ interface Document : Node {
 
     constructor();
 
+    // FIXME: These attributes currently don't do anything.
+    [PutForwards=href, LegacyUnforgeable] readonly attribute Location? location;
+
     readonly attribute DOMImplementation implementation;
 
     readonly attribute DOMString characterSet;