diff --git a/dom/base/BodyConsumer.cpp b/dom/base/BodyConsumer.cpp index 6782fe36e50e..ca805df60bab 100644 --- a/dom/base/BodyConsumer.cpp +++ b/dom/base/BodyConsumer.cpp @@ -651,7 +651,7 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, AssertIsOnTargetThread(); // This makes sure that we free the data correctly. - auto autoFree = mozilla::MakeScopeExit([&] { free(aResult); }); + UniquePtr resultPtr{aResult}; if (mBodyConsumed) { return; @@ -689,7 +689,7 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, } // Finish successfully consuming body according to type. - MOZ_ASSERT(aResult); + MOZ_ASSERT(resultPtr); AutoJSAPI jsapi; if (!jsapi.Init(mGlobal)) { @@ -703,16 +703,14 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, switch (mConsumeType) { case CONSUME_ARRAYBUFFER: { JS::Rooted arrayBuffer(cx); - BodyUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, aResult, - error); + BodyUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, + std::move(resultPtr), error); if (!error.Failed()) { JS::Rooted val(cx); val.setObjectOrNull(arrayBuffer); localPromise->MaybeResolve(val); - // ArrayBuffer takes over ownership. - aResult = nullptr; } break; } @@ -722,8 +720,7 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, } case CONSUME_FORMDATA: { nsCString data; - data.Adopt(reinterpret_cast(aResult), aResultLength); - aResult = nullptr; + data.Adopt(reinterpret_cast(resultPtr.release()), aResultLength); RefPtr fd = BodyUtil::ConsumeFormData( mGlobal, mBodyMimeType, mMixedCaseMimeType, data, error); @@ -737,7 +734,7 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, case CONSUME_JSON: { nsString decoded; if (NS_SUCCEEDED( - BodyUtil::ConsumeText(aResultLength, aResult, decoded))) { + BodyUtil::ConsumeText(aResultLength, resultPtr.get(), decoded))) { if (mConsumeType == CONSUME_TEXT) { localPromise->MaybeResolve(decoded); } else { diff --git a/dom/base/BodyUtil.cpp b/dom/base/BodyUtil.cpp index 206fa52ebf39..6e9059e6904b 100644 --- a/dom/base/BodyUtil.cpp +++ b/dom/base/BodyUtil.cpp @@ -353,11 +353,13 @@ class MOZ_STACK_CLASS FormDataParser { // static void BodyUtil::ConsumeArrayBuffer(JSContext* aCx, JS::MutableHandle aValue, - uint32_t aInputLength, uint8_t* aInput, + uint32_t aInputLength, + UniquePtr aInput, ErrorResult& aRv) { + UniquePtr dataPtr{aInput.release()}; JS::Rooted arrayBuffer(aCx); - arrayBuffer = JS::NewArrayBufferWithContents(aCx, aInputLength, - reinterpret_cast(aInput)); + arrayBuffer = + JS::NewArrayBufferWithContents(aCx, aInputLength, std::move(dataPtr)); if (!arrayBuffer) { JS_ClearPendingException(aCx); aRv.Throw(NS_ERROR_OUT_OF_MEMORY); diff --git a/dom/base/BodyUtil.h b/dom/base/BodyUtil.h index b7b2ff94fdcb..6639b54729fe 100644 --- a/dom/base/BodyUtil.h +++ b/dom/base/BodyUtil.h @@ -13,6 +13,8 @@ #include "mozilla/dom/File.h" #include "mozilla/dom/FormData.h" +#include "js/Utility.h" // JS::FreePolicy + namespace mozilla { class ErrorResult; @@ -30,7 +32,8 @@ class BodyUtil final { */ static void ConsumeArrayBuffer(JSContext* aCx, JS::MutableHandle aValue, - uint32_t aInputLength, uint8_t* aInput, + uint32_t aInputLength, + UniquePtr aInput, ErrorResult& aRv); /** diff --git a/dom/base/CompressionStream.cpp b/dom/base/CompressionStream.cpp index b178869fdf10..74a6666289d2 100644 --- a/dom/base/CompressionStream.cpp +++ b/dom/base/CompressionStream.cpp @@ -108,7 +108,7 @@ class CompressionStreamAlgorithms : public TransformerAlgorithmsWrapper { do { static uint16_t kBufferSize = 16384; - UniquePtr buffer( + UniquePtr buffer( static_cast(JS_malloc(aCx, kBufferSize))); if (!buffer) { aRv.ThrowTypeError("Out of memory"); @@ -164,8 +164,8 @@ class CompressionStreamAlgorithms : public TransformerAlgorithmsWrapper { // into Uint8Arrays. // (The buffer is 'split' by having a fixed sized buffer above.) - JS::Rooted view( - aCx, nsJSUtils::MoveBufferAsUint8Array(aCx, written, buffer)); + JS::Rooted view(aCx, nsJSUtils::MoveBufferAsUint8Array( + aCx, written, std::move(buffer))); if (!view || !array.append(view)) { JS_ClearPendingException(aCx); aRv.ThrowTypeError("Out of memory"); diff --git a/dom/base/DecompressionStream.cpp b/dom/base/DecompressionStream.cpp index 54d72ee5f978..f2cdabebbf1b 100644 --- a/dom/base/DecompressionStream.cpp +++ b/dom/base/DecompressionStream.cpp @@ -107,7 +107,7 @@ class DecompressionStreamAlgorithms : public TransformerAlgorithmsWrapper { do { static uint16_t kBufferSize = 16384; - UniquePtr buffer( + UniquePtr buffer( static_cast(JS_malloc(aCx, kBufferSize))); if (!buffer) { aRv.ThrowTypeError("Out of memory"); @@ -194,8 +194,8 @@ class DecompressionStreamAlgorithms : public TransformerAlgorithmsWrapper { // into Uint8Arrays. // (The buffer is 'split' by having a fixed sized buffer above.) - JS::Rooted view( - aCx, nsJSUtils::MoveBufferAsUint8Array(aCx, written, buffer)); + JS::Rooted view(aCx, nsJSUtils::MoveBufferAsUint8Array( + aCx, written, std::move(buffer))); if (!view || !array.append(view)) { JS_ClearPendingException(aCx); aRv.ThrowTypeError("Out of memory"); diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 86fe04583c34..462c36269681 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -186,17 +186,16 @@ bool nsJSUtils::DumpEnabled() { #endif } -JSObject* nsJSUtils::MoveBufferAsUint8Array(JSContext* aCx, size_t aSize, - UniquePtr& aBuffer) { +JSObject* nsJSUtils::MoveBufferAsUint8Array( + JSContext* aCx, size_t aSize, + UniquePtr aBuffer) { + UniquePtr dataPtr{aBuffer.release()}; JS::Rooted arrayBuffer( - aCx, JS::NewArrayBufferWithContents(aCx, aSize, aBuffer.get())); + aCx, JS::NewArrayBufferWithContents(aCx, aSize, std::move(dataPtr))); if (!arrayBuffer) { return nullptr; } - // Now the ArrayBuffer owns the buffer, so let's release our ownership - (void)aBuffer.release(); - return JS_NewUint8ArrayWithBuffer(aCx, arrayBuffer, 0, static_cast(aSize)); } diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h index 67682173f45c..36e906061588 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h @@ -21,6 +21,7 @@ #include "js/Conversions.h" #include "js/SourceText.h" #include "js/String.h" // JS::{,Lossy}CopyLinearStringChars, JS::CopyStringChars, JS::Get{,Linear}StringLength, JS::MaxStringLength, JS::StringHasLatin1Chars +#include "js/Utility.h" // JS::FreePolicy #include "nsString.h" #include "xpcpublic.h" @@ -87,8 +88,9 @@ class nsJSUtils { // Note that the buffer needs to be created by JS_malloc (or at least can be // freed by JS_free), as the resulting Uint8Array takes the ownership of the // buffer. - static JSObject* MoveBufferAsUint8Array(JSContext* aCx, size_t aSize, - mozilla::UniquePtr& aBuffer); + static JSObject* MoveBufferAsUint8Array( + JSContext* aCx, size_t aSize, + mozilla::UniquePtr aBuffer); }; inline void AssignFromStringBuffer(nsStringBuffer* buffer, size_t len, diff --git a/dom/encoding/TextEncoderStream.cpp b/dom/encoding/TextEncoderStream.cpp index 06cd9d5a7e59..c9c9106b97d9 100644 --- a/dom/encoding/TextEncoderStream.cpp +++ b/dom/encoding/TextEncoderStream.cpp @@ -68,7 +68,7 @@ static void EncodeNative(JSContext* aCx, mozilla::Decoder* aDecoder, return; } - UniquePtr buffer( + UniquePtr buffer( static_cast(JS_malloc(aCx, needed.value()))); if (!buffer) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); @@ -98,8 +98,9 @@ static void EncodeNative(JSContext* aCx, mozilla::Decoder* aDecoder, // https://encoding.spec.whatwg.org/#encode-and-enqueue-a-chunk // Step 4.2.2.1. Let chunk be a Uint8Array object wrapping an ArrayBuffer // containing output. + UniquePtr dataPtr{buffer.release()}; JS::Rooted arrayBuffer( - aCx, JS::NewArrayBufferWithContents(aCx, written, buffer.release())); + aCx, JS::NewArrayBufferWithContents(aCx, written, std::move(dataPtr))); if (!arrayBuffer.get()) { JS_ClearPendingException(aCx); aRv.Throw(NS_ERROR_OUT_OF_MEMORY); diff --git a/dom/file/FileReaderSync.cpp b/dom/file/FileReaderSync.cpp index 59a925f439ed..5d9fb8b8f0ea 100644 --- a/dom/file/FileReaderSync.cpp +++ b/dom/file/FileReaderSync.cpp @@ -84,15 +84,13 @@ void FileReaderSync::ReadAsArrayBuffer(JSContext* aCx, return; } + UniquePtr dataPtr{bufferData.release()}; JSObject* arrayBuffer = - JS::NewArrayBufferWithContents(aCx, blobSize, bufferData.get()); + JS::NewArrayBufferWithContents(aCx, blobSize, std::move(dataPtr)); if (!arrayBuffer) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } - // arrayBuffer takes the ownership when it is not null. Otherwise we - // need to release it explicitly. - (void)bufferData.release(); aRetval.set(arrayBuffer); } diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp index 8b82e70e374b..6f96023a54ee 100644 --- a/dom/indexedDB/Key.cpp +++ b/dom/indexedDB/Key.cpp @@ -855,12 +855,19 @@ JSObject* Key::DecodeBinary(const EncodedDataType*& aPos, DecodeStringy( aPos, aEnd, [&rv, aCx](uint8_t** out, uint32_t decodedSize) { - *out = static_cast(JS_malloc(aCx, decodedSize)); - if (NS_WARN_IF(!*out)) { + UniquePtr ptr{JS_malloc(aCx, decodedSize)}; + if (NS_WARN_IF(!ptr)) { + *out = nullptr; rv = nullptr; return false; } - rv = JS::NewArrayBufferWithContents(aCx, decodedSize, *out); + + *out = static_cast(ptr.get()); + rv = JS::NewArrayBufferWithContents(aCx, decodedSize, std::move(ptr)); + if (NS_WARN_IF(!rv)) { + *out = nullptr; + return false; + } return true; }, [&rv, aCx] { rv = JS::NewArrayBuffer(aCx, 0); }); diff --git a/dom/indexedDB/test/gtest/TestKey.cpp b/dom/indexedDB/test/gtest/TestKey.cpp index 8de788a2fc8b..a981882a1af4 100644 --- a/dom/indexedDB/test/gtest/TestKey.cpp +++ b/dom/indexedDB/test/gtest/TestKey.cpp @@ -238,8 +238,9 @@ INSTANTIATE_TEST_SUITE_P(DOM_IndexedDB_Key, TestWithParam_LiteralString, static JS::Value CreateArrayBufferValue(JSContext* const aContext, const size_t aSize, char* const aData) { - Rooted arrayBuffer{ - aContext, JS::NewArrayBufferWithContents(aContext, aSize, aData)}; + mozilla::UniquePtr ptr{aData}; + Rooted arrayBuffer{aContext, JS::NewArrayBufferWithContents( + aContext, aSize, std::move(ptr))}; EXPECT_TRUE(arrayBuffer); return JS::ObjectValue(*arrayBuffer); } diff --git a/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp b/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp index 567b682b2a61..8538264bf9c1 100644 --- a/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp +++ b/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp @@ -2166,9 +2166,10 @@ void PeerConnectionImpl::DumpPacket_m(size_t level, dom::mozPacketDumpType type, return; } + UniquePtr packetPtr{packet.release()}; JS::Rooted jsobj( jsapi.cx(), - JS::NewArrayBufferWithContents(jsapi.cx(), size, packet.release())); + JS::NewArrayBufferWithContents(jsapi.cx(), size, std::move(packetPtr))); RootedSpiderMonkeyInterface arrayBuffer(jsapi.cx()); if (!arrayBuffer.Init(jsobj)) { diff --git a/dom/network/TCPSocketChild.cpp b/dom/network/TCPSocketChild.cpp index b6ccba021d5c..cf9853690c59 100644 --- a/dom/network/TCPSocketChild.cpp +++ b/dom/network/TCPSocketChild.cpp @@ -32,12 +32,10 @@ bool DeserializeArrayBuffer(JSContext* cx, const nsTArray& aBuffer, if (!data) return false; memcpy(data.get(), aBuffer.Elements(), aBuffer.Length()); + mozilla::UniquePtr dataPtr{data.release()}; JSObject* obj = - JS::NewArrayBufferWithContents(cx, aBuffer.Length(), data.get()); + JS::NewArrayBufferWithContents(cx, aBuffer.Length(), std::move(dataPtr)); if (!obj) return false; - // If JS::NewArrayBufferWithContents returns non-null, the ownership of - // the data is transfered to obj, so we release the ownership here. - mozilla::Unused << data.release(); aVal.setObject(*obj); return true; diff --git a/dom/serviceworkers/ServiceWorkerEvents.cpp b/dom/serviceworkers/ServiceWorkerEvents.cpp index 955a905aa6f2..7883471014c2 100644 --- a/dom/serviceworkers/ServiceWorkerEvents.cpp +++ b/dom/serviceworkers/ServiceWorkerEvents.cpp @@ -1093,7 +1093,9 @@ void PushMessageData::ArrayBuffer(JSContext* cx, ErrorResult& aRv) { uint8_t* data = GetContentsCopy(); if (data) { - BodyUtil::ConsumeArrayBuffer(cx, aRetval, mBytes.Length(), data, aRv); + UniquePtr dataPtr(data); + BodyUtil::ConsumeArrayBuffer(cx, aRetval, mBytes.Length(), + std::move(dataPtr), aRv); } } diff --git a/dom/streams/ByteStreamHelpers.cpp b/dom/streams/ByteStreamHelpers.cpp index 5568971fed85..c2a83dc48021 100644 --- a/dom/streams/ByteStreamHelpers.cpp +++ b/dom/streams/ByteStreamHelpers.cpp @@ -26,7 +26,8 @@ JSObject* TransferArrayBuffer(JSContext* aCx, JS::Handle aObject) { size_t bufferLength = JS::GetArrayBufferByteLength(aObject); // Step 2 (Reordered) - void* bufferData = JS::StealArrayBufferContents(aCx, aObject); + UniquePtr bufferData{ + JS::StealArrayBufferContents(aCx, aObject)}; // Step 4. if (!JS::DetachArrayBuffer(aCx, aObject)) { @@ -34,7 +35,8 @@ JSObject* TransferArrayBuffer(JSContext* aCx, JS::Handle aObject) { } // Step 5. - return JS::NewArrayBufferWithContents(aCx, bufferLength, bufferData); + return JS::NewArrayBufferWithContents(aCx, bufferLength, + std::move(bufferData)); } // https://streams.spec.whatwg.org/#can-transfer-array-buffer diff --git a/dom/streams/UnderlyingSourceCallbackHelpers.cpp b/dom/streams/UnderlyingSourceCallbackHelpers.cpp index d14a12a1b930..982404229d04 100644 --- a/dom/streams/UnderlyingSourceCallbackHelpers.cpp +++ b/dom/streams/UnderlyingSourceCallbackHelpers.cpp @@ -429,7 +429,8 @@ void InputToReadableStreamAlgorithms::PullFromInputStream(JSContext* aCx, else { // Step 9.1. Set view to the result of creating a Uint8Array from pulled in // stream’s relevant Realm. - UniquePtr buffer(static_cast(JS_malloc(aCx, pullSize))); + UniquePtr buffer( + static_cast(JS_malloc(aCx, pullSize))); if (!buffer) { aRv.ThrowTypeError("Out of memory"); return; @@ -446,8 +447,8 @@ void InputToReadableStreamAlgorithms::PullFromInputStream(JSContext* aCx, } MOZ_DIAGNOSTIC_ASSERT(pullSize == bytesWritten); - JS::Rooted view( - aCx, nsJSUtils::MoveBufferAsUint8Array(aCx, bytesWritten, buffer)); + JS::Rooted view(aCx, nsJSUtils::MoveBufferAsUint8Array( + aCx, bytesWritten, std::move(buffer))); if (!view) { JS_ClearPendingException(aCx); aRv.ThrowTypeError("Out of memory"); diff --git a/dom/system/IOUtils.cpp b/dom/system/IOUtils.cpp index c623562f7c02..e8917e07b2c6 100644 --- a/dom/system/IOUtils.cpp +++ b/dom/system/IOUtils.cpp @@ -2708,20 +2708,16 @@ JSObject* IOUtils::JsBuffer::IntoUint8Array(JSContext* aCx, JsBuffer aBuffer) { return JS_NewUint8Array(aCx, 0); } - char* rawBuffer = aBuffer.mBuffer.release(); + UniquePtr rawBuffer{aBuffer.mBuffer.release()}; MOZ_RELEASE_ASSERT(rawBuffer); JS::Rooted arrayBuffer( aCx, JS::NewArrayBufferWithContents(aCx, aBuffer.mLength, - reinterpret_cast(rawBuffer))); + std::move(rawBuffer))); if (!arrayBuffer) { - // The array buffer does not take ownership of the data pointer unless - // creation succeeds. We are still on the hook to free it. - // // aBuffer will be destructed at end of scope, but its destructor does not // take into account |mCapacity| or |mLength|, so it is OK for them to be // non-zero here with a null |mBuffer|. - js_free(rawBuffer); return nullptr; } diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 41b5fa84057e..099523972ab4 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -4989,10 +4989,10 @@ class CloneBufferObject : public NativeObject { return false; } - auto* rawBuffer = buffer.release(); - JSObject* arrayBuffer = JS::NewArrayBufferWithContents(cx, size, rawBuffer); + UniquePtr dataBuffer{buffer.release()}; + JSObject* arrayBuffer = + JS::NewArrayBufferWithContents(cx, size, std::move(dataBuffer)); if (!arrayBuffer) { - js_free(rawBuffer); return false; } diff --git a/js/src/jsapi-tests/testArrayBuffer.cpp b/js/src/jsapi-tests/testArrayBuffer.cpp index cdc669f25d3c..796f9272720b 100644 --- a/js/src/jsapi-tests/testArrayBuffer.cpp +++ b/js/src/jsapi-tests/testArrayBuffer.cpp @@ -66,14 +66,15 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal) { CHECK(v.isInt32(MAGIC_VALUE_2)); // Steal the contents - void* contents = JS::StealArrayBufferContents(cx, obj); + mozilla::UniquePtr contents{ + JS::StealArrayBufferContents(cx, obj)}; CHECK(contents != nullptr); CHECK(JS::IsDetachedArrayBufferObject(obj)); // Transfer to a new ArrayBuffer - JS::RootedObject dst(cx, - JS::NewArrayBufferWithContents(cx, size, contents)); + JS::RootedObject dst( + cx, JS::NewArrayBufferWithContents(cx, size, std::move(contents))); CHECK(JS::IsArrayBufferObject(dst)); { JS::AutoCheckCannotGC nogc; diff --git a/mfbt/Span.h b/mfbt/Span.h index bcbd492d35ed..d9ba1af22054 100644 --- a/mfbt/Span.h +++ b/mfbt/Span.h @@ -490,8 +490,9 @@ class Span { /** * Constructor for mozilla::UniquePtr holding an array and length. */ - template > - constexpr Span(const mozilla::UniquePtr& aPtr, + template , + class DeleterType> + constexpr Span(const mozilla::UniquePtr& aPtr, index_type aLength) : storage_(aPtr.get(), aLength) {}