-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
check_pseudo_has_fast_reject_filter.cc
118 lines (103 loc) · 3.97 KB
/
check_pseudo_has_fast_reject_filter.cc
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/check_pseudo_has_fast_reject_filter.h"
#include "third_party/blink/renderer/core/css/css_selector.h"
namespace blink {
namespace {
// Salt to separate otherwise identical string hashes so a class-selector like
// .article won't match <article> elements.
enum { kTagNameSalt = 13, kIdSalt = 17, kClassSalt = 19, kAttributeSalt = 23 };
inline bool IsExcludedAttribute(const AtomicString& name) {
return name == html_names::kClassAttr.LocalName() ||
name == html_names::kIdAttr.LocalName() ||
name == html_names::kStyleAttr.LocalName();
}
inline unsigned GetTagHash(const AtomicString& tag_name) {
return tag_name.Impl()->ExistingHash() * kTagNameSalt;
}
inline unsigned GetClassHash(const AtomicString& class_name) {
return class_name.Impl()->ExistingHash() * kClassSalt;
}
inline unsigned GetIdHash(const AtomicString& id) {
return id.Impl()->ExistingHash() * kIdSalt;
}
inline unsigned GetAttributeHash(const AtomicString& attribute_name) {
return attribute_name.Impl()->ExistingHash() * kAttributeSalt;
}
} // namespace
void CheckPseudoHasFastRejectFilter::AddElementIdentifierHashes(
const Element& element) {
filter_.Add(GetTagHash(element.LocalNameForSelectorMatching()));
if (element.HasID())
filter_.Add(GetIdHash(element.IdForStyleResolution()));
if (element.HasClass()) {
const SpaceSplitString& class_names = element.ClassNames();
wtf_size_t count = class_names.size();
for (wtf_size_t i = 0; i < count; ++i)
filter_.Add(GetClassHash(class_names[i]));
}
AttributeCollection attributes = element.AttributesWithoutUpdate();
for (const auto& attribute_item : attributes) {
auto attribute_name = attribute_item.LocalName();
if (IsExcludedAttribute(attribute_name))
continue;
auto lower = attribute_name.IsLowerASCII() ? attribute_name
: attribute_name.LowerASCII();
filter_.Add(GetAttributeHash(lower));
}
}
bool CheckPseudoHasFastRejectFilter::FastReject(
const Vector<unsigned>& pseudo_has_argument_hashes) const {
if (pseudo_has_argument_hashes.IsEmpty())
return false;
for (unsigned hash : pseudo_has_argument_hashes) {
if (!filter_.MayContain(hash))
return true;
}
return false;
}
// static
void CheckPseudoHasFastRejectFilter::CollectPseudoHasArgumentHashes(
Vector<unsigned>& pseudo_has_argument_hashes,
const CSSSelector* simple_selector) {
DCHECK(simple_selector);
switch (simple_selector->Match()) {
case CSSSelector::kId:
if (simple_selector->Value().IsEmpty())
break;
pseudo_has_argument_hashes.push_back(GetIdHash(simple_selector->Value()));
break;
case CSSSelector::kClass:
if (simple_selector->Value().IsEmpty())
break;
pseudo_has_argument_hashes.push_back(
GetClassHash(simple_selector->Value()));
break;
case CSSSelector::kTag:
if (simple_selector->TagQName().LocalName() !=
CSSSelector::UniversalSelectorAtom()) {
pseudo_has_argument_hashes.push_back(
GetTagHash(simple_selector->TagQName().LocalName()));
}
break;
case CSSSelector::kAttributeExact:
case CSSSelector::kAttributeSet:
case CSSSelector::kAttributeList:
case CSSSelector::kAttributeContain:
case CSSSelector::kAttributeBegin:
case CSSSelector::kAttributeEnd:
case CSSSelector::kAttributeHyphen: {
auto attribute_name = simple_selector->Attribute().LocalName();
if (IsExcludedAttribute(attribute_name))
break;
auto lower_name = attribute_name.IsLowerASCII()
? attribute_name
: attribute_name.LowerASCII();
pseudo_has_argument_hashes.push_back(GetAttributeHash(lower_name));
} break;
default:
break;
}
}
} // namespace blink