Bug 1572644 - Part 11-2: Preload localized error msg and format it when resolving failed. r=jonco,yulia

Depends on D166549

Differential Revision: https://phabricator.services.mozilla.com/D170161
This commit is contained in:
Yoshi Cheng-Hao Huang 2023-03-13 22:59:41 +00:00
Родитель c01828aba9
Коммит a582a668da
6 изменённых файлов: 96 добавлений и 3 удалений

Просмотреть файл

@ -11,6 +11,9 @@
#include "mozilla/dom/WorkletImpl.h" #include "mozilla/dom/WorkletImpl.h"
#include "xpcprivate.h" #include "xpcprivate.h"
using JS::loader::ResolveError;
using JS::loader::ResolveErrorInfo;
namespace mozilla::dom { namespace mozilla::dom {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Worklet // Worklet
@ -52,12 +55,51 @@ JSObject* Worklet::WrapObject(JSContext* aCx,
return mImpl->WrapWorklet(aCx, this, aGivenProto); return mImpl->WrapWorklet(aCx, this, aGivenProto);
} }
static bool LoadLocalizedStrings(nsTArray<nsString>& aStrings) {
// All enumes in ResolveError.
ResolveError errors[] = {ResolveError::Failure,
ResolveError::FailureMayBeBare,
ResolveError::BlockedByNullEntry,
ResolveError::BlockedByAfterPrefix,
ResolveError::BlockedByBacktrackingPrefix,
ResolveError::InvalidBareSpecifier};
static_assert(
ArrayLength(errors) == static_cast<size_t>(ResolveError::Length),
"The array 'errors' has missing entries in the enum class ResolveError.");
for (auto i : errors) {
nsAutoString message;
nsresult rv = nsContentUtils::GetLocalizedString(
nsContentUtils::eDOM_PROPERTIES, ResolveErrorInfo::GetString(i),
message);
if (NS_WARN_IF(NS_FAILED(rv))) {
if (NS_WARN_IF(!aStrings.AppendElement(EmptyString(), fallible))) {
return false;
}
} else {
if (NS_WARN_IF(!aStrings.AppendElement(message, fallible))) {
return false;
}
}
}
return true;
}
already_AddRefed<Promise> Worklet::AddModule(JSContext* aCx, already_AddRefed<Promise> Worklet::AddModule(JSContext* aCx,
const nsAString& aModuleURL, const nsAString& aModuleURL,
const WorkletOptions& aOptions, const WorkletOptions& aOptions,
CallerType aCallerType, CallerType aCallerType,
ErrorResult& aRv) { ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (mLocalizedStrings.IsEmpty()) {
bool result = LoadLocalizedStrings(mLocalizedStrings);
if (!result) {
return nullptr;
}
}
return WorkletFetchHandler::AddModule(this, aCx, aModuleURL, aOptions, aRv); return WorkletFetchHandler::AddModule(this, aCx, aModuleURL, aOptions, aRv);
} }

Просмотреть файл

@ -50,6 +50,10 @@ class Worklet final : public nsISupports, public nsWrapperCache {
WorkletImpl* Impl() const { return mImpl; } WorkletImpl* Impl() const { return mImpl; }
const nsTArray<nsString>& GetLocalizedStrings() const {
return mLocalizedStrings;
}
private: private:
~Worklet(); ~Worklet();
@ -65,6 +69,8 @@ class Worklet final : public nsISupports, public nsWrapperCache {
const RefPtr<WorkletImpl> mImpl; const RefPtr<WorkletImpl> mImpl;
nsTArray<nsString> mLocalizedStrings;
friend class WorkletFetchHandler; friend class WorkletFetchHandler;
friend class WorkletScriptHandler; friend class WorkletScriptHandler;
}; };

Просмотреть файл

@ -36,12 +36,14 @@ class StartModuleLoadRunnable final : public Runnable {
StartModuleLoadRunnable( StartModuleLoadRunnable(
WorkletImpl* aWorkletImpl, WorkletImpl* aWorkletImpl,
const nsMainThreadPtrHandle<WorkletFetchHandler>& aHandlerRef, const nsMainThreadPtrHandle<WorkletFetchHandler>& aHandlerRef,
nsCOMPtr<nsIURI> aURI, nsIURI* aReferrer) nsCOMPtr<nsIURI> aURI, nsIURI* aReferrer,
const nsTArray<nsString>& aLocalizedStrs)
: Runnable("Worklet::StartModuleLoadRunnable"), : Runnable("Worklet::StartModuleLoadRunnable"),
mWorkletImpl(aWorkletImpl), mWorkletImpl(aWorkletImpl),
mHandlerRef(aHandlerRef), mHandlerRef(aHandlerRef),
mURI(std::move(aURI)), mURI(std::move(aURI)),
mReferrer(aReferrer), mReferrer(aReferrer),
mLocalizedStrs(aLocalizedStrs),
mParentRuntime( mParentRuntime(
JS_GetParentRuntime(CycleCollectedJSContext::Get()->Context())) { JS_GetParentRuntime(CycleCollectedJSContext::Get()->Context())) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -59,6 +61,7 @@ class StartModuleLoadRunnable final : public Runnable {
nsMainThreadPtrHandle<WorkletFetchHandler> mHandlerRef; nsMainThreadPtrHandle<WorkletFetchHandler> mHandlerRef;
nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mURI;
nsIURI* mReferrer; nsIURI* mReferrer;
const nsTArray<nsString>& mLocalizedStrs;
JSRuntime* mParentRuntime; JSRuntime* mParentRuntime;
}; };
@ -93,6 +96,10 @@ NS_IMETHODIMP StartModuleLoadRunnable::RunOnWorkletThread() {
static_cast<WorkletModuleLoader*>(globalScope->GetModuleLoader()); static_cast<WorkletModuleLoader*>(globalScope->GetModuleLoader());
MOZ_ASSERT(moduleLoader); MOZ_ASSERT(moduleLoader);
if (!moduleLoader->HasSetLocalizedStrings()) {
moduleLoader->SetLocalizedStrings(&mLocalizedStrs);
}
RefPtr<WorkletLoadContext> loadContext = new WorkletLoadContext(mHandlerRef); RefPtr<WorkletLoadContext> loadContext = new WorkletLoadContext(mHandlerRef);
// Part of Step 2. This sets the Top-level flag to true // Part of Step 2. This sets the Top-level flag to true
@ -297,7 +304,8 @@ already_AddRefed<Promise> WorkletFetchHandler::AddModule(
// Step 1.4. Let referrerSource be documents URL. // Step 1.4. Let referrerSource be documents URL.
nsIURI* referrer = doc->GetDocumentURIAsReferrer(); nsIURI* referrer = doc->GetDocumentURIAsReferrer();
nsCOMPtr<nsIRunnable> runnable = new StartModuleLoadRunnable( nsCOMPtr<nsIRunnable> runnable = new StartModuleLoadRunnable(
aWorklet->mImpl, handlerRef, std::move(resolvedURI), referrer); aWorklet->mImpl, handlerRef, std::move(resolvedURI), referrer,
aWorklet->GetLocalizedStrings());
if (NS_FAILED(aWorklet->mImpl->SendControlMessage(runnable.forget()))) { if (NS_FAILED(aWorklet->mImpl->SendControlMessage(runnable.forget()))) {
return nullptr; return nullptr;

Просмотреть файл

@ -12,8 +12,10 @@
#include "mozilla/ScopeExit.h" #include "mozilla/ScopeExit.h"
#include "mozilla/dom/Worklet.h" #include "mozilla/dom/Worklet.h"
#include "mozilla/dom/WorkletFetchHandler.h" #include "mozilla/dom/WorkletFetchHandler.h"
#include "nsStringBundle.h"
using JS::loader::ModuleLoadRequest; using JS::loader::ModuleLoadRequest;
using JS::loader::ResolveError;
namespace mozilla::dom::loader { namespace mozilla::dom::loader {
@ -188,6 +190,26 @@ void WorkletModuleLoader::OnModuleLoadComplete(ModuleLoadRequest* aRequest) {
NS_DispatchToMainThread(runnable.forget()); NS_DispatchToMainThread(runnable.forget());
} }
// TODO: Bug 1808301: Call FormatLocalizedString from a worklet thread.
nsresult WorkletModuleLoader::GetResolveFailureMessage(
ResolveError aError, const nsAString& aSpecifier, nsAString& aResult) {
uint8_t index = static_cast<uint8_t>(aError);
MOZ_ASSERT(index < static_cast<uint8_t>(ResolveError::Length));
MOZ_ASSERT(mLocalizedStrs);
MOZ_ASSERT(!mLocalizedStrs->IsEmpty());
if (!mLocalizedStrs || NS_WARN_IF(mLocalizedStrs->IsEmpty())) {
return NS_ERROR_FAILURE;
}
const nsString& localizedStr = mLocalizedStrs->ElementAt(index);
AutoTArray<nsString, 1> params;
params.AppendElement(aSpecifier);
nsStringBundleBase::FormatString(localizedStr.get(), params, aResult);
return NS_OK;
}
void WorkletModuleLoader::InsertRequest(nsIURI* aURI, void WorkletModuleLoader::InsertRequest(nsIURI* aURI,
ModuleLoadRequest* aRequest) { ModuleLoadRequest* aRequest) {
mFetchingRequests.InsertOrUpdate(aURI, aRequest); mFetchingRequests.InsertOrUpdate(aURI, aRequest);

Просмотреть файл

@ -9,6 +9,7 @@
#include "js/loader/LoadContextBase.h" #include "js/loader/LoadContextBase.h"
#include "js/loader/ModuleLoaderBase.h" #include "js/loader/ModuleLoaderBase.h"
#include "js/loader/ResolveResult.h" // For ResolveError
#include "mozilla/dom/WorkletFetchHandler.h" #include "mozilla/dom/WorkletFetchHandler.h"
namespace mozilla::dom { namespace mozilla::dom {
@ -54,6 +55,11 @@ class WorkletModuleLoader : public JS::loader::ModuleLoaderBase {
void RemoveRequest(nsIURI* aURI); void RemoveRequest(nsIURI* aURI);
JS::loader::ModuleLoadRequest* GetRequest(nsIURI* aURI) const; JS::loader::ModuleLoadRequest* GetRequest(nsIURI* aURI) const;
bool HasSetLocalizedStrings() const { return (bool)mLocalizedStrs; }
void SetLocalizedStrings(const nsTArray<nsString>* aStrings) {
mLocalizedStrs = aStrings;
}
private: private:
~WorkletModuleLoader() = default; ~WorkletModuleLoader() = default;
@ -78,10 +84,18 @@ class WorkletModuleLoader : public JS::loader::ModuleLoaderBase {
void OnModuleLoadComplete(JS::loader::ModuleLoadRequest* aRequest) override; void OnModuleLoadComplete(JS::loader::ModuleLoadRequest* aRequest) override;
nsresult GetResolveFailureMessage(JS::loader::ResolveError aError,
const nsAString& aSpecifier,
nsAString& aResult) override;
// A hashtable to map a nsIURI(from main thread) to a ModuleLoadRequest(in // A hashtable to map a nsIURI(from main thread) to a ModuleLoadRequest(in
// worklet thread). // worklet thread).
nsRefPtrHashtable<nsURIHashKey, JS::loader::ModuleLoadRequest> nsRefPtrHashtable<nsURIHashKey, JS::loader::ModuleLoadRequest>
mFetchingRequests; mFetchingRequests;
// We get the localized strings on the main thread, and pass it to
// WorkletModuleLoader.
const nsTArray<nsString>* mLocalizedStrs = nullptr;
}; };
} // namespace loader } // namespace loader

Просмотреть файл

@ -19,7 +19,8 @@ enum class ResolveError : uint8_t {
BlockedByNullEntry, BlockedByNullEntry,
BlockedByAfterPrefix, BlockedByAfterPrefix,
BlockedByBacktrackingPrefix, BlockedByBacktrackingPrefix,
InvalidBareSpecifier InvalidBareSpecifier,
Length
}; };
struct ResolveErrorInfo { struct ResolveErrorInfo {