1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef StyleResolverParentScope_h
6#define StyleResolverParentScope_h
7
8#include "core/css/resolver/StyleResolver.h"
9#include "core/dom/Document.h"
10#include "core/dom/Element.h"
11#include "core/dom/shadow/ShadowRoot.h"
12
13namespace blink {
14
15// Maintains the parent element stack (and bloom filter) inside recalcStyle.
16class StyleResolverParentScope FINAL {
17    STACK_ALLOCATED();
18public:
19    explicit StyleResolverParentScope(Node& parent);
20    ~StyleResolverParentScope();
21
22    static void ensureParentStackIsPushed();
23
24private:
25    void pushParentIfNeeded();
26    Node& parent() const { return *m_parent; }
27
28    RawPtrWillBeMember<Node> m_parent;
29    bool m_pushed;
30    StyleResolverParentScope* m_previous;
31    StyleResolver& m_resolver;
32
33    static StyleResolverParentScope* s_currentScope;
34};
35
36inline StyleResolverParentScope::StyleResolverParentScope(Node& parent)
37    : m_parent(parent)
38    , m_pushed(false)
39    , m_previous(s_currentScope)
40    , m_resolver(*parent.document().styleResolver())
41{
42    ASSERT(parent.document().inStyleRecalc());
43    ASSERT(parent.isElementNode() || parent.isShadowRoot());
44    s_currentScope = this;
45    m_resolver.increaseStyleSharingDepth();
46}
47
48inline StyleResolverParentScope::~StyleResolverParentScope()
49{
50    s_currentScope = m_previous;
51    m_resolver.decreaseStyleSharingDepth();
52    if (!m_pushed)
53        return;
54    if (parent().isElementNode())
55        m_resolver.popParentElement(toElement(parent()));
56}
57
58inline void StyleResolverParentScope::ensureParentStackIsPushed()
59{
60    if (s_currentScope)
61        s_currentScope->pushParentIfNeeded();
62}
63
64inline void StyleResolverParentScope::pushParentIfNeeded()
65{
66    if (m_pushed)
67        return;
68    if (m_previous)
69        m_previous->pushParentIfNeeded();
70    if (parent().isElementNode())
71        m_resolver.pushParentElement(toElement(parent()));
72    m_pushed = true;
73}
74
75} // namespace blink
76
77#endif // StyleResolverParentScope_h
78