diff --git a/js/loader/LoadedScript.cpp b/js/loader/LoadedScript.cpp index 0702884f6a16..151973b77732 100644 --- a/js/loader/LoadedScript.cpp +++ b/js/loader/LoadedScript.cpp @@ -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::FromCache( + const LoadedScript& aScript) { + MOZ_DIAGNOSTIC_ASSERT(aScript.IsModuleScript()); + MOZ_DIAGNOSTIC_ASSERT(aScript.IsStencil()); + + return mozilla::MakeRefPtr(aScript).forget(); +} + +already_AddRefed ModuleScript::ToCache() { + MOZ_DIAGNOSTIC_ASSERT(IsStencil()); + MOZ_DIAGNOSTIC_ASSERT(!HasParseError()); + MOZ_DIAGNOSTIC_ASSERT(!HasErrorToRethrow()); + + return mozilla::MakeRefPtr(*this).forget(); +} + void ModuleScript::Shutdown() { if (mModuleRecord) { JS::ClearModuleEnvironment(mModuleRecord); diff --git a/js/loader/LoadedScript.h b/js/loader/LoadedScript.h index f768a523501e..fa57bdf20f28 100644 --- a/js/loader/LoadedScript.h +++ b/js/loader/LoadedScript.h @@ -65,6 +65,11 @@ class LoadedScript : public nsIMemoryReporter { LoadedScript(ScriptKind aKind, mozilla::dom::ReferrerPolicy aReferrerPolicy, ScriptFetchOptions* aFetchOptions, nsIURI* aURI); + LoadedScript(const LoadedScript& aOther); + + template + friend RefPtr 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 mModuleRecord; JS::Heap mParseError; JS::Heap 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 + friend RefPtr mozilla::MakeRefPtr(Args&&... aArgs); + friend class ScriptLoadRequest; public: + // Convert between cacheable LoadedScript instance, which is used by + // mozilla::dom::SharedScriptCache. + static already_AddRefed FromCache(const LoadedScript& aScript); + already_AddRefed ToCache(); + void SetModuleRecord(JS::Handle aModuleRecord); void SetParseError(const JS::Value& aError); void SetErrorToRethrow(const JS::Value& aError);