tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit dee0f66355afa91c2540e289c946141e20e79ecd
parent 58730279e1f1346b898e5c95c301e237e188d49d
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Wed, 26 Nov 2025 04:10:51 +0000

Bug 1907011 - Part 2: Split LoadedScript::SRIAndBytecode into LoadedScript::SRI and LoadedScript::SRIAndSerializedStencil for each cosnumer. r=nbp

Differential Revision: https://phabricator.services.mozilla.com/D273955

Diffstat:
Mdom/script/ScriptLoadHandler.cpp | 6+++---
Mdom/script/ScriptLoader.cpp | 51+++++++++++++++++++++++++++------------------------
Mdom/script/SharedScriptCache.cpp | 2+-
Mjs/loader/LoadedScript.h | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
4 files changed, 87 insertions(+), 50 deletions(-)

diff --git a/dom/script/ScriptLoadHandler.cpp b/dom/script/ScriptLoadHandler.cpp @@ -190,7 +190,7 @@ ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader, } } else { MOZ_ASSERT(mRequest->IsSerializedStencil()); - if (!mRequest->SRIAndBytecode().append(aData, aDataLength)) { + if (!mRequest->SRIAndSerializedStencil().append(aData, aDataLength)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -301,7 +301,7 @@ nsresult ScriptLoadHandler::MaybeDecodeSRI(uint32_t* sriLength) { } // Skip until the content is large enough to be decoded. - JS::TranscodeBuffer& receivedData = mRequest->SRIAndBytecode(); + JS::TranscodeBuffer& receivedData = mRequest->SRIAndSerializedStencil(); if (receivedData.length() <= mSRIDataVerifier->DataSummaryLength()) { return NS_OK; } @@ -422,7 +422,7 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader, } } else { MOZ_ASSERT(mRequest->IsSerializedStencil()); - JS::TranscodeBuffer& bytecode = mRequest->SRIAndBytecode(); + JS::TranscodeBuffer& bytecode = mRequest->SRIAndSerializedStencil(); if (!bytecode.append(aData, aDataLength)) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp @@ -2757,7 +2757,7 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference()); // NOTE: An inline script tag can have an SRI, but we don't calculate it // for this case. - MOZ_ASSERT(aRequest->SRIAndBytecode().empty()); + MOZ_ASSERT(aRequest->HasNoSRIOrSRIAndSerializedStencil()); return; } @@ -2769,7 +2769,7 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { // have to be cached. aRequest->MarkNotCacheable(); MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference()); - MOZ_ASSERT(aRequest->SRIAndBytecode().empty()); + MOZ_ASSERT(aRequest->HasNoSRIOrSRIAndSerializedStencil()); return; } @@ -2779,7 +2779,8 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { aRequest)); aRequest->MarkNotCacheable(); MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference()); - MOZ_ASSERT_IF(aRequest->IsSource(), aRequest->SRIAndBytecode().empty()); + MOZ_ASSERT_IF(aRequest->IsSource(), + aRequest->HasNoSRIOrSRIAndSerializedStencil()); return; } @@ -2824,7 +2825,8 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { "!LoadedScript::HasDiskCacheReference", aRequest)); aRequest->MarkSkippedDiskCaching(); - MOZ_ASSERT_IF(aRequest->IsSource(), aRequest->SRIAndBytecode().empty()); + MOZ_ASSERT_IF(aRequest->IsSource(), + aRequest->HasNoSRIOrSRIAndSerializedStencil()); return; } @@ -3418,9 +3420,8 @@ nsresult ScriptLoader::MaybePrepareForDiskCacheAfterExecute( // // NOTE: This assertion will fail once we start encoding more data after the // first encode. - MOZ_ASSERT_IF( - !aRequest->IsCachedStencil(), - aRequest->GetSRILength() == aRequest->SRIAndBytecode().length()); + MOZ_ASSERT_IF(!aRequest->IsCachedStencil(), + aRequest->GetSRILength() == aRequest->SRI().length()); RegisterForDiskCache(aRequest); return aRv; @@ -3664,7 +3665,7 @@ void ScriptLoader::UpdateDiskCache() { Vector<uint8_t> compressed; if (!EncodeAndCompress(fc, loadedScript, loadedScript->GetStencil(), - loadedScript->SRIAndBytecode(), compressed)) { + loadedScript->SRI(), compressed)) { loadedScript->DropDiskCacheReference(); loadedScript->DropBytecode(); TRACE_FOR_TEST(loadedScript, "diskcache:failed"); @@ -3695,13 +3696,14 @@ bool ScriptLoader::EncodeAndCompress( size_t SRILength = aSRI.length(); MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(SRILength)); - JS::TranscodeBuffer SRIAndBytecode; - if (!SRIAndBytecode.appendAll(aSRI)) { + JS::TranscodeBuffer SRIAndSerializedStencil; + if (!SRIAndSerializedStencil.appendAll(aSRI)) { LOG(("LoadedScript (%p): Cannot allocate buffer", aLoadedScript)); return false; } - JS::TranscodeResult result = JS::EncodeStencil(aFc, aStencil, SRIAndBytecode); + JS::TranscodeResult result = + JS::EncodeStencil(aFc, aStencil, SRIAndSerializedStencil); if (result != JS::TranscodeResult::Ok) { // Encoding can be aborted for non-supported syntax (e.g. asm.js), or @@ -3714,7 +3716,8 @@ bool ScriptLoader::EncodeAndCompress( } // TODO probably need to move this to a helper thread - if (!ScriptBytecodeCompress(SRIAndBytecode, SRILength, aCompressed)) { + if (!ScriptBytecodeCompress(SRIAndSerializedStencil, SRILength, + aCompressed)) { return false; } @@ -4208,54 +4211,54 @@ nsresult ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest, nsresult ScriptLoader::SaveSRIHash( ScriptLoadRequest* aRequest, SRICheckDataVerifier* aSRIDataVerifier) const { MOZ_ASSERT(aRequest->IsSource()); - JS::TranscodeBuffer& bytecode = aRequest->SRIAndBytecode(); - MOZ_ASSERT(bytecode.empty()); + JS::TranscodeBuffer& sri = aRequest->SRI(); + MOZ_ASSERT(sri.empty()); uint32_t len = 0; // If the integrity metadata does not correspond to a valid hash function, // IsComplete would be false. if (!aRequest->mIntegrity.IsEmpty() && aSRIDataVerifier->IsComplete()) { - MOZ_ASSERT(bytecode.length() == 0); + MOZ_ASSERT(sri.length() == 0); // Encode the SRI computed hash. len = aSRIDataVerifier->DataSummaryLength(); - if (!bytecode.resize(len)) { + if (!sri.resize(len)) { return NS_ERROR_OUT_OF_MEMORY; } DebugOnly<nsresult> res = - aSRIDataVerifier->ExportDataSummary(len, bytecode.begin()); + aSRIDataVerifier->ExportDataSummary(len, sri.begin()); MOZ_ASSERT(NS_SUCCEEDED(res)); } else { - MOZ_ASSERT(bytecode.length() == 0); + MOZ_ASSERT(sri.length() == 0); // Encode a dummy SRI hash. len = SRICheckDataVerifier::EmptyDataSummaryLength(); - if (!bytecode.resize(len)) { + if (!sri.resize(len)) { return NS_ERROR_OUT_OF_MEMORY; } DebugOnly<nsresult> res = - SRICheckDataVerifier::ExportEmptyDataSummary(len, bytecode.begin()); + SRICheckDataVerifier::ExportEmptyDataSummary(len, sri.begin()); MOZ_ASSERT(NS_SUCCEEDED(res)); } // Verify that the exported and predicted length correspond. DebugOnly<uint32_t> srilen{}; MOZ_ASSERT(NS_SUCCEEDED( - SRICheckDataVerifier::DataSummaryLength(len, bytecode.begin(), &srilen))); + SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen))); MOZ_ASSERT(srilen == len); - MOZ_ASSERT(bytecode.length() == len); + MOZ_ASSERT(sri.length() == len); aRequest->SetSRILength(len); if (aRequest->GetSRILength() != len) { - // The bytecode is aligned in the bytecode buffer, and space might be + // The serialized stencil is aligned in the buffer, and space might be // reserved for padding after the SRI hash. - if (!bytecode.resize(aRequest->GetSRILength())) { + if (!sri.resize(aRequest->GetSRILength())) { return NS_ERROR_OUT_OF_MEMORY; } } diff --git a/dom/script/SharedScriptCache.cpp b/dom/script/SharedScriptCache.cpp @@ -315,7 +315,7 @@ void SharedScriptCache::UpdateDiskCache() { } if (!mEncodeItems.emplaceBack(loadedScript->GetStencil(), - std::move(loadedScript->SRIAndBytecode()), + std::move(loadedScript->SRI()), loadedScript)) { continue; } diff --git a/js/loader/LoadedScript.h b/js/loader/LoadedScript.h @@ -144,6 +144,8 @@ class LoadedScript : public nsIMemoryReporter { using MaybeSourceText = mozilla::MaybeOneOf<SourceText<char16_t>, SourceText<Utf8Unit>>; + // ==== Methods to query the data type ==== + bool IsUnknownDataType() const { return mDataType == DataType::eUnknown; } bool IsTextSource() const { return mDataType == DataType::eTextSource; } bool IsSource() const { return IsTextSource(); } @@ -152,6 +154,8 @@ class LoadedScript : public nsIMemoryReporter { } bool IsCachedStencil() const { return mDataType == DataType::eCachedStencil; } + // ==== Methods to convert the data type ==== + void SetUnknownDataType() { mDataType = DataType::eUnknown; mScriptData.reset(); @@ -181,6 +185,8 @@ class LoadedScript : public nsIMemoryReporter { return mScriptData->is<ScriptTextBuffer<Utf8Unit>>(); } + // ==== Methods to access the text soutce ==== + template <typename Unit> const ScriptTextBuffer<Unit>& ScriptText() const { MOZ_ASSERT(IsTextSource()); @@ -221,49 +227,68 @@ class LoadedScript : public nsIMemoryReporter { mReceivedScriptTextLength = aLength; } - bool CanHaveBytecode() const { - return IsSerializedStencil() || IsSource() || IsCachedStencil(); + // ==== Methods to access the serialized data or the SRI part ==== + // mSRIAndBytecode field is shared between two separate consumers. + // See mSRIAndBytecode comment for more info. + + // ---- For SRI-only consumers ---- + + bool CanHaveSRIOnly() const { return IsSource() || IsCachedStencil(); } + + bool HasSRI() { + MOZ_ASSERT(CanHaveSRIOnly()); + return !mSRIAndBytecode.empty(); } - TranscodeBuffer& SRIAndBytecode() { - // Note: SRIAndBytecode might be called even if the IsSource() returns true, - // as we want to be able to save the bytecode content when we are loading - // from source. - MOZ_ASSERT(CanHaveBytecode()); + TranscodeBuffer& SRI() { + MOZ_ASSERT(CanHaveSRIOnly()); + return mSRIAndBytecode; + } + + void DropSRI() { + MOZ_ASSERT(CanHaveSRIOnly()); + mSRIAndBytecode.clearAndFree(); + } + + // ---- For SRI and serialized Stencil consumers --- + + bool CanHaveSRIAndSerializedStencil() const { return IsSerializedStencil(); } + + TranscodeBuffer& SRIAndSerializedStencil() { + MOZ_ASSERT(CanHaveSRIAndSerializedStencil()); return mSRIAndBytecode; } TranscodeRange Bytecode() const { - MOZ_ASSERT(IsSerializedStencil()); + MOZ_ASSERT(CanHaveSRIAndSerializedStencil()); const auto& bytecode = mSRIAndBytecode; auto offset = mBytecodeOffset; return TranscodeRange(bytecode.begin() + offset, bytecode.length() - offset); } + // ---- Methods shared between both consumers ---- + size_t GetSRILength() const { - MOZ_ASSERT(CanHaveBytecode()); + MOZ_ASSERT(CanHaveSRIOnly() || CanHaveSRIAndSerializedStencil()); return mBytecodeOffset; } void SetSRILength(size_t sriLength) { - MOZ_ASSERT(CanHaveBytecode()); + MOZ_ASSERT(CanHaveSRIOnly() || CanHaveSRIAndSerializedStencil()); mBytecodeOffset = AlignTranscodingBytecodeOffset(sriLength); } - void DropBytecode() { - MOZ_ASSERT(CanHaveBytecode()); - mSRIAndBytecode.clearAndFree(); - } - - bool HasSRI() { - MOZ_ASSERT(IsSource() || IsCachedStencil()); - return !mSRIAndBytecode.empty(); + bool HasNoSRIOrSRIAndSerializedStencil() const { + MOZ_ASSERT(CanHaveSRIOnly() || CanHaveSRIAndSerializedStencil()); + return mSRIAndBytecode.empty(); } - void DropSRI() { - MOZ_ASSERT(IsSource() || IsCachedStencil()); + void DropBytecode() { + MOZ_ASSERT(CanHaveSRIOnly() || CanHaveSRIAndSerializedStencil()); mSRIAndBytecode.clearAndFree(); } + // ==== Methods to access the stencil ==== + bool HasStencil() const { return mStencil; } Stencil* GetStencil() const { @@ -280,6 +305,8 @@ class LoadedScript : public nsIMemoryReporter { void ClearStencil() { mStencil = nullptr; } + // ==== Methods to access the disk cache reference ==== + // Check the reference to the cache info channel, which is used by the disk // cache. bool HasDiskCacheReference() const { return !!mCacheInfo; } @@ -294,6 +321,8 @@ class LoadedScript : public nsIMemoryReporter { } } + // ==== Other methods ==== + /* * Set the mBaseURL, based on aChannel. * aOriginalURI is the result of aChannel->GetOriginalURI. @@ -521,8 +550,13 @@ class LoadedScriptDelegate { void ClearScriptText() { GetLoadedScript()->ClearScriptText(); } - TranscodeBuffer& SRIAndBytecode() { - return GetLoadedScript()->SRIAndBytecode(); + bool HasNoSRIOrSRIAndSerializedStencil() const { + return GetLoadedScript()->HasNoSRIOrSRIAndSerializedStencil(); + } + + TranscodeBuffer& SRI() { return GetLoadedScript()->SRI(); } + TranscodeBuffer& SRIAndSerializedStencil() { + return GetLoadedScript()->SRIAndSerializedStencil(); } TranscodeRange Bytecode() const { return GetLoadedScript()->Bytecode(); }