diff options
Diffstat (limited to 'webkit/plugins/ppapi')
-rw-r--r-- | webkit/plugins/ppapi/v8_var_converter.cc | 423 | ||||
-rw-r--r-- | webkit/plugins/ppapi/v8_var_converter.h | 41 | ||||
-rw-r--r-- | webkit/plugins/ppapi/v8_var_converter_unittest.cc | 349 |
3 files changed, 0 insertions, 813 deletions
diff --git a/webkit/plugins/ppapi/v8_var_converter.cc b/webkit/plugins/ppapi/v8_var_converter.cc deleted file mode 100644 index a8952ff..0000000 --- a/webkit/plugins/ppapi/v8_var_converter.cc +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "webkit/plugins/ppapi/v8_var_converter.h" - -#include <map> -#include <stack> -#include <string> - -#include "base/hash_tables.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "ppapi/shared_impl/array_var.h" -#include "ppapi/shared_impl/dictionary_var.h" -#include "ppapi/shared_impl/var.h" -#include "ppapi/shared_impl/var_tracker.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" -#include "webkit/plugins/ppapi/host_array_buffer_var.h" - -using ppapi::ArrayBufferVar; -using ppapi::ArrayVar; -using ppapi::DictionaryVar; -using ppapi::ScopedPPVar; -using ppapi::StringVar; -using std::make_pair; - -namespace { - -struct HashedHandle { - HashedHandle(v8::Handle<v8::Object> h) : handle(h) {} - size_t hash() const { return handle->GetIdentityHash(); } - bool operator==(const HashedHandle& h) const { return handle == h.handle; } - bool operator<(const HashedHandle& h) const { return hash() < h.hash(); } - v8::Handle<v8::Object> handle; -}; - -} // namespace - -namespace BASE_HASH_NAMESPACE { -#if defined(COMPILER_GCC) -template <> -struct hash<HashedHandle> { - size_t operator()(const HashedHandle& handle) const { - return handle.hash(); - } -}; -#elif defined(COMPILER_MSVC) -inline size_t hash_value(const HashedHandle& handle) { - return handle.hash(); -} -#endif -} // namespace BASE_HASH_NAMESPACE - -namespace webkit { -namespace ppapi { - -namespace { - -// Maps PP_Var IDs to the V8 value handle they correspond to. -typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; - -// Maps V8 value handles to the PP_Var they correspond to. -typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap; - -// Returns a V8 value which corresponds to a given PP_Var. If |var| is a -// reference counted PP_Var type, and it exists in |visited_ids|, the V8 value -// associated with it in the map will be returned, otherwise a new V8 value will -// be created and added to the map. |did_create| indicates whether a new v8 -// value was created as a result of calling the function. -bool GetOrCreateV8Value(const PP_Var& var, - v8::Handle<v8::Value>* result, - bool* did_create, - VarHandleMap* visited_ids) { - *did_create = false; - - if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { - VarHandleMap::iterator it = visited_ids->find(var.value.as_id); - if (it != visited_ids->end()) { - *result = it->second; - return true; - } - } - - switch (var.type) { - case PP_VARTYPE_UNDEFINED: - *result = v8::Undefined(); - break; - case PP_VARTYPE_NULL: - *result = v8::Null(); - break; - case PP_VARTYPE_BOOL: - *result = (var.value.as_bool == PP_TRUE) ? v8::True() : v8::False(); - break; - case PP_VARTYPE_INT32: - *result = v8::Integer::New(var.value.as_int); - break; - case PP_VARTYPE_DOUBLE: - *result = v8::Number::New(var.value.as_double); - break; - case PP_VARTYPE_STRING: { - StringVar* string = StringVar::FromPPVar(var); - if (!string) { - NOTREACHED(); - result->Clear(); - return false; - } - const std::string& value = string->value(); - // Create a string object rather than a string primitive. This allows us - // to have multiple references to the same string in javascript, which - // matches the reference behavior of PP_Vars. - *result = v8::String::New(value.c_str(), value.size())->ToObject(); - break; - } - case PP_VARTYPE_ARRAY_BUFFER: { - ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); - if (!buffer) { - NOTREACHED(); - result->Clear(); - return false; - } - HostArrayBufferVar* host_buffer = - static_cast<HostArrayBufferVar*>(buffer); - *result = - v8::Local<v8::Value>::New(host_buffer->webkit_buffer().toV8Value()); - break; - } - case PP_VARTYPE_ARRAY: - *result = v8::Array::New(); - break; - case PP_VARTYPE_DICTIONARY: - *result = v8::Object::New(); - break; - case PP_VARTYPE_OBJECT: - NOTREACHED(); - result->Clear(); - return false; - } - - *did_create = true; - if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) - (*visited_ids)[var.value.as_id] = *result; - return true; -} - -// For a given V8 value handle, this returns a PP_Var which corresponds to it. -// If the handle already exists in |visited_handles|, the PP_Var associated with -// it will be returned, otherwise a new V8 value will be created and added to -// the map. |did_create| indicates if a new PP_Var was created as a result of -// calling the function. -bool GetOrCreateVar(v8::Handle<v8::Value> val, - PP_Var* result, - bool* did_create, - HandleVarMap* visited_handles) { - CHECK(!val.IsEmpty()); - *did_create = false; - - // Even though every v8 string primitive encountered will be a unique object, - // we still add them to |visited_handles| so that the corresponding string - // PP_Var created will be properly refcounted. - if (val->IsObject() || val->IsString()) { - HandleVarMap::const_iterator it = visited_handles->find( - HashedHandle(val->ToObject())); - if (it != visited_handles->end()) { - *result = it->second.get(); - return true; - } - } - - if (val->IsUndefined()) { - *result = PP_MakeUndefined(); - } else if (val->IsNull()) { - *result = PP_MakeNull(); - } else if (val->IsBoolean() || val->IsBooleanObject()) { - *result = PP_MakeBool(PP_FromBool(val->ToBoolean()->Value())); - } else if (val->IsInt32()) { - *result = PP_MakeInt32(val->ToInt32()->Value()); - } else if (val->IsNumber() || val->IsNumberObject()) { - *result = PP_MakeDouble(val->ToNumber()->Value()); - } else if (val->IsString() || val->IsStringObject()) { - v8::String::Utf8Value utf8(val->ToString()); - *result = StringVar::StringToPPVar(std::string(*utf8, utf8.length())); - } else if (val->IsArray()) { - *result = (new ArrayVar())->GetPPVar(); - } else if (val->IsObject()) { - scoped_ptr<WebKit::WebArrayBuffer> web_array_buffer( - WebKit::WebArrayBuffer::createFromV8Value(val)); - if (web_array_buffer.get()) { - scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar( - *web_array_buffer)); - *result = buffer_var->GetPPVar(); - } else { - *result = (new DictionaryVar())->GetPPVar(); - } - } else { - NOTREACHED(); - return false; - } - - *did_create = true; - if (val->IsObject() || val->IsString()) { - visited_handles->insert(make_pair( - HashedHandle(val->ToObject()), - ScopedPPVar(ScopedPPVar::PassRef(), *result))); - } - return true; -} - -} // namespace - -V8VarConverter::V8VarConverter() { -} - -bool V8VarConverter::ToV8Value(const PP_Var& var, - v8::Handle<v8::Context> context, - v8::Handle<v8::Value>* result) const { - v8::Context::Scope context_scope(context); - v8::HandleScope handle_scope; - - VarHandleMap visited_ids; - - std::stack<PP_Var> stack; - stack.push(var); - v8::Handle<v8::Value> root; - bool is_root = true; - - while (!stack.empty()) { - const PP_Var& current_var = stack.top(); - v8::Handle<v8::Value> current_v8; - stack.pop(); - bool did_create = false; - if (!GetOrCreateV8Value(current_var, ¤t_v8, &did_create, - &visited_ids)) { - return false; - } - - if (is_root) { - is_root = false; - root = current_v8; - } - - // Add child nodes to the stack. - if (current_var.type == PP_VARTYPE_ARRAY) { - ArrayVar* array_var = ArrayVar::FromPPVar(current_var); - if (!array_var) { - NOTREACHED(); - return false; - } - DCHECK(current_v8->IsArray()); - v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); - - for (size_t i = 0; i < array_var->elements().size(); ++i) { - const PP_Var& child_var = array_var->elements()[i].get(); - v8::Handle<v8::Value> child_v8; - if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, - &visited_ids)) { - return false; - } - if (did_create && - (child_var.type == PP_VARTYPE_DICTIONARY || - child_var.type == PP_VARTYPE_ARRAY)) { - stack.push(child_var); - } - v8::TryCatch try_catch; - v8_array->Set(static_cast<uint32>(i), child_v8); - if (try_catch.HasCaught()) { - LOG(ERROR) << "Setter for index " << i << " threw an exception."; - return false; - } - } - } else if (current_var.type == PP_VARTYPE_DICTIONARY) { - DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); - if (!dict_var) { - NOTREACHED(); - return false; - } - DCHECK(current_v8->IsObject()); - v8::Handle<v8::Object> v8_object = current_v8->ToObject(); - - for (DictionaryVar::KeyValueMap::const_iterator iter = - dict_var->key_value_map().begin(); - iter != dict_var->key_value_map().end(); - ++iter) { - const std::string& key = iter->first; - const PP_Var& child_var = iter->second.get(); - v8::Handle<v8::Value> child_v8; - if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, - &visited_ids)) { - return false; - } - if (did_create && - (child_var.type == PP_VARTYPE_DICTIONARY || - child_var.type == PP_VARTYPE_ARRAY)) { - stack.push(child_var); - } - v8::TryCatch try_catch; - v8_object->Set(v8::String::New(key.c_str(), key.length()), child_v8); - if (try_catch.HasCaught()) { - LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " - << "exception."; - return false; - } - } - } - } - - *result = handle_scope.Close(root); - return true; -} - -bool V8VarConverter::FromV8Value(v8::Handle<v8::Value> val, - v8::Handle<v8::Context> context, - PP_Var* result) const { - v8::Context::Scope context_scope(context); - v8::HandleScope handle_scope; - - HandleVarMap visited_handles; - - std::stack<v8::Handle<v8::Value> > stack; - stack.push(val); - ScopedPPVar root; - bool is_root = true; - - while (!stack.empty()) { - v8::Handle<v8::Value> current_v8 = stack.top(); - PP_Var current_var; - stack.pop(); - bool did_create = false; - if (!GetOrCreateVar(current_v8, ¤t_var, &did_create, - &visited_handles)) { - return false; - } - - if (is_root) { - is_root = false; - root = current_var; - } - - // Add child nodes to the stack. - if (current_var.type == PP_VARTYPE_ARRAY) { - DCHECK(current_v8->IsArray()); - v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); - - ArrayVar* array_var = ArrayVar::FromPPVar(current_var); - if (!array_var) { - NOTREACHED(); - return false; - } - - for (uint32 i = 0; i < v8_array->Length(); ++i) { - v8::TryCatch try_catch; - v8::Handle<v8::Value> child_v8 = v8_array->Get(i); - if (try_catch.HasCaught()) - return false; - - if (!v8_array->HasRealIndexedProperty(i)) - continue; - - PP_Var child_var; - if (!GetOrCreateVar(child_v8, &child_var, &did_create, - &visited_handles)) { - // Silently ignore the case where we can't convert to a Var as we may - // be trying to convert a type that doesn't have a corresponding - // PP_Var type. - continue; - } - if (did_create && child_v8->IsObject()) - stack.push(child_v8); - - array_var->Set(i, child_var); - } - } else if (current_var.type == PP_VARTYPE_DICTIONARY) { - DCHECK(current_v8->IsObject()); - v8::Handle<v8::Object> v8_object = current_v8->ToObject(); - - DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); - if (!dict_var) { - NOTREACHED(); - return false; - } - - v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); - for (uint32 i = 0; i < property_names->Length(); ++i) { - v8::Handle<v8::Value> key(property_names->Get(i)); - - // Extend this test to cover more types as necessary and if sensible. - if (!key->IsString() && !key->IsNumber()) { - NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" " - "is neither a string nor a number"; - return false; - } - - // Skip all callbacks: crbug.com/139933 - if (v8_object->HasRealNamedCallbackProperty(key->ToString())) - continue; - - v8::String::Utf8Value name_utf8(key->ToString()); - - v8::TryCatch try_catch; - v8::Handle<v8::Value> child_v8 = v8_object->Get(key); - if (try_catch.HasCaught()) - return false; - - PP_Var child_var; - if (!GetOrCreateVar(child_v8, &child_var, &did_create, - &visited_handles)) { - continue; - } - if (did_create && child_v8->IsObject()) - stack.push(child_v8); - - bool success = dict_var->SetWithStringKey( - std::string(*name_utf8, name_utf8.length()), child_var); - DCHECK(success); - } - } - } - *result = root.Release(); - return true; -} - -} // namespace ppapi -} // namespace webkit diff --git a/webkit/plugins/ppapi/v8_var_converter.h b/webkit/plugins/ppapi/v8_var_converter.h deleted file mode 100644 index c19644c..0000000 --- a/webkit/plugins/ppapi/v8_var_converter.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WEBKIT_PLUGINS_PPAPI_V8_VAR_CONVERTER_H -#define WEBKIT_PLUGINS_PPAPI_V8_VAR_CONVERTER_H - - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ppapi/c/pp_var.h" -#include "v8/include/v8.h" -#include "webkit/plugins/webkit_plugins_export.h" - -namespace webkit { -namespace ppapi { - -// Class to convert between PP_Vars and V8 values. -class WEBKIT_PLUGINS_EXPORT V8VarConverter { - public: - V8VarConverter(); - - // Converts the given PP_Var to a v8::Value. True is returned upon success. - bool ToV8Value(const PP_Var& var, - v8::Handle<v8::Context> context, - v8::Handle<v8::Value>* result) const; - // Converts the given v8::Value to a PP_Var. True is returned upon success. - // Every PP_Var in the reference graph of which |result| is apart will have - // a refcount equal to the number of references to it in the graph. |result| - // will have one additional reference. - bool FromV8Value(v8::Handle<v8::Value> val, - v8::Handle<v8::Context> context, - PP_Var* result) const; - - DISALLOW_COPY_AND_ASSIGN(V8VarConverter); -}; - -} // namespace ppapi -} // namespace webkit - -#endif // WEBKIT_PLUGINS_PPAPI_V8_VAR_CONVERTER_H diff --git a/webkit/plugins/ppapi/v8_var_converter_unittest.cc b/webkit/plugins/ppapi/v8_var_converter_unittest.cc deleted file mode 100644 index c1810df..0000000 --- a/webkit/plugins/ppapi/v8_var_converter_unittest.cc +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "webkit/plugins/ppapi/v8_var_converter.h" - -#include <cmath> - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "ppapi/c/pp_bool.h" -#include "ppapi/c/pp_var.h" -#include "ppapi/shared_impl/array_var.h" -#include "ppapi/shared_impl/dictionary_var.h" -#include "ppapi/shared_impl/ppapi_globals.h" -#include "ppapi/shared_impl/proxy_lock.h" -#include "ppapi/shared_impl/scoped_pp_var.h" -#include "ppapi/shared_impl/test_globals.h" -#include "ppapi/shared_impl/unittest_utils.h" -#include "ppapi/shared_impl/var.h" -#include "ppapi/shared_impl/var_tracker.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "v8/include/v8.h" - -using ppapi::ArrayBufferVar; -using ppapi::ArrayVar; -using ppapi::DictionaryVar; -using ppapi::PpapiGlobals; -using ppapi::ProxyLock; -using ppapi::ScopedPPVar; -using ppapi::StringVar; -using ppapi::TestGlobals; -using ppapi::TestEqual; -using ppapi::VarTracker; - -namespace webkit { -namespace ppapi { - -namespace { - -// Maps PP_Var IDs to the V8 value handle they correspond to. -typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; - -bool Equals(const PP_Var& var, - v8::Handle<v8::Value> val, - VarHandleMap* visited_ids) { - if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { - VarHandleMap::iterator it = visited_ids->find(var.value.as_id); - if (it != visited_ids->end()) - return it->second == val; - (*visited_ids)[var.value.as_id] = val; - } - - if (val->IsUndefined()) { - return var.type == PP_VARTYPE_UNDEFINED; - } else if (val->IsNull()) { - return var.type == PP_VARTYPE_NULL; - } else if (val->IsBoolean() || val->IsBooleanObject()) { - return var.type == PP_VARTYPE_BOOL && - PP_FromBool(val->ToBoolean()->Value()) == var.value.as_bool; - } else if (val->IsInt32()) { - return var.type == PP_VARTYPE_INT32 && - val->ToInt32()->Value() == var.value.as_int; - } else if (val->IsNumber() || val->IsNumberObject()) { - return var.type == PP_VARTYPE_DOUBLE && - fabs(val->ToNumber()->Value() - var.value.as_double) <= 1.0e-4; - } else if (val->IsString() || val->IsStringObject()) { - if (var.type != PP_VARTYPE_STRING) - return false; - StringVar* string_var = StringVar::FromPPVar(var); - DCHECK(string_var); - v8::String::Utf8Value utf8(val->ToString()); - return std::string(*utf8, utf8.length()) == string_var->value(); - } else if (val->IsArray()) { - if (var.type != PP_VARTYPE_ARRAY) - return false; - ArrayVar* array_var = ArrayVar::FromPPVar(var); - DCHECK(array_var); - v8::Handle<v8::Array> v8_array = val.As<v8::Array>(); - if (v8_array->Length() != array_var->elements().size()) - return false; - for (uint32 i = 0; i < v8_array->Length(); ++i) { - v8::Handle<v8::Value> child_v8 = v8_array->Get(i); - if (!Equals(array_var->elements()[i].get(), child_v8, visited_ids)) - return false; - } - return true; - } else if (val->IsObject()) { - if (var.type == PP_VARTYPE_ARRAY_BUFFER) { - // TODO(raymes): Implement this when we have tests for array buffers. - NOTIMPLEMENTED(); - return false; - } else { - v8::Handle<v8::Object> v8_object = val->ToObject(); - if (var.type != PP_VARTYPE_DICTIONARY) - return false; - DictionaryVar* dict_var = DictionaryVar::FromPPVar(var); - DCHECK(dict_var); - v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); - if (property_names->Length() != dict_var->key_value_map().size()) - return false; - for (uint32 i = 0; i < property_names->Length(); ++i) { - v8::Handle<v8::Value> key(property_names->Get(i)); - - if (!key->IsString() && !key->IsNumber()) - return false; - v8::Handle<v8::Value> child_v8 = v8_object->Get(key); - - v8::String::Utf8Value name_utf8(key->ToString()); - ScopedPPVar release_key(ScopedPPVar::PassRef(), - StringVar::StringToPPVar( - std::string(*name_utf8, name_utf8.length()))); - if (!dict_var->HasKey(release_key.get())) - return false; - ScopedPPVar release_value(ScopedPPVar::PassRef(), - dict_var->Get(release_key.get())); - if (!Equals(release_value.get(), child_v8, visited_ids)) - return false; - } - return true; - } - } - return false; -} - -bool Equals(const PP_Var& var, - v8::Handle<v8::Value> val) { - VarHandleMap var_handle_map; - return Equals(var, val, &var_handle_map); -} - -class V8VarConverterTest : public testing::Test { - public: - V8VarConverterTest() {} - ~V8VarConverterTest() {} - - // testing::Test implementation. - virtual void SetUp() { - ProxyLock::Acquire(); - v8::HandleScope handle_scope; - v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); - context_ = v8::Context::New(NULL, global); - } - virtual void TearDown() { - context_.Dispose(context_->GetIsolate()); - ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); - ProxyLock::Release(); - } - - protected: - bool RoundTrip(const PP_Var& var, PP_Var* result) { - V8VarConverter converter; - v8::Context::Scope context_scope(context_); - v8::HandleScope handle_scope; - v8::Handle<v8::Value> v8_result; - if (!converter.ToV8Value(var, context_, &v8_result)) - return false; - if (!Equals(var, v8_result)) - return false; - if (!converter.FromV8Value(v8_result, context_, result)) - return false; - return true; - } - - // Assumes a ref for var. - bool RoundTripAndCompare(const PP_Var& var) { - ScopedPPVar expected(ScopedPPVar::PassRef(), var); - PP_Var actual_var; - if (!RoundTrip(expected.get(), &actual_var)) - return false; - ScopedPPVar actual(ScopedPPVar::PassRef(), actual_var); - return TestEqual(expected.get(), actual.get()); - } - - // Context for the JavaScript in the test. - v8::Persistent<v8::Context> context_; - - private: - TestGlobals globals_; -}; - -} // namespace - -TEST_F(V8VarConverterTest, SimpleRoundTripTest) { - EXPECT_TRUE(RoundTripAndCompare(PP_MakeUndefined())); - EXPECT_TRUE(RoundTripAndCompare(PP_MakeNull())); - EXPECT_TRUE(RoundTripAndCompare(PP_MakeInt32(100))); - EXPECT_TRUE(RoundTripAndCompare(PP_MakeBool(PP_TRUE))); - EXPECT_TRUE(RoundTripAndCompare(PP_MakeDouble(53.75))); -} - -TEST_F(V8VarConverterTest, StringRoundTripTest) { - EXPECT_TRUE(RoundTripAndCompare(StringVar::StringToPPVar(""))); - EXPECT_TRUE(RoundTripAndCompare(StringVar::StringToPPVar("hello world!"))); -} - -TEST_F(V8VarConverterTest, ArrayBufferRoundTripTest) { - // TODO(raymes): Testing this here requires spinning up some of WebKit. - // Work out how to do this. -} - -TEST_F(V8VarConverterTest, DictionaryArrayRoundTripTest) { - // Empty array. - scoped_refptr<ArrayVar> array(new ArrayVar); - ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar()); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - size_t index = 0; - - // Array with primitives. - array->Set(index++, PP_MakeUndefined()); - array->Set(index++, PP_MakeNull()); - array->Set(index++, PP_MakeInt32(100)); - array->Set(index++, PP_MakeBool(PP_FALSE)); - array->Set(index++, PP_MakeDouble(0.123)); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - // Array with 2 references to the same string. - ScopedPPVar release_string( - ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc")); - array->Set(index++, release_string.get()); - array->Set(index++, release_string.get()); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - // Array with nested array that references the same string. - scoped_refptr<ArrayVar> array2(new ArrayVar); - ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar()); - array2->Set(0, release_string.get()); - array->Set(index++, release_array2.get()); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - // Empty dictionary. - scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); - ScopedPPVar release_dictionary(ScopedPPVar::PassRef(), - dictionary->GetPPVar()); - EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); - - // Dictionary with primitives. - dictionary->SetWithStringKey("1", PP_MakeUndefined()); - dictionary->SetWithStringKey("2", PP_MakeNull()); - dictionary->SetWithStringKey("3", PP_MakeInt32(-100)); - dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE)); - dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52)); - EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); - - // Dictionary with 2 references to the same string. - dictionary->SetWithStringKey("6", release_string.get()); - dictionary->SetWithStringKey("7", release_string.get()); - EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); - - // Dictionary with nested dictionary that references the same string. - scoped_refptr<DictionaryVar> dictionary2(new DictionaryVar); - ScopedPPVar release_dictionary2(ScopedPPVar::PassRef(), - dictionary2->GetPPVar()); - dictionary2->SetWithStringKey("abc", release_string.get()); - dictionary->SetWithStringKey("8", release_dictionary2.get()); - EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); - - // Array with dictionary. - array->Set(index++, release_dictionary.get()); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - // Array with dictionary with array. - array2->Set(0, PP_MakeInt32(100)); - dictionary->SetWithStringKey("9", release_array2.get()); - EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); - - // Array <-> dictionary cycle. - dictionary->SetWithStringKey("10", release_array.get()); - PP_Var result_var; - EXPECT_TRUE(RoundTrip(release_dictionary.get(), &result_var)); - ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); - EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get())); - // Break the cycle. - // TODO(raymes): We need some better machinery for releasing vars with - // cycles. Remove the code below once we have that. - dictionary->DeleteWithStringKey("10"); - DictionaryVar* result_dictionary = DictionaryVar::FromPPVar(result.get()); - result_dictionary->DeleteWithStringKey("10"); - - // Array with self references. - array->Set(index, release_array.get()); - EXPECT_TRUE(RoundTrip(release_array.get(), &result_var)); - result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); - EXPECT_TRUE(TestEqual(release_array.get(), result.get())); - // Break the self reference. - array->Set(index, PP_MakeUndefined()); - ArrayVar* result_array = ArrayVar::FromPPVar(result.get()); - result_array->Set(index, PP_MakeUndefined()); -} - -TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { - { - // Test keys with '.'. - scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); - dictionary->SetWithStringKey(".", PP_MakeUndefined()); - dictionary->SetWithStringKey("x.y", PP_MakeUndefined()); - EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); - } - - { - // Test non-string key types. They should be cast to strings. - v8::Context::Scope context_scope(context_); - v8::HandleScope handle_scope; - - const char* source = "(function() {" - "return {" - "1: 'foo'," - "'2': 'bar'," - "true: 'baz'," - "false: 'qux'," - "null: 'quux'," - "undefined: 'oops'" - "};" - "})();"; - - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); - v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); - ASSERT_FALSE(object.IsEmpty()); - - V8VarConverter converter; - PP_Var actual; - ASSERT_TRUE(converter.FromV8Value(object, context_, &actual)); - ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); - - scoped_refptr<DictionaryVar> expected(new DictionaryVar); - ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); - expected->SetWithStringKey("1", foo.get()); - ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); - expected->SetWithStringKey("2", bar.get()); - ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); - expected->SetWithStringKey("true", baz.get()); - ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); - expected->SetWithStringKey("false", qux.get()); - ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); - expected->SetWithStringKey("null", quux.get()); - ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); - expected->SetWithStringKey("undefined", oops.get()); - ScopedPPVar release_expected( - ScopedPPVar::PassRef(), expected->GetPPVar()); - - ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get())); - } -} - -} // namespace ppapi -} // namespace webkit |