| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "include/v8.h" | 10 #include "include/v8.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 : serialization_context_(Context::New(isolate())), | 22 : serialization_context_(Context::New(isolate())), |
| 23 deserialization_context_(Context::New(isolate())) {} | 23 deserialization_context_(Context::New(isolate())) {} |
| 24 | 24 |
| 25 const Local<Context>& serialization_context() { | 25 const Local<Context>& serialization_context() { |
| 26 return serialization_context_; | 26 return serialization_context_; |
| 27 } | 27 } |
| 28 const Local<Context>& deserialization_context() { | 28 const Local<Context>& deserialization_context() { |
| 29 return deserialization_context_; | 29 return deserialization_context_; |
| 30 } | 30 } |
| 31 | 31 |
| 32 // Overridden in more specific fixtures. |
| 33 virtual void BeforeEncode(ValueSerializer*) {} |
| 34 virtual void BeforeDecode(ValueDeserializer*) {} |
| 35 |
| 32 template <typename InputFunctor, typename OutputFunctor> | 36 template <typename InputFunctor, typename OutputFunctor> |
| 33 void RoundTripTest(const InputFunctor& input_functor, | 37 void RoundTripTest(const InputFunctor& input_functor, |
| 34 const OutputFunctor& output_functor) { | 38 const OutputFunctor& output_functor) { |
| 35 EncodeTest(input_functor, | 39 EncodeTest(input_functor, |
| 36 [this, &output_functor](const std::vector<uint8_t>& data) { | 40 [this, &output_functor](const std::vector<uint8_t>& data) { |
| 37 DecodeTest(data, output_functor); | 41 DecodeTest(data, output_functor); |
| 38 }); | 42 }); |
| 39 } | 43 } |
| 40 | 44 |
| 41 // Variant for the common case where a script is used to build the original | 45 // Variant for the common case where a script is used to build the original |
| 42 // value. | 46 // value. |
| 43 template <typename OutputFunctor> | 47 template <typename OutputFunctor> |
| 44 void RoundTripTest(const char* source, const OutputFunctor& output_functor) { | 48 void RoundTripTest(const char* source, const OutputFunctor& output_functor) { |
| 45 RoundTripTest([this, source]() { return EvaluateScriptForInput(source); }, | 49 RoundTripTest([this, source]() { return EvaluateScriptForInput(source); }, |
| 46 output_functor); | 50 output_functor); |
| 47 } | 51 } |
| 48 | 52 |
| 49 Maybe<std::vector<uint8_t>> DoEncode(Local<Value> value) { | 53 Maybe<std::vector<uint8_t>> DoEncode(Local<Value> value) { |
| 50 Local<Context> context = serialization_context(); | 54 Local<Context> context = serialization_context(); |
| 51 ValueSerializer serializer(isolate()); | 55 ValueSerializer serializer(isolate()); |
| 56 BeforeEncode(&serializer); |
| 52 serializer.WriteHeader(); | 57 serializer.WriteHeader(); |
| 53 if (!serializer.WriteValue(context, value).FromMaybe(false)) { | 58 if (!serializer.WriteValue(context, value).FromMaybe(false)) { |
| 54 return Nothing<std::vector<uint8_t>>(); | 59 return Nothing<std::vector<uint8_t>>(); |
| 55 } | 60 } |
| 56 return Just(serializer.ReleaseBuffer()); | 61 return Just(serializer.ReleaseBuffer()); |
| 57 } | 62 } |
| 58 | 63 |
| 59 template <typename InputFunctor, typename EncodedDataFunctor> | 64 template <typename InputFunctor, typename EncodedDataFunctor> |
| 60 void EncodeTest(const InputFunctor& input_functor, | 65 void EncodeTest(const InputFunctor& input_functor, |
| 61 const EncodedDataFunctor& encoded_data_functor) { | 66 const EncodedDataFunctor& encoded_data_functor) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 83 | 88 |
| 84 template <typename OutputFunctor> | 89 template <typename OutputFunctor> |
| 85 void DecodeTest(const std::vector<uint8_t>& data, | 90 void DecodeTest(const std::vector<uint8_t>& data, |
| 86 const OutputFunctor& output_functor) { | 91 const OutputFunctor& output_functor) { |
| 87 Local<Context> context = deserialization_context(); | 92 Local<Context> context = deserialization_context(); |
| 88 Context::Scope scope(context); | 93 Context::Scope scope(context); |
| 89 TryCatch try_catch(isolate()); | 94 TryCatch try_catch(isolate()); |
| 90 ValueDeserializer deserializer(isolate(), &data[0], | 95 ValueDeserializer deserializer(isolate(), &data[0], |
| 91 static_cast<int>(data.size())); | 96 static_cast<int>(data.size())); |
| 92 deserializer.SetSupportsLegacyWireFormat(true); | 97 deserializer.SetSupportsLegacyWireFormat(true); |
| 98 BeforeDecode(&deserializer); |
| 93 ASSERT_TRUE(deserializer.ReadHeader().FromMaybe(false)); | 99 ASSERT_TRUE(deserializer.ReadHeader().FromMaybe(false)); |
| 94 Local<Value> result; | 100 Local<Value> result; |
| 95 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); | 101 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); |
| 96 ASSERT_FALSE(result.IsEmpty()); | 102 ASSERT_FALSE(result.IsEmpty()); |
| 97 ASSERT_FALSE(try_catch.HasCaught()); | 103 ASSERT_FALSE(try_catch.HasCaught()); |
| 98 ASSERT_TRUE( | 104 ASSERT_TRUE( |
| 99 context->Global() | 105 context->Global() |
| 100 ->CreateDataProperty(context, StringFromUtf8("result"), result) | 106 ->CreateDataProperty(context, StringFromUtf8("result"), result) |
| 101 .FromMaybe(false)); | 107 .FromMaybe(false)); |
| 102 output_functor(result); | 108 output_functor(result); |
| 103 ASSERT_FALSE(try_catch.HasCaught()); | 109 ASSERT_FALSE(try_catch.HasCaught()); |
| 104 } | 110 } |
| 105 | 111 |
| 106 template <typename OutputFunctor> | 112 template <typename OutputFunctor> |
| 107 void DecodeTestForVersion0(const std::vector<uint8_t>& data, | 113 void DecodeTestForVersion0(const std::vector<uint8_t>& data, |
| 108 const OutputFunctor& output_functor) { | 114 const OutputFunctor& output_functor) { |
| 109 Local<Context> context = deserialization_context(); | 115 Local<Context> context = deserialization_context(); |
| 110 Context::Scope scope(context); | 116 Context::Scope scope(context); |
| 111 TryCatch try_catch(isolate()); | 117 TryCatch try_catch(isolate()); |
| 112 ValueDeserializer deserializer(isolate(), &data[0], | 118 ValueDeserializer deserializer(isolate(), &data[0], |
| 113 static_cast<int>(data.size())); | 119 static_cast<int>(data.size())); |
| 114 deserializer.SetSupportsLegacyWireFormat(true); | 120 deserializer.SetSupportsLegacyWireFormat(true); |
| 121 BeforeDecode(&deserializer); |
| 115 ASSERT_TRUE(deserializer.ReadHeader().FromMaybe(false)); | 122 ASSERT_TRUE(deserializer.ReadHeader().FromMaybe(false)); |
| 116 ASSERT_EQ(0, deserializer.GetWireFormatVersion()); | 123 ASSERT_EQ(0, deserializer.GetWireFormatVersion()); |
| 117 Local<Value> result; | 124 Local<Value> result; |
| 118 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); | 125 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); |
| 119 ASSERT_FALSE(result.IsEmpty()); | 126 ASSERT_FALSE(result.IsEmpty()); |
| 120 ASSERT_FALSE(try_catch.HasCaught()); | 127 ASSERT_FALSE(try_catch.HasCaught()); |
| 121 ASSERT_TRUE( | 128 ASSERT_TRUE( |
| 122 context->Global() | 129 context->Global() |
| 123 ->CreateDataProperty(context, StringFromUtf8("result"), result) | 130 ->CreateDataProperty(context, StringFromUtf8("result"), result) |
| 124 .FromMaybe(false)); | 131 .FromMaybe(false)); |
| 125 output_functor(result); | 132 output_functor(result); |
| 126 ASSERT_FALSE(try_catch.HasCaught()); | 133 ASSERT_FALSE(try_catch.HasCaught()); |
| 127 } | 134 } |
| 128 | 135 |
| 129 void InvalidDecodeTest(const std::vector<uint8_t>& data) { | 136 void InvalidDecodeTest(const std::vector<uint8_t>& data) { |
| 130 Local<Context> context = deserialization_context(); | 137 Local<Context> context = deserialization_context(); |
| 131 Context::Scope scope(context); | 138 Context::Scope scope(context); |
| 132 TryCatch try_catch(isolate()); | 139 TryCatch try_catch(isolate()); |
| 133 ValueDeserializer deserializer(isolate(), &data[0], | 140 ValueDeserializer deserializer(isolate(), &data[0], |
| 134 static_cast<int>(data.size())); | 141 static_cast<int>(data.size())); |
| 135 deserializer.SetSupportsLegacyWireFormat(true); | 142 deserializer.SetSupportsLegacyWireFormat(true); |
| 143 BeforeDecode(&deserializer); |
| 136 Maybe<bool> header_result = deserializer.ReadHeader(); | 144 Maybe<bool> header_result = deserializer.ReadHeader(); |
| 137 if (header_result.IsNothing()) return; | 145 if (header_result.IsNothing()) return; |
| 138 ASSERT_TRUE(header_result.ToChecked()); | 146 ASSERT_TRUE(header_result.ToChecked()); |
| 139 ASSERT_TRUE(deserializer.ReadValue(context).IsEmpty()); | 147 ASSERT_TRUE(deserializer.ReadValue(context).IsEmpty()); |
| 140 } | 148 } |
| 141 | 149 |
| 142 Local<Value> EvaluateScriptForInput(const char* utf8_source) { | 150 Local<Value> EvaluateScriptForInput(const char* utf8_source) { |
| 143 Local<String> source = StringFromUtf8(utf8_source); | 151 Local<String> source = StringFromUtf8(utf8_source); |
| 144 Local<Script> script = | 152 Local<Script> script = |
| 145 Script::Compile(serialization_context_, source).ToLocalChecked(); | 153 Script::Compile(serialization_context_, source).ToLocalChecked(); |
| (...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 EXPECT_TRUE( | 1598 EXPECT_TRUE( |
| 1591 EvaluateScriptForResultBool("result.a instanceof ArrayBuffer")); | 1599 EvaluateScriptForResultBool("result.a instanceof ArrayBuffer")); |
| 1592 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b")); | 1600 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b")); |
| 1593 }); | 1601 }); |
| 1594 } | 1602 } |
| 1595 | 1603 |
| 1596 TEST_F(ValueSerializerTest, DecodeInvalidArrayBuffer) { | 1604 TEST_F(ValueSerializerTest, DecodeInvalidArrayBuffer) { |
| 1597 InvalidDecodeTest({0xff, 0x09, 0x42, 0xff, 0xff, 0x00}); | 1605 InvalidDecodeTest({0xff, 0x09, 0x42, 0xff, 0xff, 0x00}); |
| 1598 } | 1606 } |
| 1599 | 1607 |
| 1608 // Includes an ArrayBuffer wrapper marked for transfer from the serialization |
| 1609 // context to the deserialization context. |
| 1610 class ValueSerializerTestWithArrayBufferTransfer : public ValueSerializerTest { |
| 1611 protected: |
| 1612 static const size_t kTestByteLength = 4; |
| 1613 |
| 1614 ValueSerializerTestWithArrayBufferTransfer() { |
| 1615 { |
| 1616 Context::Scope scope(serialization_context()); |
| 1617 input_buffer_ = ArrayBuffer::New(isolate(), nullptr, 0); |
| 1618 input_buffer_->Neuter(); |
| 1619 } |
| 1620 { |
| 1621 Context::Scope scope(deserialization_context()); |
| 1622 output_buffer_ = ArrayBuffer::New(isolate(), kTestByteLength); |
| 1623 const uint8_t data[kTestByteLength] = {0x00, 0x01, 0x80, 0xff}; |
| 1624 memcpy(output_buffer_->GetContents().Data(), data, kTestByteLength); |
| 1625 } |
| 1626 } |
| 1627 |
| 1628 const Local<ArrayBuffer>& input_buffer() { return input_buffer_; } |
| 1629 const Local<ArrayBuffer>& output_buffer() { return output_buffer_; } |
| 1630 |
| 1631 void BeforeEncode(ValueSerializer* serializer) override { |
| 1632 serializer->TransferArrayBuffer(0, input_buffer_); |
| 1633 } |
| 1634 |
| 1635 void BeforeDecode(ValueDeserializer* deserializer) override { |
| 1636 deserializer->TransferArrayBuffer(0, output_buffer_); |
| 1637 } |
| 1638 |
| 1639 private: |
| 1640 Local<ArrayBuffer> input_buffer_; |
| 1641 Local<ArrayBuffer> output_buffer_; |
| 1642 }; |
| 1643 |
| 1644 TEST_F(ValueSerializerTestWithArrayBufferTransfer, |
| 1645 RoundTripArrayBufferTransfer) { |
| 1646 RoundTripTest([this]() { return input_buffer(); }, |
| 1647 [this](Local<Value> value) { |
| 1648 ASSERT_TRUE(value->IsArrayBuffer()); |
| 1649 EXPECT_EQ(output_buffer(), value); |
| 1650 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1651 "new Uint8Array(result).toString() === '0,1,128,255'")); |
| 1652 }); |
| 1653 RoundTripTest( |
| 1654 [this]() { |
| 1655 Local<Object> object = Object::New(isolate()); |
| 1656 EXPECT_TRUE(object |
| 1657 ->CreateDataProperty(serialization_context(), |
| 1658 StringFromUtf8("a"), |
| 1659 input_buffer()) |
| 1660 .FromMaybe(false)); |
| 1661 EXPECT_TRUE(object |
| 1662 ->CreateDataProperty(serialization_context(), |
| 1663 StringFromUtf8("b"), |
| 1664 input_buffer()) |
| 1665 .FromMaybe(false)); |
| 1666 return object; |
| 1667 }, |
| 1668 [this](Local<Value> value) { |
| 1669 EXPECT_TRUE( |
| 1670 EvaluateScriptForResultBool("result.a instanceof ArrayBuffer")); |
| 1671 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b")); |
| 1672 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1673 "new Uint8Array(result.a).toString() === '0,1,128,255'")); |
| 1674 }); |
| 1675 } |
| 1676 |
| 1600 } // namespace | 1677 } // namespace |
| 1601 } // namespace v8 | 1678 } // namespace v8 |
| OLD | NEW |