Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions docs/validation/css-placeholder-pseudo-paint-237-235.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ The remaining core pseudo-element inventory is:
discrete transition behavior remain open;
- two functional `::highlight()` rules, which require named Highlight ranges,
functional pseudo parsing, range paint, mutation, and teardown;
- two `::-webkit-details-marker` rules and six internal form-control part
rules (`::-webkit-inner-spin-button`, `::-webkit-outer-spin-button`,
- six internal form-control part rules (`::-webkit-inner-spin-button`, `::-webkit-outer-spin-button`,
`::-ms-clear`, and `::-webkit-search-cancel-button`), which require bounded
native control-part ownership before their declarations can have an
observable effect.
Expand All @@ -63,6 +62,12 @@ highlights and one `::marker`; shadow-only `::part`/`::slotted`, complete marker
styling, first-line/first-letter layout, and cumulative browser/package/
performance evidence remain outside this slice. No Code OSS source changes.

The two Code OSS `::-webkit-details-marker { display:none }` rules are now a
separate bounded follow-up. They reuse the retained list marker and store one
hidden bit only when the pseudo matches; internal form-control parts remain the
only reachable vendor pseudo inventory without an observable WebScene control
part to style.

The remaining parser-recognized but runtime-unmaterialized pseudo-elements are
`::first-letter`, `::first-line`, `::marker`, `::file-selector-button`, `::cue`,
`::cue-region`, `::grammar-error`, `::spelling-error`, and `::target-text`.
Expand Down
28 changes: 28 additions & 0 deletions docs/validation/css-webkit-details-marker-783.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Hidden retained details markers

Issues: WebScene #783, #237, and #235

Pinned unchanged Code OSS `645f29cc3176500b4b5762ba887cf2a7f0ffdf2c`
authors two `::-webkit-details-marker { display:none }` rules for Chat
disclosures. WebScene already represents `<summary>` as a list item and retains
one marker geometry/paint path. The selector was previously classified as an
ordinary unsupported pseudo and its declaration never reached that path.

The selector now has a dedicated pseudo kind. Its bounded cascade accepts the
observed `display:none` value and restores the initial marker for
`initial`/`unset`/`revert`/visible display values. A hidden bit lives inside the
existing copy-on-write pseudo allocation only for a matching summary. Marker
text, geometry, intrinsic contribution, and scene paint all consume the same
existing `list_marker_text` decision; no second marker representation exists.

Layout-style equality includes the hidden bit, so a winning-value mutation
invalidates layout once while unrelated recascades remain paint-only. A
non-summary selector match returns before allocating pseudo state. The authored
native contract covers classification, initial visibility, hiding, restoration,
and the non-summary allocation guard. The browser/native reftest compares the
pseudo-hidden result with the established `list-style:none` reference.

No tests, builds, pixels, or performance gates were executed under the current
implementation-throughput direction. Dynamic mutation, 4,096-summary scaling,
teardown, exact Code OSS Chat pixels, and cross-platform package evidence remain
zero until run.
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ inline bool computed_layout_style_equal(
right_table.border_spacing_vertical)
&& left_table.border_collapsed == right_table.border_collapsed
&& grid_layout_equal(left.grid(), right.grid())
&& left.details_marker_hidden() == right.details_marker_hidden()
&& pseudo_layout_equal(left.before_pseudo(), right.before_pseudo())
&& pseudo_layout_equal(left.after_pseudo(), right.after_pseudo());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ bool apply_native_cascade(native_document& document,dom_node& node,
variables,result,[](bool) {});
observe(declaration,result);
}
else if(kind==10) {
property_result result;
apply_details_marker_declaration(
node,declaration,variables,result);
observe(declaration,result);
}
else if(kind>=3) apply_scrollbar_declaration(node,kind,declaration,variables);
else {
auto& pseudo=kind==1?node.style.mutable_before_pseudo():node.style.mutable_after_pseudo();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ inline int split_pseudo_element_selector(const std::string& selector, std::strin
if (const auto kind = split_suffix("::-moz-placeholder", 8); kind != 0) return kind;
if (const auto kind = split_suffix("::placeholder", 8); kind != 0) return kind;
if (const auto kind = split_suffix("::details-content", 9); kind != 0) return kind;
if (const auto kind = split_suffix("::-webkit-details-marker", 10); kind != 0) return kind;
if (const auto kind = split_suffix("::backdrop", 7); kind != 0) return kind;
if (const auto kind = split_suffix("::-webkit-scrollbar-thumb", 4); kind != 0) return kind;
if (const auto kind = split_suffix("::-webkit-scrollbar-track", 5); kind != 0) return kind;
Expand Down Expand Up @@ -71,6 +72,35 @@ inline bool split_custom_highlight_selector(
return true;
}

template<typename Decision>
void apply_details_marker_declaration(
dom_node& node,
const css_declaration& declaration,
const std::unordered_map<std::string,std::string>& variables,
Decision& decision)
{
decision.classification = "unsupported";
if (node.tag != "summary" || declaration.name != "display") return;
const auto contains_variable = declaration.value.find("var(") != std::string::npos;
auto resolved_value = std::string{};
const auto& value = contains_variable
? (resolved_value = resolve_value(node, declaration.value, variables))
: declaration.value;
if (value.empty() && contains_variable) {
decision.classification = "invalid-authoring";
return;
}
const auto lower = ascii_lower(trim_value(value));
if (lower == "none") {
node.style.mutable_details_marker_hidden() = true;
decision.classification = "supported";
} else if (lower == "initial" || lower == "unset" || lower == "revert"
|| lower == "inline" || lower == "list-item") {
node.style.mutable_details_marker_hidden() = false;
decision.classification = "supported";
}
}

inline bool split_selection_selector(
std::string_view selector,
std::string& origin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ void for_each_cascaded_pseudo_declaration(
// kind prevents a high-priority ::before declaration from affecting
// ::after while reusing the same layer/importance/rollback machinery
// as the originating element.
std::array<std::vector<const css_rule*>, 10> rules_by_kind;
std::array<std::vector<const css_rule*>, 11> rules_by_kind;
for (const auto& [kind, rule] : matched_rules) {
if (kind > 0 && static_cast<size_t>(kind) < rules_by_kind.size())
rules_by_kind[static_cast<size_t>(kind)].push_back(rule);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ std::string list_marker_text(const dom_node& node)
if (node.tag != "li" && node.style.display != display_mode::list_item) {
return {};
}
if (node.tag == "summary" && node.style.details_marker_hidden()) return {};
const auto type = resolved_list_style(node, false);
if (type == "none") return {};
if (type != "decimal" && type != "decimal-leading-zero") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ struct node_style final {
pseudo_element after;
placeholder_element placeholder;
details_content_element details_content;
bool details_marker_hidden{false};
};

const pseudo_element& before_pseudo() const noexcept
Expand Down Expand Up @@ -667,6 +668,17 @@ struct node_style final {
return pseudo_elements->details_content;
}

bool details_marker_hidden() const noexcept
{
return pseudo_elements != nullptr && pseudo_elements->details_marker_hidden;
}

bool& mutable_details_marker_hidden()
{
ensure_unique_pseudo_elements();
return pseudo_elements->details_marker_hidden;
}

void clear_pseudo_elements() noexcept
{
pseudo_elements.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,12 @@
node,node.style.mutable_details_content_pseudo(),declaration);
return;
}
if (pseudo_kind == 10) {
css::property_result result;
css::apply_details_marker_declaration(
node,declaration,css_variables,result);
return;
}
if (pseudo_kind >= 3 && pseudo_kind <= 6) {
apply_scrollbar_css_declaration(node, pseudo_kind, declaration);
return;
Expand Down Expand Up @@ -734,6 +740,12 @@
node,node.style.mutable_details_content_pseudo(),declaration);
return;
}
if (pseudo_kind == 10) {
css::property_result result;
css::apply_details_marker_declaration(
node,declaration,css_variables,result);
return;
}
if (pseudo_kind >= 3 && pseudo_kind <= 6) {
apply_scrollbar_css_declaration(node, pseudo_kind, declaration);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,11 @@
if (pseudo_element) {
const auto supported = name == "before" || name == "after"
|| name == "selection" || name == "placeholder"
|| name == "-webkit-input-placeholder"
|| name == "-moz-placeholder"
|| name == "highlight"
|| name == "details-content"
|| name == "-webkit-details-marker"
|| name == "backdrop" || name == "-webkit-scrollbar"
|| name == "-webkit-scrollbar-thumb"
|| name == "-webkit-scrollbar-track"
Expand Down
16 changes: 16 additions & 0 deletions tests/NativeWeb/css_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ int main(int argc,char** argv) {
{".base::backdrop",7},{".base::placeholder",8},
{".base::-webkit-input-placeholder",8},{".base::-moz-placeholder",8},
{".base::details-content",9},
{".base::-webkit-details-marker",10},
{".base[data-label='::before']",0}
};
for(const auto& [selector,kind]:classified_selectors) {
Expand Down Expand Up @@ -1105,6 +1106,21 @@ int main(int argc,char** argv) {
if(!details_content.present || !details_content.block_size_zero
|| details_content.opacity!=.4F
|| details_content.padding_inline_start.value!=12.0F) return 180;
auto& summary=ordered_document.create_element("summary");
summary.style.display=webscene_native::display_mode::list_item;
if(webscene_native::list_marker_text(summary).empty()) return 194;
webscene_native::css::apply_details_marker_declaration(
summary,{"display","none",false},variable_root,pseudo_result);
if(!summary.style.details_marker_hidden()
|| !webscene_native::list_marker_text(summary).empty()) return 195;
webscene_native::css::apply_details_marker_declaration(
summary,{"display","initial",false},variable_root,pseudo_result);
if(summary.style.details_marker_hidden()
|| webscene_native::list_marker_text(summary).empty()) return 196;
auto& marker_miss=ordered_document.create_element("div");
webscene_native::css::apply_details_marker_declaration(
marker_miss,{"display","none",false},variable_root,pseudo_result);
if(marker_miss.style.has_pseudo_elements()) return 197;
webscene_native::css::apply_scrollbar_declaration(ordered_node,3,{"display","none",true},variable_root);
webscene_native::css::apply_scrollbar_declaration(ordered_node,3,{"display","block",false},variable_root);
if(!ordered_node.style.scrollbar_hidden || ordered_node.style.display==webscene_native::display_mode::none) return 131;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<meta charset="utf-8">
<title>Reference without a disclosure marker</title>
<style>
body { margin: 0; background: white; color: #202124; }
details { width: 260px; margin: 20px; font: 16px/24px sans-serif; }
summary { padding: 4px 8px; border: 1px solid #7b8190; list-style: none; }
</style>
<details open>
<summary>Completed response</summary>
<div>Retained details content</div>
</details>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<meta charset="utf-8">
<title>WebKit details marker display none hides the retained disclosure marker</title>
<link rel="match" href="css-webkit-details-marker-display-ref.html">
<style>
body { margin: 0; background: white; color: #202124; }
details { width: 260px; margin: 20px; font: 16px/24px sans-serif; }
summary { padding: 4px 8px; border: 1px solid #7b8190; }
summary::-webkit-details-marker { display: none; }
</style>
<details open>
<summary>Completed response</summary>
<div>Retained details content</div>
</details>
7 changes: 7 additions & 0 deletions tests/WebPlatformSubset/webscene-component-profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,13 @@
"evidence": ["css-pseudo-elements-4-placeholder", "native-retained-scene-contract", "vscode-oss-645f29c-placeholder-ledger"],
"reason": "Implementation-first WebScene #237/#781 slice for standard and legacy placeholder selectors in unchanged Code OSS core CSS. The browser-shaped contract adds the Chromium-reachable ::-webkit-input-placeholder alias; the native companion covers both WebKit and Mozilla aliases with distinct colors/opacities, class recascade, live-value suppression, and empty-value restoration. All aliases reuse the standard retained paint path without layout, generated nodes, or frame demand. Direct browser/native profile execution remains validation debt; additional placeholder properties remain outside this bounded candidate."
},
{
"path": "contracts/css-webkit-details-marker-display.html",
"type": "reftest",
"capabilities": ["webkit-details-marker-display-none", "retained-summary-marker-suppression", "details-marker-layout-invalidation"],
"evidence": ["css-pseudo-elements-derived", "native-retained-list-marker-contract", "vscode-oss-645f29c-details-marker-ledger"],
"reason": "Implementation-first WebScene #783 slice for the two unchanged Code OSS Chat disclosure rules. The pseudo-hidden result matches the established list-style:none reference while reusing one retained marker representation. Native companion coverage requires initial visibility, hide/restore, classifier origin, layout equality, and a non-summary zero-allocation guard. Direct browser/native pixels, dynamic mutation, 4,096-summary performance/lifecycle, and package execution remain validation debt."
},
{
"path": "contracts/css-checkbox-required-validity.html",
"type": "testharness",
Expand Down
Loading