Commit 926b396e authored by morrita@chromium.org's avatar morrita@chromium.org

[HTML Import] Let script block by pending resources created by lifecycle callback

This change tells the HTML parser know that lifecycle callbacks,
that is triggered through Microtask checkpoint, can create resources that
blocks scripts.

It also streamlines the unblock notification from Document to the parser
into didLoadAllScriptBlockingResources(). Now both didRemoveAllPendingStylesheets()
and didLoadAllImports() checks resource readiness and invokes the unified notification.

TEST=custom-element-style-block.html
BUG=346408
R=dglazkov@chromium.org, dominicc@chromium.org

Committed: https://src.chromium.org/viewvc/blink?view=rev&revision=169577

Review URL: https://codereview.chromium.org/202813002

git-svn-id: svn://svn.chromium.org/blink/trunk@169782 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent aeb1a561
<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<link rel="import" href="resources/custom-element-style.html">
</head>
<body>
<x-test></x-test>
<script>
test(function(){
var x = document.querySelector('x-test');
var port = x.shadowRoot.querySelector('style').sheet.cssRules[0];
assert_true(port.styleSheet instanceof StyleSheet);
}, "The @import sytle in custom element shadow DOM blocks following script element.");
</script>
</body>
</html>
<!DOCTYPE html>
<template>
<style>
@import url(hello.css);
</style>
<h1>Hello</h1>
</template>
<script>
var t = document.currentScript.ownerDocument.querySelector('template');
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
var root = this.createShadowRoot();
root.appendChild(document.importNode(t.content));
};
document.registerElement('x-test', {prototype: proto});
</script>
<!DOCTYPE html>
<html>
<head>
<script>
if (window.testRunner)
testRunner.dumpAsText();
</script>
<script defer src="hello.js"></script>
<link rel="stylesheet" href="hello.css">
</script>
<body><h1>PASS unless crash</h1></body>
</html>
h1 {
color: blue;
}
\ No newline at end of file
function hello()
{
}
\ No newline at end of file
...@@ -816,11 +816,6 @@ void Document::setImport(HTMLImport* import) ...@@ -816,11 +816,6 @@ void Document::setImport(HTMLImport* import)
m_import = import; m_import = import;
} }
void Document::didLoadAllImports()
{
executeScriptsWaitingForResourcesIfNeeded();
}
bool Document::haveImportsLoaded() const bool Document::haveImportsLoaded() const
{ {
return !m_import || !m_import->state().shouldBlockScriptExecution(); return !m_import || !m_import->state().shouldBlockScriptExecution();
...@@ -2849,20 +2844,37 @@ LocalFrame* Document::findUnsafeParentScrollPropagationBoundary() ...@@ -2849,20 +2844,37 @@ LocalFrame* Document::findUnsafeParentScrollPropagationBoundary()
return 0; return 0;
} }
void Document::didLoadAllImports()
{
if (!haveStylesheetsLoaded())
return;
didLoadAllScriptBlockingResources();
}
void Document::didRemoveAllPendingStylesheet() void Document::didRemoveAllPendingStylesheet()
{ {
m_needsNotifyRemoveAllPendingStylesheet = false; m_needsNotifyRemoveAllPendingStylesheet = false;
styleResolverChanged(RecalcStyleDeferred, hasNodesWithPlaceholderStyle() ? FullStyleUpdate : AnalyzedStyleUpdate); styleResolverChanged(RecalcStyleDeferred, hasNodesWithPlaceholderStyle() ? FullStyleUpdate : AnalyzedStyleUpdate);
if (m_import)
m_import->didRemoveAllPendingStylesheet();
if (!haveImportsLoaded())
return;
didLoadAllScriptBlockingResources();
}
void Document::didLoadAllScriptBlockingResources()
{
executeScriptsWaitingForResourcesIfNeeded(); executeScriptsWaitingForResourcesIfNeeded();
if (m_gotoAnchorNeededAfterStylesheetsLoad && view()) if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
view()->scrollToFragment(m_url); view()->scrollToFragment(m_url);
if (m_import)
m_import->didRemoveAllPendingStylesheet();
} }
void Document::executeScriptsWaitingForResourcesIfNeeded() void Document::executeScriptsWaitingForResourcesIfNeeded()
{ {
if (!haveStylesheetsAndImportsLoaded()) if (!haveStylesheetsAndImportsLoaded())
......
...@@ -993,6 +993,7 @@ public: ...@@ -993,6 +993,7 @@ public:
ElementDataCache* elementDataCache() { return m_elementDataCache.get(); } ElementDataCache* elementDataCache() { return m_elementDataCache.get(); }
void didLoadAllScriptBlockingResources();
void didRemoveAllPendingStylesheet(); void didRemoveAllPendingStylesheet();
void setNeedsNotifyRemoveAllPendingStylesheet() { m_needsNotifyRemoveAllPendingStylesheet = true; } void setNeedsNotifyRemoveAllPendingStylesheet() { m_needsNotifyRemoveAllPendingStylesheet = true; }
void clearStyleResolver(); void clearStyleResolver();
......
...@@ -151,7 +151,7 @@ bool HTMLImportsController::hasLoader() const ...@@ -151,7 +151,7 @@ bool HTMLImportsController::hasLoader() const
bool HTMLImportsController::isDone() const bool HTMLImportsController::isDone() const
{ {
return !m_master->parsing(); return !m_master->parsing() && m_master->haveStylesheetsLoaded();
} }
void HTMLImportsController::stateDidChange() void HTMLImportsController::stateDidChange()
......
...@@ -113,10 +113,10 @@ void HTMLScriptRunner::executeParsingBlockingScript() ...@@ -113,10 +113,10 @@ void HTMLScriptRunner::executeParsingBlockingScript()
ASSERT(isPendingScriptReady(m_parserBlockingScript)); ASSERT(isPendingScriptReady(m_parserBlockingScript));
InsertionPointRecord insertionPointRecord(m_host->inputStream()); InsertionPointRecord insertionPointRecord(m_host->inputStream());
executePendingScriptAndDispatchEvent(m_parserBlockingScript); executePendingScriptAndDispatchEvent(m_parserBlockingScript, PendingScriptBlockingParser);
} }
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript) void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript, PendingScriptType pendingScriptType)
{ {
bool errorOccurred = false; bool errorOccurred = false;
ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred); ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);
...@@ -125,8 +125,15 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi ...@@ -125,8 +125,15 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
if (pendingScript.resource() && pendingScript.watchingForLoad()) if (pendingScript.resource() && pendingScript.watchingForLoad())
stopWatchingForLoad(pendingScript); stopWatchingForLoad(pendingScript);
if (!isExecutingScript()) if (!isExecutingScript()) {
Microtask::performCheckpoint(); Microtask::performCheckpoint();
if (pendingScriptType == PendingScriptBlockingParser) {
m_hasScriptsWaitingForResources = !m_document->haveStylesheetsAndImportsLoaded();
// The parser cannot be unblocked as a microtask requested another resource
if (m_hasScriptsWaitingForResources)
return;
}
}
// Clear the pending script before possible rentrancy from executeScript() // Clear the pending script before possible rentrancy from executeScript()
RefPtr<Element> element = pendingScript.releaseElementAndClear(); RefPtr<Element> element = pendingScript.releaseElementAndClear();
...@@ -223,7 +230,7 @@ bool HTMLScriptRunner::executeScriptsWaitingForParsing() ...@@ -223,7 +230,7 @@ bool HTMLScriptRunner::executeScriptsWaitingForParsing()
return false; return false;
} }
PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst();
executePendingScriptAndDispatchEvent(first); executePendingScriptAndDispatchEvent(first, PendingScriptDeferred);
// FIXME: What is this m_document check for? // FIXME: What is this m_document check for?
if (!m_document) if (!m_document)
return false; return false;
......
...@@ -68,8 +68,13 @@ private: ...@@ -68,8 +68,13 @@ private:
LocalFrame* frame() const; LocalFrame* frame() const;
enum PendingScriptType {
PendingScriptBlockingParser,
PendingScriptDeferred
};
void executeParsingBlockingScript(); void executeParsingBlockingScript();
void executePendingScriptAndDispatchEvent(PendingScript&); void executePendingScriptAndDispatchEvent(PendingScript&, PendingScriptType);
void executeParsingBlockingScripts(); void executeParsingBlockingScripts();
void requestParsingBlockingScript(Element*); void requestParsingBlockingScript(Element*);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment