File: has-pseudoclass-only.html

package info (click to toggle)
firefox-esr 140.4.0esr-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,539,276 kB
  • sloc: cpp: 7,381,286; javascript: 6,388,710; ansic: 3,710,139; python: 1,393,780; xml: 628,165; asm: 426,918; java: 184,004; sh: 65,742; makefile: 19,302; objc: 13,059; perl: 12,912; yacc: 4,583; cs: 3,846; pascal: 3,352; lex: 1,720; ruby: 1,226; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10
file content (84 lines) | stat: -rw-r--r-- 2,800 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<title>CSS Selectors Invalidation: :has() containing :empty, :first-child, :last-child, pseudoclasses only</title>
<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1931432">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#subject {
  color: grey;
}

#subject.empty:has(:empty) {
  color: red;
}

#subject.first:has(:first-child) {
  color: orange;
}

#subject.last:has(:last-child) {
  color: yellow;
}

/* :empty :empty never matches, so use something else. */
#subject.empty-subtree:has(:first-child :empty) {
  color: green;
}

#subject.first-subtree:has(:first-child :first-child) {
  color: blue;
}

#subject.last-subtree:has(:last-child :last-child) {
  color: purple;
}
</style>
<div id="subject"></div>
<script>
const grey = "rgb(128, 128, 128)";
const red = "rgb(255, 0, 0)";
const orange = "rgb(255, 165, 0)";
const yellow = "rgb(255, 255, 0)";
const green = "rgb(0, 128, 0)";
const blue = 'rgb(0, 0, 255)';
const purple = 'rgb(128, 0, 128)';

function testColor(test_name, color) {
  test(function() {
    assert_equals(getComputedStyle(subject).color, color);
  }, test_name);
}

function runTest(test_class, child, insert, color_after_add, desc) {
  subject.classList.add(test_class);
  testColor(desc + ' color initial', grey);
  insert(child);
  testColor(desc + ' color after adding', color_after_add);
  subject.replaceChildren();
  testColor(desc + ' color after removing', grey);
  subject.classList.remove(test_class);
}

function createSimpleTree() {
  const root = document.createElement('div');
  root.replaceChildren(document.createElement('div'), document.createElement('div'));
  return root;
}

const tests = {
  ':empty': {cls: 'empty', child: document.createElement('div'), color_after_add: red},
  ':first-child': {cls: 'first', child: document.createElement('div'), color_after_add: orange},
  ':last-child': {cls: 'last', child: document.createElement('div'), color_after_add: yellow},
  ':empty subtree': {cls: 'empty-subtree', child: createSimpleTree(), color_after_add: green},
  ':first-child subtree': {cls: 'first-subtree', child: createSimpleTree(), color_after_add: blue},
  ':last-child subtree': {cls: 'last-subtree', child: createSimpleTree(), color_after_add: purple},
};

const element = document.createElement('div');
for (const [t, options] of Object.entries(tests)) {
  runTest(options.cls, options.child, (e) => subject.appendChild(e), options.color_after_add, t + ' append');
  runTest(options.cls, options.child, (e) => subject.insertBefore(e, null), options.color_after_add, t + ' insert');
}
</script>