1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 29 */ 30 31 #include "config.h" 32 #include "core/html/imports/HTMLImport.h" 33 34 #include "core/dom/Document.h" 35 #include "core/html/imports/HTMLImportStateResolver.h" 36 37 namespace WebCore { 38 39 HTMLImport* HTMLImport::root() 40 { 41 HTMLImport* i = this; 42 while (i->parent()) 43 i = i->parent(); 44 return i; 45 } 46 47 bool HTMLImport::precedes(HTMLImport* import) 48 { 49 for (HTMLImport* i = this; i; i = traverseNext(i)) { 50 if (i == import) 51 return true; 52 } 53 54 return false; 55 } 56 57 bool HTMLImport::formsCycle() const 58 { 59 for (const HTMLImport* i = this->parent(); i; i = i->parent()) { 60 if (i->document() == this->document()) 61 return true; 62 } 63 64 return false; 65 66 } 67 68 void HTMLImport::appendImport(HTMLImport* child) 69 { 70 appendChild(child); 71 72 // This prevents HTML parser from going beyond the 73 // blockage line before the precise state is computed by recalcState(). 74 if (child->isSync()) 75 m_state = HTMLImportState::blockedState(); 76 77 stateWillChange(); 78 } 79 80 void HTMLImport::stateDidChange() 81 { 82 if (!state().shouldBlockScriptExecution()) { 83 if (Document* document = this->document()) 84 document->didLoadAllImports(); 85 } 86 } 87 88 void HTMLImport::recalcTreeState(HTMLImport* root) 89 { 90 HashMap<HTMLImport*, HTMLImportState> snapshot; 91 Vector<HTMLImport*> updated; 92 93 for (HTMLImport* i = root; i; i = traverseNext(i)) { 94 snapshot.add(i, i->state()); 95 i->m_state = HTMLImportState::invalidState(); 96 } 97 98 // The post-visit DFS order matters here because 99 // HTMLImportStateResolver in recalcState() Depends on 100 // |m_state| of its children and precedents of ancestors. 101 // Accidental cycle dependency of state computation is prevented 102 // by invalidateCachedState() and isStateCacheValid() check. 103 for (HTMLImport* i = traverseFirstPostOrder(root); i; i = traverseNextPostOrder(i)) { 104 ASSERT(!i->m_state.isValid()); 105 i->m_state = HTMLImportStateResolver(i).resolve(); 106 107 HTMLImportState newState = i->state(); 108 HTMLImportState oldState = snapshot.get(i); 109 // Once the state reaches Ready, it shouldn't go back. 110 ASSERT(!oldState.isReady() || oldState <= newState); 111 if (newState != oldState) 112 updated.append(i); 113 } 114 115 for (size_t i = 0; i < updated.size(); ++i) 116 updated[i]->stateDidChange(); 117 } 118 119 #if !defined(NDEBUG) 120 void HTMLImport::show() 121 { 122 root()->showTree(this, 0); 123 } 124 125 void HTMLImport::showTree(HTMLImport* highlight, unsigned depth) 126 { 127 for (unsigned i = 0; i < depth*4; ++i) 128 fprintf(stderr, " "); 129 130 fprintf(stderr, "%s", this == highlight ? "*" : " "); 131 showThis(); 132 fprintf(stderr, "\n"); 133 for (HTMLImport* child = firstChild(); child; child = child->next()) 134 child->showTree(highlight, depth + 1); 135 } 136 137 void HTMLImport::showThis() 138 { 139 fprintf(stderr, "%p state=%d", this, m_state.peekValueForDebug()); 140 } 141 #endif 142 143 } // namespace WebCore 144