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 |