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