StyleSheetList.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/QuickSort.h>
  7. #include <LibWeb/Bindings/Intrinsics.h>
  8. #include <LibWeb/Bindings/StyleSheetListPrototype.h>
  9. #include <LibWeb/CSS/StyleComputer.h>
  10. #include <LibWeb/CSS/StyleSheetList.h>
  11. #include <LibWeb/DOM/Document.h>
  12. namespace Web::CSS {
  13. JS_DEFINE_ALLOCATOR(StyleSheetList);
  14. void StyleSheetList::add_sheet(CSSStyleSheet& sheet)
  15. {
  16. sheet.set_style_sheet_list({}, this);
  17. if (m_sheets.is_empty()) {
  18. // This is the first sheet, append it to the list.
  19. m_sheets.append(sheet);
  20. } else {
  21. // We have sheets from before. Insert the new sheet in the correct position (DOM tree order).
  22. bool did_insert = false;
  23. for (ssize_t i = m_sheets.size() - 1; i >= 0; --i) {
  24. auto& existing_sheet = *m_sheets[i];
  25. auto position = existing_sheet.owner_node()->compare_document_position(sheet.owner_node());
  26. if (position & DOM::Node::DocumentPosition::DOCUMENT_POSITION_FOLLOWING) {
  27. m_sheets.insert(i + 1, sheet);
  28. did_insert = true;
  29. break;
  30. }
  31. }
  32. if (!did_insert)
  33. m_sheets.prepend(sheet);
  34. }
  35. if (sheet.rules().length() == 0) {
  36. // NOTE: If the added sheet has no rules, we don't have to invalidate anything.
  37. return;
  38. }
  39. m_document->style_computer().invalidate_rule_cache();
  40. m_document->style_computer().load_fonts_from_sheet(sheet);
  41. m_document->invalidate_style();
  42. }
  43. void StyleSheetList::remove_sheet(CSSStyleSheet& sheet)
  44. {
  45. sheet.set_style_sheet_list({}, nullptr);
  46. m_sheets.remove_first_matching([&](auto& entry) { return entry.ptr() == &sheet; });
  47. if (sheet.rules().length() == 0) {
  48. // NOTE: If the removed sheet had no rules, we don't have to invalidate anything.
  49. return;
  50. }
  51. sort_sheets();
  52. m_document->style_computer().invalidate_rule_cache();
  53. m_document->invalidate_style();
  54. }
  55. JS::NonnullGCPtr<StyleSheetList> StyleSheetList::create(DOM::Document& document)
  56. {
  57. auto& realm = document.realm();
  58. return realm.heap().allocate<StyleSheetList>(realm, document);
  59. }
  60. StyleSheetList::StyleSheetList(DOM::Document& document)
  61. : Bindings::PlatformObject(document.realm())
  62. , m_document(document)
  63. {
  64. m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
  65. }
  66. void StyleSheetList::initialize(JS::Realm& realm)
  67. {
  68. Base::initialize(realm);
  69. WEB_SET_PROTOTYPE_FOR_INTERFACE(StyleSheetList);
  70. }
  71. void StyleSheetList::visit_edges(Cell::Visitor& visitor)
  72. {
  73. Base::visit_edges(visitor);
  74. visitor.visit(m_document);
  75. visitor.visit(m_sheets);
  76. }
  77. // https://www.w3.org/TR/cssom/#ref-for-dfn-supported-property-indices%E2%91%A1
  78. bool StyleSheetList::is_supported_property_index(u32 index) const
  79. {
  80. // The object’s supported property indices are the numbers in the range zero to one less than the number of CSS style sheets represented by the collection.
  81. // If there are no such CSS style sheets, then there are no supported property indices.
  82. if (m_sheets.is_empty())
  83. return false;
  84. return index < m_sheets.size();
  85. }
  86. WebIDL::ExceptionOr<JS::Value> StyleSheetList::item_value(size_t index) const
  87. {
  88. if (index >= m_sheets.size())
  89. return JS::js_undefined();
  90. return m_sheets[index].ptr();
  91. }
  92. void StyleSheetList::sort_sheets()
  93. {
  94. quick_sort(m_sheets, [](JS::NonnullGCPtr<StyleSheet> a, JS::NonnullGCPtr<StyleSheet> b) {
  95. return a->owner_node()->is_before(*b->owner_node());
  96. });
  97. }
  98. }