Backed out 5 changesets (bug 861925) so I can backout bug 900669 cleanly

Backed out changeset 8febf2f0e35d (bug 861925)
Backed out changeset e646195f32ae (bug 861925)
Backed out changeset 015a92e94c07 (bug 861925)
Backed out changeset 4546406915c1 (bug 861925)
Backed out changeset 63321a464309 (bug 861925)
This commit is contained in:
Wes Kocher 2013-10-15 18:51:50 -07:00
parent 75c28185a8
commit dd25f949c6
17 changed files with 244 additions and 758 deletions

View File

@ -48,9 +48,7 @@ typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w
// with error set to one of the JS_SCERR_* values.
typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid);
// The maximum supported structured-clone serialization format version. Note
// that this does not need to be bumped for Transferable-only changes, since
// they are never saved to persistent storage.
// The maximum supported structured-clone serialization format version.
#define JS_STRUCTURED_CLONE_VERSION 2
struct JSStructuredCloneCallbacks {

View File

@ -18,7 +18,6 @@
#include "jit/AsmJS.h"
#include "jit/AsmJSLink.h"
#include "js/StructuredClone.h"
#include "vm/ForkJoin.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
@ -31,10 +30,6 @@ using namespace JS;
using mozilla::ArrayLength;
// If fuzzingSafe is set, remove functionality that could cause problems with
// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
static bool fuzzingSafe = false;
static bool
GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
{
@ -1096,228 +1091,6 @@ SetIonAssertGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
class CloneBufferObject : public JSObject {
static const JSPropertySpec props_[2];
static const size_t DATA_SLOT = 0;
static const size_t LENGTH_SLOT = 1;
static const size_t NUM_SLOTS = 2;
public:
static const Class class_;
static CloneBufferObject *Create(JSContext *cx) {
RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_), nullptr, nullptr));
if (!obj)
return nullptr;
obj->setReservedSlot(DATA_SLOT, PrivateValue(nullptr));
obj->setReservedSlot(LENGTH_SLOT, Int32Value(0));
if (!JS_DefineProperties(cx, obj, props_))
return nullptr;
return &obj->as<CloneBufferObject>();
}
static CloneBufferObject *Create(JSContext *cx, JSAutoStructuredCloneBuffer *buffer) {
Rooted<CloneBufferObject*> obj(cx, Create(cx));
if (!obj)
return nullptr;
uint64_t *datap;
size_t nbytes;
buffer->steal(&datap, &nbytes);
obj->setData(datap);
obj->setNBytes(nbytes);
return obj;
}
uint64_t *data() const {
return static_cast<uint64_t*>(getReservedSlot(0).toPrivate());
}
void setData(uint64_t *aData) {
JS_ASSERT(!data());
setReservedSlot(DATA_SLOT, PrivateValue(aData));
}
size_t nbytes() const {
return getReservedSlot(LENGTH_SLOT).toInt32();
}
void setNBytes(size_t nbytes) {
JS_ASSERT(nbytes <= UINT32_MAX);
setReservedSlot(LENGTH_SLOT, Int32Value(nbytes));
}
// Discard an owned clone buffer.
void discard() {
if (data())
JS_ClearStructuredClone(data(), nbytes());
setReservedSlot(DATA_SLOT, PrivateValue(nullptr));
}
static bool
setCloneBuffer_impl(JSContext* cx, CallArgs args) {
if (args.length() != 1 || !args[0].isString()) {
JS_ReportError(cx,
"the first argument argument must be maxBytes, "
"maxMallocBytes, gcStackpoolLifespan, gcBytes or "
"gcNumber");
JS_ReportError(cx, "clonebuffer setter requires a single string argument");
return false;
}
if (fuzzingSafe) {
// A manually-created clonebuffer could easily trigger a crash
args.rval().setUndefined();
return true;
}
Rooted<CloneBufferObject*> obj(cx, &args.thisv().toObject().as<CloneBufferObject>());
obj->discard();
char *str = JS_EncodeString(cx, args[0].toString());
if (!str)
return false;
obj->setData(reinterpret_cast<uint64_t*>(str));
obj->setNBytes(JS_GetStringLength(args[0].toString()));
args.rval().setUndefined();
return true;
}
static bool
is(HandleValue v) {
return v.isObject() && v.toObject().is<CloneBufferObject>();
}
static bool
setCloneBuffer(JSContext* cx, unsigned int argc, JS::Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<is, setCloneBuffer_impl>(cx, args);
}
static bool
getCloneBuffer_impl(JSContext* cx, CallArgs args) {
Rooted<CloneBufferObject*> obj(cx, &args.thisv().toObject().as<CloneBufferObject>());
JS_ASSERT(args.length() == 0);
if (!obj->data()) {
args.rval().setUndefined();
return true;
}
bool hasTransferable;
if (!JS_StructuredCloneHasTransferables(obj->data(), obj->nbytes(), &hasTransferable))
return false;
if (hasTransferable) {
JS_ReportError(cx, "cannot retrieve structured clone buffer with transferables");
return false;
}
JSString *str = JS_NewStringCopyN(cx, reinterpret_cast<char*>(obj->data()), obj->nbytes());
if (!str)
return false;
args.rval().setString(str);
return true;
}
static bool
getCloneBuffer(JSContext* cx, unsigned int argc, JS::Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<is, getCloneBuffer_impl>(cx, args);
}
static void Finalize(FreeOp *fop, JSObject *obj) {
obj->as<CloneBufferObject>().discard();
}
};
const Class CloneBufferObject::class_ = {
"CloneBuffer", JSCLASS_HAS_RESERVED_SLOTS(CloneBufferObject::NUM_SLOTS),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
Finalize,
nullptr, /* checkAccess */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
JS_NULL_CLASS_EXT,
JS_NULL_OBJECT_OPS
};
const JSPropertySpec CloneBufferObject::props_[] = {
JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0),
JS_PS_END
};
static bool
Serialize(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
Value v = args.length() > 0 ? args[0] : UndefinedValue();
Value transferables = args.length() > 1 ? args[1] : UndefinedValue();
JSAutoStructuredCloneBuffer clonebuf;
if (!clonebuf.write(cx, v, transferables))
return false;
RootedObject obj(cx, CloneBufferObject::Create(cx, &clonebuf));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
}
static bool
Deserialize(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1 || !args[0].isObject()) {
JS_ReportError(cx, "deserialize requires a single clonebuffer argument");
return false;
}
if (!args[0].toObject().is<CloneBufferObject>()) {
JS_ReportError(cx, "deserialize requires a clonebuffer");
return false;
}
Rooted<CloneBufferObject*> obj(cx, &args[0].toObject().as<CloneBufferObject>());
// Clone buffer was already consumed?
if (!obj->data()) {
JS_ReportError(cx, "deserialize given invalid clone buffer "
"(transferables already consumed?)");
return false;
}
bool hasTransferable;
if (!JS_StructuredCloneHasTransferables(obj->data(), obj->nbytes(), &hasTransferable))
return false;
RootedValue deserialized(cx);
if (!JS_ReadStructuredClone(cx, obj->data(), obj->nbytes(),
JS_STRUCTURED_CLONE_VERSION, deserialized.address(), NULL, NULL)) {
return false;
}
args.rval().set(deserialized);
if (hasTransferable)
obj->discard();
return true;
}
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'compartment')",
@ -1523,23 +1296,11 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
" are valuable and should be generally enabled, however they can be very expensive for large\n"
" (asm.js) programs."),
JS_FN_HELP("serialize", Serialize, 1, 0,
"serialize(data, [transferables])",
" Serialize 'data' using JS_WriteStructuredClone. Returns a structured\n"
" clone buffer object."),
JS_FN_HELP("deserialize", Deserialize, 1, 0,
"deserialize(clonebuffer)",
" Deserialize data generated by serialize."),
JS_FS_HELP_END
};
bool
js::DefineTestingFunctions(JSContext *cx, HandleObject obj, bool fuzzingSafe_)
js::DefineTestingFunctions(JSContext *cx, HandleObject obj)
{
fuzzingSafe = fuzzingSafe_;
if (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0')
fuzzingSafe = true;
return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
}

View File

@ -12,7 +12,7 @@
namespace js {
bool
DefineTestingFunctions(JSContext *cx, HandleObject obj, bool fuzzingSafe);
DefineTestingFunctions(JSContext *cx, HandleObject obj);
bool
testingFunc_inParallelSection(JSContext *cx, unsigned argc, Value *vp);

View File

@ -233,8 +233,8 @@ MSG_DEF(JSMSG_UNUSED179, 179, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED180, 180, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED181, 181, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator")
MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 183, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 184, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
MSG_DEF(JSMSG_UNUSED183, 183, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED184, 184, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE, 185, 0, JSEXN_TYPEERR, "proxy can't report an extensible object as non-extensible")
MSG_DEF(JSMSG_UNUSED186, 186, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "")

View File

@ -224,12 +224,6 @@ class AutoArrayRooter : private AutoGCRooter {
template<class T>
class AutoVectorRooter : protected AutoGCRooter
{
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
/* Prevent overwriting of inline elements in vector. */
js::SkipRoot vectorRoot;
public:
explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -246,7 +240,6 @@ class AutoVectorRooter : protected AutoGCRooter
}
typedef T ElementType;
typedef typename VectorImpl::Range Range;
size_t length() const { return vector.length(); }
bool empty() const { return vector.empty(); }
@ -306,8 +299,6 @@ class AutoVectorRooter : protected AutoGCRooter
const T *end() const { return vector.end(); }
T *end() { return vector.end(); }
Range all() { return vector.all(); }
const T &back() const { return vector.back(); }
friend void AutoGCRooter::trace(JSTracer *trc);
@ -319,6 +310,12 @@ class AutoVectorRooter : protected AutoGCRooter
memset(t, 0, sizeof(T));
}
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
/* Prevent overwriting of inline elements in vector. */
js::SkipRoot vectorRoot;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
@ -338,7 +335,6 @@ class AutoHashMapRooter : protected AutoGCRooter
typedef Key KeyType;
typedef Value ValueType;
typedef typename HashMapImpl::Entry Entry;
typedef typename HashMapImpl::Lookup Lookup;
typedef typename HashMapImpl::Ptr Ptr;
typedef typename HashMapImpl::AddPtr AddPtr;

View File

@ -1018,7 +1018,7 @@ js::GetTestingFunctions(JSContext *cx)
if (!obj)
return nullptr;
if (!DefineTestingFunctions(cx, obj, false))
if (!DefineTestingFunctions(cx, obj))
return nullptr;
return obj;

View File

@ -1240,12 +1240,6 @@ JS_GetArrayBufferViewData(JSObject *obj);
extern JS_FRIEND_API(JSObject *)
JS_GetArrayBufferViewBuffer(JSObject *obj);
/*
* Set an ArrayBuffer's length to 0 and neuter all of its views.
*/
extern JS_FRIEND_API(void)
JS_NeuterArrayBuffer(JSObject *obj, JSContext *cx);
/*
* Check whether obj supports JS_GetDataView* APIs.
*/

View File

@ -3833,6 +3833,56 @@ WrapWithProto(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
static bool
Serialize(JSContext *cx, unsigned argc, jsval *vp)
{
jsval v = argc > 0 ? JS_ARGV(cx, vp)[0] : UndefinedValue();
uint64_t *datap;
size_t nbytes;
if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, nullptr, nullptr, UndefinedValue()))
return false;
JSObject *obj = JS_NewUint8Array(cx, nbytes);
if (!obj) {
JS_free(cx, datap);
return false;
}
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT((uintptr_t(tarr->viewData()) & 7) == 0);
js_memcpy(tarr->viewData(), datap, nbytes);
JS_ClearStructuredClone(datap, nbytes);
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(tarr));
return true;
}
static bool
Deserialize(JSContext *cx, unsigned argc, jsval *vp)
{
Rooted<jsval> v(cx, argc > 0 ? JS_ARGV(cx, vp)[0] : UndefinedValue());
JSObject *obj;
if (JSVAL_IS_PRIMITIVE(v) || !(obj = JSVAL_TO_OBJECT(v))->is<TypedArrayObject>()) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "deserialize");
return false;
}
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
if ((tarr->byteLength() & 7) != 0) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "deserialize");
return false;
}
if ((uintptr_t(tarr->viewData()) & 7) != 0) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_BAD_ALIGNMENT);
return false;
}
if (!JS_ReadStructuredClone(cx, (uint64_t *) tarr->viewData(), tarr->byteLength(),
JS_STRUCTURED_CLONE_VERSION, v.address(), nullptr, nullptr)) {
return false;
}
JS_SET_RVAL(cx, vp, v);
return true;
}
static JSObject *
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options);
@ -4309,6 +4359,14 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
"wrapWithProto(obj)",
" Wrap an object into a noop wrapper with prototype semantics."),
JS_FN_HELP("serialize", Serialize, 1, 0,
"serialize(sd)",
" Serialize sd using JS_WriteStructuredClone. Returns a TypedArray."),
JS_FN_HELP("deserialize", Deserialize, 1, 0,
"deserialize(a)",
" Deserialize data generated by serialize."),
JS_FN_HELP("newGlobal", NewGlobal, 1, 0,
"newGlobal([options])",
" Return a new global object in a new compartment. If options\n"
@ -5336,7 +5394,7 @@ NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options)
{
return nullptr;
}
if (!js::DefineTestingFunctions(cx, glob, fuzzingSafe))
if (!js::DefineTestingFunctions(cx, glob))
return nullptr;
if (!fuzzingSafe && !JS_DefineFunctionsWithHelp(cx, glob, fuzzing_unsafe_functions))
@ -5641,8 +5699,6 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
if (op->getBoolOption("fuzzing-safe"))
fuzzingSafe = true;
else
fuzzingSafe = (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0');
RootedObject glob(cx);
JS::CompartmentOptions options;

View File

@ -14,13 +14,8 @@ function assertThrows(f) {
throw new TypeError("Assertion failed: " + f + " did not throw as expected");
}
function byteArray(str) {
return [ c.charCodeAt(0) for (c of str.split('')) ];
}
// Don't allow forging bogus Date objects.
var mutated = byteArray(serialize(new Date(NaN)).clonebuffer);
var buf = serialize(new Date(NaN));
var a = [1/0, -1/0,
Number.MIN_VALUE, -Number.MIN_VALUE,
Math.PI, 1286523948674.5,
@ -29,11 +24,9 @@ var a = [1/0, -1/0,
for (var i = 0; i < a.length; i++) {
var n = a[i];
var nbuf = serialize(n);
var data = byteArray(nbuf.clonebuffer);
for (var j = 0; j < 8; j++)
mutated[j+8] = data[j];
nbuf.clonebuffer = String.fromCharCode.apply(null, mutated);
assertThrows(function () { deserialize(nbuf); });
buf[j + 8] = nbuf[j];
assertThrows(function () { deserialize(buf); });
}
reportCompare(0, 0);

View File

@ -208,7 +208,7 @@ function test() {
b = [];
b[255] = 1;
check(b);
assertEq(serialize(b).clonebuffer.length < 255, true);
assertEq(serialize(b).length < 255, true);
// Self-modifying object.
// This should never read through to b's prototype.

View File

@ -1,87 +0,0 @@
// |reftest| skip-if(!xulRuntime.shell)
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
function test() {
// Note: -8 and -200 will trigger asm.js link failures because 8 and 200
// bytes are below the minimum allowed size, and the buffer will not
// actually be converted to an asm.js buffer.
for (var size of [0, 8, 16, 200, 1000, 4096, -8, -200, -8192, -65536]) {
var buffer_ctor = (size < 0) ? AsmJSArrayBuffer : ArrayBuffer;
size = Math.abs(size);
var old = buffer_ctor(size);
var copy = deserialize(serialize(old, [old]));
assertEq(old.byteLength, 0);
assertEq(copy.byteLength, size);
var constructors = [ Int8Array,
Uint8Array,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
Uint8ClampedArray ];
for (var ctor of constructors) {
var buf = buffer_ctor(size);
var old_arr = ctor(buf);
assertEq(buf.byteLength, size);
assertEq(buf, old_arr.buffer);
assertEq(old_arr.length, size / old_arr.BYTES_PER_ELEMENT);
var copy_arr = deserialize(serialize(old_arr, [ buf ]));
assertEq(buf.byteLength, 0, "donor array buffer should be neutered");
assertEq(old_arr.length, 0, "donor typed array should be neutered");
assertEq(copy_arr.buffer.byteLength == size, true);
assertEq(copy_arr.length, size / old_arr.BYTES_PER_ELEMENT);
buf = null;
old_arr = null;
gc(); // Tickle the ArrayBuffer -> view management
}
for (var ctor of constructors) {
var buf = buffer_ctor(size);
var old_arr = ctor(buf);
var dv = DataView(buf); // Second view
var copy_arr = deserialize(serialize(old_arr, [ buf ]));
assertEq(buf.byteLength, 0, "donor array buffer should be neutered");
assertEq(old_arr.length, 0, "donor typed array should be neutered");
assertEq(dv.byteLength, 0, "all views of donor array buffer should be neutered");
buf = null;
old_arr = null;
gc(); // Tickle the ArrayBuffer -> view management
}
// Mutate the buffer during the clone operation. The modifications should be visible.
if (size >= 4) {
old = buffer_ctor(size);
var view = Int32Array(old);
view[0] = 1;
var mutator = { get foo() { view[0] = 2; } };
var copy = deserialize(serialize([ old, mutator ], [old]));
var viewCopy = Int32Array(copy[0]);
assertEq(view.length, 0); // Neutered
assertEq(viewCopy[0], 2);
}
// Neuter the buffer during the clone operation. Should throw an exception.
if (size >= 4) {
old = buffer_ctor(size);
var mutator = {
get foo() {
deserialize(serialize(old, [old]));
}
};
// The throw is not yet implemented, bug 919259.
//var copy = deserialize(serialize([ old, mutator ], [old]));
}
}
}
test();
reportCompare(0, 0, 'ok');

View File

@ -1,32 +1,32 @@
var captured = [];
captured[0] = serialize(0); captured[0].clonebuffer = String.fromCharCode(0, 0, 0, 0, 9, 0, 255, 255);
captured[1] = serialize(0); captured[1].clonebuffer = String.fromCharCode(7, 0, 0, 0, 9, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0);
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] = serialize(0); captured[3].clonebuffer = String.fromCharCode(0, 0, 0, 0, 0, 1, 255, 255);
captured[4] = serialize(0); captured[4].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[6].clonebuffer = String.fromCharCode(0, 0, 0, 0, 1, 1, 255, 255);
captured[7] = serialize(0); captured[7].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[9].clonebuffer = String.fromCharCode(0, 0, 0, 0, 2, 1, 255, 255);
captured[10] = serialize(0); captured[10].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[12].clonebuffer = String.fromCharCode(0, 0, 0, 0, 3, 1, 255, 255);
captured[13] = serialize(0); captured[13].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[15].clonebuffer = String.fromCharCode(0, 0, 0, 0, 4, 1, 255, 255);
captured[16] = serialize(0); captured[16].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[18].clonebuffer = String.fromCharCode(0, 0, 0, 0, 5, 1, 255, 255);
captured[19] = serialize(0); captured[19].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[21].clonebuffer = String.fromCharCode(0, 0, 0, 0, 6, 1, 255, 255);
captured[22] = serialize(0); captured[22].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[24].clonebuffer = String.fromCharCode(0, 0, 0, 0, 7, 1, 255, 255);
captured[25] = serialize(0); captured[25].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[27].clonebuffer = String.fromCharCode(0, 0, 0, 0, 8, 1, 255, 255);
captured[28] = serialize(0); captured[28].clonebuffer = String.fromCharCode(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[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] = serialize(0); captured[30].clonebuffer = String.fromCharCode(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);
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]);

View File

@ -120,11 +120,9 @@ if ("JS_RECORD_RESULTS" in environment) {
print("var captured = [];");
for (var i in captured) {
var s = "captured[" + i + "] = ";
if (captured[i] instanceof Error) {
if (captured[i] instanceof Error)
print(s + captured[i].toSource() + ";");
} else {
data = [ c.charCodeAt(0) for (c of captured[i].clonebuffer.split('')) ];
print(s + "serialize(0); captured[" + i + "].clonebuffer = String.fromCharCode(" + data.join(", ") + ");");
}
else
print(s + "new Uint8Array(" + [...captured[i]].toSource() + ");");
}
}

View File

@ -197,16 +197,3 @@ function referencesVia(from, edge, to) {
print(e);
return false;
}
// Note that AsmJS ArrayBuffers have a minimum size, currently 4096 bytes. If a
// smaller size is given, a regular ArrayBuffer will be returned instead.
function AsmJSArrayBuffer(size) {
var ab = new ArrayBuffer(size);
(new Function('global', 'foreign', 'buffer', '' +
' "use asm";' +
' var i32 = new global.Int32Array(buffer);' +
' function g() {};' +
' return g;' +
''))(this,null,ab);
return ab;
}

View File

@ -32,8 +32,6 @@
#include "mozilla/Endian.h"
#include "mozilla/FloatingPoint.h"
#include <algorithm>
#include "jsapi.h"
#include "jscntxt.h"
#include "jsdate.h"
@ -68,8 +66,8 @@ enum StructuredDataType {
SCTAG_STRING_OBJECT,
SCTAG_NUMBER_OBJECT,
SCTAG_BACK_REFERENCE_OBJECT,
SCTAG_DO_NOT_USE_1,
SCTAG_DO_NOT_USE_2,
SCTAG_TRANSFER_MAP_HEADER,
SCTAG_TRANSFER_MAP,
SCTAG_TYPED_ARRAY_OBJECT,
SCTAG_TYPED_ARRAY_V1_MIN = 0xFFFF0100,
SCTAG_TYPED_ARRAY_V1_INT8 = SCTAG_TYPED_ARRAY_V1_MIN + ScalarTypeRepresentation::TYPE_INT8,
@ -82,37 +80,12 @@ enum StructuredDataType {
SCTAG_TYPED_ARRAY_V1_FLOAT64 = SCTAG_TYPED_ARRAY_V1_MIN + ScalarTypeRepresentation::TYPE_FLOAT64,
SCTAG_TYPED_ARRAY_V1_UINT8_CLAMPED = SCTAG_TYPED_ARRAY_V1_MIN + ScalarTypeRepresentation::TYPE_UINT8_CLAMPED,
SCTAG_TYPED_ARRAY_V1_MAX = SCTAG_TYPED_ARRAY_V1_MIN + ScalarTypeRepresentation::TYPE_MAX - 1,
/*
* Define a separate range of numbers for Transferable-only tags, since
* they are not used for persistent clone buffers and therefore do not
* require bumping JS_STRUCTURED_CLONE_VERSION.
*/
SCTAG_TRANSFER_MAP_HEADER = 0xFFFF0200,
SCTAG_TRANSFER_MAP_ENTRY,
SCTAG_END_OF_BUILTIN_TYPES
};
// Data associated with an SCTAG_TRANSFER_MAP_HEADER that tells whether the
// contents have been read out yet or not.
enum TransferableMapHeader {
SCTAG_TM_UNREAD = 0,
SCTAG_TM_TRANSFERRED
};
enum TransferableObjectType {
// Transferable data has not been filled in yet
SCTAG_TM_UNFILLED = 0,
// Structured clone buffer does not yet own the data
SCTAG_TM_UNOWNED = 1,
// All values at least this large are owned by the clone buffer
SCTAG_TM_FIRST_OWNED = 2,
// Data is a pointer that can be freed
SCTAG_TM_ALLOC_DATA = 2,
SCTAG_TM_NOT_MARKED = 0,
SCTAG_TM_MARKED
};
namespace js {
@ -120,7 +93,6 @@ namespace js {
struct SCOutput {
public:
explicit SCOutput(JSContext *cx);
~SCOutput();
JSContext *context() const { return cx; }
@ -136,8 +108,7 @@ struct SCOutput {
bool extractBuffer(uint64_t **datap, size_t *sizep);
uint64_t count() const { return buf.length(); }
uint64_t *rawBuffer() { return buf.begin(); }
uint64_t count() { return buf.length(); }
private:
JSContext *cx;
@ -163,12 +134,6 @@ struct SCInput {
bool replace(uint64_t u);
bool replacePair(uint32_t tag, uint32_t data);
uint64_t *tell() const { return point; }
void seek(uint64_t *pos) {
JS_ASSERT(pos <= end);
point = pos;
}
template <class T>
bool readArray(T *p, size_t nelems);
@ -239,7 +204,8 @@ struct JSStructuredCloneWriter {
memory(out.context()), callbacks(cb), closure(cbClosure),
transferable(out.context(), tVal), transferableObjects(out.context()) { }
bool init() { return parseTransferable() && memory.init() && writeTransferMap(); }
bool init() { return transferableObjects.init() && parseTransferable() &&
memory.init() && writeTransferMap(); }
bool write(const js::Value &v);
@ -260,7 +226,6 @@ struct JSStructuredCloneWriter {
bool parseTransferable();
void reportErrorTransferable();
bool transferOwnership();
inline void checkStack();
@ -293,7 +258,7 @@ struct JSStructuredCloneWriter {
// List of transferable objects
JS::RootedValue transferable;
JS::AutoObjectVector transferableObjects;
js::AutoObjectHashSet transferableObjects;
friend bool JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::Value v);
};
@ -330,47 +295,35 @@ ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
return r.read(vp);
}
// This may acquire new ways of discarding transfer map entries as new
// Transferables are implemented.
static void
DiscardEntry(uint32_t mapEntryDescriptor, const uint64_t *ptr)
bool
ClearStructuredClone(const uint64_t *data, size_t nbytes)
{
JS_ASSERT(mapEntryDescriptor == SCTAG_TM_ALLOC_DATA);
uint64_t u = LittleEndian::readUint64(ptr);
js_free(reinterpret_cast<void*>(u));
}
static void
Discard(const uint64_t *begin, const uint64_t *end)
{
const uint64_t *point = begin;
const uint64_t *point = data;
const uint64_t *end = data + nbytes / 8;
uint64_t u = LittleEndian::readUint64(point++);
uint32_t tag = uint32_t(u >> 32);
if (tag != SCTAG_TRANSFER_MAP_HEADER)
return;
if (TransferableMapHeader(u) == SCTAG_TM_TRANSFERRED)
return;
uint64_t numTransferables = LittleEndian::readUint64(point++);
while (numTransferables--) {
if (tag == SCTAG_TRANSFER_MAP_HEADER) {
if ((TransferableMapHeader)uint32_t(u) == SCTAG_TM_NOT_MARKED) {
while (point != end) {
uint64_t u = LittleEndian::readUint64(point++);
JS_ASSERT(uint32_t(u >> 32) == SCTAG_TRANSFER_MAP_ENTRY);
uint32_t mapEntryDescriptor = uint32_t(u);
if (mapEntryDescriptor >= SCTAG_TM_FIRST_OWNED) {
DiscardEntry(mapEntryDescriptor, point);
point += 2; // Pointer and userdata
uint32_t tag = uint32_t(u >> 32);
if (tag == SCTAG_TRANSFER_MAP) {
u = LittleEndian::readUint64(point++);
js_free(reinterpret_cast<void*>(u));
} else {
// The only things in the transfer map should be
// SCTAG_TRANSFER_MAP tags paired with pointers. If we find
// any other tag, we've walked off the end of the transfer
// map.
break;
}
}
}
}
}
static void
ClearStructuredClone(const uint64_t *data, size_t nbytes)
{
JS_ASSERT(nbytes % 8 == 0);
Discard(data, data + nbytes / 8);
js_free(const_cast<uint64_t*>(data));
js_free((void *)data);
return true;
}
bool
@ -381,14 +334,15 @@ StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes, bool *has
if (data) {
uint64_t u = LittleEndian::readUint64(data);
uint32_t tag = uint32_t(u >> 32);
if (tag == SCTAG_TRANSFER_MAP_HEADER)
if (tag == SCTAG_TRANSFER_MAP_HEADER) {
*hasTransferable = true;
}
}
return true;
}
} /* namespace js */
}
static inline uint64_t
PairToUInt64(uint32_t tag, uint32_t data)
@ -497,7 +451,6 @@ template <typename T>
static void
copyAndSwapFromLittleEndian(T *dest, const void *src, size_t nelems)
{
if (nelems > 0)
NativeEndian::copyAndSwapFromLittleEndian(dest, src, nelems);
}
@ -553,12 +506,6 @@ SCInput::readPtr(void **p)
SCOutput::SCOutput(JSContext *cx) : cx(cx), buf(cx) {}
SCOutput::~SCOutput()
{
// Free any transferable data left lying around in the buffer
Discard(rawBuffer(), rawBuffer() + count());
}
bool
SCOutput::write(uint64_t u)
{
@ -618,7 +565,6 @@ template <typename T>
static void
copyAndSwapToLittleEndian(void *dest, const T *src, size_t nelems)
{
if (nelems > 0)
NativeEndian::copyAndSwapToLittleEndian(dest, src, nelems);
}
@ -686,7 +632,7 @@ JS_STATIC_ASSERT(JSString::MAX_LENGTH < UINT32_MAX);
bool
JSStructuredCloneWriter::parseTransferable()
{
MOZ_ASSERT(transferableObjects.empty(), "parseTransferable called with stale data");
transferableObjects.clear();
if (JSVAL_IS_NULL(transferable) || JSVAL_IS_VOID(transferable))
return true;
@ -696,22 +642,21 @@ JSStructuredCloneWriter::parseTransferable()
return false;
}
JSContext *cx = context();
RootedObject array(cx, &transferable.toObject());
if (!JS_IsArrayObject(cx, array)) {
RootedObject array(context(), &transferable.toObject());
if (!JS_IsArrayObject(context(), array)) {
reportErrorTransferable();
return false;
}
uint32_t length;
if (!JS_GetArrayLength(cx, array, &length)) {
if (!JS_GetArrayLength(context(), array, &length)) {
return false;
}
RootedValue v(context());
for (uint32_t i = 0; i < length; ++i) {
if (!JS_GetElement(cx, array, i, &v)) {
if (!JS_GetElement(context(), array, i, &v)) {
return false;
}
@ -722,7 +667,7 @@ JSStructuredCloneWriter::parseTransferable()
JSObject* tObj = CheckedUnwrap(&v.toObject());
if (!tObj) {
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_UNWRAP_DENIED);
JS_ReportError(context(), "Permission denied to access object");
return false;
}
if (!tObj->is<ArrayBufferObject>()) {
@ -730,13 +675,13 @@ JSStructuredCloneWriter::parseTransferable()
return false;
}
// No duplicates allowed
if (std::find(transferableObjects.begin(), transferableObjects.end(), tObj) != transferableObjects.end()) {
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_DUP_TRANSFERABLE);
// No duplicate:
if (transferableObjects.has(tObj)) {
reportErrorTransferable();
return false;
}
if (!transferableObjects.append(tObj))
if (!transferableObjects.putNew(tObj))
return false;
}
@ -748,8 +693,6 @@ JSStructuredCloneWriter::reportErrorTransferable()
{
if (callbacks && callbacks->reportError)
return callbacks->reportError(context(), JS_SCERR_TRANSFERABLE);
else
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_NOT_TRANSFERABLE);
}
bool
@ -951,29 +894,23 @@ JSStructuredCloneWriter::startWrite(const Value &v)
bool
JSStructuredCloneWriter::writeTransferMap()
{
if (transferableObjects.empty())
return true;
if (!out.writePair(SCTAG_TRANSFER_MAP_HEADER, (uint32_t)SCTAG_TM_UNREAD))
if (!transferableObjects.empty()) {
if (!out.writePair(SCTAG_TRANSFER_MAP_HEADER, (uint32_t)SCTAG_TM_NOT_MARKED))
return false;
if (!out.write(transferableObjects.length()))
return false;
for (JS::AutoObjectVector::Range tr = transferableObjects.all();
!tr.empty(); tr.popFront())
{
JSObject *obj = tr.front();
for (HashSet<JSObject*>::Range r = transferableObjects.all();
!r.empty(); r.popFront()) {
JSObject *obj = r.front();
if (!memory.put(obj, memory.count()))
return false;
// Emit a placeholder pointer. We will steal the data and neuter the
// transferable later.
if (!out.writePair(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_UNFILLED) ||
!out.writePtr(NULL) ||
!out.write(0))
{
void *content;
uint8_t *data;
if (!JS_StealArrayBufferContents(context(), obj, &content, &data))
return false;
if (!out.writePair(SCTAG_TRANSFER_MAP, 0) || !out.writePtr(content))
return false;
}
}
@ -981,43 +918,6 @@ JSStructuredCloneWriter::writeTransferMap()
return true;
}
bool
JSStructuredCloneWriter::transferOwnership()
{
if (transferableObjects.empty())
return true;
// Walk along the transferables and the transfer map at the same time,
// grabbing out pointers from the transferables and stuffing them into the
// transfer map.
uint64_t *point = out.rawBuffer();
JS_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_HEADER);
point++;
JS_ASSERT(LittleEndian::readUint64(point) == transferableObjects.length());
point++;
for (JS::AutoObjectVector::Range tr = transferableObjects.all();
!tr.empty();
tr.popFront())
{
void *content;
uint8_t *data;
if (!JS_StealArrayBufferContents(context(), tr.front(), &content, &data))
return false; // Destructor will clean up the already-transferred data
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_ENTRY);
LittleEndian::writeUint64(point++, PairToUInt64(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_ALLOC_DATA));
LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(content));
LittleEndian::writeUint64(point++, 0);
}
JS_ASSERT(point <= out.rawBuffer() + out.count());
JS_ASSERT_IF(point < out.rawBuffer() + out.count(),
uint32_t(LittleEndian::readUint64(point) >> 32) != SCTAG_TRANSFER_MAP_ENTRY);
return true;
}
bool
JSStructuredCloneWriter::write(const Value &v)
{
@ -1061,7 +961,8 @@ JSStructuredCloneWriter::write(const Value &v)
}
memory.clear();
return transferOwnership();
return true;
}
bool
@ -1387,7 +1288,7 @@ JSStructuredCloneReader::startRead(Value *vp)
"invalid input");
return false;
case SCTAG_TRANSFER_MAP_ENTRY:
case SCTAG_TRANSFER_MAP:
// A map cannot be here but just at the beginning of the buffer.
JS_ReportErrorNumber(context(), js_GetErrorMessage, nullptr,
JSMSG_SC_BAD_SERIALIZED_DATA,
@ -1473,57 +1374,37 @@ JSStructuredCloneReader::readId(jsid *idp)
bool
JSStructuredCloneReader::readTransferMap()
{
uint64_t *headerPos = in.tell();
uint32_t tag, data;
if (!in.getPair(&tag, &data))
return false;
if (tag != SCTAG_TRANSFER_MAP_HEADER || TransferableMapHeader(data) == SCTAG_TM_TRANSFERRED)
if (tag != SCTAG_TRANSFER_MAP_HEADER ||
(TransferableMapHeader)data == SCTAG_TM_MARKED)
return true;
uint64_t numTransferables;
MOZ_ALWAYS_TRUE(in.readPair(&tag, &data));
if (!in.read(&numTransferables))
if (!in.replacePair(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_MARKED))
return false;
for (uint64_t i = 0; i < numTransferables; i++) {
uint64_t *pos = in.tell();
if (!in.readPair(&tag, &data))
return false;
JS_ASSERT(tag == SCTAG_TRANSFER_MAP_ENTRY);
JS_ASSERT(data == SCTAG_TM_ALLOC_DATA);
void *content;
if (!in.readPtr(&content))
while (1) {
if (!in.getPair(&tag, &data))
return false;
uint64_t userdata;
if (!in.read(&userdata))
if (tag != SCTAG_TRANSFER_MAP)
break;
void *content;
if (!in.readPair(&tag, &data) || !in.readPtr(&content))
return false;
JSObject *obj = JS_NewArrayBufferWithContents(context(), content);
if (!obj)
return false;
// Rewind to the SCTAG_TRANSFER_MAP_ENTRY and mark this entry as unowned by
// the input buffer.
uint64_t *next = in.tell();
in.seek(pos);
MOZ_ALWAYS_TRUE(in.replacePair(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_UNOWNED));
in.seek(next);
if (!allObjs.append(ObjectValue(*obj)))
if (!obj || !allObjs.append(ObjectValue(*obj)))
return false;
}
// Mark the whole transfer map as consumed
uint64_t *endPos = in.tell();
in.seek(headerPos);
MOZ_ALWAYS_TRUE(in.replacePair(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_TRANSFERRED));
in.seek(endPos);
return true;
}
@ -1598,8 +1479,7 @@ JS_WriteStructuredClone(JSContext *cx, JS::Value valueArg, uint64_t **bufp, size
JS_PUBLIC_API(bool)
JS_ClearStructuredClone(const uint64_t *data, size_t nbytes)
{
ClearStructuredClone(data, nbytes);
return true;
return ClearStructuredClone(data, nbytes);
}
JS_PUBLIC_API(bool)

View File

@ -244,7 +244,7 @@ AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, uint8_t *initda
memcpy(newheader->elements(), initdata, nbytes);
// we rely on this being correct
ArrayBufferObject::updateElementsHeader(newheader, nbytes);
ArrayBufferObject::setElementsHeader(newheader, nbytes);
return newheader;
}
@ -274,7 +274,7 @@ ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes, uint8_t *co
memset(elements, 0, bytes);
}
initElementsHeader(getElementsHeader(), bytes);
setElementsHeader(getElementsHeader(), bytes);
return true;
}
@ -297,7 +297,7 @@ PostBarrierTypedArrayObject(JSObject *obj)
// JS_USE_NEW_OBJECT_REPRESENTATION pending, since it will solve this much
// more cleanly.
struct OldObjectRepresentationHack {
uint32_t flags;
uint32_t capacity;
uint32_t initializedLength;
EncapsulatedPtr<ArrayBufferViewObject> views;
};
@ -329,24 +329,6 @@ GetViewListRef(ArrayBufferObject *obj)
return reinterpret_cast<OldObjectRepresentationHack*>(obj->getElementsHeader())->views;
}
void
ArrayBufferObject::neuterViews(JSContext *maybecx)
{
ArrayBufferViewObject *view;
for (view = GetViewList(this); view; view = view->nextView()) {
view->neuter();
// Notify compiled jit code that the base pointer has moved.
if (maybecx)
MarkObjectStateChange(maybecx, view);
}
// neuterAsmJSArrayBuffer adjusts state specific to the ArrayBuffer data
// itself, but it only affects the behavior of views
if (isAsmJSArrayBuffer())
ArrayBufferObject::neuterAsmJSArrayBuffer(*this);
}
void
ArrayBufferObject::changeContents(JSContext *maybecx, ObjectElements *newHeader)
{
@ -366,35 +348,20 @@ ArrayBufferObject::changeContents(JSContext *maybecx, ObjectElements *newHeader)
MarkObjectStateChange(maybecx, view);
}
// The list of views in the old header is reachable if the contents are
// being transferred, so NULL it out
SetViewList(this, NULL);
// Change to the new header (now, so we can use SetViewList).
elements = newHeader->elements();
initElementsHeader(newHeader, byteLengthCopy);
InitViewList(this, viewListHead);
}
void
ArrayBufferObject::neuter(JSContext *cx)
{
JS_ASSERT(cx);
if (hasDynamicElements() && !isAsmJSArrayBuffer()) {
ObjectElements *oldHeader = getElementsHeader();
changeContents(cx, ObjectElements::fromElements(fixedElements()));
FreeOp fop(cx->runtime(), false);
fop.free_(oldHeader);
}
uint32_t byteLen = 0;
updateElementsHeader(getElementsHeader(), byteLen);
// Initialize 'newHeader'.
ArrayBufferObject::setElementsHeader(newHeader, byteLengthCopy);
SetViewList(this, viewListHead);
}
bool
ArrayBufferObject::copyData(JSContext *maybecx)
ArrayBufferObject::uninlineData(JSContext *maybecx)
{
if (hasDynamicElements())
return true;
ObjectElements *newHeader = AllocateArrayBufferContents(maybecx, byteLength(), dataPointer());
if (!newHeader)
return false;
@ -403,36 +370,6 @@ ArrayBufferObject::copyData(JSContext *maybecx)
return true;
}
bool
ArrayBufferObject::ensureNonInline(JSContext *maybecx)
{
if (hasDynamicElements())
return true;
return copyData(maybecx);
}
// If the ArrayBuffer already contains dynamic contents, hand them back.
// Otherwise, allocate some new contents and copy the data over, but in no case
// modify the original ArrayBuffer. (Also, any allocated contents will have no
// views linked to in its header.)
ObjectElements *
ArrayBufferObject::getTransferableContents(JSContext *maybecx, bool *callerOwns)
{
if (hasDynamicElements() && !isAsmJSArrayBuffer()) {
*callerOwns = false;
return getElementsHeader();
}
uint32_t byteLen = byteLength();
ObjectElements *newheader = AllocateArrayBufferContents(maybecx, byteLen, dataPointer());
if (!newheader)
return NULL;
initElementsHeader(newheader, byteLen);
*callerOwns = true;
return newheader;
}
#if defined(JS_ION) && defined(JS_CPU_X64)
// To avoid dynamically checking bounds on each load/store, asm.js code relies
// on the SIGSEGV handler in AsmJSSignalHandlers.cpp. However, this only works
@ -542,9 +479,8 @@ ArrayBufferObject::neuterAsmJSArrayBuffer(ArrayBufferObject &buffer)
bool
ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer)
{
if (!buffer->copyData(cx))
if (!buffer->uninlineData(cx))
return false;
JS_ASSERT(buffer->hasDynamicElements());
buffer->getElementsHeader()->setIsAsmJSArrayBuffer();
return true;
@ -661,28 +597,41 @@ ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp
}
bool
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents, uint8_t **data)
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data)
{
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
// Make the data stealable
bool own;
ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer.getTransferableContents(cx, &own));
if (!header)
return false;
ArrayBufferViewObject *views = GetViewList(&buffer);
js::ObjectElements *header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
if (buffer.hasDynamicElements() && !buffer.isAsmJSArrayBuffer()) {
SetViewList(&buffer, nullptr);
*contents = header;
*data = reinterpret_cast<uint8_t *>(header + 1);
*data = buffer.dataPointer();
// Neuter the views, which may also mprotect(PROT_NONE) the buffer. So do
// it after copying out the data.
buffer.neuterViews(cx);
if (!own) {
// If header has dynamically allocated elements, revert it back to
// fixed-element storage before neutering it.
buffer.changeContents(cx, ObjectElements::fromElements(buffer.fixedElements()));
buffer.setFixedElements();
header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
} else {
uint32_t length = buffer.byteLength();
js::ObjectElements *newheader =
AllocateArrayBufferContents(cx, length, buffer.dataPointer());
if (!newheader) {
js_ReportOutOfMemory(cx);
return false;
}
buffer.neuter(cx);
ArrayBufferObject::setElementsHeader(newheader, length);
*contents = newheader;
*data = reinterpret_cast<uint8_t *>(newheader + 1);
if (buffer.isAsmJSArrayBuffer())
ArrayBufferObject::neuterAsmJSArrayBuffer(buffer);
}
// Neuter the donor ArrayBufferObject and all views of it
ArrayBufferObject::setElementsHeader(header, 0);
InitViewList(&buffer, views);
for (ArrayBufferViewObject *view = views; view; view = view->nextView())
view->neuter();
return true;
}
@ -4017,19 +3966,11 @@ JS_GetArrayBufferData(JSObject *obj)
if (!obj)
return nullptr;
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
if (!buffer.ensureNonInline(NULL))
if (!buffer.uninlineData(nullptr))
return nullptr;
return buffer.dataPointer();
}
JS_FRIEND_API(void)
JS_NeuterArrayBuffer(JSObject *obj, JSContext *cx)
{
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
buffer.neuterViews(cx);
buffer.neuter(cx);
}
JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
{
@ -4056,7 +3997,7 @@ JS_AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents,
if (!header)
return false;
ArrayBufferObject::updateElementsHeader(header, nbytes);
ArrayBufferObject::setElementsHeader(header, nbytes);
*contents = header;
*data = reinterpret_cast<uint8_t*>(header->elements());
@ -4070,7 +4011,7 @@ JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents
if (!header)
return false;
ArrayBufferObject::initElementsHeader(header, nbytes);
ArrayBufferObject::setElementsHeader(header, nbytes);
*contents = header;
*data = reinterpret_cast<uint8_t*>(header->elements());

View File

@ -146,7 +146,8 @@ class ArrayBufferObject : public JSObject
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data);
static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {
static void setElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->flags = 0;
header->initializedLength = bytes;
// NB: one or both of these fields is clobbered by GetViewList to store
@ -156,11 +157,6 @@ class ArrayBufferObject : public JSObject
header->capacity = 0;
}
static void initElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->flags = 0;
updateElementsHeader(header, bytes);
}
static uint32_t headerInitializedLength(const js::ObjectElements *header) {
return header->initializedLength;
}
@ -168,48 +164,22 @@ class ArrayBufferObject : public JSObject
void addView(ArrayBufferViewObject *view);
bool allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = nullptr);
void changeContents(JSContext *cx, ObjectElements *newHeader);
/*
* Copy the data into freshly-allocated memory. Used when un-inlining or
* when converting an ArrayBuffer to an AsmJS (MMU-assisted) ArrayBuffer.
*/
bool copyData(JSContext *maybecx);
/*
* Ensure data is not stored inline in the object. Used when handing back a
* Ensure that the data is not stored inline. Used when handing back a
* GC-safe pointer.
*/
bool ensureNonInline(JSContext *maybecx);
bool uninlineData(JSContext *cx);
uint32_t byteLength() const {
return getElementsHeader()->initializedLength;
}
/*
* Return the contents of an ArrayBuffer without modifying the ArrayBuffer
* itself. Set *callerOwns to true if the caller has the only pointer to
* the returned contents (which is the case for inline or asm.js buffers),
* and false if the ArrayBuffer still owns the pointer.
*/
ObjectElements *getTransferableContents(JSContext *maybecx, bool *callerOwns);
/*
* Neuter all views of an ArrayBuffer.
*/
void neuterViews(JSContext *maybecx);
inline uint8_t * dataPointer() const {
return (uint8_t *) elements;
}
/*
* Discard the ArrayBuffer contents. For asm.js buffers, at least, should
* be called after neuterViews().
*/
void neuter(JSContext *maybecx);
/*
* Check if the arrayBuffer contains any data. This will return false for
* ArrayBuffer.prototype and neutered ArrayBuffers.
@ -551,7 +521,6 @@ class DataViewObject : public ArrayBufferViewObject
static bool fun_setFloat64(JSContext *cx, unsigned argc, Value *vp);
static JSObject *initClass(JSContext *cx);
static void neuter(JSObject *view);
static bool getDataPointer(JSContext *cx, Handle<DataViewObject*> obj,
CallArgs args, size_t typeSize, uint8_t **data);
template<typename NativeType>