Bug 1667455 - Part 1: Define Services in all system globals. r=kmag

`Services` object is created in the loader's shared global, and it is defined
on all globals without OMIT_COMPONENTS_OBJECT.

Differential Revision: https://phabricator.services.mozilla.com/D150890
This commit is contained in:
Tooru Fujisawa 2022-07-11 12:41:47 +00:00
Родитель 17a20bb87e
Коммит d3780ba56a
6 изменённых файлов: 71 добавлений и 1 удалений

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

@ -48,6 +48,7 @@
#include "WrapperFactory.h"
#include "JSMEnvironmentProxy.h"
#include "ModuleEnvironmentProxy.h"
#include "JSServices.h"
#include "mozilla/scache/StartupCache.h"
#include "mozilla/scache/StartupCacheUtils.h"
@ -266,7 +267,8 @@ mozJSModuleLoader::mozJSModuleLoader()
mFallbackImports(16),
mLocations(16),
mInitialized(false),
mLoaderGlobal(dom::RootingCx()) {
mLoaderGlobal(dom::RootingCx()),
mServicesObj(dom::RootingCx()) {
MOZ_ASSERT(!sSelf, "mozJSModuleLoader should be a singleton");
}
@ -545,10 +547,18 @@ void mozJSModuleLoader::CreateLoaderGlobal(JSContext* aCx,
// been defined so the JS debugger can tell what module the global is
// for
RootedObject global(aCx);
#ifdef DEBUG
// See mozJSModuleLoader::DefineJSServices.
mIsInitializingLoaderGlobal = true;
#endif
nsresult rv = xpc::InitClassesWithNewWrappedGlobal(
aCx, static_cast<nsIGlobalObject*>(backstagePass),
nsContentUtils::GetSystemPrincipal(), xpc::DONT_FIRE_ONNEWGLOBALHOOK,
options, &global);
#ifdef DEBUG
mIsInitializingLoaderGlobal = false;
#endif
NS_ENSURE_SUCCESS_VOID(rv);
NS_ENSURE_TRUE_VOID(global);
@ -560,6 +570,14 @@ void mozJSModuleLoader::CreateLoaderGlobal(JSContext* aCx,
return;
}
if (!CreateJSServices(aCx)) {
return;
}
if (!DefineJSServices(aCx, global)) {
return;
}
// Set the location information for the new global, so that tools like
// about:memory may use that information
xpc::SetLocationForGlobal(global, aLocation);
@ -959,6 +977,7 @@ void mozJSModuleLoader::UnloadModules() {
JS_SetAllNonReservedSlotsToUndefined(mLoaderGlobal);
mLoaderGlobal = nullptr;
}
mServicesObj = nullptr;
mFallbackImports.Clear();
mInProgressImports.Clear();
@ -1637,6 +1656,41 @@ nsresult mozJSModuleLoader::Unload(const nsACString& aLocation) {
return NS_OK;
}
bool mozJSModuleLoader::CreateJSServices(JSContext* aCx) {
JSObject* services = NewJSServices(aCx);
if (!services) {
return false;
}
mServicesObj = services;
return true;
}
bool mozJSModuleLoader::DefineJSServices(JSContext* aCx,
JS::Handle<JSObject*> aGlobal) {
if (!mServicesObj) {
// This function is called whenever creating a new global that needs
// `Services`, including the loader's shared global.
//
// This function is no-op if it's called during creating the loader's
// shared global.
//
// See also CreateAndDefineJSServices.
MOZ_ASSERT(!mLoaderGlobal);
MOZ_ASSERT(mIsInitializingLoaderGlobal);
return true;
}
JS::Rooted<JS::Value> services(aCx, ObjectValue(*mServicesObj));
if (!JS_WrapValue(aCx, &services)) {
return false;
}
JS::Rooted<JS::PropertyKey> servicesId(
aCx, XPCJSContext::Get()->GetStringID(XPCJSContext::IDX_SERVICES));
return JS_DefinePropertyById(aCx, aGlobal, servicesId, services, 0);
}
size_t mozJSModuleLoader::ModuleEntry::SizeOfIncludingThis(
MallocSizeOf aMallocSizeOf) const {
size_t n = aMallocSizeOf(this);

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

@ -104,6 +104,8 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
bool DefineJSServices(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
protected:
mozJSModuleLoader();
~mozJSModuleLoader();
@ -118,6 +120,8 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
void CreateLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
JS::MutableHandleObject aGlobal);
bool CreateJSServices(JSContext* aCx);
JSObject* GetSharedGlobal(JSContext* aCx);
static nsresult GetSourceFile(nsIURI* aResolvedURI, nsIFile** aSourceFileOut);
@ -227,7 +231,11 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
nsClassHashtable<nsCStringHashKey, nsCString> mLocations;
bool mInitialized;
#ifdef DEBUG
bool mIsInitializingLoaderGlobal = false;
#endif
JS::PersistentRooted<JSObject*> mLoaderGlobal;
JS::PersistentRooted<JSObject*> mServicesObj;
RefPtr<mozilla::loader::ComponentModuleLoader> mModuleLoader;
};

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

@ -103,6 +103,7 @@ const char* const XPCJSRuntime::mStrings[] = {
"Ci", // IDX_CI
"Cr", // IDX_CR
"Cu", // IDX_CU
"Services", // IDX_SERVICES
"wrappedJSObject", // IDX_WRAPPED_JSOBJECT
"prototype", // IDX_PROTOTYPE
"eval", // IDX_EVAL

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

@ -6,6 +6,7 @@
EXPORTS += [
"BackstagePass.h",
"JSServices.h",
"XPCJSMemoryReporter.h",
"xpcObjectHelper.h",
"xpcpublic.h",

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

@ -26,6 +26,7 @@
#include "WrapperFactory.h"
#include "AccessCheck.h"
#include "JSServices.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/BindingUtils.h"
@ -512,6 +513,10 @@ bool InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal,
!XPCNativeWrapper::AttachNewConstructorObject(aJSContext, aGlobal)) {
return UnexpectedFailure(false);
}
if (!mozJSModuleLoader::Get()->DefineJSServices(aJSContext, aGlobal)) {
return UnexpectedFailure(false);
}
}
if (!(aFlags & xpc::DONT_FIRE_ONNEWGLOBALHOOK)) {

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

@ -379,6 +379,7 @@ class XPCJSContext final : public mozilla::CycleCollectedJSContext,
IDX_CI,
IDX_CR,
IDX_CU,
IDX_SERVICES,
IDX_WRAPPED_JSOBJECT,
IDX_PROTOTYPE,
IDX_EVAL,