v8_value_converter_impl_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/values_test_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/v8_value_converter_impl.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To improve the performance of 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// V8ValueConverterImpl::UpdateAndCheckUniqueness, identity hashes of objects 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// are used during checking for duplicates. For testing purposes we need to 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ignore the hash sometimes. Create this helper object to avoid using identity 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// hashes for the lifetime of the helper. 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ScopedAvoidIdentityHashForTesting { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The hashes will be ignored in |converter|, which must not be NULL and it 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // must outlive the created instance of this helper. 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit ScopedAvoidIdentityHashForTesting( 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::V8ValueConverterImpl* converter); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~ScopedAvoidIdentityHashForTesting(); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::V8ValueConverterImpl* converter_; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedAvoidIdentityHashForTesting); 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedAvoidIdentityHashForTesting::ScopedAvoidIdentityHashForTesting( 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::V8ValueConverterImpl* converter) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : converter_(converter) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(converter_); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) converter_->avoid_identity_hash_for_testing_ = true; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedAvoidIdentityHashForTesting::~ScopedAvoidIdentityHashForTesting() { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) converter_->avoid_identity_hash_for_testing_ = false; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ValueConverterImplTest : public testing::Test { 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) V8ValueConverterImplTest() 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : isolate_(v8::Isolate::GetCurrent()) { 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_.Dispose(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string GetString(base::DictionaryValue* value, const std::string& key) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string temp; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->GetString(key, &temp)) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return temp; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GetString(v8::Handle<v8::Object> value, const std::string& key) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::String> temp = 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->Get(v8::String::New(key.c_str())).As<v8::String>(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (temp.IsEmpty()) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::String::Utf8Value utf8(temp); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(*utf8, utf8.length()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string GetString(base::ListValue* value, uint32 index) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string temp; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->GetString(static_cast<size_t>(index), &temp)) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return temp; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GetString(v8::Handle<v8::Array> value, uint32 index) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::String> temp = value->Get(index).As<v8::String>(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (temp.IsEmpty()) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::String::Utf8Value utf8(temp); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(*utf8, utf8.length()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool IsNull(base::DictionaryValue* value, const std::string& key) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* child = NULL; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->Get(key, &child)) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return child->GetType() == base::Value::TYPE_NULL; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsNull(v8::Handle<v8::Object> value, const std::string& key) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Value> child = value->Get(v8::String::New(key.c_str())); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.IsEmpty()) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child->IsNull(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool IsNull(base::ListValue* value, uint32 index) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* child = NULL; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->Get(static_cast<size_t>(index), &child)) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return child->GetType() == base::Value::TYPE_NULL; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsNull(v8::Handle<v8::Array> value, uint32 index) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Value> child = value->Get(index); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.IsEmpty()) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_FAILURE(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child->IsNull(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TestWeirdType(const V8ValueConverterImpl& converter, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Value> val, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Value::Type expected_type, 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> expected_value) { 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> raw(converter.FromV8Value(val, context)); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (expected_value) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(raw.get()); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(expected_value->Equals(raw.get())); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_type, raw->GetType()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(raw.get()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object(v8::Object::New()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->Set(v8::String::New("test"), val); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> dictionary( 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<base::DictionaryValue*>( 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context))); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(dictionary.get()); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (expected_value) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* temp = NULL; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(dictionary->Get("test", &temp)); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_type, temp->GetType()); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(expected_value->Equals(temp)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(dictionary->HasKey("test")); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> array(v8::Array::New()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array->Set(0, val); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> list( 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<base::ListValue*>(converter.FromV8Value(array, context))); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(list.get()); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (expected_value) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* temp = NULL; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(list->Get(0, &temp)); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_type, temp->GetType()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(expected_value->Equals(temp)); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Arrays should preserve their length, and convert unconvertible 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // types into null. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* temp = NULL; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(list->Get(0, &temp)); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(base::Value::TYPE_NULL, temp->GetType()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Isolate* isolate_; 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Context for the JavaScript in the test. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Persistent<v8::Context> context_; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, BasicRoundTrip) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> original_root = base::test::ParseJson( 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{ \n" 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"null\": null, \n" 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"true\": true, \n" 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"false\": false, \n" 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"positive-int\": 42, \n" 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"negative-int\": -42, \n" 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"zero\": 0, \n" 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"double\": 88.8, \n" 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"big-integral-double\": 9007199254740992.0, \n" // 2.0^53 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"string\": \"foobar\", \n" 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"empty-string\": \"\", \n" 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"dictionary\": { \n" 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"foo\": \"bar\",\n" 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"hot\": \"dog\",\n" 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " }, \n" 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"empty-dictionary\": {}, \n" 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"list\": [ \"monkey\", \"balls\" ], \n" 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"empty-list\": [], \n" 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "}"); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> v8_object = 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.ToV8Value(original_root.get(), context).As<v8::Object>(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(v8_object.IsEmpty()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(static_cast<const base::DictionaryValue&>(*original_root).size(), 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8_object->GetPropertyNames()->Length()); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("null"))->IsNull()); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("true"))->IsTrue()); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("false"))->IsFalse()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("positive-int"))->IsInt32()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("negative-int"))->IsInt32()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("zero"))->IsInt32()); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("double"))->IsNumber()); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE( 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8_object->Get(v8::String::New("big-integral-double"))->IsNumber()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("string"))->IsString()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("empty-string"))->IsString()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("dictionary"))->IsObject()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("empty-dictionary"))->IsObject()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("list"))->IsArray()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(v8_object->Get(v8::String::New("empty-list"))->IsArray()); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context)); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_NE(original_root.get(), new_root.get()); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(original_root->Equals(new_root.get())); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, KeysWithDots) { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> original = 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::test::ParseJson("{ \"foo.bar\": \"baz\" }"); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> copy( 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) converter.FromV8Value( 263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.ToV8Value(original.get(), context), context)); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(original->Equals(copy.get())); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectExceptions) { 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up objects to throw when reading or writing 'foo'. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Object.prototype.__defineSetter__('foo', " 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " function() { throw new Error('muah!'); });" 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Object.prototype.__defineGetter__('foo', " 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " function() { throw new Error('muah!'); });"; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) script->Run(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object(v8::Object::New()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->Set(v8::String::New("bar"), v8::String::New("bar")); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converting from v8 value should replace the foo property with null. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> converted( 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<base::DictionaryValue*>( 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context))); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(converted.get()); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/v8/issues/detail?id=1342 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EXPECT_EQ(2u, converted->size()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EXPECT_TRUE(IsNull(converted.get(), "foo")); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, converted->size()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("bar", GetString(converted.get(), "bar")); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converting to v8 value should drop the foo property. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) converted->SetString("foo", "foo"); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> copy = 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.ToV8Value(converted.get(), context).As<v8::Object>(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(copy.IsEmpty()); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, copy->GetPropertyNames()->Length()); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("bar", GetString(copy, "bar")); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayExceptions) { 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "var arr = [];" 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "arr.__defineSetter__(0, " 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " function() { throw new Error('muah!'); });" 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "arr.__defineGetter__(0, " 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " function() { throw new Error('muah!'); });" 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "arr[1] = 'bar';" 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return arr;" 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> array = script->Run().As<v8::Array>(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(array.IsEmpty()); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converting from v8 value should replace the first item with null. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>( 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(array, context))); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(converted.get()); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/v8/issues/detail?id=1342 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, converted->GetSize()); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(IsNull(converted.get(), 0)); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converting to v8 value should drop the first item and leave a hole. 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) converted.reset(static_cast<base::ListValue*>( 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::test::ParseJson("[ \"foo\", \"bar\" ]").release())); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> copy = 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.ToV8Value(converted.get(), context).As<v8::Array>(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(copy.IsEmpty()); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, copy->Length()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("bar", GetString(copy, 1)); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdTypes) { 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::RegExp> regex( 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::RegExp::New(v8::String::New("."), v8::RegExp::kNone)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestWeirdType(converter, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Undefined(), 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value::TYPE_NULL, // Arbitrary type, result is NULL. 3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::Value>()); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestWeirdType(converter, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Date::New(1000), 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value::TYPE_DICTIONARY, 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value>(new base::DictionaryValue())); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestWeirdType(converter, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) regex, 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value::TYPE_DICTIONARY, 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value>(new base::DictionaryValue())); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) converter.SetDateAllowed(true); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestWeirdType(converter, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Date::New(1000), 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value::TYPE_DOUBLE, 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value>(new base::FundamentalValue(1.0))); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) converter.SetRegExpAllowed(true); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestWeirdType(converter, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) regex, 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value::TYPE_STRING, 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value>(new base::StringValue("/./"))); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, Prototype) { 382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Object.prototype.foo = 'foo';" 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return {};" 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(object.IsEmpty()); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result( 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<base::DictionaryValue*>( 399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context))); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result.get()); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, result->size()); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, StripNullFromObjects) { 405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return { foo: undefined, bar: null };" 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(object.IsEmpty()); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) converter.SetStripNullFromObjects(true); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result( 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<base::DictionaryValue*>( 423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context))); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result.get()); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, result->size()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, RecursiveObjects) { 429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object = v8::Object::New().As<v8::Object>(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(object.IsEmpty()); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->Set(v8::String::New("foo"), v8::String::New("bar")); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->Set(v8::String::New("obj"), object); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> object_result( 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<base::DictionaryValue*>( 443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context))); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(object_result.get()); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, object_result->size()); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(IsNull(object_result.get(), "obj")); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> array = v8::Array::New().As<v8::Array>(); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(array.IsEmpty()); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array->Set(0, v8::String::New("1")); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array->Set(1, array); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> list_result( 454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<base::ListValue*>(converter.FromV8Value(array, context))); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(list_result.get()); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, list_result->GetSize()); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(IsNull(list_result.get(), 1)); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdProperties) { 461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return {" 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "1: 'foo'," 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'2': 'bar'," 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "true: 'baz'," 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "false: 'qux'," 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "null: 'quux'," 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "undefined: 'oops'" 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "};" 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(object.IsEmpty()); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> actual(converter.FromV8Value(object, context)); 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> expected = base::test::ParseJson( 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{ \n" 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"1\": \"foo\", \n" 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"2\": \"bar\", \n" 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"true\": \"baz\", \n" 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"false\": \"qux\", \n" 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"null\": \"quux\", \n" 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " \"undefined\": \"oops\", \n" 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "}"); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(expected->Equals(actual.get())); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayGetters) { 498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "var a = [0];" 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "a.__defineGetter__(1, function() { return 'bar'; });" 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return a;" 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> array = script->Run().As<v8::Array>(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(array.IsEmpty()); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> result( 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<base::ListValue*>(converter.FromV8Value(array, context))); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result.get()); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2u, result->GetSize()); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) { 521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Object> object; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return { foo: undefined, bar: null, baz: function(){} };" 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object = script->Run().As<v8::Object>(); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(object.IsEmpty()); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Array> array; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* source = "(function() {" 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "return [ undefined, null, function(){} ];" 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "})();"; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array = script->Run().As<v8::Array>(); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(array.IsEmpty()); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) V8ValueConverterImpl converter; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> actual_object( 549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(object, context)); 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(base::Value::Equals( 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get())); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Everything is null because JSON stringification preserves array length. 554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<Value> actual_array(converter.FromV8Value(array, context)); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(base::Value::Equals( 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::test::ParseJson("[ null, null, null ]").get(), actual_array.get())); 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { 560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) V8ValueConverterImpl converter; 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We check that the converter checks identity correctly by disabling the 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // optimization of using identity hashes. 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter); 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the v8::Object to be converted. 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Array> root(v8::Array::New(4)); 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root->Set(0, v8::Handle<v8::Object>(v8::Object::New())); 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root->Set(1, v8::Handle<v8::Object>(v8::Object::New())); 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root->Set(2, v8::Handle<v8::Object>(v8::Array::New(0))); 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root->Set(3, v8::Handle<v8::Object>(v8::Array::New(0))); 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The expected base::Value result. 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]"); 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(expected.get()); 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The actual result. 582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> value(converter.FromV8Value(root, context)); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(value.get()); 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(expected->Equals(value.get())); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, DetectCycles) { 589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) V8ValueConverterImpl converter; 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a recursive array. 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Array> recursive_array(v8::Array::New(1)); 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recursive_array->Set(0, recursive_array); 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The first repetition should be trimmed and replaced by a null value. 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ListValue expected_list; 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expected_list.Append(base::Value::CreateNullValue()); 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The actual result. 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> actual_list( 605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(recursive_array, context)); 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(actual_list.get()); 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(expected_list.Equals(actual_list.get())); 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now create a recursive object 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string key("key"); 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::Handle<v8::Object> recursive_object(v8::Object::New()); 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v8::TryCatch try_catch; 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recursive_object->Set(v8::String::New(key.c_str(), key.length()), 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recursive_object); 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(try_catch.HasCaught()); 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The first repetition should be trimmed and replaced by a null value. 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue expected_dictionary; 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expected_dictionary.Set(key, base::Value::CreateNullValue()); 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The actual result. 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> actual_dictionary( 624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) converter.FromV8Value(recursive_object, context)); 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(actual_dictionary.get()); 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get())); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) { 631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::HandleScope handle_scope(isolate_); 632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Context::Scope context_scope(isolate_, context_); 633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context> context = 634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Context>::New(isolate_, context_); 635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc. 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int kDepth = 1000; 638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const char kKey[] = "key"; 639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Object> deep_object = v8::Object::New(); 641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Object> leaf = deep_object; 643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int i = 0; i < kDepth; ++i) { 644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Local<v8::Object> new_object = v8::Object::New(); 645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leaf->Set(v8::String::New(kKey), new_object); 646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leaf = new_object; 647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) V8ValueConverterImpl converter; 650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> value(converter.FromV8Value(deep_object, context)); 651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(value); 652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc. 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int kExpectedDepth = 100; 655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Value* current = value.get(); 657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int i = 1; i < kExpectedDepth; ++i) { 658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::DictionaryValue* current_as_object = NULL; 659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(current->GetAsDictionary(¤t_as_object)) << i; 660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(current_as_object->Get(kKey, ¤t)) << i; 661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The leaf node shouldn't have any properties. 664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::DictionaryValue empty; 665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(Value::Equals(&empty, current)) << *current; 666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 669