1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ArrayBufferInputStream.h"
8 #include "nsStreamUtils.h"
9 #include "js/ArrayBuffer.h" // JS::{GetArrayBuffer{ByteLength,Data},IsArrayBufferObject}
10 #include "js/RootingAPI.h" // JS::{Handle,Rooted}
11 #include "js/Value.h" // JS::Value
12 #include "mozilla/Span.h"
13 #include "mozilla/UniquePtrExtensions.h"
14 #include "mozilla/dom/ScriptSettings.h"
16 using mozilla::dom::RootingCx
;
18 NS_IMPL_ISUPPORTS(ArrayBufferInputStream
, nsIArrayBufferInputStream
,
22 ArrayBufferInputStream::SetDataFromJS(JS::Handle
<JS::Value
> aBuffer
,
23 uint64_t aByteOffset
, uint64_t aLength
) {
24 NS_ASSERT_OWNINGTHREAD(ArrayBufferInputStream
);
26 if (!aBuffer
.isObject()) {
27 return NS_ERROR_FAILURE
;
29 JS::Rooted
<JSObject
*> arrayBuffer(RootingCx(), &aBuffer
.toObject());
30 if (!JS::IsArrayBufferObject(arrayBuffer
)) {
31 return NS_ERROR_FAILURE
;
34 uint64_t buflen
= JS::GetArrayBufferByteLength(arrayBuffer
);
35 uint64_t offset
= std::min(buflen
, aByteOffset
);
36 uint64_t bufferLength
= std::min(buflen
- offset
, aLength
);
38 // Prevent truncation.
39 if (bufferLength
> UINT32_MAX
) {
40 return NS_ERROR_INVALID_ARG
;
43 mArrayBuffer
= mozilla::MakeUniqueFallible
<uint8_t[]>(bufferLength
);
45 return NS_ERROR_OUT_OF_MEMORY
;
48 mBufferLength
= bufferLength
;
50 JS::AutoCheckCannotGC nogc
;
52 uint8_t* src
= JS::GetArrayBufferData(arrayBuffer
, &isShared
, nogc
) + offset
;
53 memcpy(&mArrayBuffer
[0], src
, mBufferLength
);
57 nsresult
ArrayBufferInputStream::SetData(mozilla::UniquePtr
<uint8_t[]> aBytes
,
59 mArrayBuffer
= std::move(aBytes
);
60 mBufferLength
= aByteLen
;
65 ArrayBufferInputStream::Close() {
71 ArrayBufferInputStream::Available(uint64_t* aCount
) {
73 return NS_BASE_STREAM_CLOSED
;
76 *aCount
= mBufferLength
? mBufferLength
- mPos
: 0;
84 ArrayBufferInputStream::StreamStatus() {
85 return mClosed
? NS_BASE_STREAM_CLOSED
: NS_OK
;
89 ArrayBufferInputStream::Read(char* aBuf
, uint32_t aCount
,
90 uint32_t* aReadCount
) {
91 return ReadSegments(NS_CopySegmentToBuffer
, aBuf
, aCount
, aReadCount
);
95 ArrayBufferInputStream::ReadSegments(nsWriteSegmentFun writer
, void* closure
,
96 uint32_t aCount
, uint32_t* result
) {
97 NS_ASSERTION(result
, "null ptr");
98 NS_ASSERTION(mBufferLength
>= mPos
, "bad stream state");
101 return NS_BASE_STREAM_CLOSED
;
104 MOZ_ASSERT(mArrayBuffer
|| (mPos
== mBufferLength
),
105 "stream inited incorrectly");
108 while (mPos
< mBufferLength
) {
109 uint32_t remaining
= mBufferLength
- mPos
;
110 MOZ_ASSERT(mArrayBuffer
);
112 uint32_t count
= std::min(aCount
, remaining
);
118 nsresult rv
= writer(this, closure
, (char*)&mArrayBuffer
[0] + mPos
, *result
,
121 // InputStreams do not propagate errors to caller.
125 NS_ASSERTION(written
<= count
,
126 "writer should not write more than we asked it to write");
136 ArrayBufferInputStream::IsNonBlocking(bool* aNonBlocking
) {
137 *aNonBlocking
= true;