зеркало из https://github.com/mozilla/gecko-dev.git
Bug 789593 - Clone typed arrays by cloning their buffers and only saving construction parameters. r=jorendorff, bent
Also enters a compartment where needed, and bumps both the structured clone and IndexedDB schema versions
This commit is contained in:
Родитель
7b3fdd386a
Коммит
a3f269557f
|
@ -3530,12 +3530,13 @@ NS_DOMWriteStructuredClone(JSContext* cx,
|
|||
// Prepare the ImageData internals.
|
||||
uint32_t width = imageData->Width();
|
||||
uint32_t height = imageData->Height();
|
||||
JS::Value dataArray = JS::ObjectValue(*imageData->GetDataObject());
|
||||
JSObject *dataArray = imageData->GetDataObject();
|
||||
|
||||
// Write the internals to the stream.
|
||||
JSAutoCompartment ac(cx, dataArray);
|
||||
return JS_WriteUint32Pair(writer, SCTAG_DOM_IMAGEDATA, 0) &&
|
||||
JS_WriteUint32Pair(writer, width, height) &&
|
||||
JS_WriteTypedArray(writer, dataArray);
|
||||
JS_WriteTypedArray(writer, JS::ObjectValue(*dataArray));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -32,11 +32,11 @@ namespace {
|
|||
|
||||
// If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
|
||||
// schema version.
|
||||
MOZ_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1,
|
||||
MOZ_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 2,
|
||||
"Need to update the major schema version.");
|
||||
|
||||
// Major schema version. Bump for almost everything.
|
||||
const uint32_t kMajorSchemaVersion = 13;
|
||||
const uint32_t kMajorSchemaVersion = 14;
|
||||
|
||||
// Minor schema version. Should almost always be 0 (maybe bump on release
|
||||
// branches if we have to).
|
||||
|
@ -1350,6 +1350,17 @@ UpgradeSchemaFrom12_0To13_0(mozIStorageConnection* aConnection,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UpgradeSchemaFrom13_0To14_0(mozIStorageConnection* aConnection)
|
||||
{
|
||||
// The only change between 13 and 14 was a different structured
|
||||
// clone format, but it's backwards-compatible.
|
||||
nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(14, 0));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class VersionChangeEventsRunnable;
|
||||
|
||||
class SetVersionHelper : public AsyncConnectionHelper,
|
||||
|
@ -1904,7 +1915,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
|||
}
|
||||
else {
|
||||
// This logic needs to change next time we change the schema!
|
||||
MOZ_STATIC_ASSERT(kSQLiteSchemaVersion == int32_t((13 << 4) + 0),
|
||||
MOZ_STATIC_ASSERT(kSQLiteSchemaVersion == int32_t((14 << 4) + 0),
|
||||
"Need upgrade code from schema version increase.");
|
||||
|
||||
while (schemaVersion != kSQLiteSchemaVersion) {
|
||||
|
@ -1936,6 +1947,9 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
|||
else if (schemaVersion == MakeSchemaVersion(12, 0)) {
|
||||
rv = UpgradeSchemaFrom12_0To13_0(connection, &vacuumNeeded);
|
||||
}
|
||||
else if (schemaVersion == MakeSchemaVersion(13, 0)) {
|
||||
rv = UpgradeSchemaFrom13_0To14_0(connection);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Unable to open IndexedDB database, no upgrade path is "
|
||||
"available!");
|
||||
|
|
|
@ -4404,7 +4404,7 @@ JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval
|
|||
/* API for the HTML5 internal structured cloning algorithm. */
|
||||
|
||||
/* The maximum supported structured-clone serialization format version. */
|
||||
#define JS_STRUCTURED_CLONE_VERSION 1
|
||||
#define JS_STRUCTURED_CLONE_VERSION 2
|
||||
|
||||
struct JSStructuredCloneCallbacks {
|
||||
ReadStructuredCloneOp read;
|
||||
|
|
|
@ -4,6 +4,29 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Endian.h"
|
||||
/*
|
||||
* This file implements the structured clone algorithm of
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data
|
||||
*
|
||||
* The implementation differs slightly in that it uses an explicit stack, and
|
||||
* the "memory" maps source objects to sequential integer indexes rather than
|
||||
* directly pointing to destination objects. As a result, the order in which
|
||||
* things are added to the memory must exactly match the order in which they
|
||||
* are placed into 'allObjs', an analogous array of back-referenceable
|
||||
* destination objects constructed while reading.
|
||||
*
|
||||
* For the most part, this is easy: simply add objects to the memory when first
|
||||
* encountering them. But reading in a typed array requires an ArrayBuffer for
|
||||
* construction, so objects cannot just be added to 'allObjs' in the order they
|
||||
* are created. If they were, ArrayBuffers would come before typed arrays when
|
||||
* in fact the typed array was added to 'memory' first.
|
||||
*
|
||||
* So during writing, we add objects to the memory when first encountering
|
||||
* them. When reading a typed array, a placeholder is pushed onto allObjs until
|
||||
* the ArrayBuffer has been read, then it is updated with the actual typed
|
||||
* array object.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jsclone.h"
|
||||
|
@ -40,17 +63,18 @@ enum StructuredDataType {
|
|||
SCTAG_BACK_REFERENCE_OBJECT,
|
||||
SCTAG_TRANSFER_MAP_HEADER,
|
||||
SCTAG_TRANSFER_MAP,
|
||||
SCTAG_TYPED_ARRAY_MIN = 0xFFFF0100,
|
||||
SCTAG_TYPED_ARRAY_INT8 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT8,
|
||||
SCTAG_TYPED_ARRAY_UINT8 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT8,
|
||||
SCTAG_TYPED_ARRAY_INT16 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT16,
|
||||
SCTAG_TYPED_ARRAY_UINT16 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT16,
|
||||
SCTAG_TYPED_ARRAY_INT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_INT32,
|
||||
SCTAG_TYPED_ARRAY_UINT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT32,
|
||||
SCTAG_TYPED_ARRAY_FLOAT32 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_FLOAT32,
|
||||
SCTAG_TYPED_ARRAY_FLOAT64 = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_FLOAT64,
|
||||
SCTAG_TYPED_ARRAY_UINT8_CLAMPED = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_UINT8_CLAMPED,
|
||||
SCTAG_TYPED_ARRAY_MAX = SCTAG_TYPED_ARRAY_MIN + TypedArray::TYPE_MAX - 1,
|
||||
SCTAG_TYPED_ARRAY_OBJECT,
|
||||
SCTAG_TYPED_ARRAY_V1_MIN = 0xFFFF0100,
|
||||
SCTAG_TYPED_ARRAY_V1_INT8 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_INT8,
|
||||
SCTAG_TYPED_ARRAY_V1_UINT8 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_UINT8,
|
||||
SCTAG_TYPED_ARRAY_V1_INT16 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_INT16,
|
||||
SCTAG_TYPED_ARRAY_V1_UINT16 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_UINT16,
|
||||
SCTAG_TYPED_ARRAY_V1_INT32 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_INT32,
|
||||
SCTAG_TYPED_ARRAY_V1_UINT32 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_UINT32,
|
||||
SCTAG_TYPED_ARRAY_V1_FLOAT32 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_FLOAT32,
|
||||
SCTAG_TYPED_ARRAY_V1_FLOAT64 = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_FLOAT64,
|
||||
SCTAG_TYPED_ARRAY_V1_UINT8_CLAMPED = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_UINT8_CLAMPED,
|
||||
SCTAG_TYPED_ARRAY_V1_MAX = SCTAG_TYPED_ARRAY_V1_MIN + TypedArray::TYPE_MAX - 1,
|
||||
SCTAG_END_OF_BUILTIN_TYPES
|
||||
};
|
||||
|
||||
|
@ -66,13 +90,6 @@ js_GetSCOffset(JSStructuredCloneWriter* writer)
|
|||
return writer->output().count() * sizeof(uint64_t);
|
||||
}
|
||||
|
||||
static StructuredDataType
|
||||
ArrayTypeToTag(uint32_t type)
|
||||
{
|
||||
JS_ASSERT(type < TypedArray::TYPE_MAX);
|
||||
return static_cast<StructuredDataType>(uint32_t(SCTAG_TYPED_ARRAY_MIN) + type);
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(SCTAG_END_OF_BUILTIN_TYPES <= JS_SCTAG_USER_MIN);
|
||||
JS_STATIC_ASSERT(JS_SCTAG_USER_MIN <= JS_SCTAG_USER_MAX);
|
||||
JS_STATIC_ASSERT(TypedArray::TYPE_INT8 == 0);
|
||||
|
@ -539,6 +556,7 @@ JS_PUBLIC_API(JSBool)
|
|||
JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval 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.
|
||||
|
@ -552,30 +570,29 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
|
|||
return w->writeTypedArray(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a typed array. Note that post-v1 structured clone buffers do not
|
||||
* perform endianness conversion on stored data, so multibyte typed arrays
|
||||
* cannot be deserialized into a different endianness machine. Endianness
|
||||
* conversion would prevent sharing ArrayBuffers: if you have Int8Array and
|
||||
* Int16Array views of the same ArrayBuffer, should the data bytes be
|
||||
* byte-swapped when writing or not? The Int8Array requires them to not be
|
||||
* swapped; the Int16Array requires that they are.
|
||||
*/
|
||||
bool
|
||||
JSStructuredCloneWriter::writeTypedArray(HandleObject arr)
|
||||
{
|
||||
if (!out.writePair(ArrayTypeToTag(TypedArray::type(arr)), TypedArray::length(arr)))
|
||||
if (!out.writePair(SCTAG_TYPED_ARRAY_OBJECT, TypedArray::length(arr)))
|
||||
return false;
|
||||
uint64_t type = TypedArray::type(arr);
|
||||
if (!out.write(type))
|
||||
return false;
|
||||
|
||||
switch (TypedArray::type(arr)) {
|
||||
case TypedArray::TYPE_INT8:
|
||||
case TypedArray::TYPE_UINT8:
|
||||
case TypedArray::TYPE_UINT8_CLAMPED:
|
||||
return out.writeArray((const uint8_t *) TypedArray::viewData(arr), TypedArray::length(arr));
|
||||
case TypedArray::TYPE_INT16:
|
||||
case TypedArray::TYPE_UINT16:
|
||||
return out.writeArray((const uint16_t *) TypedArray::viewData(arr), TypedArray::length(arr));
|
||||
case TypedArray::TYPE_INT32:
|
||||
case TypedArray::TYPE_UINT32:
|
||||
case TypedArray::TYPE_FLOAT32:
|
||||
return out.writeArray((const uint32_t *) TypedArray::viewData(arr), TypedArray::length(arr));
|
||||
case TypedArray::TYPE_FLOAT64:
|
||||
return out.writeArray((const uint64_t *) TypedArray::viewData(arr), TypedArray::length(arr));
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
// Write out the ArrayBuffer tag and contents
|
||||
if (!startWrite(TypedArray::bufferValue(arr)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return out.write(TypedArray::byteOffset(arr));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -818,48 +835,94 @@ JSStructuredCloneReader::readString(uint32_t nchars)
|
|||
return str;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
TagToV1ArrayType(uint32_t tag)
|
||||
{
|
||||
JS_ASSERT(tag >= SCTAG_TYPED_ARRAY_V1_MIN && tag <= SCTAG_TYPED_ARRAY_V1_MAX);
|
||||
return tag - SCTAG_TYPED_ARRAY_V1_MIN;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp)
|
||||
{
|
||||
uint32_t tag, nelems;
|
||||
if (!r->input().readPair(&tag, &nelems))
|
||||
return false;
|
||||
JS_ASSERT(tag >= SCTAG_TYPED_ARRAY_MIN && tag <= SCTAG_TYPED_ARRAY_MAX);
|
||||
return r->readTypedArray(tag, nelems, vp);
|
||||
if (tag >= SCTAG_TYPED_ARRAY_V1_MIN && tag <= SCTAG_TYPED_ARRAY_V1_MAX) {
|
||||
return r->readTypedArray(TagToV1ArrayType(tag), nelems, vp, true);
|
||||
} else if (tag == SCTAG_TYPED_ARRAY_OBJECT) {
|
||||
uint64_t arrayType;
|
||||
if (!r->input().read(&arrayType))
|
||||
return false;
|
||||
return r->readTypedArray(arrayType, nelems, vp);
|
||||
} else {
|
||||
JS_ReportErrorNumber(r->context(), js_GetErrorMessage, NULL,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "expected type array");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp)
|
||||
JSStructuredCloneReader::readTypedArray(uint32_t arrayType, uint32_t nelems, Value *vp,
|
||||
bool v1Read)
|
||||
{
|
||||
if (arrayType > TypedArray::TYPE_UINT8_CLAMPED) {
|
||||
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "unhandled typed array element type");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Push a placeholder onto the allObjs list to stand in for the typed array
|
||||
uint32_t placeholderIndex = allObjs.length();
|
||||
Value dummy = JSVAL_NULL;
|
||||
if (!allObjs.append(dummy))
|
||||
return false;
|
||||
|
||||
// Read the ArrayBuffer object and its contents (but no properties)
|
||||
Value v;
|
||||
uint32_t byteOffset;
|
||||
if (v1Read) {
|
||||
if (!readV1ArrayBuffer(arrayType, nelems, &v))
|
||||
return false;
|
||||
byteOffset = 0;
|
||||
} else {
|
||||
if (!startRead(&v))
|
||||
return false;
|
||||
uint64_t n;
|
||||
if (!in.read(&n))
|
||||
return false;
|
||||
byteOffset = n;
|
||||
}
|
||||
RootedObject buffer(context(), &v.toObject());
|
||||
RootedObject obj(context(), NULL);
|
||||
|
||||
switch (tag) {
|
||||
case SCTAG_TYPED_ARRAY_INT8:
|
||||
obj = JS_NewInt8Array(context(), nelems);
|
||||
switch (arrayType) {
|
||||
case TypedArray::TYPE_INT8:
|
||||
obj = JS_NewInt8ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_UINT8:
|
||||
obj = JS_NewUint8Array(context(), nelems);
|
||||
case TypedArray::TYPE_UINT8:
|
||||
obj = JS_NewUint8ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_INT16:
|
||||
obj = JS_NewInt16Array(context(), nelems);
|
||||
case TypedArray::TYPE_INT16:
|
||||
obj = JS_NewInt16ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_UINT16:
|
||||
obj = JS_NewUint16Array(context(), nelems);
|
||||
case TypedArray::TYPE_UINT16:
|
||||
obj = JS_NewUint16ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_INT32:
|
||||
obj = JS_NewInt32Array(context(), nelems);
|
||||
case TypedArray::TYPE_INT32:
|
||||
obj = JS_NewInt32ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_UINT32:
|
||||
obj = JS_NewUint32Array(context(), nelems);
|
||||
case TypedArray::TYPE_UINT32:
|
||||
obj = JS_NewUint32ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_FLOAT32:
|
||||
obj = JS_NewFloat32Array(context(), nelems);
|
||||
case TypedArray::TYPE_FLOAT32:
|
||||
obj = JS_NewFloat32ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_FLOAT64:
|
||||
obj = JS_NewFloat64Array(context(), nelems);
|
||||
case TypedArray::TYPE_FLOAT64:
|
||||
obj = JS_NewFloat64ArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
|
||||
obj = JS_NewUint8ClampedArray(context(), nelems);
|
||||
case TypedArray::TYPE_UINT8_CLAMPED:
|
||||
obj = JS_NewUint8ClampedArrayWithBuffer(context(), buffer, byteOffset, nelems);
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
|
@ -870,30 +933,9 @@ JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp
|
|||
return false;
|
||||
vp->setObject(*obj);
|
||||
|
||||
JS_ASSERT(TypedArray::length(obj) == nelems);
|
||||
switch (tag) {
|
||||
case SCTAG_TYPED_ARRAY_INT8:
|
||||
return in.readArray((uint8_t*) JS_GetInt8ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT8:
|
||||
return in.readArray(JS_GetUint8ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_INT16:
|
||||
return in.readArray((uint16_t*) JS_GetInt16ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT16:
|
||||
return in.readArray(JS_GetUint16ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_INT32:
|
||||
return in.readArray((uint32_t*) JS_GetInt32ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT32:
|
||||
return in.readArray(JS_GetUint32ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_FLOAT32:
|
||||
return in.readArray((uint32_t*) JS_GetFloat32ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_FLOAT64:
|
||||
return in.readArray((uint64_t*) JS_GetFloat64ArrayData(obj), nelems);
|
||||
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
|
||||
return in.readArray(JS_GetUint8ClampedArrayData(obj), nelems);
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
return false;
|
||||
}
|
||||
allObjs[placeholderIndex] = *vp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -908,6 +950,66 @@ JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
|
|||
return in.readArray(buffer.dataPointer(), nbytes);
|
||||
}
|
||||
|
||||
static size_t
|
||||
bytesPerTypedArrayElement(uint32_t arrayType)
|
||||
{
|
||||
switch (arrayType) {
|
||||
case TypedArray::TYPE_INT8:
|
||||
case TypedArray::TYPE_UINT8:
|
||||
case TypedArray::TYPE_UINT8_CLAMPED:
|
||||
return sizeof(uint8_t);
|
||||
case TypedArray::TYPE_INT16:
|
||||
case TypedArray::TYPE_UINT16:
|
||||
return sizeof(uint16_t);
|
||||
case TypedArray::TYPE_INT32:
|
||||
case TypedArray::TYPE_UINT32:
|
||||
case TypedArray::TYPE_FLOAT32:
|
||||
return sizeof(uint32_t);
|
||||
case TypedArray::TYPE_FLOAT64:
|
||||
return sizeof(uint64_t);
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the data for a structured clone version 1 ArrayBuffer, performing
|
||||
* endianness-conversion while reading.
|
||||
*/
|
||||
bool
|
||||
JSStructuredCloneReader::readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, Value *vp)
|
||||
{
|
||||
JS_ASSERT(arrayType <= TypedArray::TYPE_UINT8_CLAMPED);
|
||||
|
||||
uint32_t nbytes = nelems * bytesPerTypedArrayElement(arrayType);
|
||||
JSObject *obj = ArrayBufferObject::create(context(), nbytes);
|
||||
if (!obj)
|
||||
return false;
|
||||
vp->setObject(*obj);
|
||||
ArrayBufferObject &buffer = obj->asArrayBuffer();
|
||||
JS_ASSERT(buffer.byteLength() == nbytes);
|
||||
|
||||
switch (arrayType) {
|
||||
case TypedArray::TYPE_INT8:
|
||||
case TypedArray::TYPE_UINT8:
|
||||
case TypedArray::TYPE_UINT8_CLAMPED:
|
||||
return in.readArray((uint8_t*) buffer.dataPointer(), nelems);
|
||||
case TypedArray::TYPE_INT16:
|
||||
case TypedArray::TYPE_UINT16:
|
||||
return in.readArray((uint16_t*) buffer.dataPointer(), nelems);
|
||||
case TypedArray::TYPE_INT32:
|
||||
case TypedArray::TYPE_UINT32:
|
||||
case TypedArray::TYPE_FLOAT32:
|
||||
return in.readArray((uint32_t*) buffer.dataPointer(), nelems);
|
||||
case TypedArray::TYPE_FLOAT64:
|
||||
return in.readArray((uint64_t*) buffer.dataPointer(), nelems);
|
||||
default:
|
||||
JS_NOT_REACHED("unknown TypedArray type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::startRead(Value *vp)
|
||||
{
|
||||
|
@ -1035,6 +1137,14 @@ JSStructuredCloneReader::startRead(Value *vp)
|
|||
return false;
|
||||
break;
|
||||
|
||||
case SCTAG_TYPED_ARRAY_OBJECT:
|
||||
// readTypedArray adds the array to allObjs
|
||||
uint64_t arrayType;
|
||||
if (!in.read(&arrayType))
|
||||
return false;
|
||||
return readTypedArray(arrayType, data, vp);
|
||||
break;
|
||||
|
||||
default: {
|
||||
if (tag <= SCTAG_FLOAT_MAX) {
|
||||
double d = ReinterpretPairAsDouble(tag, data);
|
||||
|
@ -1044,10 +1154,10 @@ JSStructuredCloneReader::startRead(Value *vp)
|
|||
break;
|
||||
}
|
||||
|
||||
if (SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX) {
|
||||
if (!readTypedArray(tag, data, vp))
|
||||
return false;
|
||||
break;
|
||||
if (SCTAG_TYPED_ARRAY_V1_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_V1_MAX) {
|
||||
// A v1-format typed array
|
||||
// readTypedArray adds the array to allObjs
|
||||
return readTypedArray(TagToV1ArrayType(tag), data, vp, true);
|
||||
}
|
||||
|
||||
if (!callbacks || !callbacks->read) {
|
||||
|
|
|
@ -110,8 +110,9 @@ struct JSStructuredCloneReader {
|
|||
|
||||
bool checkDouble(double d);
|
||||
JSString *readString(uint32_t nchars);
|
||||
bool readTypedArray(uint32_t tag, uint32_t nelems, js::Value *vp);
|
||||
bool readTypedArray(uint32_t arrayType, uint32_t nelems, js::Value *vp, bool v1Read = false);
|
||||
bool readArrayBuffer(uint32_t nbytes, js::Value *vp);
|
||||
bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, js::Value *vp);
|
||||
bool readId(jsid *idp);
|
||||
bool startRead(js::Value *vp);
|
||||
|
||||
|
|
|
@ -65,9 +65,9 @@ function test() {
|
|||
checkPrototype(ctor);
|
||||
}
|
||||
|
||||
// Cloning should separately copy two TypedArrays backed by the same
|
||||
// ArrayBuffer. This also tests cloning TypedArrays where the arr->data
|
||||
// pointer is not 8-byte-aligned.
|
||||
// Two TypedArrays backed by the same ArrayBuffer should be cloned into two
|
||||
// TypedArrays still sharing a buffer. This also tests cloning TypedArrays
|
||||
// where the arr->data pointer is not 8-byte-aligned.
|
||||
|
||||
var base = Int8Array([0, 1, 2, 3]);
|
||||
b = [Int8Array(base.buffer, 0, 3), Int8Array(base.buffer, 1, 3)];
|
||||
|
@ -77,7 +77,27 @@ function test() {
|
|||
assertArraysEqual(b[0], Int8Array([0, -1, 2])); // shared with base
|
||||
assertArraysEqual(b[1], Int8Array([-1, 2, 3])); // shared with base
|
||||
assertArraysEqual(a[0], Int8Array([0, 1, -2])); // not shared with base
|
||||
assertArraysEqual(a[1], Int8Array([1, 2, 3])); // not shared with base or a[0]
|
||||
assertArraysEqual(a[1], Int8Array([1, -2, 3])); // not shared with base, shared with a[0]
|
||||
|
||||
assertEq(b[0].buffer, b[1].buffer);
|
||||
assertEq(b[1].byteOffset, 1);
|
||||
assertEq(b[1].byteLength, 3);
|
||||
assertEq(b[1].buffer.byteLength, 4);
|
||||
|
||||
// ArrayBuffer clones do not preserve properties
|
||||
|
||||
base = Int8Array([0, 1, 2, 3]);
|
||||
b = [Int8Array(base.buffer, 0, 3), Int8Array(base.buffer, 1, 3)];
|
||||
base.buffer.prop = "yes";
|
||||
base.buffer.loop = b[0];
|
||||
base.buffer.loops = [ b[0], b[1] ];
|
||||
a = deserialize(serialize(b));
|
||||
assertEq("prop" in a[0].buffer, false);
|
||||
assertEq("prop" in a[1].buffer, false);
|
||||
assertEq("loop" in a[0].buffer, false);
|
||||
assertEq("loop" in a[1].buffer, false);
|
||||
assertEq("loops" in a[0].buffer, false);
|
||||
assertEq("loops" in a[1].buffer, false);
|
||||
}
|
||||
|
||||
test();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
var captured = [];
|
||||
captured[0] = new Uint8Array([0, 0, 0, 0, 9, 0, 255, 255]);
|
||||
captured[1] = new Uint8Array([7, 0, 0, 0, 9, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[2] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[3] = new Uint8Array([0, 0, 0, 0, 0, 1, 255, 255]);
|
||||
captured[4] = new Uint8Array([100, 0, 0, 0, 0, 1, 255, 255, 1, 7, 49, 87, 97, 167, 145, 247, 193, 71, 241, 151, 33, 231, 81, 55, 129, 135, 177, 216, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[5] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[6] = new Uint8Array([0, 0, 0, 0, 1, 1, 255, 255]);
|
||||
captured[7] = new Uint8Array([100, 0, 0, 0, 1, 1, 255, 255, 1, 7, 49, 87, 97, 167, 145, 247, 193, 71, 241, 151, 33, 231, 81, 55, 129, 135, 177, 216, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[8] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[9] = new Uint8Array([0, 0, 0, 0, 2, 1, 255, 255]);
|
||||
captured[10] = new Uint8Array([100, 0, 0, 0, 2, 1, 255, 255, 1, 0, 7, 0, 49, 0, 87, 1, 97, 9, 167, 65, 145, 203, 247, 144, 193, 246, 71, 191, 241, 58, 151, 156, 33, 72, 231, 248, 81, 206, 55, 164, 129, 125, 135, 110, 177, 5, 216, 39, 224, 22, 0, 160, 0, 96, 0, 160, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[11] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[12] = new Uint8Array([0, 0, 0, 0, 3, 1, 255, 255]);
|
||||
captured[13] = new Uint8Array([100, 0, 0, 0, 3, 1, 255, 255, 1, 0, 7, 0, 49, 0, 87, 1, 97, 9, 167, 65, 145, 203, 247, 144, 193, 246, 71, 191, 241, 58, 151, 156, 33, 72, 231, 248, 81, 206, 55, 164, 129, 125, 135, 110, 177, 5, 216, 39, 224, 22, 0, 160, 0, 96, 0, 160, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[14] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[15] = new Uint8Array([0, 0, 0, 0, 4, 1, 255, 255]);
|
||||
captured[16] = new Uint8Array([100, 0, 0, 0, 4, 1, 255, 255, 1, 0, 0, 0, 7, 0, 0, 0, 49, 0, 0, 0, 87, 1, 0, 0, 97, 9, 0, 0, 167, 65, 0, 0, 145, 203, 1, 0, 247, 144, 12, 0, 193, 246, 87, 0, 71, 191, 103, 2, 241, 58, 214, 16, 151, 156, 219, 117, 33, 72, 1, 57, 231, 248, 8, 143, 81, 206, 62, 233, 55, 164, 183, 96, 129, 125, 5, 165, 135, 110, 38, 131, 177, 5, 13, 150, 216, 39, 91, 26, 224, 22, 126, 184, 0, 160, 114, 11, 0, 96, 34, 80, 0, 160, 240, 48, 0, 128, 148, 86, 0, 0, 16, 94, 0, 0, 112, 146, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[17] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[18] = new Uint8Array([0, 0, 0, 0, 5, 1, 255, 255]);
|
||||
captured[19] = new Uint8Array([100, 0, 0, 0, 5, 1, 255, 255, 1, 0, 0, 0, 7, 0, 0, 0, 49, 0, 0, 0, 87, 1, 0, 0, 97, 9, 0, 0, 167, 65, 0, 0, 145, 203, 1, 0, 247, 144, 12, 0, 193, 246, 87, 0, 71, 191, 103, 2, 241, 58, 214, 16, 151, 156, 219, 117, 33, 72, 1, 57, 231, 248, 8, 143, 81, 206, 62, 233, 55, 164, 183, 96, 129, 125, 5, 165, 135, 110, 38, 131, 177, 5, 13, 150, 216, 39, 91, 26, 224, 22, 126, 184, 0, 160, 114, 11, 0, 96, 34, 80, 0, 160, 240, 48, 0, 128, 148, 86, 0, 0, 16, 94, 0, 0, 112, 146, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
captured[20] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[21] = new Uint8Array([0, 0, 0, 0, 6, 1, 255, 255]);
|
||||
captured[22] = new Uint8Array([100, 0, 0, 0, 6, 1, 255, 255, 0, 0, 128, 63, 0, 0, 224, 64, 0, 0, 68, 66, 0, 128, 171, 67, 0, 16, 22, 69, 0, 78, 131, 70, 128, 200, 229, 71, 112, 15, 73, 73, 130, 237, 175, 74, 210, 239, 25, 76, 216, 177, 134, 77, 57, 183, 235, 78, 82, 64, 78, 80, 72, 120, 180, 81, 63, 233, 29, 83, 23, 44, 138, 84, 40, 205, 241, 85, 131, 147, 83, 87, 19, 33, 185, 88, 240, 252, 33, 90, 82, 189, 141, 91, 80, 11, 248, 92, 230, 9, 89, 94, 169, 232, 189, 95, 148, 43, 38, 97, 34, 102, 145, 98, 187, 114, 254, 99, 100, 164, 94, 101, 215, 207, 194, 102, 220, 117, 42, 104, 33, 39, 149, 105, 61, 130, 2, 107, 234, 99, 100, 108, 109, 215, 199, 109, 127, 220, 46, 111, 239, 0, 153, 112, 209, 224, 5, 114, 110, 73, 106, 115, 65, 0, 205, 116, 57, 96, 51, 118, 49, 244, 156, 119, 171, 85, 9, 121, 236, 85, 112, 122, 46, 75, 210, 123, 200, 1, 56, 125, 143, 1, 161, 126, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 128, 127, 0, 0, 192, 127]);
|
||||
captured[23] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[24] = new Uint8Array([0, 0, 0, 0, 7, 1, 255, 255]);
|
||||
captured[25] = new Uint8Array([100, 0, 0, 0, 7, 1, 255, 255, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 28, 64, 0, 0, 0, 0, 0, 128, 72, 64, 0, 0, 0, 0, 0, 112, 117, 64, 0, 0, 0, 0, 0, 194, 162, 64, 0, 0, 0, 0, 192, 105, 208, 64, 0, 0, 0, 0, 16, 185, 252, 64, 0, 0, 0, 0, 238, 33, 41, 65, 0, 0, 0, 64, 176, 253, 85, 65, 0, 0, 0, 56, 250, 61, 131, 65, 0, 0, 0, 241, 58, 214, 176, 65, 0, 0, 192, 37, 231, 118, 221, 65, 0, 0, 8, 65, 10, 200, 9, 66, 0, 0, 231, 248, 8, 143, 54, 66, 0, 32, 202, 217, 39, 189, 99, 66, 0, 220, 144, 222, 130, 69, 145, 66, 0, 129, 125, 5, 165, 57, 190, 66, 224, 208, 205, 100, 112, 114, 234, 66, 196, 22, 52, 88, 34, 36, 23, 67, 236, 147, 45, 13, 158, 63, 68, 67, 110, 225, 135, 75, 170, 183, 113, 67, 128, 202, 45, 4, 106, 1, 159, 67, 48, 17, 168, 195, 60, 33, 203, 67, 10, 15, 51, 43, 21, 189, 247, 67, 41, 173, 204, 133, 114, 197, 36, 68, 132, 23, 19, 53, 196, 44, 82, 68, 39, 105, 225, 92, 87, 206, 127, 68, 2, 60, 69, 113, 140, 212, 171, 68, 130, 148, 28, 227, 250, 89, 216, 68, 242, 1, 185, 134, 187, 78, 5, 69, 180, 225, 225, 21, 228, 164, 50, 69, 126, 165, 37, 147, 71, 80, 96, 69, 156, 225, 129, 65, 125, 140, 140, 69, 104, 165, 81, 153, 237, 250, 184, 69, 187, 112, 39, 230, 143, 219, 229, 69, 164, 130, 98, 233, 29, 32, 19, 70, 80, 50, 54, 44, 26, 188, 64, 70, 12, 216, 94, 205, 45, 73, 109, 70, 10, 253, 178, 19, 8, 160, 153, 70, 105, 157, 60, 17, 7, 108, 198, 70, 188, 9, 21, 47, 134, 158, 243, 70, 132, 104, 50, 105, 181, 42, 33, 71, 231, 54, 24, 120, 189, 10, 78, 71, 10, 48, 21, 201, 101, 73, 122, 71, 9, 138, 242, 15, 57, 0, 167, 71, 200, 56, 244, 237, 49, 32, 212, 71, 175, 177, 53, 176, 43, 156, 1, 72, 242, 246, 93, 116, 76, 209, 46, 72, 20, 56, 210, 229, 34, 247, 90, 72, 18, 241, 23, 137, 62, 152, 135, 72, 240, 242, 244, 183, 54, 165, 180, 72, 146, 84, 246, 224, 143, 16, 226, 72, 0, 20, 175, 201, 251, 156, 15, 73, 128, 49, 121, 80, 92, 169, 59, 73, 80, 11, 106, 198, 48, 52, 104, 73, 230, 201, 156, 173, 170, 45, 149, 73, 169, 48, 233, 87, 245, 135, 194, 73, 148, 10, 236, 172, 246, 54, 240, 73, 131, 18, 157, 174, 47, 96, 28, 74, 51, 112, 201, 184, 41, 212, 72, 74, 45, 66, 176, 129, 164, 185, 117, 74, 231, 57, 122, 241, 111, 2, 163, 74, 170, 242, 74, 243, 33, 162, 208, 74, 170, 40, 195, 105, 187, 27, 253, 74, 149, 195, 138, 252, 67, 120, 41, 75, 34, 107, 249, 124, 59, 73, 86, 75, 190, 61, 90, 13, 20, 128, 131, 75, 6, 246, 174, 139, 17, 16, 177, 75, 138, 46, 114, 180, 30, 220, 221, 75, 185, 232, 227, 221, 154, 32, 10, 76, 162, 107, 39, 130, 135, 220, 54, 76, 46, 126, 226, 145, 246, 0, 100, 76, 104, 46, 166, 191, 215, 128, 145, 76, 54, 209, 98, 143, 121, 161, 190, 76, 15, 119, 118, 93, 74, 205, 234, 76, 45, 168, 199, 17, 161, 115, 23, 77, 39, 179, 142, 239, 44, 133, 68, 77, 194, 220, 156, 81, 135, 244, 113, 77, 84, 130, 210, 206, 236, 107, 159, 77, 10, 50, 248, 52, 111, 126, 203, 77, 201, 43, 89, 78, 161, 14, 248, 77, 80, 6, 142, 36, 205, 12, 37, 78, 134, 69, 252, 127, 51, 107, 82, 78, 213, 188, 252, 15, 205, 29, 128, 78, 117, 74, 250, 219, 38, 52, 172, 78, 38, 1, 123, 0, 162, 173, 216, 78, 1, 161, 107, 192, 237, 151, 5, 79, 225, 44, 94, 8, 240, 228, 50, 79, 69, 103, 82, 7, 82, 136, 96, 79, 185, 52, 208, 140, 143, 238, 140, 79, 34, 46, 54, 155, 189, 80, 185, 79, 94, 104, 207, 231, 165, 38, 230, 79, 82, 123, 213, 42, 209, 97, 19, 80, 232, 203, 122, 5, 151, 245, 64, 80, 214, 228, 150, 73, 200, 173, 109, 80, 59, 8, 100, 64, 15, 248, 153, 80, 52, 135, 87, 88, 13, 185, 198, 80, 78, 150, 76, 173, 235, 225, 243, 80, 132, 3, 163, 55, 174, 101, 33, 81, 0, 0, 0, 0, 0, 0, 248, 127]);
|
||||
captured[26] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[27] = new Uint8Array([0, 0, 0, 0, 8, 1, 255, 255]);
|
||||
captured[28] = new Uint8Array([100, 0, 0, 0, 8, 1, 255, 255, 1, 7, 49, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0]);
|
||||
captured[29] = (new TypeError("unsupported type for structured data", "js1_8_5/extensions/clone-v1-typed-array.js", 19));
|
||||
captured[30] = new Uint8Array([0, 0, 0, 0, 7, 0, 255, 255, 0, 0, 0, 0, 3, 0, 255, 255, 3, 0, 0, 0, 0, 1, 255, 255, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 255, 255, 3, 0, 0, 0, 0, 1, 255, 255, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255]);
|
|
@ -0,0 +1,128 @@
|
|||
// |reftest| skip-if(!xulRuntime.shell)
|
||||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
// This file is a copy of clone-typed-array.js from before v2 structured clone
|
||||
// was implemented. If you run this test under a v1-writing engine with the
|
||||
// environment variable JS_RECORD_RESULTS set, then it will output a log of
|
||||
// structured clone buffers resulting from running this test. You can then use
|
||||
// that log as input to another run of this same test on a newer engine, to
|
||||
// verify that older-format structured clone data can be deserialized properly.
|
||||
|
||||
var old_serialize = serialize;
|
||||
var captured = [];
|
||||
|
||||
if ("JS_RECORD_RESULTS" in environment) {
|
||||
serialize = function(o) {
|
||||
var data;
|
||||
try {
|
||||
data = old_serialize(o);
|
||||
captured.push(data);
|
||||
return data;
|
||||
} catch(e) {
|
||||
captured.push(e);
|
||||
throw(e);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
loadRelativeToScript("clone-v1-typed-array-data.dat");
|
||||
serialize = function(d) {
|
||||
var data = captured.shift();
|
||||
if (data instanceof Error)
|
||||
throw(data);
|
||||
else
|
||||
return data;
|
||||
};
|
||||
}
|
||||
|
||||
function assertArraysEqual(a, b) {
|
||||
assertEq(a.constructor, b.constructor);
|
||||
assertEq(a.length, b.length);
|
||||
for (var i = 0; i < a.length; i++)
|
||||
assertEq(a[i], b[i]);
|
||||
}
|
||||
|
||||
function check(b) {
|
||||
var a = deserialize(serialize(b));
|
||||
assertArraysEqual(a, b);
|
||||
}
|
||||
|
||||
function checkPrototype(ctor) {
|
||||
var threw = false;
|
||||
try {
|
||||
serialize(ctor.prototype);
|
||||
throw new Error("serializing " + ctor.name + ".prototype should throw a TypeError");
|
||||
} catch (exc) {
|
||||
if (!(exc instanceof TypeError))
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Test cloning ArrayBuffer objects.
|
||||
check(ArrayBuffer(0));
|
||||
check(ArrayBuffer(7));
|
||||
checkPrototype(ArrayBuffer);
|
||||
|
||||
// Test cloning typed array objects.
|
||||
var ctors = [
|
||||
Int8Array,
|
||||
Uint8Array,
|
||||
Int16Array,
|
||||
Uint16Array,
|
||||
Int32Array,
|
||||
Uint32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
Uint8ClampedArray];
|
||||
|
||||
var b;
|
||||
for (var i = 0; i < ctors.length; i++) {
|
||||
var ctor = ctors[i];
|
||||
|
||||
// check empty array
|
||||
b = ctor(0);
|
||||
check(b);
|
||||
|
||||
// check array with some elements
|
||||
b = ctor(100);
|
||||
var v = 1;
|
||||
for (var j = 0; j < 100; j++) {
|
||||
b[j] = v;
|
||||
v *= 7;
|
||||
}
|
||||
b[99] = NaN; // check serializing NaNs too
|
||||
check(b);
|
||||
|
||||
// try the prototype
|
||||
checkPrototype(ctor);
|
||||
}
|
||||
|
||||
// Cloning should separately copy two TypedArrays backed by the same
|
||||
// ArrayBuffer. This also tests cloning TypedArrays where the arr->data
|
||||
// pointer is not 8-byte-aligned.
|
||||
|
||||
var base = Int8Array([0, 1, 2, 3]);
|
||||
b = [Int8Array(base.buffer, 0, 3), Int8Array(base.buffer, 1, 3)];
|
||||
var a = deserialize(serialize(b));
|
||||
base[1] = -1;
|
||||
a[0][2] = -2;
|
||||
assertArraysEqual(b[0], Int8Array([0, -1, 2])); // shared with base
|
||||
assertArraysEqual(b[1], Int8Array([-1, 2, 3])); // shared with base
|
||||
assertArraysEqual(a[0], Int8Array([0, 1, -2])); // not shared with base
|
||||
assertArraysEqual(a[1], Int8Array([1, 2, 3])); // not shared with base or a[0]
|
||||
}
|
||||
|
||||
test();
|
||||
reportCompare(0, 0, 'ok');
|
||||
|
||||
if ("JS_RECORD_RESULTS" in environment) {
|
||||
print("var captured = [];");
|
||||
for (var i in captured) {
|
||||
var s = "captured[" + i + "] = ";
|
||||
if (captured[i] instanceof Error)
|
||||
print(s + captured[i].toSource() + ";");
|
||||
else
|
||||
print(s + "new Uint8Array(" + [...captured[i]].toSource() + ");");
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче