/* -*- 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/. */
// Reference to the script source buffer which we will update.
JS::loader::ScriptLoadRequest::ScriptTextBuffer<Unit>& scriptText =
aRequest->ScriptText<Unit>();
haveRead += written;
MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
MOZ_ALWAYS_TRUE(scriptText.resize(haveRead));
aRequest->SetReceivedScriptTextLength(scriptText.length());
if (mRequest->IsBytecode() && firstTime) {
PerfStats::RecordMeasurementStart(PerfStats::Metric::JSBC_IO_Read);
}
if (mRequest->IsTextSource()) { if (!EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ false)) { return NS_OK;
}
// Below we will/shall consume entire data chunk.
*aConsumedLength = aDataLength;
// Decoder has already been initialized. -- trying to decode all loaded // bytes.
rv = mDecoder->DecodeRawData(mRequest, aData, aDataLength, /* aEndOfStream = */ false);
NS_ENSURE_SUCCESS(rv, rv);
// If SRI is required for this load, appending new bytes to the hash. if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
}
} else {
MOZ_ASSERT(mRequest->IsBytecode()); if (!mRequest->SRIAndBytecode().append(aData, aDataLength)) { return NS_ERROR_OUT_OF_MEMORY;
}
bool ScriptLoadHandler::TrySetDecoder(nsIIncrementalStreamLoader* aLoader, const uint8_t* aData,
uint32_t aDataLength, bool aEndOfStream) {
MOZ_ASSERT(mDecoder == nullptr, "can't have a decoder already if we're trying to set one");
// JavaScript modules are always UTF-8. if (mRequest->IsModuleRequest()) {
mDecoder = MakeUnique<ScriptDecoder>(UTF_8_ENCODING,
ScriptDecoder::BOMHandling::Remove); returntrue;
}
// Determine if BOM check should be done. This occurs either // if end-of-stream has been reached, or at least 3 bytes have // been read from input. if (!aEndOfStream && (aDataLength < 3)) { returnfalse;
}
if (channel) {
nsAutoCString label; if (NS_SUCCEEDED(channel->GetContentCharset(label)) &&
(encoding = Encoding::ForLabel(label))) {
mDecoder = MakeUnique<ScriptDecoder>(encoding,
ScriptDecoder::BOMHandling::Ignore); returntrue;
}
}
// Check the hint charset from the script element or preload // request.
nsAutoString hintCharset; if (!mRequest->GetScriptLoadContext()->IsPreload()) {
mRequest->GetScriptLoadContext()->GetHintCharset(hintCharset);
} else {
nsTArray<ScriptLoader::PreloadInfo>::index_type i =
mScriptLoader->mPreloads.IndexOf(
mRequest, 0, ScriptLoader::PreloadRequestComparator());
// Get the charset from the charset of the document. if (mScriptLoader->mDocument) {
encoding = mScriptLoader->mDocument->GetDocumentCharacterSet();
mDecoder =
MakeUnique<ScriptDecoder>(encoding, ScriptDecoder::BOMHandling::Ignore); returntrue;
}
// Curiously, there are various callers that don't pass aDocument. The // fallback in the old code was ISO-8859-1, which behaved like // windows-1252.
mDecoder = MakeUnique<ScriptDecoder>(WINDOWS_1252_ENCODING,
ScriptDecoder::BOMHandling::Ignore); returntrue;
}
if (!mSRIDataVerifier || mSRIDataVerifier->IsComplete() ||
NS_FAILED(mSRIStatus)) { return NS_OK;
}
// Skip until the content is large enough to be decoded.
JS::TranscodeBuffer& receivedData = mRequest->SRIAndBytecode(); if (receivedData.length() <= mSRIDataVerifier->DataSummaryLength()) { return NS_OK;
}
if (NS_FAILED(mSRIStatus)) { // We are unable to decode the hash contained in the alternate data which // contains the bytecode, or it does not use the same algorithm.
LOG(
("ScriptLoadHandler::MaybeDecodeSRI, failed to decode SRI, restart " "request")); return mSRIStatus;
}
auto firstMessage = !mPreloadStartNotified; if (!mPreloadStartNotified) {
mPreloadStartNotified = true;
mRequest->GetScriptLoadContext()->NotifyStart(channelRequest);
}
auto notifyStop = MakeScopeExit([&] {
mRequest->GetScriptLoadContext()->NotifyStop(channelRequest, rv);
});
if (!mRequest->IsCanceled()) { if (mRequest->IsUnknownDataType()) {
rv = EnsureKnownDataType(aLoader);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mRequest->IsBytecode() && !firstMessage) { // if firstMessage, then entire stream is in aData, and PerfStats would // measure 0 time
PerfStats::RecordMeasurementEnd(PerfStats::Metric::JSBC_IO_Read);
}
LOG(("ScriptLoadRequest (%p): Source length in code units = %u",
mRequest.get(), unsigned(mRequest->ScriptTextLength())));
// If SRI is required for this load, appending new bytes to the hash. if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
}
} else {
MOZ_ASSERT(mRequest->IsBytecode());
JS::TranscodeBuffer& bytecode = mRequest->SRIAndBytecode(); if (!bytecode.append(aData, aDataLength)) { return NS_ERROR_OUT_OF_MEMORY;
}
// If we abort while decoding the SRI, we fallback on explicitly // requesting the source. Thus, we should not continue in // ScriptLoader::OnStreamComplete, which removes the request from the // waiting lists. // // We calculate the SRI length below.
uint32_t unused;
rv = MaybeDecodeSRI(&unused); if (NS_FAILED(rv)) { return channelRequest->Cancel(mScriptLoader->RestartLoad(mRequest));
}
// The bytecode cache always starts with the SRI hash, thus even if there // is no SRI data verifier instance, we still want to skip the hash.
uint32_t sriLength;
rv = SRICheckDataVerifier::DataSummaryLength(
bytecode.length(), bytecode.begin(), &sriLength); if (NS_FAILED(rv)) { return channelRequest->Cancel(mScriptLoader->RestartLoad(mRequest));
}
mRequest->SetSRILength(sriLength);
Vector<uint8_t> compressedBytecode; // mRequest has the compressed bytecode, but will be filled with the // uncompressed bytecode
compressedBytecode.swap(bytecode); if (!JS::loader::ScriptBytecodeDecompress(
compressedBytecode, mRequest->GetSRILength(), bytecode)) { return NS_ERROR_UNEXPECTED;
}
}
}
// Everything went well, keep the CacheInfoChannel alive such that we can // later save the bytecode on the cache entry. if (NS_SUCCEEDED(rv) && mRequest->IsSource() &&
StaticPrefs::dom_script_loader_bytecode_cache_enabled()) {
mRequest->mCacheInfo = do_QueryInterface(channelRequest);
LOG(("ScriptLoadRequest (%p): nsICacheInfoChannel = %p", mRequest.get(),
mRequest->mCacheInfo.get()));
}
// we have to mediate and use mRequest.
rv = mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus,
mSRIDataVerifier.get());
// In case of failure, clear the mCacheInfoChannel to avoid keeping it alive. if (NS_FAILED(rv)) {
mRequest->mCacheInfo = nullptr;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.