DOMImplementation.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibWeb/Bindings/Intrinsics.h>
  8. #include <LibWeb/Bindings/MainThreadVM.h>
  9. #include <LibWeb/DOM/DOMImplementation.h>
  10. #include <LibWeb/DOM/Document.h>
  11. #include <LibWeb/DOM/DocumentType.h>
  12. #include <LibWeb/DOM/ElementFactory.h>
  13. #include <LibWeb/DOM/Text.h>
  14. #include <LibWeb/HTML/Origin.h>
  15. #include <LibWeb/Namespace.h>
  16. namespace Web::DOM {
  17. WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMImplementation>> DOMImplementation::create(Document& document)
  18. {
  19. auto& realm = document.realm();
  20. return MUST_OR_THROW_OOM(realm.heap().allocate<DOMImplementation>(realm, document));
  21. }
  22. DOMImplementation::DOMImplementation(Document& document)
  23. : PlatformObject(document.realm())
  24. , m_document(document)
  25. {
  26. }
  27. DOMImplementation::~DOMImplementation() = default;
  28. JS::ThrowCompletionOr<void> DOMImplementation::initialize(JS::Realm& realm)
  29. {
  30. MUST_OR_THROW_OOM(Base::initialize(realm));
  31. set_prototype(&Bindings::ensure_web_prototype<Bindings::DOMImplementationPrototype>(realm, "DOMImplementation"));
  32. return {};
  33. }
  34. void DOMImplementation::visit_edges(Cell::Visitor& visitor)
  35. {
  36. Base::visit_edges(visitor);
  37. visitor.visit(m_document);
  38. }
  39. // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
  40. WebIDL::ExceptionOr<JS::NonnullGCPtr<Document>> DOMImplementation::create_document(DeprecatedString const& namespace_, DeprecatedString const& qualified_name, JS::GCPtr<DocumentType> doctype) const
  41. {
  42. // FIXME: This should specifically be an XML document.
  43. auto xml_document = TRY(Document::create(realm()));
  44. xml_document->set_ready_for_post_load_tasks(true);
  45. JS::GCPtr<Element> element;
  46. if (!qualified_name.is_empty())
  47. element = TRY(xml_document->create_element_ns(namespace_, qualified_name, ElementCreationOptions {}));
  48. if (doctype)
  49. TRY(xml_document->append_child(*doctype));
  50. if (element)
  51. TRY(xml_document->append_child(*element));
  52. xml_document->set_origin(document().origin());
  53. if (namespace_ == Namespace::HTML)
  54. xml_document->set_content_type("application/xhtml+xml");
  55. else if (namespace_ == Namespace::SVG)
  56. xml_document->set_content_type("image/svg+xml");
  57. else
  58. xml_document->set_content_type("application/xml");
  59. return xml_document;
  60. }
  61. // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
  62. JS::NonnullGCPtr<Document> DOMImplementation::create_html_document(DeprecatedString const& title) const
  63. {
  64. auto html_document = Document::create(realm()).release_value_but_fixme_should_propagate_errors();
  65. html_document->set_content_type("text/html");
  66. html_document->set_ready_for_post_load_tasks(true);
  67. auto doctype = heap().allocate<DocumentType>(realm(), html_document).release_allocated_value_but_fixme_should_propagate_errors();
  68. doctype->set_name("html");
  69. MUST(html_document->append_child(*doctype));
  70. auto html_element = create_element(html_document, HTML::TagNames::html, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
  71. MUST(html_document->append_child(html_element));
  72. auto head_element = create_element(html_document, HTML::TagNames::head, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
  73. MUST(html_element->append_child(head_element));
  74. if (!title.is_null()) {
  75. auto title_element = create_element(html_document, HTML::TagNames::title, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
  76. MUST(head_element->append_child(title_element));
  77. auto text_node = heap().allocate<Text>(realm(), html_document, title).release_allocated_value_but_fixme_should_propagate_errors();
  78. MUST(title_element->append_child(*text_node));
  79. }
  80. auto body_element = create_element(html_document, HTML::TagNames::body, Namespace::HTML).release_value_but_fixme_should_propagate_errors();
  81. MUST(html_element->append_child(body_element));
  82. html_document->set_origin(document().origin());
  83. return html_document;
  84. }
  85. // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
  86. WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentType>> DOMImplementation::create_document_type(DeprecatedString const& qualified_name, DeprecatedString const& public_id, DeprecatedString const& system_id)
  87. {
  88. TRY(Document::validate_qualified_name(realm(), qualified_name));
  89. auto document_type = TRY(DocumentType::create(document()));
  90. document_type->set_name(qualified_name);
  91. document_type->set_public_id(public_id);
  92. document_type->set_system_id(system_id);
  93. return document_type;
  94. }
  95. }