Bug 1444956 - Support BinAST decoding in the script loader r=baku

This commit is contained in:
Jon Coppeard
2018-05-16 15:58:13 +01:00
parent ae847b0148
commit d4094b6b99
25 changed files with 1479 additions and 68 deletions

View File

@@ -9,6 +9,9 @@
#include "ScriptTrace.h"
#include "nsContentUtils.h"
#include "nsIEncodedChannel.h"
#include "nsIStringEnumerator.h"
#include "nsMimeTypes.h"
#include "mozilla/Telemetry.h"
@@ -59,7 +62,7 @@ ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
NS_ENSURE_SUCCESS(rv, rv);
}
if (mRequest->IsSource()) {
if (mRequest->IsTextSource()) {
if (!EnsureDecoder(aLoader, aData, aDataLength,
/* aEndOfStream = */ false)) {
return NS_OK;
@@ -72,6 +75,18 @@ ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
rv = DecodeRawData(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 if (mRequest->IsBinASTSource()) {
if (!mRequest->ScriptBinASTData().append(aData, aDataLength)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Below we will/shall consume entire data chunk.
*aConsumedLength = aDataLength;
// If SRI is required for this load, appending new bytes to the hash.
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
@@ -104,12 +119,12 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t haveRead = mRequest->mScriptText.length();
uint32_t haveRead = mRequest->ScriptText().length();
CheckedInt<uint32_t> capacity = haveRead;
capacity += needed.value();
if (!capacity.isValid() || !mRequest->mScriptText.reserve(capacity.value())) {
if (!capacity.isValid() || !mRequest->ScriptText().reserve(capacity.value())) {
return NS_ERROR_OUT_OF_MEMORY;
}
@@ -119,7 +134,7 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
bool hadErrors;
Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
MakeSpan(aData, aDataLength),
MakeSpan(mRequest->mScriptText.begin() + haveRead, needed.value()),
MakeSpan(mRequest->ScriptText().begin() + haveRead, needed.value()),
aEndOfStream);
MOZ_ASSERT(result == kInputEmpty);
MOZ_ASSERT(read == aDataLength);
@@ -128,7 +143,7 @@ ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
haveRead += written;
MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
MOZ_ALWAYS_TRUE(mRequest->mScriptText.resizeUninitialized(haveRead));
MOZ_ALWAYS_TRUE(mRequest->ScriptText().resizeUninitialized(haveRead));
return NS_OK;
}
@@ -273,33 +288,52 @@ ScriptLoadHandler::EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader)
{
MOZ_ASSERT(mRequest->IsUnknownDataType());
MOZ_ASSERT(mRequest->IsLoading());
if (mRequest->IsLoadingSource()) {
mRequest->mDataType = ScriptLoadRequest::DataType::eSource;
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
return NS_OK;
}
nsCOMPtr<nsIRequest> req;
nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
MOZ_ASSERT(req, "StreamLoader's request went away prematurely");
NS_ENSURE_SUCCESS(rv, rv);
if (ScriptLoader::BinASTEncodingEnabled()) {
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(req);
if (httpChannel) {
nsAutoCString mimeType;
httpChannel->GetContentType(mimeType);
if (mimeType.LowerCaseEqualsASCII(APPLICATION_JAVASCRIPT_BINAST)) {
if (mRequest->ShouldAcceptBinASTEncoding()) {
mRequest->SetBinASTSource();
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
}
}
if (mRequest->IsLoadingSource()) {
mRequest->SetTextSource();
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
return NS_OK;
}
nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(req));
if (cic) {
nsAutoCString altDataType;
cic->GetAlternativeDataType(altDataType);
if (altDataType.Equals(nsContentUtils::JSBytecodeMimeType())) {
mRequest->mDataType = ScriptLoadRequest::DataType::eBytecode;
mRequest->SetBytecode();
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_bytecode");
} else {
MOZ_ASSERT(altDataType.IsEmpty());
mRequest->mDataType = ScriptLoadRequest::DataType::eSource;
mRequest->SetTextSource();
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
}
} else {
mRequest->mDataType = ScriptLoadRequest::DataType::eSource;
mRequest->SetTextSource();
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
}
MOZ_ASSERT(!mRequest->IsUnknownDataType());
MOZ_ASSERT(mRequest->IsLoading());
return NS_OK;
@@ -329,7 +363,7 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
NS_ENSURE_SUCCESS(rv, rv);
}
if (mRequest->IsSource()) {
if (mRequest->IsTextSource()) {
DebugOnly<bool> encoderSet =
EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
MOZ_ASSERT(encoderSet);
@@ -337,7 +371,16 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
NS_ENSURE_SUCCESS(rv, rv);
LOG(("ScriptLoadRequest (%p): Source length = %u",
mRequest.get(), unsigned(mRequest->mScriptText.length())));
mRequest.get(), unsigned(mRequest->ScriptText().length())));
// If SRI is required for this load, appending new bytes to the hash.
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
}
} else if (mRequest->IsBinASTSource()) {
if (!mRequest->ScriptBinASTData().append(aData, aDataLength)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// If SRI is required for this load, appending new bytes to the hash.
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {