소스 검색

LibWeb: Implement document ready state

Luke 4 년 전
부모
커밋
124c52b3b5

+ 7 - 0
Libraries/LibWeb/DOM/Document.cpp

@@ -41,6 +41,7 @@
 #include <LibWeb/DOM/DocumentType.h>
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/ElementFactory.h>
+#include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/DOM/Window.h>
 #include <LibWeb/HTML/AttributeNames.h>
@@ -522,4 +523,10 @@ void Document::set_focused_element(Element* element)
         m_layout_root->set_needs_display();
 }
 
+void Document::set_ready_state(const String& ready_state)
+{
+    m_ready_state = ready_state;
+    dispatch_event(Event::create("readystatechange"));
+}
+
 }

+ 5 - 0
Libraries/LibWeb/DOM/Document.h

@@ -174,6 +174,9 @@ public:
     const Document* associated_inert_template_document() const { return m_associated_inert_template_document; }
     void set_associated_inert_template_document(Document& document) { m_associated_inert_template_document = document; }
 
+    const String& ready_state() const { return m_ready_state; }
+    void set_ready_state(const String&);
+
 private:
     virtual RefPtr<LayoutNode> create_layout_node(const CSS::StyleProperties* parent_style) override;
 
@@ -209,6 +212,8 @@ private:
 
     bool m_created_for_appropriate_template_contents { false };
     RefPtr<Document> m_associated_inert_template_document;
+
+    String m_ready_state { "loading" };
 };
 
 }

+ 2 - 0
Libraries/LibWeb/DOM/Document.idl

@@ -17,4 +17,6 @@ interface Document : Node {
     attribute HTMLElement? body;
     readonly attribute HTMLHeadElement? head;
 
+    readonly attribute DOMString readyState;
+
 }

+ 4 - 0
Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp

@@ -156,6 +156,8 @@ void HTMLDocumentParser::run(const URL& url)
 
     // "The end"
 
+    m_document->set_ready_state("interactive");
+
     auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
     for (auto& script : scripts_to_execute_when_parsing_has_finished) {
         script.execute_script();
@@ -167,6 +169,8 @@ void HTMLDocumentParser::run(const URL& url)
     for (auto& script : scripts_to_execute_as_soon_as_possible) {
         script.execute_script();
     }
+
+    m_document->set_ready_state("complete");
 }
 
 void HTMLDocumentParser::process_using_the_rules_for(InsertionMode mode, HTMLToken& token)

+ 31 - 0
Libraries/LibWeb/Tests/HTML/document.readyState.js

@@ -0,0 +1,31 @@
+loadPage("file:///res/html/misc/blank.html");
+
+beforeInitialPageLoad(() => {
+    window.events = [];
+
+    document.addEventListener("readystatechange", () => {
+        window.events.push(document.readyState);
+    });
+
+    document.addEventListener("DOMContentLoaded", () => {
+        test("Ready state should be 'interactive' when 'DOMContentLoaded' fires", () => {
+            expect(document.readyState).toBe("interactive");
+        });
+    });
+
+    test("Ready state should be 'loading' initially", () => {
+        expect(document.readyState).toBe("loading");
+    });
+});
+
+afterInitialPageLoad(() => {
+    test("'interactive' should come before 'complete' and both should have happened", () => {
+        expect(window.events).toHaveLength(2);
+        expect(window.events[0]).toBe("interactive");
+        expect(window.events[1]).toBe("complete");
+    });
+
+    test("Ready state should be 'complete' after loading", () => {
+        expect(document.readyState).toBe("complete");
+    });
+});