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 29 matching lines...) Expand all Loading... | |
40 | 40 |
41 template <typename InputFunctor, typename EncodedDataFunctor> | 41 template <typename InputFunctor, typename EncodedDataFunctor> |
42 void EncodeTest(const InputFunctor& input_functor, | 42 void EncodeTest(const InputFunctor& input_functor, |
43 const EncodedDataFunctor& encoded_data_functor) { | 43 const EncodedDataFunctor& encoded_data_functor) { |
44 Context::Scope scope(serialization_context()); | 44 Context::Scope scope(serialization_context()); |
45 TryCatch try_catch(isolate()); | 45 TryCatch try_catch(isolate()); |
46 // TODO(jbroman): Use the public API once it exists. | 46 // TODO(jbroman): Use the public API once it exists. |
47 Local<Value> input_value = input_functor(); | 47 Local<Value> input_value = input_functor(); |
48 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate()); | 48 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate()); |
49 i::HandleScope handle_scope(internal_isolate); | 49 i::HandleScope handle_scope(internal_isolate); |
50 i::ValueSerializer serializer; | 50 i::ValueSerializer serializer(internal_isolate); |
51 serializer.WriteHeader(); | 51 serializer.WriteHeader(); |
52 ASSERT_TRUE(serializer.WriteObject(Utils::OpenHandle(*input_value)) | 52 ASSERT_TRUE(serializer.WriteObject(Utils::OpenHandle(*input_value)) |
53 .FromMaybe(false)); | 53 .FromMaybe(false)); |
54 ASSERT_FALSE(try_catch.HasCaught()); | 54 ASSERT_FALSE(try_catch.HasCaught()); |
55 encoded_data_functor(serializer.ReleaseBuffer()); | 55 encoded_data_functor(serializer.ReleaseBuffer()); |
56 } | 56 } |
57 | 57 |
58 template <typename OutputFunctor> | 58 template <typename OutputFunctor> |
59 void DecodeTest(const std::vector<uint8_t>& data, | 59 void DecodeTest(const std::vector<uint8_t>& data, |
60 const OutputFunctor& output_functor) { | 60 const OutputFunctor& output_functor) { |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 [](const std::vector<uint8_t>& data) { | 381 [](const std::vector<uint8_t>& data) { |
382 // This is a sufficient but not necessary condition to be aligned. | 382 // This is a sufficient but not necessary condition to be aligned. |
383 // Note that the third byte (0x00) is padding. | 383 // Note that the third byte (0x00) is padding. |
384 const uint8_t expected_prefix[] = {0xff, 0x09, 0x00, 0x63, 0x94, 0x03}; | 384 const uint8_t expected_prefix[] = {0xff, 0x09, 0x00, 0x63, 0x94, 0x03}; |
385 ASSERT_GT(data.size(), sizeof(expected_prefix) / sizeof(uint8_t)); | 385 ASSERT_GT(data.size(), sizeof(expected_prefix) / sizeof(uint8_t)); |
386 EXPECT_TRUE(std::equal(std::begin(expected_prefix), | 386 EXPECT_TRUE(std::equal(std::begin(expected_prefix), |
387 std::end(expected_prefix), data.begin())); | 387 std::end(expected_prefix), data.begin())); |
388 }); | 388 }); |
389 } | 389 } |
390 | 390 |
391 TEST_F(ValueSerializerTest, RoundTripDictionaryObject) { | |
392 // Empty object. | |
393 RoundTripTest([this]() { return EvaluateScriptForInput("({})"); }, | |
394 [this](Local<Value> value) { | |
395 ASSERT_TRUE(value->IsObject()); | |
396 EXPECT_TRUE(EvaluateScriptForResultBool( | |
397 "Object.getPrototypeOf(result) === Object.prototype")); | |
398 EXPECT_TRUE(EvaluateScriptForResultBool( | |
399 "Object.getOwnPropertyNames(result).length === 0")); | |
400 }); | |
401 // String key. | |
402 RoundTripTest( | |
403 [this]() { return EvaluateScriptForInput("({ a: 42 })"); }, | |
404 [this](Local<Value> value) { | |
405 ASSERT_TRUE(value->IsObject()); | |
406 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty('a')")); | |
407 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === 42")); | |
408 EXPECT_TRUE(EvaluateScriptForResultBool( | |
409 "Object.getOwnPropertyNames(result).length === 1")); | |
410 }); | |
411 // Integer key (treated as a string, but may be encoded differently). | |
Camillo Bruni
2016/08/16 11:26:57
nit: can you add a copy of this test with the corn
jbroman
2016/08/16 18:16:29
I've incorporated such an example. It took me awhi
| |
412 RoundTripTest( | |
413 [this]() { return EvaluateScriptForInput("({ 42: 'a' })"); }, | |
414 [this](Local<Value> value) { | |
415 ASSERT_TRUE(value->IsObject()); | |
416 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty('42')")); | |
417 EXPECT_TRUE(EvaluateScriptForResultBool("result[42] === 'a'")); | |
418 EXPECT_TRUE(EvaluateScriptForResultBool( | |
419 "Object.getOwnPropertyNames(result).length === 1")); | |
420 }); | |
421 // Key order must be preserved. | |
422 RoundTripTest( | |
423 [this]() { return EvaluateScriptForInput("({ x: 1, y: 2, a: 3 })"); }, | |
424 [this](Local<Value> value) { | |
425 EXPECT_TRUE(EvaluateScriptForResultBool( | |
426 "Object.getOwnPropertyNames(result).toString() === 'x,y,a'")); | |
427 }); | |
428 // This detects a fairly subtle case: the object itself must be in the map | |
429 // before its properties are deserialized, so that references to it can be | |
430 // resolved. | |
431 RoundTripTest( | |
432 [this]() { | |
433 return EvaluateScriptForInput( | |
434 "(() => { var y = {}; y.self = y; return y; })()"); | |
435 }, | |
436 [this](Local<Value> value) { | |
437 ASSERT_TRUE(value->IsObject()); | |
438 EXPECT_TRUE(EvaluateScriptForResultBool("result === result.self")); | |
439 }); | |
Camillo Bruni
2016/08/16 11:26:57
future-nit: once you can handle accessors and cust
jbroman
2016/08/16 18:16:29
I can handle them now, aside from a bug which you
| |
440 } | |
441 | |
442 TEST_F(ValueSerializerTest, DecodeDictionaryObject) { | |
443 // Empty object. | |
444 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x6f, 0x7b, 0x00, 0x00}, | |
445 [this](Local<Value> value) { | |
446 ASSERT_TRUE(value->IsObject()); | |
447 EXPECT_TRUE(EvaluateScriptForResultBool( | |
448 "Object.getPrototypeOf(result) === Object.prototype")); | |
449 EXPECT_TRUE(EvaluateScriptForResultBool( | |
450 "Object.getOwnPropertyNames(result).length === 0")); | |
451 }); | |
452 // String key. | |
453 DecodeTest( | |
454 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x53, 0x01, 0x61, 0x3f, 0x01, | |
455 0x49, 0x54, 0x7b, 0x01}, | |
456 [this](Local<Value> value) { | |
457 ASSERT_TRUE(value->IsObject()); | |
458 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty('a')")); | |
459 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === 42")); | |
460 EXPECT_TRUE(EvaluateScriptForResultBool( | |
461 "Object.getOwnPropertyNames(result).length === 1")); | |
462 }); | |
463 // Integer key (treated as a string, but may be encoded differently). | |
464 DecodeTest( | |
465 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x49, 0x54, 0x3f, 0x01, 0x53, | |
466 0x01, 0x61, 0x7b, 0x01}, | |
467 [this](Local<Value> value) { | |
468 ASSERT_TRUE(value->IsObject()); | |
469 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty('42')")); | |
470 EXPECT_TRUE(EvaluateScriptForResultBool("result[42] === 'a'")); | |
471 EXPECT_TRUE(EvaluateScriptForResultBool( | |
472 "Object.getOwnPropertyNames(result).length === 1")); | |
473 }); | |
474 // Key order must be preserved. | |
475 DecodeTest( | |
476 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x53, 0x01, 0x78, 0x3f, 0x01, | |
477 0x49, 0x02, 0x3f, 0x01, 0x53, 0x01, 0x79, 0x3f, 0x01, 0x49, 0x04, 0x3f, | |
478 0x01, 0x53, 0x01, 0x61, 0x3f, 0x01, 0x49, 0x06, 0x7b, 0x03}, | |
479 [this](Local<Value> value) { | |
480 EXPECT_TRUE(EvaluateScriptForResultBool( | |
481 "Object.getOwnPropertyNames(result).toString() === 'x,y,a'")); | |
482 }); | |
483 // This detects a fairly subtle case: the object itself must be in the map | |
484 // before its properties are deserialized, so that references to it can be | |
485 // resolved. | |
486 DecodeTest( | |
487 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x53, 0x04, 0x73, | |
488 0x65, 0x6c, 0x66, 0x3f, 0x01, 0x5e, 0x00, 0x7b, 0x01, 0x00}, | |
489 [this](Local<Value> value) { | |
490 ASSERT_TRUE(value->IsObject()); | |
491 EXPECT_TRUE(EvaluateScriptForResultBool("result === result.self")); | |
492 }); | |
493 } | |
494 | |
391 } // namespace | 495 } // namespace |
392 } // namespace v8 | 496 } // namespace v8 |
OLD | NEW |