mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-04 22:37:29 +09:00
Issue #618 - (async, preload) Correctly pass info about async/defer to parser.
This makes sure we don't block body-referred sub-resources by head-referenced defer and async scripts. This is important for all script loads, not just modules, but is added here because it was run into while implementing modules.
This commit is contained in:
parent
d8c2bc2976
commit
3fa4aabfad
7 changed files with 53 additions and 15 deletions
|
|
@ -1050,15 +1050,17 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsIScriptElement *script = aRequest->mElement;
|
nsIScriptElement *script = aRequest->mElement;
|
||||||
|
bool async = script ? script->GetScriptAsync() : aRequest->mPreloadAsAsync;
|
||||||
|
bool defer = script ? script->GetScriptDeferred() : aRequest->mPreloadAsDefer;
|
||||||
|
|
||||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||||
|
|
||||||
if (cos) {
|
if (cos) {
|
||||||
if (aScriptFromHead &&
|
if (aScriptFromHead && !async && !defer) {
|
||||||
!(script && (script->GetScriptAsync() || script->GetScriptDeferred()))) {
|
|
||||||
// synchronous head scripts block lading of most other non js/css
|
// synchronous head scripts block lading of most other non js/css
|
||||||
// content such as images
|
// content such as images
|
||||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||||
} else if (!(script && script->GetScriptDeferred())) {
|
} else if (!defer) {
|
||||||
// other scripts are neither blocked nor prioritized unless marked deferred
|
// other scripts are neither blocked nor prioritized unless marked deferred
|
||||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||||
}
|
}
|
||||||
|
|
@ -2571,6 +2573,8 @@ ScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||||
const nsAString &aCrossOrigin,
|
const nsAString &aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead,
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer,
|
||||||
const mozilla::net::ReferrerPolicy aReferrerPolicy)
|
const mozilla::net::ReferrerPolicy aReferrerPolicy)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE_VOID(mDocument);
|
NS_ENSURE_TRUE_VOID(mDocument);
|
||||||
|
|
@ -2601,6 +2605,8 @@ ScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||||
Element::StringToCORSMode(aCrossOrigin), sriMetadata,
|
Element::StringToCORSMode(aCrossOrigin), sriMetadata,
|
||||||
aReferrerPolicy);
|
aReferrerPolicy);
|
||||||
request->mIsInline = false;
|
request->mIsInline = false;
|
||||||
|
request->mPreloadAsAsync = aAsync;
|
||||||
|
request->mPreloadAsDefer = aDefer;
|
||||||
|
|
||||||
nsresult rv = StartLoad(request, aType, aScriptFromHead);
|
nsresult rv = StartLoad(request, aType, aScriptFromHead);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ public:
|
||||||
mHasSourceMapURL(false),
|
mHasSourceMapURL(false),
|
||||||
mInDeferList(false),
|
mInDeferList(false),
|
||||||
mInAsyncList(false),
|
mInAsyncList(false),
|
||||||
|
mPreloadAsAsync(false),
|
||||||
|
mPreloadAsDefer(false),
|
||||||
mIsNonAsyncScriptInserted(false),
|
mIsNonAsyncScriptInserted(false),
|
||||||
mIsXSLT(false),
|
mIsXSLT(false),
|
||||||
mIsCanceled(false),
|
mIsCanceled(false),
|
||||||
|
|
@ -161,6 +163,8 @@ public:
|
||||||
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
||||||
bool mInDeferList; // True if we live in mDeferRequests.
|
bool mInDeferList; // True if we live in mDeferRequests.
|
||||||
bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
||||||
|
bool mPreloadAsAsync; // True if this is a preload request and the script is async
|
||||||
|
bool mPreloadAsDefer; // True if this is a preload request and the script is defer
|
||||||
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
||||||
bool mIsXSLT; // True if we live in mXSLTRequests.
|
bool mIsXSLT; // True if we live in mXSLTRequests.
|
||||||
bool mIsCanceled; // True if we have been explicitly canceled.
|
bool mIsCanceled; // True if we have been explicitly canceled.
|
||||||
|
|
@ -459,6 +463,8 @@ public:
|
||||||
const nsAString &aCrossOrigin,
|
const nsAString &aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead,
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer,
|
||||||
const mozilla::net::ReferrerPolicy aReferrerPolicy);
|
const mozilla::net::ReferrerPolicy aReferrerPolicy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
#include "nsHtml5TreeOpExecutor.h"
|
#include "nsHtml5TreeOpExecutor.h"
|
||||||
|
|
||||||
nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
|
nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
|
||||||
|
:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
: mOpCode(eSpeculativeLoadUninitialized)
|
mOpCode(eSpeculativeLoadUninitialized),
|
||||||
#endif
|
#endif
|
||||||
|
mIsAsync(false),
|
||||||
|
mIsDefer(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
|
MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
|
||||||
}
|
}
|
||||||
|
|
@ -48,11 +51,13 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadScript:
|
case eSpeculativeLoadScript:
|
||||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
||||||
mCrossOrigin, mIntegrity, false);
|
mCrossOrigin, mIntegrity, false,
|
||||||
|
mIsAsync, mIsDefer);
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadScriptFromHead:
|
case eSpeculativeLoadScriptFromHead:
|
||||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
||||||
mCrossOrigin, mIntegrity, true);
|
mCrossOrigin, mIntegrity, true,
|
||||||
|
mIsAsync, mIsDefer);
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadStyle:
|
case eSpeculativeLoadStyle:
|
||||||
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin, mIntegrity);
|
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin, mIntegrity);
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,9 @@ class nsHtml5SpeculativeLoad {
|
||||||
nsHtml5String aType,
|
nsHtml5String aType,
|
||||||
nsHtml5String aCrossOrigin,
|
nsHtml5String aCrossOrigin,
|
||||||
nsHtml5String aIntegrity,
|
nsHtml5String aIntegrity,
|
||||||
bool aParserInHead)
|
bool aParserInHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
||||||
"Trying to reinitialize a speculative load!");
|
"Trying to reinitialize a speculative load!");
|
||||||
|
|
@ -139,6 +141,8 @@ class nsHtml5SpeculativeLoad {
|
||||||
aType.ToString(mTypeOrCharsetSourceOrDocumentMode);
|
aType.ToString(mTypeOrCharsetSourceOrDocumentMode);
|
||||||
aCrossOrigin.ToString(mCrossOrigin);
|
aCrossOrigin.ToString(mCrossOrigin);
|
||||||
aIntegrity.ToString(mIntegrity);
|
aIntegrity.ToString(mIntegrity);
|
||||||
|
mIsAsync = aAsync;
|
||||||
|
mIsDefer = aDefer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void InitStyle(nsHtml5String aUrl,
|
inline void InitStyle(nsHtml5String aUrl,
|
||||||
|
|
@ -221,6 +225,13 @@ class nsHtml5SpeculativeLoad {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
eHtml5SpeculativeLoad mOpCode;
|
eHtml5SpeculativeLoad mOpCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the refering element has async and/or defer attributes.
|
||||||
|
*/
|
||||||
|
bool mIsAsync;
|
||||||
|
bool mIsDefer;
|
||||||
|
|
||||||
nsString mUrl;
|
nsString mUrl;
|
||||||
nsString mReferrerPolicy;
|
nsString mReferrerPolicy;
|
||||||
nsString mMetaCSP;
|
nsString mMetaCSP;
|
||||||
|
|
|
||||||
|
|
@ -185,16 +185,20 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
|
||||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
||||||
nsHtml5String integrity =
|
nsHtml5String integrity =
|
||||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
|
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
|
||||||
|
bool async =
|
||||||
|
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
|
||||||
|
bool defer =
|
||||||
|
aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
|
||||||
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
||||||
url,
|
url,
|
||||||
charset,
|
charset,
|
||||||
type,
|
type,
|
||||||
crossOrigin,
|
crossOrigin,
|
||||||
integrity,
|
integrity,
|
||||||
mode == nsHtml5TreeBuilder::IN_HEAD);
|
mode == nsHtml5TreeBuilder::IN_HEAD,
|
||||||
mCurrentHtmlScriptIsAsyncOrDefer =
|
async,
|
||||||
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
|
defer);
|
||||||
aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
|
mCurrentHtmlScriptIsAsyncOrDefer = async || defer;
|
||||||
}
|
}
|
||||||
} else if (nsHtml5Atoms::link == aName) {
|
} else if (nsHtml5Atoms::link == aName) {
|
||||||
nsHtml5String rel =
|
nsHtml5String rel =
|
||||||
|
|
@ -297,7 +301,9 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
|
||||||
type,
|
type,
|
||||||
crossOrigin,
|
crossOrigin,
|
||||||
integrity,
|
integrity,
|
||||||
mode == nsHtml5TreeBuilder::IN_HEAD);
|
mode == nsHtml5TreeBuilder::IN_HEAD,
|
||||||
|
false /* async */,
|
||||||
|
false /* defer */);
|
||||||
}
|
}
|
||||||
} else if (nsHtml5Atoms::style == aName) {
|
} else if (nsHtml5Atoms::style == aName) {
|
||||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||||
|
|
|
||||||
|
|
@ -921,14 +921,16 @@ nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL,
|
||||||
const nsAString& aType,
|
const nsAString& aType,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead)
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin,
|
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin,
|
||||||
aIntegrity, aScriptFromHead,
|
aIntegrity, aScriptFromHead, aAsync, aDefer,
|
||||||
mSpeculationReferrerPolicy);
|
mSpeculationReferrerPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,9 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
|
||||||
const nsAString& aType,
|
const nsAString& aType,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead);
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer);
|
||||||
|
|
||||||
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue