Files
tubestation/dom/encoding/TextDecoder.cpp
Cosmin Sabou c3effd7450 Backed out 13 changesets (bug 1690111) for causing fetch related crashes.
Backed out changeset 5f2c25d194ad (bug 1690111)
Backed out changeset 76c408bcd053 (bug 1690111)
Backed out changeset 6d0649fdafff (bug 1690111)
Backed out changeset c1330b5e8c43 (bug 1690111)
Backed out changeset 5fa36d8fd2a5 (bug 1690111)
Backed out changeset daf7d747853a (bug 1690111)
Backed out changeset f70e09a7f5c6 (bug 1690111)
Backed out changeset 40c6d6eed7f8 (bug 1690111)
Backed out changeset 692f2a759573 (bug 1690111)
Backed out changeset 7140866dd9f6 (bug 1690111)
Backed out changeset 2865fe682139 (bug 1690111)
Backed out changeset 9dcd2416f8a5 (bug 1690111)
Backed out changeset 9c411bf84079 (bug 1690111)
2023-09-11 17:55:24 +03:00

129 lines
4.2 KiB
C++

/* -*- 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/. */
#include "mozilla/dom/TextDecoder.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/Encoding.h"
#include "mozilla/UniquePtrExtensions.h"
#include "nsContentUtils.h"
#include <stdint.h>
namespace mozilla::dom {
void TextDecoder::Init(const nsAString& aLabel,
const TextDecoderOptions& aOptions, ErrorResult& aRv) {
// Let encoding be the result of getting an encoding from label.
// If encoding is failure or replacement, throw a RangeError
// (https://encoding.spec.whatwg.org/#dom-textdecoder).
const Encoding* encoding = Encoding::ForLabelNoReplacement(aLabel);
if (!encoding) {
NS_ConvertUTF16toUTF8 label(aLabel);
label.Trim(" \t\n\f\r");
aRv.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(label);
return;
}
InitWithEncoding(WrapNotNull(encoding), aOptions);
}
void TextDecoder::InitWithEncoding(NotNull<const Encoding*> aEncoding,
const TextDecoderOptions& aOptions) {
aEncoding->Name(mEncoding);
// Store the flags passed via our options dictionary.
mFatal = aOptions.mFatal;
mIgnoreBOM = aOptions.mIgnoreBOM;
// Create a decoder object for mEncoding.
if (mIgnoreBOM) {
mDecoder = aEncoding->NewDecoderWithoutBOMHandling();
} else {
mDecoder = aEncoding->NewDecoderWithBOMRemoval();
}
}
void TextDecoderCommon::DecodeNative(Span<const uint8_t> aInput,
const bool aStream,
nsAString& aOutDecodedString,
ErrorResult& aRv) {
aOutDecodedString.Truncate();
CheckedInt<nsAString::size_type> needed =
mDecoder->MaxUTF16BufferLength(aInput.Length());
if (!needed.isValid()) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
auto output = aOutDecodedString.GetMutableData(needed.value(), fallible);
if (!output) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
uint32_t result;
size_t read;
size_t written;
if (mFatal) {
std::tie(result, read, written) =
mDecoder->DecodeToUTF16WithoutReplacement(aInput, *output, !aStream);
if (result != kInputEmpty) {
aRv.ThrowTypeError<MSG_DOM_DECODING_FAILED>();
return;
}
} else {
std::tie(result, read, written, std::ignore) =
mDecoder->DecodeToUTF16(aInput, *output, !aStream);
}
MOZ_ASSERT(result == kInputEmpty);
MOZ_ASSERT(read == aInput.Length());
MOZ_ASSERT(written <= aOutDecodedString.Length());
if (!aOutDecodedString.SetLength(written, fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
// If the internal streaming flag of the decoder object is not set,
// then reset the encoding algorithm state to the default values
if (!aStream) {
if (mIgnoreBOM) {
mDecoder->Encoding()->NewDecoderWithoutBOMHandlingInto(*mDecoder);
} else {
mDecoder->Encoding()->NewDecoderWithBOMRemovalInto(*mDecoder);
}
}
}
void TextDecoder::Decode(const Optional<ArrayBufferViewOrArrayBuffer>& aBuffer,
const TextDecodeOptions& aOptions,
nsAString& aOutDecodedString, ErrorResult& aRv) {
if (!aBuffer.WasPassed()) {
DecodeNative(nullptr, aOptions.mStream, aOutDecodedString, aRv);
return;
}
const ArrayBufferViewOrArrayBuffer& buf = aBuffer.Value();
uint8_t* data;
uint32_t length;
if (buf.IsArrayBufferView()) {
buf.GetAsArrayBufferView().ComputeState();
data = buf.GetAsArrayBufferView().Data();
length = buf.GetAsArrayBufferView().Length();
} else {
MOZ_ASSERT(buf.IsArrayBuffer());
buf.GetAsArrayBuffer().ComputeState();
data = buf.GetAsArrayBuffer().Data();
length = buf.GetAsArrayBuffer().Length();
}
DecodeNative(Span(data, length), aOptions.mStream, aOutDecodedString, aRv);
}
void TextDecoderCommon::GetEncoding(nsAString& aEncoding) {
CopyASCIItoUTF16(mEncoding, aEncoding);
nsContentUtils::ASCIIToLower(aEncoding);
}
} // namespace mozilla::dom