Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: test/unittests/value-serializer-unittest.cc

Issue 2327653002: Support delegating serialization of host objects. (Closed)
Patch Set: Isolate* argument to delegate Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« include/v8.h ('K') | « src/value-serializer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "src/api.h" 11 #include "src/api.h"
12 #include "src/base/build_config.h" 12 #include "src/base/build_config.h"
13 #include "test/unittests/test-utils.h" 13 #include "test/unittests/test-utils.h"
14 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
15 16
16 namespace v8 { 17 namespace v8 {
17 namespace { 18 namespace {
18 19
20 using ::testing::_;
21 using ::testing::Invoke;
22
19 class ValueSerializerTest : public TestWithIsolate { 23 class ValueSerializerTest : public TestWithIsolate {
20 protected: 24 protected:
21 ValueSerializerTest() 25 ValueSerializerTest()
22 : serialization_context_(Context::New(isolate())), 26 : serialization_context_(Context::New(isolate())),
23 deserialization_context_(Context::New(isolate())) {} 27 deserialization_context_(Context::New(isolate())) {
28 // Create a host object type that can be tested through
29 // serialization/deserialization delegates below.
30 Local<FunctionTemplate> function_template = v8::FunctionTemplate::New(
31 isolate(), [](const FunctionCallbackInfo<Value>& args) {
32 args.Holder()->SetInternalField(0, args[0]);
33 args.Holder()->SetInternalField(1, args[1]);
34 });
35 function_template->InstanceTemplate()->SetInternalFieldCount(2);
36 function_template->InstanceTemplate()->SetAccessor(
37 StringFromUtf8("value"),
38 [](Local<String> property, const PropertyCallbackInfo<Value>& args) {
39 args.GetReturnValue().Set(args.Holder()->GetInternalField(0));
40 });
41 function_template->InstanceTemplate()->SetAccessor(
42 StringFromUtf8("value2"),
43 [](Local<String> property, const PropertyCallbackInfo<Value>& args) {
44 args.GetReturnValue().Set(args.Holder()->GetInternalField(1));
45 });
46 for (Local<Context> context :
47 {serialization_context_, deserialization_context_}) {
48 context->Global()
49 ->CreateDataProperty(
50 context, StringFromUtf8("ExampleHostObject"),
51 function_template->GetFunction(context).ToLocalChecked())
52 .ToChecked();
53 }
54 host_object_constructor_template_ = function_template;
55 }
24 56
25 const Local<Context>& serialization_context() { 57 const Local<Context>& serialization_context() {
26 return serialization_context_; 58 return serialization_context_;
27 } 59 }
28 const Local<Context>& deserialization_context() { 60 const Local<Context>& deserialization_context() {
29 return deserialization_context_; 61 return deserialization_context_;
30 } 62 }
31 63
32 // Overridden in more specific fixtures. 64 // Overridden in more specific fixtures.
65 virtual ValueSerializer::Delegate* GetSerializerDelegate() { return nullptr; }
33 virtual void BeforeEncode(ValueSerializer*) {} 66 virtual void BeforeEncode(ValueSerializer*) {}
67 virtual ValueDeserializer::Delegate* GetDeserializerDelegate() {
68 return nullptr;
69 }
34 virtual void BeforeDecode(ValueDeserializer*) {} 70 virtual void BeforeDecode(ValueDeserializer*) {}
35 71
36 template <typename InputFunctor, typename OutputFunctor> 72 template <typename InputFunctor, typename OutputFunctor>
37 void RoundTripTest(const InputFunctor& input_functor, 73 void RoundTripTest(const InputFunctor& input_functor,
38 const OutputFunctor& output_functor) { 74 const OutputFunctor& output_functor) {
39 EncodeTest(input_functor, 75 EncodeTest(input_functor,
40 [this, &output_functor](const std::vector<uint8_t>& data) { 76 [this, &output_functor](const std::vector<uint8_t>& data) {
41 DecodeTest(data, output_functor); 77 DecodeTest(data, output_functor);
42 }); 78 });
43 } 79 }
44 80
45 // Variant for the common case where a script is used to build the original 81 // Variant for the common case where a script is used to build the original
46 // value. 82 // value.
47 template <typename OutputFunctor> 83 template <typename OutputFunctor>
48 void RoundTripTest(const char* source, const OutputFunctor& output_functor) { 84 void RoundTripTest(const char* source, const OutputFunctor& output_functor) {
49 RoundTripTest([this, source]() { return EvaluateScriptForInput(source); }, 85 RoundTripTest([this, source]() { return EvaluateScriptForInput(source); },
50 output_functor); 86 output_functor);
51 } 87 }
52 88
53 Maybe<std::vector<uint8_t>> DoEncode(Local<Value> value) { 89 Maybe<std::vector<uint8_t>> DoEncode(Local<Value> value) {
54 Local<Context> context = serialization_context(); 90 Local<Context> context = serialization_context();
55 ValueSerializer serializer(isolate()); 91 ValueSerializer serializer(isolate(), GetSerializerDelegate());
56 BeforeEncode(&serializer); 92 BeforeEncode(&serializer);
57 serializer.WriteHeader(); 93 serializer.WriteHeader();
58 if (!serializer.WriteValue(context, value).FromMaybe(false)) { 94 if (!serializer.WriteValue(context, value).FromMaybe(false)) {
59 return Nothing<std::vector<uint8_t>>(); 95 return Nothing<std::vector<uint8_t>>();
60 } 96 }
61 return Just(serializer.ReleaseBuffer()); 97 return Just(serializer.ReleaseBuffer());
62 } 98 }
63 99
64 template <typename InputFunctor, typename EncodedDataFunctor> 100 template <typename InputFunctor, typename EncodedDataFunctor>
65 void EncodeTest(const InputFunctor& input_functor, 101 void EncodeTest(const InputFunctor& input_functor,
(...skipping 20 matching lines...) Expand all
86 InvalidEncodeTest(source, [](Local<Message>) {}); 122 InvalidEncodeTest(source, [](Local<Message>) {});
87 } 123 }
88 124
89 template <typename OutputFunctor> 125 template <typename OutputFunctor>
90 void DecodeTest(const std::vector<uint8_t>& data, 126 void DecodeTest(const std::vector<uint8_t>& data,
91 const OutputFunctor& output_functor) { 127 const OutputFunctor& output_functor) {
92 Local<Context> context = deserialization_context(); 128 Local<Context> context = deserialization_context();
93 Context::Scope scope(context); 129 Context::Scope scope(context);
94 TryCatch try_catch(isolate()); 130 TryCatch try_catch(isolate());
95 ValueDeserializer deserializer(isolate(), &data[0], 131 ValueDeserializer deserializer(isolate(), &data[0],
96 static_cast<int>(data.size())); 132 static_cast<int>(data.size()),
133 GetDeserializerDelegate());
97 deserializer.SetSupportsLegacyWireFormat(true); 134 deserializer.SetSupportsLegacyWireFormat(true);
98 BeforeDecode(&deserializer); 135 BeforeDecode(&deserializer);
99 ASSERT_TRUE(deserializer.ReadHeader(context).FromMaybe(false)); 136 ASSERT_TRUE(deserializer.ReadHeader(context).FromMaybe(false));
100 Local<Value> result; 137 Local<Value> result;
101 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); 138 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result));
102 ASSERT_FALSE(result.IsEmpty()); 139 ASSERT_FALSE(result.IsEmpty());
103 ASSERT_FALSE(try_catch.HasCaught()); 140 ASSERT_FALSE(try_catch.HasCaught());
104 ASSERT_TRUE( 141 ASSERT_TRUE(
105 context->Global() 142 context->Global()
106 ->CreateDataProperty(context, StringFromUtf8("result"), result) 143 ->CreateDataProperty(context, StringFromUtf8("result"), result)
107 .FromMaybe(false)); 144 .FromMaybe(false));
108 output_functor(result); 145 output_functor(result);
109 ASSERT_FALSE(try_catch.HasCaught()); 146 ASSERT_FALSE(try_catch.HasCaught());
110 } 147 }
111 148
112 template <typename OutputFunctor> 149 template <typename OutputFunctor>
113 void DecodeTestForVersion0(const std::vector<uint8_t>& data, 150 void DecodeTestForVersion0(const std::vector<uint8_t>& data,
114 const OutputFunctor& output_functor) { 151 const OutputFunctor& output_functor) {
115 Local<Context> context = deserialization_context(); 152 Local<Context> context = deserialization_context();
116 Context::Scope scope(context); 153 Context::Scope scope(context);
117 TryCatch try_catch(isolate()); 154 TryCatch try_catch(isolate());
118 ValueDeserializer deserializer(isolate(), &data[0], 155 ValueDeserializer deserializer(isolate(), &data[0],
119 static_cast<int>(data.size())); 156 static_cast<int>(data.size()),
157 GetDeserializerDelegate());
120 deserializer.SetSupportsLegacyWireFormat(true); 158 deserializer.SetSupportsLegacyWireFormat(true);
121 BeforeDecode(&deserializer); 159 BeforeDecode(&deserializer);
122 ASSERT_TRUE(deserializer.ReadHeader(context).FromMaybe(false)); 160 ASSERT_TRUE(deserializer.ReadHeader(context).FromMaybe(false));
123 ASSERT_EQ(0, deserializer.GetWireFormatVersion()); 161 ASSERT_EQ(0, deserializer.GetWireFormatVersion());
124 Local<Value> result; 162 Local<Value> result;
125 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result)); 163 ASSERT_TRUE(deserializer.ReadValue(context).ToLocal(&result));
126 ASSERT_FALSE(result.IsEmpty()); 164 ASSERT_FALSE(result.IsEmpty());
127 ASSERT_FALSE(try_catch.HasCaught()); 165 ASSERT_FALSE(try_catch.HasCaught());
128 ASSERT_TRUE( 166 ASSERT_TRUE(
129 context->Global() 167 context->Global()
130 ->CreateDataProperty(context, StringFromUtf8("result"), result) 168 ->CreateDataProperty(context, StringFromUtf8("result"), result)
131 .FromMaybe(false)); 169 .FromMaybe(false));
132 output_functor(result); 170 output_functor(result);
133 ASSERT_FALSE(try_catch.HasCaught()); 171 ASSERT_FALSE(try_catch.HasCaught());
134 } 172 }
135 173
136 void InvalidDecodeTest(const std::vector<uint8_t>& data) { 174 void InvalidDecodeTest(const std::vector<uint8_t>& data) {
137 Local<Context> context = deserialization_context(); 175 Local<Context> context = deserialization_context();
138 Context::Scope scope(context); 176 Context::Scope scope(context);
139 TryCatch try_catch(isolate()); 177 TryCatch try_catch(isolate());
140 ValueDeserializer deserializer(isolate(), &data[0], 178 ValueDeserializer deserializer(isolate(), &data[0],
141 static_cast<int>(data.size())); 179 static_cast<int>(data.size()),
180 GetDeserializerDelegate());
142 deserializer.SetSupportsLegacyWireFormat(true); 181 deserializer.SetSupportsLegacyWireFormat(true);
143 BeforeDecode(&deserializer); 182 BeforeDecode(&deserializer);
144 Maybe<bool> header_result = deserializer.ReadHeader(context); 183 Maybe<bool> header_result = deserializer.ReadHeader(context);
145 if (header_result.IsNothing()) { 184 if (header_result.IsNothing()) {
146 EXPECT_TRUE(try_catch.HasCaught()); 185 EXPECT_TRUE(try_catch.HasCaught());
147 return; 186 return;
148 } 187 }
149 ASSERT_TRUE(header_result.ToChecked()); 188 ASSERT_TRUE(header_result.ToChecked());
150 ASSERT_TRUE(deserializer.ReadValue(context).IsEmpty()); 189 ASSERT_TRUE(deserializer.ReadValue(context).IsEmpty());
151 EXPECT_TRUE(try_catch.HasCaught()); 190 EXPECT_TRUE(try_catch.HasCaught());
(...skipping 17 matching lines...) Expand all
169 Local<String> StringFromUtf8(const char* source) { 208 Local<String> StringFromUtf8(const char* source) {
170 return String::NewFromUtf8(isolate(), source, NewStringType::kNormal) 209 return String::NewFromUtf8(isolate(), source, NewStringType::kNormal)
171 .ToLocalChecked(); 210 .ToLocalChecked();
172 } 211 }
173 212
174 static std::string Utf8Value(Local<Value> value) { 213 static std::string Utf8Value(Local<Value> value) {
175 String::Utf8Value utf8(value); 214 String::Utf8Value utf8(value);
176 return std::string(*utf8, utf8.length()); 215 return std::string(*utf8, utf8.length());
177 } 216 }
178 217
218 Local<Object> NewHostObject(Local<Context> context, int argc,
219 Local<Value> argv[]) {
220 return host_object_constructor_template_->GetFunction(context)
221 .ToLocalChecked()
222 ->NewInstance(context, argc, argv)
223 .ToLocalChecked();
224 }
225
179 private: 226 private:
180 Local<Context> serialization_context_; 227 Local<Context> serialization_context_;
181 Local<Context> deserialization_context_; 228 Local<Context> deserialization_context_;
229 Local<FunctionTemplate> host_object_constructor_template_;
182 230
183 DISALLOW_COPY_AND_ASSIGN(ValueSerializerTest); 231 DISALLOW_COPY_AND_ASSIGN(ValueSerializerTest);
184 }; 232 };
185 233
186 TEST_F(ValueSerializerTest, DecodeInvalid) { 234 TEST_F(ValueSerializerTest, DecodeInvalid) {
187 // Version tag but no content. 235 // Version tag but no content.
188 InvalidDecodeTest({0xff}); 236 InvalidDecodeTest({0xff});
189 // Version too large. 237 // Version too large.
190 InvalidDecodeTest({0xff, 0x7f, 0x5f}); 238 InvalidDecodeTest({0xff, 0x7f, 0x5f});
191 // Nonsense tag. 239 // Nonsense tag.
(...skipping 1825 matching lines...) Expand 10 before | Expand all | Expand 10 after
2017 "new Uint8Array(result.a).toString() === '0,1,128,255'")); 2065 "new Uint8Array(result.a).toString() === '0,1,128,255'"));
2018 }); 2066 });
2019 } 2067 }
2020 2068
2021 TEST_F(ValueSerializerTestWithSharedArrayBufferTransfer, 2069 TEST_F(ValueSerializerTestWithSharedArrayBufferTransfer,
2022 SharedArrayBufferMustBeTransferred) { 2070 SharedArrayBufferMustBeTransferred) {
2023 // A SharedArrayBuffer which was not marked for transfer should fail encoding. 2071 // A SharedArrayBuffer which was not marked for transfer should fail encoding.
2024 InvalidEncodeTest("new SharedArrayBuffer(32)"); 2072 InvalidEncodeTest("new SharedArrayBuffer(32)");
2025 } 2073 }
2026 2074
2075 TEST_F(ValueSerializerTest, UnsupportedHostObject) {
2076 InvalidEncodeTest("new ExampleHostObject()");
2077 InvalidEncodeTest("({ a: new ExampleHostObject() })");
2078 }
2079
2080 class ValueSerializerTestWithHostObject : public ValueSerializerTest {
2081 protected:
2082 ValueSerializerTestWithHostObject() : serializer_delegate_(this) {}
2083
2084 static const uint8_t kExampleHostObjectTag;
2085
2086 void WriteExampleHostObjectTag() {
2087 serializer_->WriteRawBytes(&kExampleHostObjectTag, 1);
2088 }
2089
2090 bool ReadExampleHostObjectTag() {
2091 const void* tag;
2092 return deserializer_->ReadRawBytes(1, &tag) &&
2093 *reinterpret_cast<const uint8_t*>(tag) == kExampleHostObjectTag;
2094 }
2095
2096 // GMock doesn't use the "override" keyword.
2097 #if __clang__
2098 #pragma clang diagnostic push
2099 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2100 #endif
2101
2102 class SerializerDelegate : public ValueSerializer::Delegate {
2103 public:
2104 explicit SerializerDelegate(ValueSerializerTestWithHostObject* test)
2105 : test_(test) {}
2106 MOCK_METHOD2(WriteHostObject,
2107 Maybe<bool>(Isolate* isolate, Local<Object> object));
2108 void ThrowDataCloneError(Local<String> message) override {
2109 test_->isolate()->ThrowException(Exception::Error(message));
2110 }
2111
2112 private:
2113 ValueSerializerTestWithHostObject* test_;
2114 };
2115
2116 class DeserializerDelegate : public ValueDeserializer::Delegate {
2117 public:
2118 MOCK_METHOD1(ReadHostObject, MaybeLocal<Object>(Isolate* isolate));
2119 };
2120
2121 #if __clang__
2122 #pragma clang diagnostic pop
2123 #endif
2124
2125 ValueSerializer::Delegate* GetSerializerDelegate() override {
2126 return &serializer_delegate_;
2127 }
2128 void BeforeEncode(ValueSerializer* serializer) override {
2129 serializer_ = serializer;
2130 }
2131 ValueDeserializer::Delegate* GetDeserializerDelegate() override {
2132 return &deserializer_delegate_;
2133 }
2134 void BeforeDecode(ValueDeserializer* deserializer) override {
2135 deserializer_ = deserializer;
2136 }
2137
2138 SerializerDelegate serializer_delegate_;
2139 DeserializerDelegate deserializer_delegate_;
2140 ValueSerializer* serializer_;
2141 ValueDeserializer* deserializer_;
2142
2143 friend class SerializerDelegate;
2144 friend class DeserializerDelegate;
2145 };
2146
2147 // This is a tag that's not used in V8.
2148 const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = '+';
2149
2150 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) {
2151 // The host can serialize data as uint32_t.
2152 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
2153 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) {
2154 uint32_t value = 0;
2155 EXPECT_TRUE(object->GetInternalField(0)
2156 ->Uint32Value(serialization_context())
2157 .To(&value));
2158 WriteExampleHostObjectTag();
2159 serializer_->WriteUint32(value);
2160 return Just(true);
2161 }));
2162 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
2163 .WillRepeatedly(Invoke([this](Isolate*) {
2164 EXPECT_TRUE(ReadExampleHostObjectTag());
2165 uint32_t value = 0;
2166 EXPECT_TRUE(deserializer_->ReadUint32(&value));
2167 Local<Value> argv[] = {Integer::NewFromUnsigned(isolate(), value)};
2168 return NewHostObject(deserialization_context(), arraysize(argv), argv);
2169 }));
2170 RoundTripTest("new ExampleHostObject(42)", [this](Local<Value> value) {
2171 ASSERT_TRUE(value->IsObject());
2172 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
2173 EXPECT_TRUE(EvaluateScriptForResultBool(
2174 "Object.getPrototypeOf(result) === ExampleHostObject.prototype"));
2175 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42"));
2176 });
2177 RoundTripTest(
2178 "new ExampleHostObject(0xCAFECAFE)", [this](Local<Value> value) {
2179 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xCAFECAFE"));
2180 });
2181 }
2182
2183 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint64) {
2184 // The host can serialize data as uint64_t.
2185 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
2186 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) {
2187 uint32_t value = 0, value2 = 0;
2188 EXPECT_TRUE(object->GetInternalField(0)
2189 ->Uint32Value(serialization_context())
2190 .To(&value));
2191 EXPECT_TRUE(object->GetInternalField(1)
2192 ->Uint32Value(serialization_context())
2193 .To(&value2));
2194 WriteExampleHostObjectTag();
2195 serializer_->WriteUint64((static_cast<uint64_t>(value) << 32) | value2);
2196 return Just(true);
2197 }));
2198 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
2199 .WillRepeatedly(Invoke([this](Isolate*) {
2200 EXPECT_TRUE(ReadExampleHostObjectTag());
2201 uint64_t value_packed;
2202 EXPECT_TRUE(deserializer_->ReadUint64(&value_packed));
2203 Local<Value> argv[] = {
2204 Integer::NewFromUnsigned(isolate(),
2205 static_cast<uint32_t>(value_packed >> 32)),
2206 Integer::NewFromUnsigned(isolate(),
2207 static_cast<uint32_t>(value_packed))};
2208 return NewHostObject(deserialization_context(), arraysize(argv), argv);
2209 }));
2210 RoundTripTest("new ExampleHostObject(42, 0)", [this](Local<Value> value) {
2211 ASSERT_TRUE(value->IsObject());
2212 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
2213 EXPECT_TRUE(EvaluateScriptForResultBool(
2214 "Object.getPrototypeOf(result) === ExampleHostObject.prototype"));
2215 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42"));
2216 EXPECT_TRUE(EvaluateScriptForResultBool("result.value2 === 0"));
2217 });
2218 RoundTripTest(
2219 "new ExampleHostObject(0xFFFFFFFF, 0x12345678)",
2220 [this](Local<Value> value) {
2221 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xFFFFFFFF"));
2222 EXPECT_TRUE(
2223 EvaluateScriptForResultBool("result.value2 === 0x12345678"));
2224 });
2225 }
2226
2227 TEST_F(ValueSerializerTestWithHostObject, RoundTripRawBytes) {
2228 // The host can serialize arbitrary raw bytes.
2229 const struct {
2230 uint64_t u64;
2231 uint32_t u32;
2232 char str[12];
2233 } sample_data = {0x1234567812345678, 0x87654321, "Hello world"};
2234 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
2235 .WillRepeatedly(
2236 Invoke([this, &sample_data](Isolate*, Local<Object> object) {
2237 WriteExampleHostObjectTag();
2238 serializer_->WriteRawBytes(&sample_data, sizeof(sample_data));
2239 return Just(true);
2240 }));
2241 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
2242 .WillRepeatedly(Invoke([this, &sample_data](Isolate*) {
2243 EXPECT_TRUE(ReadExampleHostObjectTag());
2244 const void* copied_data = nullptr;
2245 EXPECT_TRUE(
2246 deserializer_->ReadRawBytes(sizeof(sample_data), &copied_data));
2247 if (copied_data) {
2248 EXPECT_EQ(0, memcmp(&sample_data, copied_data, sizeof(sample_data)));
2249 }
2250 return NewHostObject(deserialization_context(), 0, nullptr);
2251 }));
2252 RoundTripTest("new ExampleHostObject()", [this](Local<Value> value) {
2253 ASSERT_TRUE(value->IsObject());
2254 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount());
2255 EXPECT_TRUE(EvaluateScriptForResultBool(
2256 "Object.getPrototypeOf(result) === ExampleHostObject.prototype"));
2257 });
2258 }
2259
2260 TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) {
2261 // If the same object exists in two places, the delegate should be invoked
2262 // only once, and the objects should be the same (by reference equality) on
2263 // the other side.
2264 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
2265 .WillOnce(Invoke([this](Isolate*, Local<Object> object) {
2266 WriteExampleHostObjectTag();
2267 return Just(true);
2268 }));
2269 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
2270 .WillOnce(Invoke([this](Isolate*) {
2271 EXPECT_TRUE(ReadExampleHostObjectTag());
2272 return NewHostObject(deserialization_context(), 0, nullptr);
2273 }));
2274 RoundTripTest(
2275 "({ a: new ExampleHostObject(), get b() { return this.a; }})",
2276 [this](Local<Value> value) {
2277 EXPECT_TRUE(EvaluateScriptForResultBool(
2278 "result.a instanceof ExampleHostObject"));
2279 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b"));
2280 });
2281 }
2282
2027 } // namespace 2283 } // namespace
2028 } // namespace v8 2284 } // namespace v8
OLDNEW
« include/v8.h ('K') | « src/value-serializer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698