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 <type_traits> | 7 #include <type_traits> |
8 | 8 |
9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
10 #include "src/factory.h" | 10 #include "src/factory.h" |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 const uint8_t* peek_position = position_; | 333 const uint8_t* peek_position = position_; |
334 SerializationTag tag; | 334 SerializationTag tag; |
335 do { | 335 do { |
336 if (peek_position >= end_) return Nothing<SerializationTag>(); | 336 if (peek_position >= end_) return Nothing<SerializationTag>(); |
337 tag = static_cast<SerializationTag>(*peek_position); | 337 tag = static_cast<SerializationTag>(*peek_position); |
338 peek_position++; | 338 peek_position++; |
339 } while (tag == SerializationTag::kPadding); | 339 } while (tag == SerializationTag::kPadding); |
340 return Just(tag); | 340 return Just(tag); |
341 } | 341 } |
342 | 342 |
| 343 void ValueDeserializer::ConsumeTag(SerializationTag peeked_tag) { |
| 344 SerializationTag actual_tag = ReadTag().ToChecked(); |
| 345 DCHECK(actual_tag == peeked_tag); |
| 346 USE(actual_tag); |
| 347 } |
| 348 |
343 Maybe<SerializationTag> ValueDeserializer::ReadTag() { | 349 Maybe<SerializationTag> ValueDeserializer::ReadTag() { |
344 SerializationTag tag; | 350 SerializationTag tag; |
345 do { | 351 do { |
346 if (position_ >= end_) return Nothing<SerializationTag>(); | 352 if (position_ >= end_) return Nothing<SerializationTag>(); |
347 tag = static_cast<SerializationTag>(*position_); | 353 tag = static_cast<SerializationTag>(*position_); |
348 position_++; | 354 position_++; |
349 } while (tag == SerializationTag::kPadding); | 355 } while (tag == SerializationTag::kPadding); |
350 return Just(tag); | 356 return Just(tag); |
351 } | 357 } |
352 | 358 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 DCHECK(HasObjectWithID(id)); | 516 DCHECK(HasObjectWithID(id)); |
511 return scope.CloseAndEscape(object); | 517 return scope.CloseAndEscape(object); |
512 } | 518 } |
513 | 519 |
514 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 520 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
515 Handle<JSObject> object, SerializationTag end_tag) { | 521 Handle<JSObject> object, SerializationTag end_tag) { |
516 for (uint32_t num_properties = 0;; num_properties++) { | 522 for (uint32_t num_properties = 0;; num_properties++) { |
517 SerializationTag tag; | 523 SerializationTag tag; |
518 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 524 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
519 if (tag == end_tag) { | 525 if (tag == end_tag) { |
520 SerializationTag consumed_tag = ReadTag().ToChecked(); | 526 ConsumeTag(end_tag); |
521 USE(consumed_tag); | |
522 DCHECK(tag == consumed_tag); | |
523 return Just(num_properties); | 527 return Just(num_properties); |
524 } | 528 } |
525 | 529 |
526 Handle<Object> key; | 530 Handle<Object> key; |
527 if (!ReadObject().ToHandle(&key)) return Nothing<uint32_t>(); | 531 if (!ReadObject().ToHandle(&key)) return Nothing<uint32_t>(); |
528 Handle<Object> value; | 532 Handle<Object> value; |
529 if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>(); | 533 if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>(); |
530 | 534 |
531 bool success; | 535 bool success; |
532 LookupIterator it = LookupIterator::PropertyOrElement( | 536 LookupIterator it = LookupIterator::PropertyOrElement( |
(...skipping 29 matching lines...) Expand all Loading... |
562 used_as_prototype); | 566 used_as_prototype); |
563 | 567 |
564 // If the dictionary was reallocated, update the global handle. | 568 // If the dictionary was reallocated, update the global handle. |
565 if (!new_dictionary.is_identical_to(id_map_)) { | 569 if (!new_dictionary.is_identical_to(id_map_)) { |
566 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); | 570 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); |
567 id_map_ = Handle<SeededNumberDictionary>::cast( | 571 id_map_ = Handle<SeededNumberDictionary>::cast( |
568 isolate_->global_handles()->Create(*new_dictionary)); | 572 isolate_->global_handles()->Create(*new_dictionary)); |
569 } | 573 } |
570 } | 574 } |
571 | 575 |
| 576 static MaybeHandle<JSObject> CreateJSObjectFromKeyValuePairs( |
| 577 Isolate* isolate, Handle<Object>* data, uint32_t num_properties) { |
| 578 Handle<JSObject> object = |
| 579 isolate->factory()->NewJSObject(isolate->object_function()); |
| 580 for (unsigned i = 0; i < 2 * num_properties; i += 2) { |
| 581 Handle<Object> key = data[i]; |
| 582 Handle<Object> value = data[i + 1]; |
| 583 bool success; |
| 584 LookupIterator it = LookupIterator::PropertyOrElement( |
| 585 isolate, object, key, &success, LookupIterator::OWN); |
| 586 if (!success || |
| 587 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE) |
| 588 .is_null()) { |
| 589 return MaybeHandle<JSObject>(); |
| 590 } |
| 591 } |
| 592 return object; |
| 593 } |
| 594 |
| 595 MaybeHandle<Object> |
| 596 ValueDeserializer::ReadObjectUsingEntireBufferForLegacyFormat() { |
| 597 if (version_ > 0) return MaybeHandle<Object>(); |
| 598 |
| 599 HandleScope scope(isolate_); |
| 600 std::vector<Handle<Object>> stack; |
| 601 while (position_ < end_) { |
| 602 SerializationTag tag; |
| 603 if (!PeekTag().To(&tag)) break; |
| 604 |
| 605 Handle<Object> new_object; |
| 606 switch (tag) { |
| 607 case SerializationTag::kEndJSObject: { |
| 608 ConsumeTag(SerializationTag::kEndJSObject); |
| 609 |
| 610 // JS Object: Read the last 2*n values from the stack and use them as |
| 611 // key-value pairs. |
| 612 uint32_t num_properties; |
| 613 if (!ReadVarint<uint32_t>().To(&num_properties) || |
| 614 stack.size() / 2 < num_properties) { |
| 615 return MaybeHandle<Object>(); |
| 616 } |
| 617 |
| 618 size_t begin_properties = stack.size() - 2 * num_properties; |
| 619 Handle<Object>* data = |
| 620 num_properties ? &stack[begin_properties] : nullptr; |
| 621 if (!CreateJSObjectFromKeyValuePairs(isolate_, data, num_properties) |
| 622 .ToHandle(&new_object)) { |
| 623 return MaybeHandle<Object>(); |
| 624 } |
| 625 |
| 626 stack.resize(begin_properties); |
| 627 break; |
| 628 } |
| 629 default: |
| 630 if (!ReadObject().ToHandle(&new_object)) return MaybeHandle<Object>(); |
| 631 break; |
| 632 } |
| 633 stack.push_back(new_object); |
| 634 } |
| 635 |
| 636 // Nothing remains but padding. |
| 637 #ifdef DEBUG |
| 638 while (position_ < end_) { |
| 639 DCHECK(*position_++ == static_cast<uint8_t>(SerializationTag::kPadding)); |
| 640 } |
| 641 #endif |
| 642 position_ = end_; |
| 643 |
| 644 if (stack.size() != 1) return MaybeHandle<Object>(); |
| 645 return scope.CloseAndEscape(stack[0]); |
| 646 } |
| 647 |
572 } // namespace internal | 648 } // namespace internal |
573 } // namespace v8 | 649 } // namespace v8 |
OLD | NEW |