blob: 4c98c6811828d8779c498190dde3d2888f9ada56 [file] [log] [blame]
[email protected]3de391e82012-05-16 17:50:511// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b1cf3372011-04-20 21:28:102// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
John Abd-El-Malek312a30bb2017-10-23 19:51:525#include "content/renderer/v8_value_converter_impl.h"
dchengc864f522016-04-08 23:55:276
avi66a07722015-12-25 23:38:127#include <stddef.h>
8#include <stdint.h>
9
[email protected]b1cf3372011-04-20 21:28:1010#include <cmath>
dchengc864f522016-04-08 23:55:2711#include <memory>
[email protected]b1cf3372011-04-20 21:28:1012
Lei Zhang204812442020-10-24 00:51:0213#include "base/containers/span.h"
avi66a07722015-12-25 23:38:1214#include "base/macros.h"
[email protected]6a9b7372013-03-20 15:35:2015#include "base/stl_util.h"
Gabriel Charettec7108742019-08-23 03:31:4016#include "base/test/task_environment.h"
[email protected]06d19d82012-12-17 21:45:3717#include "base/test/values_test_util.h"
[email protected]b1cf3372011-04-20 21:28:1018#include "base/values.h"
[email protected]b1cf3372011-04-20 21:28:1019#include "testing/gtest/include/gtest/gtest.h"
20#include "v8/include/v8.h"
21
[email protected]9a292e22012-10-22 15:19:3122namespace content {
[email protected]e0658bc2012-09-17 04:05:2423
[email protected]6a9b7372013-03-20 15:35:2024// To improve the performance of
25// V8ValueConverterImpl::UpdateAndCheckUniqueness, identity hashes of objects
26// are used during checking for duplicates. For testing purposes we need to
27// ignore the hash sometimes. Create this helper object to avoid using identity
28// hashes for the lifetime of the helper.
29class ScopedAvoidIdentityHashForTesting {
30 public:
31 // The hashes will be ignored in |converter|, which must not be NULL and it
32 // must outlive the created instance of this helper.
33 explicit ScopedAvoidIdentityHashForTesting(
34 content::V8ValueConverterImpl* converter);
35 ~ScopedAvoidIdentityHashForTesting();
36
37 private:
38 content::V8ValueConverterImpl* converter_;
39
40 DISALLOW_COPY_AND_ASSIGN(ScopedAvoidIdentityHashForTesting);
41};
42
43ScopedAvoidIdentityHashForTesting::ScopedAvoidIdentityHashForTesting(
44 content::V8ValueConverterImpl* converter)
45 : converter_(converter) {
46 CHECK(converter_);
47 converter_->avoid_identity_hash_for_testing_ = true;
48}
49
50ScopedAvoidIdentityHashForTesting::~ScopedAvoidIdentityHashForTesting() {
51 converter_->avoid_identity_hash_for_testing_ = false;
52}
53
[email protected]8d86f13d2011-10-04 17:01:1954class V8ValueConverterImplTest : public testing::Test {
[email protected]52d6c3202013-06-11 04:28:1255 public:
56 V8ValueConverterImplTest()
57 : isolate_(v8::Isolate::GetCurrent()) {
58 }
59
[email protected]b1cf3372011-04-20 21:28:1060 protected:
dchengf5762152014-10-29 02:12:0661 void SetUp() override {
[email protected]52d6c3202013-06-11 04:28:1262 v8::HandleScope handle_scope(isolate_);
deepak.s750d68f2015-04-30 07:32:4163 v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
Ivan Kotenkov2c0d2bb32017-11-01 15:41:2864 context_.Reset(isolate_, v8::Context::New(isolate_, nullptr, global));
[email protected]b1cf3372011-04-20 21:28:1065 }
66
dchengf5762152014-10-29 02:12:0667 void TearDown() override { context_.Reset(); }
[email protected]b1cf3372011-04-20 21:28:1068
[email protected]0cd50aa2013-02-12 22:28:0169 std::string GetString(base::DictionaryValue* value, const std::string& key) {
[email protected]786a7fa2011-04-22 21:27:1270 std::string temp;
71 if (!value->GetString(key, &temp)) {
72 ADD_FAILURE();
[email protected]007b3f82013-04-09 08:46:4573 return std::string();
[email protected]786a7fa2011-04-22 21:27:1274 }
75 return temp;
76 }
77
deepak.s750d68f2015-04-30 07:32:4178 std::string GetString(v8::Local<v8::Object> value, const std::string& key) {
Dan Elphickcc7538d02019-02-01 13:41:4779 v8::Local<v8::Value> temp;
80 if (!value
81 ->Get(isolate_->GetCurrentContext(),
82 v8::String::NewFromUtf8(isolate_, key.c_str(),
83 v8::NewStringType::kInternalized)
84 .ToLocalChecked())
85 .ToLocal(&temp)) {
[email protected]786a7fa2011-04-22 21:27:1286 ADD_FAILURE();
[email protected]007b3f82013-04-09 08:46:4587 return std::string();
[email protected]786a7fa2011-04-22 21:27:1288 }
Dan Elphickcc7538d02019-02-01 13:41:4789 v8::String::Utf8Value utf8(isolate_, temp.As<v8::String>());
[email protected]786a7fa2011-04-22 21:27:1290 return std::string(*utf8, utf8.length());
91 }
92
avi66a07722015-12-25 23:38:1293 std::string GetString(base::ListValue* value, uint32_t index) {
[email protected]786a7fa2011-04-22 21:27:1294 std::string temp;
95 if (!value->GetString(static_cast<size_t>(index), &temp)) {
96 ADD_FAILURE();
[email protected]007b3f82013-04-09 08:46:4597 return std::string();
[email protected]786a7fa2011-04-22 21:27:1298 }
99 return temp;
100 }
101
avi66a07722015-12-25 23:38:12102 std::string GetString(v8::Local<v8::Array> value, uint32_t index) {
Dan Elphickcc7538d02019-02-01 13:41:47103 v8::Local<v8::Value> temp;
104 if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&temp)) {
[email protected]786a7fa2011-04-22 21:27:12105 ADD_FAILURE();
[email protected]007b3f82013-04-09 08:46:45106 return std::string();
[email protected]786a7fa2011-04-22 21:27:12107 }
Dan Elphickcc7538d02019-02-01 13:41:47108 v8::String::Utf8Value utf8(isolate_, temp.As<v8::String>());
[email protected]786a7fa2011-04-22 21:27:12109 return std::string(*utf8, utf8.length());
110 }
111
robb5bdf372016-04-27 11:27:06112 int32_t GetInt(v8::Local<v8::Object> value, const std::string& key) {
Dan Elphickcc7538d02019-02-01 13:41:47113 v8::Local<v8::Value> temp;
114 if (!value
115 ->Get(isolate_->GetCurrentContext(),
116 v8::String::NewFromUtf8(isolate_, key.c_str(),
117 v8::NewStringType::kInternalized)
118 .ToLocalChecked())
119 .ToLocal(&temp)) {
robb5bdf372016-04-27 11:27:06120 ADD_FAILURE();
121 return -1;
122 }
Dan Elphickcc7538d02019-02-01 13:41:47123 return temp.As<v8::Int32>()->Value();
robb5bdf372016-04-27 11:27:06124 }
125
126 int32_t GetInt(v8::Local<v8::Object> value, uint32_t index) {
Dan Elphickcc7538d02019-02-01 13:41:47127 v8::Local<v8::Value> temp;
128 if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&temp)) {
robb5bdf372016-04-27 11:27:06129 ADD_FAILURE();
130 return -1;
131 }
Dan Elphickcc7538d02019-02-01 13:41:47132 return temp.As<v8::Int32>()->Value();
robb5bdf372016-04-27 11:27:06133 }
134
[email protected]0cd50aa2013-02-12 22:28:01135 bool IsNull(base::DictionaryValue* value, const std::string& key) {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28136 base::Value* child = nullptr;
[email protected]786a7fa2011-04-22 21:27:12137 if (!value->Get(key, &child)) {
138 ADD_FAILURE();
139 return false;
140 }
jdoerrie76cee9c2017-10-06 22:42:42141 return child->type() == base::Value::Type::NONE;
[email protected]786a7fa2011-04-22 21:27:12142 }
143
deepak.s750d68f2015-04-30 07:32:41144 bool IsNull(v8::Local<v8::Object> value, const std::string& key) {
Dan Elphickcc7538d02019-02-01 13:41:47145 v8::Local<v8::Value> child;
146 if (!value
147 ->Get(isolate_->GetCurrentContext(),
148 v8::String::NewFromUtf8(isolate_, key.c_str(),
Yang Guo26b0f7772018-11-27 08:37:20149 v8::NewStringType::kInternalized)
Dan Elphickcc7538d02019-02-01 13:41:47150 .ToLocalChecked())
151 .ToLocal(&child)) {
[email protected]786a7fa2011-04-22 21:27:12152 ADD_FAILURE();
153 return false;
154 }
155 return child->IsNull();
156 }
157
avi66a07722015-12-25 23:38:12158 bool IsNull(base::ListValue* value, uint32_t index) {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28159 base::Value* child = nullptr;
[email protected]786a7fa2011-04-22 21:27:12160 if (!value->Get(static_cast<size_t>(index), &child)) {
161 ADD_FAILURE();
162 return false;
163 }
jdoerrie76cee9c2017-10-06 22:42:42164 return child->type() == base::Value::Type::NONE;
[email protected]786a7fa2011-04-22 21:27:12165 }
166
avi66a07722015-12-25 23:38:12167 bool IsNull(v8::Local<v8::Array> value, uint32_t index) {
Dan Elphickcc7538d02019-02-01 13:41:47168 v8::Local<v8::Value> child;
169 if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&child)) {
[email protected]786a7fa2011-04-22 21:27:12170 ADD_FAILURE();
171 return false;
172 }
173 return child->IsNull();
174 }
175
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:49176 void TestWeirdType(V8ValueConverterImpl& converter,
deepak.s750d68f2015-04-30 07:32:41177 v8::Local<v8::Value> val,
[email protected]bab1c13f2011-08-12 20:59:02178 base::Value::Type expected_type,
dchengc864f522016-04-08 23:55:27179 std::unique_ptr<base::Value> expected_value) {
[email protected]52d6c3202013-06-11 04:28:12180 v8::Local<v8::Context> context =
181 v8::Local<v8::Context>::New(isolate_, context_);
dchengc864f522016-04-08 23:55:27182 std::unique_ptr<base::Value> raw(converter.FromV8Value(val, context));
[email protected]e0658bc2012-09-17 04:05:24183
[email protected]59383c782013-04-17 16:43:27184 if (expected_value) {
[email protected]e0658bc2012-09-17 04:05:24185 ASSERT_TRUE(raw.get());
[email protected]786a7fa2011-04-22 21:27:12186 EXPECT_TRUE(expected_value->Equals(raw.get()));
jdoerrie76cee9c2017-10-06 22:42:42187 EXPECT_EQ(expected_type, raw->type());
[email protected]e0658bc2012-09-17 04:05:24188 } else {
189 EXPECT_FALSE(raw.get());
190 }
[email protected]786a7fa2011-04-22 21:27:12191
deepak.s750d68f2015-04-30 07:32:41192 v8::Local<v8::Object> object(v8::Object::New(isolate_));
Dan Elphickcc7538d02019-02-01 13:41:47193 object
194 ->Set(context,
195 v8::String::NewFromUtf8(isolate_, "test",
196 v8::NewStringType::kInternalized)
197 .ToLocalChecked(),
198 val)
199 .Check();
dchengc864f522016-04-08 23:55:27200 std::unique_ptr<base::DictionaryValue> dictionary(
dcheng0232f572016-05-27 17:47:44201 base::DictionaryValue::From(converter.FromV8Value(object, context)));
[email protected]786a7fa2011-04-22 21:27:12202 ASSERT_TRUE(dictionary.get());
[email protected]217d9562012-07-16 21:57:37203
[email protected]59383c782013-04-17 16:43:27204 if (expected_value) {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28205 base::Value* temp = nullptr;
[email protected]e0658bc2012-09-17 04:05:24206 ASSERT_TRUE(dictionary->Get("test", &temp));
jdoerrie76cee9c2017-10-06 22:42:42207 EXPECT_EQ(expected_type, temp->type());
[email protected]786a7fa2011-04-22 21:27:12208 EXPECT_TRUE(expected_value->Equals(temp));
[email protected]e0658bc2012-09-17 04:05:24209 } else {
210 EXPECT_FALSE(dictionary->HasKey("test"));
211 }
[email protected]786a7fa2011-04-22 21:27:12212
deepak.s750d68f2015-04-30 07:32:41213 v8::Local<v8::Array> array(v8::Array::New(isolate_));
Dan Elphickcc7538d02019-02-01 13:41:47214 array->Set(context, 0, val).Check();
dchengc864f522016-04-08 23:55:27215 std::unique_ptr<base::ListValue> list(
dcheng0232f572016-05-27 17:47:44216 base::ListValue::From(converter.FromV8Value(array, context)));
[email protected]786a7fa2011-04-22 21:27:12217 ASSERT_TRUE(list.get());
[email protected]59383c782013-04-17 16:43:27218 if (expected_value) {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28219 base::Value* temp = nullptr;
[email protected]e0658bc2012-09-17 04:05:24220 ASSERT_TRUE(list->Get(0, &temp));
jdoerrie76cee9c2017-10-06 22:42:42221 EXPECT_EQ(expected_type, temp->type());
[email protected]786a7fa2011-04-22 21:27:12222 EXPECT_TRUE(expected_value->Equals(temp));
[email protected]e0658bc2012-09-17 04:05:24223 } else {
224 // Arrays should preserve their length, and convert unconvertible
225 // types into null.
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28226 base::Value* temp = nullptr;
[email protected]e0658bc2012-09-17 04:05:24227 ASSERT_TRUE(list->Get(0, &temp));
jdoerrie76cee9c2017-10-06 22:42:42228 EXPECT_EQ(base::Value::Type::NONE, temp->type());
[email protected]e0658bc2012-09-17 04:05:24229 }
[email protected]786a7fa2011-04-22 21:27:12230 }
231
Adam Klein8a35b5b2018-01-17 00:51:00232 template <typename T>
233 v8::Local<T> CompileRun(v8::Local<v8::Context> context, const char* source) {
Yang Guo26b0f7772018-11-27 08:37:20234 return v8::Script::Compile(
Camillo Brunie5440c762020-09-10 11:53:35235 context,
236 v8::String::NewFromUtf8(isolate_, source).ToLocalChecked())
Adam Klein8a35b5b2018-01-17 00:51:00237 .ToLocalChecked()
238 ->Run(context)
239 .ToLocalChecked()
240 .As<T>();
241 }
242
Gabriel Charette694c3c332019-08-19 14:53:05243 base::test::TaskEnvironment task_environment_;
Scott Grahamc80dc3472017-08-25 18:42:18244
[email protected]52d6c3202013-06-11 04:28:12245 v8::Isolate* isolate_;
246
[email protected]b1cf3372011-04-20 21:28:10247 // Context for the JavaScript in the test.
248 v8::Persistent<v8::Context> context_;
249};
250
[email protected]8d86f13d2011-10-04 17:01:19251TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
Lei Zhang9b9d5792019-02-20 07:24:42252 std::unique_ptr<base::Value> original_root = base::test::ParseJsonDeprecated(
[email protected]06d19d82012-12-17 21:45:37253 "{ \n"
254 " \"null\": null, \n"
255 " \"true\": true, \n"
256 " \"false\": false, \n"
257 " \"positive-int\": 42, \n"
258 " \"negative-int\": -42, \n"
259 " \"zero\": 0, \n"
260 " \"double\": 88.8, \n"
[email protected]0cd50aa2013-02-12 22:28:01261 " \"big-integral-double\": 9007199254740992.0, \n" // 2.0^53
[email protected]06d19d82012-12-17 21:45:37262 " \"string\": \"foobar\", \n"
263 " \"empty-string\": \"\", \n"
264 " \"dictionary\": { \n"
265 " \"foo\": \"bar\",\n"
266 " \"hot\": \"dog\",\n"
267 " }, \n"
268 " \"empty-dictionary\": {}, \n"
jamb56c1d382016-09-29 19:28:58269 " \"list\": [ \"bar\", \"foo\" ], \n"
[email protected]06d19d82012-12-17 21:45:37270 " \"empty-list\": [], \n"
271 "}");
[email protected]b1cf3372011-04-20 21:28:10272
[email protected]52d6c3202013-06-11 04:28:12273 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12274 v8::Local<v8::Context> context =
275 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23276 v8::Context::Scope context_scope(context);
[email protected]b1cf3372011-04-20 21:28:10277
[email protected]8d86f13d2011-10-04 17:01:19278 V8ValueConverterImpl converter;
deepak.s750d68f2015-04-30 07:32:41279 v8::Local<v8::Object> v8_object =
[email protected]52d6c3202013-06-11 04:28:12280 converter.ToV8Value(original_root.get(), context).As<v8::Object>();
[email protected]b1cf3372011-04-20 21:28:10281 ASSERT_FALSE(v8_object.IsEmpty());
282
Song Fangzhen2691dfe2021-05-07 11:59:58283 EXPECT_EQ(
284 static_cast<const base::DictionaryValue&>(*original_root).DictSize(),
285 v8_object->GetPropertyNames(context).ToLocalChecked()->Length());
Dan Elphickcc7538d02019-02-01 13:41:47286 EXPECT_TRUE(
287 v8_object
288 ->Get(context, v8::String::NewFromUtf8(
289 isolate_, "null", v8::NewStringType::kInternalized)
290 .ToLocalChecked())
291 .ToLocalChecked()
292 ->IsNull());
293 EXPECT_TRUE(
294 v8_object
295 ->Get(context, v8::String::NewFromUtf8(
296 isolate_, "true", v8::NewStringType::kInternalized)
297 .ToLocalChecked())
298 .ToLocalChecked()
299 ->IsTrue());
Yang Guo26b0f7772018-11-27 08:37:20300 EXPECT_TRUE(v8_object
Dan Elphickcc7538d02019-02-01 13:41:47301 ->Get(context,
302 v8::String::NewFromUtf8(
Yang Guo26b0f7772018-11-27 08:37:20303 isolate_, "false", v8::NewStringType::kInternalized)
304 .ToLocalChecked())
Dan Elphickcc7538d02019-02-01 13:41:47305 .ToLocalChecked()
Yang Guo26b0f7772018-11-27 08:37:20306 ->IsFalse());
Yang Guo26b0f7772018-11-27 08:37:20307 EXPECT_TRUE(v8_object
Dan Elphickcc7538d02019-02-01 13:41:47308 ->Get(context, v8::String::NewFromUtf8(
309 isolate_, "positive-int",
310 v8::NewStringType::kInternalized)
311 .ToLocalChecked())
312 .ToLocalChecked()
313 ->IsInt32());
314 EXPECT_TRUE(v8_object
315 ->Get(context, v8::String::NewFromUtf8(
316 isolate_, "negative-int",
317 v8::NewStringType::kInternalized)
318 .ToLocalChecked())
319 .ToLocalChecked()
[email protected]d3c97d12013-12-02 12:19:23320 ->IsInt32());
321 EXPECT_TRUE(
Yang Guo26b0f7772018-11-27 08:37:20322 v8_object
Dan Elphickcc7538d02019-02-01 13:41:47323 ->Get(context, v8::String::NewFromUtf8(
324 isolate_, "zero", v8::NewStringType::kInternalized)
325 .ToLocalChecked())
326 .ToLocalChecked()
327 ->IsInt32());
Yang Guo26b0f7772018-11-27 08:37:20328 EXPECT_TRUE(v8_object
Dan Elphickcc7538d02019-02-01 13:41:47329 ->Get(context, v8::String::NewFromUtf8(
330 isolate_, "double",
331 v8::NewStringType::kInternalized)
332 .ToLocalChecked())
333 .ToLocalChecked()
334 ->IsNumber());
335 EXPECT_TRUE(v8_object
336 ->Get(context, v8::String::NewFromUtf8(
337 isolate_, "big-integral-double",
338 v8::NewStringType::kInternalized)
339 .ToLocalChecked())
340 .ToLocalChecked()
341 ->IsNumber());
342 EXPECT_TRUE(v8_object
343 ->Get(context, v8::String::NewFromUtf8(
344 isolate_, "string",
345 v8::NewStringType::kInternalized)
346 .ToLocalChecked())
347 .ToLocalChecked()
348 ->IsString());
349 EXPECT_TRUE(v8_object
350 ->Get(context, v8::String::NewFromUtf8(
351 isolate_, "empty-string",
352 v8::NewStringType::kInternalized)
353 .ToLocalChecked())
354 .ToLocalChecked()
355 ->IsString());
356 EXPECT_TRUE(v8_object
357 ->Get(context, v8::String::NewFromUtf8(
358 isolate_, "dictionary",
359 v8::NewStringType::kInternalized)
360 .ToLocalChecked())
361 .ToLocalChecked()
362 ->IsObject());
363 EXPECT_TRUE(v8_object
364 ->Get(context, v8::String::NewFromUtf8(
365 isolate_, "empty-dictionary",
366 v8::NewStringType::kInternalized)
367 .ToLocalChecked())
368 .ToLocalChecked()
369 ->IsObject());
Yang Guo26b0f7772018-11-27 08:37:20370 EXPECT_TRUE(
371 v8_object
Dan Elphickcc7538d02019-02-01 13:41:47372 ->Get(context, v8::String::NewFromUtf8(
373 isolate_, "list", v8::NewStringType::kInternalized)
374 .ToLocalChecked())
375 .ToLocalChecked()
Yang Guo26b0f7772018-11-27 08:37:20376 ->IsArray());
Dan Elphickcc7538d02019-02-01 13:41:47377 EXPECT_TRUE(v8_object
378 ->Get(context, v8::String::NewFromUtf8(
379 isolate_, "empty-list",
380 v8::NewStringType::kInternalized)
381 .ToLocalChecked())
382 .ToLocalChecked()
383 ->IsArray());
[email protected]b1cf3372011-04-20 21:28:10384
dchengc864f522016-04-08 23:55:27385 std::unique_ptr<base::Value> new_root(
386 converter.FromV8Value(v8_object, context));
[email protected]06d19d82012-12-17 21:45:37387 EXPECT_NE(original_root.get(), new_root.get());
388 EXPECT_TRUE(original_root->Equals(new_root.get()));
[email protected]b1cf3372011-04-20 21:28:10389}
[email protected]735e70e32011-04-20 22:04:57390
[email protected]8d86f13d2011-10-04 17:01:19391TEST_F(V8ValueConverterImplTest, KeysWithDots) {
dchengc864f522016-04-08 23:55:27392 std::unique_ptr<base::Value> original =
Lei Zhang9b9d5792019-02-20 07:24:42393 base::test::ParseJsonDeprecated("{ \"foo.bar\": \"baz\" }");
[email protected]735e70e32011-04-20 22:04:57394
[email protected]52d6c3202013-06-11 04:28:12395 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12396 v8::Local<v8::Context> context =
397 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23398 v8::Context::Scope context_scope(context);
[email protected]735e70e32011-04-20 22:04:57399
[email protected]8d86f13d2011-10-04 17:01:19400 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27401 std::unique_ptr<base::Value> copy(converter.FromV8Value(
402 converter.ToV8Value(original.get(), context), context));
[email protected]735e70e32011-04-20 22:04:57403
[email protected]06d19d82012-12-17 21:45:37404 EXPECT_TRUE(original->Equals(copy.get()));
[email protected]735e70e32011-04-20 22:04:57405}
[email protected]786a7fa2011-04-22 21:27:12406
[email protected]8d86f13d2011-10-04 17:01:19407TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
[email protected]52d6c3202013-06-11 04:28:12408 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12409 v8::Local<v8::Context> context =
410 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23411 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50412 v8::MicrotasksScope microtasks(
413 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]786a7fa2011-04-22 21:27:12414
415 // Set up objects to throw when reading or writing 'foo'.
416 const char* source =
417 "Object.prototype.__defineSetter__('foo', "
418 " function() { throw new Error('muah!'); });"
419 "Object.prototype.__defineGetter__('foo', "
420 " function() { throw new Error('muah!'); });";
421
Adam Klein8a35b5b2018-01-17 00:51:00422 CompileRun<v8::Value>(context, source);
[email protected]786a7fa2011-04-22 21:27:12423
deepak.s750d68f2015-04-30 07:32:41424 v8::Local<v8::Object> object(v8::Object::New(isolate_));
Yang Guo26b0f7772018-11-27 08:37:20425 v8::Local<v8::String> bar =
426 v8::String::NewFromUtf8(isolate_, "bar", v8::NewStringType::kInternalized)
427 .ToLocalChecked();
Dan Elphickcc7538d02019-02-01 13:41:47428 object->Set(context, bar, bar).Check();
[email protected]786a7fa2011-04-22 21:27:12429
430 // Converting from v8 value should replace the foo property with null.
[email protected]8d86f13d2011-10-04 17:01:19431 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27432 std::unique_ptr<base::DictionaryValue> converted(
dcheng0232f572016-05-27 17:47:44433 base::DictionaryValue::From(converter.FromV8Value(object, context)));
[email protected]786a7fa2011-04-22 21:27:12434 EXPECT_TRUE(converted.get());
435 // http://code.google.com/p/v8/issues/detail?id=1342
436 // EXPECT_EQ(2u, converted->size());
437 // EXPECT_TRUE(IsNull(converted.get(), "foo"));
Song Fangzhen2691dfe2021-05-07 11:59:58438 EXPECT_EQ(1u, converted->DictSize());
[email protected]786a7fa2011-04-22 21:27:12439 EXPECT_EQ("bar", GetString(converted.get(), "bar"));
440
robb5bdf372016-04-27 11:27:06441 // Converting to v8 value should not trigger the setter.
[email protected]786a7fa2011-04-22 21:27:12442 converted->SetString("foo", "foo");
deepak.s750d68f2015-04-30 07:32:41443 v8::Local<v8::Object> copy =
[email protected]52d6c3202013-06-11 04:28:12444 converter.ToV8Value(converted.get(), context).As<v8::Object>();
[email protected]786a7fa2011-04-22 21:27:12445 EXPECT_FALSE(copy.IsEmpty());
Dan Elphickcc0832ef2018-12-24 11:31:23446 EXPECT_EQ(2u, copy->GetPropertyNames(context).ToLocalChecked()->Length());
robb5bdf372016-04-27 11:27:06447 EXPECT_EQ("foo", GetString(copy, "foo"));
[email protected]786a7fa2011-04-22 21:27:12448 EXPECT_EQ("bar", GetString(copy, "bar"));
449}
450
[email protected]8d86f13d2011-10-04 17:01:19451TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
[email protected]52d6c3202013-06-11 04:28:12452 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12453 v8::Local<v8::Context> context =
454 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23455 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50456 v8::MicrotasksScope microtasks(
457 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]786a7fa2011-04-22 21:27:12458
459 const char* source = "(function() {"
460 "var arr = [];"
461 "arr.__defineSetter__(0, "
462 " function() { throw new Error('muah!'); });"
463 "arr.__defineGetter__(0, "
464 " function() { throw new Error('muah!'); });"
465 "arr[1] = 'bar';"
466 "return arr;"
467 "})();";
468
Adam Klein8a35b5b2018-01-17 00:51:00469 v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source);
[email protected]786a7fa2011-04-22 21:27:12470
471 // Converting from v8 value should replace the first item with null.
[email protected]8d86f13d2011-10-04 17:01:19472 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27473 std::unique_ptr<base::ListValue> converted(
dcheng0232f572016-05-27 17:47:44474 base::ListValue::From(converter.FromV8Value(array, context)));
[email protected]786a7fa2011-04-22 21:27:12475 ASSERT_TRUE(converted.get());
476 // http://code.google.com/p/v8/issues/detail?id=1342
477 EXPECT_EQ(2u, converted->GetSize());
478 EXPECT_TRUE(IsNull(converted.get(), 0));
479
robb5bdf372016-04-27 11:27:06480 // Converting to v8 value should not be affected by the getter/setter
481 // because the setters/getters are defined on the array instance, not
482 // on the Array's prototype.
[email protected]0cd50aa2013-02-12 22:28:01483 converted.reset(static_cast<base::ListValue*>(
Lei Zhang9b9d5792019-02-20 07:24:42484 base::test::ParseJsonDeprecated("[ \"foo\", \"bar\" ]").release()));
deepak.s750d68f2015-04-30 07:32:41485 v8::Local<v8::Array> copy =
[email protected]52d6c3202013-06-11 04:28:12486 converter.ToV8Value(converted.get(), context).As<v8::Array>();
[email protected]786a7fa2011-04-22 21:27:12487 ASSERT_FALSE(copy.IsEmpty());
488 EXPECT_EQ(2u, copy->Length());
robb5bdf372016-04-27 11:27:06489 EXPECT_EQ("foo", GetString(copy, 0));
[email protected]786a7fa2011-04-22 21:27:12490 EXPECT_EQ("bar", GetString(copy, 1));
491}
492
[email protected]8d86f13d2011-10-04 17:01:19493TEST_F(V8ValueConverterImplTest, WeirdTypes) {
[email protected]52d6c3202013-06-11 04:28:12494 v8::HandleScope handle_scope(isolate_);
[email protected]d3c97d12013-12-02 12:19:23495 v8::Local<v8::Context> context =
496 v8::Local<v8::Context>::New(isolate_, context_);
497 v8::Context::Scope context_scope(context);
Jochen Eisingerd00cc712021-04-17 07:23:13498 v8::MicrotasksScope microtasks(isolate_,
499 v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]786a7fa2011-04-22 21:27:12500
Yang Guo9a47cd62018-01-16 08:05:32501 v8::Local<v8::RegExp> regex(
Camillo Brunie5440c762020-09-10 11:53:35502 v8::RegExp::New(context, v8::String::NewFromUtf8Literal(isolate_, "."),
503 v8::RegExp::kNone)
Yang Guo9a47cd62018-01-16 08:05:32504 .ToLocalChecked());
[email protected]786a7fa2011-04-22 21:27:12505
[email protected]8d86f13d2011-10-04 17:01:19506 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27507 TestWeirdType(converter, v8::Undefined(isolate_),
jdoerriedc72ee942016-12-07 15:43:28508 base::Value::Type::NONE, // Arbitrary type, result is NULL.
dchengc864f522016-04-08 23:55:27509 std::unique_ptr<base::Value>());
Yang Guodb90c522018-01-23 13:55:30510 TestWeirdType(converter, v8::Date::New(context, 1000).ToLocalChecked(),
jdoerriedc72ee942016-12-07 15:43:28511 base::Value::Type::DICTIONARY,
dchengc864f522016-04-08 23:55:27512 std::unique_ptr<base::Value>(new base::DictionaryValue()));
jdoerriedc72ee942016-12-07 15:43:28513 TestWeirdType(converter, regex, base::Value::Type::DICTIONARY,
dchengc864f522016-04-08 23:55:27514 std::unique_ptr<base::Value>(new base::DictionaryValue()));
[email protected]786a7fa2011-04-22 21:27:12515
[email protected]3de391e82012-05-16 17:50:51516 converter.SetDateAllowed(true);
Yang Guodb90c522018-01-23 13:55:30517 TestWeirdType(converter, v8::Date::New(context, 1000).ToLocalChecked(),
Peter Boströmdd7e40ec2021-04-05 20:40:10518 base::Value::Type::DOUBLE, std::make_unique<base::Value>(1.0));
[email protected]786a7fa2011-04-22 21:27:12519
[email protected]e0658bc2012-09-17 04:05:24520 converter.SetRegExpAllowed(true);
jdoerriedc72ee942016-12-07 15:43:28521 TestWeirdType(converter, regex, base::Value::Type::STRING,
Peter Boströmdd7e40ec2021-04-05 20:40:10522 std::make_unique<base::Value>("/./"));
[email protected]786a7fa2011-04-22 21:27:12523}
524
[email protected]8d86f13d2011-10-04 17:01:19525TEST_F(V8ValueConverterImplTest, Prototype) {
[email protected]52d6c3202013-06-11 04:28:12526 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12527 v8::Local<v8::Context> context =
528 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23529 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50530 v8::MicrotasksScope microtasks(
531 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]786a7fa2011-04-22 21:27:12532
533 const char* source = "(function() {"
534 "Object.prototype.foo = 'foo';"
535 "return {};"
536 "})();";
537
Adam Klein8a35b5b2018-01-17 00:51:00538 v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source);
[email protected]786a7fa2011-04-22 21:27:12539
[email protected]8d86f13d2011-10-04 17:01:19540 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27541 std::unique_ptr<base::DictionaryValue> result(
dcheng0232f572016-05-27 17:47:44542 base::DictionaryValue::From(converter.FromV8Value(object, context)));
[email protected]786a7fa2011-04-22 21:27:12543 ASSERT_TRUE(result.get());
Song Fangzhen2691dfe2021-05-07 11:59:58544 EXPECT_EQ(0u, result->DictSize());
[email protected]786a7fa2011-04-22 21:27:12545}
[email protected]2a521842012-05-30 09:17:06546
robb5bdf372016-04-27 11:27:06547TEST_F(V8ValueConverterImplTest, ObjectPrototypeSetter) {
548 std::unique_ptr<base::Value> original =
Lei Zhang9b9d5792019-02-20 07:24:42549 base::test::ParseJsonDeprecated("{ \"foo\": \"good value\" }");
robb5bdf372016-04-27 11:27:06550
551 v8::HandleScope handle_scope(isolate_);
552 v8::Local<v8::Context> context =
553 v8::Local<v8::Context>::New(isolate_, context_);
554 v8::Context::Scope context_scope(context);
555 v8::MicrotasksScope microtasks(isolate_,
556 v8::MicrotasksScope::kDoNotRunMicrotasks);
557
558 const char* source =
559 "var result = { getters: 0, setters: 0 };"
560 "Object.defineProperty(Object.prototype, 'foo', {"
561 " get() { ++result.getters; return 'bogus'; },"
562 " set() { ++result.setters; },"
563 "});"
564 "result;";
565
566 const char* source_sanity =
567 "({}).foo = 'Trigger setter';"
568 "({}).foo;";
569
Adam Klein8a35b5b2018-01-17 00:51:00570 v8::Local<v8::Object> result = CompileRun<v8::Object>(context, source);
robb5bdf372016-04-27 11:27:06571
572 // Sanity checks: the getters/setters are normally triggered.
Adam Klein8a35b5b2018-01-17 00:51:00573 CompileRun<v8::Value>(context, source_sanity);
robb5bdf372016-04-27 11:27:06574 EXPECT_EQ(1, GetInt(result, "getters"));
575 EXPECT_EQ(1, GetInt(result, "setters"));
576
577 V8ValueConverterImpl converter;
578 v8::Local<v8::Object> converted =
579 converter.ToV8Value(original.get(), context).As<v8::Object>();
580 EXPECT_FALSE(converted.IsEmpty());
581
582 // Getters/setters shouldn't be triggered.
583 EXPECT_EQ(1, GetInt(result, "getters"));
584 EXPECT_EQ(1, GetInt(result, "setters"));
585
Dan Elphickcc0832ef2018-12-24 11:31:23586 EXPECT_EQ(1u,
587 converted->GetPropertyNames(context).ToLocalChecked()->Length());
robb5bdf372016-04-27 11:27:06588 EXPECT_EQ("good value", GetString(converted, "foo"));
589
590 // Getters/setters shouldn't be triggered while accessing existing values.
591 EXPECT_EQ(1, GetInt(result, "getters"));
592 EXPECT_EQ(1, GetInt(result, "setters"));
593
594 // Repeat the same exercise with a dictionary without the key.
595 base::DictionaryValue missing_key_dict;
596 missing_key_dict.SetString("otherkey", "hello");
597 v8::Local<v8::Object> converted2 =
598 converter.ToV8Value(&missing_key_dict, context).As<v8::Object>();
599 EXPECT_FALSE(converted2.IsEmpty());
600
601 // Getters/setters shouldn't be triggered.
602 EXPECT_EQ(1, GetInt(result, "getters"));
603 EXPECT_EQ(1, GetInt(result, "setters"));
604
Dan Elphickcc0832ef2018-12-24 11:31:23605 EXPECT_EQ(1u,
606 converted2->GetPropertyNames(context).ToLocalChecked()->Length());
robb5bdf372016-04-27 11:27:06607 EXPECT_EQ("hello", GetString(converted2, "otherkey"));
608
609 // Missing key = should trigger getter upon access.
610 EXPECT_EQ("bogus", GetString(converted2, "foo"));
611 EXPECT_EQ(2, GetInt(result, "getters"));
612 EXPECT_EQ(1, GetInt(result, "setters"));
613}
614
615TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) {
616 std::unique_ptr<base::Value> original =
Lei Zhang9b9d5792019-02-20 07:24:42617 base::test::ParseJsonDeprecated("[100, 200, 300]");
robb5bdf372016-04-27 11:27:06618
619 v8::HandleScope handle_scope(isolate_);
620 v8::Local<v8::Context> context =
621 v8::Local<v8::Context>::New(isolate_, context_);
622 v8::Context::Scope context_scope(context);
623 v8::MicrotasksScope microtasks(isolate_,
624 v8::MicrotasksScope::kDoNotRunMicrotasks);
625
626 const char* source =
627 "var result = { getters: 0, setters: 0 };"
628 "Object.defineProperty(Array.prototype, '1', {"
629 " get() { ++result.getters; return 1337; },"
630 " set() { ++result.setters; },"
631 "});"
632 "result;";
633
634 const char* source_sanity =
635 "[][1] = 'Trigger setter';"
636 "[][1];";
637
Adam Klein8a35b5b2018-01-17 00:51:00638 v8::Local<v8::Object> result = CompileRun<v8::Object>(context, source);
robb5bdf372016-04-27 11:27:06639
640 // Sanity checks: the getters/setters are normally triggered.
Adam Klein8a35b5b2018-01-17 00:51:00641 CompileRun<v8::Value>(context, source_sanity);
robb5bdf372016-04-27 11:27:06642 EXPECT_EQ(1, GetInt(result, "getters"));
643 EXPECT_EQ(1, GetInt(result, "setters"));
644
645 V8ValueConverterImpl converter;
646 v8::Local<v8::Array> converted =
647 converter.ToV8Value(original.get(), context).As<v8::Array>();
648 EXPECT_FALSE(converted.IsEmpty());
649
650 // Getters/setters shouldn't be triggered during the conversion.
651 EXPECT_EQ(1, GetInt(result, "getters"));
652 EXPECT_EQ(1, GetInt(result, "setters"));
653
654 EXPECT_EQ(3u, converted->Length());
655 EXPECT_EQ(100, GetInt(converted, 0));
656 EXPECT_EQ(200, GetInt(converted, 1));
657 EXPECT_EQ(300, GetInt(converted, 2));
658
659 // Getters/setters shouldn't be triggered while accessing existing values.
660 EXPECT_EQ(1, GetInt(result, "getters"));
661 EXPECT_EQ(1, GetInt(result, "setters"));
662
663 // Try again, using an array without the index.
664 base::ListValue one_item_list;
dcheng33f3dc9f2016-06-03 02:38:23665 one_item_list.AppendInteger(123456);
robb5bdf372016-04-27 11:27:06666 v8::Local<v8::Array> converted2 =
667 converter.ToV8Value(&one_item_list, context).As<v8::Array>();
668 EXPECT_FALSE(converted2.IsEmpty());
669
670 // Getters/setters shouldn't be triggered during the conversion.
671 EXPECT_EQ(1, GetInt(result, "getters"));
672 EXPECT_EQ(1, GetInt(result, "setters"));
673
674 EXPECT_EQ(1u, converted2->Length());
675 EXPECT_EQ(123456, GetInt(converted2, 0));
676
677 // Accessing missing index 1 triggers the getter.
678 EXPECT_EQ(1337, GetInt(converted2, 1));
679 EXPECT_EQ(2, GetInt(result, "getters"));
680 EXPECT_EQ(1, GetInt(result, "setters"));
681}
682
[email protected]2a521842012-05-30 09:17:06683TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
[email protected]52d6c3202013-06-11 04:28:12684 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12685 v8::Local<v8::Context> context =
686 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23687 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50688 v8::MicrotasksScope microtasks(
689 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]2a521842012-05-30 09:17:06690
691 const char* source = "(function() {"
692 "return { foo: undefined, bar: null };"
693 "})();";
694
Adam Klein8a35b5b2018-01-17 00:51:00695 v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source);
[email protected]2a521842012-05-30 09:17:06696
697 V8ValueConverterImpl converter;
[email protected]2a521842012-05-30 09:17:06698 converter.SetStripNullFromObjects(true);
699
dchengc864f522016-04-08 23:55:27700 std::unique_ptr<base::DictionaryValue> result(
dcheng0232f572016-05-27 17:47:44701 base::DictionaryValue::From(converter.FromV8Value(object, context)));
[email protected]2a521842012-05-30 09:17:06702 ASSERT_TRUE(result.get());
Song Fangzhen2691dfe2021-05-07 11:59:58703 EXPECT_EQ(0u, result->DictSize());
[email protected]2a521842012-05-30 09:17:06704}
[email protected]217d9562012-07-16 21:57:37705
706TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
[email protected]52d6c3202013-06-11 04:28:12707 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12708 v8::Local<v8::Context> context =
709 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23710 v8::Context::Scope context_scope(context);
Jochen Eisingerd00cc712021-04-17 07:23:13711 v8::MicrotasksScope microtasks(isolate_,
712 v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]217d9562012-07-16 21:57:37713
714 V8ValueConverterImpl converter;
715
deepak.s750d68f2015-04-30 07:32:41716 v8::Local<v8::Object> object = v8::Object::New(isolate_).As<v8::Object>();
[email protected]217d9562012-07-16 21:57:37717 ASSERT_FALSE(object.IsEmpty());
Dan Elphickcc7538d02019-02-01 13:41:47718 object
719 ->Set(context,
720 v8::String::NewFromUtf8(isolate_, "foo",
721 v8::NewStringType::kInternalized)
722 .ToLocalChecked(),
Camillo Brunie5440c762020-09-10 11:53:35723 v8::String::NewFromUtf8Literal(isolate_, "bar"))
Dan Elphickcc7538d02019-02-01 13:41:47724 .Check();
725 object
726 ->Set(context,
727 v8::String::NewFromUtf8(isolate_, "obj",
728 v8::NewStringType::kInternalized)
729 .ToLocalChecked(),
730 object)
731 .Check();
[email protected]217d9562012-07-16 21:57:37732
dchengc864f522016-04-08 23:55:27733 std::unique_ptr<base::DictionaryValue> object_result(
dcheng0232f572016-05-27 17:47:44734 base::DictionaryValue::From(converter.FromV8Value(object, context)));
[email protected]217d9562012-07-16 21:57:37735 ASSERT_TRUE(object_result.get());
Song Fangzhen2691dfe2021-05-07 11:59:58736 EXPECT_EQ(2u, object_result->DictSize());
[email protected]217d9562012-07-16 21:57:37737 EXPECT_TRUE(IsNull(object_result.get(), "obj"));
738
deepak.s750d68f2015-04-30 07:32:41739 v8::Local<v8::Array> array = v8::Array::New(isolate_).As<v8::Array>();
[email protected]217d9562012-07-16 21:57:37740 ASSERT_FALSE(array.IsEmpty());
Camillo Brunie5440c762020-09-10 11:53:35741 array->Set(context, 0, v8::String::NewFromUtf8Literal(isolate_, "1")).Check();
Dan Elphickcc7538d02019-02-01 13:41:47742 array->Set(context, 1, array).Check();
[email protected]217d9562012-07-16 21:57:37743
dchengc864f522016-04-08 23:55:27744 std::unique_ptr<base::ListValue> list_result(
dcheng0232f572016-05-27 17:47:44745 base::ListValue::From(converter.FromV8Value(array, context)));
[email protected]217d9562012-07-16 21:57:37746 ASSERT_TRUE(list_result.get());
747 EXPECT_EQ(2u, list_result->GetSize());
748 EXPECT_TRUE(IsNull(list_result.get(), 1));
749}
750
[email protected]74baf972012-09-13 02:46:39751TEST_F(V8ValueConverterImplTest, WeirdProperties) {
[email protected]52d6c3202013-06-11 04:28:12752 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12753 v8::Local<v8::Context> context =
754 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23755 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50756 v8::MicrotasksScope microtasks(
757 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]74baf972012-09-13 02:46:39758
759 const char* source = "(function() {"
760 "return {"
761 "1: 'foo',"
762 "'2': 'bar',"
763 "true: 'baz',"
764 "false: 'qux',"
765 "null: 'quux',"
766 "undefined: 'oops'"
767 "};"
768 "})();";
769
Adam Klein8a35b5b2018-01-17 00:51:00770 v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source);
[email protected]74baf972012-09-13 02:46:39771
772 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27773 std::unique_ptr<base::Value> actual(converter.FromV8Value(object, context));
[email protected]74baf972012-09-13 02:46:39774
Lei Zhang9b9d5792019-02-20 07:24:42775 std::unique_ptr<base::Value> expected = base::test::ParseJsonDeprecated(
[email protected]06d19d82012-12-17 21:45:37776 "{ \n"
777 " \"1\": \"foo\", \n"
778 " \"2\": \"bar\", \n"
779 " \"true\": \"baz\", \n"
780 " \"false\": \"qux\", \n"
781 " \"null\": \"quux\", \n"
782 " \"undefined\": \"oops\", \n"
783 "}");
[email protected]74baf972012-09-13 02:46:39784
[email protected]06d19d82012-12-17 21:45:37785 EXPECT_TRUE(expected->Equals(actual.get()));
[email protected]74baf972012-09-13 02:46:39786}
787
[email protected]217d9562012-07-16 21:57:37788TEST_F(V8ValueConverterImplTest, ArrayGetters) {
[email protected]52d6c3202013-06-11 04:28:12789 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12790 v8::Local<v8::Context> context =
791 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23792 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50793 v8::MicrotasksScope microtasks(
794 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]217d9562012-07-16 21:57:37795
796 const char* source = "(function() {"
797 "var a = [0];"
798 "a.__defineGetter__(1, function() { return 'bar'; });"
799 "return a;"
800 "})();";
801
Adam Klein8a35b5b2018-01-17 00:51:00802 v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source);
[email protected]217d9562012-07-16 21:57:37803
804 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:27805 std::unique_ptr<base::ListValue> result(
dcheng0232f572016-05-27 17:47:44806 base::ListValue::From(converter.FromV8Value(array, context)));
[email protected]217d9562012-07-16 21:57:37807 ASSERT_TRUE(result.get());
808 EXPECT_EQ(2u, result->GetSize());
809}
[email protected]e0658bc2012-09-17 04:05:24810
811TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
[email protected]52d6c3202013-06-11 04:28:12812 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12813 v8::Local<v8::Context> context =
814 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23815 v8::Context::Scope context_scope(context);
dgozman8ce19432016-03-16 22:30:50816 v8::MicrotasksScope microtasks(
817 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]e0658bc2012-09-17 04:05:24818
deepak.s750d68f2015-04-30 07:32:41819 v8::Local<v8::Object> object;
[email protected]e0658bc2012-09-17 04:05:24820 {
821 const char* source = "(function() {"
822 "return { foo: undefined, bar: null, baz: function(){} };"
823 "})();";
Adam Klein8a35b5b2018-01-17 00:51:00824 object = CompileRun<v8::Object>(context, source);
[email protected]e0658bc2012-09-17 04:05:24825 }
826
deepak.s750d68f2015-04-30 07:32:41827 v8::Local<v8::Array> array;
[email protected]e0658bc2012-09-17 04:05:24828 {
829 const char* source = "(function() {"
830 "return [ undefined, null, function(){} ];"
831 "})();";
Adam Klein8a35b5b2018-01-17 00:51:00832 array = CompileRun<v8::Array>(context, source);
[email protected]e0658bc2012-09-17 04:05:24833 }
834
deepak.s750d68f2015-04-30 07:32:41835 v8::Local<v8::Array> sparse_array;
[email protected]719ffd32014-04-23 13:12:55836 {
837 const char* source = "(function() {"
838 "return new Array(3);"
839 "})();";
Adam Klein8a35b5b2018-01-17 00:51:00840 sparse_array = CompileRun<v8::Array>(context, source);
[email protected]719ffd32014-04-23 13:12:55841 }
842
[email protected]e0658bc2012-09-17 04:05:24843 V8ValueConverterImpl converter;
844
dchengc864f522016-04-08 23:55:27845 std::unique_ptr<base::Value> actual_object(
[email protected]52d6c3202013-06-11 04:28:12846 converter.FromV8Value(object, context));
Lei Zhang9b9d5792019-02-20 07:24:42847 EXPECT_EQ(*base::test::ParseJsonDeprecated("{ \"bar\": null }"),
848 *actual_object);
[email protected]e0658bc2012-09-17 04:05:24849
[email protected]e0658bc2012-09-17 04:05:24850 // Everything is null because JSON stringification preserves array length.
dchengc864f522016-04-08 23:55:27851 std::unique_ptr<base::Value> actual_array(
852 converter.FromV8Value(array, context));
Lei Zhang9b9d5792019-02-20 07:24:42853 EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"),
854 *actual_array);
[email protected]719ffd32014-04-23 13:12:55855
dchengc864f522016-04-08 23:55:27856 std::unique_ptr<base::Value> actual_sparse_array(
[email protected]719ffd32014-04-23 13:12:55857 converter.FromV8Value(sparse_array, context));
Lei Zhang9b9d5792019-02-20 07:24:42858 EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"),
jdoerrie8551f922017-07-25 10:55:13859 *actual_sparse_array);
[email protected]e0658bc2012-09-17 04:05:24860}
[email protected]9a292e22012-10-22 15:19:31861
[email protected]6a9b7372013-03-20 15:35:20862TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
[email protected]52d6c3202013-06-11 04:28:12863 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12864 v8::Local<v8::Context> context =
865 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23866 v8::Context::Scope context_scope(context);
Jochen Eisingerd00cc712021-04-17 07:23:13867 v8::MicrotasksScope microtasks(isolate_,
868 v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]6a9b7372013-03-20 15:35:20869 V8ValueConverterImpl converter;
870
871 // We check that the converter checks identity correctly by disabling the
872 // optimization of using identity hashes.
873 ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter);
874
875 // Create the v8::Object to be converted.
deepak.s750d68f2015-04-30 07:32:41876 v8::Local<v8::Array> root(v8::Array::New(isolate_, 4));
Dan Elphickcc7538d02019-02-01 13:41:47877 root->Set(context, 0, v8::Local<v8::Object>(v8::Object::New(isolate_)))
878 .Check();
879 root->Set(context, 1, v8::Local<v8::Object>(v8::Object::New(isolate_)))
880 .Check();
881 root->Set(context, 2, v8::Local<v8::Object>(v8::Array::New(isolate_, 0)))
882 .Check();
883 root->Set(context, 3, v8::Local<v8::Object>(v8::Array::New(isolate_, 0)))
884 .Check();
[email protected]6a9b7372013-03-20 15:35:20885
886 // The expected base::Value result.
dchengc864f522016-04-08 23:55:27887 std::unique_ptr<base::Value> expected =
Lei Zhang9b9d5792019-02-20 07:24:42888 base::test::ParseJsonDeprecated("[{},{},[],[]]");
[email protected]6a9b7372013-03-20 15:35:20889 ASSERT_TRUE(expected.get());
890
891 // The actual result.
dchengc864f522016-04-08 23:55:27892 std::unique_ptr<base::Value> value(converter.FromV8Value(root, context));
[email protected]6a9b7372013-03-20 15:35:20893 ASSERT_TRUE(value.get());
894
895 EXPECT_TRUE(expected->Equals(value.get()));
896}
897
898TEST_F(V8ValueConverterImplTest, DetectCycles) {
[email protected]52d6c3202013-06-11 04:28:12899 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:12900 v8::Local<v8::Context> context =
901 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:23902 v8::Context::Scope context_scope(context);
Jochen Eisingerd00cc712021-04-17 07:23:13903 v8::MicrotasksScope microtasks(isolate_,
904 v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]6a9b7372013-03-20 15:35:20905 V8ValueConverterImpl converter;
906
907 // Create a recursive array.
deepak.s750d68f2015-04-30 07:32:41908 v8::Local<v8::Array> recursive_array(v8::Array::New(isolate_, 1));
Dan Elphickcc7538d02019-02-01 13:41:47909 recursive_array->Set(context, 0, recursive_array).Check();
[email protected]6a9b7372013-03-20 15:35:20910
911 // The first repetition should be trimmed and replaced by a null value.
912 base::ListValue expected_list;
Jeremy Roman04f27c372017-10-27 15:20:55913 expected_list.Append(std::make_unique<base::Value>());
[email protected]6a9b7372013-03-20 15:35:20914
915 // The actual result.
dchengc864f522016-04-08 23:55:27916 std::unique_ptr<base::Value> actual_list(
[email protected]52d6c3202013-06-11 04:28:12917 converter.FromV8Value(recursive_array, context));
[email protected]6a9b7372013-03-20 15:35:20918 ASSERT_TRUE(actual_list.get());
919
920 EXPECT_TRUE(expected_list.Equals(actual_list.get()));
921
922 // Now create a recursive object
923 const std::string key("key");
deepak.s750d68f2015-04-30 07:32:41924 v8::Local<v8::Object> recursive_object(v8::Object::New(isolate_));
Dan Elphickcc7538d02019-02-01 13:41:47925 recursive_object
926 ->Set(context,
927 v8::String::NewFromUtf8(isolate_, key.c_str(),
928 v8::NewStringType::kInternalized,
929 key.length())
930 .ToLocalChecked(),
931 recursive_object)
932 .Check();
[email protected]6a9b7372013-03-20 15:35:20933
934 // The first repetition should be trimmed and replaced by a null value.
935 base::DictionaryValue expected_dictionary;
Jeremy Roman04f27c372017-10-27 15:20:55936 expected_dictionary.Set(key, std::make_unique<base::Value>());
[email protected]6a9b7372013-03-20 15:35:20937
938 // The actual result.
dchengc864f522016-04-08 23:55:27939 std::unique_ptr<base::Value> actual_dictionary(
[email protected]52d6c3202013-06-11 04:28:12940 converter.FromV8Value(recursive_object, context));
[email protected]6a9b7372013-03-20 15:35:20941 ASSERT_TRUE(actual_dictionary.get());
942
943 EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get()));
944}
945
lazyboy275ec3e2016-05-04 18:04:24946// Tests that reused object values with no cycles do not get nullified.
947TEST_F(V8ValueConverterImplTest, ReuseObjects) {
948 v8::HandleScope handle_scope(isolate_);
949 v8::Local<v8::Context> context =
950 v8::Local<v8::Context>::New(isolate_, context_);
951 v8::Context::Scope context_scope(context);
952 v8::MicrotasksScope microtasks(
953 isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
954 V8ValueConverterImpl converter;
955
956 // Object with reused values in different keys.
957 {
958 const char* source = "(function() {"
959 "var objA = {key: 'another same value'};"
960 "var obj = {one: objA, two: objA};"
961 "return obj;"
962 "})();";
Adam Klein8a35b5b2018-01-17 00:51:00963 v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source);
lazyboy275ec3e2016-05-04 18:04:24964
965 // The actual result.
966 std::unique_ptr<base::DictionaryValue> result(
dcheng0232f572016-05-27 17:47:44967 base::DictionaryValue::From(converter.FromV8Value(object, context)));
lazyboy275ec3e2016-05-04 18:04:24968 ASSERT_TRUE(result.get());
Song Fangzhen2691dfe2021-05-07 11:59:58969 EXPECT_EQ(2u, result->DictSize());
lazyboy275ec3e2016-05-04 18:04:24970
971 {
972 base::DictionaryValue* one_dict = nullptr;
973 const char* key1 = "one";
974 ASSERT_TRUE(result->GetDictionary(key1, &one_dict));
975 EXPECT_EQ("another same value", GetString(one_dict, "key"));
976 }
977 {
978 base::DictionaryValue* two_dict = nullptr;
979 const char* key2 = "two";
980 ASSERT_TRUE(result->GetDictionary(key2, &two_dict));
981 EXPECT_EQ("another same value", GetString(two_dict, "key"));
982 }
983 }
984
985 // Array with reused values.
986 {
987 const char* source = "(function() {"
988 "var objA = {key: 'same value'};"
989 "var arr = [objA, objA];"
990 "return arr;"
991 "})();";
Adam Klein8a35b5b2018-01-17 00:51:00992 v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source);
lazyboy275ec3e2016-05-04 18:04:24993
994 // The actual result.
995 std::unique_ptr<base::ListValue> list_result(
dcheng0232f572016-05-27 17:47:44996 base::ListValue::From(converter.FromV8Value(array, context)));
lazyboy275ec3e2016-05-04 18:04:24997 ASSERT_TRUE(list_result.get());
998 ASSERT_EQ(2u, list_result->GetSize());
999 for (size_t i = 0; i < list_result->GetSize(); ++i) {
1000 ASSERT_FALSE(IsNull(list_result.get(), i));
1001 base::DictionaryValue* dict_value = nullptr;
1002 ASSERT_TRUE(list_result->GetDictionary(0u, &dict_value));
1003 EXPECT_EQ("same value", GetString(dict_value, "key"));
1004 }
1005 }
1006}
1007
[email protected]195487f2013-06-10 14:20:411008TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
[email protected]52d6c3202013-06-11 04:28:121009 v8::HandleScope handle_scope(isolate_);
[email protected]52d6c3202013-06-11 04:28:121010 v8::Local<v8::Context> context =
1011 v8::Local<v8::Context>::New(isolate_, context_);
[email protected]d3c97d12013-12-02 12:19:231012 v8::Context::Scope context_scope(context);
Jochen Eisingerd00cc712021-04-17 07:23:131013 v8::MicrotasksScope microtasks(isolate_,
1014 v8::MicrotasksScope::kDoNotRunMicrotasks);
[email protected]195487f2013-06-10 14:20:411015
1016 // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc.
[email protected]6e69b002013-09-12 20:58:571017 int kDepth = 1000;
[email protected]195487f2013-06-10 14:20:411018 const char kKey[] = "key";
1019
[email protected]f65a23262014-01-03 20:12:031020 v8::Local<v8::Object> deep_object = v8::Object::New(isolate_);
[email protected]195487f2013-06-10 14:20:411021
1022 v8::Local<v8::Object> leaf = deep_object;
1023 for (int i = 0; i < kDepth; ++i) {
[email protected]f65a23262014-01-03 20:12:031024 v8::Local<v8::Object> new_object = v8::Object::New(isolate_);
Dan Elphickcc7538d02019-02-01 13:41:471025 leaf->Set(context,
1026 v8::String::NewFromUtf8(isolate_, kKey,
Yang Guo26b0f7772018-11-27 08:37:201027 v8::NewStringType::kInternalized)
1028 .ToLocalChecked(),
Dan Elphickcc7538d02019-02-01 13:41:471029 new_object)
1030 .Check();
[email protected]195487f2013-06-10 14:20:411031 leaf = new_object;
1032 }
1033
1034 V8ValueConverterImpl converter;
dchengc864f522016-04-08 23:55:271035 std::unique_ptr<base::Value> value(
1036 converter.FromV8Value(deep_object, context));
[email protected]195487f2013-06-10 14:20:411037 ASSERT_TRUE(value);
1038
1039 // Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc.
[email protected]6e69b002013-09-12 20:58:571040 int kExpectedDepth = 100;
[email protected]195487f2013-06-10 14:20:411041
1042 base::Value* current = value.get();
1043 for (int i = 1; i < kExpectedDepth; ++i) {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:281044 base::DictionaryValue* current_as_object = nullptr;
[email protected]195487f2013-06-10 14:20:411045 ASSERT_TRUE(current->GetAsDictionary(&current_as_object)) << i;
1046 ASSERT_TRUE(current_as_object->Get(kKey, &current)) << i;
1047 }
1048
1049 // The leaf node shouldn't have any properties.
1050 base::DictionaryValue empty;
jdoerrie8551f922017-07-25 10:55:131051 EXPECT_EQ(empty, *current) << *current;
[email protected]195487f2013-06-10 14:20:411052}
1053
rdevlin.croninf88f9bc22017-02-24 17:09:301054TEST_F(V8ValueConverterImplTest, NegativeZero) {
1055 v8::HandleScope handle_scope(isolate_);
1056 v8::Local<v8::Context> context =
1057 v8::Local<v8::Context>::New(isolate_, context_);
1058 v8::MicrotasksScope microtasks(isolate_,
1059 v8::MicrotasksScope::kDoNotRunMicrotasks);
1060
1061 v8::Context::Scope context_scope(context);
1062 const char* source = "(function() { return -0; })();";
1063
Adam Klein8a35b5b2018-01-17 00:51:001064 v8::Local<v8::Value> value = CompileRun<v8::Value>(context, source);
rdevlin.croninf88f9bc22017-02-24 17:09:301065
1066 {
1067 V8ValueConverterImpl converter;
1068 std::unique_ptr<base::Value> result = converter.FromV8Value(value, context);
1069 ASSERT_TRUE(result->is_double())
1070 << base::Value::GetTypeName(result->type());
1071 EXPECT_EQ(0, result->GetDouble());
1072 }
1073 {
1074 V8ValueConverterImpl converter;
1075 converter.SetConvertNegativeZeroToInt(true);
1076 std::unique_ptr<base::Value> result = converter.FromV8Value(value, context);
1077 ASSERT_TRUE(result->is_int()) << base::Value::GetTypeName(result->type());
1078 EXPECT_EQ(0, result->GetInt());
1079 }
1080}
1081
[email protected]551b8642014-04-25 09:07:071082class V8ValueConverterOverridingStrategyForTesting
1083 : public V8ValueConverter::Strategy {
1084 public:
1085 V8ValueConverterOverridingStrategyForTesting()
1086 : reference_value_(NewReferenceValue()) {}
deepak.s750d68f2015-04-30 07:32:411087 bool FromV8Object(v8::Local<v8::Object> value,
dcheng0232f572016-05-27 17:47:441088 std::unique_ptr<base::Value>* out,
danakjab3475802019-05-22 19:05:171089 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071090 *out = NewReferenceValue();
1091 return true;
1092 }
deepak.s750d68f2015-04-30 07:32:411093 bool FromV8Array(v8::Local<v8::Array> value,
dcheng0232f572016-05-27 17:47:441094 std::unique_ptr<base::Value>* out,
danakjab3475802019-05-22 19:05:171095 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071096 *out = NewReferenceValue();
1097 return true;
1098 }
deepak.s750d68f2015-04-30 07:32:411099 bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
dcheng0232f572016-05-27 17:47:441100 std::unique_ptr<base::Value>* out,
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491101 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071102 *out = NewReferenceValue();
1103 return true;
1104 }
deepak.s750d68f2015-04-30 07:32:411105 bool FromV8Number(v8::Local<v8::Number> value,
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491106 std::unique_ptr<base::Value>* out) override {
[email protected]551b8642014-04-25 09:07:071107 *out = NewReferenceValue();
1108 return true;
1109 }
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491110 bool FromV8Undefined(std::unique_ptr<base::Value>* out) override {
[email protected]551b8642014-04-25 09:07:071111 *out = NewReferenceValue();
1112 return true;
1113 }
1114 base::Value* reference_value() const { return reference_value_.get(); }
1115
1116 private:
dcheng0232f572016-05-27 17:47:441117 static std::unique_ptr<base::Value> NewReferenceValue() {
Jeremy Roman04f27c372017-10-27 15:20:551118 return std::make_unique<base::Value>("strategy");
[email protected]551b8642014-04-25 09:07:071119 }
dchengc864f522016-04-08 23:55:271120 std::unique_ptr<base::Value> reference_value_;
[email protected]551b8642014-04-25 09:07:071121};
1122
1123TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
1124 v8::HandleScope handle_scope(isolate_);
1125 v8::Local<v8::Context> context =
1126 v8::Local<v8::Context>::New(isolate_, context_);
1127 v8::Context::Scope context_scope(context);
1128
1129 V8ValueConverterImpl converter;
1130 V8ValueConverterOverridingStrategyForTesting strategy;
1131 converter.SetStrategy(&strategy);
1132
deepak.s750d68f2015-04-30 07:32:411133 v8::Local<v8::Object> object(v8::Object::New(isolate_));
dchengc864f522016-04-08 23:55:271134 std::unique_ptr<base::Value> object_value(
1135 converter.FromV8Value(object, context));
[email protected]551b8642014-04-25 09:07:071136 ASSERT_TRUE(object_value);
jdoerrie8551f922017-07-25 10:55:131137 EXPECT_EQ(*strategy.reference_value(), *object_value);
[email protected]551b8642014-04-25 09:07:071138
deepak.s750d68f2015-04-30 07:32:411139 v8::Local<v8::Array> array(v8::Array::New(isolate_));
dchengc864f522016-04-08 23:55:271140 std::unique_ptr<base::Value> array_value(
1141 converter.FromV8Value(array, context));
[email protected]551b8642014-04-25 09:07:071142 ASSERT_TRUE(array_value);
jdoerrie8551f922017-07-25 10:55:131143 EXPECT_EQ(*strategy.reference_value(), *array_value);
[email protected]551b8642014-04-25 09:07:071144
deepak.s750d68f2015-04-30 07:32:411145 v8::Local<v8::ArrayBuffer> array_buffer(v8::ArrayBuffer::New(isolate_, 0));
dchengc864f522016-04-08 23:55:271146 std::unique_ptr<base::Value> array_buffer_value(
[email protected]551b8642014-04-25 09:07:071147 converter.FromV8Value(array_buffer, context));
1148 ASSERT_TRUE(array_buffer_value);
jdoerrie8551f922017-07-25 10:55:131149 EXPECT_EQ(*strategy.reference_value(), *array_buffer_value);
[email protected]551b8642014-04-25 09:07:071150
deepak.s750d68f2015-04-30 07:32:411151 v8::Local<v8::ArrayBufferView> array_buffer_view(
[email protected]551b8642014-04-25 09:07:071152 v8::Uint8Array::New(array_buffer, 0, 0));
dchengc864f522016-04-08 23:55:271153 std::unique_ptr<base::Value> array_buffer_view_value(
[email protected]551b8642014-04-25 09:07:071154 converter.FromV8Value(array_buffer_view, context));
1155 ASSERT_TRUE(array_buffer_view_value);
jdoerrie8551f922017-07-25 10:55:131156 EXPECT_EQ(*strategy.reference_value(), *array_buffer_view_value);
[email protected]551b8642014-04-25 09:07:071157
deepak.s750d68f2015-04-30 07:32:411158 v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0));
dchengc864f522016-04-08 23:55:271159 std::unique_ptr<base::Value> number_value(
1160 converter.FromV8Value(number, context));
[email protected]551b8642014-04-25 09:07:071161 ASSERT_TRUE(number_value);
jdoerrie8551f922017-07-25 10:55:131162 EXPECT_EQ(*strategy.reference_value(), *number_value);
[email protected]551b8642014-04-25 09:07:071163
deepak.s750d68f2015-04-30 07:32:411164 v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
dchengc864f522016-04-08 23:55:271165 std::unique_ptr<base::Value> undefined_value(
[email protected]551b8642014-04-25 09:07:071166 converter.FromV8Value(undefined, context));
1167 ASSERT_TRUE(undefined_value);
jdoerrie8551f922017-07-25 10:55:131168 EXPECT_EQ(*strategy.reference_value(), *undefined_value);
[email protected]551b8642014-04-25 09:07:071169}
1170
1171class V8ValueConverterBypassStrategyForTesting
1172 : public V8ValueConverter::Strategy {
1173 public:
deepak.s750d68f2015-04-30 07:32:411174 bool FromV8Object(v8::Local<v8::Object> value,
dcheng0232f572016-05-27 17:47:441175 std::unique_ptr<base::Value>* out,
danakjab3475802019-05-22 19:05:171176 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071177 return false;
1178 }
deepak.s750d68f2015-04-30 07:32:411179 bool FromV8Array(v8::Local<v8::Array> value,
dcheng0232f572016-05-27 17:47:441180 std::unique_ptr<base::Value>* out,
danakjab3475802019-05-22 19:05:171181 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071182 return false;
1183 }
deepak.s750d68f2015-04-30 07:32:411184 bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
dcheng0232f572016-05-27 17:47:441185 std::unique_ptr<base::Value>* out,
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491186 v8::Isolate* isolate) override {
[email protected]551b8642014-04-25 09:07:071187 return false;
1188 }
deepak.s750d68f2015-04-30 07:32:411189 bool FromV8Number(v8::Local<v8::Number> value,
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491190 std::unique_ptr<base::Value>* out) override {
[email protected]551b8642014-04-25 09:07:071191 return false;
1192 }
Lucas Furukawa Gadanid51ff5d62018-12-07 21:26:491193 bool FromV8Undefined(std::unique_ptr<base::Value>* out) override {
dcheng0232f572016-05-27 17:47:441194 return false;
1195 }
[email protected]551b8642014-04-25 09:07:071196};
1197
1198// Verify that having a strategy that fallbacks to default behaviour
1199// actually preserves it.
1200TEST_F(V8ValueConverterImplTest, StrategyBypass) {
1201 v8::HandleScope handle_scope(isolate_);
1202 v8::Local<v8::Context> context =
1203 v8::Local<v8::Context>::New(isolate_, context_);
1204 v8::Context::Scope context_scope(context);
1205
1206 V8ValueConverterImpl converter;
1207 V8ValueConverterBypassStrategyForTesting strategy;
1208 converter.SetStrategy(&strategy);
1209
deepak.s750d68f2015-04-30 07:32:411210 v8::Local<v8::Object> object(v8::Object::New(isolate_));
dchengc864f522016-04-08 23:55:271211 std::unique_ptr<base::Value> object_value(
1212 converter.FromV8Value(object, context));
[email protected]551b8642014-04-25 09:07:071213 ASSERT_TRUE(object_value);
dchengc864f522016-04-08 23:55:271214 std::unique_ptr<base::Value> reference_object_value(
Lei Zhang9b9d5792019-02-20 07:24:421215 base::test::ParseJsonDeprecated("{}"));
jdoerrie8551f922017-07-25 10:55:131216 EXPECT_EQ(*reference_object_value, *object_value);
[email protected]551b8642014-04-25 09:07:071217
deepak.s750d68f2015-04-30 07:32:411218 v8::Local<v8::Array> array(v8::Array::New(isolate_));
dchengc864f522016-04-08 23:55:271219 std::unique_ptr<base::Value> array_value(
1220 converter.FromV8Value(array, context));
[email protected]551b8642014-04-25 09:07:071221 ASSERT_TRUE(array_value);
dchengc864f522016-04-08 23:55:271222 std::unique_ptr<base::Value> reference_array_value(
Lei Zhang9b9d5792019-02-20 07:24:421223 base::test::ParseJsonDeprecated("[]"));
jdoerrie8551f922017-07-25 10:55:131224 EXPECT_EQ(*reference_array_value, *array_value);
[email protected]551b8642014-04-25 09:07:071225
jbroman54311d02017-02-08 15:11:391226 const char kExampleData[] = {1, 2, 3, 4, 5};
1227 v8::Local<v8::ArrayBuffer> array_buffer(
1228 v8::ArrayBuffer::New(isolate_, sizeof(kExampleData)));
Ulan Degenbaevccd07752021-03-03 17:59:201229 memcpy(array_buffer->GetBackingStore()->Data(), kExampleData,
jbroman54311d02017-02-08 15:11:391230 sizeof(kExampleData));
1231 std::unique_ptr<base::Value> binary_value(
1232 converter.FromV8Value(array_buffer, context));
1233 ASSERT_TRUE(binary_value);
Lei Zhang204812442020-10-24 00:51:021234 base::Value reference_binary_value(
1235 base::as_bytes(base::make_span(kExampleData)));
1236 EXPECT_EQ(reference_binary_value, *binary_value);
jbroman54311d02017-02-08 15:11:391237
1238 v8::Local<v8::ArrayBufferView> array_buffer_view(
1239 v8::Uint8Array::New(array_buffer, 1, 3));
1240 std::unique_ptr<base::Value> binary_view_value(
1241 converter.FromV8Value(array_buffer_view, context));
1242 ASSERT_TRUE(binary_view_value);
Lei Zhang204812442020-10-24 00:51:021243 base::Value reference_binary_view_value(
1244 base::as_bytes(base::make_span(kExampleData).subspan(1, 3)));
1245 EXPECT_EQ(reference_binary_view_value, *binary_view_value);
[email protected]551b8642014-04-25 09:07:071246
deepak.s750d68f2015-04-30 07:32:411247 v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0));
dchengc864f522016-04-08 23:55:271248 std::unique_ptr<base::Value> number_value(
1249 converter.FromV8Value(number, context));
[email protected]551b8642014-04-25 09:07:071250 ASSERT_TRUE(number_value);
dchengc864f522016-04-08 23:55:271251 std::unique_ptr<base::Value> reference_number_value(
Lei Zhang9b9d5792019-02-20 07:24:421252 base::test::ParseJsonDeprecated("0"));
jdoerrie8551f922017-07-25 10:55:131253 EXPECT_EQ(*reference_number_value, *number_value);
[email protected]551b8642014-04-25 09:07:071254
deepak.s750d68f2015-04-30 07:32:411255 v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
dchengc864f522016-04-08 23:55:271256 std::unique_ptr<base::Value> undefined_value(
[email protected]551b8642014-04-25 09:07:071257 converter.FromV8Value(undefined, context));
1258 EXPECT_FALSE(undefined_value);
1259}
1260
[email protected]9a292e22012-10-22 15:19:311261} // namespace content