[email protected] | 3de391e8 | 2012-05-16 17:50:51 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 2 | // 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-Malek | 312a30bb | 2017-10-23 19:51:52 | [diff] [blame] | 5 | #include "content/renderer/v8_value_converter_impl.h" |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 6 | |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | #include <stdint.h> |
| 9 | |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 10 | #include <cmath> |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 11 | #include <memory> |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 12 | |
Lei Zhang | 20481244 | 2020-10-24 00:51:02 | [diff] [blame] | 13 | #include "base/containers/span.h" |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 14 | #include "base/macros.h" |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 15 | #include "base/stl_util.h" |
Gabriel Charette | c710874 | 2019-08-23 03:31:40 | [diff] [blame] | 16 | #include "base/test/task_environment.h" |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 17 | #include "base/test/values_test_util.h" |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 18 | #include "base/values.h" |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 19 | #include "testing/gtest/include/gtest/gtest.h" |
| 20 | #include "v8/include/v8.h" |
| 21 | |
[email protected] | 9a292e2 | 2012-10-22 15:19:31 | [diff] [blame] | 22 | namespace content { |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 23 | |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 24 | // 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. |
| 29 | class 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 | |
| 43 | ScopedAvoidIdentityHashForTesting::ScopedAvoidIdentityHashForTesting( |
| 44 | content::V8ValueConverterImpl* converter) |
| 45 | : converter_(converter) { |
| 46 | CHECK(converter_); |
| 47 | converter_->avoid_identity_hash_for_testing_ = true; |
| 48 | } |
| 49 | |
| 50 | ScopedAvoidIdentityHashForTesting::~ScopedAvoidIdentityHashForTesting() { |
| 51 | converter_->avoid_identity_hash_for_testing_ = false; |
| 52 | } |
| 53 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 54 | class V8ValueConverterImplTest : public testing::Test { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 55 | public: |
| 56 | V8ValueConverterImplTest() |
| 57 | : isolate_(v8::Isolate::GetCurrent()) { |
| 58 | } |
| 59 | |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 60 | protected: |
dcheng | f576215 | 2014-10-29 02:12:06 | [diff] [blame] | 61 | void SetUp() override { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 62 | v8::HandleScope handle_scope(isolate_); |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 63 | v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_); |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 64 | context_.Reset(isolate_, v8::Context::New(isolate_, nullptr, global)); |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 65 | } |
| 66 | |
dcheng | f576215 | 2014-10-29 02:12:06 | [diff] [blame] | 67 | void TearDown() override { context_.Reset(); } |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 68 | |
[email protected] | 0cd50aa | 2013-02-12 22:28:01 | [diff] [blame] | 69 | std::string GetString(base::DictionaryValue* value, const std::string& key) { |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 70 | std::string temp; |
| 71 | if (!value->GetString(key, &temp)) { |
| 72 | ADD_FAILURE(); |
[email protected] | 007b3f8 | 2013-04-09 08:46:45 | [diff] [blame] | 73 | return std::string(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 74 | } |
| 75 | return temp; |
| 76 | } |
| 77 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 78 | std::string GetString(v8::Local<v8::Object> value, const std::string& key) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 79 | 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] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 86 | ADD_FAILURE(); |
[email protected] | 007b3f8 | 2013-04-09 08:46:45 | [diff] [blame] | 87 | return std::string(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 88 | } |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 89 | v8::String::Utf8Value utf8(isolate_, temp.As<v8::String>()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 90 | return std::string(*utf8, utf8.length()); |
| 91 | } |
| 92 | |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 93 | std::string GetString(base::ListValue* value, uint32_t index) { |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 94 | std::string temp; |
| 95 | if (!value->GetString(static_cast<size_t>(index), &temp)) { |
| 96 | ADD_FAILURE(); |
[email protected] | 007b3f8 | 2013-04-09 08:46:45 | [diff] [blame] | 97 | return std::string(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 98 | } |
| 99 | return temp; |
| 100 | } |
| 101 | |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 102 | std::string GetString(v8::Local<v8::Array> value, uint32_t index) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 103 | v8::Local<v8::Value> temp; |
| 104 | if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&temp)) { |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 105 | ADD_FAILURE(); |
[email protected] | 007b3f8 | 2013-04-09 08:46:45 | [diff] [blame] | 106 | return std::string(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 107 | } |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 108 | v8::String::Utf8Value utf8(isolate_, temp.As<v8::String>()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 109 | return std::string(*utf8, utf8.length()); |
| 110 | } |
| 111 | |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 112 | int32_t GetInt(v8::Local<v8::Object> value, const std::string& key) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 113 | 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)) { |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 120 | ADD_FAILURE(); |
| 121 | return -1; |
| 122 | } |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 123 | return temp.As<v8::Int32>()->Value(); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | int32_t GetInt(v8::Local<v8::Object> value, uint32_t index) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 127 | v8::Local<v8::Value> temp; |
| 128 | if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&temp)) { |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 129 | ADD_FAILURE(); |
| 130 | return -1; |
| 131 | } |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 132 | return temp.As<v8::Int32>()->Value(); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 133 | } |
| 134 | |
[email protected] | 0cd50aa | 2013-02-12 22:28:01 | [diff] [blame] | 135 | bool IsNull(base::DictionaryValue* value, const std::string& key) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 136 | base::Value* child = nullptr; |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 137 | if (!value->Get(key, &child)) { |
| 138 | ADD_FAILURE(); |
| 139 | return false; |
| 140 | } |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 141 | return child->type() == base::Value::Type::NONE; |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 142 | } |
| 143 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 144 | bool IsNull(v8::Local<v8::Object> value, const std::string& key) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 145 | v8::Local<v8::Value> child; |
| 146 | if (!value |
| 147 | ->Get(isolate_->GetCurrentContext(), |
| 148 | v8::String::NewFromUtf8(isolate_, key.c_str(), |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 149 | v8::NewStringType::kInternalized) |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 150 | .ToLocalChecked()) |
| 151 | .ToLocal(&child)) { |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 152 | ADD_FAILURE(); |
| 153 | return false; |
| 154 | } |
| 155 | return child->IsNull(); |
| 156 | } |
| 157 | |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 158 | bool IsNull(base::ListValue* value, uint32_t index) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 159 | base::Value* child = nullptr; |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 160 | if (!value->Get(static_cast<size_t>(index), &child)) { |
| 161 | ADD_FAILURE(); |
| 162 | return false; |
| 163 | } |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 164 | return child->type() == base::Value::Type::NONE; |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 165 | } |
| 166 | |
avi | 66a0772 | 2015-12-25 23:38:12 | [diff] [blame] | 167 | bool IsNull(v8::Local<v8::Array> value, uint32_t index) { |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 168 | v8::Local<v8::Value> child; |
| 169 | if (!value->Get(isolate_->GetCurrentContext(), index).ToLocal(&child)) { |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 170 | ADD_FAILURE(); |
| 171 | return false; |
| 172 | } |
| 173 | return child->IsNull(); |
| 174 | } |
| 175 | |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 176 | void TestWeirdType(V8ValueConverterImpl& converter, |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 177 | v8::Local<v8::Value> val, |
[email protected] | bab1c13f | 2011-08-12 20:59:02 | [diff] [blame] | 178 | base::Value::Type expected_type, |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 179 | std::unique_ptr<base::Value> expected_value) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 180 | v8::Local<v8::Context> context = |
| 181 | v8::Local<v8::Context>::New(isolate_, context_); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 182 | std::unique_ptr<base::Value> raw(converter.FromV8Value(val, context)); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 183 | |
[email protected] | 59383c78 | 2013-04-17 16:43:27 | [diff] [blame] | 184 | if (expected_value) { |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 185 | ASSERT_TRUE(raw.get()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 186 | EXPECT_TRUE(expected_value->Equals(raw.get())); |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 187 | EXPECT_EQ(expected_type, raw->type()); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 188 | } else { |
| 189 | EXPECT_FALSE(raw.get()); |
| 190 | } |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 191 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 192 | v8::Local<v8::Object> object(v8::Object::New(isolate_)); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 193 | object |
| 194 | ->Set(context, |
| 195 | v8::String::NewFromUtf8(isolate_, "test", |
| 196 | v8::NewStringType::kInternalized) |
| 197 | .ToLocalChecked(), |
| 198 | val) |
| 199 | .Check(); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 200 | std::unique_ptr<base::DictionaryValue> dictionary( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 201 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 202 | ASSERT_TRUE(dictionary.get()); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 203 | |
[email protected] | 59383c78 | 2013-04-17 16:43:27 | [diff] [blame] | 204 | if (expected_value) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 205 | base::Value* temp = nullptr; |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 206 | ASSERT_TRUE(dictionary->Get("test", &temp)); |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 207 | EXPECT_EQ(expected_type, temp->type()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 208 | EXPECT_TRUE(expected_value->Equals(temp)); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 209 | } else { |
| 210 | EXPECT_FALSE(dictionary->HasKey("test")); |
| 211 | } |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 212 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 213 | v8::Local<v8::Array> array(v8::Array::New(isolate_)); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 214 | array->Set(context, 0, val).Check(); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 215 | std::unique_ptr<base::ListValue> list( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 216 | base::ListValue::From(converter.FromV8Value(array, context))); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 217 | ASSERT_TRUE(list.get()); |
[email protected] | 59383c78 | 2013-04-17 16:43:27 | [diff] [blame] | 218 | if (expected_value) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 219 | base::Value* temp = nullptr; |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 220 | ASSERT_TRUE(list->Get(0, &temp)); |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 221 | EXPECT_EQ(expected_type, temp->type()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 222 | EXPECT_TRUE(expected_value->Equals(temp)); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 223 | } else { |
| 224 | // Arrays should preserve their length, and convert unconvertible |
| 225 | // types into null. |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 226 | base::Value* temp = nullptr; |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 227 | ASSERT_TRUE(list->Get(0, &temp)); |
jdoerrie | 76cee9c | 2017-10-06 22:42:42 | [diff] [blame] | 228 | EXPECT_EQ(base::Value::Type::NONE, temp->type()); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 229 | } |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 230 | } |
| 231 | |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 232 | template <typename T> |
| 233 | v8::Local<T> CompileRun(v8::Local<v8::Context> context, const char* source) { |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 234 | return v8::Script::Compile( |
Camillo Bruni | e5440c76 | 2020-09-10 11:53:35 | [diff] [blame] | 235 | context, |
| 236 | v8::String::NewFromUtf8(isolate_, source).ToLocalChecked()) |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 237 | .ToLocalChecked() |
| 238 | ->Run(context) |
| 239 | .ToLocalChecked() |
| 240 | .As<T>(); |
| 241 | } |
| 242 | |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame] | 243 | base::test::TaskEnvironment task_environment_; |
Scott Graham | c80dc347 | 2017-08-25 18:42:18 | [diff] [blame] | 244 | |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 245 | v8::Isolate* isolate_; |
| 246 | |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 247 | // Context for the JavaScript in the test. |
| 248 | v8::Persistent<v8::Context> context_; |
| 249 | }; |
| 250 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 251 | TEST_F(V8ValueConverterImplTest, BasicRoundTrip) { |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 252 | std::unique_ptr<base::Value> original_root = base::test::ParseJsonDeprecated( |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 253 | "{ \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] | 0cd50aa | 2013-02-12 22:28:01 | [diff] [blame] | 261 | " \"big-integral-double\": 9007199254740992.0, \n" // 2.0^53 |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 262 | " \"string\": \"foobar\", \n" |
| 263 | " \"empty-string\": \"\", \n" |
| 264 | " \"dictionary\": { \n" |
| 265 | " \"foo\": \"bar\",\n" |
| 266 | " \"hot\": \"dog\",\n" |
| 267 | " }, \n" |
| 268 | " \"empty-dictionary\": {}, \n" |
jam | b56c1d38 | 2016-09-29 19:28:58 | [diff] [blame] | 269 | " \"list\": [ \"bar\", \"foo\" ], \n" |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 270 | " \"empty-list\": [], \n" |
| 271 | "}"); |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 272 | |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 273 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 274 | v8::Local<v8::Context> context = |
| 275 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 276 | v8::Context::Scope context_scope(context); |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 277 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 278 | V8ValueConverterImpl converter; |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 279 | v8::Local<v8::Object> v8_object = |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 280 | converter.ToV8Value(original_root.get(), context).As<v8::Object>(); |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 281 | ASSERT_FALSE(v8_object.IsEmpty()); |
| 282 | |
Song Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 283 | EXPECT_EQ( |
| 284 | static_cast<const base::DictionaryValue&>(*original_root).DictSize(), |
| 285 | v8_object->GetPropertyNames(context).ToLocalChecked()->Length()); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 286 | 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 Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 300 | EXPECT_TRUE(v8_object |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 301 | ->Get(context, |
| 302 | v8::String::NewFromUtf8( |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 303 | isolate_, "false", v8::NewStringType::kInternalized) |
| 304 | .ToLocalChecked()) |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 305 | .ToLocalChecked() |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 306 | ->IsFalse()); |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 307 | EXPECT_TRUE(v8_object |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 308 | ->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] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 320 | ->IsInt32()); |
| 321 | EXPECT_TRUE( |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 322 | v8_object |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 323 | ->Get(context, v8::String::NewFromUtf8( |
| 324 | isolate_, "zero", v8::NewStringType::kInternalized) |
| 325 | .ToLocalChecked()) |
| 326 | .ToLocalChecked() |
| 327 | ->IsInt32()); |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 328 | EXPECT_TRUE(v8_object |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 329 | ->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 Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 370 | EXPECT_TRUE( |
| 371 | v8_object |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 372 | ->Get(context, v8::String::NewFromUtf8( |
| 373 | isolate_, "list", v8::NewStringType::kInternalized) |
| 374 | .ToLocalChecked()) |
| 375 | .ToLocalChecked() |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 376 | ->IsArray()); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 377 | 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] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 384 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 385 | std::unique_ptr<base::Value> new_root( |
| 386 | converter.FromV8Value(v8_object, context)); |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 387 | EXPECT_NE(original_root.get(), new_root.get()); |
| 388 | EXPECT_TRUE(original_root->Equals(new_root.get())); |
[email protected] | b1cf337 | 2011-04-20 21:28:10 | [diff] [blame] | 389 | } |
[email protected] | 735e70e3 | 2011-04-20 22:04:57 | [diff] [blame] | 390 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 391 | TEST_F(V8ValueConverterImplTest, KeysWithDots) { |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 392 | std::unique_ptr<base::Value> original = |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 393 | base::test::ParseJsonDeprecated("{ \"foo.bar\": \"baz\" }"); |
[email protected] | 735e70e3 | 2011-04-20 22:04:57 | [diff] [blame] | 394 | |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 395 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 396 | v8::Local<v8::Context> context = |
| 397 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 398 | v8::Context::Scope context_scope(context); |
[email protected] | 735e70e3 | 2011-04-20 22:04:57 | [diff] [blame] | 399 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 400 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 401 | std::unique_ptr<base::Value> copy(converter.FromV8Value( |
| 402 | converter.ToV8Value(original.get(), context), context)); |
[email protected] | 735e70e3 | 2011-04-20 22:04:57 | [diff] [blame] | 403 | |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 404 | EXPECT_TRUE(original->Equals(copy.get())); |
[email protected] | 735e70e3 | 2011-04-20 22:04:57 | [diff] [blame] | 405 | } |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 406 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 407 | TEST_F(V8ValueConverterImplTest, ObjectExceptions) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 408 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 409 | v8::Local<v8::Context> context = |
| 410 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 411 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 412 | v8::MicrotasksScope microtasks( |
| 413 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 414 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 422 | CompileRun<v8::Value>(context, source); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 423 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 424 | v8::Local<v8::Object> object(v8::Object::New(isolate_)); |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 425 | v8::Local<v8::String> bar = |
| 426 | v8::String::NewFromUtf8(isolate_, "bar", v8::NewStringType::kInternalized) |
| 427 | .ToLocalChecked(); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 428 | object->Set(context, bar, bar).Check(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 429 | |
| 430 | // Converting from v8 value should replace the foo property with null. |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 431 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 432 | std::unique_ptr<base::DictionaryValue> converted( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 433 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 434 | 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 Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 438 | EXPECT_EQ(1u, converted->DictSize()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 439 | EXPECT_EQ("bar", GetString(converted.get(), "bar")); |
| 440 | |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 441 | // Converting to v8 value should not trigger the setter. |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 442 | converted->SetString("foo", "foo"); |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 443 | v8::Local<v8::Object> copy = |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 444 | converter.ToV8Value(converted.get(), context).As<v8::Object>(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 445 | EXPECT_FALSE(copy.IsEmpty()); |
Dan Elphick | cc0832ef | 2018-12-24 11:31:23 | [diff] [blame] | 446 | EXPECT_EQ(2u, copy->GetPropertyNames(context).ToLocalChecked()->Length()); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 447 | EXPECT_EQ("foo", GetString(copy, "foo")); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 448 | EXPECT_EQ("bar", GetString(copy, "bar")); |
| 449 | } |
| 450 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 451 | TEST_F(V8ValueConverterImplTest, ArrayExceptions) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 452 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 453 | v8::Local<v8::Context> context = |
| 454 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 455 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 456 | v8::MicrotasksScope microtasks( |
| 457 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 458 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 469 | v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 470 | |
| 471 | // Converting from v8 value should replace the first item with null. |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 472 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 473 | std::unique_ptr<base::ListValue> converted( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 474 | base::ListValue::From(converter.FromV8Value(array, context))); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 475 | 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 | |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 480 | // 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] | 0cd50aa | 2013-02-12 22:28:01 | [diff] [blame] | 483 | converted.reset(static_cast<base::ListValue*>( |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 484 | base::test::ParseJsonDeprecated("[ \"foo\", \"bar\" ]").release())); |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 485 | v8::Local<v8::Array> copy = |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 486 | converter.ToV8Value(converted.get(), context).As<v8::Array>(); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 487 | ASSERT_FALSE(copy.IsEmpty()); |
| 488 | EXPECT_EQ(2u, copy->Length()); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 489 | EXPECT_EQ("foo", GetString(copy, 0)); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 490 | EXPECT_EQ("bar", GetString(copy, 1)); |
| 491 | } |
| 492 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 493 | TEST_F(V8ValueConverterImplTest, WeirdTypes) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 494 | v8::HandleScope handle_scope(isolate_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 495 | v8::Local<v8::Context> context = |
| 496 | v8::Local<v8::Context>::New(isolate_, context_); |
| 497 | v8::Context::Scope context_scope(context); |
Jochen Eisinger | d00cc71 | 2021-04-17 07:23:13 | [diff] [blame] | 498 | v8::MicrotasksScope microtasks(isolate_, |
| 499 | v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 500 | |
Yang Guo | 9a47cd6 | 2018-01-16 08:05:32 | [diff] [blame] | 501 | v8::Local<v8::RegExp> regex( |
Camillo Bruni | e5440c76 | 2020-09-10 11:53:35 | [diff] [blame] | 502 | v8::RegExp::New(context, v8::String::NewFromUtf8Literal(isolate_, "."), |
| 503 | v8::RegExp::kNone) |
Yang Guo | 9a47cd6 | 2018-01-16 08:05:32 | [diff] [blame] | 504 | .ToLocalChecked()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 505 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 506 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 507 | TestWeirdType(converter, v8::Undefined(isolate_), |
jdoerrie | dc72ee94 | 2016-12-07 15:43:28 | [diff] [blame] | 508 | base::Value::Type::NONE, // Arbitrary type, result is NULL. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 509 | std::unique_ptr<base::Value>()); |
Yang Guo | db90c52 | 2018-01-23 13:55:30 | [diff] [blame] | 510 | TestWeirdType(converter, v8::Date::New(context, 1000).ToLocalChecked(), |
jdoerrie | dc72ee94 | 2016-12-07 15:43:28 | [diff] [blame] | 511 | base::Value::Type::DICTIONARY, |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 512 | std::unique_ptr<base::Value>(new base::DictionaryValue())); |
jdoerrie | dc72ee94 | 2016-12-07 15:43:28 | [diff] [blame] | 513 | TestWeirdType(converter, regex, base::Value::Type::DICTIONARY, |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 514 | std::unique_ptr<base::Value>(new base::DictionaryValue())); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 515 | |
[email protected] | 3de391e8 | 2012-05-16 17:50:51 | [diff] [blame] | 516 | converter.SetDateAllowed(true); |
Yang Guo | db90c52 | 2018-01-23 13:55:30 | [diff] [blame] | 517 | TestWeirdType(converter, v8::Date::New(context, 1000).ToLocalChecked(), |
Peter Boström | dd7e40ec | 2021-04-05 20:40:10 | [diff] [blame] | 518 | base::Value::Type::DOUBLE, std::make_unique<base::Value>(1.0)); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 519 | |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 520 | converter.SetRegExpAllowed(true); |
jdoerrie | dc72ee94 | 2016-12-07 15:43:28 | [diff] [blame] | 521 | TestWeirdType(converter, regex, base::Value::Type::STRING, |
Peter Boström | dd7e40ec | 2021-04-05 20:40:10 | [diff] [blame] | 522 | std::make_unique<base::Value>("/./")); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 523 | } |
| 524 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 525 | TEST_F(V8ValueConverterImplTest, Prototype) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 526 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 527 | v8::Local<v8::Context> context = |
| 528 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 529 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 530 | v8::MicrotasksScope microtasks( |
| 531 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 532 | |
| 533 | const char* source = "(function() {" |
| 534 | "Object.prototype.foo = 'foo';" |
| 535 | "return {};" |
| 536 | "})();"; |
| 537 | |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 538 | v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 539 | |
[email protected] | 8d86f13d | 2011-10-04 17:01:19 | [diff] [blame] | 540 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 541 | std::unique_ptr<base::DictionaryValue> result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 542 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 543 | ASSERT_TRUE(result.get()); |
Song Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 544 | EXPECT_EQ(0u, result->DictSize()); |
[email protected] | 786a7fa | 2011-04-22 21:27:12 | [diff] [blame] | 545 | } |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 546 | |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 547 | TEST_F(V8ValueConverterImplTest, ObjectPrototypeSetter) { |
| 548 | std::unique_ptr<base::Value> original = |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 549 | base::test::ParseJsonDeprecated("{ \"foo\": \"good value\" }"); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 550 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 570 | v8::Local<v8::Object> result = CompileRun<v8::Object>(context, source); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 571 | |
| 572 | // Sanity checks: the getters/setters are normally triggered. |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 573 | CompileRun<v8::Value>(context, source_sanity); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 574 | 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 Elphick | cc0832ef | 2018-12-24 11:31:23 | [diff] [blame] | 586 | EXPECT_EQ(1u, |
| 587 | converted->GetPropertyNames(context).ToLocalChecked()->Length()); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 588 | 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 Elphick | cc0832ef | 2018-12-24 11:31:23 | [diff] [blame] | 605 | EXPECT_EQ(1u, |
| 606 | converted2->GetPropertyNames(context).ToLocalChecked()->Length()); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 607 | 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 | |
| 615 | TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) { |
| 616 | std::unique_ptr<base::Value> original = |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 617 | base::test::ParseJsonDeprecated("[100, 200, 300]"); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 618 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 638 | v8::Local<v8::Object> result = CompileRun<v8::Object>(context, source); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 639 | |
| 640 | // Sanity checks: the getters/setters are normally triggered. |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 641 | CompileRun<v8::Value>(context, source_sanity); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 642 | 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; |
dcheng | 33f3dc9f | 2016-06-03 02:38:23 | [diff] [blame] | 665 | one_item_list.AppendInteger(123456); |
rob | b5bdf37 | 2016-04-27 11:27:06 | [diff] [blame] | 666 | 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] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 683 | TEST_F(V8ValueConverterImplTest, StripNullFromObjects) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 684 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 685 | v8::Local<v8::Context> context = |
| 686 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 687 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 688 | v8::MicrotasksScope microtasks( |
| 689 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 690 | |
| 691 | const char* source = "(function() {" |
| 692 | "return { foo: undefined, bar: null };" |
| 693 | "})();"; |
| 694 | |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 695 | v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source); |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 696 | |
| 697 | V8ValueConverterImpl converter; |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 698 | converter.SetStripNullFromObjects(true); |
| 699 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 700 | std::unique_ptr<base::DictionaryValue> result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 701 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 702 | ASSERT_TRUE(result.get()); |
Song Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 703 | EXPECT_EQ(0u, result->DictSize()); |
[email protected] | 2a52184 | 2012-05-30 09:17:06 | [diff] [blame] | 704 | } |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 705 | |
| 706 | TEST_F(V8ValueConverterImplTest, RecursiveObjects) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 707 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 708 | v8::Local<v8::Context> context = |
| 709 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 710 | v8::Context::Scope context_scope(context); |
Jochen Eisinger | d00cc71 | 2021-04-17 07:23:13 | [diff] [blame] | 711 | v8::MicrotasksScope microtasks(isolate_, |
| 712 | v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 713 | |
| 714 | V8ValueConverterImpl converter; |
| 715 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 716 | v8::Local<v8::Object> object = v8::Object::New(isolate_).As<v8::Object>(); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 717 | ASSERT_FALSE(object.IsEmpty()); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 718 | object |
| 719 | ->Set(context, |
| 720 | v8::String::NewFromUtf8(isolate_, "foo", |
| 721 | v8::NewStringType::kInternalized) |
| 722 | .ToLocalChecked(), |
Camillo Bruni | e5440c76 | 2020-09-10 11:53:35 | [diff] [blame] | 723 | v8::String::NewFromUtf8Literal(isolate_, "bar")) |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 724 | .Check(); |
| 725 | object |
| 726 | ->Set(context, |
| 727 | v8::String::NewFromUtf8(isolate_, "obj", |
| 728 | v8::NewStringType::kInternalized) |
| 729 | .ToLocalChecked(), |
| 730 | object) |
| 731 | .Check(); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 732 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 733 | std::unique_ptr<base::DictionaryValue> object_result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 734 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 735 | ASSERT_TRUE(object_result.get()); |
Song Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 736 | EXPECT_EQ(2u, object_result->DictSize()); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 737 | EXPECT_TRUE(IsNull(object_result.get(), "obj")); |
| 738 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 739 | v8::Local<v8::Array> array = v8::Array::New(isolate_).As<v8::Array>(); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 740 | ASSERT_FALSE(array.IsEmpty()); |
Camillo Bruni | e5440c76 | 2020-09-10 11:53:35 | [diff] [blame] | 741 | array->Set(context, 0, v8::String::NewFromUtf8Literal(isolate_, "1")).Check(); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 742 | array->Set(context, 1, array).Check(); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 743 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 744 | std::unique_ptr<base::ListValue> list_result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 745 | base::ListValue::From(converter.FromV8Value(array, context))); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 746 | ASSERT_TRUE(list_result.get()); |
| 747 | EXPECT_EQ(2u, list_result->GetSize()); |
| 748 | EXPECT_TRUE(IsNull(list_result.get(), 1)); |
| 749 | } |
| 750 | |
[email protected] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 751 | TEST_F(V8ValueConverterImplTest, WeirdProperties) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 752 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 753 | v8::Local<v8::Context> context = |
| 754 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 755 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 756 | v8::MicrotasksScope microtasks( |
| 757 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 758 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 770 | v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source); |
[email protected] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 771 | |
| 772 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 773 | std::unique_ptr<base::Value> actual(converter.FromV8Value(object, context)); |
[email protected] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 774 | |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 775 | std::unique_ptr<base::Value> expected = base::test::ParseJsonDeprecated( |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 776 | "{ \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] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 784 | |
[email protected] | 06d19d8 | 2012-12-17 21:45:37 | [diff] [blame] | 785 | EXPECT_TRUE(expected->Equals(actual.get())); |
[email protected] | 74baf97 | 2012-09-13 02:46:39 | [diff] [blame] | 786 | } |
| 787 | |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 788 | TEST_F(V8ValueConverterImplTest, ArrayGetters) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 789 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 790 | v8::Local<v8::Context> context = |
| 791 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 792 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 793 | v8::MicrotasksScope microtasks( |
| 794 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 795 | |
| 796 | const char* source = "(function() {" |
| 797 | "var a = [0];" |
| 798 | "a.__defineGetter__(1, function() { return 'bar'; });" |
| 799 | "return a;" |
| 800 | "})();"; |
| 801 | |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 802 | v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 803 | |
| 804 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 805 | std::unique_ptr<base::ListValue> result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 806 | base::ListValue::From(converter.FromV8Value(array, context))); |
[email protected] | 217d956 | 2012-07-16 21:57:37 | [diff] [blame] | 807 | ASSERT_TRUE(result.get()); |
| 808 | EXPECT_EQ(2u, result->GetSize()); |
| 809 | } |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 810 | |
| 811 | TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 812 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 813 | v8::Local<v8::Context> context = |
| 814 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 815 | v8::Context::Scope context_scope(context); |
dgozman | 8ce1943 | 2016-03-16 22:30:50 | [diff] [blame] | 816 | v8::MicrotasksScope microtasks( |
| 817 | isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 818 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 819 | v8::Local<v8::Object> object; |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 820 | { |
| 821 | const char* source = "(function() {" |
| 822 | "return { foo: undefined, bar: null, baz: function(){} };" |
| 823 | "})();"; |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 824 | object = CompileRun<v8::Object>(context, source); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 825 | } |
| 826 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 827 | v8::Local<v8::Array> array; |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 828 | { |
| 829 | const char* source = "(function() {" |
| 830 | "return [ undefined, null, function(){} ];" |
| 831 | "})();"; |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 832 | array = CompileRun<v8::Array>(context, source); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 833 | } |
| 834 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 835 | v8::Local<v8::Array> sparse_array; |
[email protected] | 719ffd3 | 2014-04-23 13:12:55 | [diff] [blame] | 836 | { |
| 837 | const char* source = "(function() {" |
| 838 | "return new Array(3);" |
| 839 | "})();"; |
Adam Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 840 | sparse_array = CompileRun<v8::Array>(context, source); |
[email protected] | 719ffd3 | 2014-04-23 13:12:55 | [diff] [blame] | 841 | } |
| 842 | |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 843 | V8ValueConverterImpl converter; |
| 844 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 845 | std::unique_ptr<base::Value> actual_object( |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 846 | converter.FromV8Value(object, context)); |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 847 | EXPECT_EQ(*base::test::ParseJsonDeprecated("{ \"bar\": null }"), |
| 848 | *actual_object); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 849 | |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 850 | // Everything is null because JSON stringification preserves array length. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 851 | std::unique_ptr<base::Value> actual_array( |
| 852 | converter.FromV8Value(array, context)); |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 853 | EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"), |
| 854 | *actual_array); |
[email protected] | 719ffd3 | 2014-04-23 13:12:55 | [diff] [blame] | 855 | |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 856 | std::unique_ptr<base::Value> actual_sparse_array( |
[email protected] | 719ffd3 | 2014-04-23 13:12:55 | [diff] [blame] | 857 | converter.FromV8Value(sparse_array, context)); |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 858 | EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"), |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 859 | *actual_sparse_array); |
[email protected] | e0658bc | 2012-09-17 04:05:24 | [diff] [blame] | 860 | } |
[email protected] | 9a292e2 | 2012-10-22 15:19:31 | [diff] [blame] | 861 | |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 862 | TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 863 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 864 | v8::Local<v8::Context> context = |
| 865 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 866 | v8::Context::Scope context_scope(context); |
Jochen Eisinger | d00cc71 | 2021-04-17 07:23:13 | [diff] [blame] | 867 | v8::MicrotasksScope microtasks(isolate_, |
| 868 | v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 869 | 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.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 876 | v8::Local<v8::Array> root(v8::Array::New(isolate_, 4)); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 877 | 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] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 885 | |
| 886 | // The expected base::Value result. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 887 | std::unique_ptr<base::Value> expected = |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 888 | base::test::ParseJsonDeprecated("[{},{},[],[]]"); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 889 | ASSERT_TRUE(expected.get()); |
| 890 | |
| 891 | // The actual result. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 892 | std::unique_ptr<base::Value> value(converter.FromV8Value(root, context)); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 893 | ASSERT_TRUE(value.get()); |
| 894 | |
| 895 | EXPECT_TRUE(expected->Equals(value.get())); |
| 896 | } |
| 897 | |
| 898 | TEST_F(V8ValueConverterImplTest, DetectCycles) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 899 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 900 | v8::Local<v8::Context> context = |
| 901 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 902 | v8::Context::Scope context_scope(context); |
Jochen Eisinger | d00cc71 | 2021-04-17 07:23:13 | [diff] [blame] | 903 | v8::MicrotasksScope microtasks(isolate_, |
| 904 | v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 905 | V8ValueConverterImpl converter; |
| 906 | |
| 907 | // Create a recursive array. |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 908 | v8::Local<v8::Array> recursive_array(v8::Array::New(isolate_, 1)); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 909 | recursive_array->Set(context, 0, recursive_array).Check(); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 910 | |
| 911 | // The first repetition should be trimmed and replaced by a null value. |
| 912 | base::ListValue expected_list; |
Jeremy Roman | 04f27c37 | 2017-10-27 15:20:55 | [diff] [blame] | 913 | expected_list.Append(std::make_unique<base::Value>()); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 914 | |
| 915 | // The actual result. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 916 | std::unique_ptr<base::Value> actual_list( |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 917 | converter.FromV8Value(recursive_array, context)); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 918 | 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.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 924 | v8::Local<v8::Object> recursive_object(v8::Object::New(isolate_)); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 925 | 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] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 933 | |
| 934 | // The first repetition should be trimmed and replaced by a null value. |
| 935 | base::DictionaryValue expected_dictionary; |
Jeremy Roman | 04f27c37 | 2017-10-27 15:20:55 | [diff] [blame] | 936 | expected_dictionary.Set(key, std::make_unique<base::Value>()); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 937 | |
| 938 | // The actual result. |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 939 | std::unique_ptr<base::Value> actual_dictionary( |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 940 | converter.FromV8Value(recursive_object, context)); |
[email protected] | 6a9b737 | 2013-03-20 15:35:20 | [diff] [blame] | 941 | ASSERT_TRUE(actual_dictionary.get()); |
| 942 | |
| 943 | EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get())); |
| 944 | } |
| 945 | |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 946 | // Tests that reused object values with no cycles do not get nullified. |
| 947 | TEST_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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 963 | v8::Local<v8::Object> object = CompileRun<v8::Object>(context, source); |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 964 | |
| 965 | // The actual result. |
| 966 | std::unique_ptr<base::DictionaryValue> result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 967 | base::DictionaryValue::From(converter.FromV8Value(object, context))); |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 968 | ASSERT_TRUE(result.get()); |
Song Fangzhen | 2691dfe | 2021-05-07 11:59:58 | [diff] [blame] | 969 | EXPECT_EQ(2u, result->DictSize()); |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 970 | |
| 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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 992 | v8::Local<v8::Array> array = CompileRun<v8::Array>(context, source); |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 993 | |
| 994 | // The actual result. |
| 995 | std::unique_ptr<base::ListValue> list_result( |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 996 | base::ListValue::From(converter.FromV8Value(array, context))); |
lazyboy | 275ec3e | 2016-05-04 18:04:24 | [diff] [blame] | 997 | 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] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1008 | TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) { |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 1009 | v8::HandleScope handle_scope(isolate_); |
[email protected] | 52d6c320 | 2013-06-11 04:28:12 | [diff] [blame] | 1010 | v8::Local<v8::Context> context = |
| 1011 | v8::Local<v8::Context>::New(isolate_, context_); |
[email protected] | d3c97d1 | 2013-12-02 12:19:23 | [diff] [blame] | 1012 | v8::Context::Scope context_scope(context); |
Jochen Eisinger | d00cc71 | 2021-04-17 07:23:13 | [diff] [blame] | 1013 | v8::MicrotasksScope microtasks(isolate_, |
| 1014 | v8::MicrotasksScope::kDoNotRunMicrotasks); |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1015 | |
| 1016 | // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc. |
[email protected] | 6e69b00 | 2013-09-12 20:58:57 | [diff] [blame] | 1017 | int kDepth = 1000; |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1018 | const char kKey[] = "key"; |
| 1019 | |
[email protected] | f65a2326 | 2014-01-03 20:12:03 | [diff] [blame] | 1020 | v8::Local<v8::Object> deep_object = v8::Object::New(isolate_); |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1021 | |
| 1022 | v8::Local<v8::Object> leaf = deep_object; |
| 1023 | for (int i = 0; i < kDepth; ++i) { |
[email protected] | f65a2326 | 2014-01-03 20:12:03 | [diff] [blame] | 1024 | v8::Local<v8::Object> new_object = v8::Object::New(isolate_); |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 1025 | leaf->Set(context, |
| 1026 | v8::String::NewFromUtf8(isolate_, kKey, |
Yang Guo | 26b0f777 | 2018-11-27 08:37:20 | [diff] [blame] | 1027 | v8::NewStringType::kInternalized) |
| 1028 | .ToLocalChecked(), |
Dan Elphick | cc7538d0 | 2019-02-01 13:41:47 | [diff] [blame] | 1029 | new_object) |
| 1030 | .Check(); |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1031 | leaf = new_object; |
| 1032 | } |
| 1033 | |
| 1034 | V8ValueConverterImpl converter; |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1035 | std::unique_ptr<base::Value> value( |
| 1036 | converter.FromV8Value(deep_object, context)); |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1037 | ASSERT_TRUE(value); |
| 1038 | |
| 1039 | // Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc. |
[email protected] | 6e69b00 | 2013-09-12 20:58:57 | [diff] [blame] | 1040 | int kExpectedDepth = 100; |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1041 | |
| 1042 | base::Value* current = value.get(); |
| 1043 | for (int i = 1; i < kExpectedDepth; ++i) { |
Ivan Kotenkov | 2c0d2bb3 | 2017-11-01 15:41:28 | [diff] [blame] | 1044 | base::DictionaryValue* current_as_object = nullptr; |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1045 | ASSERT_TRUE(current->GetAsDictionary(¤t_as_object)) << i; |
| 1046 | ASSERT_TRUE(current_as_object->Get(kKey, ¤t)) << i; |
| 1047 | } |
| 1048 | |
| 1049 | // The leaf node shouldn't have any properties. |
| 1050 | base::DictionaryValue empty; |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1051 | EXPECT_EQ(empty, *current) << *current; |
[email protected] | 195487f | 2013-06-10 14:20:41 | [diff] [blame] | 1052 | } |
| 1053 | |
rdevlin.cronin | f88f9bc2 | 2017-02-24 17:09:30 | [diff] [blame] | 1054 | TEST_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 Klein | 8a35b5b | 2018-01-17 00:51:00 | [diff] [blame] | 1064 | v8::Local<v8::Value> value = CompileRun<v8::Value>(context, source); |
rdevlin.cronin | f88f9bc2 | 2017-02-24 17:09:30 | [diff] [blame] | 1065 | |
| 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] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1082 | class V8ValueConverterOverridingStrategyForTesting |
| 1083 | : public V8ValueConverter::Strategy { |
| 1084 | public: |
| 1085 | V8ValueConverterOverridingStrategyForTesting() |
| 1086 | : reference_value_(NewReferenceValue()) {} |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1087 | bool FromV8Object(v8::Local<v8::Object> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1088 | std::unique_ptr<base::Value>* out, |
danakj | ab347580 | 2019-05-22 19:05:17 | [diff] [blame] | 1089 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1090 | *out = NewReferenceValue(); |
| 1091 | return true; |
| 1092 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1093 | bool FromV8Array(v8::Local<v8::Array> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1094 | std::unique_ptr<base::Value>* out, |
danakj | ab347580 | 2019-05-22 19:05:17 | [diff] [blame] | 1095 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1096 | *out = NewReferenceValue(); |
| 1097 | return true; |
| 1098 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1099 | bool FromV8ArrayBuffer(v8::Local<v8::Object> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1100 | std::unique_ptr<base::Value>* out, |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1101 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1102 | *out = NewReferenceValue(); |
| 1103 | return true; |
| 1104 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1105 | bool FromV8Number(v8::Local<v8::Number> value, |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1106 | std::unique_ptr<base::Value>* out) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1107 | *out = NewReferenceValue(); |
| 1108 | return true; |
| 1109 | } |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1110 | bool FromV8Undefined(std::unique_ptr<base::Value>* out) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1111 | *out = NewReferenceValue(); |
| 1112 | return true; |
| 1113 | } |
| 1114 | base::Value* reference_value() const { return reference_value_.get(); } |
| 1115 | |
| 1116 | private: |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1117 | static std::unique_ptr<base::Value> NewReferenceValue() { |
Jeremy Roman | 04f27c37 | 2017-10-27 15:20:55 | [diff] [blame] | 1118 | return std::make_unique<base::Value>("strategy"); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1119 | } |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1120 | std::unique_ptr<base::Value> reference_value_; |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1121 | }; |
| 1122 | |
| 1123 | TEST_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.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1133 | v8::Local<v8::Object> object(v8::Object::New(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1134 | std::unique_ptr<base::Value> object_value( |
| 1135 | converter.FromV8Value(object, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1136 | ASSERT_TRUE(object_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1137 | EXPECT_EQ(*strategy.reference_value(), *object_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1138 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1139 | v8::Local<v8::Array> array(v8::Array::New(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1140 | std::unique_ptr<base::Value> array_value( |
| 1141 | converter.FromV8Value(array, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1142 | ASSERT_TRUE(array_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1143 | EXPECT_EQ(*strategy.reference_value(), *array_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1144 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1145 | v8::Local<v8::ArrayBuffer> array_buffer(v8::ArrayBuffer::New(isolate_, 0)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1146 | std::unique_ptr<base::Value> array_buffer_value( |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1147 | converter.FromV8Value(array_buffer, context)); |
| 1148 | ASSERT_TRUE(array_buffer_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1149 | EXPECT_EQ(*strategy.reference_value(), *array_buffer_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1150 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1151 | v8::Local<v8::ArrayBufferView> array_buffer_view( |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1152 | v8::Uint8Array::New(array_buffer, 0, 0)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1153 | std::unique_ptr<base::Value> array_buffer_view_value( |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1154 | converter.FromV8Value(array_buffer_view, context)); |
| 1155 | ASSERT_TRUE(array_buffer_view_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1156 | EXPECT_EQ(*strategy.reference_value(), *array_buffer_view_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1157 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1158 | v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1159 | std::unique_ptr<base::Value> number_value( |
| 1160 | converter.FromV8Value(number, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1161 | ASSERT_TRUE(number_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1162 | EXPECT_EQ(*strategy.reference_value(), *number_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1163 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1164 | v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1165 | std::unique_ptr<base::Value> undefined_value( |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1166 | converter.FromV8Value(undefined, context)); |
| 1167 | ASSERT_TRUE(undefined_value); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1168 | EXPECT_EQ(*strategy.reference_value(), *undefined_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1169 | } |
| 1170 | |
| 1171 | class V8ValueConverterBypassStrategyForTesting |
| 1172 | : public V8ValueConverter::Strategy { |
| 1173 | public: |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1174 | bool FromV8Object(v8::Local<v8::Object> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1175 | std::unique_ptr<base::Value>* out, |
danakj | ab347580 | 2019-05-22 19:05:17 | [diff] [blame] | 1176 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1177 | return false; |
| 1178 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1179 | bool FromV8Array(v8::Local<v8::Array> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1180 | std::unique_ptr<base::Value>* out, |
danakj | ab347580 | 2019-05-22 19:05:17 | [diff] [blame] | 1181 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1182 | return false; |
| 1183 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1184 | bool FromV8ArrayBuffer(v8::Local<v8::Object> value, |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1185 | std::unique_ptr<base::Value>* out, |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1186 | v8::Isolate* isolate) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1187 | return false; |
| 1188 | } |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1189 | bool FromV8Number(v8::Local<v8::Number> value, |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1190 | std::unique_ptr<base::Value>* out) override { |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1191 | return false; |
| 1192 | } |
Lucas Furukawa Gadani | d51ff5d6 | 2018-12-07 21:26:49 | [diff] [blame] | 1193 | bool FromV8Undefined(std::unique_ptr<base::Value>* out) override { |
dcheng | 0232f57 | 2016-05-27 17:47:44 | [diff] [blame] | 1194 | return false; |
| 1195 | } |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1196 | }; |
| 1197 | |
| 1198 | // Verify that having a strategy that fallbacks to default behaviour |
| 1199 | // actually preserves it. |
| 1200 | TEST_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.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1210 | v8::Local<v8::Object> object(v8::Object::New(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1211 | std::unique_ptr<base::Value> object_value( |
| 1212 | converter.FromV8Value(object, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1213 | ASSERT_TRUE(object_value); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1214 | std::unique_ptr<base::Value> reference_object_value( |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 1215 | base::test::ParseJsonDeprecated("{}")); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1216 | EXPECT_EQ(*reference_object_value, *object_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1217 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1218 | v8::Local<v8::Array> array(v8::Array::New(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1219 | std::unique_ptr<base::Value> array_value( |
| 1220 | converter.FromV8Value(array, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1221 | ASSERT_TRUE(array_value); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1222 | std::unique_ptr<base::Value> reference_array_value( |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 1223 | base::test::ParseJsonDeprecated("[]")); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1224 | EXPECT_EQ(*reference_array_value, *array_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1225 | |
jbroman | 54311d0 | 2017-02-08 15:11:39 | [diff] [blame] | 1226 | const char kExampleData[] = {1, 2, 3, 4, 5}; |
| 1227 | v8::Local<v8::ArrayBuffer> array_buffer( |
| 1228 | v8::ArrayBuffer::New(isolate_, sizeof(kExampleData))); |
Ulan Degenbaev | ccd0775 | 2021-03-03 17:59:20 | [diff] [blame] | 1229 | memcpy(array_buffer->GetBackingStore()->Data(), kExampleData, |
jbroman | 54311d0 | 2017-02-08 15:11:39 | [diff] [blame] | 1230 | sizeof(kExampleData)); |
| 1231 | std::unique_ptr<base::Value> binary_value( |
| 1232 | converter.FromV8Value(array_buffer, context)); |
| 1233 | ASSERT_TRUE(binary_value); |
Lei Zhang | 20481244 | 2020-10-24 00:51:02 | [diff] [blame] | 1234 | base::Value reference_binary_value( |
| 1235 | base::as_bytes(base::make_span(kExampleData))); |
| 1236 | EXPECT_EQ(reference_binary_value, *binary_value); |
jbroman | 54311d0 | 2017-02-08 15:11:39 | [diff] [blame] | 1237 | |
| 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 Zhang | 20481244 | 2020-10-24 00:51:02 | [diff] [blame] | 1243 | 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] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1246 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1247 | v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1248 | std::unique_ptr<base::Value> number_value( |
| 1249 | converter.FromV8Value(number, context)); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1250 | ASSERT_TRUE(number_value); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1251 | std::unique_ptr<base::Value> reference_number_value( |
Lei Zhang | 9b9d579 | 2019-02-20 07:24:42 | [diff] [blame] | 1252 | base::test::ParseJsonDeprecated("0")); |
jdoerrie | 8551f92 | 2017-07-25 10:55:13 | [diff] [blame] | 1253 | EXPECT_EQ(*reference_number_value, *number_value); |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1254 | |
deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 1255 | v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_)); |
dcheng | c864f52 | 2016-04-08 23:55:27 | [diff] [blame] | 1256 | std::unique_ptr<base::Value> undefined_value( |
[email protected] | 551b864 | 2014-04-25 09:07:07 | [diff] [blame] | 1257 | converter.FromV8Value(undefined, context)); |
| 1258 | EXPECT_FALSE(undefined_value); |
| 1259 | } |
| 1260 | |
[email protected] | 9a292e2 | 2012-10-22 15:19:31 | [diff] [blame] | 1261 | } // namespace content |