Sfoglia il codice sorgente

LibWeb: Update "appropriate template contents owner document" AO

This was moved from HTMLTemplateElement to Document at some point,
so let's match the spec and move it here too.
Andreas Kling 2 anni fa
parent
commit
a4de30de5a

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

@@ -327,6 +327,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
     visitor.visit(m_implementation.ptr());
     visitor.visit(m_current_script.ptr());
     visitor.visit(m_associated_inert_template_document.ptr());
+    visitor.visit(m_appropriate_template_contents_owner_document);
     visitor.visit(m_pending_parsing_blocking_script.ptr());
     visitor.visit(m_history.ptr());
 
@@ -2265,4 +2266,29 @@ void Document::did_stop_being_active_document_in_browsing_context(Badge<HTML::Br
     tear_down_layout_tree();
 }
 
+// https://html.spec.whatwg.org/multipage/scripting.html#appropriate-template-contents-owner-document
+JS::NonnullGCPtr<DOM::Document> Document::appropriate_template_contents_owner_document()
+{
+    // 1. If doc is not a Document created by this algorithm, then:
+    if (!created_for_appropriate_template_contents()) {
+        // 1. If doc does not yet have an associated inert template document, then:
+        if (!m_associated_inert_template_document) {
+            // 1. Let new doc be a new Document (whose browsing context is null). This is "a Document created by this algorithm" for the purposes of the step above.
+            auto new_document = DOM::Document::create(realm());
+            new_document->m_created_for_appropriate_template_contents = true;
+
+            // 2. If doc is an HTML document, mark new doc as an HTML document also.
+            if (document_type() == Type::HTML)
+                new_document->set_document_type(Type::HTML);
+
+            // 3. Let doc's associated inert template document be new doc.
+            m_associated_inert_template_document = new_document;
+        }
+        // 2. Set doc to doc's associated inert template document.
+        return *m_associated_inert_template_document;
+    }
+    // 2. Return doc.
+    return *this;
+}
+
 }

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

@@ -277,11 +277,8 @@ public:
     void set_active_element(Element*);
 
     bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; }
-    void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; }
 
-    Document* associated_inert_template_document() { return m_associated_inert_template_document.ptr(); }
-    Document const* associated_inert_template_document() const { return m_associated_inert_template_document.ptr(); }
-    void set_associated_inert_template_document(Document& document) { m_associated_inert_template_document = &document; }
+    JS::NonnullGCPtr<Document> appropriate_template_contents_owner_document();
 
     String ready_state() const;
     void update_readiness(HTML::DocumentReadyState);
@@ -505,6 +502,7 @@ private:
 
     bool m_created_for_appropriate_template_contents { false };
     JS::GCPtr<Document> m_associated_inert_template_document;
+    JS::GCPtr<Document> m_appropriate_template_contents_owner_document;
 
     HTML::DocumentReadyState m_readiness { HTML::DocumentReadyState::Loading };
     String m_content_type { "application/xml" };

+ 12 - 23
Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp

@@ -14,42 +14,31 @@ HTMLTemplateElement::HTMLTemplateElement(DOM::Document& document, DOM::Qualified
     : HTMLElement(document, move(qualified_name))
 {
     set_prototype(&Bindings::cached_web_prototype(realm(), "HTMLTemplateElement"));
-
-    m_content = heap().allocate<DOM::DocumentFragment>(realm(), appropriate_template_contents_owner_document(document));
-    m_content->set_host(this);
 }
 
 HTMLTemplateElement::~HTMLTemplateElement() = default;
 
-void HTMLTemplateElement::visit_edges(Cell::Visitor& visitor)
+void HTMLTemplateElement::initialize(JS::Realm& realm)
 {
-    Base::visit_edges(visitor);
-    visitor.visit(m_content.ptr());
+    Base::initialize(realm);
+    m_content = heap().allocate<DOM::DocumentFragment>(realm, m_document->appropriate_template_contents_owner_document());
+    m_content->set_host(this);
 }
 
-DOM::Document& HTMLTemplateElement::appropriate_template_contents_owner_document(DOM::Document& document)
+void HTMLTemplateElement::visit_edges(Cell::Visitor& visitor)
 {
-    if (!document.created_for_appropriate_template_contents()) {
-        if (!document.associated_inert_template_document()) {
-            auto new_document = DOM::Document::create(realm());
-            new_document->set_created_for_appropriate_template_contents(true);
-            new_document->set_document_type(document.document_type());
-
-            document.set_associated_inert_template_document(new_document);
-        }
-
-        return *document.associated_inert_template_document();
-    }
-
-    return document;
+    Base::visit_edges(visitor);
+    visitor.visit(m_content.ptr());
 }
 
 // https://html.spec.whatwg.org/multipage/scripting.html#the-template-element:concept-node-adopt-ext
 void HTMLTemplateElement::adopted_from(DOM::Document&)
 {
-    // NOTE: It seems the spec has been changed since appropriate_template_contents_owner_document was written above.
-    //       That function is now part of document, which ends up returning associated_inert_template_document in the new version anyway.
-    appropriate_template_contents_owner_document(document()).adopt_node(content());
+    // 1. Let doc be node's node document's appropriate template contents owner document.
+    auto doc = document().appropriate_template_contents_owner_document();
+
+    // 2. Adopt node's template contents (a DocumentFragment object) into doc.
+    doc->adopt_node(content());
 }
 
 // https://html.spec.whatwg.org/multipage/scripting.html#the-template-element:concept-node-clone-ext

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

@@ -27,9 +27,9 @@ private:
     HTMLTemplateElement(DOM::Document&, DOM::QualifiedName);
 
     virtual bool is_html_template_element() const final { return true; }
-    virtual void visit_edges(Cell::Visitor&) override;
 
-    DOM::Document& appropriate_template_contents_owner_document(DOM::Document&);
+    virtual void initialize(JS::Realm&) override;
+    virtual void visit_edges(Cell::Visitor&) override;
 
     JS::GCPtr<DOM::DocumentFragment> m_content;
 };