Bug 1690111 - Use new TypedArray APIs for appending data to a container. r=farre,extension-reviewers,media-playback-reviewers,kmag,alwu,padenot

Depends on D152494

Differential Revision: https://phabricator.services.mozilla.com/D152495
This commit is contained in:
Peter Van der Beken
2023-09-20 09:42:01 +00:00
parent 61f5ba150b
commit 2ba4663c86
20 changed files with 102 additions and 227 deletions

View File

@@ -172,17 +172,26 @@ void nsDOMDataChannel::Close() {
// All of the following is copy/pasted from WebSocket.cpp.
void nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv) {
if (!CheckReadyState(aRv)) {
return;
}
nsAutoCString msgString;
if (!AppendUTF16toUTF8(aData, msgString, mozilla::fallible_t())) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
return;
}
Send(nullptr, &msgString, false, aRv);
mDataChannel->SendMsg(msgString, aRv);
}
void nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!CheckReadyState(aRv)) {
return;
}
nsCOMPtr<nsIInputStream> msgStream;
aData.CreateInputStream(getter_AddRefs(msgStream), aRv);
if (NS_WARN_IF(aRv.Failed())) {
@@ -199,50 +208,42 @@ void nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv) {
return;
}
Send(&aData, nullptr, true, aRv);
mDataChannel->SendBinaryBlob(aData, aRv);
}
void nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
aData.ComputeState();
if (!CheckReadyState(aRv)) {
return;
}
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString;
if (!msgString.Assign(data, len, mozilla::fallible_t())) {
nsCString msgString;
if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
return;
}
Send(nullptr, &msgString, true, aRv);
mDataChannel->SendBinaryMsg(msgString, aRv);
}
void nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
aData.ComputeState();
if (!CheckReadyState(aRv)) {
return;
}
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString;
if (!msgString.Assign(data, len, mozilla::fallible_t())) {
nsCString msgString;
if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
return;
}
Send(nullptr, &msgString, true, aRv);
mDataChannel->SendBinaryMsg(msgString, aRv);
}
void nsDOMDataChannel::Send(mozilla::dom::Blob* aMsgBlob,
const nsACString* aMsgString, bool aIsBinary,
mozilla::ErrorResult& aRv) {
bool nsDOMDataChannel::CheckReadyState(ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
uint16_t state = mozilla::DataChannel::CLOSED;
if (!mSentClose) {
@@ -253,26 +254,18 @@ void nsDOMDataChannel::Send(mozilla::dom::Blob* aMsgBlob,
// look like WebSockets
if (state == mozilla::DataChannel::CONNECTING) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
return false;
}
if (state == mozilla::DataChannel::CLOSING ||
state == mozilla::DataChannel::CLOSED) {
return;
return false;
}
MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
"Unknown state in nsDOMDataChannel::Send");
if (aMsgBlob) {
mDataChannel->SendBinaryBlob(*aMsgBlob, aRv);
} else {
if (aIsBinary) {
mDataChannel->SendBinaryMsg(*aMsgString, aRv);
} else {
mDataChannel->SendMsg(*aMsgString, aRv);
}
}
return true;
}
nsresult nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,

View File

@@ -108,8 +108,7 @@ class nsDOMDataChannel final : public mozilla::DOMEventTargetHelper,
~nsDOMDataChannel();
private:
void Send(mozilla::dom::Blob* aMsgBlob, const nsACString* aMsgString,
bool aIsBinary, mozilla::ErrorResult& aRv);
bool CheckReadyState(mozilla::ErrorResult& aRv);
void ReleaseSelf();

View File

@@ -38,46 +38,30 @@ uint8_t* CryptoBuffer::Assign(const nsTArray<uint8_t>& aData) {
}
uint8_t* CryptoBuffer::Assign(const ArrayBuffer& aData) {
aData.ComputeState();
return Assign(aData.Data(), aData.Length());
Clear();
return aData.AppendDataTo(*this) ? Elements() : nullptr;
}
uint8_t* CryptoBuffer::Assign(const ArrayBufferView& aData) {
aData.ComputeState();
return Assign(aData.Data(), aData.Length());
Clear();
return aData.AppendDataTo(*this) ? Elements() : nullptr;
}
uint8_t* CryptoBuffer::Assign(const ArrayBufferViewOrArrayBuffer& aData) {
if (aData.IsArrayBufferView()) {
return Assign(aData.GetAsArrayBufferView());
}
if (aData.IsArrayBuffer()) {
return Assign(aData.GetAsArrayBuffer());
}
// If your union is uninitialized, something's wrong
MOZ_ASSERT(false);
Clear();
return nullptr;
return AppendTypedArrayDataTo(aData, *this) ? Elements() : nullptr;
}
uint8_t* CryptoBuffer::Assign(const OwningArrayBufferViewOrArrayBuffer& aData) {
if (aData.IsArrayBufferView()) {
return Assign(aData.GetAsArrayBufferView());
}
if (aData.IsArrayBuffer()) {
return Assign(aData.GetAsArrayBuffer());
}
// If your union is uninitialized, something's wrong
MOZ_ASSERT(false);
Clear();
return nullptr;
return AppendTypedArrayDataTo(aData, *this) ? Elements() : nullptr;
}
uint8_t* CryptoBuffer::Assign(const Uint8Array& aArray) {
aArray.ComputeState();
return Assign(aArray.Data(), aArray.Length());
Clear();
return aArray.AppendDataTo(*this) ? Elements() : nullptr;
}
uint8_t* CryptoBuffer::AppendSECItem(const SECItem* aItem) {

View File

@@ -325,7 +325,6 @@ void FetchStreamReader::ChunkSteps(JSContext* aCx, JS::Handle<JS::Value> aChunk,
CloseAndRelease(aCx, NS_ERROR_DOM_WRONG_TYPE_ERR);
return;
}
chunk.ComputeState();
MOZ_DIAGNOSTIC_ASSERT(mBuffer.IsEmpty());
@@ -333,13 +332,13 @@ void FetchStreamReader::ChunkSteps(JSContext* aCx, JS::Handle<JS::Value> aChunk,
// FIXME: We could sometimes avoid this copy by trying to write `chunk`
// directly into `mPipeOut` eagerly, and only filling `mBuffer` if there isn't
// enough space in the pipe's buffer.
if (!mBuffer.AppendElements(chunk.Data(), chunk.Length(), fallible)) {
if (!chunk.AppendDataTo(mBuffer)) {
CloseAndRelease(aCx, NS_ERROR_OUT_OF_MEMORY);
return;
}
mBufferOffset = 0;
mBufferRemaining = chunk.Length();
mBufferRemaining = mBuffer.Length();
nsresult rv = WriteBuffer();
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@@ -44,13 +44,8 @@ ArrayData GetArrayBufferViewOrArrayBufferData(
void CopyArrayBufferViewOrArrayBufferData(
const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView,
nsTArray<uint8_t>& aOutData) {
JS::AutoCheckCannotGC nogc;
ArrayData data = GetArrayBufferViewOrArrayBufferData(aBufferOrView);
aOutData.Clear();
if (!data.IsValid()) {
return;
}
aOutData.AppendElements(data.mData, data.mLength);
Unused << dom::AppendTypedArrayDataTo(aBufferOrView, aOutData);
}
bool IsClearkeyKeySystem(const nsAString& aKeySystem) {

View File

@@ -330,17 +330,12 @@ void WaveShaperNode::SetCurve(const Nullable<Float32Array>& aCurve,
return;
}
const Float32Array& floats = aCurve.Value();
floats.ComputeState();
nsTArray<float> curve;
uint32_t argLength = floats.Length();
if (!curve.SetLength(argLength, fallible)) {
if (!aCurve.Value().AppendDataTo(curve)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
PodCopy(curve.Elements(), floats.Data(), argLength);
SetCurveInternal(curve, aRv);
}

View File

@@ -233,15 +233,9 @@ static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(MIMECreateParam aParam) {
static Result<RefPtr<MediaByteBuffer>, nsresult> GetExtraData(
const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer) {
RefPtr<MediaByteBuffer> data = nullptr;
Span<uint8_t> buf;
MOZ_TRY_VAR(buf, GetSharedArrayBufferData(aBuffer));
if (buf.empty()) {
return data;
}
data = MakeRefPtr<MediaByteBuffer>();
data->AppendElements(buf);
return data;
RefPtr<MediaByteBuffer> data = MakeRefPtr<MediaByteBuffer>();
Unused << AppendTypedArrayDataTo(aBuffer, *data);
return data->Length() > 0 ? data : nullptr;
}
static Result<UniquePtr<TrackInfo>, nsresult> CreateVideoInfo(

View File

@@ -73,9 +73,6 @@ Nullable<T> MaybeToNullable(const Maybe<T>& aOptional) {
* Below are helpers to operate ArrayBuffer or ArrayBufferView.
*/
template <class T>
Result<Span<uint8_t>, nsresult> GetArrayBufferData(const T& aBuffer);
Result<Span<uint8_t>, nsresult> GetSharedArrayBufferData(
const MaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer);

View File

@@ -811,27 +811,36 @@ bool TCPSocket::Send(const ArrayBuffer& aData, uint32_t aByteOffset,
nsCOMPtr<nsIArrayBufferInputStream> stream;
aData.ComputeState();
uint32_t byteLength =
aByteLength.WasPassed() ? aByteLength.Value() : aData.Length();
uint32_t nbytes;
auto calculateOffsetAndCount = [&](uint32_t aLength) {
uint32_t offset = std::min(aLength, aByteOffset);
nbytes = std::min(aLength - aByteOffset,
aByteLength.WasPassed() ? aByteLength.Value() : aLength);
return std::pair(offset, nbytes);
};
if (mSocketBridgeChild) {
nsresult rv = mSocketBridgeChild->SendSend(aData, aByteOffset, byteLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
nsTArray<uint8_t> arrayBuffer;
if (!aData.AppendDataTo(arrayBuffer, calculateOffsetAndCount)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return false;
}
mSocketBridgeChild->SendSend(std::move(arrayBuffer));
} else {
aData.ComputeState();
calculateOffsetAndCount(aData.Length());
JS::Rooted<JS::Value> value(RootingCx(), JS::ObjectValue(*aData.Obj()));
stream = do_CreateInstance("@mozilla.org/io/arraybuffer-input-stream;1");
nsresult rv = stream->SetData(value, aByteOffset, byteLength);
nsresult rv = stream->SetData(value, aByteOffset, nbytes);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return false;
}
}
return Send(stream, byteLength);
return Send(stream, nbytes);
}
bool TCPSocket::Send(nsIInputStream* aStream, uint32_t aByteLength) {

View File

@@ -145,19 +145,8 @@ void TCPSocketChild::SendSend(const nsACString& aData) {
SendData(nsCString(aData));
}
nsresult TCPSocketChild::SendSend(const ArrayBuffer& aData,
uint32_t aByteOffset, uint32_t aByteLength) {
uint32_t buflen = aData.Length();
uint32_t offset = std::min(buflen, aByteOffset);
uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
FallibleTArray<uint8_t> fallibleArr;
if (!fallibleArr.InsertElementsAt(0, aData.Data() + offset, nbytes,
fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
SendData(SendableData{std::move(fallibleArr)});
return NS_OK;
void TCPSocketChild::SendSend(nsTArray<uint8_t>&& aData) {
SendData(SendableData{std::move(aData)});
}
void TCPSocketChild::SetSocket(TCPSocket* aSocket) { mSocket = aSocket; }

View File

@@ -52,8 +52,7 @@ class TCPSocketChild : public mozilla::net::PTCPSocketChild,
void SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL,
bool aUseArrayBuffers);
void SendSend(const nsACString& aData);
nsresult SendSend(const ArrayBuffer& aData, uint32_t aByteOffset,
uint32_t aByteLength);
void SendSend(nsTArray<uint8_t>&& aData);
void SetSocket(TCPSocket* aSocket);
void GetHost(nsAString& aHost);

View File

@@ -341,16 +341,14 @@ bool UDPSocket::Send(const StringOrBlobOrArrayBufferOrArrayBufferView& aData,
if (aData.IsString()) {
NS_ConvertUTF16toUTF8 data(aData.GetAsString());
aRv = strStream->SetData(data.BeginReading(), data.Length());
} else if (aData.IsArrayBuffer()) {
const ArrayBuffer& data = aData.GetAsArrayBuffer();
data.ComputeState();
aRv = strStream->SetData(reinterpret_cast<const char*>(data.Data()),
data.Length());
} else {
const ArrayBufferView& data = aData.GetAsArrayBufferView();
data.ComputeState();
aRv = strStream->SetData(reinterpret_cast<const char*>(data.Data()),
data.Length());
Vector<char> data;
if (!AppendTypedArrayDataTo(aData, data)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return false;
}
size_t length = data.length();
aRv = strStream->AdoptData(data.extractOrCopyRawBuffer(), length);
}
if (NS_WARN_IF(aRv.Failed())) {

View File

@@ -522,18 +522,10 @@ nsresult PushManager::NormalizeAppServerKey(
return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
}
aAppServerKey = decodedKey;
} else if (aSource.IsArrayBuffer()) {
if (!PushUtil::CopyArrayBufferToArray(aSource.GetAsArrayBuffer(),
aAppServerKey)) {
return NS_ERROR_DOM_PUSH_INVALID_KEY_ERR;
}
} else if (aSource.IsArrayBufferView()) {
if (!PushUtil::CopyArrayBufferViewToArray(aSource.GetAsArrayBufferView(),
aAppServerKey)) {
return NS_ERROR_DOM_PUSH_INVALID_KEY_ERR;
}
} else {
MOZ_CRASH("Uninitialized union: expected string, buffer, or view");
if (!AppendTypedArrayDataTo(aSource, aAppServerKey)) {
return NS_ERROR_DOM_PUSH_INVALID_KEY_ERR;
}
}
if (aAppServerKey.IsEmpty()) {
return NS_ERROR_DOM_PUSH_INVALID_KEY_ERR;

View File

@@ -228,8 +228,7 @@ already_AddRefed<PushSubscription> PushSubscription::Constructor(
nsTArray<uint8_t> rawKey;
if (aInitDict.mP256dhKey.WasPassed() &&
!aInitDict.mP256dhKey.Value().IsNull() &&
!PushUtil::CopyArrayBufferToArray(aInitDict.mP256dhKey.Value().Value(),
rawKey)) {
!aInitDict.mP256dhKey.Value().Value().AppendDataTo(rawKey)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
@@ -237,8 +236,7 @@ already_AddRefed<PushSubscription> PushSubscription::Constructor(
nsTArray<uint8_t> authSecret;
if (aInitDict.mAuthSecret.WasPassed() &&
!aInitDict.mAuthSecret.Value().IsNull() &&
!PushUtil::CopyArrayBufferToArray(aInitDict.mAuthSecret.Value().Value(),
authSecret)) {
!aInitDict.mAuthSecret.Value().Value().AppendDataTo(authSecret)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}

View File

@@ -9,35 +9,12 @@
namespace mozilla::dom {
/* static */
bool PushUtil::CopyArrayBufferToArray(const ArrayBuffer& aBuffer,
nsTArray<uint8_t>& aArray) {
MOZ_ASSERT(aArray.IsEmpty());
aBuffer.ComputeState();
return aArray.SetCapacity(aBuffer.Length(), fallible) &&
aArray.InsertElementsAt(0, aBuffer.Data(), aBuffer.Length(), fallible);
}
/* static */
bool PushUtil::CopyArrayBufferViewToArray(const ArrayBufferView& aView,
nsTArray<uint8_t>& aArray) {
MOZ_ASSERT(aArray.IsEmpty());
aView.ComputeState();
return aArray.SetCapacity(aView.Length(), fallible) &&
aArray.InsertElementsAt(0, aView.Data(), aView.Length(), fallible);
}
/* static */
bool PushUtil::CopyBufferSourceToArray(
const OwningArrayBufferViewOrArrayBuffer& aSource,
nsTArray<uint8_t>& aArray) {
if (aSource.IsArrayBuffer()) {
return CopyArrayBufferToArray(aSource.GetAsArrayBuffer(), aArray);
}
if (aSource.IsArrayBufferView()) {
return CopyArrayBufferViewToArray(aSource.GetAsArrayBufferView(), aArray);
}
MOZ_CRASH("Uninitialized union: expected buffer or view");
MOZ_ASSERT(aArray.IsEmpty());
return AppendTypedArrayDataTo(aSource, aArray);
}
/* static */

View File

@@ -23,12 +23,6 @@ class PushUtil final {
PushUtil() = delete;
public:
static bool CopyArrayBufferToArray(const ArrayBuffer& aBuffer,
nsTArray<uint8_t>& aArray);
static bool CopyArrayBufferViewToArray(const ArrayBufferView& aView,
nsTArray<uint8_t>& aArray);
static bool CopyBufferSourceToArray(
const OwningArrayBufferViewOrArrayBuffer& aSource,
nsTArray<uint8_t>& aArray);

View File

@@ -1030,19 +1030,10 @@ nsresult ExtractBytesFromUSVString(const nsAString& aStr,
nsresult ExtractBytesFromData(
const OwningArrayBufferViewOrArrayBufferOrUSVString& aDataInit,
nsTArray<uint8_t>& aBytes) {
if (aDataInit.IsArrayBufferView()) {
const ArrayBufferView& view = aDataInit.GetAsArrayBufferView();
if (NS_WARN_IF(!PushUtil::CopyArrayBufferViewToArray(view, aBytes))) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
if (aDataInit.IsArrayBuffer()) {
const ArrayBuffer& buffer = aDataInit.GetAsArrayBuffer();
if (NS_WARN_IF(!PushUtil::CopyArrayBufferToArray(buffer, aBytes))) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
MOZ_ASSERT(aBytes.IsEmpty());
Maybe<bool> result = AppendTypedArrayDataTo(aDataInit, aBytes);
if (result.isSome()) {
return NS_WARN_IF(!result.value()) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
}
if (aDataInit.IsUSVString()) {
return ExtractBytesFromUSVString(aDataInit.GetAsUSVString(), aBytes);

View File

@@ -1033,10 +1033,9 @@ already_AddRefed<Promise> IOUtils::SetMacXAttr(GlobalObject& aGlobal,
nsCOMPtr<nsIFile> file = new nsLocalFile();
REJECT_IF_INIT_PATH_FAILED(file, aPath, promise);
aValue.ComputeState();
nsTArray<uint8_t> value;
if (!value.AppendElements(aValue.Data(), aValue.Length(), fallible)) {
if (!aValue.AppendDataTo(value)) {
RejectJSPromise(
promise,
IOError(NS_ERROR_OUT_OF_MEMORY)
@@ -2834,10 +2833,9 @@ static nsCString FromUnixString(const IOUtils::UnixString& aString) {
return aString.GetAsUTF8String();
}
if (aString.IsUint8Array()) {
const auto& u8a = aString.GetAsUint8Array();
u8a.ComputeState();
// Cast to deal with char signedness
return nsCString(reinterpret_cast<const char*>(u8a.Data()), u8a.Length());
nsCString data;
Unused << aString.GetAsUint8Array().AppendDataTo(data);
return data;
}
MOZ_CRASH("unreachable");
}

View File

@@ -2388,37 +2388,31 @@ void WebSocket::Send(Blob& aData, ErrorResult& aRv) {
void WebSocket::Send(const ArrayBuffer& aData, ErrorResult& aRv) {
AssertIsOnTargetThread();
aData.ComputeState();
static_assert(
sizeof(std::remove_reference<decltype(aData)>::type::element_type) == 1,
"byte-sized data required");
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString;
if (!msgString.Assign(data, len, mozilla::fallible_t())) {
nsCString msgString;
if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
return;
}
Send(nullptr, msgString, len, true, aRv);
Send(nullptr, msgString, msgString.Length(), true, aRv);
}
void WebSocket::Send(const ArrayBufferView& aData, ErrorResult& aRv) {
AssertIsOnTargetThread();
aData.ComputeState();
static_assert(
sizeof(std::remove_reference<decltype(aData)>::type::element_type) == 1,
"byte-sized data required");
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
uint32_t len = aData.Length();
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString;
if (!msgString.Assign(data, len, mozilla::fallible_t())) {
nsCString msgString;
if (!aData.AppendDataTo(msgString)) {
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
return;
}
Send(nullptr, msgString, len, true, aRv);
Send(nullptr, msgString, msgString.Length(), true, aRv);
}
void WebSocket::Send(nsIInputStream* aMsgStream, const nsACString& aMsgString,

View File

@@ -123,18 +123,6 @@ bool StreamFilter::CheckAlive() {
* Binding methods
*****************************************************************************/
template <typename T>
static inline bool ReadTypedArrayData(nsTArray<uint8_t>& aData, const T& aArray,
ErrorResult& aRv) {
aArray.ComputeState();
if (!aData.SetLength(aArray.Length(), fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return false;
}
memcpy(aData.Elements(), aArray.Data(), aArray.Length());
return true;
}
void StreamFilter::Write(const ArrayBufferOrUint8Array& aData,
ErrorResult& aRv) {
if (!mActor) {
@@ -143,20 +131,12 @@ void StreamFilter::Write(const ArrayBufferOrUint8Array& aData,
}
nsTArray<uint8_t> data;
bool ok;
if (aData.IsArrayBuffer()) {
ok = ReadTypedArrayData(data, aData.GetAsArrayBuffer(), aRv);
} else if (aData.IsUint8Array()) {
ok = ReadTypedArrayData(data, aData.GetAsUint8Array(), aRv);
} else {
MOZ_ASSERT_UNREACHABLE("Argument should be ArrayBuffer or Uint8Array");
if (!AppendTypedArrayDataTo(aData, data)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
if (ok) {
mActor->Write(std::move(data), aRv);
}
mActor->Write(std::move(data), aRv);
}
StreamFilterStatus StreamFilter::Status() const {