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

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

Issue 1959613002: V8ValueConverter::ToV8Value should not trigger setters (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2661
Patch Set: 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
« no previous file with comments | « content/child/v8_value_converter_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 std::string GetString(v8::Local<v8::Array> value, uint32_t index) { 96 std::string GetString(v8::Local<v8::Array> value, uint32_t index) {
97 v8::Local<v8::String> temp = value->Get(index).As<v8::String>(); 97 v8::Local<v8::String> temp = value->Get(index).As<v8::String>();
98 if (temp.IsEmpty()) { 98 if (temp.IsEmpty()) {
99 ADD_FAILURE(); 99 ADD_FAILURE();
100 return std::string(); 100 return std::string();
101 } 101 }
102 v8::String::Utf8Value utf8(temp); 102 v8::String::Utf8Value utf8(temp);
103 return std::string(*utf8, utf8.length()); 103 return std::string(*utf8, utf8.length());
104 } 104 }
105 105
106 int32_t GetInt(v8::Local<v8::Object> value, const std::string& key) {
107 v8::Local<v8::Int32> temp =
108 value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()))
109 .As<v8::Int32>();
110 if (temp.IsEmpty()) {
111 ADD_FAILURE();
112 return -1;
113 }
114 return temp->Value();
115 }
116
117 int32_t GetInt(v8::Local<v8::Object> value, uint32_t index) {
118 v8::Local<v8::Int32> temp = value->Get(index).As<v8::Int32>();
119 if (temp.IsEmpty()) {
120 ADD_FAILURE();
121 return -1;
122 }
123 return temp->Value();
124 }
125
106 bool IsNull(base::DictionaryValue* value, const std::string& key) { 126 bool IsNull(base::DictionaryValue* value, const std::string& key) {
107 base::Value* child = NULL; 127 base::Value* child = NULL;
108 if (!value->Get(key, &child)) { 128 if (!value->Get(key, &child)) {
109 ADD_FAILURE(); 129 ADD_FAILURE();
110 return false; 130 return false;
111 } 131 }
112 return child->GetType() == base::Value::TYPE_NULL; 132 return child->GetType() == base::Value::TYPE_NULL;
113 } 133 }
114 134
115 bool IsNull(v8::Local<v8::Object> value, const std::string& key) { 135 bool IsNull(v8::Local<v8::Object> value, const std::string& key) {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 scoped_ptr<base::DictionaryValue> converted( 328 scoped_ptr<base::DictionaryValue> converted(
309 static_cast<base::DictionaryValue*>( 329 static_cast<base::DictionaryValue*>(
310 converter.FromV8Value(object, context))); 330 converter.FromV8Value(object, context)));
311 EXPECT_TRUE(converted.get()); 331 EXPECT_TRUE(converted.get());
312 // http://code.google.com/p/v8/issues/detail?id=1342 332 // http://code.google.com/p/v8/issues/detail?id=1342
313 // EXPECT_EQ(2u, converted->size()); 333 // EXPECT_EQ(2u, converted->size());
314 // EXPECT_TRUE(IsNull(converted.get(), "foo")); 334 // EXPECT_TRUE(IsNull(converted.get(), "foo"));
315 EXPECT_EQ(1u, converted->size()); 335 EXPECT_EQ(1u, converted->size());
316 EXPECT_EQ("bar", GetString(converted.get(), "bar")); 336 EXPECT_EQ("bar", GetString(converted.get(), "bar"));
317 337
318 // Converting to v8 value should drop the foo property. 338 // Converting to v8 value should not trigger the setter.
319 converted->SetString("foo", "foo"); 339 converted->SetString("foo", "foo");
320 v8::Local<v8::Object> copy = 340 v8::Local<v8::Object> copy =
321 converter.ToV8Value(converted.get(), context).As<v8::Object>(); 341 converter.ToV8Value(converted.get(), context).As<v8::Object>();
322 EXPECT_FALSE(copy.IsEmpty()); 342 EXPECT_FALSE(copy.IsEmpty());
323 EXPECT_EQ(2u, copy->GetPropertyNames()->Length()); 343 EXPECT_EQ(2u, copy->GetPropertyNames()->Length());
344 EXPECT_EQ("foo", GetString(copy, "foo"));
324 EXPECT_EQ("bar", GetString(copy, "bar")); 345 EXPECT_EQ("bar", GetString(copy, "bar"));
325 } 346 }
326 347
327 TEST_F(V8ValueConverterImplTest, ArrayExceptions) { 348 TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
328 v8::HandleScope handle_scope(isolate_); 349 v8::HandleScope handle_scope(isolate_);
329 v8::Local<v8::Context> context = 350 v8::Local<v8::Context> context =
330 v8::Local<v8::Context>::New(isolate_, context_); 351 v8::Local<v8::Context>::New(isolate_, context_);
331 v8::Context::Scope context_scope(context); 352 v8::Context::Scope context_scope(context);
332 353
333 const char* source = "(function() {" 354 const char* source = "(function() {"
(...skipping 13 matching lines...) Expand all
347 368
348 // Converting from v8 value should replace the first item with null. 369 // Converting from v8 value should replace the first item with null.
349 V8ValueConverterImpl converter; 370 V8ValueConverterImpl converter;
350 scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>( 371 scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>(
351 converter.FromV8Value(array, context))); 372 converter.FromV8Value(array, context)));
352 ASSERT_TRUE(converted.get()); 373 ASSERT_TRUE(converted.get());
353 // http://code.google.com/p/v8/issues/detail?id=1342 374 // http://code.google.com/p/v8/issues/detail?id=1342
354 EXPECT_EQ(2u, converted->GetSize()); 375 EXPECT_EQ(2u, converted->GetSize());
355 EXPECT_TRUE(IsNull(converted.get(), 0)); 376 EXPECT_TRUE(IsNull(converted.get(), 0));
356 377
357 // Converting to v8 value should drop the first item and leave a hole. 378 // Converting to v8 value should not be affected by the getter/setter
379 // because the setters/getters are defined on the array instance, not
380 // on the Array's prototype.
358 converted.reset(static_cast<base::ListValue*>( 381 converted.reset(static_cast<base::ListValue*>(
359 base::test::ParseJson("[ \"foo\", \"bar\" ]").release())); 382 base::test::ParseJson("[ \"foo\", \"bar\" ]").release()));
360 v8::Local<v8::Array> copy = 383 v8::Local<v8::Array> copy =
361 converter.ToV8Value(converted.get(), context).As<v8::Array>(); 384 converter.ToV8Value(converted.get(), context).As<v8::Array>();
362 ASSERT_FALSE(copy.IsEmpty()); 385 ASSERT_FALSE(copy.IsEmpty());
363 EXPECT_EQ(2u, copy->Length()); 386 EXPECT_EQ(2u, copy->Length());
387 EXPECT_EQ("foo", GetString(copy, 0));
364 EXPECT_EQ("bar", GetString(copy, 1)); 388 EXPECT_EQ("bar", GetString(copy, 1));
365 } 389 }
366 390
367 TEST_F(V8ValueConverterImplTest, WeirdTypes) { 391 TEST_F(V8ValueConverterImplTest, WeirdTypes) {
368 v8::HandleScope handle_scope(isolate_); 392 v8::HandleScope handle_scope(isolate_);
369 v8::Local<v8::Context> context = 393 v8::Local<v8::Context> context =
370 v8::Local<v8::Context>::New(isolate_, context_); 394 v8::Local<v8::Context>::New(isolate_, context_);
371 v8::Context::Scope context_scope(context); 395 v8::Context::Scope context_scope(context);
372 396
373 v8::Local<v8::RegExp> regex(v8::RegExp::New( 397 v8::Local<v8::RegExp> regex(v8::RegExp::New(
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 ASSERT_FALSE(object.IsEmpty()); 441 ASSERT_FALSE(object.IsEmpty());
418 442
419 V8ValueConverterImpl converter; 443 V8ValueConverterImpl converter;
420 scoped_ptr<base::DictionaryValue> result( 444 scoped_ptr<base::DictionaryValue> result(
421 static_cast<base::DictionaryValue*>( 445 static_cast<base::DictionaryValue*>(
422 converter.FromV8Value(object, context))); 446 converter.FromV8Value(object, context)));
423 ASSERT_TRUE(result.get()); 447 ASSERT_TRUE(result.get());
424 EXPECT_EQ(0u, result->size()); 448 EXPECT_EQ(0u, result->size());
425 } 449 }
426 450
451 TEST_F(V8ValueConverterImplTest, ObjectPrototypeSetter) {
452 std::unique_ptr<base::Value> original =
453 base::test::ParseJson("{ \"foo\": \"good value\" }");
454
455 v8::HandleScope handle_scope(isolate_);
456 v8::Local<v8::Context> context =
457 v8::Local<v8::Context>::New(isolate_, context_);
458 v8::Context::Scope context_scope(context);
459 v8::MicrotasksScope microtasks(isolate_,
460 v8::MicrotasksScope::kDoNotRunMicrotasks);
461
462 const char* source =
463 "var result = { getters: 0, setters: 0 };"
464 "Object.defineProperty(Object.prototype, 'foo', {"
465 " get() { ++result.getters; return 'bogus'; },"
466 " set() { ++result.setters; },"
467 "});"
468 "result;";
469
470 const char* source_sanity =
471 "({}).foo = 'Trigger setter';"
472 "({}).foo;";
473
474 v8::Local<v8::Script> script(
475 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
476 v8::Local<v8::Object> result = script->Run().As<v8::Object>();
477 ASSERT_FALSE(result.IsEmpty());
478
479 // Sanity checks: the getters/setters are normally triggered.
480 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source_sanity))->Run();
481 EXPECT_EQ(1, GetInt(result, "getters"));
482 EXPECT_EQ(1, GetInt(result, "setters"));
483
484 V8ValueConverterImpl converter;
485 v8::Local<v8::Object> converted =
486 converter.ToV8Value(original.get(), context).As<v8::Object>();
487 EXPECT_FALSE(converted.IsEmpty());
488
489 // Getters/setters shouldn't be triggered.
490 EXPECT_EQ(1, GetInt(result, "getters"));
491 EXPECT_EQ(1, GetInt(result, "setters"));
492
493 EXPECT_EQ(1u, converted->GetPropertyNames()->Length());
494 EXPECT_EQ("good value", GetString(converted, "foo"));
495
496 // Getters/setters shouldn't be triggered while accessing existing values.
497 EXPECT_EQ(1, GetInt(result, "getters"));
498 EXPECT_EQ(1, GetInt(result, "setters"));
499
500 // Repeat the same exercise with a dictionary without the key.
501 base::DictionaryValue missing_key_dict;
502 missing_key_dict.SetString("otherkey", "hello");
503 v8::Local<v8::Object> converted2 =
504 converter.ToV8Value(&missing_key_dict, context).As<v8::Object>();
505 EXPECT_FALSE(converted2.IsEmpty());
506
507 // Getters/setters shouldn't be triggered.
508 EXPECT_EQ(1, GetInt(result, "getters"));
509 EXPECT_EQ(1, GetInt(result, "setters"));
510
511 EXPECT_EQ(1u, converted2->GetPropertyNames()->Length());
512 EXPECT_EQ("hello", GetString(converted2, "otherkey"));
513
514 // Missing key = should trigger getter upon access.
515 EXPECT_EQ("bogus", GetString(converted2, "foo"));
516 EXPECT_EQ(2, GetInt(result, "getters"));
517 EXPECT_EQ(1, GetInt(result, "setters"));
518 }
519
520 TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) {
521 std::unique_ptr<base::Value> original =
522 base::test::ParseJson("[100, 200, 300]");
523
524 v8::HandleScope handle_scope(isolate_);
525 v8::Local<v8::Context> context =
526 v8::Local<v8::Context>::New(isolate_, context_);
527 v8::Context::Scope context_scope(context);
528 v8::MicrotasksScope microtasks(isolate_,
529 v8::MicrotasksScope::kDoNotRunMicrotasks);
530
531 const char* source =
532 "var result = { getters: 0, setters: 0 };"
533 "Object.defineProperty(Array.prototype, '1', {"
534 " get() { ++result.getters; return 1337; },"
535 " set() { ++result.setters; },"
536 "});"
537 "result;";
538
539 const char* source_sanity =
540 "[][1] = 'Trigger setter';"
541 "[][1];";
542
543 v8::Local<v8::Script> script(
544 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
545 v8::Local<v8::Object> result = script->Run().As<v8::Object>();
546 ASSERT_FALSE(result.IsEmpty());
547
548 // Sanity checks: the getters/setters are normally triggered.
549 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source_sanity))->Run();
550 EXPECT_EQ(1, GetInt(result, "getters"));
551 EXPECT_EQ(1, GetInt(result, "setters"));
552
553 V8ValueConverterImpl converter;
554 v8::Local<v8::Array> converted =
555 converter.ToV8Value(original.get(), context).As<v8::Array>();
556 EXPECT_FALSE(converted.IsEmpty());
557
558 // Getters/setters shouldn't be triggered during the conversion.
559 EXPECT_EQ(1, GetInt(result, "getters"));
560 EXPECT_EQ(1, GetInt(result, "setters"));
561
562 EXPECT_EQ(3u, converted->Length());
563 EXPECT_EQ(100, GetInt(converted, 0));
564 EXPECT_EQ(200, GetInt(converted, 1));
565 EXPECT_EQ(300, GetInt(converted, 2));
566
567 // Getters/setters shouldn't be triggered while accessing existing values.
568 EXPECT_EQ(1, GetInt(result, "getters"));
569 EXPECT_EQ(1, GetInt(result, "setters"));
570
571 // Try again, using an array without the index.
572 base::ListValue one_item_list;
573 one_item_list.Append(new base::FundamentalValue(123456));
574 v8::Local<v8::Array> converted2 =
575 converter.ToV8Value(&one_item_list, context).As<v8::Array>();
576 EXPECT_FALSE(converted2.IsEmpty());
577
578 // Getters/setters shouldn't be triggered during the conversion.
579 EXPECT_EQ(1, GetInt(result, "getters"));
580 EXPECT_EQ(1, GetInt(result, "setters"));
581
582 EXPECT_EQ(1u, converted2->Length());
583 EXPECT_EQ(123456, GetInt(converted2, 0));
584
585 // Accessing missing index 1 triggers the getter.
586 EXPECT_EQ(1337, GetInt(converted2, 1));
587 EXPECT_EQ(2, GetInt(result, "getters"));
588 EXPECT_EQ(1, GetInt(result, "setters"));
589 }
590
427 TEST_F(V8ValueConverterImplTest, StripNullFromObjects) { 591 TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
428 v8::HandleScope handle_scope(isolate_); 592 v8::HandleScope handle_scope(isolate_);
429 v8::Local<v8::Context> context = 593 v8::Local<v8::Context> context =
430 v8::Local<v8::Context>::New(isolate_, context_); 594 v8::Local<v8::Context>::New(isolate_, context_);
431 v8::Context::Scope context_scope(context); 595 v8::Context::Scope context_scope(context);
432 596
433 const char* source = "(function() {" 597 const char* source = "(function() {"
434 "return { foo: undefined, bar: null };" 598 "return { foo: undefined, bar: null };"
435 "})();"; 599 "})();";
436 600
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 EXPECT_TRUE( 1034 EXPECT_TRUE(
871 base::Value::Equals(reference_number_value.get(), number_value.get())); 1035 base::Value::Equals(reference_number_value.get(), number_value.get()));
872 1036
873 v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_)); 1037 v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
874 scoped_ptr<base::Value> undefined_value( 1038 scoped_ptr<base::Value> undefined_value(
875 converter.FromV8Value(undefined, context)); 1039 converter.FromV8Value(undefined, context));
876 EXPECT_FALSE(undefined_value); 1040 EXPECT_FALSE(undefined_value);
877 } 1041 }
878 1042
879 } // namespace content 1043 } // namespace content
OLDNEW
« no previous file with comments | « content/child/v8_value_converter_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698