Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: content/child/v8_value_converter_impl.cc

Issue 2014323002: Use std::unique_ptr<base::Value> in V8ValueConverter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: android fixes Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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>
11 #include <memory> 11 #include <memory>
12 #include <string> 12 #include <string>
13 #include <utility>
13 14
14 #include "base/bind.h" 15 #include "base/bind.h"
15 #include "base/bind_helpers.h" 16 #include "base/bind_helpers.h"
16 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/memory/ptr_util.h"
17 #include "base/values.h" 19 #include "base/values.h"
18 #include "third_party/WebKit/public/web/WebArrayBuffer.h" 20 #include "third_party/WebKit/public/web/WebArrayBuffer.h"
19 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h" 21 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
20 #include "third_party/WebKit/public/web/WebArrayBufferView.h" 22 #include "third_party/WebKit/public/web/WebArrayBufferView.h"
21 #include "v8/include/v8.h" 23 #include "v8/include/v8.h"
22 24
23 namespace content { 25 namespace content {
24 26
25 // Default implementation of V8ValueConverter::Strategy 27 // Default implementation of V8ValueConverter::Strategy
26 28
27 bool V8ValueConverter::Strategy::FromV8Object( 29 bool V8ValueConverter::Strategy::FromV8Object(
28 v8::Local<v8::Object> value, 30 v8::Local<v8::Object> value,
29 base::Value** out, 31 std::unique_ptr<base::Value>* out,
30 v8::Isolate* isolate, 32 v8::Isolate* isolate,
31 const FromV8ValueCallback& callback) const { 33 const FromV8ValueCallback& callback) const {
32 return false; 34 return false;
33 } 35 }
34 36
35 bool V8ValueConverter::Strategy::FromV8Array( 37 bool V8ValueConverter::Strategy::FromV8Array(
36 v8::Local<v8::Array> value, 38 v8::Local<v8::Array> value,
37 base::Value** out, 39 std::unique_ptr<base::Value>* out,
38 v8::Isolate* isolate, 40 v8::Isolate* isolate,
39 const FromV8ValueCallback& callback) const { 41 const FromV8ValueCallback& callback) const {
40 return false; 42 return false;
41 } 43 }
42 44
43 bool V8ValueConverter::Strategy::FromV8ArrayBuffer(v8::Local<v8::Object> value, 45 bool V8ValueConverter::Strategy::FromV8ArrayBuffer(
44 base::Value** out, 46 v8::Local<v8::Object> value,
45 v8::Isolate* isolate) const { 47 std::unique_ptr<base::Value>* out,
48 v8::Isolate* isolate) const {
46 return false; 49 return false;
47 } 50 }
48 51
49 bool V8ValueConverter::Strategy::FromV8Number(v8::Local<v8::Number> value, 52 bool V8ValueConverter::Strategy::FromV8Number(
50 base::Value** out) const { 53 v8::Local<v8::Number> value,
54 std::unique_ptr<base::Value>* out) const {
51 return false; 55 return false;
52 } 56 }
53 57
54 bool V8ValueConverter::Strategy::FromV8Undefined(base::Value** out) const { 58 bool V8ValueConverter::Strategy::FromV8Undefined(
59 std::unique_ptr<base::Value>* out) const {
55 return false; 60 return false;
56 } 61 }
57 62
58 63
59 namespace { 64 namespace {
60 65
61 // For the sake of the storage API, make this quite large. 66 // For the sake of the storage API, make this quite large.
62 const int kMaxRecursionDepth = 100; 67 const int kMaxRecursionDepth = 100;
63 68
64 } // namespace 69 } // namespace
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } 210 }
206 211
207 v8::Local<v8::Value> V8ValueConverterImpl::ToV8Value( 212 v8::Local<v8::Value> V8ValueConverterImpl::ToV8Value(
208 const base::Value* value, v8::Local<v8::Context> context) const { 213 const base::Value* value, v8::Local<v8::Context> context) const {
209 v8::Context::Scope context_scope(context); 214 v8::Context::Scope context_scope(context);
210 v8::EscapableHandleScope handle_scope(context->GetIsolate()); 215 v8::EscapableHandleScope handle_scope(context->GetIsolate());
211 return handle_scope.Escape( 216 return handle_scope.Escape(
212 ToV8ValueImpl(context->GetIsolate(), context->Global(), value)); 217 ToV8ValueImpl(context->GetIsolate(), context->Global(), value));
213 } 218 }
214 219
215 base::Value* V8ValueConverterImpl::FromV8Value( 220 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Value(
216 v8::Local<v8::Value> val, 221 v8::Local<v8::Value> val,
217 v8::Local<v8::Context> context) const { 222 v8::Local<v8::Context> context) const {
218 v8::Context::Scope context_scope(context); 223 v8::Context::Scope context_scope(context);
219 v8::HandleScope handle_scope(context->GetIsolate()); 224 v8::HandleScope handle_scope(context->GetIsolate());
220 FromV8ValueState state(avoid_identity_hash_for_testing_); 225 FromV8ValueState state(avoid_identity_hash_for_testing_);
221 return FromV8ValueImpl(&state, val, context->GetIsolate()); 226 return FromV8ValueImpl(&state, val, context->GetIsolate());
222 } 227 }
223 228
224 v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl( 229 v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl(
225 v8::Isolate* isolate, 230 v8::Isolate* isolate,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 v8::Isolate* isolate, 339 v8::Isolate* isolate,
335 v8::Local<v8::Object> creation_context, 340 v8::Local<v8::Object> creation_context,
336 const base::BinaryValue* value) const { 341 const base::BinaryValue* value) const {
337 blink::WebArrayBuffer buffer = 342 blink::WebArrayBuffer buffer =
338 blink::WebArrayBuffer::create(value->GetSize(), 1); 343 blink::WebArrayBuffer::create(value->GetSize(), 1);
339 memcpy(buffer.data(), value->GetBuffer(), value->GetSize()); 344 memcpy(buffer.data(), value->GetBuffer(), value->GetSize());
340 return blink::WebArrayBufferConverter::toV8Value( 345 return blink::WebArrayBufferConverter::toV8Value(
341 &buffer, creation_context, isolate); 346 &buffer, creation_context, isolate);
342 } 347 }
343 348
344 base::Value* V8ValueConverterImpl::FromV8ValueImpl( 349 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ValueImpl(
345 FromV8ValueState* state, 350 FromV8ValueState* state,
346 v8::Local<v8::Value> val, 351 v8::Local<v8::Value> val,
347 v8::Isolate* isolate) const { 352 v8::Isolate* isolate) const {
348 CHECK(!val.IsEmpty()); 353 CHECK(!val.IsEmpty());
349 354
350 FromV8ValueState::Level state_level(state); 355 FromV8ValueState::Level state_level(state);
351 if (state->HasReachedMaxRecursionDepth()) 356 if (state->HasReachedMaxRecursionDepth())
352 return NULL; 357 return nullptr;
353 358
354 if (val->IsNull()) 359 if (val->IsNull())
355 return base::Value::CreateNullValue().release(); 360 return base::Value::CreateNullValue();
356 361
357 if (val->IsBoolean()) 362 if (val->IsBoolean())
358 return new base::FundamentalValue(val->ToBoolean(isolate)->Value()); 363 return base::MakeUnique<base::FundamentalValue>(
364 val->ToBoolean(isolate)->Value());
359 365
360 if (val->IsNumber() && strategy_) { 366 if (val->IsNumber() && strategy_) {
361 base::Value* out = NULL; 367 std::unique_ptr<base::Value> out;
362 if (strategy_->FromV8Number(val.As<v8::Number>(), &out)) 368 if (strategy_->FromV8Number(val.As<v8::Number>(), &out))
363 return out; 369 return out;
364 } 370 }
365 371
366 if (val->IsInt32()) 372 if (val->IsInt32())
367 return new base::FundamentalValue(val->ToInt32(isolate)->Value()); 373 return base::MakeUnique<base::FundamentalValue>(
374 val->ToInt32(isolate)->Value());
368 375
369 if (val->IsNumber()) { 376 if (val->IsNumber()) {
370 double val_as_double = val.As<v8::Number>()->Value(); 377 double val_as_double = val.As<v8::Number>()->Value();
371 if (!std::isfinite(val_as_double)) 378 if (!std::isfinite(val_as_double))
372 return NULL; 379 return nullptr;
373 return new base::FundamentalValue(val_as_double); 380 return base::MakeUnique<base::FundamentalValue>(val_as_double);
374 } 381 }
375 382
376 if (val->IsString()) { 383 if (val->IsString()) {
377 v8::String::Utf8Value utf8(val); 384 v8::String::Utf8Value utf8(val);
378 return new base::StringValue(std::string(*utf8, utf8.length())); 385 return base::MakeUnique<base::StringValue>(
386 std::string(*utf8, utf8.length()));
379 } 387 }
380 388
381 if (val->IsUndefined()) { 389 if (val->IsUndefined()) {
382 if (strategy_) { 390 if (strategy_) {
383 base::Value* out = NULL; 391 std::unique_ptr<base::Value> out;
384 if (strategy_->FromV8Undefined(&out)) 392 if (strategy_->FromV8Undefined(&out))
385 return out; 393 return out;
386 } 394 }
387 // JSON.stringify ignores undefined. 395 // JSON.stringify ignores undefined.
388 return NULL; 396 return nullptr;
389 } 397 }
390 398
391 if (val->IsDate()) { 399 if (val->IsDate()) {
392 if (!date_allowed_) 400 if (!date_allowed_)
393 // JSON.stringify would convert this to a string, but an object is more 401 // JSON.stringify would convert this to a string, but an object is more
394 // consistent within this class. 402 // consistent within this class.
395 return FromV8Object(val->ToObject(isolate), state, isolate); 403 return FromV8Object(val->ToObject(isolate), state, isolate);
396 v8::Date* date = v8::Date::Cast(*val); 404 v8::Date* date = v8::Date::Cast(*val);
397 return new base::FundamentalValue(date->ValueOf() / 1000.0); 405 return base::MakeUnique<base::FundamentalValue>(date->ValueOf() / 1000.0);
398 } 406 }
399 407
400 if (val->IsRegExp()) { 408 if (val->IsRegExp()) {
401 if (!reg_exp_allowed_) 409 if (!reg_exp_allowed_)
402 // JSON.stringify converts to an object. 410 // JSON.stringify converts to an object.
403 return FromV8Object(val.As<v8::Object>(), state, isolate); 411 return FromV8Object(val.As<v8::Object>(), state, isolate);
404 return new base::StringValue(*v8::String::Utf8Value(val)); 412 return base::MakeUnique<base::StringValue>(*v8::String::Utf8Value(val));
405 } 413 }
406 414
407 // v8::Value doesn't have a ToArray() method for some reason. 415 // v8::Value doesn't have a ToArray() method for some reason.
408 if (val->IsArray()) 416 if (val->IsArray())
409 return FromV8Array(val.As<v8::Array>(), state, isolate); 417 return FromV8Array(val.As<v8::Array>(), state, isolate);
410 418
411 if (val->IsFunction()) { 419 if (val->IsFunction()) {
412 if (!function_allowed_) 420 if (!function_allowed_)
413 // JSON.stringify refuses to convert function(){}. 421 // JSON.stringify refuses to convert function(){}.
414 return NULL; 422 return nullptr;
415 return FromV8Object(val.As<v8::Object>(), state, isolate); 423 return FromV8Object(val.As<v8::Object>(), state, isolate);
416 } 424 }
417 425
418 if (val->IsArrayBuffer() || val->IsArrayBufferView()) 426 if (val->IsArrayBuffer() || val->IsArrayBufferView())
419 return FromV8ArrayBuffer(val.As<v8::Object>(), isolate); 427 return FromV8ArrayBuffer(val.As<v8::Object>(), isolate);
420 428
421 if (val->IsObject()) 429 if (val->IsObject())
422 return FromV8Object(val.As<v8::Object>(), state, isolate); 430 return FromV8Object(val.As<v8::Object>(), state, isolate);
423 431
424 LOG(ERROR) << "Unexpected v8 value type encountered."; 432 LOG(ERROR) << "Unexpected v8 value type encountered.";
425 return NULL; 433 return nullptr;
426 } 434 }
427 435
428 base::Value* V8ValueConverterImpl::FromV8Array( 436 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Array(
429 v8::Local<v8::Array> val, 437 v8::Local<v8::Array> val,
430 FromV8ValueState* state, 438 FromV8ValueState* state,
431 v8::Isolate* isolate) const { 439 v8::Isolate* isolate) const {
432 ScopedUniquenessGuard uniqueness_guard(state, val); 440 ScopedUniquenessGuard uniqueness_guard(state, val);
433 if (!uniqueness_guard.is_valid()) 441 if (!uniqueness_guard.is_valid())
434 return base::Value::CreateNullValue().release(); 442 return base::Value::CreateNullValue();
435 443
436 std::unique_ptr<v8::Context::Scope> scope; 444 std::unique_ptr<v8::Context::Scope> scope;
437 // If val was created in a different context than our current one, change to 445 // If val was created in a different context than our current one, change to
438 // that context, but change back after val is converted. 446 // that context, but change back after val is converted.
439 if (!val->CreationContext().IsEmpty() && 447 if (!val->CreationContext().IsEmpty() &&
440 val->CreationContext() != isolate->GetCurrentContext()) 448 val->CreationContext() != isolate->GetCurrentContext())
441 scope.reset(new v8::Context::Scope(val->CreationContext())); 449 scope.reset(new v8::Context::Scope(val->CreationContext()));
442 450
443 if (strategy_) { 451 if (strategy_) {
444 // These base::Unretained's are safe, because Strategy::FromV8Value should 452 // These base::Unretained's are safe, because Strategy::FromV8Value should
445 // be synchronous, so this object can't be out of scope. 453 // be synchronous, so this object can't be out of scope.
446 V8ValueConverter::Strategy::FromV8ValueCallback callback = 454 V8ValueConverter::Strategy::FromV8ValueCallback callback =
447 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl, 455 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
448 base::Unretained(this), 456 base::Unretained(this),
449 base::Unretained(state)); 457 base::Unretained(state));
450 base::Value* out = NULL; 458 std::unique_ptr<base::Value> out;
451 if (strategy_->FromV8Array(val, &out, isolate, callback)) 459 if (strategy_->FromV8Array(val, &out, isolate, callback))
452 return out; 460 return out;
453 } 461 }
454 462
455 base::ListValue* result = new base::ListValue(); 463 std::unique_ptr<base::ListValue> result(new base::ListValue());
456 464
457 // Only fields with integer keys are carried over to the ListValue. 465 // Only fields with integer keys are carried over to the ListValue.
458 for (uint32_t i = 0; i < val->Length(); ++i) { 466 for (uint32_t i = 0; i < val->Length(); ++i) {
459 v8::TryCatch try_catch(isolate); 467 v8::TryCatch try_catch(isolate);
460 v8::Local<v8::Value> child_v8 = val->Get(i); 468 v8::Local<v8::Value> child_v8 = val->Get(i);
461 if (try_catch.HasCaught()) { 469 if (try_catch.HasCaught()) {
462 LOG(ERROR) << "Getter for index " << i << " threw an exception."; 470 LOG(ERROR) << "Getter for index " << i << " threw an exception.";
463 child_v8 = v8::Null(isolate); 471 child_v8 = v8::Null(isolate);
464 } 472 }
465 473
466 if (!val->HasRealIndexedProperty(i)) { 474 if (!val->HasRealIndexedProperty(i)) {
467 result->Append(base::Value::CreateNullValue()); 475 result->Append(base::Value::CreateNullValue());
468 continue; 476 continue;
469 } 477 }
470 478
471 base::Value* child = FromV8ValueImpl(state, child_v8, isolate); 479 std::unique_ptr<base::Value> child =
480 FromV8ValueImpl(state, child_v8, isolate);
472 if (child) 481 if (child)
473 result->Append(child); 482 result->Append(std::move(child));
474 else 483 else
475 // JSON.stringify puts null in places where values don't serialize, for 484 // JSON.stringify puts null in places where values don't serialize, for
476 // example undefined and functions. Emulate that behavior. 485 // example undefined and functions. Emulate that behavior.
477 result->Append(base::Value::CreateNullValue()); 486 result->Append(base::Value::CreateNullValue());
478 } 487 }
479 return result; 488 return std::move(result);
480 } 489 }
481 490
482 base::Value* V8ValueConverterImpl::FromV8ArrayBuffer( 491 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ArrayBuffer(
483 v8::Local<v8::Object> val, 492 v8::Local<v8::Object> val,
484 v8::Isolate* isolate) const { 493 v8::Isolate* isolate) const {
485 if (strategy_) { 494 if (strategy_) {
486 base::Value* out = NULL; 495 std::unique_ptr<base::Value> out;
487 if (strategy_->FromV8ArrayBuffer(val, &out, isolate)) 496 if (strategy_->FromV8ArrayBuffer(val, &out, isolate))
488 return out; 497 return out;
489 } 498 }
490 499
491 char* data = NULL; 500 char* data = NULL;
492 size_t length = 0; 501 size_t length = 0;
493 502
494 std::unique_ptr<blink::WebArrayBuffer> array_buffer( 503 std::unique_ptr<blink::WebArrayBuffer> array_buffer(
495 blink::WebArrayBufferConverter::createFromV8Value(val, isolate)); 504 blink::WebArrayBufferConverter::createFromV8Value(val, isolate));
496 std::unique_ptr<blink::WebArrayBufferView> view; 505 std::unique_ptr<blink::WebArrayBufferView> view;
497 if (array_buffer) { 506 if (array_buffer) {
498 data = reinterpret_cast<char*>(array_buffer->data()); 507 data = reinterpret_cast<char*>(array_buffer->data());
499 length = array_buffer->byteLength(); 508 length = array_buffer->byteLength();
500 } else { 509 } else {
501 view.reset(blink::WebArrayBufferView::createFromV8Value(val)); 510 view.reset(blink::WebArrayBufferView::createFromV8Value(val));
502 if (view) { 511 if (view) {
503 data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset(); 512 data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset();
504 length = view->byteLength(); 513 length = view->byteLength();
505 } 514 }
506 } 515 }
507 516
508 if (data) 517 if (data)
509 return base::BinaryValue::CreateWithCopiedBuffer(data, length); 518 return base::WrapUnique(
519 base::BinaryValue::CreateWithCopiedBuffer(data, length));
510 else 520 else
511 return NULL; 521 return nullptr;
512 } 522 }
513 523
514 base::Value* V8ValueConverterImpl::FromV8Object( 524 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Object(
515 v8::Local<v8::Object> val, 525 v8::Local<v8::Object> val,
516 FromV8ValueState* state, 526 FromV8ValueState* state,
517 v8::Isolate* isolate) const { 527 v8::Isolate* isolate) const {
518 ScopedUniquenessGuard uniqueness_guard(state, val); 528 ScopedUniquenessGuard uniqueness_guard(state, val);
519 if (!uniqueness_guard.is_valid()) 529 if (!uniqueness_guard.is_valid())
520 return base::Value::CreateNullValue().release(); 530 return base::Value::CreateNullValue();
521 531
522 std::unique_ptr<v8::Context::Scope> scope; 532 std::unique_ptr<v8::Context::Scope> scope;
523 // If val was created in a different context than our current one, change to 533 // If val was created in a different context than our current one, change to
524 // that context, but change back after val is converted. 534 // that context, but change back after val is converted.
525 if (!val->CreationContext().IsEmpty() && 535 if (!val->CreationContext().IsEmpty() &&
526 val->CreationContext() != isolate->GetCurrentContext()) 536 val->CreationContext() != isolate->GetCurrentContext())
527 scope.reset(new v8::Context::Scope(val->CreationContext())); 537 scope.reset(new v8::Context::Scope(val->CreationContext()));
528 538
529 if (strategy_) { 539 if (strategy_) {
530 // These base::Unretained's are safe, because Strategy::FromV8Value should 540 // These base::Unretained's are safe, because Strategy::FromV8Value should
531 // be synchronous, so this object can't be out of scope. 541 // be synchronous, so this object can't be out of scope.
532 V8ValueConverter::Strategy::FromV8ValueCallback callback = 542 V8ValueConverter::Strategy::FromV8ValueCallback callback =
533 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl, 543 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
534 base::Unretained(this), 544 base::Unretained(this),
535 base::Unretained(state)); 545 base::Unretained(state));
536 base::Value* out = NULL; 546 std::unique_ptr<base::Value> out;
537 if (strategy_->FromV8Object(val, &out, isolate, callback)) 547 if (strategy_->FromV8Object(val, &out, isolate, callback))
538 return out; 548 return out;
539 } 549 }
540 550
541 // Don't consider DOM objects. This check matches isHostObject() in Blink's 551 // Don't consider DOM objects. This check matches isHostObject() in Blink's
542 // bindings/v8/V8Binding.h used in structured cloning. It reads: 552 // bindings/v8/V8Binding.h used in structured cloning. It reads:
543 // 553 //
544 // If the object has any internal fields, then we won't be able to serialize 554 // If the object has any internal fields, then we won't be able to serialize
545 // or deserialize them; conveniently, this is also a quick way to detect DOM 555 // or deserialize them; conveniently, this is also a quick way to detect DOM
546 // wrapper objects, because the mechanism for these relies on data stored in 556 // wrapper objects, because the mechanism for these relies on data stored in
547 // these fields. 557 // these fields.
548 // 558 //
549 // NOTE: check this after |strategy_| so that callers have a chance to 559 // NOTE: check this after |strategy_| so that callers have a chance to
550 // do something else, such as convert to the node's name rather than NULL. 560 // do something else, such as convert to the node's name rather than NULL.
551 // 561 //
552 // ANOTHER NOTE: returning an empty dictionary here to minimise surprise. 562 // ANOTHER NOTE: returning an empty dictionary here to minimise surprise.
553 // See also http://crbug.com/330559. 563 // See also http://crbug.com/330559.
554 if (val->InternalFieldCount()) 564 if (val->InternalFieldCount())
555 return new base::DictionaryValue(); 565 return base::MakeUnique<base::DictionaryValue>();
556 566
557 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 567 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
558 v8::Local<v8::Array> property_names(val->GetOwnPropertyNames()); 568 v8::Local<v8::Array> property_names(val->GetOwnPropertyNames());
559 569
560 for (uint32_t i = 0; i < property_names->Length(); ++i) { 570 for (uint32_t i = 0; i < property_names->Length(); ++i) {
561 v8::Local<v8::Value> key(property_names->Get(i)); 571 v8::Local<v8::Value> key(property_names->Get(i));
562 572
563 // Extend this test to cover more types as necessary and if sensible. 573 // Extend this test to cover more types as necessary and if sensible.
564 if (!key->IsString() && 574 if (!key->IsString() &&
565 !key->IsNumber()) { 575 !key->IsNumber()) {
566 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " 576 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" "
567 "is neither a string nor a number"; 577 "is neither a string nor a number";
568 continue; 578 continue;
569 } 579 }
570 580
571 v8::String::Utf8Value name_utf8(key); 581 v8::String::Utf8Value name_utf8(key);
572 582
573 v8::TryCatch try_catch(isolate); 583 v8::TryCatch try_catch(isolate);
574 v8::Local<v8::Value> child_v8 = val->Get(key); 584 v8::Local<v8::Value> child_v8 = val->Get(key);
575 585
576 if (try_catch.HasCaught()) { 586 if (try_catch.HasCaught()) {
577 LOG(WARNING) << "Getter for property " << *name_utf8 587 LOG(WARNING) << "Getter for property " << *name_utf8
578 << " threw an exception."; 588 << " threw an exception.";
579 child_v8 = v8::Null(isolate); 589 child_v8 = v8::Null(isolate);
580 } 590 }
581 591
582 std::unique_ptr<base::Value> child( 592 std::unique_ptr<base::Value> child =
583 FromV8ValueImpl(state, child_v8, isolate)); 593 FromV8ValueImpl(state, child_v8, isolate);
584 if (!child) 594 if (!child)
585 // JSON.stringify skips properties whose values don't serialize, for 595 // JSON.stringify skips properties whose values don't serialize, for
586 // example undefined and functions. Emulate that behavior. 596 // example undefined and functions. Emulate that behavior.
587 continue; 597 continue;
588 598
589 // Strip null if asked (and since undefined is turned into null, undefined 599 // Strip null if asked (and since undefined is turned into null, undefined
590 // too). The use case for supporting this is JSON-schema support, 600 // too). The use case for supporting this is JSON-schema support,
591 // specifically for extensions, where "optional" JSON properties may be 601 // specifically for extensions, where "optional" JSON properties may be
592 // represented as null, yet due to buggy legacy code elsewhere isn't 602 // represented as null, yet due to buggy legacy code elsewhere isn't
593 // treated as such (potentially causing crashes). For example, the 603 // treated as such (potentially causing crashes). For example, the
594 // "tabs.create" function takes an object as its first argument with an 604 // "tabs.create" function takes an object as its first argument with an
595 // optional "windowId" property. 605 // optional "windowId" property.
596 // 606 //
597 // Given just 607 // Given just
598 // 608 //
599 // tabs.create({}) 609 // tabs.create({})
600 // 610 //
601 // this will work as expected on code that only checks for the existence of 611 // this will work as expected on code that only checks for the existence of
602 // a "windowId" property (such as that legacy code). However given 612 // a "windowId" property (such as that legacy code). However given
603 // 613 //
604 // tabs.create({windowId: null}) 614 // tabs.create({windowId: null})
605 // 615 //
606 // there *is* a "windowId" property, but since it should be an int, code 616 // there *is* a "windowId" property, but since it should be an int, code
607 // on the browser which doesn't additionally check for null will fail. 617 // on the browser which doesn't additionally check for null will fail.
608 // We can avoid all bugs related to this by stripping null. 618 // We can avoid all bugs related to this by stripping null.
609 if (strip_null_from_objects_ && child->IsType(base::Value::TYPE_NULL)) 619 if (strip_null_from_objects_ && child->IsType(base::Value::TYPE_NULL))
610 continue; 620 continue;
611 621
612 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), 622 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
613 child.release()); 623 std::move(child));
614 } 624 }
615 625
616 return result.release(); 626 return std::move(result);
617 } 627 }
618 628
619 } // namespace content 629 } // namespace content
OLDNEW
« no previous file with comments | « content/child/v8_value_converter_impl.h ('k') | content/child/v8_value_converter_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698