mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 15:27:30 +09:00
Issue #618 - (async) Implement async attribute for inline module scripts.
This commit does several things: - Moves the pref check from ScriptLoader to ns[I]Document so it can be called on the document. - Changes the atrribute freezing function to a better name that takes the document as a parameter. - Sets the proper async/defer attributes on HTML script elements based on keywords and whether they are module scripts or not.
This commit is contained in:
parent
294721687c
commit
3781c4a6dd
11 changed files with 73 additions and 41 deletions
|
|
@ -12446,3 +12446,16 @@ nsIDocument::GetSelection(ErrorResult& aRv)
|
||||||
|
|
||||||
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsIDocument::ModuleScriptsEnabled()
|
||||||
|
{
|
||||||
|
static bool sEnabledForContent = false;
|
||||||
|
static bool sCachedPref = false;
|
||||||
|
if (!sCachedPref) {
|
||||||
|
sCachedPref = true;
|
||||||
|
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsContentUtils::IsChromeDoc(this) || sEnabledForContent;
|
||||||
|
}
|
||||||
|
|
@ -2851,6 +2851,8 @@ public:
|
||||||
return mIsWebComponentsEnabled;
|
return mIsWebComponentsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModuleScriptsEnabled();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -280,12 +280,20 @@ HTMLScriptElement::GetScriptCharset(nsAString& charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLScriptElement::FreezeUriAsyncDefer()
|
HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
|
||||||
{
|
{
|
||||||
if (mFrozen) {
|
if (mFrozen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mIsModule && !mAsync && !mDefer && !mExternal);
|
||||||
|
|
||||||
|
// Determine whether this is a classic script or a module script.
|
||||||
|
nsAutoString type;
|
||||||
|
GetScriptType(type);
|
||||||
|
mIsModule = aOwnerDoc->ModuleScriptsEnabled() &&
|
||||||
|
!type.IsEmpty() && type.LowerCaseEqualsASCII("module");
|
||||||
|
|
||||||
// variation of this code in nsSVGScriptElement - check if changes
|
// variation of this code in nsSVGScriptElement - check if changes
|
||||||
// need to be transfered when modifying. Note that we don't use GetSrc here
|
// need to be transfered when modifying. Note that we don't use GetSrc here
|
||||||
// because it will return the base URL when the attr value is "".
|
// because it will return the base URL when the attr value is "".
|
||||||
|
|
@ -300,14 +308,13 @@ HTMLScriptElement::FreezeUriAsyncDefer()
|
||||||
|
|
||||||
// At this point mUri will be null for invalid URLs.
|
// At this point mUri will be null for invalid URLs.
|
||||||
mExternal = true;
|
mExternal = true;
|
||||||
|
|
||||||
bool defer, async;
|
|
||||||
GetAsync(&async);
|
|
||||||
GetDefer(&defer);
|
|
||||||
|
|
||||||
mDefer = !async && defer;
|
|
||||||
mAsync = async;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool defer, async;
|
||||||
|
GetAsync(&async);
|
||||||
|
mAsync = (mExternal || mIsModule) && async;
|
||||||
|
GetDefer(&defer);
|
||||||
|
mDefer = mExternal && !async && defer;
|
||||||
|
|
||||||
mFrozen = true;
|
mFrozen = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
virtual bool GetScriptType(nsAString& type) override;
|
virtual bool GetScriptType(nsAString& type) override;
|
||||||
virtual void GetScriptText(nsAString& text) override;
|
virtual void GetScriptText(nsAString& text) override;
|
||||||
virtual void GetScriptCharset(nsAString& charset) override;
|
virtual void GetScriptCharset(nsAString& charset) override;
|
||||||
virtual void FreezeUriAsyncDefer() override;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
|
||||||
virtual CORSMode GetCORSMode() const override;
|
virtual CORSMode GetCORSMode() const override;
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
|
|
|
||||||
|
|
@ -128,11 +128,11 @@ ScriptElement::MaybeProcessScript()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreezeUriAsyncDefer();
|
nsIDocument* ownerDoc = cont->OwnerDoc();
|
||||||
|
FreezeExecutionAttrs(ownerDoc);
|
||||||
|
|
||||||
mAlreadyStarted = true;
|
mAlreadyStarted = true;
|
||||||
|
|
||||||
nsIDocument* ownerDoc = cont->OwnerDoc();
|
|
||||||
nsCOMPtr<nsIParser> parser = ((nsIScriptElement*) this)->GetCreatorParser();
|
nsCOMPtr<nsIParser> parser = ((nsIScriptElement*) this)->GetCreatorParser();
|
||||||
if (parser) {
|
if (parser) {
|
||||||
nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
|
nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
|
||||||
|
|
|
||||||
|
|
@ -390,19 +390,6 @@ ScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ScriptLoader::ModuleScriptsEnabled()
|
|
||||||
{
|
|
||||||
static bool sEnabledForContent = false;
|
|
||||||
static bool sCachedPref = false;
|
|
||||||
if (!sCachedPref) {
|
|
||||||
sCachedPref = true;
|
|
||||||
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nsContentUtils::IsChromeDoc(mDocument) || sEnabledForContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ScriptLoader::ModuleMapContainsURL(nsIURI* aURL) const
|
ScriptLoader::ModuleMapContainsURL(nsIURI* aURL) const
|
||||||
{
|
{
|
||||||
|
|
@ -1227,14 +1214,12 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
|
nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
|
||||||
|
|
||||||
// Determine whether this is a classic script or a module script.
|
|
||||||
nsAutoString type;
|
nsAutoString type;
|
||||||
bool hasType = aElement->GetScriptType(type);
|
bool hasType = aElement->GetScriptType(type);
|
||||||
ScriptKind scriptKind = ScriptKind::Classic;
|
|
||||||
if (ModuleScriptsEnabled() &&
|
ScriptKind scriptKind = aElement->GetScriptIsModule() ?
|
||||||
!type.IsEmpty() && type.LowerCaseEqualsASCII("module")) {
|
ScriptKind::Module :
|
||||||
scriptKind = ScriptKind::Module;
|
ScriptKind::Classic;
|
||||||
}
|
|
||||||
|
|
||||||
// Step 13. Check that the script is not an eventhandler
|
// Step 13. Check that the script is not an eventhandler
|
||||||
if (IsScriptEventHandler(scriptKind, scriptContent)) {
|
if (IsScriptEventHandler(scriptKind, scriptContent)) {
|
||||||
|
|
@ -1268,7 +1253,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
||||||
// the nomodule attribute will be ignored".
|
// the nomodule attribute will be ignored".
|
||||||
// "The nomodule attribute must not be specified on module scripts (and will
|
// "The nomodule attribute must not be specified on module scripts (and will
|
||||||
// be ignored if it is)."
|
// be ignored if it is)."
|
||||||
if (ModuleScriptsEnabled() &&
|
if (mDocument->ModuleScriptsEnabled() &&
|
||||||
scriptKind == ScriptKind::Classic &&
|
scriptKind == ScriptKind::Classic &&
|
||||||
scriptContent->IsHTMLElement() &&
|
scriptContent->IsHTMLElement() &&
|
||||||
scriptContent->HasAttr(kNameSpaceID_None, nsGkAtoms::nomodule)) {
|
scriptContent->HasAttr(kNameSpaceID_None, nsGkAtoms::nomodule)) {
|
||||||
|
|
@ -1480,6 +1465,12 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
||||||
request->mIsInline = true;
|
request->mIsInline = true;
|
||||||
request->mLineNo = aElement->GetScriptLineNumber();
|
request->mLineNo = aElement->GetScriptLineNumber();
|
||||||
|
|
||||||
|
// Only the 'async' attribute is heeded on an inline module script and
|
||||||
|
// inline classic scripts ignore both these attributes.
|
||||||
|
MOZ_ASSERT(!aElement->GetScriptDeferred());
|
||||||
|
MOZ_ASSERT_IF(!request->IsModuleRequest(), !aElement->GetScriptAsync());
|
||||||
|
request->SetScriptMode(false, aElement->GetScriptAsync());
|
||||||
|
|
||||||
if (request->IsModuleRequest()) {
|
if (request->IsModuleRequest()) {
|
||||||
ModuleLoadRequest* modReq = request->AsModuleRequest();
|
ModuleLoadRequest* modReq = request->AsModuleRequest();
|
||||||
modReq->mBaseURL = mDocument->GetDocBaseURI();
|
modReq->mBaseURL = mDocument->GetDocBaseURI();
|
||||||
|
|
@ -2601,7 +2592,7 @@ ScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Preload module scripts.
|
// TODO: Preload module scripts.
|
||||||
if (ModuleScriptsEnabled() && aType.LowerCaseEqualsASCII("module")) {
|
if (mDocument->ModuleScriptsEnabled() && aType.LowerCaseEqualsASCII("module")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -606,8 +606,6 @@ private:
|
||||||
JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
|
JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
|
||||||
nsAutoString& inlineData);
|
nsAutoString& inlineData);
|
||||||
|
|
||||||
bool ModuleScriptsEnabled();
|
|
||||||
|
|
||||||
void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
|
void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
|
||||||
void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
|
void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
|
||||||
nsresult aResult);
|
nsresult aResult);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "nsIScriptLoaderObserver.h"
|
#include "nsIScriptLoaderObserver.h"
|
||||||
#include "nsWeakPtr.h"
|
#include "nsWeakPtr.h"
|
||||||
#include "nsIParser.h"
|
#include "nsIParser.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
#include "nsIDOMHTMLScriptElement.h"
|
#include "nsIDOMHTMLScriptElement.h"
|
||||||
#include "mozilla/CORSMode.h"
|
#include "mozilla/CORSMode.h"
|
||||||
|
|
@ -37,6 +38,7 @@ public:
|
||||||
mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
||||||
aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
|
aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
|
||||||
mFrozen(false),
|
mFrozen(false),
|
||||||
|
mIsModule(false),
|
||||||
mDefer(false),
|
mDefer(false),
|
||||||
mAsync(false),
|
mAsync(false),
|
||||||
mExternal(false),
|
mExternal(false),
|
||||||
|
|
@ -73,11 +75,25 @@ public:
|
||||||
virtual void GetScriptCharset(nsAString& charset) = 0;
|
virtual void GetScriptCharset(nsAString& charset) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Freezes the return values of GetScriptDeferred(), GetScriptAsync() and
|
* Freezes the return values of the following methods so that subsequent
|
||||||
* GetScriptURI() so that subsequent modifications to the attributes don't
|
* modifications to the attributes don't change execution behavior:
|
||||||
* change execution behavior.
|
* - GetScriptIsModule()
|
||||||
|
* - GetScriptDeferred()
|
||||||
|
* - GetScriptAsync()
|
||||||
|
* - GetScriptURI()
|
||||||
|
* - GetScriptExternal()
|
||||||
*/
|
*/
|
||||||
virtual void FreezeUriAsyncDefer() = 0;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the script a module script?
|
||||||
|
* Currently only supported by HTML scripts.
|
||||||
|
*/
|
||||||
|
bool GetScriptIsModule()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mFrozen, "Execution attributes not yet frozen: Not ready for this call!");
|
||||||
|
return mIsModule;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the script deferred. Currently only supported by HTML scripts.
|
* Is the script deferred. Currently only supported by HTML scripts.
|
||||||
|
|
@ -292,6 +308,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool mFrozen;
|
bool mFrozen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The effective moduleness.
|
||||||
|
*/
|
||||||
|
bool mIsModule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The effective deferredness.
|
* The effective deferredness.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ SVGScriptElement::GetScriptCharset(nsAString& charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SVGScriptElement::FreezeUriAsyncDefer()
|
SVGScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
|
||||||
{
|
{
|
||||||
if (mFrozen) {
|
if (mFrozen) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ public:
|
||||||
virtual bool GetScriptType(nsAString& type) override;
|
virtual bool GetScriptType(nsAString& type) override;
|
||||||
virtual void GetScriptText(nsAString& text) override;
|
virtual void GetScriptText(nsAString& text) override;
|
||||||
virtual void GetScriptCharset(nsAString& charset) override;
|
virtual void GetScriptCharset(nsAString& charset) override;
|
||||||
virtual void FreezeUriAsyncDefer() override;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
|
||||||
virtual CORSMode GetCORSMode() const override;
|
virtual CORSMode GetCORSMode() const override;
|
||||||
|
|
||||||
// ScriptElement
|
// ScriptElement
|
||||||
|
|
|
||||||
|
|
@ -1076,7 +1076,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
|
||||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
|
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
|
||||||
NS_ASSERTION(sele, "Node didn't QI to script.");
|
NS_ASSERTION(sele, "Node didn't QI to script.");
|
||||||
sele->SetScriptLineNumber(mFour.integer);
|
sele->SetScriptLineNumber(mFour.integer);
|
||||||
sele->FreezeUriAsyncDefer();
|
sele->FreezeExecutionAttrs(node->OwnerDoc());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
case eTreeOpSvgLoad: {
|
case eTreeOpSvgLoad: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue