mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 1050340 - Handle ArrayBuffers and TypedArrays pseudo-generically. r=luke
This commit is contained in:
parent
9660944944
commit
38eea4a829
@ -1729,6 +1729,17 @@ JS_IsArrayBufferObject(JSObject *obj);
|
||||
extern JS_FRIEND_API(uint32_t)
|
||||
JS_GetArrayBufferByteLength(JSObject *obj);
|
||||
|
||||
/*
|
||||
* Return true if the arrayBuffer contains any data. This will return false for
|
||||
* ArrayBuffer.prototype and neutered ArrayBuffers.
|
||||
*
|
||||
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
|
||||
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
|
||||
* ArrayBuffer, and the unwrapping will succeed.
|
||||
*/
|
||||
extern JS_FRIEND_API(bool)
|
||||
JS_ArrayBufferHasData(JSObject *obj);
|
||||
|
||||
/*
|
||||
* Check whether the obj is ArrayBufferObject and memory mapped. Note that this
|
||||
* may return false if a security wrapper is encountered that denies the
|
||||
|
@ -1147,6 +1147,12 @@ JS_IsArrayBufferObject(JSObject *obj)
|
||||
return obj ? obj->is<ArrayBufferObject>() : false;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
JS_ArrayBufferHasData(JSObject *obj)
|
||||
{
|
||||
return CheckedUnwrap(obj)->as<ArrayBufferObject>().hasData();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::UnwrapArrayBuffer(JSObject *obj)
|
||||
{
|
||||
|
@ -856,7 +856,8 @@ JSStructuredCloneWriter::checkStack()
|
||||
bool
|
||||
JSStructuredCloneWriter::writeTypedArray(HandleObject obj)
|
||||
{
|
||||
Rooted<TypedArrayObject*> tarr(context(), &obj->as<TypedArrayObject>());
|
||||
Rooted<TypedArrayObject*> tarr(context(), &CheckedUnwrap(obj)->as<TypedArrayObject>());
|
||||
JSAutoCompartment ac(context(), tarr);
|
||||
|
||||
if (!TypedArrayObject::ensureHasBuffer(context(), tarr))
|
||||
return false;
|
||||
@ -878,7 +879,8 @@ JSStructuredCloneWriter::writeTypedArray(HandleObject obj)
|
||||
bool
|
||||
JSStructuredCloneWriter::writeArrayBuffer(HandleObject obj)
|
||||
{
|
||||
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
|
||||
ArrayBufferObject &buffer = CheckedUnwrap(obj)->as<ArrayBufferObject>();
|
||||
JSAutoCompartment ac(context(), &buffer);
|
||||
|
||||
return out.writePair(SCTAG_ARRAY_BUFFER_OBJECT, buffer.byteLength()) &&
|
||||
out.writeBytes(buffer.dataPointer(), buffer.byteLength());
|
||||
@ -1020,9 +1022,9 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
|
||||
} else if (ObjectClassIs(obj, ESClass_Date, context())) {
|
||||
double d = js_DateGetMsecSinceEpoch(obj);
|
||||
return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
|
||||
} else if (obj->is<TypedArrayObject>()) {
|
||||
} else if (JS_IsTypedArrayObject(obj)) {
|
||||
return writeTypedArray(obj);
|
||||
} else if (obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().hasData()) {
|
||||
} else if (JS_IsArrayBufferObject(obj) && JS_ArrayBufferHasData(obj)) {
|
||||
return writeArrayBuffer(obj);
|
||||
} else if (obj->is<JSObject>() || obj->is<ArrayObject>()) {
|
||||
return traverseObject(obj);
|
||||
@ -1108,29 +1110,34 @@ JSStructuredCloneWriter::transferOwnership()
|
||||
MOZ_ASSERT(ownership == JS::SCTAG_TMO_UNFILLED);
|
||||
#endif
|
||||
|
||||
if (obj->is<ArrayBufferObject>()) {
|
||||
bool isMapped = obj->as<ArrayBufferObject>().isMappedArrayBuffer();
|
||||
size_t nbytes = obj->as<ArrayBufferObject>().byteLength();
|
||||
content = JS_StealArrayBufferContents(context(), obj);
|
||||
if (!content)
|
||||
return false; // Destructor will clean up the already-transferred data
|
||||
tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER;
|
||||
if (isMapped)
|
||||
ownership = JS::SCTAG_TMO_MAPPED_DATA;
|
||||
else
|
||||
ownership = JS::SCTAG_TMO_ALLOC_DATA;
|
||||
extraData = nbytes;
|
||||
} else if (obj->is<SharedArrayBufferObject>()) {
|
||||
SharedArrayRawBuffer *rawbuf = obj->as<SharedArrayBufferObject>().rawBufferObject();
|
||||
if (ObjectClassIs(obj, ESClass_ArrayBuffer, context())) {
|
||||
// The current setup of the array buffer inheritance hierarchy doesn't
|
||||
// lend itself well to generic manipulation via proxies.
|
||||
Rooted<ArrayBufferObject*> arrayBuffer(context(), &CheckedUnwrap(obj)->as<ArrayBufferObject>());
|
||||
if (arrayBuffer->isSharedArrayBuffer()) {
|
||||
SharedArrayRawBuffer *rawbuf = arrayBuffer->as<SharedArrayBufferObject>().rawBufferObject();
|
||||
|
||||
// Avoids a race condition where the parent thread frees the buffer
|
||||
// before the child has accepted the transferable.
|
||||
rawbuf->addReference();
|
||||
// Avoids a race condition where the parent thread frees the buffer
|
||||
// before the child has accepted the transferable.
|
||||
rawbuf->addReference();
|
||||
|
||||
tag = SCTAG_TRANSFER_MAP_SHARED_BUFFER;
|
||||
ownership = JS::SCTAG_TMO_SHARED_BUFFER;
|
||||
content = rawbuf;
|
||||
extraData = 0;
|
||||
tag = SCTAG_TRANSFER_MAP_SHARED_BUFFER;
|
||||
ownership = JS::SCTAG_TMO_SHARED_BUFFER;
|
||||
content = rawbuf;
|
||||
extraData = 0;
|
||||
} else {
|
||||
bool isMapped = arrayBuffer->isMappedArrayBuffer();
|
||||
size_t nbytes = arrayBuffer->byteLength();
|
||||
content = JS_StealArrayBufferContents(context(), arrayBuffer);
|
||||
if (!content)
|
||||
return false; // Destructor will clean up the already-transferred data
|
||||
tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER;
|
||||
if (isMapped)
|
||||
ownership = JS::SCTAG_TMO_MAPPED_DATA;
|
||||
else
|
||||
ownership = JS::SCTAG_TMO_ALLOC_DATA;
|
||||
extraData = nbytes;
|
||||
}
|
||||
} else {
|
||||
if (!callbacks || !callbacks->writeTransfer)
|
||||
return reportErrorTransferable();
|
||||
@ -2010,14 +2017,5 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, HandleValue v)
|
||||
JS_ASSERT(v.isObject());
|
||||
assertSameCompartment(w->context(), v);
|
||||
RootedObject obj(w->context(), &v.toObject());
|
||||
|
||||
// If the object is a security wrapper, see if we're allowed to unwrap it.
|
||||
// If we aren't, throw.
|
||||
if (obj->is<WrapperObject>())
|
||||
obj = CheckedUnwrap(obj);
|
||||
if (!obj) {
|
||||
JS_ReportErrorNumber(w->context(), js_GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
|
||||
return false;
|
||||
}
|
||||
return w->writeTypedArray(obj);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user