2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "core/css/StyleSheetContents.h"
24 #include "core/css/CSSStyleSheet.h"
25 #include "core/css/StylePropertySet.h"
26 #include "core/css/StyleRule.h"
27 #include "core/css/StyleRuleImport.h"
28 #include "core/css/StyleRuleNamespace.h"
29 #include "core/css/parser/CSSParser.h"
30 #include "core/dom/Document.h"
31 #include "core/dom/Node.h"
32 #include "core/dom/StyleEngine.h"
33 #include "core/fetch/CSSStyleSheetResource.h"
34 #include "core/frame/UseCounter.h"
35 #include "core/inspector/InspectorTraceEvents.h"
36 #include "platform/TraceEvent.h"
37 #include "platform/weborigin/SecurityOrigin.h"
38 #include "wtf/Deque.h"
42 // Rough size estimate for the memory cache.
43 unsigned StyleSheetContents::estimatedSizeInBytes() const
45 // Note that this does not take into account size of the strings hanging from various objects.
46 // The assumption is that nearly all of of them are atomic and would exist anyway.
47 unsigned size
= sizeof(*this);
49 // FIXME: This ignores the children of media rules.
50 // Most rules are StyleRules.
51 size
+= ruleCount() * StyleRule::averageSizeInBytes();
53 for (unsigned i
= 0; i
< m_importRules
.size(); ++i
) {
54 if (StyleSheetContents
* sheet
= m_importRules
[i
]->styleSheet())
55 size
+= sheet
->estimatedSizeInBytes();
60 StyleSheetContents::StyleSheetContents(StyleRuleImport
* ownerRule
, const String
& originalURL
, const CSSParserContext
& context
)
61 : m_ownerRule(ownerRule
)
62 , m_originalURL(originalURL
)
63 , m_defaultNamespace(starAtom
)
64 , m_hasSyntacticallyValidCSSHeader(true)
65 , m_didLoadErrorOccur(false)
67 , m_isInMemoryCache(false)
68 , m_hasFontFaceRule(false)
69 , m_hasMediaQueries(false)
70 , m_hasSingleOwnerDocument(true)
71 , m_parserContext(context
)
75 StyleSheetContents::StyleSheetContents(const StyleSheetContents
& o
)
76 : m_ownerRule(nullptr)
77 , m_originalURL(o
.m_originalURL
)
78 , m_importRules(o
.m_importRules
.size())
79 , m_namespaceRules(o
.m_namespaceRules
.size())
80 , m_childRules(o
.m_childRules
.size())
81 , m_namespaces(o
.m_namespaces
)
82 , m_defaultNamespace(o
.m_defaultNamespace
)
83 , m_hasSyntacticallyValidCSSHeader(o
.m_hasSyntacticallyValidCSSHeader
)
84 , m_didLoadErrorOccur(false)
86 , m_isInMemoryCache(false)
87 , m_hasFontFaceRule(o
.m_hasFontFaceRule
)
88 , m_hasMediaQueries(o
.m_hasMediaQueries
)
89 , m_hasSingleOwnerDocument(true)
90 , m_parserContext(o
.m_parserContext
)
92 ASSERT(o
.isCacheable());
94 // FIXME: Copy import rules.
95 ASSERT(o
.m_importRules
.isEmpty());
97 for (unsigned i
= 0; i
< m_childRules
.size(); ++i
)
98 m_childRules
[i
] = o
.m_childRules
[i
]->copy();
101 StyleSheetContents::~StyleSheetContents()
108 void StyleSheetContents::setHasSyntacticallyValidCSSHeader(bool isValidCss
)
111 if (Document
* document
= clientSingleOwnerDocument())
112 removeSheetFromCache(document
);
114 m_hasSyntacticallyValidCSSHeader
= isValidCss
;
117 bool StyleSheetContents::isCacheable() const
119 // This would require dealing with multiple clients for load callbacks.
120 if (!loadCompleted())
122 // FIXME: StyleSheets with media queries can't be cached because their RuleSet
123 // is processed differently based off the media queries, which might resolve
124 // differently depending on the context of the parent CSSStyleSheet (e.g.
125 // if they are in differently sized iframes). Once RuleSets are media query
126 // agnostic, we can restore sharing of StyleSheetContents with medea queries.
127 if (m_hasMediaQueries
)
129 // FIXME: Support copying import rules.
130 if (!m_importRules
.isEmpty())
132 // FIXME: Support cached stylesheets in import rules.
135 if (m_didLoadErrorOccur
)
137 // It is not the original sheet anymore.
140 // If the header is valid we are not going to need to check the SecurityOrigin.
141 // FIXME: Valid mime type avoids the check too.
142 if (!m_hasSyntacticallyValidCSSHeader
)
147 void StyleSheetContents::parserAppendRule(PassRefPtrWillBeRawPtr
<StyleRuleBase
> rule
)
149 if (rule
->isImportRule()) {
150 // Parser enforces that @import rules come before anything else
151 ASSERT(m_childRules
.isEmpty());
152 StyleRuleImport
* importRule
= toStyleRuleImport(rule
.get());
153 if (importRule
->mediaQueries())
154 setHasMediaQueries();
155 m_importRules
.append(importRule
);
156 m_importRules
.last()->setParentStyleSheet(this);
157 m_importRules
.last()->requestStyleSheet();
161 if (rule
->isNamespaceRule()) {
162 // Parser enforces that @namespace rules come before all rules other than
163 // import/charset rules
164 ASSERT(m_childRules
.isEmpty());
165 StyleRuleNamespace
& namespaceRule
= toStyleRuleNamespace(*rule
);
166 parserAddNamespace(namespaceRule
.prefix(), namespaceRule
.uri());
167 m_namespaceRules
.append(&namespaceRule
);
171 if (rule
->isMediaRule())
172 setHasMediaQueries();
174 m_childRules
.append(rule
);
177 void StyleSheetContents::setHasMediaQueries()
179 m_hasMediaQueries
= true;
180 if (parentStyleSheet())
181 parentStyleSheet()->setHasMediaQueries();
184 StyleRuleBase
* StyleSheetContents::ruleAt(unsigned index
) const
186 ASSERT_WITH_SECURITY_IMPLICATION(index
< ruleCount());
188 if (index
< m_importRules
.size())
189 return m_importRules
[index
].get();
191 index
-= m_importRules
.size();
193 if (index
< m_namespaceRules
.size())
194 return m_namespaceRules
[index
].get();
196 index
-= m_namespaceRules
.size();
198 return m_childRules
[index
].get();
201 unsigned StyleSheetContents::ruleCount() const
203 return m_importRules
.size() + m_namespaceRules
.size() + m_childRules
.size();
206 void StyleSheetContents::clearRules()
208 for (unsigned i
= 0; i
< m_importRules
.size(); ++i
) {
209 ASSERT(m_importRules
.at(i
)->parentStyleSheet() == this);
210 m_importRules
[i
]->clearParentStyleSheet();
212 m_importRules
.clear();
213 m_namespaceRules
.clear();
214 m_childRules
.clear();
217 bool StyleSheetContents::wrapperInsertRule(PassRefPtrWillBeRawPtr
<StyleRuleBase
> rule
, unsigned index
)
220 ASSERT_WITH_SECURITY_IMPLICATION(index
<= ruleCount());
222 if (index
< m_importRules
.size() || (index
== m_importRules
.size() && rule
->isImportRule())) {
223 // Inserting non-import rule before @import is not allowed.
224 if (!rule
->isImportRule())
227 StyleRuleImport
* importRule
= toStyleRuleImport(rule
.get());
228 if (importRule
->mediaQueries())
229 setHasMediaQueries();
231 m_importRules
.insert(index
, importRule
);
232 m_importRules
[index
]->setParentStyleSheet(this);
233 m_importRules
[index
]->requestStyleSheet();
234 // FIXME: Stylesheet doesn't actually change meaningfully before the imported sheets are loaded.
237 // Inserting @import rule after a non-import rule is not allowed.
238 if (rule
->isImportRule())
241 if (rule
->isMediaRule())
242 setHasMediaQueries();
244 index
-= m_importRules
.size();
246 if (index
< m_namespaceRules
.size() || (index
== m_namespaceRules
.size() && rule
->isNamespaceRule())) {
247 // Inserting non-namespace rules other than import rule before @namespace is not allowed.
248 if (!rule
->isNamespaceRule())
250 // Inserting @namespace rule when rules other than import/namespace/charset are present is not allowed.
251 if (!m_childRules
.isEmpty())
254 StyleRuleNamespace
* namespaceRule
= toStyleRuleNamespace(rule
.get());
255 m_namespaceRules
.insert(index
, namespaceRule
);
256 // For now to be compatible with IE and Firefox if namespace rule with same prefix is added
257 // irrespective of adding the rule at any index, last added rule's value is considered.
258 // TODO (ramya.v@samsung.com): As per spec last valid rule should be considered,
259 // which means if namespace rule is added in the middle of existing namespace rules,
260 // rule which comes later in rule list with same prefix needs to be considered.
261 parserAddNamespace(namespaceRule
->prefix(), namespaceRule
->uri());
265 if (rule
->isNamespaceRule())
268 index
-= m_namespaceRules
.size();
270 if (rule
->isFontFaceRule())
271 setHasFontFaceRule(true);
272 m_childRules
.insert(index
, rule
);
276 bool StyleSheetContents::wrapperDeleteRule(unsigned index
)
279 ASSERT_WITH_SECURITY_IMPLICATION(index
< ruleCount());
281 if (index
< m_importRules
.size()) {
282 m_importRules
[index
]->clearParentStyleSheet();
283 if (m_importRules
[index
]->isFontFaceRule())
284 notifyRemoveFontFaceRule(toStyleRuleFontFace(m_importRules
[index
].get()));
285 m_importRules
.remove(index
);
288 index
-= m_importRules
.size();
290 if (index
< m_namespaceRules
.size()) {
291 if (!m_childRules
.isEmpty())
293 m_namespaceRules
.remove(index
);
296 index
-= m_namespaceRules
.size();
298 if (m_childRules
[index
]->isFontFaceRule())
299 notifyRemoveFontFaceRule(toStyleRuleFontFace(m_childRules
[index
].get()));
300 m_childRules
.remove(index
);
304 void StyleSheetContents::parserAddNamespace(const AtomicString
& prefix
, const AtomicString
& uri
)
306 ASSERT(!uri
.isNull());
307 if (prefix
.isNull()) {
308 m_defaultNamespace
= uri
;
311 PrefixNamespaceURIMap::AddResult result
= m_namespaces
.add(prefix
, uri
);
312 if (result
.isNewEntry
)
314 result
.storedValue
->value
= uri
;
317 const AtomicString
& StyleSheetContents::determineNamespace(const AtomicString
& prefix
)
320 return defaultNamespace();
321 if (prefix
.isEmpty())
322 return emptyAtom
; // No namespace. If an element/attribute has a namespace, we won't match it.
323 if (prefix
== starAtom
)
324 return starAtom
; // We'll match any namespace.
325 return m_namespaces
.get(prefix
);
328 void StyleSheetContents::parseAuthorStyleSheet(const CSSStyleSheetResource
* cachedStyleSheet
, const SecurityOrigin
* securityOrigin
)
330 TRACE_EVENT1("blink,devtools.timeline", "ParseAuthorStyleSheet", "data", InspectorParseAuthorStyleSheetEvent::data(cachedStyleSheet
));
332 bool isSameOriginRequest
= securityOrigin
&& securityOrigin
->canRequest(baseURL());
333 CSSStyleSheetResource::MIMETypeCheck mimeTypeCheck
= isQuirksModeBehavior(m_parserContext
.mode()) && isSameOriginRequest
? CSSStyleSheetResource::MIMETypeCheck::Lax
: CSSStyleSheetResource::MIMETypeCheck::Strict
;
334 String sheetText
= cachedStyleSheet
->sheetText(mimeTypeCheck
);
336 const ResourceResponse
& response
= cachedStyleSheet
->response();
337 m_sourceMapURL
= response
.httpHeaderField("SourceMap");
338 if (m_sourceMapURL
.isEmpty()) {
339 // Try to get deprecated header.
340 m_sourceMapURL
= response
.httpHeaderField("X-SourceMap");
343 CSSParserContext
context(parserContext(), UseCounter::getFrom(this));
344 CSSParser::parseSheet(context
, this, sheetText
);
347 void StyleSheetContents::parseString(const String
& sheetText
)
349 parseStringAtPosition(sheetText
, TextPosition::minimumPosition());
352 void StyleSheetContents::parseStringAtPosition(const String
& sheetText
, const TextPosition
& startPosition
)
354 CSSParserContext
context(parserContext(), UseCounter::getFrom(this));
355 CSSParser::parseSheet(context
, this, sheetText
);
358 bool StyleSheetContents::isLoading() const
360 for (unsigned i
= 0; i
< m_importRules
.size(); ++i
) {
361 if (m_importRules
[i
]->isLoading())
367 bool StyleSheetContents::loadCompleted() const
369 StyleSheetContents
* parentSheet
= parentStyleSheet();
371 return parentSheet
->loadCompleted();
373 StyleSheetContents
* root
= rootStyleSheet();
374 return root
->m_loadingClients
.isEmpty();
377 void StyleSheetContents::checkLoaded()
382 // Avoid |this| being deleted by scripts that run via
383 // ScriptableDocumentParser::executeScriptsWaitingForResources().
384 // See https://bugs.webkit.org/show_bug.cgi?id=95106
385 RefPtrWillBeRawPtr
<StyleSheetContents
> protect(this);
387 StyleSheetContents
* parentSheet
= parentStyleSheet();
389 parentSheet
->checkLoaded();
393 ASSERT(this == rootStyleSheet());
394 if (m_loadingClients
.isEmpty())
397 // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run via
398 // ScriptableDocumentParser::executeScriptsWaitingForResources(). Also protect
399 // the |CSSStyleSheet| from being deleted during iteration via the |sheetLoaded|
402 // When a sheet is loaded it is moved from the set of loading clients
403 // to the set of completed clients. We therefore need the copy in order to
404 // not modify the set while iterating it.
405 WillBeHeapVector
<RefPtrWillBeMember
<CSSStyleSheet
>> loadingClients
;
406 copyToVector(m_loadingClients
, loadingClients
);
408 for (unsigned i
= 0; i
< loadingClients
.size(); ++i
) {
409 if (loadingClients
[i
]->loadCompleted())
412 // sheetLoaded might be invoked after its owner node is removed from document.
413 if (RefPtrWillBeRawPtr
<Node
> ownerNode
= loadingClients
[i
]->ownerNode()) {
414 if (loadingClients
[i
]->sheetLoaded())
415 ownerNode
->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur
? Node::ErrorOccurredLoadingSubresource
: Node::NoErrorLoadingSubresource
);
420 void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource
* sheet
)
423 m_didLoadErrorOccur
|= sheet
->errorOccurred();
424 // updateLayoutIgnorePendingStyleSheets can cause us to create the RuleSet on this
425 // sheet before its imports have loaded. So clear the RuleSet when the imports
426 // load since the import's subrules are flattened into its parent sheet's RuleSet.
430 void StyleSheetContents::startLoadingDynamicSheet()
432 StyleSheetContents
* root
= rootStyleSheet();
433 for (const auto& client
: root
->m_loadingClients
)
434 client
->startLoadingDynamicSheet();
435 // Copy the completed clients to a vector for iteration.
436 // startLoadingDynamicSheet will move the style sheet from the
437 // completed state to the loading state which modifies the set of
438 // completed clients. We therefore need the copy in order to not
439 // modify the set of completed clients while iterating it.
440 WillBeHeapVector
<RawPtrWillBeMember
<CSSStyleSheet
>> completedClients
;
441 copyToVector(root
->m_completedClients
, completedClients
);
442 for (unsigned i
= 0; i
< completedClients
.size(); ++i
)
443 completedClients
[i
]->startLoadingDynamicSheet();
446 StyleSheetContents
* StyleSheetContents::rootStyleSheet() const
448 const StyleSheetContents
* root
= this;
449 while (root
->parentStyleSheet())
450 root
= root
->parentStyleSheet();
451 return const_cast<StyleSheetContents
*>(root
);
454 bool StyleSheetContents::hasSingleOwnerNode() const
456 return rootStyleSheet()->hasOneClient();
459 Node
* StyleSheetContents::singleOwnerNode() const
461 StyleSheetContents
* root
= rootStyleSheet();
462 if (!root
->hasOneClient())
464 if (root
->m_loadingClients
.size())
465 return (*root
->m_loadingClients
.begin())->ownerNode();
466 return (*root
->m_completedClients
.begin())->ownerNode();
469 Document
* StyleSheetContents::singleOwnerDocument() const
471 StyleSheetContents
* root
= rootStyleSheet();
472 return root
->clientSingleOwnerDocument();
475 static bool childRulesHaveFailedOrCanceledSubresources(const WillBeHeapVector
<RefPtrWillBeMember
<StyleRuleBase
>>& rules
)
477 for (unsigned i
= 0; i
< rules
.size(); ++i
) {
478 const StyleRuleBase
* rule
= rules
[i
].get();
479 switch (rule
->type()) {
480 case StyleRuleBase::Style
:
481 if (toStyleRule(rule
)->properties().hasFailedOrCanceledSubresources())
484 case StyleRuleBase::FontFace
:
485 if (toStyleRuleFontFace(rule
)->properties().hasFailedOrCanceledSubresources())
488 case StyleRuleBase::Media
:
489 if (childRulesHaveFailedOrCanceledSubresources(toStyleRuleMedia(rule
)->childRules()))
492 case StyleRuleBase::Charset
:
493 case StyleRuleBase::Import
:
494 case StyleRuleBase::Namespace
:
495 ASSERT_NOT_REACHED();
496 case StyleRuleBase::Page
:
497 case StyleRuleBase::Keyframes
:
498 case StyleRuleBase::Keyframe
:
499 case StyleRuleBase::Supports
:
500 case StyleRuleBase::Viewport
:
507 bool StyleSheetContents::hasFailedOrCanceledSubresources() const
509 ASSERT(isCacheable());
510 return childRulesHaveFailedOrCanceledSubresources(m_childRules
);
513 Document
* StyleSheetContents::clientSingleOwnerDocument() const
515 if (!m_hasSingleOwnerDocument
|| clientSize() <= 0)
518 if (m_loadingClients
.size())
519 return (*m_loadingClients
.begin())->ownerDocument();
520 return (*m_completedClients
.begin())->ownerDocument();
523 StyleSheetContents
* StyleSheetContents::parentStyleSheet() const
525 return m_ownerRule
? m_ownerRule
->parentStyleSheet() : nullptr;
528 void StyleSheetContents::registerClient(CSSStyleSheet
* sheet
)
530 ASSERT(!m_loadingClients
.contains(sheet
) && !m_completedClients
.contains(sheet
));
532 // InspectorCSSAgent::buildObjectForRule creates CSSStyleSheet without any owner node.
533 if (!sheet
->ownerDocument())
536 if (Document
* document
= clientSingleOwnerDocument()) {
537 if (sheet
->ownerDocument() != document
)
538 m_hasSingleOwnerDocument
= false;
540 m_loadingClients
.add(sheet
);
543 void StyleSheetContents::unregisterClient(CSSStyleSheet
* sheet
)
545 m_loadingClients
.remove(sheet
);
546 m_completedClients
.remove(sheet
);
548 if (!sheet
->ownerDocument() || !m_loadingClients
.isEmpty() || !m_completedClients
.isEmpty())
551 if (m_hasSingleOwnerDocument
)
552 removeSheetFromCache(sheet
->ownerDocument());
553 m_hasSingleOwnerDocument
= true;
556 void StyleSheetContents::clientLoadCompleted(CSSStyleSheet
* sheet
)
558 ASSERT(m_loadingClients
.contains(sheet
) || !sheet
->ownerDocument());
559 m_loadingClients
.remove(sheet
);
560 // In m_ownerNode->sheetLoaded, the CSSStyleSheet might be detached.
561 // (i.e. clearOwnerNode was invoked.)
562 // In this case, we don't need to add the stylesheet to completed clients.
563 if (!sheet
->ownerDocument())
565 m_completedClients
.add(sheet
);
568 void StyleSheetContents::clientLoadStarted(CSSStyleSheet
* sheet
)
570 ASSERT(m_completedClients
.contains(sheet
));
571 m_completedClients
.remove(sheet
);
572 m_loadingClients
.add(sheet
);
575 void StyleSheetContents::removeSheetFromCache(Document
* document
)
578 document
->styleEngine().removeSheet(this);
581 void StyleSheetContents::addedToMemoryCache()
583 ASSERT(!m_isInMemoryCache
);
584 ASSERT(isCacheable());
585 m_isInMemoryCache
= true;
588 void StyleSheetContents::removedFromMemoryCache()
590 ASSERT(m_isInMemoryCache
);
591 ASSERT(isCacheable());
592 m_isInMemoryCache
= false;
595 RuleSet
& StyleSheetContents::ensureRuleSet(const MediaQueryEvaluator
& medium
, AddRuleFlags addRuleFlags
)
598 m_ruleSet
= RuleSet::create();
599 m_ruleSet
->addRulesFromSheet(this, medium
, addRuleFlags
);
601 return *m_ruleSet
.get();
604 static void clearResolvers(WillBeHeapHashSet
<RawPtrWillBeWeakMember
<CSSStyleSheet
>>& clients
)
606 for (const auto& sheet
: clients
) {
607 if (Document
* document
= sheet
->ownerDocument())
608 document
->styleEngine().clearResolver();
612 void StyleSheetContents::clearRuleSet()
614 if (StyleSheetContents
* parentSheet
= parentStyleSheet())
615 parentSheet
->clearRuleSet();
617 // Don't want to clear the StyleResolver if the RuleSet hasn't been created
618 // since we only clear the StyleResolver so that it's members are properly
619 // updated in ScopedStyleResolver::addRulesFromSheet.
623 // Clearing the ruleSet means we need to recreate the styleResolver data structures.
624 // See the StyleResolver calls in ScopedStyleResolver::addRulesFromSheet.
625 clearResolvers(m_loadingClients
);
626 clearResolvers(m_completedClients
);
630 static void removeFontFaceRules(WillBeHeapHashSet
<RawPtrWillBeWeakMember
<CSSStyleSheet
>>& clients
, const StyleRuleFontFace
* fontFaceRule
)
632 for (const auto& sheet
: clients
) {
633 if (Node
* ownerNode
= sheet
->ownerNode())
634 ownerNode
->document().styleEngine().removeFontFaceRules(WillBeHeapVector
<RawPtrWillBeMember
<const StyleRuleFontFace
>>(1, fontFaceRule
));
638 void StyleSheetContents::notifyRemoveFontFaceRule(const StyleRuleFontFace
* fontFaceRule
)
640 StyleSheetContents
* root
= rootStyleSheet();
641 removeFontFaceRules(root
->m_loadingClients
, fontFaceRule
);
642 removeFontFaceRules(root
->m_completedClients
, fontFaceRule
);
645 static void findFontFaceRulesFromRules(const WillBeHeapVector
<RefPtrWillBeMember
<StyleRuleBase
>>& rules
, WillBeHeapVector
<RawPtrWillBeMember
<const StyleRuleFontFace
>>& fontFaceRules
)
647 for (unsigned i
= 0; i
< rules
.size(); ++i
) {
648 StyleRuleBase
* rule
= rules
[i
].get();
650 if (rule
->isFontFaceRule()) {
651 fontFaceRules
.append(toStyleRuleFontFace(rule
));
652 } else if (rule
->isMediaRule()) {
653 StyleRuleMedia
* mediaRule
= toStyleRuleMedia(rule
);
654 // We cannot know whether the media rule matches or not, but
655 // for safety, remove @font-face in the media rule (if exists).
656 findFontFaceRulesFromRules(mediaRule
->childRules(), fontFaceRules
);
661 void StyleSheetContents::findFontFaceRules(WillBeHeapVector
<RawPtrWillBeMember
<const StyleRuleFontFace
>>& fontFaceRules
)
663 for (unsigned i
= 0; i
< m_importRules
.size(); ++i
) {
664 if (!m_importRules
[i
]->styleSheet())
666 m_importRules
[i
]->styleSheet()->findFontFaceRules(fontFaceRules
);
669 findFontFaceRulesFromRules(childRules(), fontFaceRules
);
672 DEFINE_TRACE(StyleSheetContents
)
675 visitor
->trace(m_ownerRule
);
676 visitor
->trace(m_importRules
);
677 visitor
->trace(m_namespaceRules
);
678 visitor
->trace(m_childRules
);
679 visitor
->trace(m_loadingClients
);
680 visitor
->trace(m_completedClients
);
681 visitor
->trace(m_ruleSet
);