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_);
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_.Reset();
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 =
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()))
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            .As<v8::String>();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp.IsEmpty()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::String::Utf8Value utf8(temp);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string(*utf8, utf8.length());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string GetString(base::ListValue* value, uint32 index) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string temp;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->GetString(static_cast<size_t>(index), &temp)) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetString(v8::Handle<v8::Array> value, uint32 index) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::String> temp = value->Get(index).As<v8::String>();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp.IsEmpty()) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::String::Utf8Value utf8(temp);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string(*utf8, utf8.length());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsNull(base::DictionaryValue* value, const std::string& key) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* child = NULL;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->Get(key, &child)) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return child->GetType() == base::Value::TYPE_NULL;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsNull(v8::Handle<v8::Object> value, const std::string& key) {
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Handle<v8::Value> child =
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child.IsEmpty()) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child->IsNull();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsNull(base::ListValue* value, uint32 index) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* child = NULL;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->Get(static_cast<size_t>(index), &child)) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return child->GetType() == base::Value::TYPE_NULL;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsNull(v8::Handle<v8::Array> value, uint32 index) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Value> child = value->Get(index);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child.IsEmpty()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child->IsNull();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestWeirdType(const V8ValueConverterImpl& converter,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     v8::Handle<v8::Value> val,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Value::Type expected_type,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_ptr<base::Value> expected_value) {
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    v8::Local<v8::Context> context =
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, context_);
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<base::Value> raw(converter.FromV8Value(val, context));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(raw.get());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(raw.get()));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, raw->GetType());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(raw.get());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Handle<v8::Object> object(v8::Object::New(isolate_));
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    object->Set(v8::String::NewFromUtf8(isolate_, "test"), val);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> dictionary(
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<base::DictionaryValue*>(
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            converter.FromV8Value(object, context)));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(dictionary.get());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(dictionary->Get("test", &temp));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, temp->GetType());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(temp));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(dictionary->HasKey("test"));
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Handle<v8::Array> array(v8::Array::New(isolate_));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array->Set(0, val);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::ListValue> list(
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(list.get());
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(list->Get(0, &temp));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, temp->GetType());
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(temp));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Arrays should preserve their length, and convert unconvertible
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // types into null.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(list->Get(0, &temp));
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(base::Value::TYPE_NULL, temp->GetType());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Isolate* isolate_;
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Context for the JavaScript in the test.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::Context> context_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> original_root = base::test::ParseJson(
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{ \n"
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"null\": null, \n"
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"true\": true, \n"
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"false\": false, \n"
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"positive-int\": 42, \n"
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"negative-int\": -42, \n"
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"zero\": 0, \n"
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"double\": 88.8, \n"
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"big-integral-double\": 9007199254740992.0, \n"  // 2.0^53
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"string\": \"foobar\", \n"
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-string\": \"\", \n"
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"dictionary\": { \n"
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    \"foo\": \"bar\",\n"
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    \"hot\": \"dog\",\n"
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  }, \n"
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-dictionary\": {}, \n"
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"list\": [ \"monkey\", \"balls\" ], \n"
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-list\": [], \n"
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}");
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> v8_object =
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(original_root.get(), context).As<v8::Object>();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(v8_object.IsEmpty());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(static_cast<const base::DictionaryValue&>(*original_root).size(),
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            v8_object->GetPropertyNames()->Length());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "null"))->IsNull());
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "true"))->IsTrue());
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "false"))->IsFalse());
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "positive-int"))
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  ->IsInt32());
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "negative-int"))
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  ->IsInt32());
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "zero"))->IsInt32());
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "double"))->IsNumber());
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 isolate_, "big-integral-double"))->IsNumber());
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "string"))->IsString());
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-string"))
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  ->IsString());
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "dictionary"))
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  ->IsObject());
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 isolate_, "empty-dictionary"))->IsObject());
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8_object->Get(v8::String::NewFromUtf8(isolate_, "list"))->IsArray());
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-list"))
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  ->IsArray());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context));
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(original_root.get(), new_root.get());
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(original_root->Equals(new_root.get()));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, KeysWithDots) {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> original =
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("{ \"foo.bar\": \"baz\" }");
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> copy(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converter.FromV8Value(
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.ToV8Value(original.get(), context), context));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(original->Equals(copy.get()));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up objects to throw when reading or writing 'foo'.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source =
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.__defineSetter__('foo', "
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.__defineGetter__('foo', "
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });";
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script->Run();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Object> object(v8::Object::New(isolate_));
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  object->Set(v8::String::NewFromUtf8(isolate_, "bar"),
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              v8::String::NewFromUtf8(isolate_, "bar"));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting from v8 value should replace the foo property with null.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> converted(
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(converted.get());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/v8/issues/detail?id=1342
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(2u, converted->size());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_TRUE(IsNull(converted.get(), "foo"));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, converted->size());
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(converted.get(), "bar"));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting to v8 value should drop the foo property.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converted->SetString("foo", "foo");
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> copy =
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(converted.get(), context).As<v8::Object>();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(copy.IsEmpty());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, copy->GetPropertyNames()->Length());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(copy, "bar"));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "var arr = [];"
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr.__defineSetter__(0, "
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr.__defineGetter__(0, "
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr[1] = 'bar';"
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return arr;"
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting from v8 value should replace the first item with null.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>(
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(array, context)));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(converted.get());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/v8/issues/detail?id=1342
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, converted->GetSize());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(converted.get(), 0));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting to v8 value should drop the first item and leave a hole.
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converted.reset(static_cast<base::ListValue*>(
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("[ \"foo\", \"bar\" ]").release()));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> copy =
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(converted.get(), context).As<v8::Array>();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(copy.IsEmpty());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, copy->Length());
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(copy, 1));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdTypes) {
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Local<v8::Context> context =
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::RegExp> regex(v8::RegExp::New(
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8::String::NewFromUtf8(isolate_, "."), v8::RegExp::kNone));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                v8::Undefined(isolate_),
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_NULL,  // Arbitrary type, result is NULL.
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                scoped_ptr<base::Value>());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                v8::Date::New(isolate_, 1000),
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DICTIONARY,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::DictionaryValue()));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                regex,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DICTIONARY,
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::DictionaryValue()));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetDateAllowed(true);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                v8::Date::New(isolate_, 1000),
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DOUBLE,
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::FundamentalValue(1.0)));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetRegExpAllowed(true);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                regex,
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_STRING,
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::StringValue("/./")));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, Prototype) {
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.foo = 'foo';"
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return {};"
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result(
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, result->size());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return { foo: undefined, bar: null };"
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetStripNullFromObjects(true);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, result->size());
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Object> object = v8::Object::New(isolate_).As<v8::Object>();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  object->Set(v8::String::NewFromUtf8(isolate_, "foo"),
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              v8::String::NewFromUtf8(isolate_, "bar"));
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> object_result(
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_result.get());
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, object_result->size());
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(object_result.get(), "obj"));
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Array> array = v8::Array::New(isolate_).As<v8::Array>();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  array->Set(0, v8::String::NewFromUtf8(isolate_, "1"));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  array->Set(1, array);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> list_result(
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(list_result.get());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, list_result->GetSize());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(list_result.get(), 1));
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdProperties) {
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return {"
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "1: 'foo',"
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "'2': 'bar',"
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "true: 'baz',"
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "false: 'qux',"
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "null: 'quux',"
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "undefined: 'oops'"
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "};"
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> actual(converter.FromV8Value(object, context));
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> expected = base::test::ParseJson(
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{ \n"
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"1\": \"foo\", \n"
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"2\": \"bar\", \n"
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"true\": \"baz\", \n"
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"false\": \"qux\", \n"
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"null\": \"quux\", \n"
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"undefined\": \"oops\", \n"
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}");
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected->Equals(actual.get()));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayGetters) {
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "var a = [0];"
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "a.__defineGetter__(1, function() { return 'bar'; });"
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return a;"
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Script> script(
534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> result(
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, result->GetSize());
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* source = "(function() {"
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "return { foo: undefined, bar: null, baz: function(){} };"
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "})();";
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Handle<v8::Script> script(
557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object = script->Run().As<v8::Object>();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(object.IsEmpty());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* source = "(function() {"
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "return [ undefined, null, function(){} ];"
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "})();";
567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Handle<v8::Script> script(
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = script->Run().As<v8::Array>();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(array.IsEmpty());
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  v8::Handle<v8::Array> sparse_array;
5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  {
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const char* source = "(function() {"
5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        "return new Array(3);"
5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        "})();";
5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    v8::Handle<v8::Script> script(
5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    sparse_array = script->Run().As<v8::Array>();
5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ASSERT_FALSE(sparse_array.IsEmpty());
5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
5830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_object(
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(object, context));
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::Value::Equals(
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get()));
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Everything is null because JSON stringification preserves array length.
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> actual_array(converter.FromV8Value(array, context));
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::Value::Equals(
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("[ null, null, null ]").get(), actual_array.get()));
5950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<base::Value> actual_sparse_array(
5970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      converter.FromV8Value(sparse_array, context));
5980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_TRUE(
5990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      base::Value::Equals(base::test::ParseJson("[ null, null, null ]").get(),
6000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                          actual_sparse_array.get()));
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  V8ValueConverterImpl converter;
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We check that the converter checks identity correctly by disabling the
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // optimization of using identity hashes.
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the v8::Object to be converted.
615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Array> root(v8::Array::New(isolate_, 4));
616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  root->Set(0, v8::Handle<v8::Object>(v8::Object::New(isolate_)));
617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  root->Set(1, v8::Handle<v8::Object>(v8::Object::New(isolate_)));
618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  root->Set(2, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0)));
619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  root->Set(3, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0)));
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The expected base::Value result.
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]");
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(expected.get());
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> value(converter.FromV8Value(root, context));
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(value.get());
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected->Equals(value.get()));
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, DetectCycles) {
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  V8ValueConverterImpl converter;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a recursive array.
640a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Handle<v8::Array> recursive_array(v8::Array::New(isolate_, 1));
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recursive_array->Set(0, recursive_array);
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first repetition should be trimmed and replaced by a null value.
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue expected_list;
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_list.Append(base::Value::CreateNullValue());
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_list(
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(recursive_array, context));
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(actual_list.get());
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected_list.Equals(actual_list.get()));
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now create a recursive object
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string key("key");
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Object> recursive_object(v8::Object::New(isolate_));
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::TryCatch try_catch;
658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  recursive_object->Set(
659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8::String::NewFromUtf8(
660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          isolate_, key.c_str(), v8::String::kNormalString, key.length()),
661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      recursive_object);
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(try_catch.HasCaught());
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first repetition should be trimmed and replaced by a null value.
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue expected_dictionary;
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_dictionary.Set(key, base::Value::CreateNullValue());
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_dictionary(
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(recursive_object, context));
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(actual_dictionary.get());
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get()));
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v8::Context::Scope context_scope(context);
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc.
683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int kDepth = 1000;
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char kKey[] = "key";
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Local<v8::Object> deep_object = v8::Object::New(isolate_);
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Object> leaf = deep_object;
689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < kDepth; ++i) {
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Local<v8::Object> new_object = v8::Object::New(isolate_);
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    leaf->Set(v8::String::NewFromUtf8(isolate_, kKey), new_object);
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    leaf = new_object;
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  V8ValueConverterImpl converter;
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> value(converter.FromV8Value(deep_object, context));
697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(value);
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc.
700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int kExpectedDepth = 100;
701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::Value* current = value.get();
703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 1; i < kExpectedDepth; ++i) {
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::DictionaryValue* current_as_object = NULL;
705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_TRUE(current->GetAsDictionary(&current_as_object)) << i;
706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_TRUE(current_as_object->Get(kKey, &current)) << i;
707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The leaf node shouldn't have any properties.
710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::DictionaryValue empty;
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(base::Value::Equals(&empty, current)) << *current;
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass V8ValueConverterOverridingStrategyForTesting
7155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public V8ValueConverter::Strategy {
7165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
7175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  V8ValueConverterOverridingStrategyForTesting()
7185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : reference_value_(NewReferenceValue()) {}
7195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Object(
7205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Handle<v8::Object> value,
7215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value** out,
7225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Isolate* isolate,
7235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const FromV8ValueCallback& callback) const OVERRIDE {
7245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *out = NewReferenceValue();
7255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Array(v8::Handle<v8::Array> value,
7285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           base::Value** out,
7295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           v8::Isolate* isolate,
7305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           const FromV8ValueCallback& callback) const OVERRIDE {
7315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *out = NewReferenceValue();
7325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 base::Value** out,
736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 v8::Isolate* isolate) const OVERRIDE {
7375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *out = NewReferenceValue();
7385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Number(v8::Handle<v8::Number> value,
7415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            base::Value** out) const OVERRIDE {
7425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *out = NewReferenceValue();
7435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Undefined(base::Value** out) const OVERRIDE {
7465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *out = NewReferenceValue();
7475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::Value* reference_value() const { return reference_value_.get(); }
7505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
7525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static base::Value* NewReferenceValue() {
7535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return new base::StringValue("strategy");
7545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> reference_value_;
7565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
7575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(V8ValueConverterImplTest, StrategyOverrides) {
7595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::HandleScope handle_scope(isolate_);
7605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Local<v8::Context> context =
7615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Local<v8::Context>::New(isolate_, context_);
7625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Context::Scope context_scope(context);
7635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  V8ValueConverterImpl converter;
7655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  V8ValueConverterOverridingStrategyForTesting strategy;
7665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  converter.SetStrategy(&strategy);
7675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Object> object(v8::Object::New(isolate_));
7695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> object_value(converter.FromV8Value(object, context));
7705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(object_value);
7715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
7725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(strategy.reference_value(), object_value.get()));
7735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Array> array(v8::Array::New(isolate_));
7755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> array_value(converter.FromV8Value(array, context));
7765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(array_value);
7775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
7785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(strategy.reference_value(), array_value.get()));
7795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::ArrayBuffer> array_buffer(v8::ArrayBuffer::New(isolate_, 0));
7815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> array_buffer_value(
7825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      converter.FromV8Value(array_buffer, context));
7835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(array_buffer_value);
7845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(base::Value::Equals(strategy.reference_value(),
7855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  array_buffer_value.get()));
7865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::ArrayBufferView> array_buffer_view(
7885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Uint8Array::New(array_buffer, 0, 0));
7895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> array_buffer_view_value(
7905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      converter.FromV8Value(array_buffer_view, context));
7915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(array_buffer_view_value);
7925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(base::Value::Equals(strategy.reference_value(),
7935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  array_buffer_view_value.get()));
7945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Number> number(v8::Number::New(isolate_, 0.0));
7965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> number_value(converter.FromV8Value(number, context));
7975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(number_value);
7985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
7995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(strategy.reference_value(), number_value.get()));
8005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Primitive> undefined(v8::Undefined(isolate_));
8025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> undefined_value(
8035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      converter.FromV8Value(undefined, context));
8045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(undefined_value);
8055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
8065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(strategy.reference_value(), undefined_value.get()));
8075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
8085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass V8ValueConverterBypassStrategyForTesting
8105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public V8ValueConverter::Strategy {
8115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
8125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Object(
8135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Handle<v8::Object> value,
8145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value** out,
8155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Isolate* isolate,
8165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const FromV8ValueCallback& callback) const OVERRIDE {
8175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Array(v8::Handle<v8::Array> value,
8205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           base::Value** out,
8215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           v8::Isolate* isolate,
8225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           const FromV8ValueCallback& callback) const OVERRIDE {
8235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
826cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 base::Value** out,
827cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 v8::Isolate* isolate) const OVERRIDE {
8285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Number(v8::Handle<v8::Number> value,
8315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            base::Value** out) const OVERRIDE {
8325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool FromV8Undefined(base::Value** out) const OVERRIDE {
8355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
8385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Verify that having a strategy that fallbacks to default behaviour
8405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// actually preserves it.
8415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(V8ValueConverterImplTest, StrategyBypass) {
8425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::HandleScope handle_scope(isolate_);
8435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Local<v8::Context> context =
8445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      v8::Local<v8::Context>::New(isolate_, context_);
8455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Context::Scope context_scope(context);
8465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  V8ValueConverterImpl converter;
8485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  V8ValueConverterBypassStrategyForTesting strategy;
8495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  converter.SetStrategy(&strategy);
8505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Object> object(v8::Object::New(isolate_));
8525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> object_value(converter.FromV8Value(object, context));
8535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(object_value);
8545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> reference_object_value(base::test::ParseJson("{}"));
8555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
8565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(reference_object_value.get(), object_value.get()));
8575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Array> array(v8::Array::New(isolate_));
8595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> array_value(converter.FromV8Value(array, context));
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(array_value);
8615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> reference_array_value(base::test::ParseJson("[]"));
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
8635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(reference_array_value.get(), array_value.get()));
8645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Not testing ArrayBuffers as V8ValueConverter uses blink helpers and
8665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // this requires having blink to be initialized.
8675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Number> number(v8::Number::New(isolate_, 0.0));
8695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> number_value(converter.FromV8Value(number, context));
8705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(number_value);
8715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> reference_number_value(base::test::ParseJson("0"));
8725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(
8735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Value::Equals(reference_number_value.get(), number_value.get()));
8745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  v8::Handle<v8::Primitive> undefined(v8::Undefined(isolate_));
8765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::Value> undefined_value(
8775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      converter.FromV8Value(undefined, context));
8785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(undefined_value);
8795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
8805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
882