summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/script/ModuleLoadRequest.cpp44
-rw-r--r--dom/script/ModuleLoadRequest.h33
-rw-r--r--dom/script/ModuleScript.cpp43
-rw-r--r--dom/script/ModuleScript.h12
-rw-r--r--dom/script/ScriptElement.cpp4
-rw-r--r--dom/script/ScriptLoader.cpp319
-rw-r--r--dom/script/ScriptLoader.h42
-rw-r--r--dom/script/nsIScriptLoaderObserver.idl9
-rw-r--r--dom/xslt/xslt/txMozillaXMLOutput.cpp2
9 files changed, 282 insertions, 226 deletions
diff --git a/dom/script/ModuleLoadRequest.cpp b/dom/script/ModuleLoadRequest.cpp
index d62214304..5b0e0bdba 100644
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -17,26 +17,53 @@ NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest,
mBaseURL,
mLoader,
- mParent,
mModuleScript,
mImports)
NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
-ModuleLoadRequest::ModuleLoadRequest(nsIScriptElement* aElement,
+ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
+ nsIScriptElement* aElement,
uint32_t aVersion,
CORSMode aCORSMode,
const SRIMetadata &aIntegrity,
+ nsIURI* aReferrer,
+ mozilla::net::ReferrerPolicy aReferrerPolicy,
ScriptLoader* aLoader)
: ScriptLoadRequest(ScriptKind::Module,
+ aURI,
aElement,
aVersion,
aCORSMode,
- aIntegrity),
+ aIntegrity,
+ aReferrer,
+ aReferrerPolicy),
mIsTopLevel(true),
- mLoader(aLoader)
-{}
+ mLoader(aLoader),
+ mVisitedSet(new VisitedURLSet())
+{
+ mVisitedSet->PutEntry(aURI);
+}
+
+ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
+ ModuleLoadRequest* aParent)
+ : ScriptLoadRequest(ScriptKind::Module,
+ aURI,
+ aParent->mElement,
+ aParent->mJSVersion,
+ aParent->mCORSMode,
+ aParent->mIntegrity,
+ aParent->mURI,
+ aParent->mReferrerPolicy),
+ mIsTopLevel(false),
+ mLoader(aParent->mLoader),
+ mVisitedSet(aParent->mVisitedSet)
+{
+ MOZ_ASSERT(mVisitedSet->Contains(aURI));
+
+ mIsInline = false;
+}
void ModuleLoadRequest::Cancel()
{
@@ -83,7 +110,7 @@ ModuleLoadRequest::ModuleLoaded()
// been loaded.
mModuleScript = mLoader->GetFetchedModule(mURI);
- if (!mModuleScript || mModuleScript->IsErrored()) {
+ if (!mModuleScript || mModuleScript->HasParseError()) {
ModuleErrored();
return;
}
@@ -95,7 +122,7 @@ void
ModuleLoadRequest::ModuleErrored()
{
mLoader->CheckModuleDependenciesLoaded(this);
- MOZ_ASSERT(!mModuleScript || mModuleScript->IsErrored());
+ MOZ_ASSERT(!mModuleScript || mModuleScript->HasParseError());
CancelImports();
SetReady();
@@ -132,8 +159,7 @@ ModuleLoadRequest::LoadFinished()
{
mLoader->ProcessLoadedModuleTree(this);
mLoader = nullptr;
- mParent = nullptr;
}
} // dom namespace
-} // mozilla namespace \ No newline at end of file
+} // mozilla namespace
diff --git a/dom/script/ModuleLoadRequest.h b/dom/script/ModuleLoadRequest.h
index 7b06dd2cf..eefb7dad5 100644
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -8,6 +8,7 @@
#define mozilla_dom_ModuleLoadRequest_h
#include "mozilla/dom/ScriptLoader.h"
+#include "nsURIHashKey.h"
#include "mozilla/MozPromise.h"
namespace mozilla {
@@ -16,6 +17,16 @@ namespace dom {
class ModuleScript;
class ScriptLoader;
+// A reference counted set of URLs we have visited in the process of loading a
+// module graph.
+class VisitedURLSet : public nsTHashtable<nsURIHashKey>
+{
+ NS_INLINE_DECL_REFCOUNTING(VisitedURLSet)
+
+private:
+ ~VisitedURLSet() = default;
+};
+
// A load request for a module, created for every top level module script and
// every module import. Load request can share a ModuleScript if there are
// multiple imports of the same module.
@@ -31,12 +42,20 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
- ModuleLoadRequest(nsIScriptElement* aElement,
+ // Create a top-level module load request.
+ ModuleLoadRequest(nsIURI* aURI,
+ nsIScriptElement* aElement,
uint32_t aVersion,
CORSMode aCORSMode,
const SRIMetadata& aIntegrity,
+ nsIURI* aReferrer,
+ mozilla::net::ReferrerPolicy,
ScriptLoader* aLoader);
+ // Create a module load request for an imported module.
+ ModuleLoadRequest(nsIURI* aURI,
+ ModuleLoadRequest* aParent);
+
bool IsTopLevel() const {
return mIsTopLevel;
}
@@ -55,7 +74,7 @@ private:
public:
// Is this a request for a top level module script or an import?
- bool mIsTopLevel;
+ const bool mIsTopLevel;
// The base URL used for resolving relative module imports.
nsCOMPtr<nsIURI> mBaseURL;
@@ -64,10 +83,6 @@ public:
// finishes.
RefPtr<ScriptLoader> mLoader;
- // The importing module, or nullptr for top level module scripts. Used to
- // implement the ancestor list checked when fetching module dependencies.
- RefPtr<ModuleLoadRequest> mParent;
-
// Set to a module script object after a successful load or nullptr on
// failure.
RefPtr<ModuleScript> mModuleScript;
@@ -79,9 +94,13 @@ public:
// Array of imported modules.
nsTArray<RefPtr<ModuleLoadRequest>> mImports;
+
+ // Set of module URLs visited while fetching the module graph this request is
+ // part of.
+ RefPtr<VisitedURLSet> mVisitedSet;
};
} // dom namespace
} // mozilla namespace
-#endif // mozilla_dom_ModuleLoadRequest_h \ No newline at end of file
+#endif // mozilla_dom_ModuleLoadRequest_h
diff --git a/dom/script/ModuleScript.cpp b/dom/script/ModuleScript.cpp
index 28b97a3cb..1bf9d0b0f 100644
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -26,7 +26,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
tmp->UnlinkModuleRecord();
- tmp->mError.setUndefined();
+ tmp->mParseError.setUndefined();
+ tmp->mErrorToRethrow.setUndefined();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
@@ -35,7 +36,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mError)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
@@ -48,7 +50,8 @@ ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL)
MOZ_ASSERT(mLoader);
MOZ_ASSERT(mBaseURL);
MOZ_ASSERT(!mModuleRecord);
- MOZ_ASSERT(mError.isUndefined());
+ MOZ_ASSERT(!HasParseError());
+ MOZ_ASSERT(!HasErrorToRethrow());
}
void
@@ -74,7 +77,8 @@ void
ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
{
MOZ_ASSERT(!mModuleRecord);
- MOZ_ASSERT(mError.isUndefined());
+ MOZ_ASSERT(!HasParseError());
+ MOZ_ASSERT(!HasErrorToRethrow());
mModuleRecord = aModuleRecord;
@@ -85,37 +89,24 @@ ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
}
void
-ModuleScript::SetPreInstantiationError(const JS::Value& aError)
+ModuleScript::SetParseError(const JS::Value& aError)
{
MOZ_ASSERT(!aError.isUndefined());
+ MOZ_ASSERT(!HasParseError());
+ MOZ_ASSERT(!HasErrorToRethrow());
UnlinkModuleRecord();
- mError = aError;
-
+ mParseError = aError;
HoldJSObjects(this);
}
-bool
-ModuleScript::IsErrored() const
-{
- if (!mModuleRecord) {
- MOZ_ASSERT(!mError.isUndefined());
- return true;
- }
-
- return JS::IsModuleErrored(mModuleRecord);
-}
-
-JS::Value
-ModuleScript::Error() const
+void
+ModuleScript::SetErrorToRethrow(const JS::Value& aError)
{
- MOZ_ASSERT(IsErrored());
-
- if (!mModuleRecord) {
- return mError;
- }
+ MOZ_ASSERT(!aError.isUndefined());
+ MOZ_ASSERT(!HasErrorToRethrow());
- return JS::GetModuleError(mModuleRecord);
+ mErrorToRethrow = aError;
}
} // dom namespace
diff --git a/dom/script/ModuleScript.h b/dom/script/ModuleScript.h
index 571359859..f765aa0fa 100644
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -23,7 +23,8 @@ class ModuleScript final : public nsISupports
RefPtr<ScriptLoader> mLoader;
nsCOMPtr<nsIURI> mBaseURL;
JS::Heap<JSObject*> mModuleRecord;
- JS::Heap<JS::Value> mError;
+ JS::Heap<JS::Value> mParseError;
+ JS::Heap<JS::Value> mErrorToRethrow;
~ModuleScript();
@@ -35,14 +36,17 @@ public:
nsIURI* aBaseURL);
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
- void SetPreInstantiationError(const JS::Value& aError);
+ void SetParseError(const JS::Value& aError);
+ void SetErrorToRethrow(const JS::Value& aError);
ScriptLoader* Loader() const { return mLoader; }
JSObject* ModuleRecord() const { return mModuleRecord; }
nsIURI* BaseURL() const { return mBaseURL; }
- bool IsErrored() const;
- JS::Value Error() const;
+ JS::Value ParseError() const { return mParseError; }
+ JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
+ bool HasParseError() const { return !mParseError.isUndefined(); }
+ bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
void UnlinkModuleRecord();
};
diff --git a/dom/script/ScriptElement.cpp b/dom/script/ScriptElement.cpp
index 0cb17dcb0..9cb239c66 100644
--- a/dom/script/ScriptElement.cpp
+++ b/dom/script/ScriptElement.cpp
@@ -21,11 +21,11 @@ using namespace mozilla::dom;
NS_IMETHODIMP
ScriptElement::ScriptAvailable(nsresult aResult,
nsIScriptElement *aElement,
- bool aIsInline,
+ bool aIsInlineClassicScript,
nsIURI *aURI,
int32_t aLineNo)
{
- if (!aIsInline && NS_FAILED(aResult)) {
+ if (!aIsInlineClassicScript && NS_FAILED(aResult)) {
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
if (parser) {
parser->PushDefinedInsertionPoint();
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index a53098974..38649e1dd 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -299,8 +299,12 @@ ScriptLoader::~ScriptLoader()
// <script for=... event=...> element.
static bool
-IsScriptEventHandler(nsIContent* aScriptElement)
+IsScriptEventHandler(ScriptKind kind, nsIContent* aScriptElement)
{
+ if (kind != ScriptKind::Classic) {
+ return false;
+ }
+
if (!aScriptElement->IsHTMLElement()) {
return false;
}
@@ -388,12 +392,12 @@ ScriptLoader::ModuleScriptsEnabled()
}
bool
-ScriptLoader::ModuleMapContainsModule(ModuleLoadRequest *aRequest) const
+ScriptLoader::ModuleMapContainsURL(nsIURI* aURL) const
{
// Returns whether we have fetched, or are currently fetching, a module script
- // for the request's URL.
- return mFetchingModules.Contains(aRequest->mURI) ||
- mFetchedModules.Contains(aRequest->mURI);
+ // for a URL.
+ return mFetchingModules.Contains(aURL) ||
+ mFetchedModules.Contains(aURL);
}
bool
@@ -410,7 +414,7 @@ ScriptLoader::SetModuleFetchStarted(ModuleLoadRequest *aRequest)
// Update the module map to indicate that a module is currently being fetched.
MOZ_ASSERT(aRequest->IsLoading());
- MOZ_ASSERT(!ModuleMapContainsModule(aRequest));
+ MOZ_ASSERT(!ModuleMapContainsURL(aRequest->mURI));
mFetchingModules.Put(aRequest->mURI, nullptr);
}
@@ -443,21 +447,21 @@ ScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *
}
RefPtr<GenericPromise>
-ScriptLoader::WaitForModuleFetch(ModuleLoadRequest *aRequest)
+ScriptLoader::WaitForModuleFetch(nsIURI* aURL)
{
- MOZ_ASSERT(ModuleMapContainsModule(aRequest));
+ MOZ_ASSERT(ModuleMapContainsURL(aURL));
RefPtr<GenericPromise::Private> promise;
- if (mFetchingModules.Get(aRequest->mURI, getter_AddRefs(promise))) {
+ if (mFetchingModules.Get(aURL, getter_AddRefs(promise))) {
if (!promise) {
promise = new GenericPromise::Private(__func__);
- mFetchingModules.Put(aRequest->mURI, promise);
+ mFetchingModules.Put(aURL, promise);
}
return promise;
}
RefPtr<ModuleScript> ms;
- MOZ_ALWAYS_TRUE(mFetchedModules.Get(aRequest->mURI, getter_AddRefs(ms)));
+ MOZ_ALWAYS_TRUE(mFetchedModules.Get(aURL, getter_AddRefs(ms)));
if (!ms) {
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
@@ -493,7 +497,7 @@ ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
return rv;
}
- if (!aRequest->mModuleScript->IsErrored()) {
+ if (!aRequest->mModuleScript->HasParseError()) {
StartFetchingModuleDependencies(aRequest);
}
@@ -501,7 +505,7 @@ ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
}
static nsresult
-ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>& aUrls);
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOut);
nsresult
ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
@@ -568,7 +572,7 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
return NS_ERROR_FAILURE;
}
- moduleScript->SetPreInstantiationError(error);
+ moduleScript->SetParseError(error);
aRequest->ModuleErrored();
return NS_OK;
}
@@ -577,11 +581,8 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
// Validate requested modules and treat failure to resolve module specifiers
// the same as a parse error.
- nsCOMArray<nsIURI> urls;
- rv = ResolveRequestedModules(aRequest, urls);
+ rv = ResolveRequestedModules(aRequest, nullptr);
if (NS_FAILED(rv)) {
- // ResolveRequestedModules sets pre-instanitation error on failure.
- MOZ_ASSERT(moduleScript->IsErrored());
aRequest->ModuleErrored();
return NS_OK;
}
@@ -627,7 +628,7 @@ HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
return NS_ERROR_OUT_OF_MEMORY;
}
- aScript->SetPreInstantiationError(error);
+ aScript->SetParseError(error);
return NS_OK;
}
@@ -667,33 +668,7 @@ ResolveModuleSpecifier(ModuleScript* aScript,
}
static nsresult
-RequestedModuleIsInAncestorList(ModuleLoadRequest* aRequest, nsIURI* aURL, bool* aResult)
-{
- const size_t ImportDepthLimit = 100;
-
- *aResult = false;
- size_t depth = 0;
- while (aRequest) {
- if (depth++ == ImportDepthLimit) {
- return NS_ERROR_FAILURE;
- }
-
- bool equal;
- nsresult rv = aURL->Equals(aRequest->mURI, &equal);
- NS_ENSURE_SUCCESS(rv, rv);
- if (equal) {
- *aResult = true;
- return NS_OK;
- }
-
- aRequest = aRequest->mParent;
- }
-
- return NS_OK;
-}
-
-static nsresult
-ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOut)
{
ModuleScript* ms = aRequest->mModuleScript;
@@ -723,7 +698,6 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
}
// Let url be the result of resolving a module specifier given module script and requested.
- ModuleScript* ms = aRequest->mModuleScript;
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
if (!uri) {
nsresult rv = HandleResolveFailure(cx, ms, specifier);
@@ -731,11 +705,8 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
return NS_ERROR_FAILURE;
}
- bool isAncestor;
- nsresult rv = RequestedModuleIsInAncestorList(aRequest, uri, &isAncestor);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isAncestor) {
- aUrls.AppendElement(uri.forget());
+ if (aUrlsOut) {
+ aUrlsOut->AppendElement(uri.forget());
}
}
@@ -746,20 +717,36 @@ void
ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mModuleScript);
- MOZ_ASSERT(!aRequest->mModuleScript->IsErrored());
+ MOZ_ASSERT(!aRequest->mModuleScript->HasParseError());
MOZ_ASSERT(!aRequest->IsReadyToRun());
+ auto visitedSet = aRequest->mVisitedSet;
+ MOZ_ASSERT(visitedSet->Contains(aRequest->mURI));
+
aRequest->mProgress = ModuleLoadRequest::Progress::FetchingImports;
nsCOMArray<nsIURI> urls;
- nsresult rv = ResolveRequestedModules(aRequest, urls);
+ nsresult rv = ResolveRequestedModules(aRequest, &urls);
if (NS_FAILED(rv)) {
aRequest->ModuleErrored();
return;
}
- if (urls.Length() == 0) {
- // There are no descendents to load so this request is ready.
+ // Remove already visited URLs from the list. Put unvisited URLs into the
+ // visited set.
+ int32_t i = 0;
+ while (i < urls.Count()) {
+ nsIURI* url = urls[i];
+ if (visitedSet->Contains(url)) {
+ urls.RemoveObjectAt(i);
+ } else {
+ visitedSet->PutEntry(url);
+ i++;
+ }
+ }
+
+ if (urls.Count() == 0) {
+ // There are no descendants to load so this request is ready.
aRequest->DependenciesLoaded();
return;
}
@@ -782,20 +769,14 @@ ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
}
RefPtr<GenericPromise>
-ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
+ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent,
nsIURI* aURI)
{
MOZ_ASSERT(aURI);
- RefPtr<ModuleLoadRequest> childRequest =
- new ModuleLoadRequest(aRequest->mElement, aRequest->mJSVersion,
- aRequest->mCORSMode, aRequest->mIntegrity, this);
+ RefPtr<ModuleLoadRequest> childRequest = new ModuleLoadRequest(aURI, aParent);
- childRequest->mIsTopLevel = false;
- childRequest->mURI = aURI;
- childRequest->mIsInline = false;
- childRequest->mReferrerPolicy = aRequest->mReferrerPolicy;
- childRequest->mParent = aRequest;
+ aParent->mImports.AppendElement(childRequest);
RefPtr<GenericPromise> ready = childRequest->mReady.Ensure(__func__);
@@ -806,29 +787,24 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
return ready;
}
- aRequest->mImports.AppendElement(childRequest);
return ready;
}
// 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
-bool
-HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
+JSObject*
+HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
+ JS::Handle<JSString*> aSpecifier)
{
- MOZ_ASSERT(argc == 2);
- JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- JS::Rooted<JSObject*> module(aCx, &args[0].toObject());
- JS::Rooted<JSString*> specifier(aCx, args[1].toString());
-
// Let referencing module script be referencingModule.[[HostDefined]].
- JS::Value value = JS::GetModuleHostDefinedField(module);
+ JS::Value value = JS::GetModuleHostDefinedField(aModule);
auto script = static_cast<ModuleScript*>(value.toPrivate());
- MOZ_ASSERT(script->ModuleRecord() == module);
+ MOZ_ASSERT(script->ModuleRecord() == aModule);
// Let url be the result of resolving a module specifier given referencing
// module script and specifier.
nsAutoJSString string;
- if (!string.init(aCx, specifier)) {
- return false;
+ if (!string.init(aCx, aSpecifier)) {
+ return nullptr;
}
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
@@ -843,46 +819,37 @@ HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
MOZ_ASSERT(ms, "Resolved module not found in module map");
- MOZ_ASSERT(!ms->IsErrored());
+ MOZ_ASSERT(!ms->HasParseError());
+ MOZ_ASSERT(ms->ModuleRecord());
- *vp = JS::ObjectValue(*ms->ModuleRecord());
- return true;
+ return ms->ModuleRecord();
}
-static nsresult
+static void
EnsureModuleResolveHook(JSContext* aCx)
{
- if (JS::GetModuleResolveHook(aCx)) {
- return NS_OK;
- }
-
- JS::Rooted<JSFunction*> func(aCx);
- func = JS_NewFunction(aCx, HostResolveImportedModule, 2, 0,
- "HostResolveImportedModule");
- if (!func) {
- return NS_ERROR_FAILURE;
+ JSRuntime* rt = JS_GetRuntime(aCx);
+ if (JS::GetModuleResolveHook(rt)) {
+ return;
}
- JS::SetModuleResolveHook(aCx, func);
- return NS_OK;
+ JS::SetModuleResolveHook(rt, HostResolveImportedModule);
}
void
ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
{
RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
- if (moduleScript && !moduleScript->IsErrored()) {
- for (auto childRequest : aRequest->mImports) {
- ModuleScript* childScript = childRequest->mModuleScript;
- if (!childScript) {
- // Load error
- aRequest->mModuleScript = nullptr;
- return;
- } else if (childScript->IsErrored()) {
- // Script error
- moduleScript->SetPreInstantiationError(childScript->Error());
- return;
- }
+ if (!moduleScript || moduleScript->HasParseError()) {
+ return;
+ }
+
+ for (auto childRequest : aRequest->mImports) {
+ ModuleScript* childScript = childRequest->mModuleScript;
+ if (!childScript) {
+ aRequest->mModuleScript = nullptr;
+ // Load error on script load request; bail.
+ return;
}
}
}
@@ -892,7 +859,7 @@ ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
{
if (aRequest->IsTopLevel()) {
ModuleScript* moduleScript = aRequest->mModuleScript;
- if (moduleScript && !moduleScript->IsErrored()) {
+ if (moduleScript && !moduleScript->HasErrorToRethrow()) {
if (!InstantiateModuleTree(aRequest)) {
aRequest->mModuleScript = nullptr;
}
@@ -906,6 +873,28 @@ ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
}
}
+JS::Value
+ScriptLoader::FindFirstParseError(ModuleLoadRequest* aRequest)
+{
+ MOZ_ASSERT(aRequest);
+
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ MOZ_ASSERT(moduleScript);
+
+ if (moduleScript->HasParseError()) {
+ return moduleScript->ParseError();
+ }
+
+ for (ModuleLoadRequest* childRequest : aRequest->mImports) {
+ JS::Value error = FindFirstParseError(childRequest);
+ if (!error.isUndefined()) {
+ return error;
+ }
+ }
+
+ return JS::UndefinedValue();
+}
+
bool
ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
{
@@ -916,6 +905,14 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
ModuleScript* moduleScript = aRequest->mModuleScript;
MOZ_ASSERT(moduleScript);
+
+ JS::Value parseError = FindFirstParseError(aRequest);
+ if (!parseError.isUndefined()) {
+ // Parse error found in the requested script
+ moduleScript->SetErrorToRethrow(parseError);
+ return true;
+ }
+
MOZ_ASSERT(moduleScript->ModuleRecord());
nsAutoMicroTask mt;
@@ -924,8 +921,7 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
return false;
}
- nsresult rv = EnsureModuleResolveHook(jsapi.cx());
- NS_ENSURE_SUCCESS(rv, false);
+ EnsureModuleResolveHook(jsapi.cx());
JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
@@ -937,7 +933,7 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
return false;
}
MOZ_ASSERT(!exception.isUndefined());
- // Ignore the exception. It will be recorded in the module record.
+ moduleScript->SetErrorToRethrow(exception);
}
return true;
@@ -959,8 +955,8 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
// Check whether the module has been fetched or is currently being fetched,
// and if so wait for it.
ModuleLoadRequest* request = aRequest->AsModuleRequest();
- if (ModuleMapContainsModule(request)) {
- WaitForModuleFetch(request)
+ if (ModuleMapContainsURL(request->mURI)) {
+ WaitForModuleFetch(request->mURI)
->Then(AbstractThread::GetCurrent(), __func__, request,
&ModuleLoadRequest::ModuleLoaded,
&ModuleLoadRequest::LoadFailed);
@@ -1047,7 +1043,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
NS_LITERAL_CSTRING("*/*"),
false);
- httpChannel->SetReferrerWithPolicy(mDocument->GetDocumentURI(),
+ httpChannel->SetReferrerWithPolicy(aRequest->mReferrer,
aRequest->mReferrerPolicy);
nsCOMPtr<nsIHttpChannelInternal> internalChannel(do_QueryInterface(httpChannel));
@@ -1176,17 +1172,24 @@ CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument)
ScriptLoadRequest*
ScriptLoader::CreateLoadRequest(ScriptKind aKind,
+ nsIURI* aURI,
nsIScriptElement* aElement,
uint32_t aVersion, CORSMode aCORSMode,
- const SRIMetadata &aIntegrity)
+ const SRIMetadata& aIntegrity,
+ mozilla::net::ReferrerPolicy aReferrerPolicy)
{
+ nsIURI* referrer = mDocument->GetDocumentURI();
+
if (aKind == ScriptKind::Classic) {
- return new ScriptLoadRequest(aKind, aElement, aVersion, aCORSMode,
- aIntegrity);
+ return new ScriptLoadRequest(aKind, aURI, aElement,
+ aVersion, aCORSMode,
+ aIntegrity,
+ referrer, aReferrerPolicy);
}
MOZ_ASSERT(aKind == ScriptKind::Module);
- return new ModuleLoadRequest(aElement, aVersion, aCORSMode, aIntegrity, this);
+ return new ModuleLoadRequest(aURI, aElement, aVersion, aCORSMode,
+ aIntegrity, referrer, aReferrerPolicy, this);
}
bool
@@ -1204,35 +1207,38 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
+ // Determine whether this is a classic script or a module script.
+ nsAutoString type;
+ bool hasType = aElement->GetScriptType(type);
+ ScriptKind scriptKind = ScriptKind::Classic;
+ if (ModuleScriptsEnabled() &&
+ !type.IsEmpty() && type.LowerCaseEqualsASCII("module")) {
+ scriptKind = ScriptKind::Module;
+ }
+
// Step 13. Check that the script is not an eventhandler
- if (IsScriptEventHandler(scriptContent)) {
+ if (IsScriptEventHandler(scriptKind, scriptContent)) {
return false;
}
JSVersion version = JSVERSION_DEFAULT;
- // Check the type attribute to determine language and version.
- // If type exists, it trumps the deprecated 'language='
- nsAutoString type;
- bool hasType = aElement->GetScriptType(type);
-
- ScriptKind scriptKind = ScriptKind::Classic;
- if (!type.IsEmpty()) {
- if (ModuleScriptsEnabled() && type.LowerCaseEqualsASCII("module")) {
- scriptKind = ScriptKind::Module;
- } else {
+ // For classic scripts, check the type attribute to determine language and
+ // version. If type exists, it trumps the deprecated 'language='
+ if (scriptKind == ScriptKind::Classic) {
+ if (!type.IsEmpty()) {
NS_ENSURE_TRUE(ParseTypeAttribute(type, &version), false);
- }
- } else if (!hasType) {
- // no 'type=' element
- // "language" is a deprecated attribute of HTML, so we check it only for
- // HTML script elements.
- if (scriptContent->IsHTMLElement()) {
- nsAutoString language;
- scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::language, language);
- if (!language.IsEmpty()) {
- if (!nsContentUtils::IsJavaScriptLanguage(language)) {
- return false;
+ } else if (!hasType) {
+ // no 'type=' element
+ // "language" is a deprecated attribute of HTML, so we check it only for
+ // HTML script elements.
+ if (scriptContent->IsHTMLElement()) {
+ nsAutoString language;
+ scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::language, language);
+ if (!language.IsEmpty()) {
+ if (!nsContentUtils::IsJavaScriptLanguage(language)) {
+ return false;
+ }
}
}
}
@@ -1252,6 +1258,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Step 15. and later in the HTML5 spec
nsresult rv = NS_OK;
RefPtr<ScriptLoadRequest> request;
+ mozilla::net::ReferrerPolicy ourRefPolicy = mDocument->GetReferrerPolicy();
if (aElement->GetScriptExternal()) {
// external script
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
@@ -1264,7 +1271,6 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
// Double-check that the preload matches what we're asked to load now.
- mozilla::net::ReferrerPolicy ourRefPolicy = mDocument->GetReferrerPolicy();
CORSMode ourCORSMode = aElement->GetCORSMode();
nsTArray<PreloadInfo>::index_type i =
mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
@@ -1318,11 +1324,10 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
}
- request = CreateLoadRequest(scriptKind, aElement, version, ourCORSMode,
- sriMetadata);
- request->mURI = scriptURI;
+ request = CreateLoadRequest(scriptKind, scriptURI, aElement,
+ version, ourCORSMode, sriMetadata,
+ ourRefPolicy);
request->mIsInline = false;
- request->mReferrerPolicy = ourRefPolicy;
// set aScriptFromHead to false so we don't treat non preloaded scripts as
// blockers for full page load. See bug 792438.
@@ -1440,12 +1445,13 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return false;
}
- // Inline scripts ignore ther CORS mode and are always CORS_NONE
- request = CreateLoadRequest(scriptKind, aElement, version, CORS_NONE,
- SRIMetadata()); // SRI doesn't apply
+ // Inline scripts ignore ther CORS mode and are always CORS_NONE.
+ request = CreateLoadRequest(scriptKind, mDocument->GetDocumentURI(), aElement,
+ version, CORS_NONE,
+ SRIMetadata(), // SRI doesn't apply
+ ourRefPolicy);
request->mJSVersion = version;
request->mIsInline = true;
- request->mURI = mDocument->GetDocumentURI();
request->mLineNo = aElement->GetScriptLineNumber();
if (request->IsModuleRequest()) {
@@ -1462,7 +1468,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
} else {
AddDeferRequest(request);
}
- if (!modReq->mModuleScript->IsErrored()) {
+ if (!modReq->mModuleScript->HasParseError()) {
StartFetchingModuleDependencies(modReq);
}
return false;
@@ -1958,17 +1964,16 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
}
if (aRequest->IsModuleRequest()) {
- rv = EnsureModuleResolveHook(cx);
- NS_ENSURE_SUCCESS(rv, rv);
+ EnsureModuleResolveHook(cx);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
MOZ_ASSERT(request->mModuleScript);
MOZ_ASSERT(!request->mOffThreadToken);
ModuleScript* moduleScript = request->mModuleScript;
- if (moduleScript->IsErrored()) {
- // Module has an error status
- JS::Rooted<JS::Value> error(cx, moduleScript->Error());
+ if (moduleScript->HasErrorToRethrow()) {
+ // Module has an error status to be rethrown
+ JS::Rooted<JS::Value> error(cx, moduleScript->ErrorToRethrow());
JS_SetPendingException(cx, error);
return NS_OK; // An error is reported by AutoEntryScript.
}
@@ -2327,7 +2332,8 @@ ScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
MOZ_ASSERT(!modReq->IsTopLevel());
MOZ_ASSERT(!modReq->isInList());
modReq->Cancel();
- FireScriptAvailable(rv, request);
+ // A single error is fired for the top level module, so don't use
+ // FireScriptAvailable here.
} else if (mParserBlockingRequest == request) {
MOZ_ASSERT(!request->isInList());
mParserBlockingRequest = nullptr;
@@ -2577,11 +2583,10 @@ ScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
}
RefPtr<ScriptLoadRequest> request =
- CreateLoadRequest(ScriptKind::Classic, nullptr, 0,
- Element::StringToCORSMode(aCrossOrigin), sriMetadata);
- request->mURI = aURI;
+ CreateLoadRequest(ScriptKind::Classic, aURI, nullptr, 0,
+ Element::StringToCORSMode(aCrossOrigin), sriMetadata,
+ aReferrerPolicy);
request->mIsInline = false;
- request->mReferrerPolicy = aReferrerPolicy;
nsresult rv = StartLoad(request, aType, aScriptFromHead);
if (NS_FAILED(rv)) {
diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
index e6b75bf3b..2a14b53ae 100644
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -62,10 +62,13 @@ protected:
public:
ScriptLoadRequest(ScriptKind aKind,
+ nsIURI* aURI,
nsIScriptElement* aElement,
uint32_t aVersion,
mozilla::CORSMode aCORSMode,
- const mozilla::dom::SRIMetadata &aIntegrity)
+ const mozilla::dom::SRIMetadata& aIntegrity,
+ nsIURI* aReferrer,
+ mozilla::net::ReferrerPolicy aReferrerPolicy)
: mKind(aKind),
mElement(aElement),
mProgress(Progress::Loading),
@@ -81,10 +84,12 @@ public:
mScriptTextBuf(nullptr),
mScriptTextLength(0),
mJSVersion(aVersion),
+ mURI(aURI),
mLineNo(1),
mCORSMode(aCORSMode),
mIntegrity(aIntegrity),
- mReferrerPolicy(mozilla::net::RP_Default)
+ mReferrer(aReferrer),
+ mReferrerPolicy(aReferrerPolicy)
{
}
@@ -100,7 +105,8 @@ public:
void FireScriptAvailable(nsresult aResult)
{
- mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
+ bool isInlineClassicScript = mIsInline && !IsModuleRequest();
+ mElement->ScriptAvailable(aResult, mElement, isInlineClassicScript, mURI, mLineNo);
}
void FireScriptEvaluated(nsresult aResult)
{
@@ -164,13 +170,14 @@ public:
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
uint32_t mJSVersion;
- nsCOMPtr<nsIURI> mURI;
+ const nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
int32_t mLineNo;
const mozilla::CORSMode mCORSMode;
const mozilla::dom::SRIMetadata mIntegrity;
- mozilla::net::ReferrerPolicy mReferrerPolicy;
+ const nsCOMPtr<nsIURI> mReferrer;
+ const mozilla::net::ReferrerPolicy mReferrerPolicy;
};
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
@@ -467,12 +474,13 @@ public:
private:
virtual ~ScriptLoader();
- ScriptLoadRequest* CreateLoadRequest(
- ScriptKind aKind,
- nsIScriptElement* aElement,
- uint32_t aVersion,
- mozilla::CORSMode aCORSMode,
- const mozilla::dom::SRIMetadata &aIntegrity);
+ ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
+ nsIURI* aURI,
+ nsIScriptElement* aElement,
+ uint32_t aVersion,
+ mozilla::CORSMode aCORSMode,
+ const mozilla::dom::SRIMetadata& aIntegrity,
+ mozilla::net::ReferrerPolicy aReferrerPolicy);
/**
* Unblocks the creator parser of the parser-blocking scripts.
@@ -571,22 +579,24 @@ private:
bool IsFetchingModule(ModuleLoadRequest *aRequest) const;
- bool ModuleMapContainsModule(ModuleLoadRequest *aRequest) const;
- RefPtr<mozilla::GenericPromise> WaitForModuleFetch(ModuleLoadRequest *aRequest);
+ bool ModuleMapContainsURL(nsIURI* aURL) const;
+ RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
ModuleScript* GetFetchedModule(nsIURI* aURL) const;
- friend bool
- HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp);
+ friend JSObject*
+ HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
+ JS::Handle<JSString*> aSpecifier);
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
+ JS::Value FindFirstParseError(ModuleLoadRequest* aRequest);
bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
RefPtr<mozilla::GenericPromise>
- StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest, nsIURI* aURI);
+ StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent, nsIURI* aURI);
nsIDocument* mDocument; // [WEAK]
nsCOMArray<nsIScriptLoaderObserver> mObservers;
diff --git a/dom/script/nsIScriptLoaderObserver.idl b/dom/script/nsIScriptLoaderObserver.idl
index ed7196525..880738360 100644
--- a/dom/script/nsIScriptLoaderObserver.idl
+++ b/dom/script/nsIScriptLoaderObserver.idl
@@ -20,15 +20,16 @@ interface nsIScriptLoaderObserver : nsISupports {
* a script. If this is a failure code, script evaluation
* will not occur.
* @param aElement The element being processed.
- * @param aIsInline Is this an inline script or externally loaded?
+ * @param aIsInline Is this an inline classic script (as opposed to an
+ * externally loaded classic script or module script)?
* @param aURI What is the URI of the script (the document URI if
* it is inline).
* @param aLineNo At what line does the script appear (generally 1
* if it is a loaded script).
*/
- void scriptAvailable(in nsresult aResult,
+ void scriptAvailable(in nsresult aResult,
in nsIScriptElement aElement,
- in boolean aIsInline,
+ in boolean aIsInlineClassicScript,
in nsIURI aURI,
in int32_t aLineNo);
@@ -40,7 +41,7 @@ interface nsIScriptLoaderObserver : nsISupports {
* @param aElement The element being processed.
* @param aIsInline Is this an inline script or externally loaded?
*/
- void scriptEvaluated(in nsresult aResult,
+ void scriptEvaluated(in nsresult aResult,
in nsIScriptElement aElement,
in boolean aIsInline);
diff --git a/dom/xslt/xslt/txMozillaXMLOutput.cpp b/dom/xslt/xslt/txMozillaXMLOutput.cpp
index 704d8ac11..21b3c228f 100644
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -955,7 +955,7 @@ NS_IMPL_ISUPPORTS(txTransformNotifier,
NS_IMETHODIMP
txTransformNotifier::ScriptAvailable(nsresult aResult,
nsIScriptElement *aElement,
- bool aIsInline,
+ bool aIsInlineClassicScript,
nsIURI *aURI,
int32_t aLineNo)
{