summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryoichio@chromium.org <yoichio@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-14 07:55:16 +0000
committeryoichio@chromium.org <yoichio@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-14 07:55:16 +0000
commita386ef44352c398148a5b3ea438f9f4605aa2290 (patch)
treeb296b6fac2d642fe6cfcf1f0e93f8007b189cfd4
parent4df437dc0ae4a1600dfa93e519d7f7528a4d8a78 (diff)
downloadchromium_src-a386ef44352c398148a5b3ea438f9f4605aa2290.zip
chromium_src-a386ef44352c398148a5b3ea438f9f4605aa2290.tar.gz
chromium_src-a386ef44352c398148a5b3ea438f9f4605aa2290.tar.bz2
Revert 199938 "This implements a converter for transforming betw..."
> This implements a converter for transforming between V8 values and PP_Vars. This is needed to support transferring arrays/dictionaries (or arrays/objects in javascript) to and from the plugin using the pepper Post/HandleMessage APIs. The entire object graph is converted in the process. > > TBR=darin@chromium.org > > BUG=236958 > > Review URL: https://chromiumcodereview.appspot.com/14424006 TBR=raymes@chromium.org Review URL: https://codereview.chromium.org/15158002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199944 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/content_tests.gypi1
-rw-r--r--ppapi/ppapi_tests.gypi2
-rw-r--r--ppapi/proxy/raw_var_data_unittest.cc156
-rw-r--r--ppapi/shared_impl/unittest_utils.cc166
-rw-r--r--ppapi/shared_impl/unittest_utils.h19
-rw-r--r--webkit/glue/webkit_glue.gypi2
-rw-r--r--webkit/plugins/ppapi/v8_var_converter.cc423
-rw-r--r--webkit/plugins/ppapi/v8_var_converter.h41
-rw-r--r--webkit/plugins/ppapi/v8_var_converter_unittest.cc349
9 files changed, 152 insertions, 1007 deletions
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 252a232..642bc28 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -528,7 +528,6 @@
'../webkit/plugins/ppapi/ppapi_unittest.cc',
'../webkit/plugins/ppapi/ppapi_unittest.h',
'../webkit/plugins/ppapi/quota_file_io_unittest.cc',
- '../webkit/plugins/ppapi/v8_var_converter_unittest.cc',
'../webkit/quota/mock_quota_manager.cc',
'../webkit/quota/mock_quota_manager.h',
'../webkit/quota/mock_quota_manager_unittest.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index 3e5dbf1..ffd577f 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -101,8 +101,6 @@
'proxy/resource_message_test_sink.h',
'shared_impl/test_globals.cc',
'shared_impl/test_globals.h',
- 'shared_impl/unittest_utils.cc',
- 'shared_impl/unittest_utils.h',
],
},
diff --git a/ppapi/proxy/raw_var_data_unittest.cc b/ppapi/proxy/raw_var_data_unittest.cc
index 2b134af..8a00d21 100644
--- a/ppapi/proxy/raw_var_data_unittest.cc
+++ b/ppapi/proxy/raw_var_data_unittest.cc
@@ -4,6 +4,8 @@
#include "ppapi/proxy/raw_var_data.h"
+#include <cmath>
+
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -16,7 +18,6 @@
#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"
@@ -44,6 +45,153 @@ class RawVarDataTest : public testing::Test {
TestGlobals globals_;
};
+// Compares two vars for equality. When two vars are found to be equal, an entry
+// is inserted into |visited_map| with (expected id, actual id). When comparing
+// two PP_Vars that have a graph of references, this avoids following reference
+// cycles. It also ensures that a var with ID x in the graph is always equal
+// to a var with ID y. This guarantees that the topology of the two graphs
+// being compared is identical.
+bool Equals(const PP_Var& expected,
+ const PP_Var& actual,
+ base::hash_map<int64_t, int64_t>* visited_map) {
+ if (expected.type != actual.type) {
+ LOG(ERROR) << "expected type: " << expected.type <<
+ " actual type: " << actual.type;
+ return false;
+ }
+ if (VarTracker::IsVarTypeRefcounted(expected.type)) {
+ base::hash_map<int64_t, int64_t>::iterator it =
+ visited_map->find(expected.value.as_id);
+ if (it != visited_map->end()) {
+ if (it->second != actual.value.as_id) {
+ LOG(ERROR) << "expected id: " << it->second << " actual id: " <<
+ actual.value.as_id;
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ (*visited_map)[expected.value.as_id] = actual.value.as_id;
+ }
+ }
+ switch (expected.type) {
+ case PP_VARTYPE_UNDEFINED:
+ return true;
+ case PP_VARTYPE_NULL:
+ return true;
+ case PP_VARTYPE_BOOL:
+ if (expected.value.as_bool != actual.value.as_bool) {
+ LOG(ERROR) << "expected: " << expected.value.as_bool << " actual: " <<
+ actual.value.as_bool;
+ return false;
+ }
+ return true;
+ case PP_VARTYPE_INT32:
+ if (expected.value.as_int != actual.value.as_int) {
+ LOG(ERROR) << "expected: " << expected.value.as_int << " actual: " <<
+ actual.value.as_int;
+ return false;
+ }
+ return true;
+ case PP_VARTYPE_DOUBLE:
+ if (fabs(expected.value.as_double - actual.value.as_double) > 1.0e-4) {
+ LOG(ERROR) << "expected: " << expected.value.as_double <<
+ " actual: " << actual.value.as_double;
+ return false;
+ }
+ return true;
+ case PP_VARTYPE_OBJECT:
+ if (expected.value.as_id != actual.value.as_id) {
+ LOG(ERROR) << "expected: " << expected.value.as_id << " actual: " <<
+ actual.value.as_id;
+ return false;
+ }
+ return true;
+ case PP_VARTYPE_STRING: {
+ StringVar* expected_var = StringVar::FromPPVar(expected);
+ StringVar* actual_var = StringVar::FromPPVar(actual);
+ DCHECK(expected_var && actual_var);
+ if (expected_var->value() != actual_var->value()) {
+ LOG(ERROR) << "expected: " << expected_var->value() << " actual: " <<
+ actual_var->value();
+ return false;
+ }
+ return true;
+ }
+ case PP_VARTYPE_ARRAY_BUFFER: {
+ ArrayBufferVar* expected_var = ArrayBufferVar::FromPPVar(expected);
+ ArrayBufferVar* actual_var = ArrayBufferVar::FromPPVar(actual);
+ DCHECK(expected_var && actual_var);
+ if (expected_var->ByteLength() != actual_var->ByteLength()) {
+ LOG(ERROR) << "expected: " << expected_var->ByteLength() <<
+ " actual: " << actual_var->ByteLength();
+ return false;
+ }
+ if (memcmp(expected_var->Map(), actual_var->Map(),
+ expected_var->ByteLength()) != 0) {
+ LOG(ERROR) << "expected array buffer does not match actual.";
+ return false;
+ }
+ return true;
+ }
+ case PP_VARTYPE_ARRAY: {
+ ArrayVar* expected_var = ArrayVar::FromPPVar(expected);
+ ArrayVar* actual_var = ArrayVar::FromPPVar(actual);
+ DCHECK(expected_var && actual_var);
+ if (expected_var->elements().size() != actual_var->elements().size()) {
+ LOG(ERROR) << "expected: " << expected_var->elements().size() <<
+ " actual: " << actual_var->elements().size();
+ return false;
+ }
+ for (size_t i = 0; i < expected_var->elements().size(); ++i) {
+ if (!Equals(expected_var->elements()[i].get(),
+ actual_var->elements()[i].get(),
+ visited_map)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ case PP_VARTYPE_DICTIONARY: {
+ DictionaryVar* expected_var = DictionaryVar::FromPPVar(expected);
+ DictionaryVar* actual_var = DictionaryVar::FromPPVar(actual);
+ DCHECK(expected_var && actual_var);
+ if (expected_var->key_value_map().size() !=
+ actual_var->key_value_map().size()) {
+ LOG(ERROR) << "expected: " << expected_var->key_value_map().size() <<
+ " actual: " << actual_var->key_value_map().size();
+ return false;
+ }
+ DictionaryVar::KeyValueMap::const_iterator expected_iter =
+ expected_var->key_value_map().begin();
+ DictionaryVar::KeyValueMap::const_iterator actual_iter =
+ actual_var->key_value_map().begin();
+ for ( ; expected_iter != expected_var->key_value_map().end();
+ ++expected_iter, ++actual_iter) {
+ if (expected_iter->first != actual_iter->first) {
+ LOG(ERROR) << "expected: " << expected_iter->first <<
+ " actual: " << actual_iter->first;
+ return false;
+ }
+ if (!Equals(expected_iter->second.get(),
+ actual_iter->second.get(),
+ visited_map)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
+bool Equals(const PP_Var& expected,
+ const PP_Var& actual) {
+ base::hash_map<int64_t, int64_t> visited_map;
+ return Equals(expected, actual, &visited_map);
+}
+
PP_Var WriteAndRead(const PP_Var& var) {
PP_Instance dummy_instance = 1234;
scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create(
@@ -59,7 +207,7 @@ PP_Var WriteAndRead(const PP_Var& var) {
bool WriteReadAndCompare(const PP_Var& var) {
ScopedPPVar expected(ScopedPPVar::PassRef(), var);
ScopedPPVar actual(ScopedPPVar::PassRef(), WriteAndRead(expected.get()));
- return TestEqual(expected.get(), actual.get());
+ return Equals(expected.get(), actual.get());
}
} // namespace
@@ -162,7 +310,7 @@ TEST_F(RawVarDataTest, DictionaryArrayTest) {
dictionary->SetWithStringKey("10", release_array.get());
ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(),
WriteAndRead(release_dictionary.get()));
- EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get()));
+ EXPECT_TRUE(Equals(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.
@@ -174,7 +322,7 @@ TEST_F(RawVarDataTest, DictionaryArrayTest) {
array->Set(index, release_array.get());
result = ScopedPPVar(ScopedPPVar::PassRef(),
WriteAndRead(release_array.get()));
- EXPECT_TRUE(TestEqual(release_array.get(), result.get()));
+ EXPECT_TRUE(Equals(release_array.get(), result.get()));
// Break the self reference.
array->Set(index, PP_MakeUndefined());
ArrayVar* result_array = ArrayVar::FromPPVar(result.get());
diff --git a/ppapi/shared_impl/unittest_utils.cc b/ppapi/shared_impl/unittest_utils.cc
deleted file mode 100644
index 2c32b30..0000000
--- a/ppapi/shared_impl/unittest_utils.cc
+++ /dev/null
@@ -1,166 +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 "ppapi/shared_impl/unittest_utils.h"
-
-#include <cmath>
-
-#include "base/hash_tables.h"
-#include "base/logging.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"
-
-namespace ppapi {
-
-namespace {
-
-// When two vars x and y are found to be equal, an entry is inserted into
-// |visited_map| with (x.value.as_id, y.value.as_id). This allows reference
-// cycles to be avoided. It also allows us to associate nodes in |expected| with
-// nodes in |actual| and check whether the graphs have equivalent topology.
-bool Equals(const PP_Var& expected,
- const PP_Var& actual,
- base::hash_map<int64_t, int64_t>* visited_map) {
- if (expected.type != actual.type) {
- LOG(ERROR) << "expected type: " << expected.type <<
- " actual type: " << actual.type;
- return false;
- }
- if (VarTracker::IsVarTypeRefcounted(expected.type)) {
- base::hash_map<int64_t, int64_t>::iterator it =
- visited_map->find(expected.value.as_id);
- if (it != visited_map->end()) {
- if (it->second != actual.value.as_id) {
- LOG(ERROR) << "expected id: " << it->second << " actual id: " <<
- actual.value.as_id;
- return false;
- } else {
- return true;
- }
- } else {
- (*visited_map)[expected.value.as_id] = actual.value.as_id;
- }
- }
- switch (expected.type) {
- case PP_VARTYPE_UNDEFINED:
- return true;
- case PP_VARTYPE_NULL:
- return true;
- case PP_VARTYPE_BOOL:
- if (expected.value.as_bool != actual.value.as_bool) {
- LOG(ERROR) << "expected: " << expected.value.as_bool << " actual: " <<
- actual.value.as_bool;
- return false;
- }
- return true;
- case PP_VARTYPE_INT32:
- if (expected.value.as_int != actual.value.as_int) {
- LOG(ERROR) << "expected: " << expected.value.as_int << " actual: " <<
- actual.value.as_int;
- return false;
- }
- return true;
- case PP_VARTYPE_DOUBLE:
- if (fabs(expected.value.as_double - actual.value.as_double) > 1.0e-4) {
- LOG(ERROR) << "expected: " << expected.value.as_double <<
- " actual: " << actual.value.as_double;
- return false;
- }
- return true;
- case PP_VARTYPE_OBJECT:
- if (expected.value.as_id != actual.value.as_id) {
- LOG(ERROR) << "expected: " << expected.value.as_id << " actual: " <<
- actual.value.as_id;
- return false;
- }
- return true;
- case PP_VARTYPE_STRING: {
- StringVar* expected_var = StringVar::FromPPVar(expected);
- StringVar* actual_var = StringVar::FromPPVar(actual);
- DCHECK(expected_var && actual_var);
- if (expected_var->value() != actual_var->value()) {
- LOG(ERROR) << "expected: " << expected_var->value() << " actual: " <<
- actual_var->value();
- return false;
- }
- return true;
- }
- case PP_VARTYPE_ARRAY_BUFFER: {
- ArrayBufferVar* expected_var = ArrayBufferVar::FromPPVar(expected);
- ArrayBufferVar* actual_var = ArrayBufferVar::FromPPVar(actual);
- DCHECK(expected_var && actual_var);
- if (expected_var->ByteLength() != actual_var->ByteLength()) {
- LOG(ERROR) << "expected: " << expected_var->ByteLength() <<
- " actual: " << actual_var->ByteLength();
- return false;
- }
- if (memcmp(expected_var->Map(), actual_var->Map(),
- expected_var->ByteLength()) != 0) {
- LOG(ERROR) << "expected array buffer does not match actual.";
- return false;
- }
- return true;
- }
- case PP_VARTYPE_ARRAY: {
- ArrayVar* expected_var = ArrayVar::FromPPVar(expected);
- ArrayVar* actual_var = ArrayVar::FromPPVar(actual);
- DCHECK(expected_var && actual_var);
- if (expected_var->elements().size() != actual_var->elements().size()) {
- LOG(ERROR) << "expected: " << expected_var->elements().size() <<
- " actual: " << actual_var->elements().size();
- return false;
- }
- for (size_t i = 0; i < expected_var->elements().size(); ++i) {
- if (!Equals(expected_var->elements()[i].get(),
- actual_var->elements()[i].get(),
- visited_map)) {
- return false;
- }
- }
- return true;
- }
- case PP_VARTYPE_DICTIONARY: {
- DictionaryVar* expected_var = DictionaryVar::FromPPVar(expected);
- DictionaryVar* actual_var = DictionaryVar::FromPPVar(actual);
- DCHECK(expected_var && actual_var);
- if (expected_var->key_value_map().size() !=
- actual_var->key_value_map().size()) {
- LOG(ERROR) << "expected: " << expected_var->key_value_map().size() <<
- " actual: " << actual_var->key_value_map().size();
- return false;
- }
- DictionaryVar::KeyValueMap::const_iterator expected_iter =
- expected_var->key_value_map().begin();
- DictionaryVar::KeyValueMap::const_iterator actual_iter =
- actual_var->key_value_map().begin();
- for ( ; expected_iter != expected_var->key_value_map().end();
- ++expected_iter, ++actual_iter) {
- if (expected_iter->first != actual_iter->first) {
- LOG(ERROR) << "expected: " << expected_iter->first <<
- " actual: " << actual_iter->first;
- return false;
- }
- if (!Equals(expected_iter->second.get(),
- actual_iter->second.get(),
- visited_map)) {
- return false;
- }
- }
- return true;
- }
- }
- NOTREACHED();
- return false;
-}
-
-} // namespace
-
-bool TestEqual(const PP_Var& expected, const PP_Var& actual) {
- base::hash_map<int64_t, int64_t> visited_map;
- return Equals(expected, actual, &visited_map);
-}
-
-} // namespace ppapi
diff --git a/ppapi/shared_impl/unittest_utils.h b/ppapi/shared_impl/unittest_utils.h
deleted file mode 100644
index e07d8a8..0000000
--- a/ppapi/shared_impl/unittest_utils.h
+++ /dev/null
@@ -1,19 +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 PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_
-#define PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_
-
-#include "ppapi/c/pp_var.h"
-
-namespace ppapi {
-
-// Compares two vars for equality. This is a deep comparison (the entire graph
-// is traversed recursively). The function guarantees that the topology of the
-// two PP_Var graphs being compared is identical, including graphs with cycles.
-bool TestEqual(const PP_Var& expected, const PP_Var& actual);
-
-} // namespace ppapi
-
-#endif // PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index cf19abf..a163dfb 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -244,8 +244,6 @@
'../plugins/ppapi/usb_key_code_conversion_linux.cc',
'../plugins/ppapi/usb_key_code_conversion_mac.cc',
'../plugins/ppapi/usb_key_code_conversion_win.cc',
- '../plugins/ppapi/v8_var_converter.cc',
- '../plugins/ppapi/v8_var_converter.h',
'../plugins/sad_plugin.cc',
'../plugins/sad_plugin.h',
'../plugins/webkit_plugins_export.h',
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, &current_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, &current_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