зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1789543 - Part 3: Trigger missing chrome/resource URL error handling with original JSM URL when fallback to ESMified URL also fails. r=yulia
Depends on D156763 Differential Revision: https://phabricator.services.mozilla.com/D156764
This commit is contained in:
Родитель
ce2d3ed35b
Коммит
e8ade43d3f
|
@ -10,6 +10,8 @@
|
||||||
#include "js/loader/LoadContextBase.h"
|
#include "js/loader/LoadContextBase.h"
|
||||||
#include "js/loader/ModuleLoaderBase.h"
|
#include "js/loader/ModuleLoaderBase.h"
|
||||||
|
|
||||||
|
#include "SkipCheckForBrokenURLOrZeroSized.h"
|
||||||
|
|
||||||
class mozJSModuleLoader;
|
class mozJSModuleLoader;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -103,6 +105,8 @@ class ComponentLoadContext : public JS::loader::LoadContextBase {
|
||||||
// before being passed to the module loader.
|
// before being passed to the module loader.
|
||||||
nsresult mRv;
|
nsresult mRv;
|
||||||
|
|
||||||
|
SkipCheckForBrokenURLOrZeroSized mSkipCheck;
|
||||||
|
|
||||||
// The exception thrown during compiling a module script. These fields are
|
// The exception thrown during compiling a module script. These fields are
|
||||||
// used temporarily before being passed to the module loader.
|
// used temporarily before being passed to the module loader.
|
||||||
JS::PersistentRooted<JS::Value> mExceptionValue;
|
JS::PersistentRooted<JS::Value> mExceptionValue;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_loader_SkipCheckForBrokenURLOrZeroSized_h
|
||||||
|
#define mozilla_loader_SkipCheckForBrokenURLOrZeroSized_h
|
||||||
|
|
||||||
|
#include <stdint.h> // uint8_t
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace loader {
|
||||||
|
|
||||||
|
// Represents the `aSkipCheckForBrokenURLOrZeroSized` parameter for
|
||||||
|
// `NS_NewChannel` function.
|
||||||
|
enum class SkipCheckForBrokenURLOrZeroSized : uint8_t { No, Yes };
|
||||||
|
|
||||||
|
} // namespace loader
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_loader_SkipCheckForBrokenURLOrZeroSized_h
|
|
@ -45,6 +45,7 @@ EXPORTS.mozilla.loader += [
|
||||||
"AutoMemMap.h",
|
"AutoMemMap.h",
|
||||||
"ComponentModuleLoader.h",
|
"ComponentModuleLoader.h",
|
||||||
"ScriptCacheActors.h",
|
"ScriptCacheActors.h",
|
||||||
|
"SkipCheckForBrokenURLOrZeroSized.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_JS_MODULES += [
|
||||||
|
|
|
@ -289,10 +289,25 @@ mozJSModuleLoader::mozJSModuleLoader()
|
||||||
|
|
||||||
class MOZ_STACK_CLASS ModuleLoaderInfo {
|
class MOZ_STACK_CLASS ModuleLoaderInfo {
|
||||||
public:
|
public:
|
||||||
explicit ModuleLoaderInfo(const nsACString& aLocation)
|
explicit ModuleLoaderInfo(const nsACString& aLocation,
|
||||||
: mLocation(&aLocation), mIsModule(false) {}
|
SkipCheckForBrokenURLOrZeroSized aSkipCheck =
|
||||||
|
SkipCheckForBrokenURLOrZeroSized::No)
|
||||||
|
: mLocation(&aLocation), mIsModule(false), mSkipCheck(aSkipCheck) {}
|
||||||
explicit ModuleLoaderInfo(JS::loader::ModuleLoadRequest* aRequest)
|
explicit ModuleLoaderInfo(JS::loader::ModuleLoadRequest* aRequest)
|
||||||
: mLocation(nullptr), mURI(aRequest->mURI), mIsModule(true) {}
|
: mLocation(nullptr),
|
||||||
|
mURI(aRequest->mURI),
|
||||||
|
mIsModule(true),
|
||||||
|
mSkipCheck(aRequest->GetComponentLoadContext()->mSkipCheck) {}
|
||||||
|
|
||||||
|
SkipCheckForBrokenURLOrZeroSized getSkipCheckForBrokenURLOrZeroSized() const {
|
||||||
|
return mSkipCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetChannelWithCheckForBrokenURLOrZeroSized() {
|
||||||
|
MOZ_ASSERT(mSkipCheck == SkipCheckForBrokenURLOrZeroSized::Yes);
|
||||||
|
mSkipCheck = SkipCheckForBrokenURLOrZeroSized::No;
|
||||||
|
mScriptChannel = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
nsIIOService* IOService() {
|
nsIIOService* IOService() {
|
||||||
MOZ_ASSERT(mIOService);
|
MOZ_ASSERT(mIOService);
|
||||||
|
@ -325,14 +340,7 @@ class MOZ_STACK_CLASS ModuleLoaderInfo {
|
||||||
nsresult EnsureScriptChannel() {
|
nsresult EnsureScriptChannel() {
|
||||||
BEGIN_ENSURE(ScriptChannel, IOService, URI);
|
BEGIN_ENSURE(ScriptChannel, IOService, URI);
|
||||||
|
|
||||||
// The JSM may already be ESM-ified, and in that case the load is expected
|
// Skip check for missing URL when handling JSM-to-ESM fallback.
|
||||||
// to fail. Suppress the error message, the crash, and also the telemetry
|
|
||||||
// event for the failure.
|
|
||||||
//
|
|
||||||
// If this load fails, it will be redirected to `.sys.mjs` URL
|
|
||||||
// in TryFallbackToImportESModule, and the check is performed there.
|
|
||||||
bool skipCheckForBrokenURLOrZeroSized = !IsModule();
|
|
||||||
|
|
||||||
return NS_NewChannel(
|
return NS_NewChannel(
|
||||||
getter_AddRefs(mScriptChannel), mURI,
|
getter_AddRefs(mScriptChannel), mURI,
|
||||||
nsContentUtils::GetSystemPrincipal(),
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
@ -342,7 +350,7 @@ class MOZ_STACK_CLASS ModuleLoaderInfo {
|
||||||
/* aPerformanceStorage = */ nullptr,
|
/* aPerformanceStorage = */ nullptr,
|
||||||
/* aLoadGroup = */ nullptr, /* aCallbacks = */ nullptr,
|
/* aLoadGroup = */ nullptr, /* aCallbacks = */ nullptr,
|
||||||
nsIRequest::LOAD_NORMAL, mIOService, /* aSandboxFlags = */ 0,
|
nsIRequest::LOAD_NORMAL, mIOService, /* aSandboxFlags = */ 0,
|
||||||
skipCheckForBrokenURLOrZeroSized);
|
mSkipCheck == SkipCheckForBrokenURLOrZeroSized::Yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIURI* ResolvedURI() {
|
nsIURI* ResolvedURI() {
|
||||||
|
@ -374,6 +382,7 @@ class MOZ_STACK_CLASS ModuleLoaderInfo {
|
||||||
nsCOMPtr<nsIChannel> mScriptChannel;
|
nsCOMPtr<nsIChannel> mScriptChannel;
|
||||||
nsCOMPtr<nsIURI> mResolvedURI;
|
nsCOMPtr<nsIURI> mResolvedURI;
|
||||||
const bool mIsModule;
|
const bool mIsModule;
|
||||||
|
SkipCheckForBrokenURLOrZeroSized mSkipCheck;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -1394,7 +1403,14 @@ nsresult mozJSModuleLoader::Import(JSContext* aCx, const nsACString& aLocation,
|
||||||
MarkerInnerWindowIdFromJSContext(aCx)),
|
MarkerInnerWindowIdFromJSContext(aCx)),
|
||||||
aLocation);
|
aLocation);
|
||||||
|
|
||||||
ModuleLoaderInfo info(aLocation);
|
// The JSM may already be ESM-ified, and in that case the load is expected
|
||||||
|
// to fail. Suppress the error message, the crash, and also the telemetry
|
||||||
|
// event for the failure.
|
||||||
|
//
|
||||||
|
// If this load fails, it will be redirected to `.sys.mjs` URL
|
||||||
|
// in TryFallbackToImportESModule, and if the redirect also fails,
|
||||||
|
// the load is performed again below, with the check enabled.
|
||||||
|
ModuleLoaderInfo info(aLocation, SkipCheckForBrokenURLOrZeroSized::Yes);
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
ModuleEntry* mod;
|
ModuleEntry* mod;
|
||||||
|
@ -1467,8 +1483,23 @@ nsresult mozJSModuleLoader::Import(JSContext* aCx, const nsACString& aLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
||||||
return TryFallbackToImportESModule(aCx, aLocation, aModuleGlobal,
|
rv = TryFallbackToImportESModule(aCx, aLocation, aModuleGlobal,
|
||||||
aModuleExports, aIgnoreExports);
|
aModuleExports, aIgnoreExports);
|
||||||
|
|
||||||
|
if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
||||||
|
// Both JSM and ESM are not found, with the check inside necko
|
||||||
|
// skipped (See EnsureScriptChannel and mSkipCheck).
|
||||||
|
//
|
||||||
|
// Perform the load again with the check enabled, so that
|
||||||
|
// logging, crash-on-autonation, and telemetry event happen.
|
||||||
|
if (NS_SUCCEEDED(info.EnsureURI()) &&
|
||||||
|
!LocationIsRealFile(info.URI())) {
|
||||||
|
info.resetChannelWithCheckForBrokenURLOrZeroSized();
|
||||||
|
(void)ReadScript(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something failed, but we don't know what it is, guess.
|
// Something failed, but we don't know what it is, guess.
|
||||||
|
@ -1526,7 +1557,10 @@ nsresult mozJSModuleLoader::TryFallbackToImportESModule(
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::RootedObject moduleNamespace(aCx);
|
JS::RootedObject moduleNamespace(aCx);
|
||||||
nsresult rv = ImportESModule(aCx, mjsLocation, &moduleNamespace);
|
// The fallback can fail if the URL was not for ESMified JSM. Suppress the
|
||||||
|
// error message, the crash, and also the telemetry event for the failure.
|
||||||
|
nsresult rv = ImportESModule(aCx, mjsLocation, &moduleNamespace,
|
||||||
|
SkipCheckForBrokenURLOrZeroSized::Yes);
|
||||||
if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
||||||
// The error for ESModule shouldn't be exposed if the file does not exist.
|
// The error for ESModule shouldn't be exposed if the file does not exist.
|
||||||
if (JS_IsExceptionPending(aCx)) {
|
if (JS_IsExceptionPending(aCx)) {
|
||||||
|
@ -1605,7 +1639,9 @@ nsresult mozJSModuleLoader::TryCachedFallbackToImportESModule(
|
||||||
|
|
||||||
nsresult mozJSModuleLoader::ImportESModule(
|
nsresult mozJSModuleLoader::ImportESModule(
|
||||||
JSContext* aCx, const nsACString& aLocation,
|
JSContext* aCx, const nsACString& aLocation,
|
||||||
JS::MutableHandleObject aModuleNamespace) {
|
JS::MutableHandleObject aModuleNamespace,
|
||||||
|
SkipCheckForBrokenURLOrZeroSized
|
||||||
|
aSkipCheck /* = SkipCheckForBrokenURLOrZeroSized::No */) {
|
||||||
using namespace JS::loader;
|
using namespace JS::loader;
|
||||||
|
|
||||||
MOZ_ASSERT(mModuleLoader);
|
MOZ_ASSERT(mModuleLoader);
|
||||||
|
@ -1643,6 +1679,7 @@ nsresult mozJSModuleLoader::ImportESModule(
|
||||||
CORS_NONE, dom::ReferrerPolicy::No_referrer, principal);
|
CORS_NONE, dom::ReferrerPolicy::No_referrer, principal);
|
||||||
|
|
||||||
RefPtr<ComponentLoadContext> context = new ComponentLoadContext();
|
RefPtr<ComponentLoadContext> context = new ComponentLoadContext();
|
||||||
|
context->mSkipCheck = aSkipCheck;
|
||||||
|
|
||||||
RefPtr<VisitedURLSet> visitedSet =
|
RefPtr<VisitedURLSet> visitedSet =
|
||||||
ModuleLoadRequest::NewVisitedSetForTopLevelImport(uri);
|
ModuleLoadRequest::NewVisitedSetForTopLevelImport(uri);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "js/experimental/JSStencil.h"
|
#include "js/experimental/JSStencil.h"
|
||||||
|
#include "SkipCheckForBrokenURLOrZeroSized.h"
|
||||||
|
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
|
|
||||||
|
@ -75,8 +76,11 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
|
||||||
bool aIgnoreExports = false);
|
bool aIgnoreExports = false);
|
||||||
|
|
||||||
// Load an ES6 module and all its dependencies.
|
// Load an ES6 module and all its dependencies.
|
||||||
nsresult ImportESModule(JSContext* aCx, const nsACString& aResourceURI,
|
nsresult ImportESModule(
|
||||||
JS::MutableHandleObject aModuleNamespace);
|
JSContext* aCx, const nsACString& aResourceURI,
|
||||||
|
JS::MutableHandleObject aModuleNamespace,
|
||||||
|
mozilla::loader::SkipCheckForBrokenURLOrZeroSized aSkipCheck =
|
||||||
|
mozilla::loader::SkipCheckForBrokenURLOrZeroSized::No);
|
||||||
|
|
||||||
// Fallback from Import to ImportESModule.
|
// Fallback from Import to ImportESModule.
|
||||||
nsresult TryFallbackToImportESModule(JSContext* aCx,
|
nsresult TryFallbackToImportESModule(JSContext* aCx,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче