diff options
Diffstat (limited to 'deps/v8/test/unittests/objects/value-serializer-unittest.cc')
-rw-r--r-- | deps/v8/test/unittests/objects/value-serializer-unittest.cc | 172 |
1 files changed, 169 insertions, 3 deletions
diff --git a/deps/v8/test/unittests/objects/value-serializer-unittest.cc b/deps/v8/test/unittests/objects/value-serializer-unittest.cc index 8a36f6dbb3..a2f6461ab2 100644 --- a/deps/v8/test/unittests/objects/value-serializer-unittest.cc +++ b/deps/v8/test/unittests/objects/value-serializer-unittest.cc @@ -21,7 +21,9 @@ #include "src/base/build_config.h" #include "src/objects/backing-store.h" #include "src/objects/js-array-buffer-inl.h" +#include "src/objects/js-array-buffer.h" #include "src/objects/objects-inl.h" +#include "test/common/flag-utils.h" #include "test/unittests/test-utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -1398,7 +1400,6 @@ TEST_F(ValueSerializerTest, RoundTripDate) { } TEST_F(ValueSerializerTest, DecodeDate) { - Local<Value> value; #if defined(V8_TARGET_LITTLE_ENDIAN) DecodeTestFutureVersions( {0xFF, 0x09, 0x3F, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x2E, @@ -1884,11 +1885,20 @@ TEST_F(ValueSerializerTest, RoundTripArrayBuffer) { ASSERT_TRUE(value->IsArrayBuffer()); EXPECT_EQ(0u, ArrayBuffer::Cast(*value)->ByteLength()); ExpectScriptTrue("Object.getPrototypeOf(result) === ArrayBuffer.prototype"); + // TODO(v8:11111): Use API functions for testing max_byte_length and resizable + // once they're exposed via the API. + i::Handle<i::JSArrayBuffer> array_buffer = + Utils::OpenHandle(ArrayBuffer::Cast(*value)); + EXPECT_EQ(0u, array_buffer->max_byte_length()); + EXPECT_EQ(false, array_buffer->is_resizable_by_js()); value = RoundTripTest("new Uint8Array([0, 128, 255]).buffer"); ASSERT_TRUE(value->IsArrayBuffer()); EXPECT_EQ(3u, ArrayBuffer::Cast(*value)->ByteLength()); ExpectScriptTrue("new Uint8Array(result).toString() === '0,128,255'"); + array_buffer = Utils::OpenHandle(ArrayBuffer::Cast(*value)); + EXPECT_EQ(3u, array_buffer->max_byte_length()); + EXPECT_EQ(false, array_buffer->is_resizable_by_js()); value = RoundTripTest("({ a: new ArrayBuffer(), get b() { return this.a; }})"); @@ -1896,6 +1906,21 @@ TEST_F(ValueSerializerTest, RoundTripArrayBuffer) { ExpectScriptTrue("result.a === result.b"); } +TEST_F(ValueSerializerTest, RoundTripResizableArrayBuffer) { + FLAG_SCOPE(harmony_rab_gsab); + Local<Value> value = + RoundTripTest("new ArrayBuffer(100, {maxByteLength: 200})"); + ASSERT_TRUE(value->IsArrayBuffer()); + EXPECT_EQ(100u, ArrayBuffer::Cast(*value)->ByteLength()); + + // TODO(v8:11111): Use API functions for testing max_byte_length and resizable + // once they're exposed via the API. + i::Handle<i::JSArrayBuffer> array_buffer = + Utils::OpenHandle(ArrayBuffer::Cast(*value)); + EXPECT_EQ(200u, array_buffer->max_byte_length()); + EXPECT_EQ(true, array_buffer->is_resizable_by_js()); +} + TEST_F(ValueSerializerTest, DecodeArrayBuffer) { DecodeTestFutureVersions( {0xFF, 0x09, 0x3F, 0x00, 0x42, 0x00}, [this](Local<Value> value) { @@ -1927,6 +1952,13 @@ TEST_F(ValueSerializerTest, DecodeInvalidArrayBuffer) { InvalidDecodeTest({0xFF, 0x09, 0x42, 0xFF, 0xFF, 0x00}); } +TEST_F(ValueSerializerTest, DecodeInvalidResizableArrayBuffer) { + FLAG_SCOPE(harmony_rab_gsab); + // Enough bytes available after reading the length, but not anymore when + // reading the max byte length. + InvalidDecodeTest({0xFF, 0x09, 0x7E, 0x2, 0x10, 0x00}); +} + // An array buffer allocator that never has available memory. class OOMArrayBufferAllocator : public ArrayBuffer::Allocator { public: @@ -2026,14 +2058,20 @@ TEST_F(ValueSerializerTestWithArrayBufferTransfer, TEST_F(ValueSerializerTest, RoundTripTypedArray) { // Check that the right type comes out the other side for every kind of typed // array. + // TODO(v8:11111): Use API functions for testing is_length_tracking and + // is_backed_by_rab, once they're exposed via the API. Local<Value> value; + i::Handle<i::JSTypedArray> i_ta; #define TYPED_ARRAY_ROUND_TRIP_TEST(Type, type, TYPE, ctype) \ value = RoundTripTest("new " #Type "Array(2)"); \ ASSERT_TRUE(value->Is##Type##Array()); \ EXPECT_EQ(2u * sizeof(ctype), TypedArray::Cast(*value)->ByteLength()); \ EXPECT_EQ(2u, TypedArray::Cast(*value)->Length()); \ ExpectScriptTrue("Object.getPrototypeOf(result) === " #Type \ - "Array.prototype"); + "Array.prototype"); \ + i_ta = v8::Utils::OpenHandle(TypedArray::Cast(*value)); \ + EXPECT_EQ(false, i_ta->is_length_tracking()); \ + EXPECT_EQ(false, i_ta->is_backed_by_rab()); TYPED_ARRAYS(TYPED_ARRAY_ROUND_TRIP_TEST) #undef TYPED_ARRAY_ROUND_TRIP_TEST @@ -2066,6 +2104,56 @@ TEST_F(ValueSerializerTest, RoundTripTypedArray) { ExpectScriptTrue("result.f32.length === 5"); } +TEST_F(ValueSerializerTest, RoundTripRabBackedLengthTrackingTypedArray) { + FLAG_SCOPE(harmony_rab_gsab); + // Check that the right type comes out the other side for every kind of typed + // array. + // TODO(v8:11111): Use API functions for testing is_length_tracking and + // is_backed_by_rab, once they're exposed via the API. + Local<Value> value; + i::Handle<i::JSTypedArray> i_ta; +#define TYPED_ARRAY_ROUND_TRIP_TEST(Type, type, TYPE, ctype) \ + value = RoundTripTest("new " #Type \ + "Array(new ArrayBuffer(80, " \ + "{maxByteLength: 160}))"); \ + ASSERT_TRUE(value->Is##Type##Array()); \ + EXPECT_EQ(80u, TypedArray::Cast(*value)->ByteLength()); \ + EXPECT_EQ(80u / sizeof(ctype), TypedArray::Cast(*value)->Length()); \ + ExpectScriptTrue("Object.getPrototypeOf(result) === " #Type \ + "Array.prototype"); \ + i_ta = v8::Utils::OpenHandle(TypedArray::Cast(*value)); \ + EXPECT_EQ(true, i_ta->is_length_tracking()); \ + EXPECT_EQ(true, i_ta->is_backed_by_rab()); + + TYPED_ARRAYS(TYPED_ARRAY_ROUND_TRIP_TEST) +#undef TYPED_ARRAY_ROUND_TRIP_TEST +} + +TEST_F(ValueSerializerTest, RoundTripRabBackedNonLengthTrackingTypedArray) { + FLAG_SCOPE(harmony_rab_gsab); + // Check that the right type comes out the other side for every kind of typed + // array. + // TODO(v8:11111): Use API functions for testing is_length_tracking and + // is_backed_by_rab, once they're exposed via the API. + Local<Value> value; + i::Handle<i::JSTypedArray> i_ta; +#define TYPED_ARRAY_ROUND_TRIP_TEST(Type, type, TYPE, ctype) \ + value = RoundTripTest("new " #Type \ + "Array(new ArrayBuffer(80, " \ + "{maxByteLength: 160}), 8, 4)"); \ + ASSERT_TRUE(value->Is##Type##Array()); \ + EXPECT_EQ(4u * sizeof(ctype), TypedArray::Cast(*value)->ByteLength()); \ + EXPECT_EQ(4u, TypedArray::Cast(*value)->Length()); \ + ExpectScriptTrue("Object.getPrototypeOf(result) === " #Type \ + "Array.prototype"); \ + i_ta = v8::Utils::OpenHandle(TypedArray::Cast(*value)); \ + EXPECT_EQ(false, i_ta->is_length_tracking()); \ + EXPECT_EQ(true, i_ta->is_backed_by_rab()); + + TYPED_ARRAYS(TYPED_ARRAY_ROUND_TRIP_TEST) +#undef TYPED_ARRAY_ROUND_TRIP_TEST +} + TEST_F(ValueSerializerTest, DecodeTypedArray) { // Check that the right type comes out the other side for every kind of typed // array (version 14 and above). @@ -2397,7 +2485,8 @@ TEST_F(ValueSerializerTest, RoundTripDataView) { // TODO(v8:11111): Use API functions for testing is_length_tracking and // is_backed_by_rab, once they're exposed // via the API. - i::Handle<i::JSDataView> i_dv = v8::Utils::OpenHandle(DataView::Cast(*value)); + i::Handle<i::JSDataViewOrRabGsabDataView> i_dv = + v8::Utils::OpenHandle(DataView::Cast(*value)); EXPECT_EQ(false, i_dv->is_length_tracking()); EXPECT_EQ(false, i_dv->is_backed_by_rab()); } @@ -2416,6 +2505,42 @@ TEST_F(ValueSerializerTest, DecodeDataView) { }); } +TEST_F(ValueSerializerTest, RoundTripRabBackedDataView) { + FLAG_SCOPE(harmony_rab_gsab); + + Local<Value> value = RoundTripTest( + "new DataView(new ArrayBuffer(4, {maxByteLength: 8}), 1, 2)"); + ASSERT_TRUE(value->IsDataView()); + EXPECT_EQ(1u, DataView::Cast(*value)->ByteOffset()); + EXPECT_EQ(2u, DataView::Cast(*value)->ByteLength()); + EXPECT_EQ(4u, DataView::Cast(*value)->Buffer()->ByteLength()); + ExpectScriptTrue("Object.getPrototypeOf(result) === DataView.prototype"); + // TODO(v8:11111): Use API functions for testing is_length_tracking and + // is_backed_by_rab, once they're exposed via the API. + i::Handle<i::JSDataViewOrRabGsabDataView> i_dv = + v8::Utils::OpenHandle(DataView::Cast(*value)); + EXPECT_EQ(false, i_dv->is_length_tracking()); + EXPECT_EQ(true, i_dv->is_backed_by_rab()); +} + +TEST_F(ValueSerializerTest, RoundTripRabBackedLengthTrackingDataView) { + FLAG_SCOPE(harmony_rab_gsab); + + Local<Value> value = + RoundTripTest("new DataView(new ArrayBuffer(4, {maxByteLength: 8}), 1)"); + ASSERT_TRUE(value->IsDataView()); + EXPECT_EQ(1u, DataView::Cast(*value)->ByteOffset()); + EXPECT_EQ(3u, DataView::Cast(*value)->ByteLength()); + EXPECT_EQ(4u, DataView::Cast(*value)->Buffer()->ByteLength()); + ExpectScriptTrue("Object.getPrototypeOf(result) === DataView.prototype"); + // TODO(v8:11111): Use API functions for testing is_length_tracking and + // is_backed_by_rab, once they're exposed via the API. + i::Handle<i::JSDataViewOrRabGsabDataView> i_dv = + v8::Utils::OpenHandle(DataView::Cast(*value)); + EXPECT_EQ(true, i_dv->is_length_tracking()); + EXPECT_EQ(true, i_dv->is_backed_by_rab()); +} + TEST_F(ValueSerializerTest, DecodeDataViewBackwardsCompatibility) { DecodeTestUpToVersion( 13, @@ -2633,6 +2758,47 @@ TEST_F(ValueSerializerTestWithSharedArrayBufferClone, ExpectScriptTrue( "new Uint8Array(result.buffer, 0, 4).toString() === '0,1,128,255'"); } + +TEST_F(ValueSerializerTestWithSharedArrayBufferClone, + RoundTripWebAssemblyMemory_WithPreviousReference) { + // This is a regression test for crbug.com/1421524. + // It ensures that WasmMemoryObject can deserialize even if its underlying + // buffer was already encountered, and so will be encoded with an object + // backreference. + std::vector<uint8_t> data = {0x00, 0x01, 0x80, 0xFF}; + data.resize(65536); + InitializeData(data, true); + + EXPECT_CALL(serializer_delegate_, + GetSharedArrayBufferId(isolate(), input_buffer())) + .WillRepeatedly(Return(Just(0U))); + EXPECT_CALL(deserializer_delegate_, GetSharedArrayBufferFromId(isolate(), 0U)) + .WillRepeatedly(Return(output_buffer())); + + Local<Value> input; + { + Context::Scope scope(serialization_context()); + const int32_t kMaxPages = 1; + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate()); + i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*input_buffer()); + i::Handle<i::WasmMemoryObject> wasm_memory = + i::WasmMemoryObject::New(i_isolate, buffer, kMaxPages) + .ToHandleChecked(); + i::Handle<i::FixedArray> fixed_array = + i_isolate->factory()->NewFixedArray(2); + fixed_array->set(0, *buffer); + fixed_array->set(1, *wasm_memory); + input = Utils::ToLocal(i_isolate->factory()->NewJSArrayWithElements( + fixed_array, i::PACKED_ELEMENTS, 2)); + } + RoundTripTest(input); + ExpectScriptTrue("result[0] instanceof SharedArrayBuffer"); + ExpectScriptTrue("result[1] instanceof WebAssembly.Memory"); + ExpectScriptTrue("result[0] === result[1].buffer"); + ExpectScriptTrue("result[0].byteLength === 65536"); + ExpectScriptTrue( + "new Uint8Array(result[0], 0, 4).toString() === '0,1,128,255'"); +} #endif // V8_ENABLE_WEBASSEMBLY TEST_F(ValueSerializerTest, UnsupportedHostObject) { |