Bug 1404897: Implement Element.matches using stylo. r=heycam

MozReview-Commit-ID: 7nxYVcweu0W

--HG--
extra : rebase_source : e660504ba8ec2be7d678049000cb76018dc4ba5e
This commit is contained in:
Emilio Cobos Álvarez 2017-10-02 18:14:15 +02:00
Родитель c3d21f55ab
Коммит 4eb5336c9b
3 изменённых файлов: 109 добавлений и 17 удалений

Просмотреть файл

@ -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