summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-06-04 16:06:32 +0200
committerAndreas Kling <kling@serenityos.org>2020-06-04 16:06:32 +0200
commit959de19418c831e1384f6d65a45971dd1d6a4287 (patch)
tree11799bded8de162b37feab50fd098aeb0b6a0a71
parentec1891837fd2aeec9b644ca1b70caf6f026e305a (diff)
downloadserenity-959de19418c831e1384f6d65a45971dd1d6a4287.zip
LibWeb: Process style sheets in document order
Until now we would simply apply stylesheets in the order they finished loading. This patch adds a StyleSheetList object that hangs off of each Document and contains all the style sheets in document order. There's still a lot of work to do for a proper cascade, but at least this makes us consistently wrong every time. :^)
-rw-r--r--Applications/Browser/Tab.cpp2
-rw-r--r--Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Libraries/LibWeb/CSS/StyleResolver.cpp2
-rw-r--r--Libraries/LibWeb/CSS/StyleSheet.h1
-rw-r--r--Libraries/LibWeb/CSS/StyleSheetList.cpp43
-rw-r--r--Libraries/LibWeb/CSS/StyleSheetList.h54
-rw-r--r--Libraries/LibWeb/DOM/Document.cpp1
-rw-r--r--Libraries/LibWeb/DOM/Document.h7
-rw-r--r--Libraries/LibWeb/DOM/HTMLLinkElement.cpp10
-rw-r--r--Libraries/LibWeb/DOM/HTMLLinkElement.h2
-rw-r--r--Libraries/LibWeb/DOM/HTMLStyleElement.cpp4
11 files changed, 120 insertions, 7 deletions
diff --git a/Applications/Browser/Tab.cpp b/Applications/Browser/Tab.cpp
index e26d2bb99a..4028612c15 100644
--- a/Applications/Browser/Tab.cpp
+++ b/Applications/Browser/Tab.cpp
@@ -322,7 +322,7 @@ Tab::Tab()
this));
debug_menu.add_action(GUI::Action::create(
"Dump Style sheets", [this](auto&) {
- for (auto& sheet : m_page_view->document()->stylesheets()) {
+ for (auto& sheet : m_page_view->document()->style_sheets().sheets()) {
dump_sheet(sheet);
}
},
diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt
index 023a60be8b..02b98b3133 100644
--- a/Libraries/LibWeb/CMakeLists.txt
+++ b/Libraries/LibWeb/CMakeLists.txt
@@ -24,6 +24,7 @@ set(SOURCES
CSS/StyleResolver.cpp
CSS/StyleRule.cpp
CSS/StyleSheet.cpp
+ CSS/StyleSheetList.cpp
CSS/StyleValue.cpp
DOM/AttributeNames.cpp
DOM/CanvasRenderingContext2D.cpp
diff --git a/Libraries/LibWeb/CSS/StyleResolver.cpp b/Libraries/LibWeb/CSS/StyleResolver.cpp
index 6a0f14b88d..dc6bfe7ea0 100644
--- a/Libraries/LibWeb/CSS/StyleResolver.cpp
+++ b/Libraries/LibWeb/CSS/StyleResolver.cpp
@@ -60,7 +60,7 @@ template<typename Callback>
void StyleResolver::for_each_stylesheet(Callback callback) const
{
callback(default_stylesheet());
- for (auto& sheet : document().stylesheets()) {
+ for (auto& sheet : document().style_sheets().sheets()) {
callback(sheet);
}
}
diff --git a/Libraries/LibWeb/CSS/StyleSheet.h b/Libraries/LibWeb/CSS/StyleSheet.h
index 4acd446038..496260d76a 100644
--- a/Libraries/LibWeb/CSS/StyleSheet.h
+++ b/Libraries/LibWeb/CSS/StyleSheet.h
@@ -41,6 +41,7 @@ public:
~StyleSheet();
const NonnullRefPtrVector<StyleRule>& rules() const { return m_rules; }
+ NonnullRefPtrVector<StyleRule>& rules() { return m_rules; }
private:
explicit StyleSheet(NonnullRefPtrVector<StyleRule>&&);
diff --git a/Libraries/LibWeb/CSS/StyleSheetList.cpp b/Libraries/LibWeb/CSS/StyleSheetList.cpp
new file mode 100644
index 0000000000..bbda79757c
--- /dev/null
+++ b/Libraries/LibWeb/CSS/StyleSheetList.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/CSS/StyleSheetList.h>
+
+namespace Web {
+namespace CSS {
+
+void StyleSheetList::add_sheet(NonnullRefPtr<StyleSheet> sheet)
+{
+ m_sheets.append(move(sheet));
+}
+
+StyleSheetList::StyleSheetList(Document& document)
+ : m_document(document)
+{
+}
+
+}
+}
diff --git a/Libraries/LibWeb/CSS/StyleSheetList.h b/Libraries/LibWeb/CSS/StyleSheetList.h
new file mode 100644
index 0000000000..ebccf4dccb
--- /dev/null
+++ b/Libraries/LibWeb/CSS/StyleSheetList.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/RefCounted.h>
+#include <LibWeb/CSS/StyleSheet.h>
+
+namespace Web {
+namespace CSS {
+
+class StyleSheetList : public RefCounted<StyleSheetList> {
+public:
+ static NonnullRefPtr<StyleSheetList> create(Document& document)
+ {
+ return adopt(*new StyleSheetList(document));
+ }
+
+ void add_sheet(NonnullRefPtr<StyleSheet>);
+
+ const NonnullRefPtrVector<StyleSheet>& sheets() const { return m_sheets; }
+
+private:
+ explicit StyleSheetList(Document&);
+
+ Document& m_document;
+ NonnullRefPtrVector<StyleSheet> m_sheets;
+};
+
+}
+}
diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp
index 48acc74d8a..529be4f88e 100644
--- a/Libraries/LibWeb/DOM/Document.cpp
+++ b/Libraries/LibWeb/DOM/Document.cpp
@@ -63,6 +63,7 @@ namespace Web {
Document::Document(const URL& url)
: ParentNode(*this, NodeType::DOCUMENT_NODE)
, m_style_resolver(make<StyleResolver>(*this))
+ , m_style_sheets(CSS::StyleSheetList::create(*this))
, m_url(url)
, m_window(Window::create_with_document(*this))
{
diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h
index 37db176127..6679e46e23 100644
--- a/Libraries/LibWeb/DOM/Document.h
+++ b/Libraries/LibWeb/DOM/Document.h
@@ -37,6 +37,7 @@
#include <LibJS/Forward.h>
#include <LibWeb/CSS/StyleResolver.h>
#include <LibWeb/CSS/StyleSheet.h>
+#include <LibWeb/CSS/StyleSheetList.h>
#include <LibWeb/DOM/NonElementParentNode.h>
#include <LibWeb/DOM/ParentNode.h>
@@ -63,8 +64,8 @@ public:
StyleResolver& style_resolver() { return *m_style_resolver; }
const StyleResolver& style_resolver() const { return *m_style_resolver; }
- void add_sheet(const StyleSheet& sheet) { m_sheets.append(sheet); }
- const NonnullRefPtrVector<StyleSheet>& stylesheets() const { return m_sheets; }
+ CSS::StyleSheetList& style_sheets() { return *m_style_sheets; }
+ const CSS::StyleSheetList& style_sheets() const { return *m_style_sheets; }
virtual FlyString tag_name() const override { return "#document"; }
@@ -146,7 +147,7 @@ private:
virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
OwnPtr<StyleResolver> m_style_resolver;
- NonnullRefPtrVector<StyleSheet> m_sheets;
+ RefPtr<CSS::StyleSheetList> m_style_sheets;
RefPtr<Node> m_hovered_node;
RefPtr<Node> m_inspected_node;
WeakPtr<Frame> m_frame;
diff --git a/Libraries/LibWeb/DOM/HTMLLinkElement.cpp b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp
index 4ccc36bc5b..30e08f0010 100644
--- a/Libraries/LibWeb/DOM/HTMLLinkElement.cpp
+++ b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp
@@ -68,12 +68,20 @@ void HTMLLinkElement::resource_did_load()
dbg() << "HTMLLinkElement: Failed to parse stylesheet: " << href();
return;
}
- document().add_sheet(*sheet);
+
+ // Transfer the rules from the successfully parsed sheet into the sheet we've already inserted.
+ m_style_sheet->rules() = sheet->rules();
+
document().update_style();
}
void HTMLLinkElement::load_stylesheet(const URL& url)
{
+ // First insert an empty style sheet in the document sheet list.
+ // There's probably a nicer way to do this, but this ensures that sheets are in document order.
+ m_style_sheet = StyleSheet::create({});
+ document().style_sheets().add_sheet(*m_style_sheet);
+
LoadRequest request;
request.set_url(url);
set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request));
diff --git a/Libraries/LibWeb/DOM/HTMLLinkElement.h b/Libraries/LibWeb/DOM/HTMLLinkElement.h
index b0a85c0195..bae7d8d9f0 100644
--- a/Libraries/LibWeb/DOM/HTMLLinkElement.h
+++ b/Libraries/LibWeb/DOM/HTMLLinkElement.h
@@ -50,6 +50,8 @@ private:
virtual void resource_did_load() override;
void load_stylesheet(const URL&);
+
+ RefPtr<StyleSheet> m_style_sheet;
};
template<>
diff --git a/Libraries/LibWeb/DOM/HTMLStyleElement.cpp b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
index 83ae31b148..e2e2ec4a27 100644
--- a/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
+++ b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
@@ -50,7 +50,9 @@ void HTMLStyleElement::children_changed()
});
m_stylesheet = parse_css(builder.to_string());
if (m_stylesheet)
- document().add_sheet(*m_stylesheet);
+ document().style_sheets().add_sheet(*m_stylesheet);
+ else
+ document().style_sheets().add_sheet(StyleSheet::create({}));
HTMLElement::children_changed();
}