test-typedarrays.cc 4.69 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdlib.h>

7
#include "src/init/v8.h"
8 9
#include "test/cctest/cctest.h"

10
#include "src/execution/protectors-inl.h"
11
#include "src/heap/heap.h"
12 13
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
14

15 16
namespace v8 {
namespace internal {
17

18
void TestArrayBufferViewContents(LocalContext* env, bool should_use_buffer) {
19
  v8::Local<v8::Object> obj_a = v8::Local<v8::Object>::Cast(
20 21 22
      (*env)
          ->Global()
          ->Get((*env)->GetIsolate()->GetCurrentContext(), v8_str("a"))
23
          .ToLocalChecked());
24 25 26
  CHECK(obj_a->IsArrayBufferView());
  v8::Local<v8::ArrayBufferView> array_buffer_view =
      v8::Local<v8::ArrayBufferView>::Cast(obj_a);
27
  CHECK_EQ(array_buffer_view->HasBuffer(), should_use_buffer);
28 29 30
  unsigned char contents[4] = {23, 23, 23, 23};
  CHECK_EQ(sizeof(contents),
           array_buffer_view->CopyContents(contents, sizeof(contents)));
31
  CHECK_EQ(array_buffer_view->HasBuffer(), should_use_buffer);
32 33 34 35 36 37 38 39 40 41 42 43 44 45
  for (size_t i = 0; i < sizeof(contents); ++i) {
    CHECK_EQ(i, contents[i]);
  }
}

TEST(CopyContentsTypedArray) {
  LocalContext env;
  v8::HandleScope scope(env->GetIsolate());
  CompileRun(
      "var a = new Uint8Array(4);"
      "a[0] = 0;"
      "a[1] = 1;"
      "a[2] = 2;"
      "a[3] = 3;");
46
  TestArrayBufferViewContents(&env, false);
47 48 49 50 51 52 53
}


TEST(CopyContentsArray) {
  LocalContext env;
  v8::HandleScope scope(env->GetIsolate());
  CompileRun("var a = new Uint8Array([0, 1, 2, 3]);");
54
  TestArrayBufferViewContents(&env, false);
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
}


TEST(CopyContentsView) {
  LocalContext env;
  v8::HandleScope scope(env->GetIsolate());
  CompileRun(
      "var b = new ArrayBuffer(6);"
      "var c = new Uint8Array(b);"
      "c[0] = -1;"
      "c[1] = -1;"
      "c[2] = 0;"
      "c[3] = 1;"
      "c[4] = 2;"
      "c[5] = 3;"
      "var a = new DataView(b, 2);");
71
  TestArrayBufferViewContents(&env, true);
72
}
73

74 75 76 77 78
void TestSpeciesProtector(char* code,
                          bool invalidates_species_protector = true) {
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
  std::string typed_array_constructors[] = {
79
#define TYPED_ARRAY_CTOR(Type, type, TYPE, ctype) #Type "Array",
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

      TYPED_ARRAYS(TYPED_ARRAY_CTOR)
#undef TYPED_ARRAY_CTOR
  };

  for (auto& constructor : typed_array_constructors) {
    v8::Isolate* isolate = v8::Isolate::New(create_params);
    isolate->Enter();
    {
      LocalContext context(isolate);
      v8::HandleScope scope(isolate);
      v8::TryCatch try_catch(isolate);

      CompileRun(("let x = new " + constructor + "();").c_str());
      CompileRun(("let constructor = " + constructor + ";").c_str());
      v8::Local<v8::Value> constructor_obj = CompileRun(constructor.c_str());
      CHECK_EQ(constructor_obj, CompileRun("x.slice().constructor"));
97
      CHECK_EQ(constructor_obj, CompileRun("x.subarray().constructor"));
98 99 100 101 102 103
      CHECK_EQ(constructor_obj, CompileRun("x.map(()=>{}).constructor"));
      std::string decl = "class MyTypedArray extends " + constructor + " { }";
      CompileRun(decl.c_str());

      v8::internal::Isolate* i_isolate =
          reinterpret_cast<v8::internal::Isolate*>(isolate);
104
      CHECK(Protectors::IsTypedArraySpeciesLookupChainIntact(i_isolate));
105 106
      CompileRun(code);
      if (invalidates_species_protector) {
107
        CHECK(!Protectors::IsTypedArraySpeciesLookupChainIntact(i_isolate));
108
      } else {
109
        CHECK(Protectors::IsTypedArraySpeciesLookupChainIntact(i_isolate));
110 111 112 113
      }

      v8::Local<v8::Value> my_typed_array = CompileRun("MyTypedArray");
      CHECK_EQ(my_typed_array, CompileRun("x.slice().constructor"));
114
      CHECK_EQ(my_typed_array, CompileRun("x.subarray().constructor"));
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
      CHECK_EQ(my_typed_array, CompileRun("x.map(()=>{}).constructor"));
    }
    isolate->Exit();
    isolate->Dispose();
  }
}

UNINITIALIZED_TEST(SpeciesConstructor) {
  char code[] = "x.constructor = MyTypedArray";
  TestSpeciesProtector(code);
}

UNINITIALIZED_TEST(SpeciesConstructorAccessor) {
  char code[] =
      "Object.defineProperty(x, 'constructor',{get() {return MyTypedArray;}})";
  TestSpeciesProtector(code);
}

UNINITIALIZED_TEST(SpeciesModified) {
  char code[] =
      "Object.defineProperty(constructor, Symbol.species, "
      "{value:MyTypedArray})";
  TestSpeciesProtector(code);
}

UNINITIALIZED_TEST(SpeciesParentConstructor) {
  char code[] = "constructor.prototype.constructor = MyTypedArray";
  TestSpeciesProtector(code);
}

UNINITIALIZED_TEST(SpeciesProto) {
  char code[] = "x.__proto__ = MyTypedArray.prototype";
  TestSpeciesProtector(code, false);
}

150 151
}  // namespace internal
}  // namespace v8