зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1690111 - Use new TypedArray APIs for creating a container with a copy of the data. r=necko-reviewers,farre,kershaw
Depends on D152496 Differential Revision: https://phabricator.services.mozilla.com/D152497
This commit is contained in:
Родитель
869651c1fc
Коммит
c49b5c3f78
|
@ -21,18 +21,21 @@
|
|||
|
||||
namespace mozilla::dom {
|
||||
|
||||
static nsresult GetBufferDataAsStream(
|
||||
const uint8_t* aData, uint32_t aDataLength, nsIInputStream** aResult,
|
||||
uint64_t* aContentLength, nsACString& aContentType, nsACString& aCharset) {
|
||||
static nsresult GetBufferDataAsStream(Vector<uint8_t>&& aData,
|
||||
nsIInputStream** aResult,
|
||||
uint64_t* aContentLength,
|
||||
nsACString& aContentType,
|
||||
nsACString& aCharset) {
|
||||
aContentType.SetIsVoid(true);
|
||||
aCharset.Truncate();
|
||||
|
||||
*aContentLength = aDataLength;
|
||||
const char* data = reinterpret_cast<const char*>(aData);
|
||||
*aContentLength = aData.length();
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = NS_NewByteInputStream(
|
||||
getter_AddRefs(stream), Span(data, aDataLength), NS_ASSIGNMENT_COPY);
|
||||
getter_AddRefs(stream),
|
||||
AsChars(Span(aData.extractOrCopyRawBuffer(), *aContentLength)),
|
||||
NS_ASSIGNMENT_ADOPT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
stream.forget(aResult);
|
||||
|
@ -44,20 +47,24 @@ template <>
|
|||
nsresult BodyExtractor<const ArrayBuffer>::GetAsStream(
|
||||
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||
nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
|
||||
mBody->ComputeState();
|
||||
return GetBufferDataAsStream(mBody->Data(), mBody->Length(), aResult,
|
||||
aContentLength, aContentTypeWithCharset,
|
||||
aCharset);
|
||||
Maybe<Vector<uint8_t>> body = mBody->CreateFromData<Vector<uint8_t>>();
|
||||
if (body.isNothing()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return GetBufferDataAsStream(body.extract(), aResult, aContentLength,
|
||||
aContentTypeWithCharset, aCharset);
|
||||
}
|
||||
|
||||
template <>
|
||||
nsresult BodyExtractor<const ArrayBufferView>::GetAsStream(
|
||||
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||
nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
|
||||
mBody->ComputeState();
|
||||
return GetBufferDataAsStream(mBody->Data(), mBody->Length(), aResult,
|
||||
aContentLength, aContentTypeWithCharset,
|
||||
aCharset);
|
||||
Maybe<Vector<uint8_t>> body = mBody->CreateFromData<Vector<uint8_t>>();
|
||||
if (body.isNothing()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return GetBufferDataAsStream(body.extract(), aResult, aContentLength,
|
||||
aContentTypeWithCharset, aCharset);
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
|
@ -30,6 +30,13 @@ nsresult BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength) {
|
|||
return AppendBlobImpl(blobImpl);
|
||||
}
|
||||
|
||||
nsresult BlobSet::AppendVector(Vector<uint8_t>&& aData) {
|
||||
size_t length = aData.length();
|
||||
RefPtr<BlobImpl> blobImpl =
|
||||
new MemoryBlobImpl(aData.extractOrCopyRawBuffer(), length, u""_ns);
|
||||
return AppendBlobImpl(blobImpl);
|
||||
}
|
||||
|
||||
nsresult BlobSet::AppendUTF8String(const nsACString& aUTF8String,
|
||||
bool nativeEOL) {
|
||||
nsCString utf8Str;
|
||||
|
|
|
@ -20,6 +20,8 @@ class BlobSet final {
|
|||
public:
|
||||
[[nodiscard]] nsresult AppendVoidPtr(const void* aData, uint32_t aLength);
|
||||
|
||||
[[nodiscard]] nsresult AppendVector(Vector<uint8_t>&& aData);
|
||||
|
||||
[[nodiscard]] nsresult AppendUTF8String(const nsACString& aUTF8String,
|
||||
bool nativeEOL);
|
||||
|
||||
|
|
|
@ -210,26 +210,22 @@ void MultipartBlobImpl::InitializeBlob(const Sequence<Blob::BlobPart>& aData,
|
|||
}
|
||||
}
|
||||
|
||||
else if (data.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = data.GetAsArrayBuffer();
|
||||
buffer.ComputeState();
|
||||
aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if (data.IsArrayBufferView()) {
|
||||
const ArrayBufferView& buffer = data.GetAsArrayBufferView();
|
||||
buffer.ComputeState();
|
||||
aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
MOZ_CRASH("Impossible blob data type.");
|
||||
auto blobData = CreateFromTypedArrayData<Vector<uint8_t>>(data);
|
||||
if (blobData.isNothing()) {
|
||||
MOZ_CRASH("Impossible blob data type.");
|
||||
}
|
||||
|
||||
if (!blobData.ref()) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = blobSet.AppendVector(blobData.ref().extract());
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -841,23 +841,18 @@ RefPtr<Int64Promise> FileSystemWritableFileStream::Write(
|
|||
|
||||
// https://fs.spec.whatwg.org/#write-a-chunk
|
||||
// Step 3.4.6 If data is a BufferSource, let dataBytes be a copy of data.
|
||||
if (aData.IsArrayBuffer() || aData.IsArrayBufferView()) {
|
||||
const auto dataSpan = [&aData]() -> mozilla::Span<uint8_t> {
|
||||
if (aData.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = aData.GetAsArrayBuffer();
|
||||
buffer.ComputeState();
|
||||
return Span{buffer.Data(), buffer.Length()};
|
||||
}
|
||||
|
||||
const ArrayBufferView& buffer = aData.GetAsArrayBufferView();
|
||||
buffer.ComputeState();
|
||||
return Span{buffer.Data(), buffer.Length()};
|
||||
}();
|
||||
auto vectorFromTypedArray = CreateFromTypedArrayData<Vector<uint8_t>>(aData);
|
||||
if (vectorFromTypedArray.isSome()) {
|
||||
Maybe<Vector<uint8_t>>& maybeVector = vectorFromTypedArray.ref();
|
||||
QM_TRY(MOZ_TO_RESULT(maybeVector.isSome()), CreateAndRejectInt64Promise);
|
||||
|
||||
// Here we copy
|
||||
QM_TRY(MOZ_TO_RESULT(NS_NewByteInputStream(getter_AddRefs(inputStream),
|
||||
AsChars(dataSpan),
|
||||
NS_ASSIGNMENT_COPY)),
|
||||
|
||||
size_t length = maybeVector->length();
|
||||
QM_TRY(MOZ_TO_RESULT(NS_NewByteInputStream(
|
||||
getter_AddRefs(inputStream),
|
||||
AsChars(Span(maybeVector->extractOrCopyRawBuffer(), length)),
|
||||
NS_ASSIGNMENT_ADOPT)),
|
||||
CreateAndRejectInt64Promise);
|
||||
|
||||
return WriteImpl(mTaskQueue, std::move(inputStream), mStreamOwner,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/EncodedVideoChunk.h"
|
||||
#include <utility>
|
||||
#include "mozilla/dom/EncodedVideoChunkBinding.h"
|
||||
|
||||
#include "MediaData.h"
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Buffer.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
|
|
@ -828,13 +828,16 @@ bool TCPSocket::Send(const ArrayBuffer& aData, uint32_t aByteOffset,
|
|||
|
||||
mSocketBridgeChild->SendSend(std::move(arrayBuffer));
|
||||
} else {
|
||||
aData.ComputeState();
|
||||
calculateOffsetAndCount(aData.Length());
|
||||
|
||||
JS::Rooted<JS::Value> value(RootingCx(), JS::ObjectValue(*aData.Obj()));
|
||||
mozilla::Maybe<mozilla::UniquePtr<uint8_t[]>> arrayBuffer =
|
||||
aData.CreateFromData<mozilla::UniquePtr<uint8_t[]>>(
|
||||
calculateOffsetAndCount);
|
||||
if (arrayBuffer.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = do_CreateInstance("@mozilla.org/io/arraybuffer-input-stream;1");
|
||||
nsresult rv = stream->SetData(value, aByteOffset, nbytes);
|
||||
nsresult rv = stream->SetData(arrayBuffer.extract(), nbytes);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return false;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "ErrorList.h"
|
||||
#include "TypedArray.h"
|
||||
#include "js/ArrayBuffer.h"
|
||||
#include "js/ColumnNumber.h" // JS::ColumnNumberZeroOrigin
|
||||
#include "js/JSON.h"
|
||||
|
@ -526,9 +527,7 @@ already_AddRefed<Promise> IOUtils::Write(GlobalObject& aGlobal,
|
|||
nsCOMPtr<nsIFile> file = new nsLocalFile();
|
||||
REJECT_IF_INIT_PATH_FAILED(file, aPath, promise);
|
||||
|
||||
aData.ComputeState();
|
||||
auto buf =
|
||||
Buffer<uint8_t>::CopyFrom(Span(aData.Data(), aData.Length()));
|
||||
Maybe<Buffer<uint8_t>> buf = aData.CreateFromData<Buffer<uint8_t>>();
|
||||
if (buf.isNothing()) {
|
||||
promise->MaybeRejectWithOperationError(
|
||||
"Out of memory: Could not allocate buffer while writing to file");
|
||||
|
@ -543,7 +542,7 @@ already_AddRefed<Promise> IOUtils::Write(GlobalObject& aGlobal,
|
|||
|
||||
DispatchAndResolve<uint32_t>(
|
||||
state->mEventQueue, promise,
|
||||
[file = std::move(file), buf = std::move(*buf),
|
||||
[file = std::move(file), buf = buf.extract(),
|
||||
opts = opts.unwrap()]() { return WriteSync(file, buf, opts); });
|
||||
});
|
||||
}
|
||||
|
|
|
@ -279,19 +279,8 @@ already_AddRefed<Promise> OutgoingDatagramStreamAlgorithms::WriteCallback(
|
|||
// Step 3: Let datagrams be transport.[[Datagrams]].
|
||||
// (mDatagrams is transport.[[Datagrams]])
|
||||
|
||||
// This is a duplicate of dom/encoding/TextDecoderStream.cpp#51-69
|
||||
// PeterV will deal with that when he lands his patch for TypedArrays
|
||||
auto data = [&arrayBuffer]() {
|
||||
if (arrayBuffer.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = arrayBuffer.GetAsArrayBuffer();
|
||||
buffer.ComputeState();
|
||||
return Span{buffer.Data(), buffer.Length()};
|
||||
}
|
||||
MOZ_ASSERT(arrayBuffer.IsArrayBufferView());
|
||||
const ArrayBufferView& buffer = arrayBuffer.GetAsArrayBufferView();
|
||||
buffer.ComputeState();
|
||||
return Span{buffer.Data(), buffer.Length()};
|
||||
}();
|
||||
nsTArray<uint8_t> data;
|
||||
Unused << AppendTypedArrayDataTo(arrayBuffer, data);
|
||||
|
||||
// Step 4: If datagrams.[[OutgoingMaxDatagramSize]] is less than data’s
|
||||
// [[ByteLength]], return a promise resolved with undefined.
|
||||
|
@ -309,10 +298,9 @@ already_AddRefed<Promise> OutgoingDatagramStreamAlgorithms::WriteCallback(
|
|||
// We pass along the datagram to the parent immediately.
|
||||
// The OutgoingDatagramsQueue lives there, and steps 6-9 generally are
|
||||
// implemented there
|
||||
nsTArray<uint8_t> array(data);
|
||||
LOG(("Sending Datagram, size = %zu", array.Length()));
|
||||
LOG(("Sending Datagram, size = %zu", data.Length()));
|
||||
mChild->SendOutgoingDatagram(
|
||||
array, now,
|
||||
std::move(data), now,
|
||||
[promise](nsresult&&) {
|
||||
// XXX result
|
||||
LOG(("Datagram was sent"));
|
||||
|
@ -331,7 +319,7 @@ already_AddRefed<Promise> OutgoingDatagramStreamAlgorithms::WriteCallback(
|
|||
// We should be guaranteed that we don't get called again until the
|
||||
// promise is resolved.
|
||||
MOZ_ASSERT(mWaitConnect == nullptr);
|
||||
mWaitConnect.reset(new DatagramEntry(data, now));
|
||||
mWaitConnect.reset(new DatagramEntry(std::move(data), now));
|
||||
mWaitConnectPromise = promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,16 +32,16 @@ template <typename T>
|
|||
static void GetDataFrom(const T& aObject, uint8_t*& aBuffer,
|
||||
uint32_t& aLength) {
|
||||
MOZ_ASSERT(!aBuffer);
|
||||
aObject.ComputeState();
|
||||
// We use malloc here rather than a FallibleTArray or fallible
|
||||
// operator new[] since the gfxUserFontEntry will be calling free
|
||||
// on it.
|
||||
aBuffer = (uint8_t*)malloc(aObject.Length());
|
||||
if (!aBuffer) {
|
||||
// We need to use malloc here because the gfxUserFontEntry will be calling
|
||||
// free on it, so the Vector's default AllocPolicy (MallocAllocPolicy) is
|
||||
// fine.
|
||||
Maybe<Vector<uint8_t>> buffer =
|
||||
aObject.template CreateFromData<Vector<uint8_t>>();
|
||||
if (buffer.isNothing()) {
|
||||
return;
|
||||
}
|
||||
memcpy((void*)aBuffer, aObject.Data(), aObject.Length());
|
||||
aLength = aObject.Length();
|
||||
aLength = buffer->length();
|
||||
aBuffer = buffer->extractOrCopyRawBuffer();
|
||||
}
|
||||
|
||||
// -- FontFace ---------------------------------------------------------------
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "js/ArrayBuffer.h" // JS::{GetArrayBuffer{ByteLength,Data},IsArrayBufferObject}
|
||||
#include "js/RootingAPI.h" // JS::{Handle,Rooted}
|
||||
#include "js/Value.h" // JS::Value
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
|
@ -18,8 +19,8 @@ NS_IMPL_ISUPPORTS(ArrayBufferInputStream, nsIArrayBufferInputStream,
|
|||
nsIInputStream);
|
||||
|
||||
NS_IMETHODIMP
|
||||
ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
|
||||
uint64_t aByteOffset, uint64_t aLength) {
|
||||
ArrayBufferInputStream::SetDataFromJS(JS::Handle<JS::Value> aBuffer,
|
||||
uint64_t aByteOffset, uint64_t aLength) {
|
||||
NS_ASSERT_OWNINGTHREAD(ArrayBufferInputStream);
|
||||
|
||||
if (!aBuffer.isObject()) {
|
||||
|
@ -39,7 +40,7 @@ ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mArrayBuffer = mozilla::MakeUniqueFallible<char[]>(bufferLength);
|
||||
mArrayBuffer = mozilla::MakeUniqueFallible<uint8_t[]>(bufferLength);
|
||||
if (!mArrayBuffer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -48,12 +49,18 @@ ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
|
|||
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
bool isShared;
|
||||
char* src =
|
||||
(char*)JS::GetArrayBufferData(arrayBuffer, &isShared, nogc) + offset;
|
||||
uint8_t* src = JS::GetArrayBufferData(arrayBuffer, &isShared, nogc) + offset;
|
||||
memcpy(&mArrayBuffer[0], src, mBufferLength);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult ArrayBufferInputStream::SetData(mozilla::UniquePtr<uint8_t[]> aBytes,
|
||||
uint64_t aByteLen) {
|
||||
mArrayBuffer = std::move(aBytes);
|
||||
mBufferLength = aByteLen;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ArrayBufferInputStream::Close() {
|
||||
mClosed = true;
|
||||
|
@ -108,8 +115,8 @@ ArrayBufferInputStream::ReadSegments(nsWriteSegmentFun writer, void* closure,
|
|||
}
|
||||
|
||||
uint32_t written;
|
||||
nsresult rv = writer(this, closure, &mArrayBuffer[0] + mPos, *result, count,
|
||||
&written);
|
||||
nsresult rv = writer(this, closure, (char*)&mArrayBuffer[0] + mPos, *result,
|
||||
count, &written);
|
||||
if (NS_FAILED(rv)) {
|
||||
// InputStreams do not propagate errors to caller.
|
||||
return NS_OK;
|
||||
|
|
|
@ -31,7 +31,7 @@ class ArrayBufferInputStream : public nsIArrayBufferInputStream {
|
|||
|
||||
private:
|
||||
virtual ~ArrayBufferInputStream() = default;
|
||||
mozilla::UniquePtr<char[]> mArrayBuffer;
|
||||
mozilla::UniquePtr<uint8_t[]> mArrayBuffer;
|
||||
uint32_t mBufferLength{0};
|
||||
uint32_t mPos{0};
|
||||
bool mClosed{false};
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
#include "nsIInputStream.idl"
|
||||
|
||||
%{C++
|
||||
#include "mozilla/UniquePtr.h"
|
||||
%}
|
||||
native Bytes(mozilla::UniquePtr<uint8_t[]>);
|
||||
|
||||
/**
|
||||
* nsIArrayBufferInputStream
|
||||
*
|
||||
|
@ -21,5 +26,15 @@ interface nsIArrayBufferInputStream : nsIInputStream
|
|||
* @param byteOffset - stream data offset
|
||||
* @param byteLen - stream data length
|
||||
*/
|
||||
[binaryname(SetDataFromJS)]
|
||||
void setData(in jsval buffer, in uint64_t byteOffset, in uint64_t byteLen);
|
||||
|
||||
/**
|
||||
* SetData - assign data to the input stream.
|
||||
*
|
||||
* @param aBytes - stream data
|
||||
* @param byteLen - stream data length
|
||||
*/
|
||||
[noscript, nostdcall, binaryname(SetData)]
|
||||
void setDataNative(in Bytes bytes, in uint64_t byteLen);
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче