| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "include/v8.h" | 10 #include "include/v8.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 class ValueSerializerTest : public TestWithIsolate { | 25 class ValueSerializerTest : public TestWithIsolate { |
| 26 protected: | 26 protected: |
| 27 ValueSerializerTest() | 27 ValueSerializerTest() |
| 28 : serialization_context_(Context::New(isolate())), | 28 : serialization_context_(Context::New(isolate())), |
| 29 deserialization_context_(Context::New(isolate())) { | 29 deserialization_context_(Context::New(isolate())) { |
| 30 // Create a host object type that can be tested through | 30 // Create a host object type that can be tested through |
| 31 // serialization/deserialization delegates below. | 31 // serialization/deserialization delegates below. |
| 32 Local<FunctionTemplate> function_template = v8::FunctionTemplate::New( | 32 Local<FunctionTemplate> function_template = v8::FunctionTemplate::New( |
| 33 isolate(), [](const FunctionCallbackInfo<Value>& args) { | 33 isolate(), [](const FunctionCallbackInfo<Value>& args) { |
| 34 args.Holder()->SetInternalField(0, args[0]); | 34 args.Holder()->SetEmbedderField(0, args[0]); |
| 35 args.Holder()->SetInternalField(1, args[1]); | 35 args.Holder()->SetEmbedderField(1, args[1]); |
| 36 }); | 36 }); |
| 37 function_template->InstanceTemplate()->SetInternalFieldCount(2); | 37 function_template->InstanceTemplate()->SetEmbedderFieldCount(2); |
| 38 function_template->InstanceTemplate()->SetAccessor( | 38 function_template->InstanceTemplate()->SetAccessor( |
| 39 StringFromUtf8("value"), | 39 StringFromUtf8("value"), |
| 40 [](Local<String> property, const PropertyCallbackInfo<Value>& args) { | 40 [](Local<String> property, const PropertyCallbackInfo<Value>& args) { |
| 41 args.GetReturnValue().Set(args.Holder()->GetInternalField(0)); | 41 args.GetReturnValue().Set(args.Holder()->GetEmbedderField(0)); |
| 42 }); | 42 }); |
| 43 function_template->InstanceTemplate()->SetAccessor( | 43 function_template->InstanceTemplate()->SetAccessor( |
| 44 StringFromUtf8("value2"), | 44 StringFromUtf8("value2"), |
| 45 [](Local<String> property, const PropertyCallbackInfo<Value>& args) { | 45 [](Local<String> property, const PropertyCallbackInfo<Value>& args) { |
| 46 args.GetReturnValue().Set(args.Holder()->GetInternalField(1)); | 46 args.GetReturnValue().Set(args.Holder()->GetEmbedderField(1)); |
| 47 }); | 47 }); |
| 48 for (Local<Context> context : | 48 for (Local<Context> context : |
| 49 {serialization_context_, deserialization_context_}) { | 49 {serialization_context_, deserialization_context_}) { |
| 50 context->Global() | 50 context->Global() |
| 51 ->CreateDataProperty( | 51 ->CreateDataProperty( |
| 52 context, StringFromUtf8("ExampleHostObject"), | 52 context, StringFromUtf8("ExampleHostObject"), |
| 53 function_template->GetFunction(context).ToLocalChecked()) | 53 function_template->GetFunction(context).ToLocalChecked()) |
| 54 .ToChecked(); | 54 .ToChecked(); |
| 55 } | 55 } |
| 56 host_object_constructor_template_ = function_template; | 56 host_object_constructor_template_ = function_template; |
| (...skipping 2315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 | 2372 |
| 2373 // This is a tag that is used in V8. Using this ensures that we have separate | 2373 // This is a tag that is used in V8. Using this ensures that we have separate |
| 2374 // tag namespaces. | 2374 // tag namespaces. |
| 2375 const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = 'T'; | 2375 const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = 'T'; |
| 2376 | 2376 |
| 2377 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) { | 2377 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) { |
| 2378 // The host can serialize data as uint32_t. | 2378 // The host can serialize data as uint32_t. |
| 2379 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) | 2379 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) |
| 2380 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { | 2380 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { |
| 2381 uint32_t value = 0; | 2381 uint32_t value = 0; |
| 2382 EXPECT_TRUE(object->GetInternalField(0) | 2382 EXPECT_TRUE(object->GetEmbedderField(0) |
| 2383 ->Uint32Value(serialization_context()) | 2383 ->Uint32Value(serialization_context()) |
| 2384 .To(&value)); | 2384 .To(&value)); |
| 2385 WriteExampleHostObjectTag(); | 2385 WriteExampleHostObjectTag(); |
| 2386 serializer_->WriteUint32(value); | 2386 serializer_->WriteUint32(value); |
| 2387 return Just(true); | 2387 return Just(true); |
| 2388 })); | 2388 })); |
| 2389 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) | 2389 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) |
| 2390 .WillRepeatedly(Invoke([this](Isolate*) { | 2390 .WillRepeatedly(Invoke([this](Isolate*) { |
| 2391 EXPECT_TRUE(ReadExampleHostObjectTag()); | 2391 EXPECT_TRUE(ReadExampleHostObjectTag()); |
| 2392 uint32_t value = 0; | 2392 uint32_t value = 0; |
| 2393 EXPECT_TRUE(deserializer_->ReadUint32(&value)); | 2393 EXPECT_TRUE(deserializer_->ReadUint32(&value)); |
| 2394 Local<Value> argv[] = {Integer::NewFromUnsigned(isolate(), value)}; | 2394 Local<Value> argv[] = {Integer::NewFromUnsigned(isolate(), value)}; |
| 2395 return NewHostObject(deserialization_context(), arraysize(argv), argv); | 2395 return NewHostObject(deserialization_context(), arraysize(argv), argv); |
| 2396 })); | 2396 })); |
| 2397 RoundTripTest("new ExampleHostObject(42)", [this](Local<Value> value) { | 2397 RoundTripTest("new ExampleHostObject(42)", [this](Local<Value> value) { |
| 2398 ASSERT_TRUE(value->IsObject()); | 2398 ASSERT_TRUE(value->IsObject()); |
| 2399 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount()); | 2399 ASSERT_TRUE(Object::Cast(*value)->EmbedderFieldCount()); |
| 2400 EXPECT_TRUE(EvaluateScriptForResultBool( | 2400 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 2401 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); | 2401 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); |
| 2402 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42")); | 2402 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42")); |
| 2403 }); | 2403 }); |
| 2404 RoundTripTest( | 2404 RoundTripTest( |
| 2405 "new ExampleHostObject(0xCAFECAFE)", [this](Local<Value> value) { | 2405 "new ExampleHostObject(0xCAFECAFE)", [this](Local<Value> value) { |
| 2406 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xCAFECAFE")); | 2406 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xCAFECAFE")); |
| 2407 }); | 2407 }); |
| 2408 } | 2408 } |
| 2409 | 2409 |
| 2410 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint64) { | 2410 TEST_F(ValueSerializerTestWithHostObject, RoundTripUint64) { |
| 2411 // The host can serialize data as uint64_t. | 2411 // The host can serialize data as uint64_t. |
| 2412 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) | 2412 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) |
| 2413 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { | 2413 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { |
| 2414 uint32_t value = 0, value2 = 0; | 2414 uint32_t value = 0, value2 = 0; |
| 2415 EXPECT_TRUE(object->GetInternalField(0) | 2415 EXPECT_TRUE(object->GetEmbedderField(0) |
| 2416 ->Uint32Value(serialization_context()) | 2416 ->Uint32Value(serialization_context()) |
| 2417 .To(&value)); | 2417 .To(&value)); |
| 2418 EXPECT_TRUE(object->GetInternalField(1) | 2418 EXPECT_TRUE(object->GetEmbedderField(1) |
| 2419 ->Uint32Value(serialization_context()) | 2419 ->Uint32Value(serialization_context()) |
| 2420 .To(&value2)); | 2420 .To(&value2)); |
| 2421 WriteExampleHostObjectTag(); | 2421 WriteExampleHostObjectTag(); |
| 2422 serializer_->WriteUint64((static_cast<uint64_t>(value) << 32) | value2); | 2422 serializer_->WriteUint64((static_cast<uint64_t>(value) << 32) | value2); |
| 2423 return Just(true); | 2423 return Just(true); |
| 2424 })); | 2424 })); |
| 2425 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) | 2425 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) |
| 2426 .WillRepeatedly(Invoke([this](Isolate*) { | 2426 .WillRepeatedly(Invoke([this](Isolate*) { |
| 2427 EXPECT_TRUE(ReadExampleHostObjectTag()); | 2427 EXPECT_TRUE(ReadExampleHostObjectTag()); |
| 2428 uint64_t value_packed; | 2428 uint64_t value_packed; |
| 2429 EXPECT_TRUE(deserializer_->ReadUint64(&value_packed)); | 2429 EXPECT_TRUE(deserializer_->ReadUint64(&value_packed)); |
| 2430 Local<Value> argv[] = { | 2430 Local<Value> argv[] = { |
| 2431 Integer::NewFromUnsigned(isolate(), | 2431 Integer::NewFromUnsigned(isolate(), |
| 2432 static_cast<uint32_t>(value_packed >> 32)), | 2432 static_cast<uint32_t>(value_packed >> 32)), |
| 2433 Integer::NewFromUnsigned(isolate(), | 2433 Integer::NewFromUnsigned(isolate(), |
| 2434 static_cast<uint32_t>(value_packed))}; | 2434 static_cast<uint32_t>(value_packed))}; |
| 2435 return NewHostObject(deserialization_context(), arraysize(argv), argv); | 2435 return NewHostObject(deserialization_context(), arraysize(argv), argv); |
| 2436 })); | 2436 })); |
| 2437 RoundTripTest("new ExampleHostObject(42, 0)", [this](Local<Value> value) { | 2437 RoundTripTest("new ExampleHostObject(42, 0)", [this](Local<Value> value) { |
| 2438 ASSERT_TRUE(value->IsObject()); | 2438 ASSERT_TRUE(value->IsObject()); |
| 2439 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount()); | 2439 ASSERT_TRUE(Object::Cast(*value)->EmbedderFieldCount()); |
| 2440 EXPECT_TRUE(EvaluateScriptForResultBool( | 2440 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 2441 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); | 2441 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); |
| 2442 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42")); | 2442 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 42")); |
| 2443 EXPECT_TRUE(EvaluateScriptForResultBool("result.value2 === 0")); | 2443 EXPECT_TRUE(EvaluateScriptForResultBool("result.value2 === 0")); |
| 2444 }); | 2444 }); |
| 2445 RoundTripTest( | 2445 RoundTripTest( |
| 2446 "new ExampleHostObject(0xFFFFFFFF, 0x12345678)", | 2446 "new ExampleHostObject(0xFFFFFFFF, 0x12345678)", |
| 2447 [this](Local<Value> value) { | 2447 [this](Local<Value> value) { |
| 2448 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xFFFFFFFF")); | 2448 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === 0xFFFFFFFF")); |
| 2449 EXPECT_TRUE( | 2449 EXPECT_TRUE( |
| 2450 EvaluateScriptForResultBool("result.value2 === 0x12345678")); | 2450 EvaluateScriptForResultBool("result.value2 === 0x12345678")); |
| 2451 }); | 2451 }); |
| 2452 } | 2452 } |
| 2453 | 2453 |
| 2454 TEST_F(ValueSerializerTestWithHostObject, RoundTripDouble) { | 2454 TEST_F(ValueSerializerTestWithHostObject, RoundTripDouble) { |
| 2455 // The host can serialize data as double. | 2455 // The host can serialize data as double. |
| 2456 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) | 2456 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) |
| 2457 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { | 2457 .WillRepeatedly(Invoke([this](Isolate*, Local<Object> object) { |
| 2458 double value = 0; | 2458 double value = 0; |
| 2459 EXPECT_TRUE(object->GetInternalField(0) | 2459 EXPECT_TRUE(object->GetEmbedderField(0) |
| 2460 ->NumberValue(serialization_context()) | 2460 ->NumberValue(serialization_context()) |
| 2461 .To(&value)); | 2461 .To(&value)); |
| 2462 WriteExampleHostObjectTag(); | 2462 WriteExampleHostObjectTag(); |
| 2463 serializer_->WriteDouble(value); | 2463 serializer_->WriteDouble(value); |
| 2464 return Just(true); | 2464 return Just(true); |
| 2465 })); | 2465 })); |
| 2466 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) | 2466 EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())) |
| 2467 .WillRepeatedly(Invoke([this](Isolate*) { | 2467 .WillRepeatedly(Invoke([this](Isolate*) { |
| 2468 EXPECT_TRUE(ReadExampleHostObjectTag()); | 2468 EXPECT_TRUE(ReadExampleHostObjectTag()); |
| 2469 double value = 0; | 2469 double value = 0; |
| 2470 EXPECT_TRUE(deserializer_->ReadDouble(&value)); | 2470 EXPECT_TRUE(deserializer_->ReadDouble(&value)); |
| 2471 Local<Value> argv[] = {Number::New(isolate(), value)}; | 2471 Local<Value> argv[] = {Number::New(isolate(), value)}; |
| 2472 return NewHostObject(deserialization_context(), arraysize(argv), argv); | 2472 return NewHostObject(deserialization_context(), arraysize(argv), argv); |
| 2473 })); | 2473 })); |
| 2474 RoundTripTest("new ExampleHostObject(-3.5)", [this](Local<Value> value) { | 2474 RoundTripTest("new ExampleHostObject(-3.5)", [this](Local<Value> value) { |
| 2475 ASSERT_TRUE(value->IsObject()); | 2475 ASSERT_TRUE(value->IsObject()); |
| 2476 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount()); | 2476 ASSERT_TRUE(Object::Cast(*value)->EmbedderFieldCount()); |
| 2477 EXPECT_TRUE(EvaluateScriptForResultBool( | 2477 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 2478 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); | 2478 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); |
| 2479 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === -3.5")); | 2479 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === -3.5")); |
| 2480 }); | 2480 }); |
| 2481 RoundTripTest("new ExampleHostObject(NaN)", [this](Local<Value> value) { | 2481 RoundTripTest("new ExampleHostObject(NaN)", [this](Local<Value> value) { |
| 2482 EXPECT_TRUE(EvaluateScriptForResultBool("Number.isNaN(result.value)")); | 2482 EXPECT_TRUE(EvaluateScriptForResultBool("Number.isNaN(result.value)")); |
| 2483 }); | 2483 }); |
| 2484 RoundTripTest("new ExampleHostObject(Infinity)", [this](Local<Value> value) { | 2484 RoundTripTest("new ExampleHostObject(Infinity)", [this](Local<Value> value) { |
| 2485 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === Infinity")); | 2485 EXPECT_TRUE(EvaluateScriptForResultBool("result.value === Infinity")); |
| 2486 }); | 2486 }); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2509 const void* copied_data = nullptr; | 2509 const void* copied_data = nullptr; |
| 2510 EXPECT_TRUE( | 2510 EXPECT_TRUE( |
| 2511 deserializer_->ReadRawBytes(sizeof(sample_data), &copied_data)); | 2511 deserializer_->ReadRawBytes(sizeof(sample_data), &copied_data)); |
| 2512 if (copied_data) { | 2512 if (copied_data) { |
| 2513 EXPECT_EQ(0, memcmp(&sample_data, copied_data, sizeof(sample_data))); | 2513 EXPECT_EQ(0, memcmp(&sample_data, copied_data, sizeof(sample_data))); |
| 2514 } | 2514 } |
| 2515 return NewHostObject(deserialization_context(), 0, nullptr); | 2515 return NewHostObject(deserialization_context(), 0, nullptr); |
| 2516 })); | 2516 })); |
| 2517 RoundTripTest("new ExampleHostObject()", [this](Local<Value> value) { | 2517 RoundTripTest("new ExampleHostObject()", [this](Local<Value> value) { |
| 2518 ASSERT_TRUE(value->IsObject()); | 2518 ASSERT_TRUE(value->IsObject()); |
| 2519 ASSERT_TRUE(Object::Cast(*value)->InternalFieldCount()); | 2519 ASSERT_TRUE(Object::Cast(*value)->EmbedderFieldCount()); |
| 2520 EXPECT_TRUE(EvaluateScriptForResultBool( | 2520 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 2521 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); | 2521 "Object.getPrototypeOf(result) === ExampleHostObject.prototype")); |
| 2522 }); | 2522 }); |
| 2523 } | 2523 } |
| 2524 | 2524 |
| 2525 TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) { | 2525 TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) { |
| 2526 // If the same object exists in two places, the delegate should be invoked | 2526 // If the same object exists in two places, the delegate should be invoked |
| 2527 // only once, and the objects should be the same (by reference equality) on | 2527 // only once, and the objects should be the same (by reference equality) on |
| 2528 // the other side. | 2528 // the other side. |
| 2529 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) | 2529 EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)) |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2744 InvalidDecodeTest(raw); | 2744 InvalidDecodeTest(raw); |
| 2745 } | 2745 } |
| 2746 | 2746 |
| 2747 TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidDataLength) { | 2747 TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidDataLength) { |
| 2748 InvalidDecodeTest({0xff, 0x09, 0x3f, 0x00, 0x57, 0x79, 0x7f, 0x00}); | 2748 InvalidDecodeTest({0xff, 0x09, 0x3f, 0x00, 0x57, 0x79, 0x7f, 0x00}); |
| 2749 InvalidDecodeTest({0xff, 0x09, 0x3f, 0x00, 0x57, 0x79, 0x00, 0x7f}); | 2749 InvalidDecodeTest({0xff, 0x09, 0x3f, 0x00, 0x57, 0x79, 0x00, 0x7f}); |
| 2750 } | 2750 } |
| 2751 | 2751 |
| 2752 } // namespace | 2752 } // namespace |
| 2753 } // namespace v8 | 2753 } // namespace v8 |
| OLD | NEW |