1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
5 /* This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "jsfriendapi.h"
11 #include "js/ArrayBuffer.h" // JS::NewArrayBuffer
12 #include "js/experimental/TypedData.h" // JS_GetArrayBufferView{Type,ByteLength,Data}, JS_GetObjectAsArrayBufferView, JS_GetObjectAs{{Ui,I}nt{8,16,32},Float{32,64}}Array, JS_IsArrayBufferViewObject, JS_NewDataView, JS_New{{Ui,I}nt{8,16,32},Float{32,64},Uint8Clamped}Array
13 #include "js/GlobalObject.h" // JS_NewGlobalObject
14 #include "js/PropertyAndElement.h" // JS_SetProperty
15 #include "js/ScalarType.h" // js::Scalar::Type
16 #include "jsapi-tests/tests.h"
17 #include "vm/ProxyObject.h"
19 #include "vm/Uint8Clamped.h" // js::uint8_clamped_t
21 #include "vm/JSObject-inl.h"
22 #include "vm/Realm-inl.h"
23 #include "vm/TypedArrayObject-inl.h" // TypeIDOfType
27 template <class ViewType
>
28 static JSObject
* Create(JSContext
* cx
, size_t len
) {
29 return ViewType::create(cx
, len
).asObject();
33 JSObject
* Create
<JS::DataView
>(JSContext
* cx
, size_t len
) {
34 JS::Rooted
<JSObject
*> buffer(cx
, JS::NewArrayBuffer(cx
, len
));
38 return JS_NewDataView(cx
, buffer
, 0, len
);
46 #define INT_TYPE(ExternalType, NativeType, Name) \
48 struct InternalType<JS::TypedArray<js::Scalar::Name>> { \
49 using Type = NativeType; \
51 JS_FOR_EACH_TYPED_ARRAY(INT_TYPE
)
54 BEGIN_TEST(testArrayBufferView_type
) {
55 CHECK((TestViewType
<JS::TypedArray
<Scalar::Uint8
>, 7, 7>(cx
)));
56 CHECK((TestViewType
<JS::TypedArray
<Scalar::Int8
>, 33, 33>(cx
)));
57 CHECK((TestViewType
<JS::TypedArray
<Scalar::Uint8Clamped
>, 7, 7>(cx
)));
58 CHECK((TestViewType
<JS::TypedArray
<Scalar::Uint16
>, 3, 6>(cx
)));
59 CHECK((TestViewType
<JS::TypedArray
<Scalar::Int16
>, 17, 34>(cx
)));
60 CHECK((TestViewType
<JS::TypedArray
<Scalar::Uint32
>, 15, 60>(cx
)));
61 CHECK((TestViewType
<JS::TypedArray
<Scalar::Int32
>, 8, 32>(cx
)));
62 CHECK((TestViewType
<JS::TypedArray
<Scalar::Float32
>, 7, 28>(cx
)));
63 CHECK((TestViewType
<JS::TypedArray
<Scalar::Float64
>, 9, 72>(cx
)));
64 CHECK((TestViewType
<JS::DataView
, 8, 8>(cx
)));
71 static constexpr js::Scalar::Type value
= js::Scalar::MaxTypedArrayViewType
;
74 template <js::Scalar::Type EType
>
75 struct ScalarTypeOf
<JS::TypedArray
<EType
>> {
76 static constexpr js::Scalar::Type value
= EType
;
78 template <class ViewType
, uint32_t ExpectedLength
, uint32_t ExpectedByteLength
>
79 bool TestViewType(JSContext
* cx
) {
80 JS::Rooted
<JSObject
*> obj(cx
, Create
<ViewType
>(cx
, ExpectedLength
));
83 CHECK(JS_IsArrayBufferViewObject(obj
));
85 CHECK(JS_GetArrayBufferViewByteLength(obj
) == ExpectedByteLength
);
88 JS::AutoCheckCannotGC nogc
;
90 JSObject
* unwrapped
= js::UnwrapArrayBufferView(obj
);
92 (uint8_t*)JS_GetArrayBufferViewData(unwrapped
, &shared1
, nogc
);
94 auto view
= ViewType::unwrap(obj
);
95 CHECK(JS_GetArrayBufferViewType(obj
) == ScalarTypeOf
<ViewType
>::value
);
97 if (JS_IsTypedArrayObject(unwrapped
)) {
98 CHECK(unwrapped
->as
<TypedArrayObject
>().type() ==
99 TypeIDOfType
<typename InternalType
<ViewType
>::Type
>::id
);
105 reinterpret_cast<uint8_t*>(view
.getLengthAndData(&len
, &shared2
, nogc
));
106 CHECK(obj
== view
.asObject());
107 CHECK(data1
== data2
);
108 CHECK(shared1
== shared2
);
109 CHECK(len
== ExpectedLength
);
111 JS::Heap
<ViewType
> hv(view
);
116 reinterpret_cast<uint8_t*>(hv
.getLengthAndData(&len3
, &shared3
, nogc
));
117 CHECK(obj
== hv
.asObject());
118 CHECK(data1
== data3
);
119 CHECK(shared1
== shared3
);
120 CHECK(len3
== ExpectedLength
);
123 JS::RealmOptions options
;
124 JS::RootedObject
otherGlobal(
125 cx
, JS_NewGlobalObject(cx
, basicGlobalClass(), nullptr,
126 JS::DontFireOnNewGlobalHook
, options
));
129 JS::Rooted
<JSObject
*> buffer(cx
);
131 AutoRealm
ar(cx
, otherGlobal
);
132 buffer
= JS::NewArrayBuffer(cx
, 8);
134 CHECK(buffer
->as
<ArrayBufferObject
>().byteLength() == 8);
136 CHECK(buffer
->compartment() == otherGlobal
->compartment());
137 CHECK(JS_WrapObject(cx
, &buffer
));
138 CHECK(buffer
->compartment() == global
->compartment());
140 JS::Rooted
<JSObject
*> dataview(cx
, JS_NewDataView(cx
, buffer
, 4, 4));
142 CHECK(dataview
->is
<ProxyObject
>());
144 JS::Rooted
<JS::Value
> val(cx
);
146 val
= ObjectValue(*dataview
);
147 CHECK(JS_SetProperty(cx
, global
, "view", val
));
149 EVAL("view.buffer", &val
);
150 CHECK(val
.toObject().is
<ProxyObject
>());
152 CHECK(dataview
->compartment() == global
->compartment());
153 JS::Rooted
<JSObject
*> otherView(cx
, js::UncheckedUnwrap(dataview
));
154 CHECK(otherView
->compartment() == otherGlobal
->compartment());
155 JS::Rooted
<JSObject
*> otherBuffer(cx
, js::UncheckedUnwrap(&val
.toObject()));
156 CHECK(otherBuffer
->compartment() == otherGlobal
->compartment());
158 EVAL("Object.getPrototypeOf(view) === DataView.prototype", &val
);
159 CHECK(val
.toBoolean() == true);
164 END_TEST(testArrayBufferView_type
)