tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

testArrayBufferView.cpp (5637B)


      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:
      3 */
      4 
      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/. */
      8 
      9 #include "jsfriendapi.h"
     10 
     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"
     18 #include "vm/Realm.h"
     19 #include "vm/Uint8Clamped.h"  // js::uint8_clamped_t
     20 
     21 #include "vm/JSObject-inl.h"
     22 #include "vm/Realm-inl.h"
     23 #include "vm/TypedArrayObject-inl.h"  // TypeIDOfType
     24 
     25 using namespace js;
     26 
     27 template <class ViewType>
     28 static JSObject* Create(JSContext* cx, size_t len) {
     29  return ViewType::create(cx, len).asObject();
     30 }
     31 
     32 template <>
     33 JSObject* Create<JS::DataView>(JSContext* cx, size_t len) {
     34  JS::Rooted<JSObject*> buffer(cx, JS::NewArrayBuffer(cx, len));
     35  if (!buffer) {
     36    return nullptr;
     37  }
     38  return JS_NewDataView(cx, buffer, 0, len);
     39 }
     40 
     41 template <class T>
     42 struct InternalType {
     43  using Type = uint8_t;
     44 };
     45 
     46 #define INT_TYPE(ExternalType, NativeType, Name)          \
     47  template <>                                             \
     48  struct InternalType<JS::TypedArray<js::Scalar::Name>> { \
     49    using Type = NativeType;                              \
     50  };
     51 JS_FOR_EACH_TYPED_ARRAY(INT_TYPE)
     52 #undef INT_TYPE
     53 
     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)));
     65 
     66  return true;
     67 }
     68 
     69 template <class T>
     70 struct ScalarTypeOf {
     71  static constexpr js::Scalar::Type value = js::Scalar::MaxTypedArrayViewType;
     72 };
     73 
     74 template <js::Scalar::Type EType>
     75 struct ScalarTypeOf<JS::TypedArray<EType>> {
     76  static constexpr js::Scalar::Type value = EType;
     77 };
     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));
     81  CHECK(obj);
     82 
     83  CHECK(JS_IsArrayBufferViewObject(obj));
     84 
     85  CHECK(JS_GetArrayBufferViewByteLength(obj) == ExpectedByteLength);
     86 
     87  {
     88    JS::AutoCheckCannotGC nogc;
     89    bool shared1;
     90    JSObject* unwrapped = js::UnwrapArrayBufferView(obj);
     91    uint8_t* data1 =
     92        (uint8_t*)JS_GetArrayBufferViewData(unwrapped, &shared1, nogc);
     93 
     94    auto view = ViewType::unwrap(obj);
     95    CHECK(JS_GetArrayBufferViewType(obj) == ScalarTypeOf<ViewType>::value);
     96 
     97    if (JS_IsTypedArrayObject(unwrapped)) {
     98      CHECK(unwrapped->as<TypedArrayObject>().type() ==
     99            TypeIDOfType<typename InternalType<ViewType>::Type>::id);
    100    }
    101 
    102    bool shared2;
    103    mozilla::Span<typename ViewType::DataType> span2 =
    104        view.getData(&shared2, nogc);
    105    CHECK(obj == view.asObject());
    106    CHECK(data1 == reinterpret_cast<uint8_t*>(span2.data()));
    107    CHECK(shared1 == shared2);
    108    CHECK(span2.Length() == ExpectedLength);
    109 
    110    JS::Heap<ViewType> hv(view);
    111 
    112    bool shared3;
    113    mozilla::Span<typename ViewType::DataType> span3 =
    114        hv.getData(&shared3, nogc);
    115    CHECK(obj == hv.asObject());
    116    CHECK(data1 == reinterpret_cast<uint8_t*>(span3.data()));
    117    CHECK(shared1 == shared3);
    118    CHECK(span3.Length() == ExpectedLength);
    119  }
    120 
    121  JS::RealmOptions options;
    122  JS::RootedObject otherGlobal(
    123      cx, JS_NewGlobalObject(cx, basicGlobalClass(), nullptr,
    124                             JS::DontFireOnNewGlobalHook, options));
    125  CHECK(otherGlobal);
    126 
    127  JS::Rooted<JSObject*> buffer(cx);
    128  {
    129    AutoRealm ar(cx, otherGlobal);
    130    buffer = JS::NewArrayBuffer(cx, 8);
    131    CHECK(buffer);
    132    CHECK(buffer->as<ArrayBufferObject>().byteLength() == 8);
    133  }
    134  CHECK(buffer->compartment() == otherGlobal->compartment());
    135  CHECK(JS_WrapObject(cx, &buffer));
    136  CHECK(buffer->compartment() == global->compartment());
    137 
    138  JS::Rooted<JSObject*> dataview(cx, JS_NewDataView(cx, buffer, 4, 4));
    139  CHECK(dataview);
    140  CHECK(dataview->is<ProxyObject>());
    141 
    142  JS::Rooted<JS::Value> val(cx);
    143 
    144  val = ObjectValue(*dataview);
    145  CHECK(JS_SetProperty(cx, global, "view", val));
    146 
    147  EVAL("view.buffer", &val);
    148  CHECK(val.toObject().is<ProxyObject>());
    149 
    150  CHECK(dataview->compartment() == global->compartment());
    151  JS::Rooted<JSObject*> otherView(cx, js::UncheckedUnwrap(dataview));
    152  CHECK(otherView->compartment() == otherGlobal->compartment());
    153  JS::Rooted<JSObject*> otherBuffer(cx, js::UncheckedUnwrap(&val.toObject()));
    154  CHECK(otherBuffer->compartment() == otherGlobal->compartment());
    155 
    156  EVAL("Object.getPrototypeOf(view) === DataView.prototype", &val);
    157  CHECK(val.toBoolean() == true);
    158 
    159  return true;
    160 }
    161 
    162 END_TEST(testArrayBufferView_type)