| OLD | NEW |
| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 // Check around HTMLImportsController::findLink() for more detail. | 80 // Check around HTMLImportsController::findLink() for more detail. |
| 81 // | 81 // |
| 82 // Note that HTMLImportLoader provides HTMLImportLoaderClient to hook it up. | 82 // Note that HTMLImportLoader provides HTMLImportLoaderClient to hook it up. |
| 83 // As it can be shared, HTMLImportLoader supports multiple clients. | 83 // As it can be shared, HTMLImportLoader supports multiple clients. |
| 84 // | 84 // |
| 85 // HTMLImportChild (1)-->(*) HTMLImportLoader | 85 // HTMLImportChild (1)-->(*) HTMLImportLoader |
| 86 // | 86 // |
| 87 // | 87 // |
| 88 // # Script Blocking | 88 // # Script Blocking |
| 89 // | 89 // |
| 90 // The HTML parser blocks on <script> when preceding <link>s aren't finish loadi
ng imports. | 90 // - An import blocks the HTML parser of its own imported document from running
<script> |
| 91 // Each HTMLImport instance tracks such a blocking state, that is called "script
-blocked" | 91 // until all of its children are loaded. |
| 92 // or HTMLImport::isBlockedFromRunningScript(). | 92 // Note that dynamically added import won't block the parser. |
| 93 // | 93 // |
| 94 // ## Blocking Imports | 94 // - An import under loading also blocks imported documents that follow from bei
ng created. |
| 95 // | 95 // This is because an import can include another import that has same URLs of
following ones. |
| 96 // Each imports can become being script-blocked when new imports are added to th
e import tree. | 96 // In such case, the preceding import should be loaded and following ones shou
ld be de-duped. |
| 97 // For example, the parser of a parent import is blocked when new child import i
s given. | |
| 98 // See HTMLImport::appendChild() to see how it is handled. Note that this blocki
ng-ness is | |
| 99 // transitive. HTMLImport::blockPredecessorsOf() flips the flags iteratively to
fullfill this transitivity. | |
| 100 // | |
| 101 // ## Unblocking Imports | |
| 102 // | |
| 103 // The blocking state can change when one of the imports finish loading. The Doc
ument notices it through | |
| 104 // HTMLImportRoot::blockerGone(). The blockerGone() triggers HTMLImport::unblock
FromRunningScript(), which traverses | |
| 105 // whole import tree and find unblock-able imports and unblock them. | |
| 106 // Ready imported documents are notified through Document::didLoadAllImports() s
o that | |
| 107 // it can resume its parser. | |
| 108 // | |
| 109 // # Document Blocking | |
| 110 // | |
| 111 // There is another type of blocking state that is called | |
| 112 // "document-blocked". If the import is document-blocked, it cannot | |
| 113 // create its own document object because sharable imported document | |
| 114 // can appear later. The spec defines the loading order of the | |
| 115 // import: The earlier one in the import-tree order should win and | |
| 116 // later ones should share earlier one. | |
| 117 // | |
| 118 // The "document-blocked" state keeps the tree node from loading its | |
| 119 // import until all preceding imports are ready t respect the | |
| 120 // order. Note that the node may fetch the bytes from the URL | |
| 121 // speculatively, even though it doesn't process it. | |
| 122 // | |
| 123 // The node is "document-unblocked" when there are unfinished, | |
| 124 // preceeding import loading. Unblocking attempt for | |
| 125 // "document-blocked" happens at the same timing as unblocking | |
| 126 // "script-blocked". | |
| 127 // | 97 // |
| 128 | 98 |
| 129 // The superclass of HTMLImportsController and HTMLImportChild | 99 // The superclass of HTMLImportsController and HTMLImportChild |
| 130 // This represents the import tree data structure. | 100 // This represents the import tree data structure. |
| 131 class HTMLImport : public TreeNode<HTMLImport> { | 101 class HTMLImport : public TreeNode<HTMLImport> { |
| 132 public: | 102 public: |
| 133 static bool unblock(HTMLImport*); | |
| 134 static bool isMaster(Document*); | 103 static bool isMaster(Document*); |
| 135 | 104 |
| 136 virtual ~HTMLImport() { } | 105 virtual ~HTMLImport() { } |
| 137 | 106 |
| 138 Frame* frame(); | 107 Frame* frame(); |
| 139 Document* master(); | 108 Document* master(); |
| 140 HTMLImportsController* controller(); | 109 HTMLImportsController* controller(); |
| 141 bool isRoot() const { return !isChild(); } | 110 bool isRoot() const { return !isChild(); } |
| 142 | 111 |
| 143 bool isCreatedByParser() const { return m_createdByParser; } | 112 bool isCreatedByParser() const { return m_createdByParser; } |
| 144 bool isBlockedFromRunningScript() const { return m_state <= BlockedFromRunni
ngScript; } | |
| 145 bool isBlocked() const { return m_state < Ready; } | |
| 146 | 113 |
| 147 bool isBlockedFromCreatingDocument() const; | 114 bool isStateBlockedFromRunningScript() const { return state() <= BlockedFrom
RunningScript; } |
| 115 bool isStateBlockedFromCreatingDocument() const { return state() <= BlockedF
romCreatingDocument; } |
| 116 bool isStateReady() const { return state() == Ready; } |
| 148 | 117 |
| 149 void appendChild(HTMLImport*); | 118 void appendChild(HTMLImport*); |
| 150 | 119 |
| 151 virtual bool isChild() const { return false; } | 120 virtual bool isChild() const { return false; } |
| 152 virtual HTMLImportRoot* root() = 0; | 121 virtual HTMLImportRoot* root() = 0; |
| 153 virtual Document* document() const = 0; | 122 virtual Document* document() const = 0; |
| 154 virtual void wasDetachedFromDocument() = 0; | 123 virtual void wasDetachedFromDocument() = 0; |
| 155 virtual void didFinishParsing() = 0; | 124 virtual void didFinishParsing() { }; |
| 156 virtual bool isDone() const = 0; // FIXME: Should be renamed to haveFinished
Loading() | 125 virtual bool isDone() const = 0; // FIXME: Should be renamed to haveFinished
Loading() |
| 157 virtual bool hasLoader() const = 0; | 126 virtual bool hasLoader() const = 0; |
| 158 virtual bool ownsLoader() const { return false; } | 127 virtual bool ownsLoader() const { return false; } |
| 159 virtual CustomElementMicrotaskImportStep* customElementMicrotaskStep() const
{ return 0; } | 128 virtual CustomElementMicrotaskImportStep* customElementMicrotaskStep() const
{ return 0; } |
| 129 virtual void stateDidChange(); |
| 130 |
| 131 enum State { |
| 132 BlockedFromCreatingDocument = 0, |
| 133 BlockedFromRunningScript, |
| 134 Active, |
| 135 Ready, |
| 136 Invalid |
| 137 }; |
| 160 | 138 |
| 161 protected: | 139 protected: |
| 162 enum State { | 140 // Stating from most conservative state. |
| 163 BlockedFromRunningScript, | 141 // It will be corrected through state update flow. |
| 164 WaitingLoaderOrChildren, | 142 explicit HTMLImport(bool createdByParser = false) |
| 165 Ready | 143 : m_cachedState(BlockedFromCreatingDocument) |
| 166 }; | |
| 167 | |
| 168 explicit HTMLImport(State state, bool createdByParser = false) | |
| 169 : m_state(state) | |
| 170 , m_createdByParser(createdByParser) | 144 , m_createdByParser(createdByParser) |
| 171 { } | 145 { } |
| 172 | 146 |
| 173 virtual void didUnblockFromCreatingDocument(); | 147 void stateWillChange(); |
| 174 virtual void didUnblockFromRunningScript(); | 148 State state() const; |
| 175 virtual void didBecomeReady(); | 149 static void recalcTreeState(HTMLImport* root); |
| 176 | 150 |
| 177 void loaderWasResolved(); | 151 #if !defined(NDEBUG) |
| 178 void loaderDidFinish(); | 152 void show(); |
| 153 void showTree(HTMLImport* highlight, unsigned depth); |
| 154 virtual void showThis(); |
| 155 #endif |
| 179 | 156 |
| 180 private: | 157 private: |
| 181 static void block(HTMLImport*); | 158 void recalcState(); |
| 159 void forceBlock(); |
| 160 void invalidateCachedState() { m_cachedState = Invalid; } |
| 161 bool isStateCacheValid() const { return m_cachedState != Invalid; } |
| 182 | 162 |
| 183 void blockPredecessorsOf(HTMLImport* child); | 163 State m_cachedState; |
| 184 void blockFromRunningScript(); | |
| 185 void waitLoaderOrChildren(); | |
| 186 void unblockFromRunningScript(); | |
| 187 void becomeReady(); | |
| 188 | |
| 189 bool isBlockedFromRunningScriptByPredecessors() const; | |
| 190 bool isBlockingFollowersFromRunningScript() const; | |
| 191 bool isBlockingFollowersFromCreatingDocument() const; | |
| 192 | |
| 193 State m_state; | |
| 194 | |
| 195 bool m_createdByParser : 1; | 164 bool m_createdByParser : 1; |
| 196 }; | 165 }; |
| 197 | 166 |
| 167 inline HTMLImport::State HTMLImport::state() const |
| 168 { |
| 169 ASSERT(isStateCacheValid()); |
| 170 return m_cachedState; |
| 171 } |
| 172 |
| 173 |
| 198 // An abstract class to decouple its sublcass HTMLImportsController. | 174 // An abstract class to decouple its sublcass HTMLImportsController. |
| 199 class HTMLImportRoot : public HTMLImport { | 175 class HTMLImportRoot : public HTMLImport { |
| 200 public: | 176 public: |
| 201 HTMLImportRoot() : HTMLImport(Ready) { } | 177 HTMLImportRoot() { } |
| 202 | 178 |
| 203 virtual void blockerGone() = 0; | 179 virtual void scheduleRecalcState() = 0; |
| 204 virtual HTMLImportsController* toController() = 0; | 180 virtual HTMLImportsController* toController() = 0; |
| 205 virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0)
const = 0; | 181 virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0)
const = 0; |
| 206 }; | 182 }; |
| 207 | 183 |
| 208 } // namespace WebCore | 184 } // namespace WebCore |
| 209 | 185 |
| 210 #endif // HTMLImport_h | 186 #endif // HTMLImport_h |
| OLD | NEW |