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 |