mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1167411 - Add JSAutoStructuredCloneBuffer::abandon, r=jorendorff
This commit is contained in:
parent
eaf5e38092
commit
1e125efa54
@ -162,17 +162,25 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
|
||||
uint64_t* data_;
|
||||
size_t nbytes_;
|
||||
uint32_t version_;
|
||||
enum {
|
||||
OwnsTransferablesIfAny,
|
||||
IgnoreTransferablesIfAny,
|
||||
NoTransferables
|
||||
} ownTransferables_;
|
||||
|
||||
const JSStructuredCloneCallbacks* callbacks_;
|
||||
void* closure_;
|
||||
|
||||
public:
|
||||
JSAutoStructuredCloneBuffer()
|
||||
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
|
||||
ownTransferables_(NoTransferables),
|
||||
callbacks_(nullptr), closure_(nullptr)
|
||||
{}
|
||||
|
||||
JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks* callbacks, void* closure)
|
||||
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
|
||||
ownTransferables_(NoTransferables),
|
||||
callbacks_(callbacks), closure_(closure)
|
||||
{}
|
||||
|
||||
@ -194,11 +202,17 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
|
||||
// JSAutoStructuredCloneBuffer::steal).
|
||||
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
|
||||
|
||||
// Remove the buffer so that it will not be automatically freed.
|
||||
// After this, the caller is responsible for feeding the memory back to
|
||||
// JSAutoStructuredCloneBuffer::adopt.
|
||||
// Release the buffer and transfer ownership to the caller. The caller is
|
||||
// responsible for calling JS_ClearStructuredClone or feeding the memory
|
||||
// back to JSAutoStructuredCloneBuffer::adopt.
|
||||
void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr);
|
||||
|
||||
// Abandon ownership of any transferable objects stored in the buffer,
|
||||
// without freeing the buffer itself. Useful when copying the data out into
|
||||
// an external container, though note that you will need to use adopt() or
|
||||
// JS_ClearStructuredClone to properly release that data eventually.
|
||||
void abandon() { ownTransferables_ = IgnoreTransferablesIfAny; }
|
||||
|
||||
bool read(JSContext* cx, JS::MutableHandleValue vp,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
|
||||
|
||||
|
@ -383,7 +383,8 @@ ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, MutableHandleV
|
||||
// Transferables will use the JSStructuredCloneCallbacks::freeTransfer() to
|
||||
// delete their transferables.
|
||||
static void
|
||||
Discard(uint64_t* buffer, size_t nbytes, const JSStructuredCloneCallbacks* cb, void* cbClosure)
|
||||
DiscardTransferables(uint64_t* buffer, size_t nbytes,
|
||||
const JSStructuredCloneCallbacks* cb, void* cbClosure)
|
||||
{
|
||||
MOZ_ASSERT(nbytes % sizeof(uint64_t) == 0);
|
||||
if (nbytes < sizeof(uint64_t))
|
||||
@ -431,27 +432,15 @@ Discard(uint64_t* buffer, size_t nbytes, const JSStructuredCloneCallbacks* cb, v
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ClearStructuredClone(uint64_t* data, size_t nbytes,
|
||||
const JSStructuredCloneCallbacks* cb, void* cbClosure)
|
||||
static bool
|
||||
StructuredCloneHasTransferObjects(const uint64_t* data, size_t nbytes)
|
||||
{
|
||||
Discard(data, nbytes, cb, cbClosure);
|
||||
js_free(data);
|
||||
}
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
bool
|
||||
StructuredCloneHasTransferObjects(const uint64_t* data, size_t nbytes, bool* hasTransferable)
|
||||
{
|
||||
*hasTransferable = false;
|
||||
|
||||
if (data) {
|
||||
uint64_t u = LittleEndian::readUint64(data);
|
||||
uint32_t tag = uint32_t(u >> 32);
|
||||
if (tag == SCTAG_TRANSFER_MAP_HEADER)
|
||||
*hasTransferable = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
uint64_t u = LittleEndian::readUint64(data);
|
||||
uint32_t tag = uint32_t(u >> 32);
|
||||
return (tag == SCTAG_TRANSFER_MAP_HEADER);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@ -734,7 +723,8 @@ JSStructuredCloneWriter::~JSStructuredCloneWriter()
|
||||
uint64_t* data;
|
||||
size_t size;
|
||||
MOZ_ALWAYS_TRUE(extractBuffer(&data, &size));
|
||||
ClearStructuredClone(data, size, callbacks, closure);
|
||||
DiscardTransferables(data, size, callbacks, closure);
|
||||
js_free(data);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1789,8 +1779,9 @@ JSStructuredCloneReader::readTransferMap()
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
}
|
||||
|
||||
// On failure, the buffer will still own the data (since its ownership will not get set to SCTAG_TMO_UNOWNED),
|
||||
// so the data will be freed by ClearStructuredClone
|
||||
// On failure, the buffer will still own the data (since its ownership
|
||||
// will not get set to SCTAG_TMO_UNOWNED), so the data will be freed by
|
||||
// DiscardTransferables.
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@ -1919,7 +1910,8 @@ JS_ClearStructuredClone(uint64_t* data, size_t nbytes,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks,
|
||||
void* closure)
|
||||
{
|
||||
ClearStructuredClone(data, nbytes, optionalCallbacks, closure);
|
||||
DiscardTransferables(data, nbytes, optionalCallbacks, closure);
|
||||
js_free(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1927,11 +1919,7 @@ JS_PUBLIC_API(bool)
|
||||
JS_StructuredCloneHasTransferables(const uint64_t* data, size_t nbytes,
|
||||
bool* hasTransferable)
|
||||
{
|
||||
bool transferable;
|
||||
if (!StructuredCloneHasTransferObjects(data, nbytes, &transferable))
|
||||
return false;
|
||||
|
||||
*hasTransferable = transferable;
|
||||
*hasTransferable = StructuredCloneHasTransferObjects(data, nbytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1979,6 +1967,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
|
||||
|
||||
JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
|
||||
{
|
||||
ownTransferables_ = other.ownTransferables_;
|
||||
other.steal(&data_, &nbytes_, &version_);
|
||||
}
|
||||
|
||||
@ -1987,6 +1976,7 @@ JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
|
||||
{
|
||||
MOZ_ASSERT(&other != this);
|
||||
clear();
|
||||
ownTransferables_ = other.ownTransferables_;
|
||||
other.steal(&data_, &nbytes_, &version_);
|
||||
return *this;
|
||||
}
|
||||
@ -1995,7 +1985,10 @@ void
|
||||
JSAutoStructuredCloneBuffer::clear()
|
||||
{
|
||||
if (data_) {
|
||||
ClearStructuredClone(data_, nbytes_, callbacks_, closure_);
|
||||
if (ownTransferables_ == OwnsTransferablesIfAny)
|
||||
DiscardTransferables(data_, nbytes_, callbacks_, closure_);
|
||||
ownTransferables_ = NoTransferables;
|
||||
js_free(data_);
|
||||
data_ = nullptr;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
@ -2006,9 +1999,7 @@ bool
|
||||
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
|
||||
{
|
||||
// transferable objects cannot be copied
|
||||
bool hasTransferable;
|
||||
if (!StructuredCloneHasTransferObjects(data_, nbytes_, &hasTransferable) ||
|
||||
hasTransferable)
|
||||
if (StructuredCloneHasTransferObjects(data_, nbytes_))
|
||||
return false;
|
||||
|
||||
uint64_t* newData = static_cast<uint64_t*>(js_malloc(nbytes));
|
||||
@ -2021,6 +2012,7 @@ JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32
|
||||
data_ = newData;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
ownTransferables_ = NoTransferables;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2031,6 +2023,7 @@ JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t versi
|
||||
data_ = data;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
ownTransferables_ = OwnsTransferablesIfAny;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2044,6 +2037,7 @@ JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t*
|
||||
data_ = nullptr;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
ownTransferables_ = NoTransferables;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2073,13 +2067,17 @@ JSAutoStructuredCloneBuffer::write(JSContext* cx, HandleValue value,
|
||||
void* closure)
|
||||
{
|
||||
clear();
|
||||
bool ok = !!JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
|
||||
optionalCallbacks, closure,
|
||||
transferable);
|
||||
if (!ok) {
|
||||
bool ok = JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
|
||||
optionalCallbacks, closure,
|
||||
transferable);
|
||||
|
||||
if (ok) {
|
||||
ownTransferables_ = OwnsTransferablesIfAny;
|
||||
} else {
|
||||
data_ = nullptr;
|
||||
nbytes_ = 0;
|
||||
version_ = JS_STRUCTURED_CLONE_VERSION;
|
||||
ownTransferables_ = NoTransferables;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user