LibWeb+WebContent: Report CSS rule source data
Include parser rule locations and stylesheet identities in the applied style rule data sent to DevTools. This gives the protocol layer enough information to map matched rules to existing stylesheet resources without guessing from displayed rule text.
This commit is contained in:
parent
52e1d30404
commit
b2b164ebd7
5 changed files with 61 additions and 29 deletions
|
|
@ -50,6 +50,7 @@
|
|||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/CSS/StyleProperty.h>
|
||||
#include <LibWeb/CSS/StyleSheet.h>
|
||||
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
|
||||
|
|
@ -1750,6 +1751,18 @@ static JsonArray serialize_devtools_selector_specificities(MatchingRule const& r
|
|||
return specificities;
|
||||
}
|
||||
|
||||
static JsonObject serialize_devtools_style_sheet_identifier(StyleSheetIdentifier const& identifier)
|
||||
{
|
||||
JsonObject serialized_identifier;
|
||||
serialized_identifier.set("type"sv, style_sheet_identifier_type_to_string(identifier.type));
|
||||
if (identifier.dom_element_unique_id.has_value())
|
||||
serialized_identifier.set("domElementUniqueId"sv, identifier.dom_element_unique_id->value());
|
||||
if (identifier.url.has_value())
|
||||
serialized_identifier.set("url"sv, *identifier.url);
|
||||
serialized_identifier.set("ruleCount"sv, identifier.rule_count);
|
||||
return serialized_identifier;
|
||||
}
|
||||
|
||||
static JsonObject serialize_devtools_matching_rule(DOM::Document const& document, MatchingRule const& rule)
|
||||
{
|
||||
auto const& declaration = rule.declaration();
|
||||
|
|
@ -1776,6 +1789,17 @@ static JsonObject serialize_devtools_matching_rule(DOM::Document const& document
|
|||
serialized_rule.set("ruleIndex"sv, rule.rule_index);
|
||||
serialized_rule.set("isSystem"sv, rule.cascade_origin == CascadeOrigin::UserAgent);
|
||||
|
||||
if (auto const& source_location = rule.rule->source_location(); source_location.has_value()) {
|
||||
// Our positions are 0-based, but DevTools expects them to be 1-based.
|
||||
serialized_rule.set("line"sv, source_location->line + 1);
|
||||
serialized_rule.set("column"sv, source_location->column + 1);
|
||||
}
|
||||
|
||||
if (auto const* style_sheet = rule.rule->parent_style_sheet()) {
|
||||
if (auto identifier = style_sheet_identifier_for(*style_sheet); identifier.has_value())
|
||||
serialized_rule.set("styleSheet"sv, serialize_devtools_style_sheet_identifier(identifier.release_value()));
|
||||
}
|
||||
|
||||
return serialized_rule;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ public:
|
|||
virtual String type() const = 0;
|
||||
|
||||
DOM::Element* owner_node() { return m_owner_node; }
|
||||
DOM::Element const* owner_node() const { return m_owner_node; }
|
||||
void set_owner_node(DOM::Element*);
|
||||
|
||||
Optional<String> href() const;
|
||||
|
|
@ -57,6 +58,7 @@ public:
|
|||
virtual void set_disabled(bool disabled) { m_disabled = disabled; }
|
||||
|
||||
CSSStyleSheet* parent_style_sheet() { return m_parent_style_sheet; }
|
||||
CSSStyleSheet const* parent_style_sheet() const { return m_parent_style_sheet; }
|
||||
void set_parent_css_style_sheet(CSSStyleSheet*);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@
|
|||
*/
|
||||
|
||||
#include "StyleSheetIdentifier.h"
|
||||
#include <AK/Debug.h>
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
|
@ -42,6 +45,34 @@ Optional<StyleSheetIdentifier::Type> style_sheet_identifier_type_from_string(Str
|
|||
return {};
|
||||
}
|
||||
|
||||
Optional<StyleSheetIdentifier> style_sheet_identifier_for(CSSStyleSheet const& sheet)
|
||||
{
|
||||
StyleSheetIdentifier identifier {};
|
||||
|
||||
if (sheet.owner_rule()) {
|
||||
identifier.type = StyleSheetIdentifier::Type::ImportRule;
|
||||
} else if (auto* node = sheet.owner_node()) {
|
||||
if (node->is_html_style_element() || node->is_svg_style_element()) {
|
||||
identifier.type = StyleSheetIdentifier::Type::StyleElement;
|
||||
} else if (node->is_html_link_element()) {
|
||||
identifier.type = StyleSheetIdentifier::Type::LinkElement;
|
||||
} else {
|
||||
dbgln("Can't identify where style sheet came from; owner node is {}", node->debug_description());
|
||||
identifier.type = StyleSheetIdentifier::Type::StyleElement;
|
||||
}
|
||||
identifier.dom_element_unique_id = node->unique_id();
|
||||
} else {
|
||||
dbgln("Style sheet has no owner rule or owner node; skipping");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto sheet_url = sheet.href(); sheet_url.has_value())
|
||||
identifier.url = sheet_url.release_value();
|
||||
|
||||
identifier.rule_count = sheet.rules().length();
|
||||
return identifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ struct StyleSheetIdentifier {
|
|||
|
||||
StringView style_sheet_identifier_type_to_string(StyleSheetIdentifier::Type);
|
||||
Optional<StyleSheetIdentifier::Type> style_sheet_identifier_type_from_string(StringView);
|
||||
WEB_API Optional<StyleSheetIdentifier> style_sheet_identifier_for(CSSStyleSheet const&);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <LibJS/Runtime/ConsoleObject.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/CSS/CSSImportRule.h>
|
||||
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||
#include <LibWeb/CSS/StyleSheetList.h>
|
||||
#include <LibWeb/DOM/CharacterData.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include <LibWeb/DOM/NodeList.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
||||
#include <LibWeb/HTML/HTMLLinkElement.h>
|
||||
#include <LibWeb/HTML/Navigable.h>
|
||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
|
|
@ -1043,34 +1043,8 @@ void PageClient::console_peer_did_misbehave(char const* reason)
|
|||
|
||||
static void gather_style_sheets(Vector<Web::CSS::StyleSheetIdentifier>& results, Web::CSS::CSSStyleSheet& sheet)
|
||||
{
|
||||
Web::CSS::StyleSheetIdentifier identifier {};
|
||||
|
||||
bool valid = true;
|
||||
|
||||
if (sheet.owner_rule()) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::ImportRule;
|
||||
} else if (auto* node = sheet.owner_node()) {
|
||||
if (node->is_html_style_element() || node->is_svg_style_element()) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::StyleElement;
|
||||
} else if (is<Web::HTML::HTMLLinkElement>(node)) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::LinkElement;
|
||||
} else {
|
||||
dbgln("Can't identify where style sheet came from; owner node is {}", node->debug_description());
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::StyleElement;
|
||||
}
|
||||
identifier.dom_element_unique_id = node->unique_id();
|
||||
} else {
|
||||
dbgln("Style sheet has no owner rule or owner node; skipping");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (auto sheet_url = sheet.href(); sheet_url.has_value())
|
||||
identifier.url = sheet_url.release_value();
|
||||
|
||||
identifier.rule_count = sheet.rules().length();
|
||||
results.append(move(identifier));
|
||||
}
|
||||
if (auto identifier = Web::CSS::style_sheet_identifier_for(sheet); identifier.has_value())
|
||||
results.append(identifier.release_value());
|
||||
|
||||
for (auto& import_rule : sheet.import_rules()) {
|
||||
if (import_rule->loaded_style_sheet()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue