| /* -*- 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) |