summaryrefslogtreecommitdiff
path: root/dom
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-09-08 11:01:01 +0000
committerMoonchild <moonchild@palemoon.org>2020-09-08 11:01:01 +0000
commitb55d425b37b552e3fd5c781af6d9a172d0ce763c (patch)
tree2ecc2528720563be1ddfa02b637dcd8297dfd2ba /dom
parent1154e48843479efa00d81712cafcd9e520180030 (diff)
parentdf55ce90372c71ec9cb186677044aacc96c87187 (diff)
downloaduxp-b55d425b37b552e3fd5c781af6d9a172d0ce763c.tar.gz
Merge branch 'es-modules-work'
Diffstat (limited to 'dom')
-rw-r--r--dom/html/nsHTMLDocument.cpp3
-rw-r--r--dom/script/ModuleLoadRequest.h2
-rw-r--r--dom/script/ScriptLoader.cpp106
-rw-r--r--dom/script/ScriptLoader.h12
4 files changed, 100 insertions, 23 deletions
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index f3cb096b9a..9d0b2c9bb8 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1471,6 +1471,9 @@ nsHTMLDocument::Open(JSContext* cx,
// document again otherwise the document could have a non-zero onload block
// count without the onload blocker request being in the loadgroup.
EnsureOnloadBlocker();
+
+ // Throw away loaded modules created for the previous global.
+ ScriptLoader()->ClearModuleMap();
}
// Step 8 - Clear all event listeners out of our DOM tree
diff --git a/dom/script/ModuleLoadRequest.h b/dom/script/ModuleLoadRequest.h
index eefb7dad5f..4eac65090c 100644
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -56,7 +56,7 @@ public:
ModuleLoadRequest(nsIURI* aURI,
ModuleLoadRequest* aParent);
- bool IsTopLevel() const {
+ bool IsTopLevel() const override {
return mIsTopLevel;
}
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index 0052c72fe4..362c27f3e0 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -477,6 +477,11 @@ ScriptLoader::GetFetchedModule(nsIURI* aURL) const
return ms;
}
+void ScriptLoader::ClearModuleMap() {
+ MOZ_ASSERT(mFetchingModules.IsEmpty());
+ mFetchedModules.Clear();
+}
+
nsresult
ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
{
@@ -559,7 +564,9 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
rv = nsJSUtils::CompileModule(cx, srcBuf, global, options, &module);
}
}
+
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
+
RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
aRequest->mModuleScript = moduleScript;
@@ -979,7 +986,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
if (aRequest->IsModuleRequest()) {
// Check whether the module has been fetched or is currently being fetched,
- // and if so wait for it.
+ // and if so wait for it rather than starting a new fetch.
ModuleLoadRequest* request = aRequest->AsModuleRequest();
if (ModuleMapContainsURL(request->mURI)) {
WaitForModuleFetch(request->mURI)
@@ -988,9 +995,6 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
&ModuleLoadRequest::LoadFailed);
return NS_OK;
}
-
- // Otherwise put the URL in the module map and mark it as fetching.
- SetModuleFetchStarted(request);
}
nsContentPolicyType contentPolicyType = aRequest->IsPreload()
@@ -1103,7 +1107,16 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
NS_ENSURE_SUCCESS(rv, rv);
- return channel->AsyncOpen2(loader);
+ rv = channel->AsyncOpen2(loader);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aRequest->IsModuleRequest()) {
+ // We successfully started fetching a module so put its URL in the module
+ // map and mark it as fetching.
+ SetModuleFetchStarted(aRequest->AsModuleRequest());
+ }
+
+ return NS_OK;
}
bool
@@ -1355,8 +1368,8 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
}
- // Should still be in loading stage of script.
- NS_ASSERTION(!request->InCompilingStage(),
+ // Should still be in loading stage of script unless we're loading a module.
+ NS_ASSERTION(!request->InCompilingStage() || request->IsModuleRequest(),
"Request should not yet be in compiling stage.");
request->mJSVersion = version;
@@ -1904,14 +1917,17 @@ ScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
aOptions->setMutedErrors(!subsumes);
}
- JSContext* cx = jsapi.cx();
- JS::Rooted<JS::Value> elementVal(cx);
- MOZ_ASSERT(aRequest->mElement);
- if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, aRequest->mElement,
- &elementVal,
- /* aAllowWrapping = */ true))) {
- MOZ_ASSERT(elementVal.isObject());
- aOptions->setElement(&elementVal.toObject());
+ if (!aRequest->IsModuleRequest()) {
+ // Only do this for classic scripts.
+ JSContext* cx = jsapi.cx();
+ JS::Rooted<JS::Value> elementVal(cx);
+ MOZ_ASSERT(aRequest->mElement);
+ if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, aRequest->mElement,
+ &elementVal,
+ /* aAllowWrapping = */ true))) {
+ MOZ_ASSERT(elementVal.isObject());
+ aOptions->setElement(&elementVal.toObject());
+ }
}
return NS_OK;
@@ -2373,7 +2389,7 @@ ScriptLoader::HandleLoadError(ScriptLoadRequest *aRequest, nsresult aResult) {
RefPtr<ScriptLoadRequest> req = mXSLTRequests.Steal(aRequest);
FireScriptAvailable(aResult, req);
}
- } else if (aRequest->IsModuleRequest()) {
+ } else if (aRequest->IsModuleRequest() && !aRequest->IsPreload()) {
ModuleLoadRequest* modReq = aRequest->AsModuleRequest();
MOZ_ASSERT(!modReq->IsTopLevel());
MOZ_ASSERT(!modReq->isInList());
@@ -2394,8 +2410,19 @@ ScriptLoader::HandleLoadError(ScriptLoadRequest *aRequest, nsresult aResult) {
FireScriptAvailable(aResult, aRequest);
ContinueParserAsync(aRequest);
mCurrentParserInsertedScript = oldParserInsertedScript;
+ } else if (aRequest->IsPreload()) {
+ if (aRequest->IsModuleRequest()) {
+ // If there is an error preloading modules, cancel the load request.
+ aRequest->Cancel();
+ }
+ if (aRequest->IsTopLevel()) {
+ MOZ_ALWAYS_TRUE(mPreloads.RemoveElement(aRequest, PreloadRequestComparator()));
+ }
+ MOZ_ASSERT(!aRequest->isInList());
} else {
- mPreloads.RemoveElement(aRequest, PreloadRequestComparator());
+ // This happens for blocking requests cancelled by ParsingComplete().
+ MOZ_ASSERT(aRequest->IsCanceled());
+ MOZ_ASSERT(!aRequest->isInList());
}
}
@@ -2424,6 +2451,18 @@ ScriptLoader::NumberOfProcessors()
return mNumberOfProcessors;
}
+static bool
+IsInternalURIScheme(nsIURI* uri)
+{
+ // Note: Extend this if other schemes need to be included.
+ bool isResource;
+ if (NS_SUCCEEDED(uri->SchemeIs("resource", &isResource)) && isResource) {
+ return true;
+ }
+
+ return false;
+}
+
nsresult
ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
nsIIncrementalStreamLoader* aLoader,
@@ -2511,7 +2550,17 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
return NS_ERROR_FAILURE;
}
- channel->GetURI(getter_AddRefs(request->mBaseURL));
+ nsCOMPtr<nsIURI> uri;
+ rv = channel->GetOriginalURI(getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Fixup internal scheme URIs like resource:, because the channel URI
+ // will point to file: which won't be allowed to load.
+ if (uri && IsInternalURIScheme(uri)) {
+ request->mBaseURL = uri;
+ } else {
+ channel->GetURI(getter_AddRefs(request->mBaseURL));
+ }
// Attempt to compile off main thread.
rv = AttemptAsyncScriptCompile(request);
@@ -2593,18 +2642,31 @@ ScriptLoader::PreloadURI(nsIURI *aURI,
return;
}
+ ScriptKind scriptKind = ScriptKind::Classic;
+
if (mDocument->ModuleScriptsEnabled()) {
// Don't load nomodule scripts.
if (aNoModule) {
return;
}
- // TODO: Preload module scripts.
- if (aType.LowerCaseEqualsASCII("module")) {
- return;
+ // Preload module scripts.
+ static const char kASCIIWhitespace[] = "\t\n\f\r ";
+
+ nsAutoString type(aType);
+ type.Trim(kASCIIWhitespace);
+ if (type.LowerCaseEqualsASCII("module")) {
+ scriptKind = ScriptKind::Module;
}
}
+ if (scriptKind == ScriptKind::Classic &&
+ !aType.IsEmpty() && !nsContentUtils::IsJavascriptMIMEType(aType)) {
+ // Unknown type (not type = module and not type = JS MIME type).
+ // Don't load it.
+ return;
+ }
+
SRIMetadata sriMetadata;
if (!aIntegrity.IsEmpty()) {
MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
@@ -2618,7 +2680,7 @@ ScriptLoader::PreloadURI(nsIURI *aURI,
}
RefPtr<ScriptLoadRequest> request =
- CreateLoadRequest(ScriptKind::Classic, aURI, nullptr, 0,
+ CreateLoadRequest(scriptKind, aURI, nullptr, 0,
Element::StringToCORSMode(aCrossOrigin), sriMetadata,
aReferrerPolicy);
request->mIsInline = false;
diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
index 20e76970f4..73f2a92589 100644
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -173,6 +173,12 @@ public:
return mScriptMode == ScriptMode::eAsync;
}
+ virtual bool IsTopLevel() const
+ {
+ // Classic scripts are always top level.
+ return true;
+ }
+
void MaybeCancelOffThreadScript();
using super::getNext;
@@ -500,6 +506,12 @@ public:
return mPendingChildLoaders.AppendElement(aChild) != nullptr;
}
+ /*
+ * Clear the map of loaded modules. Called when a Document object is reused
+ * for a different global.
+ */
+ void ClearModuleMap();
+
private:
virtual ~ScriptLoader();