Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(601)

Side by Side Diff: Source/core/html/HTMLImport.cpp

Issue 141143006: [import] Cleanup: get rid of ad-hoc state machine. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Updated to ToT Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/HTMLImport.h ('k') | Source/core/html/HTMLImportChild.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 14 matching lines...) Expand all
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/html/HTMLImport.h" 32 #include "core/html/HTMLImport.h"
33 33
34 #include "core/dom/Document.h" 34 #include "core/dom/Document.h"
35 #include "core/html/HTMLImportStateResolver.h"
35 36
36 namespace WebCore { 37 namespace WebCore {
37 38
38 Frame* HTMLImport::frame() 39 Frame* HTMLImport::frame()
39 { 40 {
40 return master()->frame(); 41 return master()->frame();
41 } 42 }
42 43
43 Document* HTMLImport::master() 44 Document* HTMLImport::master()
44 { 45 {
45 return root()->document(); 46 return root()->document();
46 } 47 }
47 48
48 HTMLImportsController* HTMLImport::controller() 49 HTMLImportsController* HTMLImport::controller()
49 { 50 {
50 return root()->toController(); 51 return root()->toController();
51 } 52 }
52 53
53 void HTMLImport::appendChild(HTMLImport* child) 54 void HTMLImport::appendChild(HTMLImport* child)
54 { 55 {
55 if (isBlockedFromRunningScript())
56 child->blockFromRunningScript();
57 TreeNode<HTMLImport>::appendChild(child); 56 TreeNode<HTMLImport>::appendChild(child);
57
58 // This prevents HTML parser from going beyond the
59 // blockage line before the precise state is computed by recalcState().
58 if (child->isCreatedByParser()) 60 if (child->isCreatedByParser())
59 blockPredecessorsOf(child); 61 forceBlock();
62
63 stateWillChange();
60 } 64 }
61 65
62 bool HTMLImport::isBlockedFromCreatingDocument() const 66 void HTMLImport::stateDidChange()
63 { 67 {
64 if (hasLoader()) 68 if (!isStateBlockedFromRunningScript()) {
65 return false; 69 if (Document* document = this->document())
66 return previous() && previous()->isBlockingFollowersFromCreatingDocument(); 70 document->didLoadAllImports();
71 }
67 } 72 }
68 73
69 bool HTMLImport::isBlockedFromRunningScriptByPredecessors() const 74 void HTMLImport::recalcState()
70 { 75 {
71 HTMLImport* parent = this->parent(); 76 ASSERT(!isStateCacheValid());
72 if (!parent) 77 m_cachedState = HTMLImportStateResolver(this).resolve();
73 return false; 78 }
74 79
75 for (HTMLImport* sibling = parent->firstChild(); sibling; sibling = sibling- >next()) { 80 void HTMLImport::forceBlock()
76 if (sibling == this) 81 {
77 break; 82 ASSERT(m_cachedState != Ready);
78 if (sibling->isBlockingFollowersFromRunningScript()) 83 m_cachedState = BlockedFromCreatingDocument;
79 return true; 84 }
85
86 void HTMLImport::stateWillChange()
87 {
88 root()->scheduleRecalcState();
89 }
90
91 void HTMLImport::recalcTreeState(HTMLImport* root)
92 {
93 ASSERT(root == root->root());
94
95 HashMap<HTMLImport*, State> snapshot;
96 Vector<HTMLImport*> updated;
97
98 for (HTMLImport* i = root; i; i = traverseNext(i)) {
99 snapshot.add(i, i->state());
100 i->invalidateCachedState();
80 } 101 }
81 102
82 return false; 103 // The post-visit DFS order matters here because
83 } 104 // HTMLImportStateResolver in recalcState() Depends on
105 // |m_cachedState| of its children and precedents of ancestors.
106 // Accidental cycle dependency of state computation is prevented
107 // by invalidateCachedState() and isStateCacheValid() check.
108 for (HTMLImport* i = traverseFirstPostOrder(root); i; i = traverseNextPostOr der(i)) {
109 i->recalcState();
84 110
85 void HTMLImport::waitLoaderOrChildren() 111 State newState = i->state();
86 { 112 State oldState = snapshot.get(i);
87 if (WaitingLoaderOrChildren < m_state) 113 // Once the state reaches Ready, it shouldn't go back.
88 m_state = WaitingLoaderOrChildren; 114 ASSERT(oldState != Ready || oldState <= newState);
89 } 115 if (newState != oldState)
90 116 updated.append(i);
91 void HTMLImport::blockFromRunningScript()
92 {
93 if (BlockedFromRunningScript < m_state)
94 m_state = BlockedFromRunningScript;
95 }
96
97 void HTMLImport::becomeReady()
98 {
99 if (!isBlocked())
100 return;
101 m_state = Ready;
102 didBecomeReady();
103 }
104
105 void HTMLImport::unblockFromRunningScript()
106 {
107 if (!isBlockedFromRunningScript())
108 return;
109 m_state = WaitingLoaderOrChildren;
110 didUnblockFromRunningScript();
111 }
112
113 void HTMLImport::didUnblockFromRunningScript()
114 {
115 ASSERT(!isBlockedFromCreatingDocument());
116 ASSERT(!isBlockedFromRunningScript());
117 if (Document* document = this->document())
118 document->didLoadAllImports();
119 }
120
121 void HTMLImport::didBecomeReady()
122 {
123 ASSERT(isDone());
124 }
125
126 void HTMLImport::didUnblockFromCreatingDocument()
127 {
128 ASSERT(!isBlockedFromCreatingDocument());
129 }
130
131 void HTMLImport::loaderWasResolved()
132 {
133 unblockFromRunningScript();
134 }
135
136 void HTMLImport::loaderDidFinish()
137 {
138 if (m_state == WaitingLoaderOrChildren)
139 becomeReady();
140 root()->blockerGone();
141 }
142
143 inline bool HTMLImport::isBlockingFollowersFromRunningScript() const
144 {
145 if (!isCreatedByParser())
146 return false;
147 if (isBlockedFromRunningScript())
148 return true;
149 // Blocking here can result dead lock if the node doesn't own loader and has shared loader.
150 // Because the shared loader can point its ascendant and forms a cycle.
151 if (!ownsLoader())
152 return false;
153 return !isDone();
154 }
155
156 inline bool HTMLImport::isBlockingFollowersFromCreatingDocument() const
157 {
158 return !isDone();
159 }
160
161 bool HTMLImport::unblock(HTMLImport* import)
162 {
163 ASSERT(!import->isBlockedFromRunningScriptByPredecessors());
164
165 if (import->isBlockedFromCreatingDocument())
166 return false;
167 import->didUnblockFromCreatingDocument();
168
169 for (HTMLImport* child = import->firstChild(); child; child = child->next()) {
170 if (!unblock(child))
171 return false;
172 } 117 }
173 118
174 import->unblockFromRunningScript(); 119 for (size_t i = 0; i < updated.size(); ++i)
175 if (import->isDone()) 120 updated[i]->stateDidChange();
176 import->becomeReady();
177
178 return !import->isBlockingFollowersFromRunningScript();
179 }
180
181 void HTMLImport::block(HTMLImport* import)
182 {
183 for (HTMLImport* child = import; child; child = traverseNext(child, import))
184 child->blockFromRunningScript();
185 }
186
187 void HTMLImport::blockPredecessorsOf(HTMLImport* child)
188 {
189 ASSERT(child->parent() == this);
190
191 for (HTMLImport* sibling = lastChild(); sibling; sibling = sibling->previous ()) {
192 if (sibling == child)
193 break;
194 HTMLImport::block(sibling);
195 }
196
197 this->blockFromRunningScript();
198
199 if (HTMLImport* parent = this->parent()) {
200 if (isCreatedByParser())
201 parent->blockPredecessorsOf(this);
202 }
203 } 121 }
204 122
205 bool HTMLImport::isMaster(Document* document) 123 bool HTMLImport::isMaster(Document* document)
206 { 124 {
207 if (!document->import()) 125 if (!document->import())
208 return true; 126 return true;
209 return (document->import()->master() == document); 127 return (document->import()->master() == document);
210 } 128 }
211 129
130 #if !defined(NDEBUG)
131 void HTMLImport::show()
132 {
133 root()->showTree(this, 0);
134 }
135
136 void HTMLImport::showTree(HTMLImport* highlight, unsigned depth)
137 {
138 for (unsigned i = 0; i < depth*4; ++i)
139 fprintf(stderr, " ");
140
141 fprintf(stderr, "%s", this == highlight ? "*" : " ");
142 showThis();
143 fprintf(stderr, "\n");
144 for (HTMLImport* child = firstChild(); child; child = child->next())
145 child->showTree(highlight, depth + 1);
146 }
147
148 void HTMLImport::showThis()
149 {
150 fprintf(stderr, "%p state=%d", this, m_cachedState);
151 }
152 #endif
153
212 } // namespace WebCore 154 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/html/HTMLImport.h ('k') | Source/core/html/HTMLImportChild.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698