OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/plugins/ppapi/v8_var_converter.h" | 5 #include "webkit/plugins/ppapi/v8_var_converter.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); | 145 context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); |
146 } | 146 } |
147 virtual void TearDown() { | 147 virtual void TearDown() { |
148 context_.Dispose(); | 148 context_.Dispose(); |
149 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); | 149 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); |
150 ProxyLock::Release(); | 150 ProxyLock::Release(); |
151 } | 151 } |
152 | 152 |
153 protected: | 153 protected: |
154 bool RoundTrip(const PP_Var& var, PP_Var* result) { | 154 bool RoundTrip(const PP_Var& var, PP_Var* result) { |
155 V8VarConverter converter; | |
156 v8::HandleScope handle_scope(isolate_); | 155 v8::HandleScope handle_scope(isolate_); |
157 v8::Context::Scope context_scope(isolate_, context_); | 156 v8::Context::Scope context_scope(isolate_, context_); |
158 v8::Local<v8::Context> context = | 157 v8::Local<v8::Context> context = |
159 v8::Local<v8::Context>::New(isolate_, context_); | 158 v8::Local<v8::Context>::New(isolate_, context_); |
160 v8::Handle<v8::Value> v8_result; | 159 v8::Handle<v8::Value> v8_result; |
161 if (!converter.ToV8Value(var, context, &v8_result)) | 160 if (!V8VarConverter::ToV8Value(var, context, &v8_result)) |
162 return false; | 161 return false; |
163 if (!Equals(var, v8_result)) | 162 if (!Equals(var, v8_result)) |
164 return false; | 163 return false; |
165 if (!converter.FromV8Value(v8_result, context, result)) | 164 if (!V8VarConverter::FromV8Value(v8_result, context, result)) |
166 return false; | 165 return false; |
167 return true; | 166 return true; |
168 } | 167 } |
169 | 168 |
170 // Assumes a ref for var. | 169 // Assumes a ref for var. |
171 bool RoundTripAndCompare(const PP_Var& var) { | 170 bool RoundTripAndCompare(const PP_Var& var) { |
172 ScopedPPVar expected(ScopedPPVar::PassRef(), var); | 171 ScopedPPVar expected(ScopedPPVar::PassRef(), var); |
173 PP_Var actual_var; | 172 PP_Var actual_var; |
174 if (!RoundTrip(expected.get(), &actual_var)) | 173 if (!RoundTrip(expected.get(), &actual_var)) |
175 return false; | 174 return false; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); | 263 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); |
265 | 264 |
266 // Array with dictionary. | 265 // Array with dictionary. |
267 array->Set(index++, release_dictionary.get()); | 266 array->Set(index++, release_dictionary.get()); |
268 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 267 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
269 | 268 |
270 // Array with dictionary with array. | 269 // Array with dictionary with array. |
271 array2->Set(0, PP_MakeInt32(100)); | 270 array2->Set(0, PP_MakeInt32(100)); |
272 dictionary->SetWithStringKey("9", release_array2.get()); | 271 dictionary->SetWithStringKey("9", release_array2.get()); |
273 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 272 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
| 273 } |
274 | 274 |
275 // Array <-> dictionary cycle. | 275 TEST_F(V8VarConverterTest, Cycles) { |
276 dictionary->SetWithStringKey("10", release_array.get()); | 276 // Check that cycles aren't converted. |
277 PP_Var result_var; | 277 v8::HandleScope handle_scope(isolate_); |
278 EXPECT_TRUE(RoundTrip(release_dictionary.get(), &result_var)); | 278 v8::Context::Scope context_scope(isolate_, context_); |
279 ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); | 279 v8::Local<v8::Context> context = |
280 EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get())); | 280 v8::Local<v8::Context>::New(isolate_, context_); |
281 // Break the cycle. | |
282 // TODO(raymes): We need some better machinery for releasing vars with | |
283 // cycles. Remove the code below once we have that. | |
284 dictionary->DeleteWithStringKey("10"); | |
285 DictionaryVar* result_dictionary = DictionaryVar::FromPPVar(result.get()); | |
286 result_dictionary->DeleteWithStringKey("10"); | |
287 | 281 |
288 // Array with self references. | 282 // Var->V8 conversion. |
289 array->Set(index, release_array.get()); | 283 { |
290 EXPECT_TRUE(RoundTrip(release_array.get(), &result_var)); | 284 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); |
291 result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); | 285 ScopedPPVar release_dictionary(ScopedPPVar::PassRef(), |
292 EXPECT_TRUE(TestEqual(release_array.get(), result.get())); | 286 dictionary->GetPPVar()); |
293 // Break the self reference. | 287 scoped_refptr<ArrayVar> array(new ArrayVar); |
294 array->Set(index, PP_MakeUndefined()); | 288 ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar()); |
295 ArrayVar* result_array = ArrayVar::FromPPVar(result.get()); | 289 |
296 result_array->Set(index, PP_MakeUndefined()); | 290 dictionary->SetWithStringKey("1", release_array.get()); |
| 291 array->Set(0, release_dictionary.get()); |
| 292 |
| 293 v8::Handle<v8::Value> v8_result; |
| 294 |
| 295 // Array <-> dictionary cycle. |
| 296 dictionary->SetWithStringKey("1", release_array.get()); |
| 297 ASSERT_FALSE(V8VarConverter::ToV8Value(release_dictionary.get(), |
| 298 context, &v8_result)); |
| 299 // Break the cycle. |
| 300 // TODO(raymes): We need some better machinery for releasing vars with |
| 301 // cycles. Remove the code below once we have that. |
| 302 dictionary->DeleteWithStringKey("1"); |
| 303 |
| 304 // Array with self reference. |
| 305 array->Set(0, release_array.get()); |
| 306 ASSERT_FALSE(V8VarConverter::ToV8Value(release_array.get(), |
| 307 context, &v8_result)); |
| 308 // Break the self reference. |
| 309 array->Set(0, PP_MakeUndefined()); |
| 310 } |
| 311 |
| 312 // V8->Var conversion. |
| 313 { |
| 314 v8::Handle<v8::Object> object = v8::Object::New(); |
| 315 v8::Handle<v8::Array> array = v8::Array::New(); |
| 316 |
| 317 PP_Var var_result; |
| 318 |
| 319 // Array <-> dictionary cycle. |
| 320 std::string key = "1"; |
| 321 object->Set(v8::String::New(key.c_str(), key.length()), array); |
| 322 array->Set(0, object); |
| 323 |
| 324 ASSERT_FALSE(V8VarConverter::FromV8Value(object, context, &var_result)); |
| 325 |
| 326 // Array with self reference. |
| 327 array->Set(0, array); |
| 328 ASSERT_FALSE(V8VarConverter::FromV8Value(array, context, &var_result)); |
| 329 } |
297 } | 330 } |
298 | 331 |
299 TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { | 332 TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { |
300 { | 333 { |
301 // Test keys with '.'. | 334 // Test keys with '.'. |
302 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); | 335 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); |
303 dictionary->SetWithStringKey(".", PP_MakeUndefined()); | 336 dictionary->SetWithStringKey(".", PP_MakeUndefined()); |
304 dictionary->SetWithStringKey("x.y", PP_MakeUndefined()); | 337 dictionary->SetWithStringKey("x.y", PP_MakeUndefined()); |
305 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); | 338 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); |
306 } | 339 } |
(...skipping 11 matching lines...) Expand all Loading... |
318 "false: 'qux'," | 351 "false: 'qux'," |
319 "null: 'quux'," | 352 "null: 'quux'," |
320 "undefined: 'oops'" | 353 "undefined: 'oops'" |
321 "};" | 354 "};" |
322 "})();"; | 355 "})();"; |
323 | 356 |
324 v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); | 357 v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); |
325 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); | 358 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); |
326 ASSERT_FALSE(object.IsEmpty()); | 359 ASSERT_FALSE(object.IsEmpty()); |
327 | 360 |
328 V8VarConverter converter; | |
329 PP_Var actual; | 361 PP_Var actual; |
330 ASSERT_TRUE(converter.FromV8Value( | 362 ASSERT_TRUE(V8VarConverter::FromV8Value(object, |
331 object, v8::Local<v8::Context>::New(isolate_, context_), &actual)); | 363 v8::Local<v8::Context>::New(isolate_, context_), &actual)); |
332 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); | 364 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); |
333 | 365 |
334 scoped_refptr<DictionaryVar> expected(new DictionaryVar); | 366 scoped_refptr<DictionaryVar> expected(new DictionaryVar); |
335 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); | 367 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); |
336 expected->SetWithStringKey("1", foo.get()); | 368 expected->SetWithStringKey("1", foo.get()); |
337 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); | 369 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); |
338 expected->SetWithStringKey("2", bar.get()); | 370 expected->SetWithStringKey("2", bar.get()); |
339 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); | 371 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); |
340 expected->SetWithStringKey("true", baz.get()); | 372 expected->SetWithStringKey("true", baz.get()); |
341 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); | 373 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); |
342 expected->SetWithStringKey("false", qux.get()); | 374 expected->SetWithStringKey("false", qux.get()); |
343 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); | 375 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); |
344 expected->SetWithStringKey("null", quux.get()); | 376 expected->SetWithStringKey("null", quux.get()); |
345 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); | 377 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); |
346 expected->SetWithStringKey("undefined", oops.get()); | 378 expected->SetWithStringKey("undefined", oops.get()); |
347 ScopedPPVar release_expected( | 379 ScopedPPVar release_expected( |
348 ScopedPPVar::PassRef(), expected->GetPPVar()); | 380 ScopedPPVar::PassRef(), expected->GetPPVar()); |
349 | 381 |
350 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get())); | 382 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get())); |
351 } | 383 } |
352 } | 384 } |
353 | 385 |
354 } // namespace ppapi | 386 } // namespace ppapi |
355 } // namespace webkit | 387 } // namespace webkit |
OLD | NEW |