1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* 2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2008 Apple Inc. All rights reserved. 38f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2009 Google Inc. All rights reserved. 4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without 6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions 7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * are met: 8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer. 10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * documentation and/or other materials provided with the distribution. 13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h" 28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSSelectorList.h" 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "CSSParserValues.h" 312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore { 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic CSSSelector* const freedSelectorArrayMarker = reinterpret_cast<CSSSelector*>(0xbbadbeef); 3581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectCSSSelectorList::~CSSSelectorList() 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project deleteSelectors(); 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid CSSSelectorList::adopt(CSSSelectorList& list) 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project deleteSelectors(); 44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_selectorArray = list.m_selectorArray; 45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project list.m_selectorArray = 0; 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 482fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector) 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project deleteSelectors(); 512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const size_t vectorSize = selectorVector.size(); 522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block size_t flattenedSize = 0; 532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for (size_t i = 0; i < vectorSize; ++i) { 542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory()) 552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ++flattenedSize; 562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(flattenedSize); 582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (flattenedSize == 1) { 592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_selectorArray = selectorVector[0]->releaseSelector().leakPtr(); 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_selectorArray->setLastInSelectorList(); 612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(m_selectorArray->isLastInTagHistory()); 62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project selectorVector.shrink(0); 63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize)); 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block size_t arrayIndex = 0; 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for (size_t i = 0; i < vectorSize; ++i) { 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CSSParserSelector* current = selectorVector[i].get(); 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (current) { 702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block OwnPtr<CSSSelector> selector = current->releaseSelector(); 712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block current = current->tagHistory(); 722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block move(selector.release(), &m_selectorArray[arrayIndex]); 732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList()); 742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (current) 752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_selectorArray[arrayIndex].setNotLastInTagHistory(); 762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ++arrayIndex; 772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory()); 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(flattenedSize == arrayIndex); 812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_selectorArray[arrayIndex - 1].setLastInSelectorList(); 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project selectorVector.shrink(0); 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid CSSSelectorList::deleteSelectors() 86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_selectorArray) 88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 902bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: Remove once http://webkit.org/b/56124 is fixed. 9181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (m_selectorArray == freedSelectorArrayMarker) 9281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CRASH(); 9381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // We had two cases in adoptSelectVector. The fast case of a 1 element 958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // vector took the CSSSelector directly, which was allocated with new. 968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // The second case we allocated a new fastMalloc buffer, which should be 978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // freed with fastFree, and the destructors called manually. 98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CSSSelector* s = m_selectorArray; 998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool done = s->isLastInSelectorList(); 1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (done) 1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian delete s; 1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (1) { 1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian s->~CSSSelector(); 1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (done) 1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ++s; 1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian done = s->isLastInSelectorList(); 1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian fastFree(m_selectorArray); 111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 11281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 11381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_selectorArray = freedSelectorArrayMarker; 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <typename Functor> 118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic bool forEachTagSelector(Functor& functor, CSSSelector* selector) 119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(selector); 121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block do { 123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (functor(selector)) 124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 1252bde8e466a4451c7319e3a072d118917957d6554Steve Block if (CSSSelectorList* selectorList = selector->selectorList()) { 1262bde8e466a4451c7319e3a072d118917957d6554Steve Block for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { 1272bde8e466a4451c7319e3a072d118917957d6554Steve Block if (forEachTagSelector(functor, subSelector)) 1282bde8e466a4451c7319e3a072d118917957d6554Steve Block return true; 1292bde8e466a4451c7319e3a072d118917957d6554Steve Block } 130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } while ((selector = selector->tagHistory())); 132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <typename Functor> 137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList) 138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { 140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (forEachTagSelector(functor, selector)) 141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockclass SelectorNeedsNamespaceResolutionFunctor { 148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic: 149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block bool operator()(CSSSelector* selector) 150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block { 1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom) 152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (selector->hasAttribute() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom) 154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}; 158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool CSSSelectorList::selectorsNeedNamespaceResolution() 160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block SelectorNeedsNamespaceResolutionFunctor functor; 162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return forEachSelector(functor, this); 163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 16565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochclass SelectorHasUnknownPseudoElementFunctor { 16665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochpublic: 16765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch bool operator()(CSSSelector* selector) 16865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch { 16965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return selector->isUnknownPseudoElement(); 17065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 17165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}; 17265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 17365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool CSSSelectorList::hasUnknownPseudoElements() const 17465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{ 17565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch SelectorHasUnknownPseudoElementFunctor functor; 17665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return forEachSelector(functor, this); 17765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch} 17865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 17965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 18065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} // namespace WebCore 182