mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb: Ensure valid placement of @import and @namespace rules
These rules should appear before all other rules (excluding @layer statements and @charset) with @import appearing first.
This commit is contained in:
parent
6b84cd8d11
commit
6144154e4f
Notes:
github-actions[bot]
2025-06-23 11:54:05 +00:00
Author: https://github.com/Calme1709
Commit: 6144154e4f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5158
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/tcl3
7 changed files with 139 additions and 0 deletions
|
@ -125,6 +125,9 @@ GC::Ref<CSS::CSSStyleSheet> Parser::parse_as_css_stylesheet(Optional<::URL::URL>
|
|||
// To parse a CSS stylesheet, first parse a stylesheet.
|
||||
auto const& style_sheet = parse_a_stylesheet(m_token_stream, location);
|
||||
|
||||
bool import_rules_valid = true;
|
||||
bool namespace_rules_valid = true;
|
||||
|
||||
// Interpret all of the resulting top-level qualified rules as style rules, defined below.
|
||||
GC::RootVector<GC::Ref<CSSRule>> rules(realm().heap());
|
||||
for (auto const& raw_rule : style_sheet.rules) {
|
||||
|
@ -135,6 +138,36 @@ GC::Ref<CSS::CSSStyleSheet> Parser::parse_as_css_stylesheet(Optional<::URL::URL>
|
|||
log_parse_error();
|
||||
continue;
|
||||
}
|
||||
|
||||
// "Any @import rules must precede all other valid at-rules and style rules in a style sheet
|
||||
// (ignoring @charset and @layer statement rules) and must not have any other valid at-rules
|
||||
// or style rules between it and previous @import rules, or else the @import rule is invalid."
|
||||
// https://drafts.csswg.org/css-cascade-5/#at-import
|
||||
//
|
||||
// "Any @namespace rules must follow all @charset and @import rules and precede all other
|
||||
// non-ignored at-rules and style rules in a style sheet.
|
||||
// ...
|
||||
// A syntactically invalid @namespace rule (whether malformed or misplaced) must be ignored."
|
||||
// https://drafts.csswg.org/css-namespaces/#syntax
|
||||
switch (rule->type()) {
|
||||
case CSSRule::Type::LayerStatement:
|
||||
break;
|
||||
case CSSRule::Type::Import:
|
||||
if (!import_rules_valid)
|
||||
continue;
|
||||
break;
|
||||
case CSSRule::Type::Namespace:
|
||||
import_rules_valid = false;
|
||||
|
||||
if (!namespace_rules_valid)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
import_rules_valid = false;
|
||||
namespace_rules_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
rules.append(*rule);
|
||||
}
|
||||
|
||||
|
|
46
Tests/LibWeb/Layout/expected/import-after-namespace.txt
Normal file
46
Tests/LibWeb/Layout/expected/import-after-namespace.txt
Normal file
|
@ -0,0 +1,46 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x463 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,16) content-size 784x434 children: not-inline
|
||||
BlockContainer <p> at (8,16) content-size 784x18 children: inline
|
||||
frag 0 from TextNode start: 0, length: 35, rect: [8,16 290.765625x18] baseline: 13.796875
|
||||
"All divs below should be 100px wide"
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,50) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#target1> at (8,50) content-size 100x100 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,150) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#target2> at (8,150) content-size 100x100 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,250) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#target3> at (8,250) content-size 100x100 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,350) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#target4> at (8,350) content-size 100x100 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,450) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <pre#out> at (8,463) content-size 784x0 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,463) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
|
||||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x463]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,16 784x434]
|
||||
PaintableWithLines (BlockContainer<P>) [8,16 784x18]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,50 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>#target1) [8,50 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,150 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>#target2) [8,150 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,250 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>#target3) [8,250 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,350 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>#target4) [8,350 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,450 784x0]
|
||||
PaintableWithLines (BlockContainer<PRE>#out) [8,463 784x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,463 784x0]
|
3
Tests/LibWeb/Layout/input/import-after-namespace-1.css
Normal file
3
Tests/LibWeb/Layout/input/import-after-namespace-1.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
#target1 {
|
||||
width: 100px;
|
||||
}
|
3
Tests/LibWeb/Layout/input/import-after-namespace-2.css
Normal file
3
Tests/LibWeb/Layout/input/import-after-namespace-2.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
#target2 {
|
||||
width: 200px;
|
||||
}
|
3
Tests/LibWeb/Layout/input/import-after-namespace-3.css
Normal file
3
Tests/LibWeb/Layout/input/import-after-namespace-3.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
#target3 {
|
||||
width: 200px;
|
||||
}
|
3
Tests/LibWeb/Layout/input/import-after-namespace-4.css
Normal file
3
Tests/LibWeb/Layout/input/import-after-namespace-4.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
#target4 {
|
||||
width: 200px;
|
||||
}
|
48
Tests/LibWeb/Layout/input/import-after-namespace.html
Normal file
48
Tests/LibWeb/Layout/input/import-after-namespace.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<p>All divs below should be 100px wide</p>
|
||||
<div id="target1"></div>
|
||||
<div id="target2"></div>
|
||||
<div id="target3"></div>
|
||||
<div id="target4"></div>
|
||||
<style>
|
||||
div {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
#target1 {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#target2,
|
||||
#target3,
|
||||
#target4 {
|
||||
background-color: 100px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
/* Imports are allowed after invalid (malformed) namespace rules */
|
||||
@namespace abc;
|
||||
@import "./import-after-namespace-1.css";
|
||||
</style>
|
||||
<style>
|
||||
/* Imports are not allowed after valid namespace rules */
|
||||
@namespace def url("https://www.w3.org/1999/xhtml");
|
||||
@import "./import-after-namespace-2.css";
|
||||
</style>
|
||||
<style>
|
||||
/* Imports are not allowed after invalid supports rules */
|
||||
@supports (display: block;) {
|
||||
}
|
||||
@import "./import-after-namespace-3.css";
|
||||
</style>
|
||||
<style>
|
||||
/* Imports are not allowed after valid namespaces */
|
||||
@supports (display: block) {
|
||||
}
|
||||
@import "./import-after-namespace-4.css";
|
||||
</style>
|
||||
<pre id="out"></pre>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue