#include "core/dom/Document.h"
#include "core/dom/custom/CustomElement.h"
+#include "core/dom/custom/CustomElementMicrotaskDispatcher.h"
#include "core/dom/custom/CustomElementMicrotaskImportStep.h"
#include "core/html/imports/HTMLImportChildClient.h"
#include "core/html/imports/HTMLImportLoader.h"
+#include "core/html/imports/HTMLImportsController.h"
namespace WebCore {
HTMLImportChild::HTMLImportChild(Document& master, const KURL& url, SyncMode sync)
: HTMLImport(sync)
+#if ENABLE(OILPAN)
+ , m_master(&master)
+#else
, m_master(master)
+#endif
, m_url(url)
- , m_customElementMicrotaskStep(0)
+ , m_weakFactory(this)
+ , m_loader(0)
, m_client(0)
{
+#if !ENABLE(OILPAN)
m_master.guardRef();
+#endif
}
HTMLImportChild::~HTMLImportChild()
// importDestroyed() should be called before the destruction.
ASSERT(!m_loader);
- if (m_customElementMicrotaskStep) {
- // if Custom Elements were blocked, must unblock them before death
- m_customElementMicrotaskStep->importDidFinish();
- m_customElementMicrotaskStep = 0;
- }
-
if (m_client)
m_client->importChildWasDestroyed(this);
+#if !ENABLE(OILPAN)
m_master.guardDeref();
+#endif
}
void HTMLImportChild::wasAlreadyLoaded()
{
ASSERT(!m_loader);
ASSERT(m_client);
+ ensureLoader();
stateWillChange();
}
ASSERT(!this->resource());
ASSERT(!m_loader);
- if (isSync()) {
- ASSERT(!m_customElementMicrotaskStep);
- m_customElementMicrotaskStep = CustomElement::didCreateImport(this);
- }
-
setResource(resource);
- // If the node is "document blocked", it cannot create HTMLImportLoader
- // even if there is no sharable one found, as there is possibility that
- // preceding imports load the sharable imports.
- // In that case preceding one should win because it comes first in the tree order.
- // See also didUnblockFromCreatingDocument().
- if (state().shouldBlockDocumentCreation())
- return;
-
ensureLoader();
}
{
if (m_client)
m_client->didFinish();
-
- if (m_customElementMicrotaskStep) {
- m_customElementMicrotaskStep->importDidFinish();
- m_customElementMicrotaskStep = 0;
- }
}
void HTMLImportChild::didFinishLoading()
{
clearResource();
stateWillChange();
+ if (m_customElementMicrotaskStep)
+ CustomElementMicrotaskDispatcher::instance().importDidFinish(m_customElementMicrotaskStep.get());
+}
+
+void HTMLImportChild::didFinishUpgradingCustomElements()
+{
+ stateWillChange();
+ m_customElementMicrotaskStep.clear();
+}
+
+bool HTMLImportChild::isLoaded() const
+{
+ return m_loader && m_loader->isDone();
}
Document* HTMLImportChild::importedDocument() const
parent()->removeChild(this);
if (m_loader) {
m_loader->removeImport(this);
- m_loader.clear();
+ m_loader = 0;
}
}
-HTMLImportRoot* HTMLImportChild::root()
-{
- return parent() ? parent()->root() : 0;
-}
-
Document* HTMLImportChild::document() const
{
- return (m_loader && m_loader->isOwnedBy(this)) ? m_loader->document() : 0;
-}
-
-void HTMLImportChild::wasDetachedFromDocument()
-{
- // For imported documens this shouldn't be called because Document::m_import is
- // cleared before Document is destroyed by HTMLImportChild::importDestroyed().
- ASSERT_NOT_REACHED();
-}
-
-void HTMLImportChild::didFinishParsing()
-{
- ASSERT(m_loader->isOwnedBy(this));
- m_loader->didFinishParsing();
+ return m_loader ? m_loader->document() : 0;
}
-void HTMLImportChild::didRemoveAllPendingStylesheet()
+void HTMLImportChild::stateWillChange()
{
- ASSERT(m_loader->isOwnedBy(this));
- m_loader->didRemoveAllPendingStylesheet();
+ toHTMLImportsController(root())->scheduleRecalcState();
}
void HTMLImportChild::stateDidChange()
{
HTMLImport::stateDidChange();
- // Once all preceding imports are loaded,
- // HTMLImportChild can decide whether it should load the import by itself
- // or it can share existing one.
- if (!state().shouldBlockDocumentCreation())
- ensureLoader();
+ ensureLoader();
if (state().isReady())
didFinish();
}
if (m_loader)
return;
- if (HTMLImportChild* found = root()->findLinkFor(m_url, this))
+ if (HTMLImportChild* found = toHTMLImportsController(root())->findLinkFor(m_url, this))
shareLoader(found);
else
createLoader();
+
+ if (!isDone() && !formsCycle()) {
+ ASSERT(!m_customElementMicrotaskStep);
+ m_customElementMicrotaskStep = CustomElement::didCreateImport(this)->weakPtr();
+ }
}
void HTMLImportChild::createLoader()
{
- ASSERT(!state().shouldBlockDocumentCreation());
ASSERT(!m_loader);
- m_loader = HTMLImportLoader::create();
+ m_loader = toHTMLImportsController(root())->createLoader();
m_loader->addImport(this);
m_loader->startLoading(resource());
}
bool HTMLImportChild::isDone() const
{
- return m_loader && m_loader->isDone();
-}
-
-bool HTMLImportChild::hasLoader() const
-{
- return m_loader;
-}
-
-bool HTMLImportChild::ownsLoader() const
-{
- return m_loader && m_loader->isOwnedBy(this);
+ return m_loader && m_loader->isDone() && !m_customElementMicrotaskStep;
}
bool HTMLImportChild::loaderHasError() const
return m_client->link();
}
+// Ensuring following invariants against the import tree:
+// - HTMLImportChild::firstImport() is the "first import" of the DFS order of the import tree.
+// - The "first import" manages all the children that is loaded by the document.
+void HTMLImportChild::normalize()
+{
+ if (!loader()->isFirstImport(this) && this->precedes(loader()->firstImport())) {
+ HTMLImportChild* oldFirst = loader()->firstImport();
+ loader()->moveToFirst(this);
+ takeChildrenFrom(oldFirst);
+ }
+
+ for (HTMLImport* child = firstChild(); child; child = child->next())
+ toHTMLImportChild(child)->normalize();
+}
+
#if !defined(NDEBUG)
void HTMLImportChild::showThis()
{
+ bool isFirst = loader() ? loader()->isFirstImport(this) : false;
HTMLImport::showThis();
- fprintf(stderr, " loader=%p own=%s async=%s url=%s",
- m_loader.get(),
- hasLoader() && ownsLoader() ? "Y" : "N",
+ fprintf(stderr, " loader=%p first=%d, step=%p sync=%s url=%s",
+ m_loader,
+ isFirst,
+ m_customElementMicrotaskStep.get(),
isSync() ? "Y" : "N",
url().string().utf8().data());
}