Commit 78ceb1f5 authored by mitz@apple.com's avatar mitz@apple.com

WebCore:

        Reviewed by Darin Adler.

        - fix https://bugs.webkit.org/show_bug.cgi?id=17655
          <rdar://problem/5778077> REGRESSION (3.1.1-TOT): Reproducible crash calling querySelector on viewless Document

        Test: fast/dom/SelectorAPI/viewless-document.html

        * css/CSSStyleSelector.cpp:
        (WebCore::CSSStyleSelector::CSSStyleSelector): Updated to initialize the
        selector checker.
        (WebCore::CSSStyleSelector::init): Removed initialization of
        m_collectRulesOnly, which is now part of the selector checker.
        (WebCore::CSSStyleSelector::matchRules): Updated for renames and data
        moved into the selector checker.
        (WebCore::CSSStyleSelector::matchRulesForList): Ditto.
        (WebCore::CSSStyleSelector::initForStyleResolve): Added a PseudoId
        argument, which is used to initialize a data member of the selector
        checker. Updated for renames. Removed initialization of m_isXMLDoc
        because this bit is now initialized only once in the selector checker's
        constructor.
        (WebCore::CSSStyleSelector::SelectorChecker::SelectorChecker): Added.
        (WebCore::CSSStyleSelector::SelectorChecker::checkPseudoState): Changed
        into a SelectorChecker method.
        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector): Added. Used
        by querySelector() and querySelectorAll().
        (WebCore::CSSStyleSelector::canShareStyleWithElement): Updated for data
        moved into the selector checker.
        (WebCore::CSSStyleSelector::matchUARules): Ditto.
        (WebCore::CSSStyleSelector::styleForElement):
        (WebCore::CSSStyleSelector::pseudoStyleForElement): Ditto. Also removed
        code that set the parentStyle variable after the last place it is
        accessed, and changed to ensure that m_style is set early in this
        function.
        (WebCore::CSSStyleSelector::adjustRenderStyle): Updated for data moved
        into the selector checker.
        (WebCore::CSSStyleSelector::styleRulesForElement): Ditto.
        (WebCore::CSSStyleSelector::checkSelector): Ditto. Also changed to pass
        the element's style and the parent style to the selector checker, as
        well as the dynamic pseudo variable and the selector attributes vector.
        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Added
        arguments for the style of the base element and its parent. When the
        elementStyle argument is 0, the style is fetched from the element
        and its parent as needed. Also changed to take a reference to the
        dynamic pseudo ID and a pointer to the vector of attributes affecting
        the match.
        (WebCore::CSSStyleSelector::applyProperty): Updated for data moved
        into the selector checker.
        (WebCore::CSSStyleSelector::checkForGenericFamilyChange): Ditto.
        (WebCore::CSSStyleSelector::getComputedSizeFromSpecifiedSize): Ditto.
        (WebCore::CSSStyleSelector::fontSizeForKeyword): Ditto.
        (WebCore::CSSStyleSelector::getColorFromPrimitiveValue): Ditto.
        (WebCore::CSSStyleSelector::SelectorChecker::allVisitedStateChanged):
        Changed into a SelectorChecker method.
        (WebCore::CSSStyleSelector::SelectorChecker::visitedStateChanged):
        Ditto.

        * css/CSSStyleSelector.h:
        Added a SelectorChecker class and moved data and methods used in
        checking selectors into it.
        (WebCore::CSSStyleSelector::allVisitedStateChanged): Changed to call the
        SelectorChecker method.
        (WebCore::CSSStyleSelector::visitedStateChanged): Ditto.
        * dom/Node.cpp:
        (WebCore::Node::querySelector): Changed to use a SelectorChecker instead
        of the document's style selector.
        * dom/SelectorNodeList.cpp:
        (WebCore::SelectorNodeList::SelectorNodeList): Ditto.

LayoutTests:

        Reviewed by Darin Adler.

        - test for https://bugs.webkit.org/show_bug.cgi?id=17655
          <rdar://problem/5778077> REGRESSION (3.1.1-TOT): Reproducible crash calling querySelector on viewless Document

        * fast/dom/SelectorAPI/resources/viewless-document.js: Added.
        * fast/dom/SelectorAPI/viewless-document-expected.txt: Added.
        * fast/dom/SelectorAPI/viewless-document.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@33939 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 23cf67bb
2008-05-20 Dan Bernstein <mitz@apple.com>
Reviewed by Darin Adler.
- test for https://bugs.webkit.org/show_bug.cgi?id=17655
<rdar://problem/5778077> REGRESSION (3.1.1-TOT): Reproducible crash calling querySelector on viewless Document
* fast/dom/SelectorAPI/resources/viewless-document.js: Added.
* fast/dom/SelectorAPI/viewless-document-expected.txt: Added.
* fast/dom/SelectorAPI/viewless-document.html: Added.
2008-05-19 Dan Bernstein <mitz@apple.com>
Reviewed by Adam Roben.
description(
"This tests that querySelector and querySelectorAll don't crash when used in a viewless document."
);
var testDoc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html");
testDoc.documentElement.appendChild(testDoc.createElement("body"));
testDoc.body.appendChild(testDoc.createElement("p")).id = "p1";
testDoc.getElementById("p1").appendChild(testDoc.createElement("span")).id = "s1";
testDoc.body.appendChild(testDoc.createElement("span")).id = "s2";
testDoc.body.appendChild(testDoc.createElement("div")).className = "d1";
var p1 = testDoc.getElementById("p1");
var s2 = testDoc.getElementById("s2");
var d1 = testDoc.body.lastChild;
shouldBe("testDoc.querySelector('p')", "p1");
shouldBe("testDoc.querySelectorAll('span').length", "2");
shouldBe("testDoc.querySelectorAll('span').item(1)", "s2");
shouldBe("testDoc.querySelector('.d1')", "d1");
shouldBe("testDoc.querySelectorAll('p span').length", "1");
var successfullyParsed = true;
This tests that querySelector and querySelectorAll don't crash when used in a viewless document.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS testDoc.querySelector('p') is p1
PASS testDoc.querySelectorAll('span').length is 2
PASS testDoc.querySelectorAll('span').item(1) is s2
PASS testDoc.querySelector('.d1') is d1
PASS testDoc.querySelectorAll('p span').length is 1
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/viewless-document.js"></script>
<script src="../../js/resources/js-test-post.js"></script>
</body>
</html>
2008-05-20 Dan Bernstein <mitz@apple.com>
Reviewed by Darin Adler.
- fix https://bugs.webkit.org/show_bug.cgi?id=17655
<rdar://problem/5778077> REGRESSION (3.1.1-TOT): Reproducible crash calling querySelector on viewless Document
Test: fast/dom/SelectorAPI/viewless-document.html
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::CSSStyleSelector): Updated to initialize the
selector checker.
(WebCore::CSSStyleSelector::init): Removed initialization of
m_collectRulesOnly, which is now part of the selector checker.
(WebCore::CSSStyleSelector::matchRules): Updated for renames and data
moved into the selector checker.
(WebCore::CSSStyleSelector::matchRulesForList): Ditto.
(WebCore::CSSStyleSelector::initForStyleResolve): Added a PseudoId
argument, which is used to initialize a data member of the selector
checker. Updated for renames. Removed initialization of m_isXMLDoc
because this bit is now initialized only once in the selector checker's
constructor.
(WebCore::CSSStyleSelector::SelectorChecker::SelectorChecker): Added.
(WebCore::CSSStyleSelector::SelectorChecker::checkPseudoState): Changed
into a SelectorChecker method.
(WebCore::CSSStyleSelector::SelectorChecker::checkSelector): Added. Used
by querySelector() and querySelectorAll().
(WebCore::CSSStyleSelector::canShareStyleWithElement): Updated for data
moved into the selector checker.
(WebCore::CSSStyleSelector::matchUARules): Ditto.
(WebCore::CSSStyleSelector::styleForElement):
(WebCore::CSSStyleSelector::pseudoStyleForElement): Ditto. Also removed
code that set the parentStyle variable after the last place it is
accessed, and changed to ensure that m_style is set early in this
function.
(WebCore::CSSStyleSelector::adjustRenderStyle): Updated for data moved
into the selector checker.
(WebCore::CSSStyleSelector::styleRulesForElement): Ditto.
(WebCore::CSSStyleSelector::checkSelector): Ditto. Also changed to pass
the element's style and the parent style to the selector checker, as
well as the dynamic pseudo variable and the selector attributes vector.
(WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Added
arguments for the style of the base element and its parent. When the
elementStyle argument is 0, the style is fetched from the element
and its parent as needed. Also changed to take a reference to the
dynamic pseudo ID and a pointer to the vector of attributes affecting
the match.
(WebCore::CSSStyleSelector::applyProperty): Updated for data moved
into the selector checker.
(WebCore::CSSStyleSelector::checkForGenericFamilyChange): Ditto.
(WebCore::CSSStyleSelector::getComputedSizeFromSpecifiedSize): Ditto.
(WebCore::CSSStyleSelector::fontSizeForKeyword): Ditto.
(WebCore::CSSStyleSelector::getColorFromPrimitiveValue): Ditto.
(WebCore::CSSStyleSelector::SelectorChecker::allVisitedStateChanged):
Changed into a SelectorChecker method.
(WebCore::CSSStyleSelector::SelectorChecker::visitedStateChanged):
Ditto.
* css/CSSStyleSelector.h:
Added a SelectorChecker class and moved data and methods used in
checking selectors into it.
(WebCore::CSSStyleSelector::allVisitedStateChanged): Changed to call the
SelectorChecker method.
(WebCore::CSSStyleSelector::visitedStateChanged): Ditto.
* dom/Node.cpp:
(WebCore::Node::querySelector): Changed to use a SelectorChecker instead
of the document's style selector.
* dom/SelectorNodeList.cpp:
(WebCore::SelectorNodeList::SelectorNodeList): Ditto.
2008-05-20 Timothy Hatcher <timothy@apple.com>
Implements the Profiles panel and Profile view.
This diff is collapsed.
......@@ -78,7 +78,7 @@ public:
~CSSStyleSelector();
void initElementAndPseudoState(Element*);
void initForStyleResolve(Element*, RenderStyle* parentStyle);
void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, RenderStyle::PseudoId = RenderStyle::NOPSEUDO);
RenderStyle* styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false);
RenderStyle* pseudoStyleForElement(RenderStyle::PseudoId, Element*, RenderStyle* parentStyle = 0);
......@@ -126,15 +126,11 @@ public:
bool affectedByViewportChange() const;
void allVisitedStateChanged();
void visitedStateChanged(unsigned visitedHash);
void allVisitedStateChanged() { m_checker.allVisitedStateChanged(); }
void visitedStateChanged(unsigned visitedHash) { m_checker.visitedStateChanged(visitedHash); }
private:
enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsCompletely };
SelectorMatch checkSelector(CSSSelector*, Element*, bool isAncestor, bool isSubSelector);
// Checks if the selector matches the given Element.
bool checkOneSelector(CSSSelector*, Element*, bool isAncestor, bool isSubSelector = false);
// This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
......@@ -152,8 +148,6 @@ public:
void applyDeclarations(bool firstPass, bool important, int startIndex, int endIndex);
bool m_strictParsing;
CSSRuleSet* m_authorStyle;
CSSRuleSet* m_userStyle;
RefPtr<CSSStyleSheet> m_userSheet;
......@@ -166,6 +160,26 @@ public:
public:
static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; }
class SelectorChecker : public Noncopyable {
public:
SelectorChecker(Document*, bool strictParsing, bool collectRulesOnly = true);
bool checkSelector(CSSSelector*, Element*) const;
SelectorMatch checkSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, RenderStyle::PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, RenderStyle::PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle*, RenderStyle* elementParentStyle) const;
PseudoState checkPseudoState(Element*, bool checkVisited = true) const;
void allVisitedStateChanged();
void visitedStateChanged(unsigned visitedHash);
Document* m_document;
bool m_strictParsing;
bool m_collectRulesOnly;
RenderStyle::PseudoId m_pseudoStyle;
bool m_documentIsHTML;
mutable HashSet<unsigned, AlreadyHashed> m_linksCheckedForVisitedState;
};
private:
static RenderStyle* s_styleNotYetAvailable;
......@@ -198,8 +212,6 @@ public:
#endif
StyleImage* styleImage(CSSValue* value);
PseudoState checkPseudoState(Element*, bool checkVisited = true);
// We collect the set of decls that match in |m_matchedDecls|. We then walk the
// set of matched decls four times, once for those properties that others depend on (like font-size),
......@@ -212,31 +224,27 @@ public:
Vector<CSSRuleData*> m_matchedRules;
CSSRuleList* m_ruleList;
bool m_collectRulesOnly;
MediaQueryEvaluator* m_medium;
RenderStyle* m_rootDefaultStyle;
RenderStyle::PseudoId dynamicPseudo;
RenderStyle::PseudoId m_dynamicPseudo;
SelectorChecker m_checker;
Document* m_document; // back pointer to owner document
RenderStyle* m_style;
RenderStyle* m_parentStyle;
Element* m_element;
StyledElement* m_styledElement;
Node* m_parentNode;
RenderStyle::PseudoId m_pseudoStyle;
CSSValue* m_lineHeightValue;
bool m_fontDirty;
bool m_isXMLDoc;
bool m_matchAuthorAndUserStyles;
RefPtr<CSSFontSelector> m_fontSelector;
HashSet<AtomicStringImpl*> m_selectorAttrs;
Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls;
Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults;
HashSet<unsigned, AlreadyHashed> m_linksCheckedForVisitedState;
};
class CSSRuleData {
......
......@@ -1235,17 +1235,15 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
return 0;
}
CSSStyleSelector* styleSelector = document()->styleSelector();
CSSStyleSelector::SelectorChecker selectorChecker(document(), !document()->inCompatMode());
CSSSelector* querySelector = static_cast<CSSStyleRule*>(rule.get())->selector();
// FIXME: We can speed this up by implementing caching similar to the one use by getElementById
for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
styleSelector->initElementAndPseudoState(element);
styleSelector->initForStyleResolve(element, 0);
for (CSSSelector* selector = querySelector; selector; selector = selector->next()) {
if (styleSelector->checkSelector(selector))
if (selectorChecker.checkSelector(selector, element))
return element;
}
}
......
......@@ -40,14 +40,12 @@ namespace WebCore {
SelectorNodeList::SelectorNodeList(PassRefPtr<Node> rootNode, CSSSelector* querySelector)
{
Document* document = rootNode->document();
CSSStyleSelector* styleSelector = document->styleSelector();
CSSStyleSelector::SelectorChecker selectorChecker(document, !document->inCompatMode());
for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode.get())) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
styleSelector->initElementAndPseudoState(element);
styleSelector->initForStyleResolve(element, 0);
for (CSSSelector* selector = querySelector; selector; selector = selector->next()) {
if (styleSelector->checkSelector(selector)) {
if (selectorChecker.checkSelector(selector, element)) {
m_nodes.append(n);
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment