/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: */ #include "jscompartment.h" #include "jsfriendapi.h" #include "jsapi-tests/tests.h" #include "jscompartmentinlines.h" using namespace js; BEGIN_TEST(testArrayBufferView_type) { CHECK((TestViewType<uint8_t, Create<JS_NewUint8Array, 7>, JS_GetObjectAsUint8Array, js::Scalar::Uint8, 7, 7>(cx))); CHECK((TestViewType<int8_t, Create<JS_NewInt8Array, 33>, JS_GetObjectAsInt8Array, js::Scalar::Int8, 33, 33>(cx))); CHECK((TestViewType<uint8_t, Create<JS_NewUint8ClampedArray, 7>, JS_GetObjectAsUint8ClampedArray, js::Scalar::Uint8Clamped, 7, 7>(cx))); CHECK((TestViewType<uint16_t, Create<JS_NewUint16Array, 3>, JS_GetObjectAsUint16Array, js::Scalar::Uint16, 3, 6>(cx))); CHECK((TestViewType<int16_t, Create<JS_NewInt16Array, 17>, JS_GetObjectAsInt16Array, js::Scalar::Int16, 17, 34>(cx))); CHECK((TestViewType<uint32_t, Create<JS_NewUint32Array, 15>, JS_GetObjectAsUint32Array, js::Scalar::Uint32, 15, 60>(cx))); CHECK((TestViewType<int32_t, Create<JS_NewInt32Array, 8>, JS_GetObjectAsInt32Array, js::Scalar::Int32, 8, 32>(cx))); CHECK((TestViewType<float, Create<JS_NewFloat32Array, 7>, JS_GetObjectAsFloat32Array, js::Scalar::Float32, 7, 28>(cx))); CHECK((TestViewType<double, Create<JS_NewFloat64Array, 9>, JS_GetObjectAsFloat64Array, js::Scalar::Float64, 9, 72>(cx))); CHECK((TestViewType<uint8_t, CreateDataView, JS_GetObjectAsArrayBufferView, js::Scalar::MaxTypedArrayViewType, 8, 8>(cx))); JS::Rooted<JS::Value> hasTypedObject(cx); EVAL("typeof TypedObject !== 'undefined'", &hasTypedObject); if (hasTypedObject.isTrue()) { JS::Rooted<JS::Value> tval(cx); EVAL("var T = new TypedObject.StructType({ x: TypedObject.uint32 });\n" "new T(new ArrayBuffer(4));", &tval); JS::Rooted<JSObject*> tobj(cx, &tval.toObject()); CHECK(!JS_IsArrayBufferViewObject(tobj)); } return true; } static JSObject* CreateDataView(JSContext* cx) { JS::Rooted<JSObject*> buffer(cx, JS_NewArrayBuffer(cx, 8)); if (!buffer) return nullptr; return JS_NewDataView(cx, buffer, 0, 8); } template<JSObject * CreateTypedArray(JSContext* cx, uint32_t length), size_t Length> static JSObject* Create(JSContext* cx) { return CreateTypedArray(cx, Length); } template<typename T, JSObject * CreateViewType(JSContext* cx), JSObject * GetObjectAs(JSObject* obj, uint32_t* length, bool* isSharedMemory, T** data), js::Scalar::Type ExpectedType, uint32_t ExpectedLength, uint32_t ExpectedByteLength> bool TestViewType(JSContext* cx) { JS::Rooted<JSObject*> obj(cx, CreateViewType(cx)); CHECK(obj); CHECK(JS_IsArrayBufferViewObject(obj)); CHECK(JS_GetArrayBufferViewType(obj) == ExpectedType); CHECK(JS_GetArrayBufferViewByteLength(obj) == ExpectedByteLength); { JS::AutoCheckCannotGC nogc; bool shared1; T* data1 = static_cast<T*>(JS_GetArrayBufferViewData(obj, &shared1, nogc)); T* data2; bool shared2; uint32_t len; CHECK(obj == GetObjectAs(obj, &len, &shared2, &data2)); CHECK(data1 == data2); CHECK(shared1 == shared2); CHECK(len == ExpectedLength); } JS::CompartmentOptions options; JS::RootedObject otherGlobal(cx, JS_NewGlobalObject(cx, basicGlobalClass(), nullptr, JS::DontFireOnNewGlobalHook, options)); CHECK(otherGlobal); JS::Rooted<JSObject*> buffer(cx); { AutoCompartment ac(cx, otherGlobal); buffer = JS_NewArrayBuffer(cx, 8); CHECK(buffer); CHECK(buffer->as<ArrayBufferObject>().byteLength() == 8); } CHECK(buffer->compartment() == otherGlobal->compartment()); CHECK(JS_WrapObject(cx, &buffer)); CHECK(buffer->compartment() == global->compartment()); JS::Rooted<JSObject*> dataview(cx, JS_NewDataView(cx, buffer, 4, 4)); CHECK(dataview); CHECK(dataview->is<ProxyObject>()); JS::Rooted<JS::Value> val(cx); val = ObjectValue(*dataview); CHECK(JS_SetProperty(cx, global, "view", val)); EVAL("view.buffer", &val); CHECK(val.toObject().is<ProxyObject>()); CHECK(dataview->compartment() == global->compartment()); JS::Rooted<JSObject*> otherView(cx, js::UncheckedUnwrap(dataview)); CHECK(otherView->compartment() == otherGlobal->compartment()); JS::Rooted<JSObject*> otherBuffer(cx, js::UncheckedUnwrap(&val.toObject())); CHECK(otherBuffer->compartment() == otherGlobal->compartment()); EVAL("Object.getPrototypeOf(view) === DataView.prototype", &val); CHECK(val.toBoolean() == true); return true; } END_TEST(testArrayBufferView_type)