Skip to content

Commit c99b8d2

Browse files
mrobinsonTG199
authored andcommitted
layout: Add initial support for the ::marker pseudo-element (servo#36317)
This change adds support for the `::marker` pseudo-element and ensure that markers are cached into the box tree. This is only initial support, there are a few things missing such as animations, transitions, and support the `content` CSS property. Testing: There are WPT tests for this change. Signed-off-by: Martin Robinson <[email protected]> Signed-off-by: Martin Robinson <[email protected]>
1 parent 90bb696 commit c99b8d2

27 files changed

+282
-276
lines changed

Cargo.lock

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/layout_2020/dom.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct InnerDOMLayoutData {
3434
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
3535
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
3636
pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>,
37+
pub(super) pseudo_marker_box: ArcRefCell<Option<LayoutBox>>,
3738
}
3839

3940
/// A box that is stored in one of the `DOMLayoutData` slots.
@@ -222,6 +223,7 @@ where
222223
let cell = match pseudo_element_type {
223224
PseudoElement::Before => &data.pseudo_before_box,
224225
PseudoElement::After => &data.pseudo_after_box,
226+
PseudoElement::Marker => &data.pseudo_marker_box,
225227
_ => unreachable!(
226228
"Asked for box slot for unsupported pseudo-element: {:?}",
227229
pseudo_element_type
@@ -235,6 +237,7 @@ where
235237
let cell = match pseudo_element_type {
236238
PseudoElement::Before => &data.pseudo_before_box,
237239
PseudoElement::After => &data.pseudo_after_box,
240+
PseudoElement::Marker => &data.pseudo_marker_box,
238241
_ => unreachable!(
239242
"Asked for box slot for unsupported pseudo-element: {:?}",
240243
pseudo_element_type
@@ -248,6 +251,7 @@ where
248251
*data.self_box.borrow_mut() = None;
249252
*data.pseudo_before_box.borrow_mut() = None;
250253
*data.pseudo_after_box.borrow_mut() = None;
254+
*data.pseudo_marker_box.borrow_mut() = None;
251255
// Stylo already takes care of removing all layout data
252256
// for DOM descendants of elements with `display: none`.
253257
}

components/layout_2020/dom_traversal.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ fn traverse_element<'dom, Node>(
236236
) where
237237
Node: NodeExt<'dom>,
238238
{
239+
// Clear any existing pseudo-element box slot, because markers are not handled like
240+
// `::before`` and `::after`. They are processed during box tree creation.
241+
element.unset_pseudo_element_box(PseudoElement::Marker);
242+
239243
let replaced = ReplacedContents::for_element(element, context);
240244
let style = element.style(context);
241245
match Display::from(style.get_box().display) {

components/layout_2020/flow/construct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ where
393393
is_list_item: false,
394394
},
395395
NonReplacedContents::OfPseudoElement(contents).into(),
396-
BoxSlot::dummy(),
396+
info.node.pseudo_element_box_slot(PseudoElement::Marker),
397397
);
398398
}
399399

@@ -405,7 +405,7 @@ where
405405
) {
406406
self.block_level_boxes.push(BlockLevelJob {
407407
info: info.clone(),
408-
box_slot: BoxSlot::dummy(),
408+
box_slot: info.node.pseudo_element_box_slot(PseudoElement::Marker),
409409
kind: BlockLevelCreator::OutsideMarker {
410410
contents,
411411
list_item_style,

components/layout_2020/lists.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ pub(crate) fn make_marker<'dom, Node>(
1919
where
2020
Node: NodeExt<'dom>,
2121
{
22-
// TODO: use `PseudoElement::Marker` when we add it.
23-
let marker_info = info.pseudo(
24-
context,
25-
style::selector_parser::PseudoElement::ServoLegacyText,
26-
)?;
22+
let marker_info = info.pseudo(context, style::selector_parser::PseudoElement::Marker)?;
2723
let style = &marker_info.style;
2824
let list_style = style.get_list();
2925

components/layout_2020/query.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub fn process_resolved_style_request<'dom>(
131131
None => layout_element,
132132
};
133133

134-
let style = &*layout_element.resolved_style();
134+
let style = &*layout_element.style(context);
135135
let longhand_id = match *property {
136136
PropertyId::NonCustom(id) => match id.longhand_or_shorthand() {
137137
Ok(longhand_id) => longhand_id,
@@ -1122,7 +1122,7 @@ where
11221122
let element = node.as_element().unwrap();
11231123
let parent_style = if node.is_connected() {
11241124
if element.has_data() {
1125-
node.to_threadsafe().as_element().unwrap().resolved_style()
1125+
node.to_threadsafe().as_element().unwrap().style(context)
11261126
} else {
11271127
let mut tlc = ThreadLocalStyleContext::new();
11281128
let mut context = StyleContext {

components/script/dom/window.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
12621262
Some(PseudoElement::After)
12631263
},
12641264
Some(ref pseudo) if pseudo == "::selection" => Some(PseudoElement::Selection),
1265+
Some(ref pseudo) if pseudo == "::marker" => Some(PseudoElement::Marker),
12651266
Some(ref pseudo) if pseudo.starts_with(':') => {
12661267
// Step 3.2: If type is failure, or is a ::slotted() or ::part()
12671268
// pseudo-element, let obj be null.

components/shared/script_layout/wrapper_traits.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -363,22 +363,6 @@ pub trait ThreadSafeLayoutElement<'dom>:
363363
.clone()
364364
}
365365

366-
/// Returns the already resolved style of the node.
367-
///
368-
/// This differs from `style(ctx)` in that if the pseudo-element has not yet
369-
/// been computed it would panic.
370-
///
371-
/// This should be used just for querying layout, or when we know the
372-
/// element style is precomputed, not from general layout itself.
373-
#[inline]
374-
fn resolved_style(&self) -> Arc<ComputedValues> {
375-
let data = self.style_data();
376-
match self.pseudo_element() {
377-
None => data.styles.primary().clone(),
378-
Some(pseudo_element) => data.styles.pseudos.get(&pseudo_element).unwrap().clone(),
379-
}
380-
}
381-
382366
fn is_shadow_host(&self) -> bool;
383367

384368
/// Returns whether this node is a body element of an html element root

resources/servo.css

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,6 @@ svg > * {
174174
writing-mode: inherit;
175175
}
176176

177-
/* style for text node. */
178-
*|*::-servo-legacy-text {
179-
text-overflow: inherit;
180-
overflow: inherit;
181-
padding: unset;
182-
margin: unset;
183-
}
184-
185177
*|*::-servo-legacy-table-wrapper {
186178
display: table;
187179
border: none;

resources/user-agent.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,12 @@ iframe:fullscreen {
422422
border:none !important;
423423
padding:0 !important;
424424
}
425+
426+
/* https://drafts.csswg.org/css-lists-3/#ua-stylesheet */
427+
*::marker {
428+
text-align: end;
429+
text-transform: none;
430+
unicode-bidi: isolate;
431+
font-variant-numeric: tabular-nums;
432+
white-space: pre;
433+
}

0 commit comments

Comments
 (0)