зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1404897: Implement Element.matches using stylo. r=heycam
MozReview-Commit-ID: 7nxYVcweu0W --HG-- extra : rebase_source : e660504ba8ec2be7d678049000cb76018dc4ba5e
This commit is contained in:
Родитель
c3d21f55ab
Коммит
4eb5336c9b
|
@ -3496,21 +3496,31 @@ Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
|
|||
bool
|
||||
Element::Matches(const nsAString& aSelector, ErrorResult& aError)
|
||||
{
|
||||
nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError);
|
||||
if (!selectorList) {
|
||||
// Either we failed (and aError already has the exception), or this
|
||||
// is a pseudo-element-only selector that matches nothing.
|
||||
return false;
|
||||
}
|
||||
|
||||
TreeMatchContext matchingContext(false,
|
||||
nsRuleWalker::eRelevantLinkUnvisited,
|
||||
OwnerDoc(),
|
||||
TreeMatchContext::eNeverMatchVisited);
|
||||
matchingContext.SetHasSpecifiedScope();
|
||||
matchingContext.AddScopeElement(this);
|
||||
return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
||||
selectorList);
|
||||
return WithSelectorList<bool>(
|
||||
aSelector,
|
||||
aError,
|
||||
[&](const RawServoSelectorList* aList) {
|
||||
if (!aList) {
|
||||
return false;
|
||||
}
|
||||
return Servo_SelectorList_Matches(this, aList);
|
||||
},
|
||||
[&](nsCSSSelectorList* aList) {
|
||||
if (!aList) {
|
||||
// Either we failed (and aError already has the exception), or this
|
||||
// is a pseudo-element-only selector that matches nothing.
|
||||
return false;
|
||||
}
|
||||
TreeMatchContext matchingContext(false,
|
||||
nsRuleWalker::eRelevantLinkUnvisited,
|
||||
OwnerDoc(),
|
||||
TreeMatchContext::eNeverMatchVisited);
|
||||
matchingContext.SetHasSpecifiedScope();
|
||||
matchingContext.AddScopeElement(this);
|
||||
return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
||||
aList);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
||||
|
|
|
@ -2676,6 +2676,47 @@ nsINode::Length() const
|
|||
}
|
||||
}
|
||||
|
||||
const RawServoSelectorList*
|
||||
nsINode::ParseServoSelectorList(
|
||||
const nsAString& aSelectorString,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
MOZ_ASSERT(doc->IsStyledByServo());
|
||||
|
||||
nsIDocument::SelectorCache& cache = doc->GetSelectorCache();
|
||||
nsIDocument::SelectorCache::SelectorList* list =
|
||||
cache.GetList(aSelectorString);
|
||||
if (list) {
|
||||
if (!*list) {
|
||||
// Invalid selector.
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
|
||||
NS_LITERAL_CSTRING("'") + NS_ConvertUTF16toUTF8(aSelectorString) +
|
||||
NS_LITERAL_CSTRING("' is not a valid selector")
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME(emilio): Make this private and use `WithSelectorList` everywhere,
|
||||
// then assert.
|
||||
if (list->IsServo()) {
|
||||
return list->AsServo();
|
||||
}
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 selectorString(aSelectorString);
|
||||
|
||||
auto* selectorList = Servo_SelectorList_Parse(&selectorString);
|
||||
if (!selectorList) {
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
|
||||
NS_LITERAL_CSTRING("'") + selectorString +
|
||||
NS_LITERAL_CSTRING("' is not a valid selector")
|
||||
);
|
||||
}
|
||||
|
||||
cache.CacheList(aSelectorString, UniquePtr<RawServoSelectorList>(selectorList));
|
||||
return selectorList;
|
||||
}
|
||||
|
||||
nsCSSSelectorList*
|
||||
nsINode::ParseSelectorList(const nsAString& aSelectorString,
|
||||
ErrorResult& aRv)
|
||||
|
@ -2692,8 +2733,12 @@ nsINode::ParseSelectorList(const nsAString& aSelectorString,
|
|||
NS_LITERAL_CSTRING("' is not a valid selector")
|
||||
);
|
||||
}
|
||||
MOZ_ASSERT(list->IsGecko(), "We haven't done anything with Servo yet");
|
||||
return list->AsGecko();
|
||||
|
||||
// FIXME(emilio): Make this private and use `WithSelectorList` everywhere,
|
||||
// then assert.
|
||||
if (list->IsGecko()) {
|
||||
return list->AsGecko();
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSParser parser(doc->CSSLoader());
|
||||
|
|
|
@ -55,6 +55,7 @@ class nsNodeSupportsWeakRefTearoff;
|
|||
class nsNodeWeakReference;
|
||||
class nsDOMMutationObserver;
|
||||
class nsRange;
|
||||
struct RawServoSelectorList;
|
||||
|
||||
namespace mozilla {
|
||||
class EventListenerManager;
|
||||
|
@ -2066,10 +2067,46 @@ protected:
|
|||
* contained pseudo-element selectors.
|
||||
*
|
||||
* A failing aRv means the string was not a valid selector.
|
||||
*
|
||||
* Note that the selector list returned here is owned by the owner doc's
|
||||
* selector cache.
|
||||
*/
|
||||
nsCSSSelectorList* ParseSelectorList(const nsAString& aSelectorString,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Parse the given selector string into a servo SelectorList.
|
||||
*
|
||||
* Never returns null if aRv is not failing.
|
||||
*
|
||||
* Note that the selector list returned here is owned by the owner doc's
|
||||
* selector cache.
|
||||
*/
|
||||
const RawServoSelectorList* ParseServoSelectorList(
|
||||
const nsAString& aSelectorString,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Parse the given selector string into a SelectorList.
|
||||
*
|
||||
* A null return value with a non-failing aRv means the string only
|
||||
* contained pseudo-element selectors.
|
||||
*
|
||||
* A failing aRv means the string was not a valid selector.
|
||||
*/
|
||||
template<typename Ret, typename ServoFunctor, typename GeckoFunctor>
|
||||
Ret WithSelectorList(
|
||||
const nsAString& aSelectorString,
|
||||
mozilla::ErrorResult& aRv,
|
||||
const ServoFunctor& aServoFunctor,
|
||||
const GeckoFunctor& aGeckoFunctor)
|
||||
{
|
||||
if (IsStyledByServo()) {
|
||||
return aServoFunctor(ParseServoSelectorList(aSelectorString, aRv));
|
||||
}
|
||||
return aGeckoFunctor(ParseSelectorList(aSelectorString, aRv));
|
||||
}
|
||||
|
||||
public:
|
||||
/* Event stuff that documents and elements share. This needs to be
|
||||
NS_IMETHOD because some subclasses implement DOM methods with
|
||||
|
|
Загрузка…
Ссылка в новой задаче