Bug 1899316 - Add ModuleScript::{FromCache,ToCache}. r=nbp

In order to store ModuleScript in SharedScriptCache, we need to strip off
all GC-things and runtime-related flags.
All fields in ModuleScript matches either of them, so just converting to
base class LoadedScript fits this purpose.

Differential Revision: https://phabricator.services.mozilla.com/D242305
This commit is contained in:
Tooru Fujisawa
2025-03-22 04:03:54 +00:00
parent f5e3e0b553
commit 5c69e6024e
2 changed files with 66 additions and 6 deletions

View File

@@ -6,7 +6,9 @@
#include "LoadedScript.h"
#include "mozilla/AlreadyAddRefed.h" // already_AddRefed
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/RefPtr.h" // RefPtr, mozilla::MakeRefPtr
#include "mozilla/UniquePtr.h" // mozilla::UniquePtr
#include "mozilla/dom/ScriptLoadContext.h" // ScriptLoadContext
@@ -54,6 +56,26 @@ LoadedScript::LoadedScript(ScriptKind aKind,
MOZ_ASSERT(mURI);
}
LoadedScript::LoadedScript(const LoadedScript& aOther)
: mKind(aOther.mKind),
mReferrerPolicy(aOther.mReferrerPolicy),
mFetchOptions(aOther.mFetchOptions),
mURI(aOther.mURI),
mBaseURL(aOther.mBaseURL),
mDataType(DataType::eStencil),
mReceivedScriptTextLength(0),
mBytecodeOffset(0),
mStencil(aOther.mStencil) {
MOZ_ASSERT(mFetchOptions);
MOZ_ASSERT(mURI);
// NOTE: This is only for the stencil case.
// The script text and the bytecode are not reflected.
MOZ_DIAGNOSTIC_ASSERT(aOther.mDataType == DataType::eStencil);
MOZ_DIAGNOSTIC_ASSERT(mStencil);
MOZ_ASSERT(!mScriptData);
MOZ_ASSERT(mScriptBytecode.empty());
}
LoadedScript::~LoadedScript() {
mozilla::UnregisterWeakMemoryReporter(this);
mozilla::DropJSObjects(this);
@@ -262,14 +284,35 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
ModuleScript::ModuleScript(mozilla::dom::ReferrerPolicy aReferrerPolicy,
ScriptFetchOptions* aFetchOptions, nsIURI* aURI)
: LoadedScript(ScriptKind::eModule, aReferrerPolicy, aFetchOptions, aURI),
mHadImportMap(false),
mDebuggerDataInitialized(false) {
: LoadedScript(ScriptKind::eModule, aReferrerPolicy, aFetchOptions, aURI) {
MOZ_ASSERT(!ModuleRecord());
MOZ_ASSERT(!HasParseError());
MOZ_ASSERT(!HasErrorToRethrow());
}
ModuleScript::ModuleScript(const LoadedScript& aOther) : LoadedScript(aOther) {
MOZ_ASSERT(!ModuleRecord());
MOZ_ASSERT(!HasParseError());
MOZ_ASSERT(!HasErrorToRethrow());
}
/* static */
already_AddRefed<ModuleScript> ModuleScript::FromCache(
const LoadedScript& aScript) {
MOZ_DIAGNOSTIC_ASSERT(aScript.IsModuleScript());
MOZ_DIAGNOSTIC_ASSERT(aScript.IsStencil());
return mozilla::MakeRefPtr<ModuleScript>(aScript).forget();
}
already_AddRefed<LoadedScript> ModuleScript::ToCache() {
MOZ_DIAGNOSTIC_ASSERT(IsStencil());
MOZ_DIAGNOSTIC_ASSERT(!HasParseError());
MOZ_DIAGNOSTIC_ASSERT(!HasErrorToRethrow());
return mozilla::MakeRefPtr<LoadedScript>(*this).forget();
}
void ModuleScript::Shutdown() {
if (mModuleRecord) {
JS::ClearModuleEnvironment(mModuleRecord);

View File

@@ -65,6 +65,11 @@ class LoadedScript : public nsIMemoryReporter {
LoadedScript(ScriptKind aKind, mozilla::dom::ReferrerPolicy aReferrerPolicy,
ScriptFetchOptions* aFetchOptions, nsIURI* aURI);
LoadedScript(const LoadedScript& aOther);
template <typename T, typename... Args>
friend RefPtr<T> mozilla::MakeRefPtr(Args&&... aArgs);
virtual ~LoadedScript();
public:
@@ -383,12 +388,14 @@ class EventScript final : public LoadedScript {
// A single module script. May be used to satisfy multiple load requests.
class ModuleScript final : public LoadedScript {
// Those fields are used only after instantiated, and they're reset to
// null and false when stored into the cache as LoadedScript instance.
JS::Heap<JSObject*> mModuleRecord;
JS::Heap<JS::Value> mParseError;
JS::Heap<JS::Value> mErrorToRethrow;
bool mForPreload;
bool mHadImportMap;
bool mDebuggerDataInitialized;
bool mForPreload = false;
bool mHadImportMap = false;
bool mDebuggerDataInitialized = false;
~ModuleScript();
@@ -402,9 +409,19 @@ class ModuleScript final : public LoadedScript {
ModuleScript(mozilla::dom::ReferrerPolicy aReferrerPolicy,
ScriptFetchOptions* aFetchOptions, nsIURI* aURI);
explicit ModuleScript(const LoadedScript& other);
template <typename T, typename... Args>
friend RefPtr<T> mozilla::MakeRefPtr(Args&&... aArgs);
friend class ScriptLoadRequest;
public:
// Convert between cacheable LoadedScript instance, which is used by
// mozilla::dom::SharedScriptCache.
static already_AddRefed<ModuleScript> FromCache(const LoadedScript& aScript);
already_AddRefed<LoadedScript> ToCache();
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
void SetParseError(const JS::Value& aError);
void SetErrorToRethrow(const JS::Value& aError);