LCOV - code coverage report
Current view: top level - test/unittests - value-serializer-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1352 1373 98.5 %
Date: 2019-04-17 Functions: 257 363 70.8 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/value-serializer.h"
       6             : 
       7             : #include <algorithm>
       8             : #include <string>
       9             : 
      10             : #include "include/v8.h"
      11             : #include "src/api-inl.h"
      12             : #include "src/base/build_config.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/wasm/wasm-objects.h"
      15             : #include "test/unittests/test-utils.h"
      16             : #include "testing/gmock/include/gmock/gmock.h"
      17             : #include "testing/gtest/include/gtest/gtest.h"
      18             : 
      19             : namespace v8 {
      20             : namespace {
      21             : 
      22             : using ::testing::_;
      23             : using ::testing::Invoke;
      24             : using ::testing::Return;
      25             : 
      26             : class ValueSerializerTest : public TestWithIsolate {
      27             :  protected:
      28          83 :   ValueSerializerTest()
      29          83 :       : serialization_context_(Context::New(isolate())),
      30         332 :         deserialization_context_(Context::New(isolate())) {
      31             :     // Create a host object type that can be tested through
      32             :     // serialization/deserialization delegates below.
      33             :     Local<FunctionTemplate> function_template = v8::FunctionTemplate::New(
      34          52 :         isolate(), [](const FunctionCallbackInfo<Value>& args) {
      35          26 :           args.Holder()->SetInternalField(0, args[0]);
      36          26 :           args.Holder()->SetInternalField(1, args[1]);
      37         135 :         });
      38         166 :     function_template->InstanceTemplate()->SetInternalFieldCount(2);
      39         166 :     function_template->InstanceTemplate()->SetAccessor(
      40             :         StringFromUtf8("value"),
      41          16 :         [](Local<String> property, const PropertyCallbackInfo<Value>& args) {
      42             :           args.GetReturnValue().Set(args.Holder()->GetInternalField(0));
      43          99 :         });
      44         166 :     function_template->InstanceTemplate()->SetAccessor(
      45             :         StringFromUtf8("value2"),
      46           4 :         [](Local<String> property, const PropertyCallbackInfo<Value>& args) {
      47             :           args.GetReturnValue().Set(args.Holder()->GetInternalField(1));
      48          87 :         });
      49         415 :     for (Local<Context> context :
      50         249 :          {serialization_context_, deserialization_context_}) {
      51         332 :       context->Global()
      52         332 :           ->CreateDataProperty(
      53             :               context, StringFromUtf8("ExampleHostObject"),
      54         498 :               function_template->GetFunction(context).ToLocalChecked())
      55             :           .ToChecked();
      56             :     }
      57          83 :     host_object_constructor_template_ = function_template;
      58          83 :     isolate_ = reinterpret_cast<i::Isolate*>(isolate());
      59          83 :   }
      60             : 
      61         166 :   ~ValueSerializerTest() override {
      62             :     // In some cases unhandled scheduled exceptions from current test produce
      63             :     // that Context::New(isolate()) from next test's constructor returns NULL.
      64             :     // In order to prevent that, we added destructor which will clear scheduled
      65             :     // exceptions just for the current test from test case.
      66         166 :     if (isolate_->has_scheduled_exception()) {
      67             :       isolate_->clear_scheduled_exception();
      68             :     }
      69             :   }
      70             : 
      71             :   const Local<Context>& serialization_context() {
      72          16 :     return serialization_context_;
      73             :   }
      74             :   const Local<Context>& deserialization_context() {
      75          11 :     return deserialization_context_;
      76             :   }
      77             : 
      78             :   bool ExpectInlineWasm() const { return expect_inline_wasm_; }
      79           4 :   void SetExpectInlineWasm(bool value) { expect_inline_wasm_ = value; }
      80             : 
      81             :   // Overridden in more specific fixtures.
      82         222 :   virtual ValueSerializer::Delegate* GetSerializerDelegate() { return nullptr; }
      83         125 :   virtual void BeforeEncode(ValueSerializer*) {}
      84         235 :   virtual ValueDeserializer::Delegate* GetDeserializerDelegate() {
      85         235 :     return nullptr;
      86             :   }
      87         248 :   virtual void BeforeDecode(ValueDeserializer*) {}
      88             : 
      89         127 :   Local<Value> RoundTripTest(Local<Value> input_value) {
      90         127 :     std::vector<uint8_t> encoded = EncodeTest(input_value);
      91         254 :     return DecodeTest(encoded);
      92             :   }
      93             : 
      94             :   // Variant for the common case where a script is used to build the original
      95             :   // value.
      96             :   Local<Value> RoundTripTest(const char* source) {
      97          97 :     return RoundTripTest(EvaluateScriptForInput(source));
      98             :   }
      99             : 
     100             :   // Variant which uses JSON.parse/stringify to check the result.
     101           2 :   void RoundTripJSON(const char* source) {
     102             :     Local<Value> input_value =
     103           2 :         JSON::Parse(serialization_context_, StringFromUtf8(source))
     104           2 :             .ToLocalChecked();
     105           2 :     Local<Value> result = RoundTripTest(input_value);
     106           4 :     ASSERT_TRUE(result->IsObject());
     107           6 :     EXPECT_EQ(source, Utf8Value(JSON::Stringify(deserialization_context_,
     108             :                                                 result.As<Object>())
     109           0 :                                     .ToLocalChecked()));
     110             :   }
     111             : 
     112         141 :   Maybe<std::vector<uint8_t>> DoEncode(Local<Value> value) {
     113         141 :     Local<Context> context = serialization_context();
     114         423 :     ValueSerializer serializer(isolate(), GetSerializerDelegate());
     115         141 :     BeforeEncode(&serializer);
     116         141 :     serializer.WriteHeader();
     117         282 :     if (!serializer.WriteValue(context, value).FromMaybe(false)) {
     118             :       return Nothing<std::vector<uint8_t>>();
     119             :     }
     120         132 :     std::pair<uint8_t*, size_t> buffer = serializer.Release();
     121         132 :     std::vector<uint8_t> result(buffer.first, buffer.first + buffer.second);
     122         132 :     if (auto* delegate = GetSerializerDelegate())
     123          20 :       delegate->FreeBufferMemory(buffer.first);
     124             :     else
     125         112 :       free(buffer.first);
     126             :     return Just(std::move(result));
     127             :   }
     128             : 
     129         132 :   std::vector<uint8_t> EncodeTest(Local<Value> input_value) {
     130             :     Context::Scope scope(serialization_context());
     131         264 :     TryCatch try_catch(isolate());
     132             :     std::vector<uint8_t> buffer;
     133             :     // Ideally we would use GTest's ASSERT_* macros here and below. However,
     134             :     // those only work in functions returning {void}, and they only terminate
     135             :     // the current function, but not the entire current test (so we would need
     136             :     // additional manual checks whether it is okay to proceed). Given that our
     137             :     // test driver starts a new process for each test anyway, it is acceptable
     138             :     // to just use a CHECK (which would kill the process on failure) instead.
     139         396 :     CHECK(DoEncode(input_value).To(&buffer));
     140         132 :     CHECK(!try_catch.HasCaught());
     141         132 :     return buffer;
     142             :   }
     143             : 
     144             :   std::vector<uint8_t> EncodeTest(const char* source) {
     145           1 :     return EncodeTest(EvaluateScriptForInput(source));
     146             :   }
     147             : 
     148           9 :   v8::Local<v8::Message> InvalidEncodeTest(Local<Value> input_value) {
     149             :     Context::Scope scope(serialization_context());
     150          18 :     TryCatch try_catch(isolate());
     151          27 :     CHECK(DoEncode(input_value).IsNothing());
     152          18 :     return try_catch.Message();
     153             :   }
     154             : 
     155             :   v8::Local<v8::Message> InvalidEncodeTest(const char* source) {
     156           7 :     return InvalidEncodeTest(EvaluateScriptForInput(source));
     157             :   }
     158             : 
     159         224 :   Local<Value> DecodeTest(const std::vector<uint8_t>& data) {
     160         224 :     Local<Context> context = deserialization_context();
     161             :     Context::Scope scope(context);
     162         448 :     TryCatch try_catch(isolate());
     163             :     ValueDeserializer deserializer(isolate(), &data[0],
     164             :                                    static_cast<int>(data.size()),
     165         896 :                                    GetDeserializerDelegate());
     166         224 :     deserializer.SetSupportsLegacyWireFormat(true);
     167         224 :     deserializer.SetExpectInlineWasm(ExpectInlineWasm());
     168         224 :     BeforeDecode(&deserializer);
     169         448 :     CHECK(deserializer.ReadHeader(context).FromMaybe(false));
     170             :     Local<Value> result;
     171         448 :     CHECK(deserializer.ReadValue(context).ToLocal(&result));
     172         224 :     CHECK(!result.IsEmpty());
     173         224 :     CHECK(!try_catch.HasCaught());
     174         896 :     CHECK(context->Global()
     175             :               ->CreateDataProperty(context, StringFromUtf8("result"), result)
     176             :               .FromMaybe(false));
     177         224 :     CHECK(!try_catch.HasCaught());
     178         448 :     return result;
     179             :   }
     180             : 
     181           8 :   Local<Value> DecodeTestForVersion0(const std::vector<uint8_t>& data) {
     182           8 :     Local<Context> context = deserialization_context();
     183             :     Context::Scope scope(context);
     184          16 :     TryCatch try_catch(isolate());
     185             :     ValueDeserializer deserializer(isolate(), &data[0],
     186             :                                    static_cast<int>(data.size()),
     187          32 :                                    GetDeserializerDelegate());
     188           8 :     deserializer.SetSupportsLegacyWireFormat(true);
     189           8 :     deserializer.SetExpectInlineWasm(ExpectInlineWasm());
     190           8 :     BeforeDecode(&deserializer);
     191          16 :     CHECK(deserializer.ReadHeader(context).FromMaybe(false));
     192           8 :     CHECK_EQ(0u, deserializer.GetWireFormatVersion());
     193             :     Local<Value> result;
     194          16 :     CHECK(deserializer.ReadValue(context).ToLocal(&result));
     195           8 :     CHECK(!result.IsEmpty());
     196           8 :     CHECK(!try_catch.HasCaught());
     197          32 :     CHECK(context->Global()
     198             :               ->CreateDataProperty(context, StringFromUtf8("result"), result)
     199             :               .FromMaybe(false));
     200           8 :     CHECK(!try_catch.HasCaught());
     201          16 :     return result;
     202             :   }
     203             : 
     204          30 :   void InvalidDecodeTest(const std::vector<uint8_t>& data) {
     205          30 :     Local<Context> context = deserialization_context();
     206             :     Context::Scope scope(context);
     207          58 :     TryCatch try_catch(isolate());
     208             :     ValueDeserializer deserializer(isolate(), &data[0],
     209             :                                    static_cast<int>(data.size()),
     210         118 :                                    GetDeserializerDelegate());
     211          30 :     deserializer.SetSupportsLegacyWireFormat(true);
     212          30 :     deserializer.SetExpectInlineWasm(ExpectInlineWasm());
     213          30 :     BeforeDecode(&deserializer);
     214          30 :     Maybe<bool> header_result = deserializer.ReadHeader(context);
     215          30 :     if (header_result.IsNothing()) {
     216           4 :       EXPECT_TRUE(try_catch.HasCaught());
     217           2 :       return;
     218             :     }
     219          28 :     CHECK(header_result.ToChecked());
     220          56 :     CHECK(deserializer.ReadValue(context).IsEmpty());
     221          56 :     EXPECT_TRUE(try_catch.HasCaught());
     222             :   }
     223             : 
     224         108 :   Local<Value> EvaluateScriptForInput(const char* utf8_source) {
     225             :     Context::Scope scope(serialization_context_);
     226         108 :     Local<String> source = StringFromUtf8(utf8_source);
     227             :     Local<Script> script =
     228         108 :         Script::Compile(serialization_context_, source).ToLocalChecked();
     229         216 :     return script->Run(serialization_context_).ToLocalChecked();
     230             :   }
     231             : 
     232         327 :   void ExpectScriptTrue(const char* utf8_source) {
     233             :     Context::Scope scope(deserialization_context_);
     234         327 :     Local<String> source = StringFromUtf8(utf8_source);
     235             :     Local<Script> script =
     236         327 :         Script::Compile(deserialization_context_, source).ToLocalChecked();
     237         327 :     Local<Value> value = script->Run(deserialization_context_).ToLocalChecked();
     238         654 :     EXPECT_TRUE(value->BooleanValue(isolate()));
     239         327 :   }
     240             : 
     241        1019 :   Local<String> StringFromUtf8(const char* source) {
     242        1019 :     return String::NewFromUtf8(isolate(), source, NewStringType::kNormal)
     243        1019 :         .ToLocalChecked();
     244             :   }
     245             : 
     246          14 :   std::string Utf8Value(Local<Value> value) {
     247          28 :     String::Utf8Value utf8(isolate(), value);
     248          28 :     return std::string(*utf8, utf8.length());
     249             :   }
     250             : 
     251          11 :   Local<Object> NewHostObject(Local<Context> context, int argc,
     252             :                               Local<Value> argv[]) {
     253          11 :     return host_object_constructor_template_->GetFunction(context)
     254             :         .ToLocalChecked()
     255          11 :         ->NewInstance(context, argc, argv)
     256          11 :         .ToLocalChecked();
     257             :   }
     258             : 
     259           1 :   Local<Object> NewDummyUint8Array() {
     260             :     static uint8_t data[] = {4, 5, 6};
     261             :     Local<ArrayBuffer> ab =
     262           1 :         ArrayBuffer::New(isolate(), static_cast<void*>(data), sizeof(data));
     263           1 :     return Uint8Array::New(ab, 0, sizeof(data));
     264             :   }
     265             : 
     266             :  private:
     267             :   Local<Context> serialization_context_;
     268             :   Local<Context> deserialization_context_;
     269             :   Local<FunctionTemplate> host_object_constructor_template_;
     270             :   i::Isolate* isolate_;
     271             :   bool expect_inline_wasm_ = false;
     272             : 
     273             :   DISALLOW_COPY_AND_ASSIGN(ValueSerializerTest);
     274             : };
     275             : 
     276       15444 : TEST_F(ValueSerializerTest, DecodeInvalid) {
     277             :   // Version tag but no content.
     278           2 :   InvalidDecodeTest({0xFF});
     279             :   // Version too large.
     280           2 :   InvalidDecodeTest({0xFF, 0x7F, 0x5F});
     281             :   // Nonsense tag.
     282           2 :   InvalidDecodeTest({0xFF, 0x09, 0xDD});
     283           1 : }
     284             : 
     285       15444 : TEST_F(ValueSerializerTest, RoundTripOddball) {
     286           1 :   Local<Value> value = RoundTripTest(Undefined(isolate()));
     287           1 :   EXPECT_TRUE(value->IsUndefined());
     288           1 :   value = RoundTripTest(True(isolate()));
     289           2 :   EXPECT_TRUE(value->IsTrue());
     290           1 :   value = RoundTripTest(False(isolate()));
     291           2 :   EXPECT_TRUE(value->IsFalse());
     292           1 :   value = RoundTripTest(Null(isolate()));
     293           1 :   EXPECT_TRUE(value->IsNull());
     294           1 : }
     295             : 
     296       15444 : TEST_F(ValueSerializerTest, DecodeOddball) {
     297             :   // What this code is expected to generate.
     298           2 :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x5F});
     299           1 :   EXPECT_TRUE(value->IsUndefined());
     300           2 :   value = DecodeTest({0xFF, 0x09, 0x54});
     301           2 :   EXPECT_TRUE(value->IsTrue());
     302           2 :   value = DecodeTest({0xFF, 0x09, 0x46});
     303           2 :   EXPECT_TRUE(value->IsFalse());
     304           2 :   value = DecodeTest({0xFF, 0x09, 0x30});
     305           1 :   EXPECT_TRUE(value->IsNull());
     306             : 
     307             :   // What v9 of the Blink code generates.
     308           2 :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x5F, 0x00});
     309           1 :   EXPECT_TRUE(value->IsUndefined());
     310           2 :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x54, 0x00});
     311           2 :   EXPECT_TRUE(value->IsTrue());
     312           2 :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x46, 0x00});
     313           2 :   EXPECT_TRUE(value->IsFalse());
     314           2 :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x30, 0x00});
     315           1 :   EXPECT_TRUE(value->IsNull());
     316             : 
     317             :   // v0 (with no explicit version).
     318           2 :   value = DecodeTest({0x5F, 0x00});
     319           1 :   EXPECT_TRUE(value->IsUndefined());
     320           2 :   value = DecodeTest({0x54, 0x00});
     321           2 :   EXPECT_TRUE(value->IsTrue());
     322           2 :   value = DecodeTest({0x46, 0x00});
     323           2 :   EXPECT_TRUE(value->IsFalse());
     324           2 :   value = DecodeTest({0x30, 0x00});
     325           1 :   EXPECT_TRUE(value->IsNull());
     326           1 : }
     327             : 
     328       15444 : TEST_F(ValueSerializerTest, EncodeArrayStackOverflow) {
     329           1 :   InvalidEncodeTest("var a = []; for (var i = 0; i < 1E5; i++) a = [a]; a");
     330           1 : }
     331             : 
     332       15444 : TEST_F(ValueSerializerTest, EncodeObjectStackOverflow) {
     333           1 :   InvalidEncodeTest("var a = {}; for (var i = 0; i < 1E5; i++) a = {a}; a");
     334           1 : }
     335             : 
     336       15444 : TEST_F(ValueSerializerTest, DecodeArrayStackOverflow) {
     337             :   static const int nesting_level = 1E5;
     338             :   std::vector<uint8_t> payload;
     339             :   // Header.
     340           2 :   payload.push_back(0xFF);
     341           2 :   payload.push_back(0x0D);
     342             : 
     343             :   // Nested arrays, each with one element.
     344      200001 :   for (int i = 0; i < nesting_level; i++) {
     345      200000 :     payload.push_back(0x41);
     346      200000 :     payload.push_back(0x01);
     347             :   }
     348             : 
     349             :   // Innermost array is empty.
     350           2 :   payload.push_back(0x41);
     351           2 :   payload.push_back(0x00);
     352           2 :   payload.push_back(0x24);
     353           2 :   payload.push_back(0x00);
     354           2 :   payload.push_back(0x00);
     355             : 
     356             :   // Close nesting.
     357      200001 :   for (int i = 0; i < nesting_level; i++) {
     358      200000 :     payload.push_back(0x24);
     359      200000 :     payload.push_back(0x00);
     360      200000 :     payload.push_back(0x01);
     361             :   }
     362             : 
     363           1 :   InvalidDecodeTest(payload);
     364           1 : }
     365             : 
     366       15444 : TEST_F(ValueSerializerTest, DecodeObjectStackOverflow) {
     367             :   static const int nesting_level = 1E5;
     368             :   std::vector<uint8_t> payload;
     369             :   // Header.
     370           2 :   payload.push_back(0xFF);
     371           2 :   payload.push_back(0x0D);
     372             : 
     373             :   // Nested objects, each with one property 'a'.
     374      200001 :   for (int i = 0; i < nesting_level; i++) {
     375      200000 :     payload.push_back(0x6F);
     376      200000 :     payload.push_back(0x22);
     377      200000 :     payload.push_back(0x01);
     378      200000 :     payload.push_back(0x61);
     379             :   }
     380             : 
     381             :   // Innermost array is empty.
     382           2 :   payload.push_back(0x6F);
     383           2 :   payload.push_back(0x7B);
     384           2 :   payload.push_back(0x00);
     385             : 
     386             :   // Close nesting.
     387      200001 :   for (int i = 0; i < nesting_level; i++) {
     388      200000 :     payload.push_back(0x7B);
     389      200000 :     payload.push_back(0x01);
     390             :   }
     391             : 
     392           1 :   InvalidDecodeTest(payload);
     393           1 : }
     394             : 
     395       15444 : TEST_F(ValueSerializerTest, DecodeVerifyObjectCount) {
     396             :   static const int nesting_level = 1E5;
     397             :   std::vector<uint8_t> payload;
     398             :   // Header.
     399           2 :   payload.push_back(0xFF);
     400           2 :   payload.push_back(0x0D);
     401             : 
     402             :   // Repeat SerializationTag:kVerifyObjectCount. This leads to stack overflow.
     403      200001 :   for (int i = 0; i < nesting_level; i++) {
     404      200000 :     payload.push_back(0x3F);
     405      200000 :     payload.push_back(0x01);
     406             :   }
     407             : 
     408           1 :   InvalidDecodeTest(payload);
     409           1 : }
     410             : 
     411       15444 : TEST_F(ValueSerializerTest, RoundTripNumber) {
     412           2 :   Local<Value> value = RoundTripTest(Integer::New(isolate(), 42));
     413           2 :   ASSERT_TRUE(value->IsInt32());
     414           2 :   EXPECT_EQ(42, Int32::Cast(*value)->Value());
     415             : 
     416           2 :   value = RoundTripTest(Integer::New(isolate(), -31337));
     417           2 :   ASSERT_TRUE(value->IsInt32());
     418           2 :   EXPECT_EQ(-31337, Int32::Cast(*value)->Value());
     419             : 
     420             :   value = RoundTripTest(
     421           2 :       Integer::New(isolate(), std::numeric_limits<int32_t>::min()));
     422           2 :   ASSERT_TRUE(value->IsInt32());
     423           2 :   EXPECT_EQ(std::numeric_limits<int32_t>::min(), Int32::Cast(*value)->Value());
     424             : 
     425           2 :   value = RoundTripTest(Number::New(isolate(), -0.25));
     426           2 :   ASSERT_TRUE(value->IsNumber());
     427           2 :   EXPECT_EQ(-0.25, Number::Cast(*value)->Value());
     428             : 
     429             :   value = RoundTripTest(
     430           2 :       Number::New(isolate(), std::numeric_limits<double>::quiet_NaN()));
     431           2 :   ASSERT_TRUE(value->IsNumber());
     432           2 :   EXPECT_TRUE(std::isnan(Number::Cast(*value)->Value()));
     433             : }
     434             : 
     435       15444 : TEST_F(ValueSerializerTest, DecodeNumber) {
     436             :   // 42 zig-zag encoded (signed)
     437           2 :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x49, 0x54});
     438           2 :   ASSERT_TRUE(value->IsInt32());
     439           2 :   EXPECT_EQ(42, Int32::Cast(*value)->Value());
     440             : 
     441             :   // 42 varint encoded (unsigned)
     442           2 :   value = DecodeTest({0xFF, 0x09, 0x55, 0x2A});
     443           2 :   ASSERT_TRUE(value->IsInt32());
     444           2 :   EXPECT_EQ(42, Int32::Cast(*value)->Value());
     445             : 
     446             :   // 160 zig-zag encoded (signed)
     447           2 :   value = DecodeTest({0xFF, 0x09, 0x49, 0xC0, 0x02});
     448           2 :   ASSERT_TRUE(value->IsInt32());
     449           2 :   ASSERT_EQ(160, Int32::Cast(*value)->Value());
     450             : 
     451             :   // 160 varint encoded (unsigned)
     452           2 :   value = DecodeTest({0xFF, 0x09, 0x55, 0xA0, 0x01});
     453           2 :   ASSERT_TRUE(value->IsInt32());
     454           2 :   ASSERT_EQ(160, Int32::Cast(*value)->Value());
     455             : 
     456             : #if defined(V8_TARGET_LITTLE_ENDIAN)
     457             :   // IEEE 754 doubles, little-endian byte order
     458             :   value = DecodeTest(
     459           2 :       {0xFF, 0x09, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBF});
     460           2 :   ASSERT_TRUE(value->IsNumber());
     461           2 :   EXPECT_EQ(-0.25, Number::Cast(*value)->Value());
     462             : 
     463             :   // quiet NaN
     464             :   value = DecodeTest(
     465           2 :       {0xFF, 0x09, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7F});
     466           2 :   ASSERT_TRUE(value->IsNumber());
     467           2 :   EXPECT_TRUE(std::isnan(Number::Cast(*value)->Value()));
     468             : 
     469             :   // signaling NaN
     470             :   value = DecodeTest(
     471           2 :       {0xFF, 0x09, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x7F});
     472           2 :   ASSERT_TRUE(value->IsNumber());
     473           2 :   EXPECT_TRUE(std::isnan(Number::Cast(*value)->Value()));
     474             : #endif
     475             :   // TODO(jbroman): Equivalent test for big-endian machines.
     476             : }
     477             : 
     478       15444 : TEST_F(ValueSerializerTest, RoundTripBigInt) {
     479           2 :   Local<Value> value = RoundTripTest(BigInt::New(isolate(), -42));
     480           2 :   ASSERT_TRUE(value->IsBigInt());
     481           1 :   ExpectScriptTrue("result === -42n");
     482             : 
     483           2 :   value = RoundTripTest(BigInt::New(isolate(), 42));
     484           1 :   ExpectScriptTrue("result === 42n");
     485             : 
     486           2 :   value = RoundTripTest(BigInt::New(isolate(), 0));
     487           1 :   ExpectScriptTrue("result === 0n");
     488             : 
     489             :   value = RoundTripTest("0x1234567890abcdef777888999n");
     490           1 :   ExpectScriptTrue("result === 0x1234567890abcdef777888999n");
     491             : 
     492             :   value = RoundTripTest("-0x1234567890abcdef777888999123n");
     493           1 :   ExpectScriptTrue("result === -0x1234567890abcdef777888999123n");
     494             : 
     495             :   Context::Scope scope(serialization_context());
     496           1 :   value = RoundTripTest(BigIntObject::New(isolate(), 23));
     497           2 :   ASSERT_TRUE(value->IsBigIntObject());
     498           1 :   ExpectScriptTrue("result == 23n");
     499             : }
     500             : 
     501       15444 : TEST_F(ValueSerializerTest, DecodeBigInt) {
     502             :   Local<Value> value = DecodeTest({
     503             :       0xFF, 0x0D,              // Version 13
     504             :       0x5A,                    // BigInt
     505             :       0x08,                    // Bitfield: sign = false, bytelength = 4
     506             :       0x2A, 0x00, 0x00, 0x00,  // Digit: 42
     507           2 :   });
     508           2 :   ASSERT_TRUE(value->IsBigInt());
     509           1 :   ExpectScriptTrue("result === 42n");
     510             : 
     511             :   value = DecodeTest({
     512             :       0xFF, 0x0D,  // Version 13
     513             :       0x7A,        // BigIntObject
     514             :       0x11,        // Bitfield: sign = true, bytelength = 8
     515             :       0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Digit: 42
     516           2 :   });
     517           2 :   ASSERT_TRUE(value->IsBigIntObject());
     518           1 :   ExpectScriptTrue("result == -42n");
     519             : 
     520             :   value = DecodeTest({
     521             :       0xFF, 0x0D,  // Version 13
     522             :       0x5A,        // BigInt
     523             :       0x10,        // Bitfield: sign = false, bytelength = 8
     524             :       0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12  // Digit(s).
     525           2 :   });
     526           1 :   ExpectScriptTrue("result === 0x1234567890abcdefn");
     527             : 
     528             :   value = DecodeTest({0xFF, 0x0D,  // Version 13
     529             :                       0x5A,        // BigInt
     530             :                       0x17,        // Bitfield: sign = true, bytelength = 11
     531             :                       0xEF, 0xCD, 0xAB, 0x90,  // Digits.
     532           2 :                       0x78, 0x56, 0x34, 0x12, 0x33, 0x44, 0x55});
     533           1 :   ExpectScriptTrue("result === -0x5544331234567890abcdefn");
     534             : 
     535             :   value = DecodeTest({
     536             :       0xFF, 0x0D,  // Version 13
     537             :       0x5A,        // BigInt
     538             :       0x02,        // Bitfield: sign = false, bytelength = 1
     539             :       0x2A,        // Digit: 42
     540           2 :   });
     541           1 :   ExpectScriptTrue("result === 42n");
     542             : }
     543             : 
     544             : // String constants (in UTF-8) used for string encoding tests.
     545             : static const char kHelloString[] = "Hello";
     546             : static const char kQuebecString[] = "\x51\x75\xC3\xA9\x62\x65\x63";
     547             : static const char kEmojiString[] = "\xF0\x9F\x91\x8A";
     548             : 
     549       15444 : TEST_F(ValueSerializerTest, RoundTripString) {
     550           1 :   Local<Value> value = RoundTripTest(String::Empty(isolate()));
     551           1 :   ASSERT_TRUE(value->IsString());
     552           2 :   EXPECT_EQ(0, String::Cast(*value)->Length());
     553             : 
     554             :   // Inside ASCII.
     555           2 :   value = RoundTripTest(StringFromUtf8(kHelloString));
     556           1 :   ASSERT_TRUE(value->IsString());
     557           2 :   EXPECT_EQ(5, String::Cast(*value)->Length());
     558           2 :   EXPECT_EQ(kHelloString, Utf8Value(value));
     559             : 
     560             :   // Inside Latin-1 (i.e. one-byte string), but not ASCII.
     561           2 :   value = RoundTripTest(StringFromUtf8(kQuebecString));
     562           1 :   ASSERT_TRUE(value->IsString());
     563           2 :   EXPECT_EQ(6, String::Cast(*value)->Length());
     564           2 :   EXPECT_EQ(kQuebecString, Utf8Value(value));
     565             : 
     566             :   // An emoji (decodes to two 16-bit chars).
     567           2 :   value = RoundTripTest(StringFromUtf8(kEmojiString));
     568           1 :   ASSERT_TRUE(value->IsString());
     569           2 :   EXPECT_EQ(2, String::Cast(*value)->Length());
     570           2 :   EXPECT_EQ(kEmojiString, Utf8Value(value));
     571             : }
     572             : 
     573       15444 : TEST_F(ValueSerializerTest, DecodeString) {
     574             :   // Decoding the strings above from UTF-8.
     575           2 :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x53, 0x00});
     576           1 :   ASSERT_TRUE(value->IsString());
     577           2 :   EXPECT_EQ(0, String::Cast(*value)->Length());
     578             : 
     579           2 :   value = DecodeTest({0xFF, 0x09, 0x53, 0x05, 'H', 'e', 'l', 'l', 'o'});
     580           1 :   ASSERT_TRUE(value->IsString());
     581           2 :   EXPECT_EQ(5, String::Cast(*value)->Length());
     582           2 :   EXPECT_EQ(kHelloString, Utf8Value(value));
     583             : 
     584             :   value =
     585           2 :       DecodeTest({0xFF, 0x09, 0x53, 0x07, 'Q', 'u', 0xC3, 0xA9, 'b', 'e', 'c'});
     586           1 :   ASSERT_TRUE(value->IsString());
     587           2 :   EXPECT_EQ(6, String::Cast(*value)->Length());
     588           2 :   EXPECT_EQ(kQuebecString, Utf8Value(value));
     589             : 
     590           2 :   value = DecodeTest({0xFF, 0x09, 0x53, 0x04, 0xF0, 0x9F, 0x91, 0x8A});
     591           1 :   ASSERT_TRUE(value->IsString());
     592           2 :   EXPECT_EQ(2, String::Cast(*value)->Length());
     593           2 :   EXPECT_EQ(kEmojiString, Utf8Value(value));
     594             : 
     595             :   // And from Latin-1 (for the ones that fit).
     596           2 :   value = DecodeTest({0xFF, 0x0A, 0x22, 0x00});
     597           1 :   ASSERT_TRUE(value->IsString());
     598           2 :   EXPECT_EQ(0, String::Cast(*value)->Length());
     599             : 
     600           2 :   value = DecodeTest({0xFF, 0x0A, 0x22, 0x05, 'H', 'e', 'l', 'l', 'o'});
     601           1 :   ASSERT_TRUE(value->IsString());
     602           2 :   EXPECT_EQ(5, String::Cast(*value)->Length());
     603           2 :   EXPECT_EQ(kHelloString, Utf8Value(value));
     604             : 
     605           2 :   value = DecodeTest({0xFF, 0x0A, 0x22, 0x06, 'Q', 'u', 0xE9, 'b', 'e', 'c'});
     606           1 :   ASSERT_TRUE(value->IsString());
     607           2 :   EXPECT_EQ(6, String::Cast(*value)->Length());
     608           2 :   EXPECT_EQ(kQuebecString, Utf8Value(value));
     609             : 
     610             : // And from two-byte strings (endianness dependent).
     611             : #if defined(V8_TARGET_LITTLE_ENDIAN)
     612           2 :   value = DecodeTest({0xFF, 0x09, 0x63, 0x00});
     613           1 :   ASSERT_TRUE(value->IsString());
     614           2 :   EXPECT_EQ(0, String::Cast(*value)->Length());
     615             : 
     616             :   value = DecodeTest({0xFF, 0x09, 0x63, 0x0A, 'H', '\0', 'e', '\0', 'l', '\0',
     617           2 :                       'l', '\0', 'o', '\0'});
     618           1 :   ASSERT_TRUE(value->IsString());
     619           2 :   EXPECT_EQ(5, String::Cast(*value)->Length());
     620           2 :   EXPECT_EQ(kHelloString, Utf8Value(value));
     621             : 
     622             :   value = DecodeTest({0xFF, 0x09, 0x63, 0x0C, 'Q', '\0', 'u', '\0', 0xE9, '\0',
     623           2 :                       'b', '\0', 'e', '\0', 'c', '\0'});
     624           1 :   ASSERT_TRUE(value->IsString());
     625           2 :   EXPECT_EQ(6, String::Cast(*value)->Length());
     626           2 :   EXPECT_EQ(kQuebecString, Utf8Value(value));
     627             : 
     628           2 :   value = DecodeTest({0xFF, 0x09, 0x63, 0x04, 0x3D, 0xD8, 0x4A, 0xDC});
     629           1 :   ASSERT_TRUE(value->IsString());
     630           2 :   EXPECT_EQ(2, String::Cast(*value)->Length());
     631           2 :   EXPECT_EQ(kEmojiString, Utf8Value(value));
     632             : #endif
     633             :   // TODO(jbroman): The same for big-endian systems.
     634             : }
     635             : 
     636       15444 : TEST_F(ValueSerializerTest, DecodeInvalidString) {
     637             :   // UTF-8 string with too few bytes available.
     638           2 :   InvalidDecodeTest({0xFF, 0x09, 0x53, 0x10, 'v', '8'});
     639             :   // One-byte string with too few bytes available.
     640           2 :   InvalidDecodeTest({0xFF, 0x0A, 0x22, 0x10, 'v', '8'});
     641             : #if defined(V8_TARGET_LITTLE_ENDIAN)
     642             :   // Two-byte string with too few bytes available.
     643           2 :   InvalidDecodeTest({0xFF, 0x09, 0x63, 0x10, 'v', '\0', '8', '\0'});
     644             :   // Two-byte string with an odd byte length.
     645           2 :   InvalidDecodeTest({0xFF, 0x09, 0x63, 0x03, 'v', '\0', '8'});
     646             : #endif
     647             :   // TODO(jbroman): The same for big-endian systems.
     648           1 : }
     649             : 
     650       15444 : TEST_F(ValueSerializerTest, EncodeTwoByteStringUsesPadding) {
     651             :   // As long as the output has a version that Blink expects to be able to read,
     652             :   // we must respect its alignment requirements. It requires that two-byte
     653             :   // characters be aligned.
     654             :   // We need a string whose length will take two bytes to encode, so that
     655             :   // a padding byte is needed to keep the characters aligned. The string
     656             :   // must also have a two-byte character, so that it gets the two-byte
     657             :   // encoding.
     658             :   std::string string(200, ' ');
     659             :   string += kEmojiString;
     660           2 :   const std::vector<uint8_t> data = EncodeTest(StringFromUtf8(string.c_str()));
     661             :   // This is a sufficient but not necessary condition. This test assumes
     662             :   // that the wire format version is one byte long, but is flexible to
     663             :   // what that value may be.
     664           1 :   const uint8_t expected_prefix[] = {0x00, 0x63, 0x94, 0x03};
     665           2 :   ASSERT_GT(data.size(), sizeof(expected_prefix) + 2);
     666           2 :   EXPECT_EQ(0xFF, data[0]);
     667           2 :   EXPECT_GE(data[1], 0x09);
     668           2 :   EXPECT_LE(data[1], 0x7F);
     669           1 :   EXPECT_TRUE(std::equal(std::begin(expected_prefix), std::end(expected_prefix),
     670           0 :                          data.begin() + 2));
     671             : }
     672             : 
     673       15444 : TEST_F(ValueSerializerTest, RoundTripDictionaryObject) {
     674             :   // Empty object.
     675           1 :   Local<Value> value = RoundTripTest("({})");
     676           2 :   ASSERT_TRUE(value->IsObject());
     677           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Object.prototype");
     678           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 0");
     679             : 
     680             :   // String key.
     681             :   value = RoundTripTest("({ a: 42 })");
     682           2 :   ASSERT_TRUE(value->IsObject());
     683           1 :   ExpectScriptTrue("result.hasOwnProperty('a')");
     684           1 :   ExpectScriptTrue("result.a === 42");
     685           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     686             : 
     687             :   // Integer key (treated as a string, but may be encoded differently).
     688             :   value = RoundTripTest("({ 42: 'a' })");
     689           2 :   ASSERT_TRUE(value->IsObject());
     690           1 :   ExpectScriptTrue("result.hasOwnProperty('42')");
     691           1 :   ExpectScriptTrue("result[42] === 'a'");
     692           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     693             : 
     694             :   // Key order must be preserved.
     695             :   value = RoundTripTest("({ x: 1, y: 2, a: 3 })");
     696           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).toString() === 'x,y,a'");
     697             : 
     698             :   // A harder case of enumeration order.
     699             :   // Indexes first, in order (but not 2^32 - 1, which is not an index), then the
     700             :   // remaining (string) keys, in the order they were defined.
     701             :   value = RoundTripTest("({ a: 2, 0xFFFFFFFF: 1, 0xFFFFFFFE: 3, 1: 0 })");
     702             :   ExpectScriptTrue(
     703             :       "Object.getOwnPropertyNames(result).toString() === "
     704           1 :       "'1,4294967294,a,4294967295'");
     705           1 :   ExpectScriptTrue("result.a === 2");
     706           1 :   ExpectScriptTrue("result[0xFFFFFFFF] === 1");
     707           1 :   ExpectScriptTrue("result[0xFFFFFFFE] === 3");
     708           1 :   ExpectScriptTrue("result[1] === 0");
     709             : 
     710             :   // This detects a fairly subtle case: the object itself must be in the map
     711             :   // before its properties are deserialized, so that references to it can be
     712             :   // resolved.
     713             :   value = RoundTripTest("var y = {}; y.self = y; y;");
     714           2 :   ASSERT_TRUE(value->IsObject());
     715           1 :   ExpectScriptTrue("result === result.self");
     716             : }
     717             : 
     718       15444 : TEST_F(ValueSerializerTest, DecodeDictionaryObject) {
     719             :   // Empty object.
     720             :   Local<Value> value =
     721           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x7B, 0x00, 0x00});
     722           2 :   ASSERT_TRUE(value->IsObject());
     723           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Object.prototype");
     724           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 0");
     725             : 
     726             :   // String key.
     727             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x01,
     728           2 :                       0x61, 0x3F, 0x01, 0x49, 0x54, 0x7B, 0x01});
     729           2 :   ASSERT_TRUE(value->IsObject());
     730           1 :   ExpectScriptTrue("result.hasOwnProperty('a')");
     731           1 :   ExpectScriptTrue("result.a === 42");
     732           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     733             : 
     734             :   // Integer key (treated as a string, but may be encoded differently).
     735             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x49, 0x54,
     736           2 :                       0x3F, 0x01, 0x53, 0x01, 0x61, 0x7B, 0x01});
     737           2 :   ASSERT_TRUE(value->IsObject());
     738           1 :   ExpectScriptTrue("result.hasOwnProperty('42')");
     739           1 :   ExpectScriptTrue("result[42] === 'a'");
     740           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     741             : 
     742             :   // Key order must be preserved.
     743             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x01,
     744             :                       0x78, 0x3F, 0x01, 0x49, 0x02, 0x3F, 0x01, 0x53, 0x01,
     745             :                       0x79, 0x3F, 0x01, 0x49, 0x04, 0x3F, 0x01, 0x53, 0x01,
     746           2 :                       0x61, 0x3F, 0x01, 0x49, 0x06, 0x7B, 0x03});
     747           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).toString() === 'x,y,a'");
     748             : 
     749             :   // A harder case of enumeration order.
     750             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x49, 0x02,
     751             :                       0x3F, 0x01, 0x49, 0x00, 0x3F, 0x01, 0x55, 0xFE, 0xFF,
     752             :                       0xFF, 0xFF, 0x0F, 0x3F, 0x01, 0x49, 0x06, 0x3F, 0x01,
     753             :                       0x53, 0x01, 0x61, 0x3F, 0x01, 0x49, 0x04, 0x3F, 0x01,
     754             :                       0x53, 0x0A, 0x34, 0x32, 0x39, 0x34, 0x39, 0x36, 0x37,
     755           2 :                       0x32, 0x39, 0x35, 0x3F, 0x01, 0x49, 0x02, 0x7B, 0x04});
     756             :   ExpectScriptTrue(
     757             :       "Object.getOwnPropertyNames(result).toString() === "
     758           1 :       "'1,4294967294,a,4294967295'");
     759           1 :   ExpectScriptTrue("result.a === 2");
     760           1 :   ExpectScriptTrue("result[0xFFFFFFFF] === 1");
     761           1 :   ExpectScriptTrue("result[0xFFFFFFFE] === 3");
     762           1 :   ExpectScriptTrue("result[1] === 0");
     763             : 
     764             :   // This detects a fairly subtle case: the object itself must be in the map
     765             :   // before its properties are deserialized, so that references to it can be
     766             :   // resolved.
     767             :   value =
     768             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x04, 0x73,
     769           2 :                   0x65, 0x6C, 0x66, 0x3F, 0x01, 0x5E, 0x00, 0x7B, 0x01, 0x00});
     770           2 :   ASSERT_TRUE(value->IsObject());
     771           1 :   ExpectScriptTrue("result === result.self");
     772             : }
     773             : 
     774       15444 : TEST_F(ValueSerializerTest, InvalidDecodeObjectWithInvalidKeyType) {
     775             :   // Objects which would need conversion to string shouldn't be present as
     776             :   // object keys. The serializer would have obtained them from the own property
     777             :   // keys list, which should only contain names and indices.
     778           2 :   InvalidDecodeTest(
     779           1 :       {0xFF, 0x09, 0x6F, 0x61, 0x00, 0x40, 0x00, 0x00, 0x7B, 0x01});
     780           1 : }
     781             : 
     782       15444 : TEST_F(ValueSerializerTest, RoundTripOnlyOwnEnumerableStringKeys) {
     783             :   // Only "own" properties should be serialized, not ones on the prototype.
     784           1 :   Local<Value> value = RoundTripTest("var x = {}; x.__proto__ = {a: 4}; x;");
     785           1 :   ExpectScriptTrue("!('a' in result)");
     786             : 
     787             :   // Only enumerable properties should be serialized.
     788             :   value = RoundTripTest(
     789             :       "var x = {};"
     790             :       "Object.defineProperty(x, 'a', {value: 1, enumerable: false});"
     791             :       "x;");
     792           1 :   ExpectScriptTrue("!('a' in result)");
     793             : 
     794             :   // Symbol keys should not be serialized.
     795             :   value = RoundTripTest("({ [Symbol()]: 4 })");
     796           1 :   ExpectScriptTrue("Object.getOwnPropertySymbols(result).length === 0");
     797           1 : }
     798             : 
     799       15444 : TEST_F(ValueSerializerTest, RoundTripTrickyGetters) {
     800             :   // Keys are enumerated before any setters are called, but if there is no own
     801             :   // property when the value is to be read, then it should not be serialized.
     802             :   Local<Value> value =
     803           1 :       RoundTripTest("({ get a() { delete this.b; return 1; }, b: 2 })");
     804           1 :   ExpectScriptTrue("!('b' in result)");
     805             : 
     806             :   // Keys added after the property enumeration should not be serialized.
     807             :   value = RoundTripTest("({ get a() { this.b = 3; }})");
     808           1 :   ExpectScriptTrue("!('b' in result)");
     809             : 
     810             :   // But if you remove a key and add it back, that's fine. But it will appear in
     811             :   // the original place in enumeration order.
     812             :   value =
     813             :       RoundTripTest("({ get a() { delete this.b; this.b = 4; }, b: 2, c: 3 })");
     814           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).toString() === 'a,b,c'");
     815           1 :   ExpectScriptTrue("result.b === 4");
     816             : 
     817             :   // Similarly, it only matters if a property was enumerable when the
     818             :   // enumeration happened.
     819             :   value = RoundTripTest(
     820             :       "({ get a() {"
     821             :       "    Object.defineProperty(this, 'b', {value: 2, enumerable: false});"
     822             :       "}, b: 1})");
     823           1 :   ExpectScriptTrue("result.b === 2");
     824             : 
     825             :   value = RoundTripTest(
     826             :       "var x = {"
     827             :       "  get a() {"
     828             :       "    Object.defineProperty(this, 'b', {value: 2, enumerable: true});"
     829             :       "  }"
     830             :       "};"
     831             :       "Object.defineProperty(x, 'b',"
     832             :       "    {value: 1, enumerable: false, configurable: true});"
     833             :       "x;");
     834           1 :   ExpectScriptTrue("!('b' in result)");
     835             : 
     836             :   // The property also should not be read if it can only be found on the
     837             :   // prototype chain (but not as an own property) after enumeration.
     838             :   value = RoundTripTest(
     839             :       "var x = { get a() { delete this.b; }, b: 1 };"
     840             :       "x.__proto__ = { b: 0 };"
     841             :       "x;");
     842           1 :   ExpectScriptTrue("!('b' in result)");
     843             : 
     844             :   // If an exception is thrown by script, encoding must fail and the exception
     845             :   // must be thrown.
     846             :   Local<Message> message =
     847             :       InvalidEncodeTest("({ get a() { throw new Error('sentinel'); } })");
     848           2 :   ASSERT_FALSE(message.IsEmpty());
     849           4 :   EXPECT_NE(std::string::npos, Utf8Value(message->Get()).find("sentinel"));
     850             : }
     851             : 
     852       15444 : TEST_F(ValueSerializerTest, RoundTripDictionaryObjectForTransitions) {
     853             :   // A case which should run on the fast path, and should reach all of the
     854             :   // different cases:
     855             :   // 1. no known transition (first time creating this kind of object)
     856             :   // 2. expected transitions match to end
     857             :   // 3. transition partially matches, but falls back due to new property 'w'
     858             :   // 4. transition to 'z' is now a full transition (needs to be looked up)
     859             :   // 5. same for 'w'
     860             :   // 6. new property after complex transition succeeded
     861             :   // 7. new property after complex transition failed (due to new property)
     862           1 :   RoundTripJSON(
     863             :       "[{\"x\":1,\"y\":2,\"z\":3}"
     864             :       ",{\"x\":4,\"y\":5,\"z\":6}"
     865             :       ",{\"x\":5,\"y\":6,\"w\":7}"
     866             :       ",{\"x\":6,\"y\":7,\"z\":8}"
     867             :       ",{\"x\":0,\"y\":0,\"w\":0}"
     868             :       ",{\"x\":3,\"y\":1,\"w\":4,\"z\":1}"
     869           1 :       ",{\"x\":5,\"y\":9,\"k\":2,\"z\":6}]");
     870             :   // A simpler case that uses two-byte strings.
     871             :   RoundTripJSON(
     872             :       "[{\"\xF0\x9F\x91\x8A\":1,\"\xF0\x9F\x91\x8B\":2}"
     873             :       ",{\"\xF0\x9F\x91\x8A\":3,\"\xF0\x9F\x91\x8C\":4}"
     874           1 :       ",{\"\xF0\x9F\x91\x8A\":5,\"\xF0\x9F\x91\x9B\":6}]");
     875           1 : }
     876             : 
     877       15444 : TEST_F(ValueSerializerTest, DecodeDictionaryObjectVersion0) {
     878             :   // Empty object.
     879           2 :   Local<Value> value = DecodeTestForVersion0({0x7B, 0x00});
     880           2 :   ASSERT_TRUE(value->IsObject());
     881           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Object.prototype");
     882           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 0");
     883             : 
     884             :   // String key.
     885             :   value =
     886           2 :       DecodeTestForVersion0({0x53, 0x01, 0x61, 0x49, 0x54, 0x7B, 0x01, 0x00});
     887           2 :   ASSERT_TRUE(value->IsObject());
     888           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Object.prototype");
     889           1 :   ExpectScriptTrue("result.hasOwnProperty('a')");
     890           1 :   ExpectScriptTrue("result.a === 42");
     891           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     892             : 
     893             :   // Integer key (treated as a string, but may be encoded differently).
     894             :   value =
     895           2 :       DecodeTestForVersion0({0x49, 0x54, 0x53, 0x01, 0x61, 0x7B, 0x01, 0x00});
     896           2 :   ASSERT_TRUE(value->IsObject());
     897           1 :   ExpectScriptTrue("result.hasOwnProperty('42')");
     898           1 :   ExpectScriptTrue("result[42] === 'a'");
     899           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).length === 1");
     900             : 
     901             :   // Key order must be preserved.
     902             :   value = DecodeTestForVersion0({0x53, 0x01, 0x78, 0x49, 0x02, 0x53, 0x01, 0x79,
     903             :                                  0x49, 0x04, 0x53, 0x01, 0x61, 0x49, 0x06, 0x7B,
     904           2 :                                  0x03, 0x00});
     905           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).toString() === 'x,y,a'");
     906             : 
     907             :   // A property and an element.
     908             :   value = DecodeTestForVersion0(
     909           2 :       {0x49, 0x54, 0x53, 0x01, 0x61, 0x53, 0x01, 0x61, 0x49, 0x54, 0x7B, 0x02});
     910           1 :   ExpectScriptTrue("Object.getOwnPropertyNames(result).toString() === '42,a'");
     911           1 :   ExpectScriptTrue("result[42] === 'a'");
     912           1 :   ExpectScriptTrue("result.a === 42");
     913             : }
     914             : 
     915       15444 : TEST_F(ValueSerializerTest, RoundTripArray) {
     916             :   // A simple array of integers.
     917           1 :   Local<Value> value = RoundTripTest("[1, 2, 3, 4, 5]");
     918           2 :   ASSERT_TRUE(value->IsArray());
     919           2 :   EXPECT_EQ(5u, Array::Cast(*value)->Length());
     920           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Array.prototype");
     921           1 :   ExpectScriptTrue("result.toString() === '1,2,3,4,5'");
     922             : 
     923             :   // A long (sparse) array.
     924             :   value = RoundTripTest("var x = new Array(1000); x[500] = 42; x;");
     925           2 :   ASSERT_TRUE(value->IsArray());
     926           2 :   EXPECT_EQ(1000u, Array::Cast(*value)->Length());
     927           1 :   ExpectScriptTrue("result[500] === 42");
     928             : 
     929             :   // Duplicate reference.
     930             :   value = RoundTripTest("var y = {}; [y, y];");
     931           2 :   ASSERT_TRUE(value->IsArray());
     932           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
     933           1 :   ExpectScriptTrue("result[0] === result[1]");
     934             : 
     935             :   // Duplicate reference in a sparse array.
     936             :   value = RoundTripTest("var x = new Array(1000); x[1] = x[500] = {}; x;");
     937           2 :   ASSERT_TRUE(value->IsArray());
     938           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
     939           1 :   ExpectScriptTrue("typeof result[1] === 'object'");
     940           1 :   ExpectScriptTrue("result[1] === result[500]");
     941             : 
     942             :   // Self reference.
     943             :   value = RoundTripTest("var y = []; y[0] = y; y;");
     944           2 :   ASSERT_TRUE(value->IsArray());
     945           2 :   ASSERT_EQ(1u, Array::Cast(*value)->Length());
     946           1 :   ExpectScriptTrue("result[0] === result");
     947             : 
     948             :   // Self reference in a sparse array.
     949             :   value = RoundTripTest("var y = new Array(1000); y[519] = y; y;");
     950           2 :   ASSERT_TRUE(value->IsArray());
     951           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
     952           1 :   ExpectScriptTrue("result[519] === result");
     953             : 
     954             :   // Array with additional properties.
     955             :   value = RoundTripTest("var y = [1, 2]; y.foo = 'bar'; y;");
     956           2 :   ASSERT_TRUE(value->IsArray());
     957           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
     958           1 :   ExpectScriptTrue("result.toString() === '1,2'");
     959           1 :   ExpectScriptTrue("result.foo === 'bar'");
     960             : 
     961             :   // Sparse array with additional properties.
     962             :   value = RoundTripTest("var y = new Array(1000); y.foo = 'bar'; y;");
     963           2 :   ASSERT_TRUE(value->IsArray());
     964           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
     965           1 :   ExpectScriptTrue("result.toString() === ','.repeat(999)");
     966           1 :   ExpectScriptTrue("result.foo === 'bar'");
     967             : 
     968             :   // The distinction between holes and undefined elements must be maintained.
     969             :   value = RoundTripTest("[,undefined]");
     970           2 :   ASSERT_TRUE(value->IsArray());
     971           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
     972           1 :   ExpectScriptTrue("typeof result[0] === 'undefined'");
     973           1 :   ExpectScriptTrue("typeof result[1] === 'undefined'");
     974           1 :   ExpectScriptTrue("!result.hasOwnProperty(0)");
     975           1 :   ExpectScriptTrue("result.hasOwnProperty(1)");
     976             : }
     977             : 
     978       15444 : TEST_F(ValueSerializerTest, DecodeArray) {
     979             :   // A simple array of integers.
     980             :   Local<Value> value =
     981             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x41, 0x05, 0x3F, 0x01, 0x49, 0x02,
     982             :                   0x3F, 0x01, 0x49, 0x04, 0x3F, 0x01, 0x49, 0x06, 0x3F, 0x01,
     983           2 :                   0x49, 0x08, 0x3F, 0x01, 0x49, 0x0A, 0x24, 0x00, 0x05, 0x00});
     984           2 :   ASSERT_TRUE(value->IsArray());
     985           2 :   EXPECT_EQ(5u, Array::Cast(*value)->Length());
     986           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Array.prototype");
     987           1 :   ExpectScriptTrue("result.toString() === '1,2,3,4,5'");
     988             : 
     989             :   // A long (sparse) array.
     990             :   value =
     991             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x61, 0xE8, 0x07, 0x3F, 0x01, 0x49,
     992           2 :                   0xE8, 0x07, 0x3F, 0x01, 0x49, 0x54, 0x40, 0x01, 0xE8, 0x07});
     993           2 :   ASSERT_TRUE(value->IsArray());
     994           2 :   EXPECT_EQ(1000u, Array::Cast(*value)->Length());
     995           1 :   ExpectScriptTrue("result[500] === 42");
     996             : 
     997             :   // Duplicate reference.
     998             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x41, 0x02, 0x3F, 0x01, 0x6F,
     999           2 :                       0x7B, 0x00, 0x3F, 0x02, 0x5E, 0x01, 0x24, 0x00, 0x02});
    1000           2 :   ASSERT_TRUE(value->IsArray());
    1001           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1002           1 :   ExpectScriptTrue("result[0] === result[1]");
    1003             : 
    1004             :   // Duplicate reference in a sparse array.
    1005             :   value =
    1006             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x61, 0xE8, 0x07, 0x3F, 0x01, 0x49,
    1007             :                   0x02, 0x3F, 0x01, 0x6F, 0x7B, 0x00, 0x3F, 0x02, 0x49, 0xE8,
    1008           2 :                   0x07, 0x3F, 0x02, 0x5E, 0x01, 0x40, 0x02, 0xE8, 0x07, 0x00});
    1009           2 :   ASSERT_TRUE(value->IsArray());
    1010           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1011           1 :   ExpectScriptTrue("typeof result[1] === 'object'");
    1012           1 :   ExpectScriptTrue("result[1] === result[500]");
    1013             : 
    1014             :   // Self reference.
    1015             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x41, 0x01, 0x3F, 0x01, 0x5E,
    1016           2 :                       0x00, 0x24, 0x00, 0x01, 0x00});
    1017           2 :   ASSERT_TRUE(value->IsArray());
    1018           2 :   ASSERT_EQ(1u, Array::Cast(*value)->Length());
    1019           1 :   ExpectScriptTrue("result[0] === result");
    1020             : 
    1021             :   // Self reference in a sparse array.
    1022             :   value =
    1023             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x61, 0xE8, 0x07, 0x3F, 0x01, 0x49,
    1024           2 :                   0x8E, 0x08, 0x3F, 0x01, 0x5E, 0x00, 0x40, 0x01, 0xE8, 0x07});
    1025           2 :   ASSERT_TRUE(value->IsArray());
    1026           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1027           1 :   ExpectScriptTrue("result[519] === result");
    1028             : 
    1029             :   // Array with additional properties.
    1030             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x41, 0x02, 0x3F, 0x01,
    1031             :                       0x49, 0x02, 0x3F, 0x01, 0x49, 0x04, 0x3F, 0x01,
    1032             :                       0x53, 0x03, 0x66, 0x6F, 0x6F, 0x3F, 0x01, 0x53,
    1033           2 :                       0x03, 0x62, 0x61, 0x72, 0x24, 0x01, 0x02, 0x00});
    1034           2 :   ASSERT_TRUE(value->IsArray());
    1035           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1036           1 :   ExpectScriptTrue("result.toString() === '1,2'");
    1037           1 :   ExpectScriptTrue("result.foo === 'bar'");
    1038             : 
    1039             :   // Sparse array with additional properties.
    1040             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x61, 0xE8, 0x07, 0x3F, 0x01,
    1041             :                       0x53, 0x03, 0x66, 0x6F, 0x6F, 0x3F, 0x01, 0x53, 0x03,
    1042           2 :                       0x62, 0x61, 0x72, 0x40, 0x01, 0xE8, 0x07, 0x00});
    1043           2 :   ASSERT_TRUE(value->IsArray());
    1044           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1045           1 :   ExpectScriptTrue("result.toString() === ','.repeat(999)");
    1046           1 :   ExpectScriptTrue("result.foo === 'bar'");
    1047             : 
    1048             :   // The distinction between holes and undefined elements must be maintained.
    1049             :   // Note that since the previous output from Chrome fails this test, an
    1050             :   // encoding using the sparse format was constructed instead.
    1051             :   value =
    1052           2 :       DecodeTest({0xFF, 0x09, 0x61, 0x02, 0x49, 0x02, 0x5F, 0x40, 0x01, 0x02});
    1053           2 :   ASSERT_TRUE(value->IsArray());
    1054           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1055           1 :   ExpectScriptTrue("typeof result[0] === 'undefined'");
    1056           1 :   ExpectScriptTrue("typeof result[1] === 'undefined'");
    1057           1 :   ExpectScriptTrue("!result.hasOwnProperty(0)");
    1058           1 :   ExpectScriptTrue("result.hasOwnProperty(1)");
    1059             : }
    1060             : 
    1061       15444 : TEST_F(ValueSerializerTest, DecodeInvalidOverLargeArray) {
    1062             :   // So large it couldn't exist in the V8 heap, and its size couldn't fit in a
    1063             :   // SMI on 32-bit systems (2^30).
    1064           2 :   InvalidDecodeTest({0xFF, 0x09, 0x41, 0x80, 0x80, 0x80, 0x80, 0x04});
    1065             :   // Not so large, but there isn't enough data left in the buffer.
    1066           2 :   InvalidDecodeTest({0xFF, 0x09, 0x41, 0x01});
    1067           1 : }
    1068             : 
    1069       15444 : TEST_F(ValueSerializerTest, RoundTripArrayWithNonEnumerableElement) {
    1070             :   // Even though this array looks like [1,5,3], the 5 should be missing from the
    1071             :   // perspective of structured clone, which only clones properties that were
    1072             :   // enumerable.
    1073             :   Local<Value> value = RoundTripTest(
    1074             :       "var x = [1,2,3];"
    1075             :       "Object.defineProperty(x, '1', {enumerable:false, value:5});"
    1076           1 :       "x;");
    1077           2 :   ASSERT_TRUE(value->IsArray());
    1078           2 :   ASSERT_EQ(3u, Array::Cast(*value)->Length());
    1079           1 :   ExpectScriptTrue("!result.hasOwnProperty('1')");
    1080             : }
    1081             : 
    1082       15444 : TEST_F(ValueSerializerTest, RoundTripArrayWithTrickyGetters) {
    1083             :   // If an element is deleted before it is serialized, then it's deleted.
    1084             :   Local<Value> value =
    1085           1 :       RoundTripTest("var x = [{ get a() { delete x[1]; }}, 42]; x;");
    1086           2 :   ASSERT_TRUE(value->IsArray());
    1087           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1088           1 :   ExpectScriptTrue("typeof result[1] === 'undefined'");
    1089           1 :   ExpectScriptTrue("!result.hasOwnProperty(1)");
    1090             : 
    1091             :   // Same for sparse arrays.
    1092             :   value = RoundTripTest(
    1093             :       "var x = [{ get a() { delete x[1]; }}, 42];"
    1094             :       "x.length = 1000;"
    1095             :       "x;");
    1096           2 :   ASSERT_TRUE(value->IsArray());
    1097           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1098           1 :   ExpectScriptTrue("typeof result[1] === 'undefined'");
    1099           1 :   ExpectScriptTrue("!result.hasOwnProperty(1)");
    1100             : 
    1101             :   // If the length is changed, then the resulting array still has the original
    1102             :   // length, but elements that were not yet serialized are gone.
    1103             :   value = RoundTripTest("var x = [1, { get a() { x.length = 0; }}, 3, 4]; x;");
    1104           2 :   ASSERT_TRUE(value->IsArray());
    1105           2 :   ASSERT_EQ(4u, Array::Cast(*value)->Length());
    1106           1 :   ExpectScriptTrue("result[0] === 1");
    1107           1 :   ExpectScriptTrue("!result.hasOwnProperty(2)");
    1108             : 
    1109             :   // The same is true if the length is shortened, but there are still items
    1110             :   // remaining.
    1111             :   value = RoundTripTest("var x = [1, { get a() { x.length = 3; }}, 3, 4]; x;");
    1112           2 :   ASSERT_TRUE(value->IsArray());
    1113           2 :   ASSERT_EQ(4u, Array::Cast(*value)->Length());
    1114           1 :   ExpectScriptTrue("result[2] === 3");
    1115           1 :   ExpectScriptTrue("!result.hasOwnProperty(3)");
    1116             : 
    1117             :   // Same for sparse arrays.
    1118             :   value = RoundTripTest(
    1119             :       "var x = [1, { get a() { x.length = 0; }}, 3, 4];"
    1120             :       "x.length = 1000;"
    1121             :       "x;");
    1122           2 :   ASSERT_TRUE(value->IsArray());
    1123           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1124           1 :   ExpectScriptTrue("result[0] === 1");
    1125           1 :   ExpectScriptTrue("!result.hasOwnProperty(2)");
    1126             : 
    1127             :   value = RoundTripTest(
    1128             :       "var x = [1, { get a() { x.length = 3; }}, 3, 4];"
    1129             :       "x.length = 1000;"
    1130             :       "x;");
    1131           2 :   ASSERT_TRUE(value->IsArray());
    1132           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1133           1 :   ExpectScriptTrue("result[2] === 3");
    1134           1 :   ExpectScriptTrue("!result.hasOwnProperty(3)");
    1135             : 
    1136             :   // If a getter makes a property non-enumerable, it should still be enumerated
    1137             :   // as enumeration happens once before getters are invoked.
    1138             :   value = RoundTripTest(
    1139             :       "var x = [{ get a() {"
    1140             :       "  Object.defineProperty(x, '1', { value: 3, enumerable: false });"
    1141             :       "}}, 2];"
    1142             :       "x;");
    1143           2 :   ASSERT_TRUE(value->IsArray());
    1144           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1145           1 :   ExpectScriptTrue("result[1] === 3");
    1146             : 
    1147             :   // Same for sparse arrays.
    1148             :   value = RoundTripTest(
    1149             :       "var x = [{ get a() {"
    1150             :       "  Object.defineProperty(x, '1', { value: 3, enumerable: false });"
    1151             :       "}}, 2];"
    1152             :       "x.length = 1000;"
    1153             :       "x;");
    1154           2 :   ASSERT_TRUE(value->IsArray());
    1155           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1156           1 :   ExpectScriptTrue("result[1] === 3");
    1157             : 
    1158             :   // Getters on the array itself must also run.
    1159             :   value = RoundTripTest(
    1160             :       "var x = [1, 2, 3];"
    1161             :       "Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
    1162             :       "x;");
    1163           2 :   ASSERT_TRUE(value->IsArray());
    1164           2 :   ASSERT_EQ(3u, Array::Cast(*value)->Length());
    1165           1 :   ExpectScriptTrue("result[1] === 4");
    1166             : 
    1167             :   // Same for sparse arrays.
    1168             :   value = RoundTripTest(
    1169             :       "var x = [1, 2, 3];"
    1170             :       "Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
    1171             :       "x.length = 1000;"
    1172             :       "x;");
    1173           2 :   ASSERT_TRUE(value->IsArray());
    1174           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1175           1 :   ExpectScriptTrue("result[1] === 4");
    1176             : 
    1177             :   // Even with a getter that deletes things, we don't read from the prototype.
    1178             :   value = RoundTripTest(
    1179             :       "var x = [{ get a() { delete x[1]; } }, 2];"
    1180             :       "x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
    1181             :       "x;");
    1182           2 :   ASSERT_TRUE(value->IsArray());
    1183           2 :   ASSERT_EQ(2u, Array::Cast(*value)->Length());
    1184           1 :   ExpectScriptTrue("!(1 in result)");
    1185             : 
    1186             :   // Same for sparse arrays.
    1187             :   value = RoundTripTest(
    1188             :       "var x = [{ get a() { delete x[1]; } }, 2];"
    1189             :       "x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
    1190             :       "x.length = 1000;"
    1191             :       "x;");
    1192           2 :   ASSERT_TRUE(value->IsArray());
    1193           2 :   ASSERT_EQ(1000u, Array::Cast(*value)->Length());
    1194           1 :   ExpectScriptTrue("!(1 in result)");
    1195             : }
    1196             : 
    1197       15444 : TEST_F(ValueSerializerTest, DecodeSparseArrayVersion0) {
    1198             :   // Empty (sparse) array.
    1199           2 :   Local<Value> value = DecodeTestForVersion0({0x40, 0x00, 0x00, 0x00});
    1200           2 :   ASSERT_TRUE(value->IsArray());
    1201           2 :   ASSERT_EQ(0u, Array::Cast(*value)->Length());
    1202             : 
    1203             :   // Sparse array with a mixture of elements and properties.
    1204             :   value = DecodeTestForVersion0({0x55, 0x00, 0x53, 0x01, 'a',  0x55, 0x02, 0x55,
    1205             :                                  0x05, 0x53, 0x03, 'f',  'o',  'o',  0x53, 0x03,
    1206             :                                  'b',  'a',  'r',  0x53, 0x03, 'b',  'a',  'z',
    1207           2 :                                  0x49, 0x0B, 0x40, 0x04, 0x03, 0x00});
    1208           2 :   ASSERT_TRUE(value->IsArray());
    1209           2 :   EXPECT_EQ(3u, Array::Cast(*value)->Length());
    1210           1 :   ExpectScriptTrue("result.toString() === 'a,,5'");
    1211           1 :   ExpectScriptTrue("!(1 in result)");
    1212           1 :   ExpectScriptTrue("result.foo === 'bar'");
    1213           1 :   ExpectScriptTrue("result.baz === -6");
    1214             : 
    1215             :   // Sparse array in a sparse array (sanity check of nesting).
    1216             :   value = DecodeTestForVersion0(
    1217           2 :       {0x55, 0x01, 0x55, 0x01, 0x54, 0x40, 0x01, 0x02, 0x40, 0x01, 0x02, 0x00});
    1218           2 :   ASSERT_TRUE(value->IsArray());
    1219           2 :   EXPECT_EQ(2u, Array::Cast(*value)->Length());
    1220           1 :   ExpectScriptTrue("!(0 in result)");
    1221           1 :   ExpectScriptTrue("result[1] instanceof Array");
    1222           1 :   ExpectScriptTrue("!(0 in result[1])");
    1223           1 :   ExpectScriptTrue("result[1][1] === true");
    1224             : }
    1225             : 
    1226       15444 : TEST_F(ValueSerializerTest, RoundTripDenseArrayContainingUndefined) {
    1227             :   // In previous serialization versions, this would be interpreted as an absent
    1228             :   // property.
    1229           1 :   Local<Value> value = RoundTripTest("[undefined]");
    1230           2 :   ASSERT_TRUE(value->IsArray());
    1231           2 :   EXPECT_EQ(1u, Array::Cast(*value)->Length());
    1232           1 :   ExpectScriptTrue("result.hasOwnProperty(0)");
    1233           1 :   ExpectScriptTrue("result[0] === undefined");
    1234             : }
    1235             : 
    1236       15444 : TEST_F(ValueSerializerTest, DecodeDenseArrayContainingUndefined) {
    1237             :   // In previous versions, "undefined" in a dense array signified absence of the
    1238             :   // element (for compatibility). In new versions, it has a separate encoding.
    1239             :   Local<Value> value =
    1240           2 :       DecodeTest({0xFF, 0x09, 0x41, 0x01, 0x5F, 0x24, 0x00, 0x01});
    1241           1 :   ExpectScriptTrue("!(0 in result)");
    1242             : 
    1243           2 :   value = DecodeTest({0xFF, 0x0B, 0x41, 0x01, 0x5F, 0x24, 0x00, 0x01});
    1244           1 :   ExpectScriptTrue("0 in result");
    1245           1 :   ExpectScriptTrue("result[0] === undefined");
    1246             : 
    1247           2 :   value = DecodeTest({0xFF, 0x0B, 0x41, 0x01, 0x2D, 0x24, 0x00, 0x01});
    1248           1 :   ExpectScriptTrue("!(0 in result)");
    1249           1 : }
    1250             : 
    1251       15444 : TEST_F(ValueSerializerTest, RoundTripDate) {
    1252           1 :   Local<Value> value = RoundTripTest("new Date(1e6)");
    1253           2 :   ASSERT_TRUE(value->IsDate());
    1254           2 :   EXPECT_EQ(1e6, Date::Cast(*value)->ValueOf());
    1255           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Date.prototype");
    1256             : 
    1257             :   value = RoundTripTest("new Date(Date.UTC(1867, 6, 1))");
    1258           2 :   ASSERT_TRUE(value->IsDate());
    1259           1 :   ExpectScriptTrue("result.toISOString() === '1867-07-01T00:00:00.000Z'");
    1260             : 
    1261             :   value = RoundTripTest("new Date(NaN)");
    1262           2 :   ASSERT_TRUE(value->IsDate());
    1263           2 :   EXPECT_TRUE(std::isnan(Date::Cast(*value)->ValueOf()));
    1264             : 
    1265             :   value = RoundTripTest("({ a: new Date(), get b() { return this.a; } })");
    1266           1 :   ExpectScriptTrue("result.a instanceof Date");
    1267           1 :   ExpectScriptTrue("result.a === result.b");
    1268             : }
    1269             : 
    1270       15444 : TEST_F(ValueSerializerTest, DecodeDate) {
    1271             :   Local<Value> value;
    1272             : #if defined(V8_TARGET_LITTLE_ENDIAN)
    1273             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
    1274           2 :                       0x80, 0x84, 0x2E, 0x41, 0x00});
    1275           2 :   ASSERT_TRUE(value->IsDate());
    1276           2 :   EXPECT_EQ(1e6, Date::Cast(*value)->ValueOf());
    1277           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Date.prototype");
    1278             : 
    1279             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0x00, 0x00, 0x20, 0x45,
    1280           2 :                       0x27, 0x89, 0x87, 0xC2, 0x00});
    1281           2 :   ASSERT_TRUE(value->IsDate());
    1282           1 :   ExpectScriptTrue("result.toISOString() === '1867-07-01T00:00:00.000Z'");
    1283             : 
    1284             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
    1285           2 :                       0x00, 0x00, 0xF8, 0x7F, 0x00});
    1286           2 :   ASSERT_TRUE(value->IsDate());
    1287           2 :   EXPECT_TRUE(std::isnan(Date::Cast(*value)->ValueOf()));
    1288             : #else
    1289             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0x41, 0x2E, 0x84, 0x80,
    1290             :                       0x00, 0x00, 0x00, 0x00, 0x00});
    1291             :   ASSERT_TRUE(value->IsDate());
    1292             :   EXPECT_EQ(1e6, Date::Cast(*value)->ValueOf());
    1293             :   ExpectScriptTrue("Object.getPrototypeOf(result) === Date.prototype");
    1294             : 
    1295             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0xC2, 0x87, 0x89, 0x27,
    1296             :                       0x45, 0x20, 0x00, 0x00, 0x00});
    1297             :   ASSERT_TRUE(value->IsDate());
    1298             :   ExpectScriptTrue("result.toISOString() === '1867-07-01T00:00:00.000Z'");
    1299             : 
    1300             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x44, 0x7F, 0xF8, 0x00, 0x00,
    1301             :                       0x00, 0x00, 0x00, 0x00, 0x00});
    1302             :   ASSERT_TRUE(value->IsDate());
    1303             :   EXPECT_TRUE(std::isnan(Date::Cast(*value)->ValueOf()));
    1304             : #endif
    1305             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53,
    1306             :                       0x01, 0x61, 0x3F, 0x01, 0x44, 0x00, 0x20, 0x39,
    1307             :                       0x50, 0x37, 0x6A, 0x75, 0x42, 0x3F, 0x02, 0x53,
    1308           2 :                       0x01, 0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02});
    1309           1 :   ExpectScriptTrue("result.a instanceof Date");
    1310           1 :   ExpectScriptTrue("result.a === result.b");
    1311             : }
    1312             : 
    1313       15444 : TEST_F(ValueSerializerTest, RoundTripValueObjects) {
    1314           1 :   Local<Value> value = RoundTripTest("new Boolean(true)");
    1315           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Boolean.prototype");
    1316           1 :   ExpectScriptTrue("result.valueOf() === true");
    1317             : 
    1318             :   value = RoundTripTest("new Boolean(false)");
    1319           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Boolean.prototype");
    1320           1 :   ExpectScriptTrue("result.valueOf() === false");
    1321             : 
    1322             :   value =
    1323             :       RoundTripTest("({ a: new Boolean(true), get b() { return this.a; }})");
    1324           1 :   ExpectScriptTrue("result.a instanceof Boolean");
    1325           1 :   ExpectScriptTrue("result.a === result.b");
    1326             : 
    1327             :   value = RoundTripTest("new Number(-42)");
    1328           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1329           1 :   ExpectScriptTrue("result.valueOf() === -42");
    1330             : 
    1331             :   value = RoundTripTest("new Number(NaN)");
    1332           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1333           1 :   ExpectScriptTrue("Number.isNaN(result.valueOf())");
    1334             : 
    1335             :   value = RoundTripTest("({ a: new Number(6), get b() { return this.a; }})");
    1336           1 :   ExpectScriptTrue("result.a instanceof Number");
    1337           1 :   ExpectScriptTrue("result.a === result.b");
    1338             : 
    1339             :   value = RoundTripTest("new String('Qu\\xe9bec')");
    1340           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === String.prototype");
    1341           1 :   ExpectScriptTrue("result.valueOf() === 'Qu\\xe9bec'");
    1342           1 :   ExpectScriptTrue("result.length === 6");
    1343             : 
    1344             :   value = RoundTripTest("new String('\\ud83d\\udc4a')");
    1345           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === String.prototype");
    1346           1 :   ExpectScriptTrue("result.valueOf() === '\\ud83d\\udc4a'");
    1347           1 :   ExpectScriptTrue("result.length === 2");
    1348             : 
    1349             :   value = RoundTripTest("({ a: new String(), get b() { return this.a; }})");
    1350           1 :   ExpectScriptTrue("result.a instanceof String");
    1351           1 :   ExpectScriptTrue("result.a === result.b");
    1352           1 : }
    1353             : 
    1354       15444 : TEST_F(ValueSerializerTest, RejectsOtherValueObjects) {
    1355             :   // This is a roundabout way of getting an instance of Symbol.
    1356           1 :   InvalidEncodeTest("Object.valueOf.apply(Symbol())");
    1357           1 : }
    1358             : 
    1359       15444 : TEST_F(ValueSerializerTest, DecodeValueObjects) {
    1360           2 :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x79, 0x00});
    1361           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Boolean.prototype");
    1362           1 :   ExpectScriptTrue("result.valueOf() === true");
    1363             : 
    1364           2 :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x78, 0x00});
    1365           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Boolean.prototype");
    1366           1 :   ExpectScriptTrue("result.valueOf() === false");
    1367             : 
    1368             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53,
    1369             :                       0x01, 0x61, 0x3F, 0x01, 0x79, 0x3F, 0x02, 0x53,
    1370           2 :                       0x01, 0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02});
    1371           1 :   ExpectScriptTrue("result.a instanceof Boolean");
    1372           1 :   ExpectScriptTrue("result.a === result.b");
    1373             : 
    1374             : #if defined(V8_TARGET_LITTLE_ENDIAN)
    1375             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00,
    1376           2 :                       0x00, 0x00, 0x45, 0xC0, 0x00});
    1377           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1378           1 :   ExpectScriptTrue("result.valueOf() === -42");
    1379             : 
    1380             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00,
    1381           2 :                       0x00, 0x00, 0xF8, 0x7F, 0x00});
    1382           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1383           1 :   ExpectScriptTrue("Number.isNaN(result.valueOf())");
    1384             : #else
    1385             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6E, 0xC0, 0x45, 0x00, 0x00,
    1386             :                       0x00, 0x00, 0x00, 0x00, 0x00});
    1387             :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1388             :   ExpectScriptTrue("result.valueOf() === -42");
    1389             : 
    1390             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6E, 0x7F, 0xF8, 0x00, 0x00,
    1391             :                       0x00, 0x00, 0x00, 0x00, 0x00});
    1392             :   ExpectScriptTrue("Object.getPrototypeOf(result) === Number.prototype");
    1393             :   ExpectScriptTrue("Number.isNaN(result.valueOf())");
    1394             : #endif
    1395             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53,
    1396             :                       0x01, 0x61, 0x3F, 0x01, 0x6E, 0x00, 0x00, 0x00,
    1397             :                       0x00, 0x00, 0x00, 0x18, 0x40, 0x3F, 0x02, 0x53,
    1398           2 :                       0x01, 0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02});
    1399           1 :   ExpectScriptTrue("result.a instanceof Number");
    1400           1 :   ExpectScriptTrue("result.a === result.b");
    1401             : 
    1402             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x73, 0x07, 0x51, 0x75, 0xC3,
    1403           2 :                       0xA9, 0x62, 0x65, 0x63, 0x00});
    1404           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === String.prototype");
    1405           1 :   ExpectScriptTrue("result.valueOf() === 'Qu\\xe9bec'");
    1406           1 :   ExpectScriptTrue("result.length === 6");
    1407             : 
    1408             :   value =
    1409           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x73, 0x04, 0xF0, 0x9F, 0x91, 0x8A});
    1410           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === String.prototype");
    1411           1 :   ExpectScriptTrue("result.valueOf() === '\\ud83d\\udc4a'");
    1412           1 :   ExpectScriptTrue("result.length === 2");
    1413             : 
    1414             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x01,
    1415             :                       0x61, 0x3F, 0x01, 0x73, 0x00, 0x3F, 0x02, 0x53, 0x01,
    1416           2 :                       0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02, 0x00});
    1417           1 :   ExpectScriptTrue("result.a instanceof String");
    1418           1 :   ExpectScriptTrue("result.a === result.b");
    1419             : 
    1420             :   // String object containing a Latin-1 string.
    1421             :   value =
    1422           2 :       DecodeTest({0xFF, 0x0C, 0x73, 0x22, 0x06, 'Q', 'u', 0xE9, 'b', 'e', 'c'});
    1423           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === String.prototype");
    1424           1 :   ExpectScriptTrue("result.valueOf() === 'Qu\\xe9bec'");
    1425           1 :   ExpectScriptTrue("result.length === 6");
    1426           1 : }
    1427             : 
    1428       15444 : TEST_F(ValueSerializerTest, RoundTripRegExp) {
    1429           1 :   Local<Value> value = RoundTripTest("/foo/g");
    1430           2 :   ASSERT_TRUE(value->IsRegExp());
    1431           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === RegExp.prototype");
    1432           1 :   ExpectScriptTrue("result.toString() === '/foo/g'");
    1433             : 
    1434             :   value = RoundTripTest("new RegExp('Qu\\xe9bec', 'i')");
    1435           2 :   ASSERT_TRUE(value->IsRegExp());
    1436           1 :   ExpectScriptTrue("result.toString() === '/Qu\\xe9bec/i'");
    1437             : 
    1438             :   value = RoundTripTest("new RegExp('\\ud83d\\udc4a', 'ug')");
    1439           2 :   ASSERT_TRUE(value->IsRegExp());
    1440           1 :   ExpectScriptTrue("result.toString() === '/\\ud83d\\udc4a/gu'");
    1441             : 
    1442             :   value = RoundTripTest("({ a: /foo/gi, get b() { return this.a; }})");
    1443           1 :   ExpectScriptTrue("result.a instanceof RegExp");
    1444           1 :   ExpectScriptTrue("result.a === result.b");
    1445             : }
    1446             : 
    1447       15444 : TEST_F(ValueSerializerTest, DecodeRegExp) {
    1448             :   Local<Value> value =
    1449           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x52, 0x03, 0x66, 0x6F, 0x6F, 0x01});
    1450           2 :   ASSERT_TRUE(value->IsRegExp());
    1451           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === RegExp.prototype");
    1452           1 :   ExpectScriptTrue("result.toString() === '/foo/g'");
    1453             : 
    1454             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x52, 0x07, 0x51, 0x75, 0xC3,
    1455           2 :                       0xA9, 0x62, 0x65, 0x63, 0x02});
    1456           2 :   ASSERT_TRUE(value->IsRegExp());
    1457           1 :   ExpectScriptTrue("result.toString() === '/Qu\\xe9bec/i'");
    1458             : 
    1459             :   value = DecodeTest(
    1460           2 :       {0xFF, 0x09, 0x3F, 0x00, 0x52, 0x04, 0xF0, 0x9F, 0x91, 0x8A, 0x11, 0x00});
    1461           2 :   ASSERT_TRUE(value->IsRegExp());
    1462           1 :   ExpectScriptTrue("result.toString() === '/\\ud83d\\udc4a/gu'");
    1463             : 
    1464             :   value =
    1465             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x01, 0x61,
    1466             :                   0x3F, 0x01, 0x52, 0x03, 0x66, 0x6F, 0x6F, 0x03, 0x3F, 0x02,
    1467           2 :                   0x53, 0x01, 0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02, 0x00});
    1468           1 :   ExpectScriptTrue("result.a instanceof RegExp");
    1469           1 :   ExpectScriptTrue("result.a === result.b");
    1470             : 
    1471             :   // RegExp containing a Latin-1 string.
    1472             :   value = DecodeTest(
    1473           2 :       {0xFF, 0x0C, 0x52, 0x22, 0x06, 'Q', 'u', 0xE9, 'b', 'e', 'c', 0x02});
    1474           2 :   ASSERT_TRUE(value->IsRegExp());
    1475           1 :   ExpectScriptTrue("result.toString() === '/Qu\\xe9bec/i'");
    1476             : }
    1477             : 
    1478             : // Tests that invalid flags are not accepted by the deserializer.
    1479       15444 : TEST_F(ValueSerializerTest, DecodeRegExpDotAll) {
    1480             :   Local<Value> value =
    1481           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x52, 0x03, 0x66, 0x6F, 0x6F, 0x1F});
    1482           2 :   ASSERT_TRUE(value->IsRegExp());
    1483           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === RegExp.prototype");
    1484           1 :   ExpectScriptTrue("result.toString() === '/foo/gimuy'");
    1485             : 
    1486             :   value =
    1487           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x52, 0x03, 0x66, 0x6F, 0x6F, 0x3F});
    1488           2 :   ASSERT_TRUE(value->IsRegExp());
    1489           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === RegExp.prototype");
    1490           1 :   ExpectScriptTrue("result.toString() === '/foo/gimsuy'");
    1491             : 
    1492           1 :   InvalidDecodeTest(
    1493           1 :       {0xFF, 0x09, 0x3F, 0x00, 0x52, 0x03, 0x66, 0x6F, 0x6F, 0x7F});
    1494             : }
    1495             : 
    1496       15444 : TEST_F(ValueSerializerTest, RoundTripMap) {
    1497           1 :   Local<Value> value = RoundTripTest("var m = new Map(); m.set(42, 'foo'); m;");
    1498           2 :   ASSERT_TRUE(value->IsMap());
    1499           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Map.prototype");
    1500           1 :   ExpectScriptTrue("result.size === 1");
    1501           1 :   ExpectScriptTrue("result.get(42) === 'foo'");
    1502             : 
    1503             :   value = RoundTripTest("var m = new Map(); m.set(m, m); m;");
    1504           2 :   ASSERT_TRUE(value->IsMap());
    1505           1 :   ExpectScriptTrue("result.size === 1");
    1506           1 :   ExpectScriptTrue("result.get(result) === result");
    1507             : 
    1508             :   // Iteration order must be preserved.
    1509             :   value = RoundTripTest(
    1510             :       "var m = new Map();"
    1511             :       "m.set(1, 0); m.set('a', 0); m.set(3, 0); m.set(2, 0);"
    1512             :       "m;");
    1513           2 :   ASSERT_TRUE(value->IsMap());
    1514           1 :   ExpectScriptTrue("Array.from(result.keys()).toString() === '1,a,3,2'");
    1515             : }
    1516             : 
    1517       15444 : TEST_F(ValueSerializerTest, DecodeMap) {
    1518             :   Local<Value> value =
    1519             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3B, 0x3F, 0x01, 0x49, 0x54, 0x3F,
    1520           2 :                   0x01, 0x53, 0x03, 0x66, 0x6F, 0x6F, 0x3A, 0x02});
    1521           2 :   ASSERT_TRUE(value->IsMap());
    1522           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Map.prototype");
    1523           1 :   ExpectScriptTrue("result.size === 1");
    1524           1 :   ExpectScriptTrue("result.get(42) === 'foo'");
    1525             : 
    1526             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3B, 0x3F, 0x01, 0x5E, 0x00,
    1527           2 :                       0x3F, 0x01, 0x5E, 0x00, 0x3A, 0x02, 0x00});
    1528           2 :   ASSERT_TRUE(value->IsMap());
    1529           1 :   ExpectScriptTrue("result.size === 1");
    1530           1 :   ExpectScriptTrue("result.get(result) === result");
    1531             : 
    1532             :   // Iteration order must be preserved.
    1533             :   value =
    1534             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3B, 0x3F, 0x01, 0x49, 0x02, 0x3F,
    1535             :                   0x01, 0x49, 0x00, 0x3F, 0x01, 0x53, 0x01, 0x61, 0x3F, 0x01,
    1536             :                   0x49, 0x00, 0x3F, 0x01, 0x49, 0x06, 0x3F, 0x01, 0x49, 0x00,
    1537           2 :                   0x3F, 0x01, 0x49, 0x04, 0x3F, 0x01, 0x49, 0x00, 0x3A, 0x08});
    1538           2 :   ASSERT_TRUE(value->IsMap());
    1539           1 :   ExpectScriptTrue("Array.from(result.keys()).toString() === '1,a,3,2'");
    1540             : }
    1541             : 
    1542       15444 : TEST_F(ValueSerializerTest, RoundTripMapWithTrickyGetters) {
    1543             :   // Even if an entry is removed or reassigned, the original key/value pair is
    1544             :   // used.
    1545             :   Local<Value> value = RoundTripTest(
    1546             :       "var m = new Map();"
    1547             :       "m.set(0, { get a() {"
    1548             :       "  m.delete(1); m.set(2, 'baz'); m.set(3, 'quux');"
    1549             :       "}});"
    1550             :       "m.set(1, 'foo');"
    1551             :       "m.set(2, 'bar');"
    1552           1 :       "m;");
    1553           2 :   ASSERT_TRUE(value->IsMap());
    1554           1 :   ExpectScriptTrue("Array.from(result.keys()).toString() === '0,1,2'");
    1555           1 :   ExpectScriptTrue("result.get(1) === 'foo'");
    1556           1 :   ExpectScriptTrue("result.get(2) === 'bar'");
    1557             : 
    1558             :   // However, deeper modifications of objects yet to be serialized still apply.
    1559             :   value = RoundTripTest(
    1560             :       "var m = new Map();"
    1561             :       "var key = { get a() { value.foo = 'bar'; } };"
    1562             :       "var value = { get a() { key.baz = 'quux'; } };"
    1563             :       "m.set(key, value);"
    1564             :       "m;");
    1565           2 :   ASSERT_TRUE(value->IsMap());
    1566           1 :   ExpectScriptTrue("!('baz' in Array.from(result.keys())[0])");
    1567           1 :   ExpectScriptTrue("Array.from(result.values())[0].foo === 'bar'");
    1568             : }
    1569             : 
    1570       15444 : TEST_F(ValueSerializerTest, RoundTripSet) {
    1571             :   Local<Value> value =
    1572           1 :       RoundTripTest("var s = new Set(); s.add(42); s.add('foo'); s;");
    1573           2 :   ASSERT_TRUE(value->IsSet());
    1574           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Set.prototype");
    1575           1 :   ExpectScriptTrue("result.size === 2");
    1576           1 :   ExpectScriptTrue("result.has(42)");
    1577           1 :   ExpectScriptTrue("result.has('foo')");
    1578             : 
    1579             :   value = RoundTripTest("var s = new Set(); s.add(s); s;");
    1580           2 :   ASSERT_TRUE(value->IsSet());
    1581           1 :   ExpectScriptTrue("result.size === 1");
    1582           1 :   ExpectScriptTrue("result.has(result)");
    1583             : 
    1584             :   // Iteration order must be preserved.
    1585             :   value = RoundTripTest(
    1586             :       "var s = new Set();"
    1587             :       "s.add(1); s.add('a'); s.add(3); s.add(2);"
    1588             :       "s;");
    1589           2 :   ASSERT_TRUE(value->IsSet());
    1590           1 :   ExpectScriptTrue("Array.from(result.keys()).toString() === '1,a,3,2'");
    1591             : }
    1592             : 
    1593       15444 : TEST_F(ValueSerializerTest, DecodeSet) {
    1594             :   Local<Value> value =
    1595             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x27, 0x3F, 0x01, 0x49, 0x54, 0x3F,
    1596           2 :                   0x01, 0x53, 0x03, 0x66, 0x6F, 0x6F, 0x2C, 0x02});
    1597           2 :   ASSERT_TRUE(value->IsSet());
    1598           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Set.prototype");
    1599           1 :   ExpectScriptTrue("result.size === 2");
    1600           1 :   ExpectScriptTrue("result.has(42)");
    1601           1 :   ExpectScriptTrue("result.has('foo')");
    1602             : 
    1603             :   value = DecodeTest(
    1604           2 :       {0xFF, 0x09, 0x3F, 0x00, 0x27, 0x3F, 0x01, 0x5E, 0x00, 0x2C, 0x01, 0x00});
    1605           2 :   ASSERT_TRUE(value->IsSet());
    1606           1 :   ExpectScriptTrue("result.size === 1");
    1607           1 :   ExpectScriptTrue("result.has(result)");
    1608             : 
    1609             :   // Iteration order must be preserved.
    1610             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x27, 0x3F, 0x01, 0x49,
    1611             :                       0x02, 0x3F, 0x01, 0x53, 0x01, 0x61, 0x3F, 0x01,
    1612           2 :                       0x49, 0x06, 0x3F, 0x01, 0x49, 0x04, 0x2C, 0x04});
    1613           2 :   ASSERT_TRUE(value->IsSet());
    1614           1 :   ExpectScriptTrue("Array.from(result.keys()).toString() === '1,a,3,2'");
    1615             : }
    1616             : 
    1617       15444 : TEST_F(ValueSerializerTest, RoundTripSetWithTrickyGetters) {
    1618             :   // Even if an element is added or removed during serialization, the original
    1619             :   // set of elements is used.
    1620             :   Local<Value> value = RoundTripTest(
    1621             :       "var s = new Set();"
    1622             :       "s.add({ get a() { s.delete(1); s.add(2); } });"
    1623             :       "s.add(1);"
    1624           1 :       "s;");
    1625           2 :   ASSERT_TRUE(value->IsSet());
    1626             :   ExpectScriptTrue(
    1627           1 :       "Array.from(result.keys()).toString() === '[object Object],1'");
    1628             : 
    1629             :   // However, deeper modifications of objects yet to be serialized still apply.
    1630             :   value = RoundTripTest(
    1631             :       "var s = new Set();"
    1632             :       "var first = { get a() { second.foo = 'bar'; } };"
    1633             :       "var second = { get a() { first.baz = 'quux'; } };"
    1634             :       "s.add(first);"
    1635             :       "s.add(second);"
    1636             :       "s;");
    1637           2 :   ASSERT_TRUE(value->IsSet());
    1638           1 :   ExpectScriptTrue("!('baz' in Array.from(result.keys())[0])");
    1639           1 :   ExpectScriptTrue("Array.from(result.keys())[1].foo === 'bar'");
    1640             : }
    1641             : 
    1642       15444 : TEST_F(ValueSerializerTest, RoundTripArrayBuffer) {
    1643           1 :   Local<Value> value = RoundTripTest("new ArrayBuffer()");
    1644           2 :   ASSERT_TRUE(value->IsArrayBuffer());
    1645           2 :   EXPECT_EQ(0u, ArrayBuffer::Cast(*value)->ByteLength());
    1646           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === ArrayBuffer.prototype");
    1647             : 
    1648             :   value = RoundTripTest("new Uint8Array([0, 128, 255]).buffer");
    1649           2 :   ASSERT_TRUE(value->IsArrayBuffer());
    1650           2 :   EXPECT_EQ(3u, ArrayBuffer::Cast(*value)->ByteLength());
    1651           1 :   ExpectScriptTrue("new Uint8Array(result).toString() === '0,128,255'");
    1652             : 
    1653             :   value =
    1654             :       RoundTripTest("({ a: new ArrayBuffer(), get b() { return this.a; }})");
    1655           1 :   ExpectScriptTrue("result.a instanceof ArrayBuffer");
    1656           1 :   ExpectScriptTrue("result.a === result.b");
    1657             : }
    1658             : 
    1659       15444 : TEST_F(ValueSerializerTest, DecodeArrayBuffer) {
    1660           2 :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x42, 0x00});
    1661           2 :   ASSERT_TRUE(value->IsArrayBuffer());
    1662           2 :   EXPECT_EQ(0u, ArrayBuffer::Cast(*value)->ByteLength());
    1663           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === ArrayBuffer.prototype");
    1664             : 
    1665             :   value =
    1666           2 :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x42, 0x03, 0x00, 0x80, 0xFF, 0x00});
    1667           2 :   ASSERT_TRUE(value->IsArrayBuffer());
    1668           2 :   EXPECT_EQ(3u, ArrayBuffer::Cast(*value)->ByteLength());
    1669           1 :   ExpectScriptTrue("new Uint8Array(result).toString() === '0,128,255'");
    1670             : 
    1671             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x01,
    1672             :                       0x61, 0x3F, 0x01, 0x42, 0x00, 0x3F, 0x02, 0x53, 0x01,
    1673           2 :                       0x62, 0x3F, 0x02, 0x5E, 0x01, 0x7B, 0x02, 0x00});
    1674           1 :   ExpectScriptTrue("result.a instanceof ArrayBuffer");
    1675           1 :   ExpectScriptTrue("result.a === result.b");
    1676             : }
    1677             : 
    1678       15444 : TEST_F(ValueSerializerTest, DecodeInvalidArrayBuffer) {
    1679           2 :   InvalidDecodeTest({0xFF, 0x09, 0x42, 0xFF, 0xFF, 0x00});
    1680           1 : }
    1681             : 
    1682             : // An array buffer allocator that never has available memory.
    1683           1 : class OOMArrayBufferAllocator : public ArrayBuffer::Allocator {
    1684             :  public:
    1685           0 :   void* Allocate(size_t) override { return nullptr; }
    1686           1 :   void* AllocateUninitialized(size_t) override { return nullptr; }
    1687           0 :   void Free(void*, size_t) override {}
    1688             : };
    1689             : 
    1690       15444 : TEST_F(ValueSerializerTest, DecodeArrayBufferOOM) {
    1691             :   // This test uses less of the harness, because it has to customize the
    1692             :   // isolate.
    1693           1 :   OOMArrayBufferAllocator allocator;
    1694             :   Isolate::CreateParams params;
    1695           1 :   params.array_buffer_allocator = &allocator;
    1696           1 :   Isolate* isolate = Isolate::New(params);
    1697             :   {
    1698             :     Isolate::Scope isolate_scope(isolate);
    1699           2 :     HandleScope handle_scope(isolate);
    1700           1 :     Local<Context> context = Context::New(isolate);
    1701             :     Context::Scope context_scope(context);
    1702           2 :     TryCatch try_catch(isolate);
    1703             : 
    1704             :     const std::vector<uint8_t> data = {0xFF, 0x09, 0x3F, 0x00, 0x42,
    1705             :                                        0x03, 0x00, 0x80, 0xFF, 0x00};
    1706             :     ValueDeserializer deserializer(isolate, &data[0],
    1707           2 :                                    static_cast<int>(data.size()), nullptr);
    1708           1 :     deserializer.SetSupportsLegacyWireFormat(true);
    1709           2 :     ASSERT_TRUE(deserializer.ReadHeader(context).FromMaybe(false));
    1710           2 :     ASSERT_FALSE(try_catch.HasCaught());
    1711           2 :     EXPECT_TRUE(deserializer.ReadValue(context).IsEmpty());
    1712           2 :     EXPECT_TRUE(try_catch.HasCaught());
    1713             :   }
    1714           1 :   isolate->Dispose();
    1715             : }
    1716             : 
    1717             : // Includes an ArrayBuffer wrapper marked for transfer from the serialization
    1718             : // context to the deserialization context.
    1719           2 : class ValueSerializerTestWithArrayBufferTransfer : public ValueSerializerTest {
    1720             :  protected:
    1721             :   static const size_t kTestByteLength = 4;
    1722             : 
    1723           1 :   ValueSerializerTestWithArrayBufferTransfer() {
    1724             :     {
    1725             :       Context::Scope scope(serialization_context());
    1726           1 :       input_buffer_ = ArrayBuffer::New(isolate(), nullptr, 0);
    1727             :     }
    1728             :     {
    1729             :       Context::Scope scope(deserialization_context());
    1730           1 :       output_buffer_ = ArrayBuffer::New(isolate(), kTestByteLength);
    1731           1 :       const uint8_t data[kTestByteLength] = {0x00, 0x01, 0x80, 0xFF};
    1732           2 :       memcpy(output_buffer_->GetContents().Data(), data, kTestByteLength);
    1733             :     }
    1734           1 :   }
    1735             : 
    1736             :   const Local<ArrayBuffer>& input_buffer() { return input_buffer_; }
    1737           1 :   const Local<ArrayBuffer>& output_buffer() { return output_buffer_; }
    1738             : 
    1739           2 :   void BeforeEncode(ValueSerializer* serializer) override {
    1740           2 :     serializer->TransferArrayBuffer(0, input_buffer_);
    1741           2 :   }
    1742             : 
    1743           2 :   void BeforeDecode(ValueDeserializer* deserializer) override {
    1744           2 :     deserializer->TransferArrayBuffer(0, output_buffer_);
    1745           2 :   }
    1746             : 
    1747             :  private:
    1748             :   Local<ArrayBuffer> input_buffer_;
    1749             :   Local<ArrayBuffer> output_buffer_;
    1750             : };
    1751             : 
    1752       15444 : TEST_F(ValueSerializerTestWithArrayBufferTransfer,
    1753             :        RoundTripArrayBufferTransfer) {
    1754           1 :   Local<Value> value = RoundTripTest(input_buffer());
    1755           2 :   ASSERT_TRUE(value->IsArrayBuffer());
    1756           1 :   EXPECT_EQ(output_buffer(), value);
    1757           1 :   ExpectScriptTrue("new Uint8Array(result).toString() === '0,1,128,255'");
    1758             : 
    1759             :   Local<Object> object;
    1760             :   {
    1761             :     Context::Scope scope(serialization_context());
    1762           1 :     object = Object::New(isolate());
    1763           3 :     EXPECT_TRUE(object
    1764             :                     ->CreateDataProperty(serialization_context(),
    1765             :                                          StringFromUtf8("a"), input_buffer())
    1766           0 :                     .FromMaybe(false));
    1767           3 :     EXPECT_TRUE(object
    1768             :                     ->CreateDataProperty(serialization_context(),
    1769             :                                          StringFromUtf8("b"), input_buffer())
    1770           0 :                     .FromMaybe(false));
    1771             :   }
    1772           1 :   value = RoundTripTest(object);
    1773           1 :   ExpectScriptTrue("result.a instanceof ArrayBuffer");
    1774           1 :   ExpectScriptTrue("result.a === result.b");
    1775           1 :   ExpectScriptTrue("new Uint8Array(result.a).toString() === '0,1,128,255'");
    1776             : }
    1777             : 
    1778       15444 : TEST_F(ValueSerializerTest, RoundTripTypedArray) {
    1779             :   // Check that the right type comes out the other side for every kind of typed
    1780             :   // array.
    1781             :   Local<Value> value;
    1782             : #define TYPED_ARRAY_ROUND_TRIP_TEST(Type, type, TYPE, ctype)             \
    1783             :   value = RoundTripTest("new " #Type "Array(2)");                        \
    1784             :   ASSERT_TRUE(value->Is##Type##Array());                                 \
    1785             :   EXPECT_EQ(2u * sizeof(ctype), TypedArray::Cast(*value)->ByteLength()); \
    1786             :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());                     \
    1787             :   ExpectScriptTrue("Object.getPrototypeOf(result) === " #Type            \
    1788             :                    "Array.prototype");
    1789             : 
    1790          78 :   TYPED_ARRAYS(TYPED_ARRAY_ROUND_TRIP_TEST)
    1791             : #undef TYPED_ARRAY_ROUND_TRIP_TEST
    1792             : 
    1793             :   // Check that values of various kinds are suitably preserved.
    1794             :   value = RoundTripTest("new Uint8Array([1, 128, 255])");
    1795           1 :   ExpectScriptTrue("result.toString() === '1,128,255'");
    1796             : 
    1797             :   value = RoundTripTest("new Int16Array([0, 256, -32768])");
    1798           1 :   ExpectScriptTrue("result.toString() === '0,256,-32768'");
    1799             : 
    1800             :   value = RoundTripTest("new Float32Array([0, -0.5, NaN, Infinity])");
    1801           1 :   ExpectScriptTrue("result.toString() === '0,-0.5,NaN,Infinity'");
    1802             : 
    1803             :   // Array buffer views sharing a buffer should do so on the other side.
    1804             :   // Similarly, multiple references to the same typed array should be resolved.
    1805             :   value = RoundTripTest(
    1806             :       "var buffer = new ArrayBuffer(32);"
    1807             :       "({"
    1808             :       "  u8: new Uint8Array(buffer),"
    1809             :       "  get u8_2() { return this.u8; },"
    1810             :       "  f32: new Float32Array(buffer, 4, 5),"
    1811             :       "  b: buffer,"
    1812             :       "});");
    1813           1 :   ExpectScriptTrue("result.u8 instanceof Uint8Array");
    1814           1 :   ExpectScriptTrue("result.u8 === result.u8_2");
    1815           1 :   ExpectScriptTrue("result.f32 instanceof Float32Array");
    1816           1 :   ExpectScriptTrue("result.u8.buffer === result.f32.buffer");
    1817           1 :   ExpectScriptTrue("result.f32.byteOffset === 4");
    1818           1 :   ExpectScriptTrue("result.f32.length === 5");
    1819             : }
    1820             : 
    1821       15444 : TEST_F(ValueSerializerTest, DecodeTypedArray) {
    1822             :   // Check that the right type comes out the other side for every kind of typed
    1823             :   // array.
    1824             :   Local<Value> value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42,
    1825           2 :                                    0x02, 0x00, 0x00, 0x56, 0x42, 0x00, 0x02});
    1826           2 :   ASSERT_TRUE(value->IsUint8Array());
    1827           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->ByteLength());
    1828           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1829           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Uint8Array.prototype");
    1830             : 
    1831             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x02, 0x00,
    1832           2 :                       0x00, 0x56, 0x62, 0x00, 0x02});
    1833           2 :   ASSERT_TRUE(value->IsInt8Array());
    1834           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->ByteLength());
    1835           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1836           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Int8Array.prototype");
    1837             : 
    1838             : #if defined(V8_TARGET_LITTLE_ENDIAN)
    1839             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x04, 0x00,
    1840           2 :                       0x00, 0x00, 0x00, 0x56, 0x57, 0x00, 0x04});
    1841           2 :   ASSERT_TRUE(value->IsUint16Array());
    1842           2 :   EXPECT_EQ(4u, TypedArray::Cast(*value)->ByteLength());
    1843           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1844           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Uint16Array.prototype");
    1845             : 
    1846             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x04, 0x00,
    1847           2 :                       0x00, 0x00, 0x00, 0x56, 0x77, 0x00, 0x04});
    1848           2 :   ASSERT_TRUE(value->IsInt16Array());
    1849           2 :   EXPECT_EQ(4u, TypedArray::Cast(*value)->ByteLength());
    1850           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1851           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Int16Array.prototype");
    1852             : 
    1853             :   value =
    1854             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x08, 0x00, 0x00,
    1855           2 :                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x44, 0x00, 0x08});
    1856           2 :   ASSERT_TRUE(value->IsUint32Array());
    1857           2 :   EXPECT_EQ(8u, TypedArray::Cast(*value)->ByteLength());
    1858           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1859           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Uint32Array.prototype");
    1860             : 
    1861             :   value =
    1862             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x08, 0x00, 0x00,
    1863           2 :                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x64, 0x00, 0x08});
    1864           2 :   ASSERT_TRUE(value->IsInt32Array());
    1865           2 :   EXPECT_EQ(8u, TypedArray::Cast(*value)->ByteLength());
    1866           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1867           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Int32Array.prototype");
    1868             : 
    1869             :   value =
    1870             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x08, 0x00, 0x00,
    1871           2 :                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x66, 0x00, 0x08});
    1872           2 :   ASSERT_TRUE(value->IsFloat32Array());
    1873           2 :   EXPECT_EQ(8u, TypedArray::Cast(*value)->ByteLength());
    1874           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1875           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Float32Array.prototype");
    1876             : 
    1877             :   value =
    1878             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x10, 0x00, 0x00,
    1879             :                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1880           2 :                   0x00, 0x00, 0x00, 0x00, 0x56, 0x46, 0x00, 0x10});
    1881           2 :   ASSERT_TRUE(value->IsFloat64Array());
    1882           2 :   EXPECT_EQ(16u, TypedArray::Cast(*value)->ByteLength());
    1883           2 :   EXPECT_EQ(2u, TypedArray::Cast(*value)->Length());
    1884           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === Float64Array.prototype");
    1885             : 
    1886             : #endif  // V8_TARGET_LITTLE_ENDIAN
    1887             : 
    1888             :   // Check that values of various kinds are suitably preserved.
    1889             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x03, 0x01,
    1890           2 :                       0x80, 0xFF, 0x56, 0x42, 0x00, 0x03, 0x00});
    1891           1 :   ExpectScriptTrue("result.toString() === '1,128,255'");
    1892             : 
    1893             : #if defined(V8_TARGET_LITTLE_ENDIAN)
    1894             :   value = DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x06, 0x00,
    1895           2 :                       0x00, 0x00, 0x01, 0x00, 0x80, 0x56, 0x77, 0x00, 0x06});
    1896           1 :   ExpectScriptTrue("result.toString() === '0,256,-32768'");
    1897             : 
    1898             :   value =
    1899             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x10, 0x00, 0x00,
    1900             :                   0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0xC0, 0x7F,
    1901           2 :                   0x00, 0x00, 0x80, 0x7F, 0x56, 0x66, 0x00, 0x10});
    1902           1 :   ExpectScriptTrue("result.toString() === '0,-0.5,NaN,Infinity'");
    1903             : 
    1904             : #endif  // V8_TARGET_LITTLE_ENDIAN
    1905             : 
    1906             :   // Array buffer views sharing a buffer should do so on the other side.
    1907             :   // Similarly, multiple references to the same typed array should be resolved.
    1908             :   value = DecodeTest(
    1909             :       {0xFF, 0x09, 0x3F, 0x00, 0x6F, 0x3F, 0x01, 0x53, 0x02, 0x75, 0x38, 0x3F,
    1910             :        0x01, 0x3F, 0x01, 0x42, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1911             :        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1912             :        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1913             :        0x00, 0x56, 0x42, 0x00, 0x20, 0x3F, 0x03, 0x53, 0x04, 0x75, 0x38, 0x5F,
    1914             :        0x32, 0x3F, 0x03, 0x5E, 0x02, 0x3F, 0x03, 0x53, 0x03, 0x66, 0x33, 0x32,
    1915             :        0x3F, 0x03, 0x3F, 0x03, 0x5E, 0x01, 0x56, 0x66, 0x04, 0x14, 0x3F, 0x04,
    1916           2 :        0x53, 0x01, 0x62, 0x3F, 0x04, 0x5E, 0x01, 0x7B, 0x04, 0x00});
    1917           1 :   ExpectScriptTrue("result.u8 instanceof Uint8Array");
    1918           1 :   ExpectScriptTrue("result.u8 === result.u8_2");
    1919           1 :   ExpectScriptTrue("result.f32 instanceof Float32Array");
    1920           1 :   ExpectScriptTrue("result.u8.buffer === result.f32.buffer");
    1921           1 :   ExpectScriptTrue("result.f32.byteOffset === 4");
    1922           1 :   ExpectScriptTrue("result.f32.length === 5");
    1923             : }
    1924             : 
    1925       15444 : TEST_F(ValueSerializerTest, DecodeInvalidTypedArray) {
    1926             :   // Byte offset out of range.
    1927           2 :   InvalidDecodeTest(
    1928           1 :       {0xFF, 0x09, 0x42, 0x02, 0x00, 0x00, 0x56, 0x42, 0x03, 0x01});
    1929             :   // Byte offset in range, offset + length out of range.
    1930           1 :   InvalidDecodeTest(
    1931           1 :       {0xFF, 0x09, 0x42, 0x02, 0x00, 0x00, 0x56, 0x42, 0x01, 0x03});
    1932             :   // Byte offset not divisible by element size.
    1933           1 :   InvalidDecodeTest(
    1934           1 :       {0xFF, 0x09, 0x42, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56, 0x77, 0x01, 0x02});
    1935             :   // Byte length not divisible by element size.
    1936           1 :   InvalidDecodeTest(
    1937           1 :       {0xFF, 0x09, 0x42, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56, 0x77, 0x02, 0x01});
    1938             :   // Invalid view type (0xFF).
    1939           1 :   InvalidDecodeTest(
    1940           1 :       {0xFF, 0x09, 0x42, 0x02, 0x00, 0x00, 0x56, 0xFF, 0x01, 0x01});
    1941           1 : }
    1942             : 
    1943       15444 : TEST_F(ValueSerializerTest, RoundTripDataView) {
    1944           1 :   Local<Value> value = RoundTripTest("new DataView(new ArrayBuffer(4), 1, 2)");
    1945           2 :   ASSERT_TRUE(value->IsDataView());
    1946           2 :   EXPECT_EQ(1u, DataView::Cast(*value)->ByteOffset());
    1947           2 :   EXPECT_EQ(2u, DataView::Cast(*value)->ByteLength());
    1948           3 :   EXPECT_EQ(4u, DataView::Cast(*value)->Buffer()->ByteLength());
    1949           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === DataView.prototype");
    1950             : }
    1951             : 
    1952       15444 : TEST_F(ValueSerializerTest, DecodeDataView) {
    1953             :   Local<Value> value =
    1954             :       DecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x3F, 0x00, 0x42, 0x04, 0x00, 0x00,
    1955           2 :                   0x00, 0x00, 0x56, 0x3F, 0x01, 0x02});
    1956           2 :   ASSERT_TRUE(value->IsDataView());
    1957           2 :   EXPECT_EQ(1u, DataView::Cast(*value)->ByteOffset());
    1958           2 :   EXPECT_EQ(2u, DataView::Cast(*value)->ByteLength());
    1959           3 :   EXPECT_EQ(4u, DataView::Cast(*value)->Buffer()->ByteLength());
    1960           1 :   ExpectScriptTrue("Object.getPrototypeOf(result) === DataView.prototype");
    1961             : }
    1962             : 
    1963       15444 : TEST_F(ValueSerializerTest, DecodeArrayWithLengthProperty1) {
    1964           2 :   InvalidDecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
    1965             :                      0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
    1966           1 :                      0x74, 0x68, 0x49, 0x02, 0x24, 0x01, 0x03});
    1967           1 : }
    1968             : 
    1969       15444 : TEST_F(ValueSerializerTest, DecodeArrayWithLengthProperty2) {
    1970           2 :   InvalidDecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
    1971             :                      0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
    1972           1 :                      0x74, 0x68, 0x6f, 0x7b, 0x00, 0x24, 0x01, 0x03});
    1973           1 : }
    1974             : 
    1975       15444 : TEST_F(ValueSerializerTest, DecodeInvalidDataView) {
    1976             :   // Byte offset out of range.
    1977           2 :   InvalidDecodeTest(
    1978           1 :       {0xFF, 0x09, 0x42, 0x02, 0x00, 0x00, 0x56, 0x3F, 0x03, 0x01});
    1979             :   // Byte offset in range, offset + length out of range.
    1980           1 :   InvalidDecodeTest(
    1981           1 :       {0xFF, 0x09, 0x42, 0x02, 0x00, 0x00, 0x56, 0x3F, 0x01, 0x03});
    1982           1 : }
    1983             : 
    1984           4 : class ValueSerializerTestWithSharedArrayBufferClone
    1985             :     : public ValueSerializerTest {
    1986             :  protected:
    1987           2 :   ValueSerializerTestWithSharedArrayBufferClone()
    1988           4 :       : serializer_delegate_(this), deserializer_delegate_(this) {}
    1989             : 
    1990           2 :   void InitializeData(const std::vector<uint8_t>& data) {
    1991           2 :     data_ = data;
    1992             :     {
    1993             :       Context::Scope scope(serialization_context());
    1994             :       input_buffer_ =
    1995           2 :           SharedArrayBuffer::New(isolate(), data_.data(), data_.size());
    1996             :     }
    1997             :     {
    1998             :       Context::Scope scope(deserialization_context());
    1999             :       output_buffer_ =
    2000           2 :           SharedArrayBuffer::New(isolate(), data_.data(), data_.size());
    2001             :     }
    2002           2 :   }
    2003             : 
    2004           2 :   const Local<SharedArrayBuffer>& input_buffer() { return input_buffer_; }
    2005           1 :   const Local<SharedArrayBuffer>& output_buffer() { return output_buffer_; }
    2006             : 
    2007           2 :   static void SetUpTestCase() {
    2008           2 :     flag_was_enabled_ = i::FLAG_harmony_sharedarraybuffer;
    2009           2 :     i::FLAG_harmony_sharedarraybuffer = true;
    2010             :     ValueSerializerTest::SetUpTestCase();
    2011           2 :   }
    2012             : 
    2013           2 :   static void TearDownTestCase() {
    2014             :     ValueSerializerTest::TearDownTestCase();
    2015           2 :     i::FLAG_harmony_sharedarraybuffer = flag_was_enabled_;
    2016           2 :     flag_was_enabled_ = false;
    2017           2 :   }
    2018             : 
    2019             :  protected:
    2020             : // GMock doesn't use the "override" keyword.
    2021             : #if __clang__
    2022             : #pragma clang diagnostic push
    2023             : #pragma clang diagnostic ignored "-Winconsistent-missing-override"
    2024             : #endif
    2025             : 
    2026           4 :   class SerializerDelegate : public ValueSerializer::Delegate {
    2027             :    public:
    2028             :     explicit SerializerDelegate(
    2029             :         ValueSerializerTestWithSharedArrayBufferClone* test)
    2030           4 :         : test_(test) {}
    2031          11 :     MOCK_METHOD2(GetSharedArrayBufferId,
    2032             :                  Maybe<uint32_t>(Isolate* isolate,
    2033             :                                  Local<SharedArrayBuffer> shared_array_buffer));
    2034             :     MOCK_METHOD2(GetSharedArrayBufferFromId,
    2035             :                  MaybeLocal<SharedArrayBuffer>(Isolate* isolate, uint32_t id));
    2036           0 :     void ThrowDataCloneError(Local<String> message) override {
    2037           0 :       test_->isolate()->ThrowException(Exception::Error(message));
    2038           0 :     }
    2039             : 
    2040             :    private:
    2041             :     ValueSerializerTestWithSharedArrayBufferClone* test_;
    2042             :   };
    2043             : 
    2044           4 :   class DeserializerDelegate : public ValueDeserializer::Delegate {
    2045             :    public:
    2046             :     explicit DeserializerDelegate(
    2047           2 :         ValueSerializerTestWithSharedArrayBufferClone* test) {}
    2048          11 :     MOCK_METHOD2(GetSharedArrayBufferFromId,
    2049             :                  MaybeLocal<SharedArrayBuffer>(Isolate* isolate, uint32_t id));
    2050             :   };
    2051             : 
    2052             : #if __clang__
    2053             : #pragma clang diagnostic pop
    2054             : #endif
    2055             : 
    2056           6 :   ValueSerializer::Delegate* GetSerializerDelegate() override {
    2057           6 :     return &serializer_delegate_;
    2058             :   }
    2059             : 
    2060           3 :   ValueDeserializer::Delegate* GetDeserializerDelegate() override {
    2061           3 :     return &deserializer_delegate_;
    2062             :   }
    2063             : 
    2064             :   SerializerDelegate serializer_delegate_;
    2065             :   DeserializerDelegate deserializer_delegate_;
    2066             : 
    2067             :  private:
    2068             :   static bool flag_was_enabled_;
    2069             :   std::vector<uint8_t> data_;
    2070             :   Local<SharedArrayBuffer> input_buffer_;
    2071             :   Local<SharedArrayBuffer> output_buffer_;
    2072             : };
    2073             : 
    2074             : bool ValueSerializerTestWithSharedArrayBufferClone::flag_was_enabled_ = false;
    2075             : 
    2076       15443 : TEST_F(ValueSerializerTestWithSharedArrayBufferClone,
    2077             :        RoundTripSharedArrayBufferClone) {
    2078           2 :   InitializeData({0x00, 0x01, 0x80, 0xFF});
    2079             : 
    2080           6 :   EXPECT_CALL(serializer_delegate_,
    2081             :               GetSharedArrayBufferId(isolate(), input_buffer()))
    2082           4 :       .WillRepeatedly(Return(Just(0U)));
    2083           5 :   EXPECT_CALL(deserializer_delegate_, GetSharedArrayBufferFromId(isolate(), 0U))
    2084           4 :       .WillRepeatedly(Return(output_buffer()));
    2085             : 
    2086           1 :   Local<Value> value = RoundTripTest(input_buffer());
    2087           2 :   ASSERT_TRUE(value->IsSharedArrayBuffer());
    2088           1 :   EXPECT_EQ(output_buffer(), value);
    2089           1 :   ExpectScriptTrue("new Uint8Array(result).toString() === '0,1,128,255'");
    2090             : 
    2091             :   Local<Object> object;
    2092             :   {
    2093             :     Context::Scope scope(serialization_context());
    2094           1 :     object = Object::New(isolate());
    2095           3 :     EXPECT_TRUE(object
    2096             :                     ->CreateDataProperty(serialization_context(),
    2097             :                                          StringFromUtf8("a"), input_buffer())
    2098           0 :                     .FromMaybe(false));
    2099           3 :     EXPECT_TRUE(object
    2100             :                     ->CreateDataProperty(serialization_context(),
    2101             :                                          StringFromUtf8("b"), input_buffer())
    2102           0 :                     .FromMaybe(false));
    2103             :   }
    2104           1 :   value = RoundTripTest(object);
    2105           1 :   ExpectScriptTrue("result.a instanceof SharedArrayBuffer");
    2106           1 :   ExpectScriptTrue("result.a === result.b");
    2107           1 :   ExpectScriptTrue("new Uint8Array(result.a).toString() === '0,1,128,255'");
    2108             : }
    2109             : 
    2110       15443 : TEST_F(ValueSerializerTestWithSharedArrayBufferClone,
    2111             :        RoundTripWebAssemblyMemory) {
    2112           1 :   bool flag_was_enabled = i::FLAG_experimental_wasm_threads;
    2113           1 :   i::FLAG_experimental_wasm_threads = true;
    2114             : 
    2115             :   std::vector<uint8_t> data = {0x00, 0x01, 0x80, 0xFF};
    2116           1 :   data.resize(65536);
    2117           1 :   InitializeData(data);
    2118             : 
    2119           6 :   EXPECT_CALL(serializer_delegate_,
    2120             :               GetSharedArrayBufferId(isolate(), input_buffer()))
    2121           4 :       .WillRepeatedly(Return(Just(0U)));
    2122           5 :   EXPECT_CALL(deserializer_delegate_, GetSharedArrayBufferFromId(isolate(), 0U))
    2123           4 :       .WillRepeatedly(Return(output_buffer()));
    2124             : 
    2125             :   Local<Value> input;
    2126             :   {
    2127             :     Context::Scope scope(serialization_context());
    2128             :     const int32_t kMaxPages = 1;
    2129             :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate());
    2130             :     i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(*input_buffer());
    2131             :     input = Utils::Convert<i::WasmMemoryObject, Value>(
    2132           1 :         i::WasmMemoryObject::New(i_isolate, obj, kMaxPages));
    2133             :   }
    2134           1 :   RoundTripTest(input);
    2135           1 :   ExpectScriptTrue("result instanceof WebAssembly.Memory");
    2136           1 :   ExpectScriptTrue("result.buffer.byteLength === 65536");
    2137             :   ExpectScriptTrue(
    2138           1 :       "new Uint8Array(result.buffer, 0, 4).toString() === '0,1,128,255'");
    2139             : 
    2140           1 :   i::FLAG_experimental_wasm_threads = flag_was_enabled;
    2141           1 : }
    2142             : 
    2143       15444 : TEST_F(ValueSerializerTest, UnsupportedHostObject) {
    2144           1 :   InvalidEncodeTest("new ExampleHostObject()");
    2145             :   InvalidEncodeTest("({ a: new ExampleHostObject() })");
    2146           1 : }
    2147             : 
    2148          14 : class ValueSerializerTestWithHostObject : public ValueSerializerTest {
    2149             :  protected:
    2150          14 :   ValueSerializerTestWithHostObject() : serializer_delegate_(this) {}
    2151             : 
    2152             :   static const uint8_t kExampleHostObjectTag;
    2153             : 
    2154             :   void WriteExampleHostObjectTag() {
    2155          11 :     serializer_->WriteRawBytes(&kExampleHostObjectTag, 1);
    2156             :   }
    2157             : 
    2158          12 :   bool ReadExampleHostObjectTag() {
    2159             :     const void* tag;
    2160          24 :     return deserializer_->ReadRawBytes(1, &tag) &&
    2161          24 :            *reinterpret_cast<const uint8_t*>(tag) == kExampleHostObjectTag;
    2162             :   }
    2163             : 
    2164             : // GMock doesn't use the "override" keyword.
    2165             : #if __clang__
    2166             : #pragma clang diagnostic push
    2167             : #pragma clang diagnostic ignored "-Winconsistent-missing-override"
    2168             : #endif
    2169             : 
    2170          14 :   class SerializerDelegate : public ValueSerializer::Delegate {
    2171             :    public:
    2172             :     explicit SerializerDelegate(ValueSerializerTestWithHostObject* test)
    2173          14 :         : test_(test) {}
    2174          35 :     MOCK_METHOD2(WriteHostObject,
    2175             :                  Maybe<bool>(Isolate* isolate, Local<Object> object));
    2176           0 :     void ThrowDataCloneError(Local<String> message) override {
    2177           0 :       test_->isolate()->ThrowException(Exception::Error(message));
    2178           0 :     }
    2179             : 
    2180             :    private:
    2181             :     ValueSerializerTestWithHostObject* test_;
    2182             :   };
    2183             : 
    2184          21 :   class DeserializerDelegate : public ValueDeserializer::Delegate {
    2185             :    public:
    2186          33 :     MOCK_METHOD1(ReadHostObject, MaybeLocal<Object>(Isolate* isolate));
    2187             :   };
    2188             : 
    2189             : #if __clang__
    2190             : #pragma clang diagnostic pop
    2191             : #endif
    2192             : 
    2193          22 :   ValueSerializer::Delegate* GetSerializerDelegate() override {
    2194          22 :     return &serializer_delegate_;
    2195             :   }
    2196          10 :   void BeforeEncode(ValueSerializer* serializer) override {
    2197          11 :     serializer_ = serializer;
    2198          10 :   }
    2199          12 :   ValueDeserializer::Delegate* GetDeserializerDelegate() override {
    2200          12 :     return &deserializer_delegate_;
    2201             :   }
    2202          12 :   void BeforeDecode(ValueDeserializer* deserializer) override {
    2203          12 :     deserializer_ = deserializer;
    2204          12 :   }
    2205             : 
    2206             :   SerializerDelegate serializer_delegate_;
    2207             :   DeserializerDelegate deserializer_delegate_;
    2208             :   ValueSerializer* serializer_;
    2209             :   ValueDeserializer* deserializer_;
    2210             : 
    2211             :   friend class SerializerDelegate;
    2212             :   friend class DeserializerDelegate;
    2213             : };
    2214             : 
    2215             : // This is a tag that is used in V8. Using this ensures that we have separate
    2216             : // tag namespaces.
    2217             : const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = 'T';
    2218             : 
    2219       15443 : TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) {
    2220             :   // The host can serialize data as uint32_t.
    2221           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2222           6 :       .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) {
    2223             :         uint32_t value = 0;
    2224           4 :         EXPECT_TRUE(object->GetInternalField(0)
    2225             :                         ->Uint32Value(serialization_context())
    2226           0 :                         .To(&value));
    2227             :         WriteExampleHostObjectTag();
    2228           2 :         serializer_->WriteUint32(value);
    2229           2 :         return Just(true);
    2230           2 :       }));
    2231           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2232           6 :       .WillRepeatedly(Invoke([this](Isolate*) {
    2233           4 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2234           2 :         uint32_t value = 0;
    2235           4 :         EXPECT_TRUE(deserializer_->ReadUint32(&value));
    2236           4 :         Local<Value> argv[] = {Integer::NewFromUnsigned(isolate(), value)};
    2237           2 :         return NewHostObject(deserialization_context(), arraysize(argv), argv);
    2238           2 :       }));
    2239           1 :   Local<Value> value = RoundTripTest("new ExampleHostObject(42)");
    2240           2 :   ASSERT_TRUE(value->IsObject());
    2241           2 :   ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
    2242             :   ExpectScriptTrue(
    2243           1 :       "Object.getPrototypeOf(result) === ExampleHostObject.prototype");
    2244           1 :   ExpectScriptTrue("result.value === 42");
    2245             : 
    2246             :   value = RoundTripTest("new ExampleHostObject(0xCAFECAFE)");
    2247           1 :   ExpectScriptTrue("result.value === 0xCAFECAFE");
    2248             : }
    2249             : 
    2250       15443 : TEST_F(ValueSerializerTestWithHostObject, RoundTripUint64) {
    2251             :   // The host can serialize data as uint64_t.
    2252           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2253           8 :       .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) {
    2254             :         uint32_t value = 0, value2 = 0;
    2255           4 :         EXPECT_TRUE(object->GetInternalField(0)
    2256             :                         ->Uint32Value(serialization_context())
    2257           0 :                         .To(&value));
    2258           4 :         EXPECT_TRUE(object->GetInternalField(1)
    2259             :                         ->Uint32Value(serialization_context())
    2260           0 :                         .To(&value2));
    2261             :         WriteExampleHostObjectTag();
    2262           4 :         serializer_->WriteUint64((static_cast<uint64_t>(value) << 32) | value2);
    2263           2 :         return Just(true);
    2264           2 :       }));
    2265           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2266           6 :       .WillRepeatedly(Invoke([this](Isolate*) {
    2267           4 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2268             :         uint64_t value_packed;
    2269           4 :         EXPECT_TRUE(deserializer_->ReadUint64(&value_packed));
    2270             :         Local<Value> argv[] = {
    2271             :             Integer::NewFromUnsigned(isolate(),
    2272           2 :                                      static_cast<uint32_t>(value_packed >> 32)),
    2273             :             Integer::NewFromUnsigned(isolate(),
    2274           8 :                                      static_cast<uint32_t>(value_packed))};
    2275           2 :         return NewHostObject(deserialization_context(), arraysize(argv), argv);
    2276           2 :       }));
    2277           1 :   Local<Value> value = RoundTripTest("new ExampleHostObject(42, 0)");
    2278           2 :   ASSERT_TRUE(value->IsObject());
    2279           2 :   ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
    2280             :   ExpectScriptTrue(
    2281           1 :       "Object.getPrototypeOf(result) === ExampleHostObject.prototype");
    2282           1 :   ExpectScriptTrue("result.value === 42");
    2283           1 :   ExpectScriptTrue("result.value2 === 0");
    2284             : 
    2285             :   value = RoundTripTest("new ExampleHostObject(0xFFFFFFFF, 0x12345678)");
    2286           1 :   ExpectScriptTrue("result.value === 0xFFFFFFFF");
    2287           1 :   ExpectScriptTrue("result.value2 === 0x12345678");
    2288             : }
    2289             : 
    2290       15443 : TEST_F(ValueSerializerTestWithHostObject, RoundTripDouble) {
    2291             :   // The host can serialize data as double.
    2292           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2293          12 :       .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) {
    2294             :         double value = 0;
    2295           8 :         EXPECT_TRUE(object->GetInternalField(0)
    2296             :                         ->NumberValue(serialization_context())
    2297           0 :                         .To(&value));
    2298             :         WriteExampleHostObjectTag();
    2299           4 :         serializer_->WriteDouble(value);
    2300           4 :         return Just(true);
    2301           2 :       }));
    2302           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2303          12 :       .WillRepeatedly(Invoke([this](Isolate*) {
    2304           8 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2305           4 :         double value = 0;
    2306           8 :         EXPECT_TRUE(deserializer_->ReadDouble(&value));
    2307           8 :         Local<Value> argv[] = {Number::New(isolate(), value)};
    2308           4 :         return NewHostObject(deserialization_context(), arraysize(argv), argv);
    2309           2 :       }));
    2310           1 :   Local<Value> value = RoundTripTest("new ExampleHostObject(-3.5)");
    2311           2 :   ASSERT_TRUE(value->IsObject());
    2312           2 :   ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
    2313             :   ExpectScriptTrue(
    2314           1 :       "Object.getPrototypeOf(result) === ExampleHostObject.prototype");
    2315           1 :   ExpectScriptTrue("result.value === -3.5");
    2316             : 
    2317             :   value = RoundTripTest("new ExampleHostObject(NaN)");
    2318           1 :   ExpectScriptTrue("Number.isNaN(result.value)");
    2319             : 
    2320             :   value = RoundTripTest("new ExampleHostObject(Infinity)");
    2321           1 :   ExpectScriptTrue("result.value === Infinity");
    2322             : 
    2323             :   value = RoundTripTest("new ExampleHostObject(-0)");
    2324           1 :   ExpectScriptTrue("1/result.value === -Infinity");
    2325             : }
    2326             : 
    2327       15443 : TEST_F(ValueSerializerTestWithHostObject, RoundTripRawBytes) {
    2328             :   // The host can serialize arbitrary raw bytes.
    2329             :   const struct {
    2330             :     uint64_t u64;
    2331             :     uint32_t u32;
    2332             :     char str[12];
    2333           1 :   } sample_data = {0x1234567812345678, 0x87654321, "Hello world"};
    2334           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2335             :       .WillRepeatedly(
    2336           2 :           Invoke([this, &sample_data](Isolate*, Local<Object> object) {
    2337             :             WriteExampleHostObjectTag();
    2338           1 :             serializer_->WriteRawBytes(&sample_data, sizeof(sample_data));
    2339           1 :             return Just(true);
    2340           2 :           }));
    2341           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2342           4 :       .WillRepeatedly(Invoke([this, &sample_data](Isolate*) {
    2343           2 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2344           1 :         const void* copied_data = nullptr;
    2345           2 :         EXPECT_TRUE(
    2346           0 :             deserializer_->ReadRawBytes(sizeof(sample_data), &copied_data));
    2347           1 :         if (copied_data) {
    2348           2 :           EXPECT_EQ(0, memcmp(&sample_data, copied_data, sizeof(sample_data)));
    2349             :         }
    2350           1 :         return NewHostObject(deserialization_context(), 0, nullptr);
    2351           2 :       }));
    2352           1 :   Local<Value> value = RoundTripTest("new ExampleHostObject()");
    2353           2 :   ASSERT_TRUE(value->IsObject());
    2354           2 :   ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
    2355             :   ExpectScriptTrue(
    2356           1 :       "Object.getPrototypeOf(result) === ExampleHostObject.prototype");
    2357             : }
    2358             : 
    2359       15443 : TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) {
    2360             :   // If the same object exists in two places, the delegate should be invoked
    2361             :   // only once, and the objects should be the same (by reference equality) on
    2362             :   // the other side.
    2363           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2364           1 :       .WillOnce(Invoke([this](Isolate*, Local<Object> object) {
    2365             :         WriteExampleHostObjectTag();
    2366             :         return Just(true);
    2367           2 :       }));
    2368           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2369           2 :       .WillOnce(Invoke([this](Isolate*) {
    2370           2 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2371           1 :         return NewHostObject(deserialization_context(), 0, nullptr);
    2372           2 :       }));
    2373           1 :   RoundTripTest("({ a: new ExampleHostObject(), get b() { return this.a; }})");
    2374           1 :   ExpectScriptTrue("result.a instanceof ExampleHostObject");
    2375           1 :   ExpectScriptTrue("result.a === result.b");
    2376           1 : }
    2377             : 
    2378       15443 : TEST_F(ValueSerializerTestWithHostObject, DecodeSimpleHostObject) {
    2379           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2380           2 :       .WillRepeatedly(Invoke([this](Isolate*) {
    2381           2 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2382           1 :         return NewHostObject(deserialization_context(), 0, nullptr);
    2383           2 :       }));
    2384           2 :   DecodeTest({0xFF, 0x0D, 0x5C, kExampleHostObjectTag});
    2385             :   ExpectScriptTrue(
    2386           1 :       "Object.getPrototypeOf(result) === ExampleHostObject.prototype");
    2387           1 : }
    2388             : 
    2389           2 : class ValueSerializerTestWithHostArrayBufferView
    2390             :     : public ValueSerializerTestWithHostObject {
    2391             :  protected:
    2392           1 :   void BeforeEncode(ValueSerializer* serializer) override {
    2393             :     ValueSerializerTestWithHostObject::BeforeEncode(serializer);
    2394           1 :     serializer_->SetTreatArrayBufferViewsAsHostObjects(true);
    2395           1 :   }
    2396             : };
    2397             : 
    2398       15444 : TEST_F(ValueSerializerTestWithHostArrayBufferView, RoundTripUint8ArrayInput) {
    2399           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2400           2 :       .WillOnce(Invoke([this](Isolate*, Local<Object> object) {
    2401           2 :         EXPECT_TRUE(object->IsUint8Array());
    2402             :         WriteExampleHostObjectTag();
    2403           1 :         return Just(true);
    2404           2 :       }));
    2405           4 :   EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
    2406           1 :       .WillOnce(Invoke([this](Isolate*) {
    2407           2 :         EXPECT_TRUE(ReadExampleHostObjectTag());
    2408           1 :         return NewDummyUint8Array();
    2409           2 :       }));
    2410             :   RoundTripTest(
    2411           1 :       "({ a: new Uint8Array([1, 2, 3]), get b() { return this.a; }})");
    2412           1 :   ExpectScriptTrue("result.a instanceof Uint8Array");
    2413           1 :   ExpectScriptTrue("result.a.toString() === '4,5,6'");
    2414           1 :   ExpectScriptTrue("result.a === result.b");
    2415           1 : }
    2416             : 
    2417             : // It's expected that WebAssembly has more exhaustive tests elsewhere; this
    2418             : // mostly checks that the logic to embed it in structured clone serialization
    2419             : // works correctly.
    2420             : 
    2421             : // A simple module which exports an "increment" function.
    2422             : // Copied from test/mjsunit/wasm/incrementer.wasm.
    2423             : const unsigned char kIncrementerWasm[] = {
    2424             :     0,   97, 115, 109, 1, 0,  0, 0, 1,   6,   1,  96,  1,   127, 1,   127,
    2425             :     3,   2,  1,   0,   7, 13, 1, 9, 105, 110, 99, 114, 101, 109, 101, 110,
    2426             :     116, 0,  0,   10,  9, 1,  7, 0, 32,  0,   65, 1,   106, 11,
    2427             : };
    2428             : 
    2429          42 : class ValueSerializerTestWithWasm : public ValueSerializerTest {
    2430             :  public:
    2431             :   static const char* kUnsupportedSerialization;
    2432             : 
    2433          14 :   ValueSerializerTestWithWasm()
    2434             :       : serialize_delegate_(&transfer_modules_),
    2435          56 :         deserialize_delegate_(&transfer_modules_) {}
    2436             : 
    2437             :   void Reset() {
    2438             :     current_serializer_delegate_ = nullptr;
    2439             :     transfer_modules_.clear();
    2440             :     SetExpectInlineWasm(false);
    2441             :   }
    2442             : 
    2443             :   void EnableTransferSerialization() {
    2444           5 :     current_serializer_delegate_ = &serialize_delegate_;
    2445             :   }
    2446             : 
    2447             :   void EnableTransferDeserialization() {
    2448           3 :     current_deserializer_delegate_ = &deserialize_delegate_;
    2449             :   }
    2450             : 
    2451             :   void EnableThrowingSerializer() {
    2452           1 :     current_serializer_delegate_ = &throwing_serializer_;
    2453             :   }
    2454             : 
    2455             :   void EnableDefaultDeserializer() {
    2456           1 :     current_deserializer_delegate_ = &default_deserializer_;
    2457             :   }
    2458             : 
    2459             :  protected:
    2460          14 :   static void SetUpTestCase() {
    2461          14 :     g_saved_flag = i::FLAG_expose_wasm;
    2462          14 :     i::FLAG_expose_wasm = true;
    2463             :     ValueSerializerTest::SetUpTestCase();
    2464          14 :   }
    2465             : 
    2466          14 :   static void TearDownTestCase() {
    2467             :     ValueSerializerTest::TearDownTestCase();
    2468          14 :     i::FLAG_expose_wasm = g_saved_flag;
    2469          14 :     g_saved_flag = false;
    2470          14 :   }
    2471             : 
    2472          42 :   class ThrowingSerializer : public ValueSerializer::Delegate {
    2473             :    public:
    2474           1 :     Maybe<uint32_t> GetWasmModuleTransferId(
    2475             :         Isolate* isolate, Local<WasmModuleObject> module) override {
    2476             :       isolate->ThrowException(Exception::Error(
    2477           1 :           String::NewFromOneByte(
    2478             :               isolate,
    2479             :               reinterpret_cast<const uint8_t*>(kUnsupportedSerialization),
    2480           1 :               NewStringType::kNormal)
    2481           1 :               .ToLocalChecked()));
    2482           1 :       return Nothing<uint32_t>();
    2483             :     }
    2484             : 
    2485           0 :     void ThrowDataCloneError(Local<String> message) override { UNREACHABLE(); }
    2486             :   };
    2487             : 
    2488          28 :   class SerializeToTransfer : public ValueSerializer::Delegate {
    2489             :    public:
    2490             :     SerializeToTransfer(
    2491             :         std::vector<WasmModuleObject::TransferrableModule>* modules)
    2492          14 :         : modules_(modules) {}
    2493           6 :     Maybe<uint32_t> GetWasmModuleTransferId(
    2494             :         Isolate* isolate, Local<WasmModuleObject> module) override {
    2495          12 :       modules_->push_back(module->GetTransferrableModule());
    2496          12 :       return Just(static_cast<uint32_t>(modules_->size()) - 1);
    2497             :     }
    2498             : 
    2499           0 :     void ThrowDataCloneError(Local<String> message) override { UNREACHABLE(); }
    2500             : 
    2501             :    private:
    2502             :     std::vector<WasmModuleObject::TransferrableModule>* modules_;
    2503             :   };
    2504             : 
    2505          28 :   class DeserializeFromTransfer : public ValueDeserializer::Delegate {
    2506             :    public:
    2507             :     DeserializeFromTransfer(
    2508             :         std::vector<WasmModuleObject::TransferrableModule>* modules)
    2509          14 :         : modules_(modules) {}
    2510             : 
    2511           4 :     MaybeLocal<WasmModuleObject> GetWasmModuleFromId(Isolate* isolate,
    2512             :                                                      uint32_t id) override {
    2513             :       return WasmModuleObject::FromTransferrableModule(isolate,
    2514           8 :                                                        modules_->at(id));
    2515             :     }
    2516             : 
    2517             :    private:
    2518             :     std::vector<WasmModuleObject::TransferrableModule>* modules_;
    2519             :   };
    2520             : 
    2521          19 :   ValueSerializer::Delegate* GetSerializerDelegate() override {
    2522          19 :     return current_serializer_delegate_;
    2523             :   }
    2524             : 
    2525          12 :   ValueDeserializer::Delegate* GetDeserializerDelegate() override {
    2526          12 :     return current_deserializer_delegate_;
    2527             :   }
    2528             : 
    2529          12 :   Local<WasmModuleObject> MakeWasm() {
    2530             :     Context::Scope scope(serialization_context());
    2531          12 :     return WasmModuleObject::DeserializeOrCompile(
    2532             :                isolate(), {nullptr, 0},
    2533          12 :                {kIncrementerWasm, sizeof(kIncrementerWasm)})
    2534          12 :         .ToLocalChecked();
    2535             :   }
    2536             : 
    2537           2 :   void ExpectPass() {
    2538           4 :     Local<Value> value = RoundTripTest(MakeWasm());
    2539             :     Context::Scope scope(deserialization_context());
    2540           4 :     ASSERT_TRUE(value->IsWebAssemblyCompiledModule());
    2541             :     ExpectScriptTrue(
    2542           2 :         "new WebAssembly.Instance(result).exports.increment(8) === 9");
    2543             :   }
    2544             : 
    2545           3 :   void ExpectFail() {
    2546           6 :     const std::vector<uint8_t> data = EncodeTest(MakeWasm());
    2547           3 :     InvalidDecodeTest(data);
    2548           3 :   }
    2549             : 
    2550           2 :   Local<Value> GetComplexObjectWithDuplicate() {
    2551             :     Context::Scope scope(serialization_context());
    2552           2 :     Local<Value> wasm_module = MakeWasm();
    2553             :     serialization_context()
    2554           4 :         ->Global()
    2555           2 :         ->CreateDataProperty(serialization_context(),
    2556           4 :                              StringFromUtf8("wasm_module"), wasm_module)
    2557             :         .FromMaybe(false);
    2558             :     Local<Script> script =
    2559           2 :         Script::Compile(
    2560             :             serialization_context(),
    2561           2 :             StringFromUtf8("({mod1: wasm_module, num: 2, mod2: wasm_module})"))
    2562             :             .ToLocalChecked();
    2563           4 :     return script->Run(serialization_context()).ToLocalChecked();
    2564             :   }
    2565             : 
    2566           4 :   void VerifyComplexObject(Local<Value> value) {
    2567           8 :     ASSERT_TRUE(value->IsObject());
    2568           4 :     ExpectScriptTrue("result.mod1 instanceof WebAssembly.Module");
    2569           4 :     ExpectScriptTrue("result.mod2 instanceof WebAssembly.Module");
    2570           4 :     ExpectScriptTrue("result.num === 2");
    2571             :   }
    2572             : 
    2573           2 :   Local<Value> GetComplexObjectWithMany() {
    2574             :     Context::Scope scope(serialization_context());
    2575           2 :     Local<Value> wasm_module1 = MakeWasm();
    2576           2 :     Local<Value> wasm_module2 = MakeWasm();
    2577             :     serialization_context()
    2578           4 :         ->Global()
    2579           2 :         ->CreateDataProperty(serialization_context(),
    2580           4 :                              StringFromUtf8("wasm_module1"), wasm_module1)
    2581             :         .FromMaybe(false);
    2582             :     serialization_context()
    2583           4 :         ->Global()
    2584           2 :         ->CreateDataProperty(serialization_context(),
    2585           4 :                              StringFromUtf8("wasm_module2"), wasm_module2)
    2586             :         .FromMaybe(false);
    2587             :     Local<Script> script =
    2588           2 :         Script::Compile(
    2589             :             serialization_context(),
    2590             :             StringFromUtf8(
    2591           2 :                 "({mod1: wasm_module1, num: 2, mod2: wasm_module2})"))
    2592             :             .ToLocalChecked();
    2593           4 :     return script->Run(serialization_context()).ToLocalChecked();
    2594             :   }
    2595             : 
    2596             :  private:
    2597             :   static bool g_saved_flag;
    2598             :   std::vector<WasmModuleObject::TransferrableModule> transfer_modules_;
    2599             :   SerializeToTransfer serialize_delegate_;
    2600             :   DeserializeFromTransfer deserialize_delegate_;
    2601             :   ValueSerializer::Delegate* current_serializer_delegate_ = nullptr;
    2602             :   ValueDeserializer::Delegate* current_deserializer_delegate_ = nullptr;
    2603             :   ThrowingSerializer throwing_serializer_;
    2604             :   ValueDeserializer::Delegate default_deserializer_;
    2605             : };
    2606             : 
    2607             : bool ValueSerializerTestWithWasm::g_saved_flag = false;
    2608             : const char* ValueSerializerTestWithWasm::kUnsupportedSerialization =
    2609             :     "Wasm Serialization Not Supported";
    2610             : 
    2611             : // The default implementation of the serialization
    2612             : // delegate throws when trying to serialize wasm. The
    2613             : // embedder must decide serialization policy.
    2614       15443 : TEST_F(ValueSerializerTestWithWasm, DefaultSerializationDelegate) {
    2615             :   EnableThrowingSerializer();
    2616           2 :   Local<Message> message = InvalidEncodeTest(MakeWasm());
    2617           2 :   size_t msg_len = static_cast<size_t>(message->Get()->Length());
    2618           1 :   std::unique_ptr<char[]> buff(new char[msg_len + 1]);
    2619           2 :   message->Get()->WriteOneByte(isolate(),
    2620           1 :                                reinterpret_cast<uint8_t*>(buff.get()));
    2621             :   // the message ends with the custom error string
    2622           1 :   size_t custom_msg_len = strlen(kUnsupportedSerialization);
    2623           1 :   ASSERT_GE(msg_len, custom_msg_len);
    2624           1 :   size_t start_pos = msg_len - custom_msg_len;
    2625           2 :   ASSERT_EQ(strcmp(&buff.get()[start_pos], kUnsupportedSerialization), 0);
    2626             : }
    2627             : 
    2628             : // The default deserializer throws if wasm transfer is attempted
    2629       15443 : TEST_F(ValueSerializerTestWithWasm, DefaultDeserializationDelegate) {
    2630             :   EnableTransferSerialization();
    2631             :   EnableDefaultDeserializer();
    2632           1 :   ExpectFail();
    2633           1 : }
    2634             : 
    2635             : // We only want to allow deserialization through
    2636             : // transferred modules - which requres both serializer
    2637             : // and deserializer to understand that - or through
    2638             : // explicitly allowing inlined data, which requires
    2639             : // deserializer opt-in (we default the serializer to
    2640             : // inlined data because we don't trust that data on the
    2641             : // receiving end anyway).
    2642             : 
    2643       15443 : TEST_F(ValueSerializerTestWithWasm, RoundtripWasmTransfer) {
    2644             :   EnableTransferSerialization();
    2645             :   EnableTransferDeserialization();
    2646           1 :   ExpectPass();
    2647           1 : }
    2648             : 
    2649       15443 : TEST_F(ValueSerializerTestWithWasm, RountripWasmInline) {
    2650             :   SetExpectInlineWasm(true);
    2651           1 :   ExpectPass();
    2652           1 : }
    2653             : 
    2654       15443 : TEST_F(ValueSerializerTestWithWasm, CannotDeserializeWasmInlineData) {
    2655           1 :   ExpectFail();
    2656           1 : }
    2657             : 
    2658       15443 : TEST_F(ValueSerializerTestWithWasm, CannotTransferWasmWhenExpectingInline) {
    2659             :   EnableTransferSerialization();
    2660             :   SetExpectInlineWasm(true);
    2661           1 :   ExpectFail();
    2662           1 : }
    2663             : 
    2664       15443 : TEST_F(ValueSerializerTestWithWasm, ComplexObjectDuplicateTransfer) {
    2665             :   EnableTransferSerialization();
    2666             :   EnableTransferDeserialization();
    2667           1 :   Local<Value> value = RoundTripTest(GetComplexObjectWithDuplicate());
    2668           1 :   VerifyComplexObject(value);
    2669           1 :   ExpectScriptTrue("result.mod1 === result.mod2");
    2670           1 : }
    2671             : 
    2672       15443 : TEST_F(ValueSerializerTestWithWasm, ComplexObjectDuplicateInline) {
    2673             :   SetExpectInlineWasm(true);
    2674           1 :   Local<Value> value = RoundTripTest(GetComplexObjectWithDuplicate());
    2675           1 :   VerifyComplexObject(value);
    2676           1 :   ExpectScriptTrue("result.mod1 === result.mod2");
    2677           1 : }
    2678             : 
    2679       15443 : TEST_F(ValueSerializerTestWithWasm, ComplexObjectWithManyTransfer) {
    2680             :   EnableTransferSerialization();
    2681             :   EnableTransferDeserialization();
    2682           1 :   Local<Value> value = RoundTripTest(GetComplexObjectWithMany());
    2683           1 :   VerifyComplexObject(value);
    2684           1 :   ExpectScriptTrue("result.mod1 != result.mod2");
    2685           1 : }
    2686             : 
    2687       15443 : TEST_F(ValueSerializerTestWithWasm, ComplexObjectWithManyInline) {
    2688             :   SetExpectInlineWasm(true);
    2689           1 :   Local<Value> value = RoundTripTest(GetComplexObjectWithMany());
    2690           1 :   VerifyComplexObject(value);
    2691           1 :   ExpectScriptTrue("result.mod1 != result.mod2");
    2692           1 : }
    2693             : 
    2694             : // As produced around Chrome 56.
    2695             : const unsigned char kSerializedIncrementerWasm[] = {
    2696             :     0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x2D, 0x00, 0x61, 0x73, 0x6D, 0x0D,
    2697             :     0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03,
    2698             :     0x02, 0x01, 0x00, 0x07, 0x0D, 0x01, 0x09, 0x69, 0x6E, 0x63, 0x72, 0x65,
    2699             :     0x6D, 0x65, 0x6E, 0x74, 0x00, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0x20,
    2700             :     0x00, 0x41, 0x01, 0x6A, 0xF8, 0x04, 0xA1, 0x06, 0xDE, 0xC0, 0xC6, 0x44,
    2701             :     0x3C, 0x29, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x02, 0x00, 0x00, 0x81, 0x4E,
    2702             :     0xCE, 0x7C, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x02,
    2703             :     0x00, 0x00, 0xB0, 0x25, 0x30, 0xE3, 0xF2, 0xDB, 0x2E, 0x48, 0x00, 0x00,
    2704             :     0x00, 0x80, 0xE8, 0x00, 0x00, 0x80, 0xE0, 0x01, 0x00, 0x80, 0x00, 0x00,
    2705             :     0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x07, 0x08, 0x00, 0x00, 0x09, 0x04,
    2706             :     0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3C, 0x8C, 0xC0, 0x00, 0x00,
    2707             :     0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x8C, 0xC0, 0x00, 0x00,
    2708             :     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x70, 0x94, 0x01, 0x0C, 0x8B,
    2709             :     0xC1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x25, 0xDC, 0x00,
    2710             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x01, 0x10, 0x8C, 0xC0, 0x00, 0x00,
    2711             :     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x00, 0x00, 0x00, 0x00,
    2712             :     0x00, 0x00, 0x00, 0x00, 0x05, 0x7D, 0x01, 0x1A, 0xE1, 0x02, 0x00, 0x00,
    2713             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x23, 0x88, 0x42, 0x32, 0x03,
    2714             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00,
    2715             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x04, 0x00,
    2716             :     0x00, 0x02, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
    2717             :     0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x49, 0x3B, 0xA5, 0x60, 0x0C, 0x00,
    2718             :     0x00, 0x0F, 0x86, 0x04, 0x00, 0x00, 0x00, 0x83, 0xC0, 0x01, 0xC3, 0x55,
    2719             :     0x48, 0x89, 0xE5, 0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
    2720             :     0x00, 0x41, 0x52, 0x48, 0x83, 0xEC, 0x08, 0x48, 0x89, 0x45, 0xF0, 0x48,
    2721             :     0xBB, 0xB0, 0x67, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xC0, 0x48,
    2722             :     0xBE, 0xE1, 0x57, 0x81, 0x85, 0xF6, 0x14, 0x00, 0x00, 0xE8, 0xFC, 0x3C,
    2723             :     0xEA, 0xFF, 0x48, 0x8B, 0x45, 0xF0, 0x48, 0x8B, 0xE5, 0x5D, 0xEB, 0xBF,
    2724             :     0x66, 0x90, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x44, 0x00,
    2725             :     0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
    2726             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2727             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2728             :     0x00, 0x00, 0x0F, 0x20, 0x84, 0x0F, 0x7D, 0x01, 0x0D, 0x00, 0x0F, 0x04,
    2729             :     0x6D, 0x08, 0x0F, 0xF0, 0x02, 0x80, 0x94, 0x01, 0x0C, 0x8B, 0xC1, 0x00,
    2730             :     0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xED, 0xA9, 0x2D, 0x00, 0x00,
    2731             :     0x00, 0x00, 0x00, 0x9E, 0xE0, 0x38, 0x1A, 0x61, 0x03, 0x00, 0x00, 0x00,
    2732             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x23, 0x88, 0x42, 0x32, 0x03, 0x00,
    2733             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00,
    2734             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
    2735             :     0x02, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
    2736             :     0xFF, 0x00, 0x00, 0x00, 0x00, 0x55, 0x48, 0x89, 0xE5, 0x56, 0x57, 0x48,
    2737             :     0x8B, 0x45, 0x10, 0xE8, 0x11, 0xED, 0xED, 0xFF, 0xA8, 0x01, 0x0F, 0x85,
    2738             :     0x2D, 0x00, 0x00, 0x00, 0x48, 0xC1, 0xE8, 0x20, 0xC5, 0xF9, 0x57, 0xC0,
    2739             :     0xC5, 0xFB, 0x2A, 0xC0, 0xC4, 0xE1, 0xFB, 0x2C, 0xC0, 0x48, 0x83, 0xF8,
    2740             :     0x01, 0x0F, 0x80, 0x34, 0x00, 0x00, 0x00, 0x8B, 0xC0, 0xE8, 0x27, 0xFE,
    2741             :     0xFF, 0xFF, 0x48, 0xC1, 0xE0, 0x20, 0x48, 0x8B, 0xE5, 0x5D, 0xC2, 0x10,
    2742             :     0x00, 0x49, 0x39, 0x45, 0xA0, 0x0F, 0x84, 0x07, 0x00, 0x00, 0x00, 0xC5,
    2743             :     0xFB, 0x10, 0x40, 0x07, 0xEB, 0xCE, 0x49, 0xBA, 0x00, 0x00, 0x00, 0x00,
    2744             :     0x00, 0x00, 0xF8, 0x7F, 0xC4, 0xC1, 0xF9, 0x6E, 0xC2, 0xEB, 0xBD, 0x48,
    2745             :     0x83, 0xEC, 0x08, 0xC5, 0xFB, 0x11, 0x04, 0x24, 0xE8, 0xCC, 0xFE, 0xFF,
    2746             :     0xFF, 0x48, 0x83, 0xC4, 0x08, 0xEB, 0xB8, 0x66, 0x90, 0x02, 0x00, 0x00,
    2747             :     0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
    2748             :     0x0F, 0x39, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x00,
    2749             :     0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x20, 0x84,
    2750             :     0x0F, 0xCC, 0x6E, 0x7D, 0x01, 0x72, 0x98, 0x00, 0x0F, 0xDC, 0x6D, 0x0C,
    2751             :     0x0F, 0xB0, 0x84, 0x0D, 0x04, 0x84, 0xE3, 0xC0, 0x00, 0x00, 0x00, 0x00,
    2752             :     0x00, 0x00, 0x00, 0x00, 0x84, 0xE0, 0x84, 0x84, 0x18, 0x2F, 0x2F, 0x2F,
    2753             :     0x2F, 0x2F};
    2754             : 
    2755       15443 : TEST_F(ValueSerializerTestWithWasm, DecodeWasmModule) {
    2756             :   if ((true)) return;  // TODO(mtrofin): fix this test
    2757             :   std::vector<uint8_t> raw(
    2758             :       kSerializedIncrementerWasm,
    2759             :       kSerializedIncrementerWasm + sizeof(kSerializedIncrementerWasm));
    2760             :   Local<Value> value = DecodeTest(raw);
    2761             :   ASSERT_TRUE(value->IsWebAssemblyCompiledModule());
    2762             :   ExpectScriptTrue(
    2763             :       "new WebAssembly.Instance(result).exports.increment(8) === 9");
    2764             : }
    2765             : 
    2766             : // As above, but with empty compiled data. Should work due to fallback to wire
    2767             : // data.
    2768             : const unsigned char kSerializedIncrementerWasmWithInvalidCompiledData[] = {
    2769             :     0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x2D, 0x00, 0x61, 0x73, 0x6D,
    2770             :     0x0D, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F, 0x01,
    2771             :     0x7F, 0x03, 0x02, 0x01, 0x00, 0x07, 0x0D, 0x01, 0x09, 0x69, 0x6E,
    2772             :     0x63, 0x72, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x00, 0x00, 0x0A, 0x08,
    2773             :     0x01, 0x06, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6A, 0x00};
    2774             : 
    2775       15443 : TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidCompiledData) {
    2776             :   if ((true)) return;  // TODO(titzer): regenerate this test
    2777             :   std::vector<uint8_t> raw(
    2778             :       kSerializedIncrementerWasmWithInvalidCompiledData,
    2779             :       kSerializedIncrementerWasmWithInvalidCompiledData +
    2780             :           sizeof(kSerializedIncrementerWasmWithInvalidCompiledData));
    2781             :   Local<Value> value = DecodeTest(raw);
    2782             :   ASSERT_TRUE(value->IsWebAssemblyCompiledModule());
    2783             :   ExpectScriptTrue(
    2784             :       "new WebAssembly.Instance(result).exports.increment(8) === 9");
    2785             : }
    2786             : 
    2787             : // As above, but also with empty wire data. Should fail.
    2788             : const unsigned char kSerializedIncrementerWasmInvalid[] = {
    2789             :     0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x00, 0x00};
    2790             : 
    2791       15443 : TEST_F(ValueSerializerTestWithWasm,
    2792             :        DecodeWasmModuleWithInvalidCompiledAndWireData) {
    2793             :   std::vector<uint8_t> raw(kSerializedIncrementerWasmInvalid,
    2794             :                            kSerializedIncrementerWasmInvalid +
    2795             :                                sizeof(kSerializedIncrementerWasmInvalid));
    2796           1 :   InvalidDecodeTest(raw);
    2797           1 : }
    2798             : 
    2799       15443 : TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidDataLength) {
    2800           2 :   InvalidDecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x7F, 0x00});
    2801           2 :   InvalidDecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x00, 0x7F});
    2802           1 : }
    2803             : 
    2804           4 : class ValueSerializerTestWithLimitedMemory : public ValueSerializerTest {
    2805             :  protected:
    2806             : // GMock doesn't use the "override" keyword.
    2807             : #if __clang__
    2808             : #pragma clang diagnostic push
    2809             : #pragma clang diagnostic ignored "-Winconsistent-missing-override"
    2810             : #endif
    2811             : 
    2812             :   class SerializerDelegate : public ValueSerializer::Delegate {
    2813             :    public:
    2814             :     explicit SerializerDelegate(ValueSerializerTestWithLimitedMemory* test)
    2815           2 :         : test_(test) {}
    2816             : 
    2817           4 :     ~SerializerDelegate() { EXPECT_EQ(nullptr, last_buffer_); }
    2818             : 
    2819           3 :     void SetMemoryLimit(size_t limit) { memory_limit_ = limit; }
    2820             : 
    2821           6 :     void* ReallocateBufferMemory(void* old_buffer, size_t size,
    2822             :                                  size_t* actual_size) override {
    2823          12 :       EXPECT_EQ(old_buffer, last_buffer_);
    2824           6 :       if (size > memory_limit_) return nullptr;
    2825           4 :       *actual_size = size;
    2826           4 :       last_buffer_ = realloc(old_buffer, size);
    2827           4 :       return last_buffer_;
    2828             :     }
    2829             : 
    2830           3 :     void FreeBufferMemory(void* buffer) override {
    2831           6 :       EXPECT_EQ(buffer, last_buffer_);
    2832           3 :       last_buffer_ = nullptr;
    2833           3 :       free(buffer);
    2834           3 :     }
    2835             : 
    2836           2 :     void ThrowDataCloneError(Local<String> message) override {
    2837           4 :       test_->isolate()->ThrowException(Exception::Error(message));
    2838           2 :     }
    2839             : 
    2840           7 :     MOCK_METHOD2(WriteHostObject,
    2841             :                  Maybe<bool>(Isolate* isolate, Local<Object> object));
    2842             : 
    2843             :    private:
    2844             :     ValueSerializerTestWithLimitedMemory* test_;
    2845             :     void* last_buffer_ = nullptr;
    2846             :     size_t memory_limit_ = 0;
    2847             :   };
    2848             : 
    2849             : #if __clang__
    2850             : #pragma clang diagnostic pop
    2851             : #endif
    2852             : 
    2853           4 :   ValueSerializer::Delegate* GetSerializerDelegate() override {
    2854           4 :     return &serializer_delegate_;
    2855             :   }
    2856             : 
    2857           3 :   void BeforeEncode(ValueSerializer* serializer) override {
    2858           3 :     serializer_ = serializer;
    2859           3 :   }
    2860             : 
    2861             :   SerializerDelegate serializer_delegate_{this};
    2862             :   ValueSerializer* serializer_ = nullptr;
    2863             : };
    2864             : 
    2865       15443 : TEST_F(ValueSerializerTestWithLimitedMemory, FailIfNoMemoryInWriteHostObject) {
    2866           5 :   EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
    2867           3 :       .WillRepeatedly(Invoke([this](Isolate*, Local<Object>) {
    2868             :         static const char kDummyData[1024] = {};
    2869           3 :         serializer_->WriteRawBytes(&kDummyData, sizeof(kDummyData));
    2870             :         return Just(true);
    2871           2 :       }));
    2872             : 
    2873             :   // If there is enough memory, things work.
    2874             :   serializer_delegate_.SetMemoryLimit(2048);
    2875           2 :   EncodeTest("new ExampleHostObject()");
    2876             : 
    2877             :   // If not, we get a graceful failure, rather than silent misbehavior.
    2878             :   serializer_delegate_.SetMemoryLimit(1024);
    2879             :   InvalidEncodeTest("new ExampleHostObject()");
    2880             : 
    2881             :   // And we definitely don't continue to serialize other things.
    2882             :   serializer_delegate_.SetMemoryLimit(1024);
    2883           1 :   EvaluateScriptForInput("gotA = false");
    2884             :   InvalidEncodeTest("[new ExampleHostObject, {get a() { gotA = true; }}]");
    2885           3 :   EXPECT_TRUE(EvaluateScriptForInput("gotA")->IsFalse());
    2886           1 : }
    2887             : 
    2888             : }  // namespace
    2889        9264 : }  // namespace v8

Generated by: LCOV version 1.10