Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium 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 "content/child/v8_value_converter_impl.h" | 5 #include "content/child/v8_value_converter_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <cmath> | 10 #include <cmath> |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 : max_recursion_depth_(kMaxRecursionDepth), | 84 : max_recursion_depth_(kMaxRecursionDepth), |
| 85 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {} | 85 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {} |
| 86 | 86 |
| 87 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and | 87 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and |
| 88 // return true. | 88 // return true. |
| 89 // | 89 // |
| 90 // Otherwise do nothing and return false. Here "A is unique" means that no | 90 // Otherwise do nothing and return false. Here "A is unique" means that no |
| 91 // other handle B in the map points to the same object as A. Note that A can | 91 // other handle B in the map points to the same object as A. Note that A can |
| 92 // be unique even if there already is another handle with the same identity | 92 // be unique even if there already is another handle with the same identity |
| 93 // hash (key) in the map, because two objects can have the same hash. | 93 // hash (key) in the map, because two objects can have the same hash. |
| 94 bool UpdateAndCheckUniqueness(v8::Local<v8::Object> handle) { | 94 bool AddToUniquenessCheck(v8::Local<v8::Object> handle) { |
| 95 typedef HashToHandleMap::const_iterator Iterator; | 95 typedef HashToHandleMap::const_iterator Iterator; |
| 96 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); | 96 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); |
| 97 // We only compare using == with handles to objects with the same identity | 97 // We only compare using == with handles to objects with the same identity |
| 98 // hash. Different hash obviously means different objects, but two objects | 98 // hash. Different hash obviously means different objects, but two objects |
| 99 // in a couple of thousands could have the same identity hash. | 99 // in a couple of thousands could have the same identity hash. |
| 100 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); | 100 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); |
| 101 for (Iterator it = range.first; it != range.second; ++it) { | 101 for (Iterator it = range.first; it != range.second; ++it) { |
| 102 // Operator == for handles actually compares the underlying objects. | 102 // Operator == for handles actually compares the underlying objects. |
| 103 if (it->second == handle) | 103 if (it->second == handle) |
| 104 return false; | 104 return false; |
| 105 } | 105 } |
| 106 unique_map_.insert(std::make_pair(hash, handle)); | 106 unique_map_.insert(std::make_pair(hash, handle)); |
| 107 return true; | 107 return true; |
| 108 } | 108 } |
| 109 | 109 |
| 110 bool RemoveFromUniquenessCheck(v8::Local<v8::Object> handle) { | |
| 111 typedef HashToHandleMap::const_iterator Iterator; | |
| 112 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); | |
| 113 // We only compare using == with handles to objects with the same identity | |
| 114 // hash. Different hash obviously means different objects, but two objects | |
| 115 // in a couple of thousands could have the same identity hash. | |
| 116 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); | |
| 117 for (Iterator it = range.first; it != range.second; ++it) { | |
| 118 // Operator == for handles actually compares the underlying objects. | |
| 119 if (it->second == handle) { | |
| 120 unique_map_.erase(it); | |
| 121 return true; | |
| 122 } | |
| 123 } | |
|
asargent_no_longer_on_chrome
2016/05/03 23:04:58
nit: looks all the above code is duplicated from A
lazyboy
2016/05/03 23:57:49
returning Iterator instead since I'd have lookup t
| |
| 124 return false; | |
| 125 } | |
| 126 | |
| 110 bool HasReachedMaxRecursionDepth() { | 127 bool HasReachedMaxRecursionDepth() { |
| 111 return max_recursion_depth_ < 0; | 128 return max_recursion_depth_ < 0; |
| 112 } | 129 } |
| 113 | 130 |
| 114 private: | 131 private: |
| 115 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap; | 132 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap; |
| 116 HashToHandleMap unique_map_; | 133 HashToHandleMap unique_map_; |
| 117 | 134 |
| 118 int max_recursion_depth_; | 135 int max_recursion_depth_; |
| 119 | 136 |
| 120 bool avoid_identity_hash_for_testing_; | 137 bool avoid_identity_hash_for_testing_; |
| 138 | |
| 139 DISALLOW_COPY_AND_ASSIGN(FromV8ValueState); | |
| 140 }; | |
| 141 | |
| 142 // A class to ensure that objects/arrays that are being converted by | |
| 143 // this V8ValueConverterImpl do not have cycles. | |
| 144 // | |
| 145 // An example of cycle: var v = {}; v = {key: v}; | |
| 146 // Not an example of cycle: var v = {}; a = [v, v]; or w = {a: v, b: v}; | |
| 147 class V8ValueConverterImpl::ScopedUniquenessGuard { | |
| 148 public: | |
| 149 ScopedUniquenessGuard(V8ValueConverterImpl::FromV8ValueState* state, | |
| 150 v8::Local<v8::Object> value) | |
| 151 : state_(state), | |
| 152 value_(value), | |
| 153 is_valid_(state_->AddToUniquenessCheck(value_)) {} | |
| 154 ~ScopedUniquenessGuard() { | |
| 155 if (is_valid_) { | |
| 156 bool removed = state_->RemoveFromUniquenessCheck(value_); | |
| 157 DCHECK(removed); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 bool is_valid() const { return is_valid_; } | |
| 162 | |
| 163 private: | |
| 164 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap; | |
| 165 V8ValueConverterImpl::FromV8ValueState* state_; | |
| 166 v8::Local<v8::Object> value_; | |
| 167 bool is_valid_; | |
| 168 | |
| 169 DISALLOW_COPY_AND_ASSIGN(ScopedUniquenessGuard); | |
| 121 }; | 170 }; |
| 122 | 171 |
| 123 V8ValueConverter* V8ValueConverter::create() { | 172 V8ValueConverter* V8ValueConverter::create() { |
| 124 return new V8ValueConverterImpl(); | 173 return new V8ValueConverterImpl(); |
| 125 } | 174 } |
| 126 | 175 |
| 127 V8ValueConverterImpl::V8ValueConverterImpl() | 176 V8ValueConverterImpl::V8ValueConverterImpl() |
| 128 : date_allowed_(false), | 177 : date_allowed_(false), |
| 129 reg_exp_allowed_(false), | 178 reg_exp_allowed_(false), |
| 130 function_allowed_(false), | 179 function_allowed_(false), |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 return FromV8Object(val.As<v8::Object>(), state, isolate); | 419 return FromV8Object(val.As<v8::Object>(), state, isolate); |
| 371 | 420 |
| 372 LOG(ERROR) << "Unexpected v8 value type encountered."; | 421 LOG(ERROR) << "Unexpected v8 value type encountered."; |
| 373 return NULL; | 422 return NULL; |
| 374 } | 423 } |
| 375 | 424 |
| 376 base::Value* V8ValueConverterImpl::FromV8Array( | 425 base::Value* V8ValueConverterImpl::FromV8Array( |
| 377 v8::Local<v8::Array> val, | 426 v8::Local<v8::Array> val, |
| 378 FromV8ValueState* state, | 427 FromV8ValueState* state, |
| 379 v8::Isolate* isolate) const { | 428 v8::Isolate* isolate) const { |
| 380 if (!state->UpdateAndCheckUniqueness(val)) | 429 ScopedUniquenessGuard uniqueness_guard(state, val); |
| 430 if (!uniqueness_guard.is_valid()) | |
| 381 return base::Value::CreateNullValue().release(); | 431 return base::Value::CreateNullValue().release(); |
| 382 | 432 |
| 383 std::unique_ptr<v8::Context::Scope> scope; | 433 std::unique_ptr<v8::Context::Scope> scope; |
| 384 // If val was created in a different context than our current one, change to | 434 // If val was created in a different context than our current one, change to |
| 385 // that context, but change back after val is converted. | 435 // that context, but change back after val is converted. |
| 386 if (!val->CreationContext().IsEmpty() && | 436 if (!val->CreationContext().IsEmpty() && |
| 387 val->CreationContext() != isolate->GetCurrentContext()) | 437 val->CreationContext() != isolate->GetCurrentContext()) |
| 388 scope.reset(new v8::Context::Scope(val->CreationContext())); | 438 scope.reset(new v8::Context::Scope(val->CreationContext())); |
| 389 | 439 |
| 390 if (strategy_) { | 440 if (strategy_) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 if (data) | 505 if (data) |
| 456 return base::BinaryValue::CreateWithCopiedBuffer(data, length); | 506 return base::BinaryValue::CreateWithCopiedBuffer(data, length); |
| 457 else | 507 else |
| 458 return NULL; | 508 return NULL; |
| 459 } | 509 } |
| 460 | 510 |
| 461 base::Value* V8ValueConverterImpl::FromV8Object( | 511 base::Value* V8ValueConverterImpl::FromV8Object( |
| 462 v8::Local<v8::Object> val, | 512 v8::Local<v8::Object> val, |
| 463 FromV8ValueState* state, | 513 FromV8ValueState* state, |
| 464 v8::Isolate* isolate) const { | 514 v8::Isolate* isolate) const { |
| 465 if (!state->UpdateAndCheckUniqueness(val)) | 515 ScopedUniquenessGuard uniqueness_guard(state, val); |
| 516 if (!uniqueness_guard.is_valid()) | |
| 466 return base::Value::CreateNullValue().release(); | 517 return base::Value::CreateNullValue().release(); |
| 467 | 518 |
| 468 std::unique_ptr<v8::Context::Scope> scope; | 519 std::unique_ptr<v8::Context::Scope> scope; |
| 469 // If val was created in a different context than our current one, change to | 520 // If val was created in a different context than our current one, change to |
| 470 // that context, but change back after val is converted. | 521 // that context, but change back after val is converted. |
| 471 if (!val->CreationContext().IsEmpty() && | 522 if (!val->CreationContext().IsEmpty() && |
| 472 val->CreationContext() != isolate->GetCurrentContext()) | 523 val->CreationContext() != isolate->GetCurrentContext()) |
| 473 scope.reset(new v8::Context::Scope(val->CreationContext())); | 524 scope.reset(new v8::Context::Scope(val->CreationContext())); |
| 474 | 525 |
| 475 if (strategy_) { | 526 if (strategy_) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 continue; | 607 continue; |
| 557 | 608 |
| 558 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), | 609 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), |
| 559 child.release()); | 610 child.release()); |
| 560 } | 611 } |
| 561 | 612 |
| 562 return result.release(); | 613 return result.release(); |
| 563 } | 614 } |
| 564 | 615 |
| 565 } // namespace content | 616 } // namespace content |
| OLD | NEW |