Skip to content

Commit b267594

Browse files
committed
Bug 1916277 - Part 6: Implement AddToResolvedModuleSet to complete the 'resolve a module specifier' per spec. r=jonco
The addition is performed after resolution so that resolved specifiers can be processed more easily, particularly for preload requests. This change also refactors the return value of ResolvedModuleSpecifier to use a SpecifierResolutionRecord instead. Differential Revision: https://phabricator.services.mozilla.com/D272779
1 parent ada725c commit b267594

5 files changed

Lines changed: 113 additions & 10 deletions

File tree

dom/script/ScriptLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,8 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
652652
ScriptLoadRequest* aRequest, const char* aMessageName,
653653
const nsTArray<nsString>& aParams = nsTArray<nsString>()) const override;
654654

655+
bool IsImportMapSupported() const override { return true; }
656+
655657
void ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest);
656658

657659
nsIConsoleReportCollector* GetConsoleReportCollector() const override {

js/loader/ImportMap.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
1111
#include "js/JSON.h" // JS_ParseJSON
1212
#include "js/PropertyDescriptor.h" // JS::PropertyDescriptor
13+
#include "mozilla/StaticPrefs_dom.h"
1314
#include "LoadedScript.h"
1415
#include "ModuleLoaderBase.h" // ScriptLoaderInterface
1516
#include "nsContentUtils.h"
@@ -42,9 +43,12 @@ void ReportWarningHelper::Report(const char* aMessageName,
4243
mLoader->ReportWarningToConsole(mRequest, aMessageName, aParams);
4344
}
4445

46+
using ResolveURLLikeResult =
47+
mozilla::Result<mozilla::NotNull<nsCOMPtr<nsIURI>>, ResolveError>;
48+
4549
// https://html.spec.whatwg.org/multipage/webappapis.html#resolving-a-url-like-module-specifier
46-
static ResolveResult ResolveURLLikeModuleSpecifier(const nsAString& aSpecifier,
47-
nsIURI* aBaseURL) {
50+
static ResolveURLLikeResult ResolveURLLikeModuleSpecifier(
51+
const nsAString& aSpecifier, nsIURI* aBaseURL) {
4852
nsCOMPtr<nsIURI> uri;
4953
nsresult rv;
5054

@@ -719,6 +723,16 @@ static mozilla::Result<nsCOMPtr<nsIURI>, ResolveError> ResolveImportsMatch(
719723
return nsCOMPtr<nsIURI>(nullptr);
720724
}
721725

726+
static UniquePtr<SpecifierResolutionRecord> CreateResolutionRecord(
727+
ScriptLoaderInterface* aLoader, nsCString& aSerializedBaseURL,
728+
nsString& aNormalizedSpecifier, nsIURI* aAsURL, nsIURI* aResult) {
729+
bool isURLLike = !!aAsURL;
730+
bool isSpecial = aAsURL ? IsSpecialScheme(aAsURL) : false;
731+
732+
return mozilla::MakeUnique<SpecifierResolutionRecord>(
733+
aSerializedBaseURL, aNormalizedSpecifier, aResult, isURLLike, isSpecial);
734+
}
735+
722736
// https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
723737
// static
724738
ResolveResult ImportMap::ResolveModuleSpecifier(ImportMap* aImportMap,
@@ -802,10 +816,17 @@ ResolveResult ImportMap::ResolveModuleSpecifier(ImportMap* aImportMap,
802816

803817
// 13. If result is not null, then:
804818
if (result) {
805-
// 2. Return result.
806819
LOG(("ResolveModuleSpecifier returns result: %s",
807820
result->GetSpecOrDefault().get()));
808-
return WrapNotNull(result);
821+
// 1. Add module to resolved module set given settingsObject,
822+
// serializedBaseURL, normalizedSpecifier, and asURL.
823+
//
824+
// Impl note: Implemented in the caller(ModuleLoaderBase), as we need to
825+
// store the result if this resolution is for preload.
826+
827+
// 2. Return result.
828+
return CreateResolutionRecord(aLoader, serializedBaseURL,
829+
normalizedSpecifier, asURL, result);
809830
}
810831

811832
LOG(("ResolveModuleSpecifier failed to resolve specifier: %s",

js/loader/ModuleLoaderBase.cpp

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@
3636
using mozilla::AutoSlowOperation;
3737
using mozilla::CycleCollectedJSContext;
3838
using mozilla::Err;
39+
using mozilla::MakeUnique;
3940
using mozilla::MicroTaskRunnable;
4041
using mozilla::Preferences;
4142
using mozilla::UniquePtr;
42-
using mozilla::WrapNotNull;
4343
using mozilla::dom::AutoJSAPI;
4444
using mozilla::dom::ReferrerPolicy;
4545

@@ -210,9 +210,20 @@ bool ModuleLoaderBase::HostLoadImportedModule(
210210
}
211211

212212
MOZ_ASSERT(result.isOk());
213-
nsCOMPtr<nsIURI> uri = result.unwrap();
213+
auto record = result.unwrap();
214+
nsCOMPtr<nsIURI> uri = record->Result();
214215
MOZ_ASSERT(uri, "Failed to resolve module specifier");
215216

217+
if (ImportMap::IsMultipleImportMapsSupported()) {
218+
// This implements the 'Add module to resolved module set' part defined in
219+
// 'resolve a module specifier'. This is done here because we need to
220+
// process the resolved specifiers differently for preloading module
221+
// scripts.
222+
//
223+
// See https://html.spec.whatwg.org/#resolve-a-module-specifier
224+
loader->AddToResolvedModuleSet(std::move(record), script, aHostDefined);
225+
}
226+
216227
ModuleType moduleType = GetModuleRequestType(aCx, aModuleRequest);
217228
if (!loader->IsModuleTypeAllowed(moduleType)) {
218229
LOG(("ModuleLoaderBase::HostLoadImportedModule uri %s, bad module type",
@@ -398,7 +409,16 @@ JSString* ModuleLoaderBase::ImportMetaResolveImpl(
398409
return nullptr;
399410
}
400411

401-
nsCOMPtr<nsIURI> uri = result.unwrap();
412+
MOZ_ASSERT(result.isOk());
413+
auto record = result.unwrap();
414+
415+
nsCOMPtr<nsIURI> uri = record->Result();
416+
if (ImportMap::IsMultipleImportMapsSupported()) {
417+
// This implements the 'Add module to resolved module set' part defined in
418+
// 'resolve a module specifier'.
419+
loader->AddToResolvedModuleSet(std::move(record));
420+
}
421+
402422
nsAutoCString url;
403423
MOZ_ALWAYS_SUCCEEDS(uri->GetAsciiSpec(url));
404424

@@ -1101,6 +1121,44 @@ ResolveResult ModuleLoaderBase::ResolveModuleSpecifier(
11011121
aSpecifier);
11021122
}
11031123

1124+
ResolvedModuleSet* ModuleLoaderBase::GetResolvedModuleSet() {
1125+
MOZ_ASSERT(ImportMap::IsMultipleImportMapsSupported());
1126+
if (!mResolvedModuleSet) {
1127+
mResolvedModuleSet = MakeUnique<ResolvedModuleSet>();
1128+
}
1129+
1130+
return mResolvedModuleSet.get();
1131+
}
1132+
1133+
static void AddToResolvedSet(ResolvedModuleSet* aSet,
1134+
UniquePtr<SpecifierResolutionRecord> aRecord) {
1135+
MOZ_ASSERT(ImportMap::IsMultipleImportMapsSupported());
1136+
auto ptr = aSet->lookupForAdd(aRecord);
1137+
if (ptr) {
1138+
return;
1139+
}
1140+
1141+
MOZ_ALWAYS_TRUE(aSet->add(ptr, std::move(aRecord)));
1142+
}
1143+
1144+
void ModuleLoaderBase::AddToGlobalResolvedSet(
1145+
UniquePtr<SpecifierResolutionRecord> aRecord) {
1146+
AddToResolvedSet(GetResolvedModuleSet(), std::move(aRecord));
1147+
}
1148+
1149+
void ModuleLoaderBase::AddToResolvedModuleSet(
1150+
UniquePtr<SpecifierResolutionRecord> aRecord, LoadedScript* aScript,
1151+
Handle<Value> aHostDefined) {
1152+
// 2. If global does not implement Window, then return.
1153+
if (!mLoader->IsImportMapSupported()) {
1154+
return;
1155+
}
1156+
1157+
// release the mResult from the record as it is not needed.
1158+
nsCOMPtr<nsIURI> _ = aRecord->TakeResult();
1159+
AddToGlobalResolvedSet(std::move(aRecord));
1160+
}
1161+
11041162
void ModuleLoaderBase::StartFetchingModuleDependencies(
11051163
ModuleLoadRequest* aRequest) {
11061164
if (aRequest->IsCanceled()) {

js/loader/ModuleLoaderBase.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "mozilla/UniquePtr.h"
2727
#include "mozilla/dom/ReferrerPolicyBinding.h"
2828
#include "mozilla/StaticPrefs_layout.h"
29+
#include "ResolvedModuleSet.h"
2930
#include "ResolveResult.h"
3031

3132
class nsIConsoleReportCollector;
@@ -116,6 +117,10 @@ class ScriptLoaderInterface : public nsISupports {
116117
}
117118

118119
virtual void MaybeUpdateDiskCache() {}
120+
121+
// Import map is supported if the global implements 'Windows'.
122+
// See https://html.spec.whatwg.org/#concept-global-import-map
123+
virtual bool IsImportMapSupported() const { return false; }
119124
};
120125

121126
class ModuleMapKey : public PLDHashEntryHdr {
@@ -280,6 +285,8 @@ class ModuleLoaderBase : public nsISupports {
280285

281286
mozilla::UniquePtr<ImportMap> mImportMap;
282287

288+
mozilla::UniquePtr<ResolvedModuleSet> mResolvedModuleSet;
289+
283290
virtual ~ModuleLoaderBase();
284291

285292
#ifdef DEBUG
@@ -441,6 +448,8 @@ class ModuleLoaderBase : public nsISupports {
441448
nsIConsoleReportCollector* aReporter,
442449
mozilla::dom::SRIMetadata* aMetadataOut);
443450

451+
ResolvedModuleSet* GetResolvedModuleSet();
452+
444453
// Returns true if the module for given module key is already fetched.
445454
bool IsModuleFetched(const ModuleMapKey& key) const;
446455

@@ -522,6 +531,17 @@ class ModuleLoaderBase : public nsISupports {
522531
bool IsModuleFetching(const ModuleMapKey& key) const;
523532
void WaitForModuleFetch(ModuleLoadRequest* aRequest);
524533

534+
void AddToGlobalResolvedSet(
535+
mozilla::UniquePtr<SpecifierResolutionRecord> aRecord);
536+
537+
// https://html.spec.whatwg.org/#add-module-to-resolved-module-set
538+
// The aScript and aHostDefined arguments are for determining if this is
539+
// resolved during preloading.
540+
void AddToResolvedModuleSet(
541+
mozilla::UniquePtr<SpecifierResolutionRecord> aRecord,
542+
LoadedScript* aScript = nullptr,
543+
Handle<Value> aHostDefined = UndefinedHandleValue);
544+
525545
protected:
526546
void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
527547

js/loader/ResolveResult.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
#define js_loader_ResolveResult_h
99

1010
#include "mozilla/ResultVariant.h"
11-
#include "mozilla/NotNull.h"
11+
#include "mozilla/UniquePtr.h"
1212
#include "nsIURI.h"
13+
#include "ResolvedModuleSet.h"
1314

1415
namespace JS::loader {
1516

@@ -46,10 +47,11 @@ struct ResolveErrorInfo {
4647

4748
/**
4849
* ResolveResult is used to store the result of 'resolving a module specifier',
49-
* which could be an URI on success or a ResolveError on failure.
50+
* which could be a resolution record on success or a ResolveError on failure.
5051
*/
5152
using ResolveResult =
52-
mozilla::Result<mozilla::NotNull<nsCOMPtr<nsIURI>>, ResolveError>;
53+
mozilla::Result<mozilla::UniquePtr<SpecifierResolutionRecord>,
54+
ResolveError>;
5355

5456
} // namespace JS::loader
5557

0 commit comments

Comments
 (0)