[go: nahoru, domu]

blob: 770b61a820e27138e090a00b0890decd4f8deb56 [file] [log] [blame]
Avi Drissman468e51b62022-09-13 20:47:011// Copyright 2013 The Chromium Authors
abarth@chromium.orga22998a2013-11-10 05:00:502// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "gin/converter.h"
6
7#include <limits.h>
avi90e658dd2015-12-21 07:16:198#include <stddef.h>
9#include <stdint.h>
abarth@chromium.orga22998a2013-11-10 05:00:5010
Jan Wilken Dörriead587c32021-03-11 14:09:2711#include <string>
12
abarth@chromium.orga22998a2013-11-10 05:00:5013#include "base/compiler_specific.h"
Shelley Vohr4c679122019-09-06 00:41:3914#include "base/strings/utf_string_conversions.h"
Jeremy Apthorp789ac3b2020-04-01 01:06:4515#include "gin/function_template.h"
Jeremy Romaneb8a2f172018-01-29 17:33:4016#include "gin/handle.h"
jochen@chromium.orgf04b0e92013-11-22 14:20:5517#include "gin/public/isolate_holder.h"
abarth@chromium.orga22998a2013-11-10 05:00:5018#include "gin/test/v8_test.h"
Jeremy Romaneb8a2f172018-01-29 17:33:4019#include "gin/wrappable.h"
20#include "testing/gmock/include/gmock/gmock.h"
abarth@chromium.orga22998a2013-11-10 05:00:5021#include "testing/gtest/include/gtest/gtest.h"
Dan Elphick05acd602021-08-30 15:22:0722#include "v8/include/v8-container.h"
23#include "v8/include/v8-forward.h"
24#include "v8/include/v8-function.h"
25#include "v8/include/v8-isolate.h"
26#include "v8/include/v8-primitive.h"
27#include "v8/include/v8-template.h"
abarth@chromium.orga22998a2013-11-10 05:00:5028
ssid93b23d92015-05-07 12:11:0729namespace gin {
30
abarth@chromium.orga22998a2013-11-10 05:00:5031using v8::Array;
32using v8::Boolean;
abarth@chromium.orga22998a2013-11-10 05:00:5033using v8::HandleScope;
34using v8::Integer;
tfarina777bfee2015-05-04 14:12:2935using v8::Local;
abarth@chromium.orga22998a2013-11-10 05:00:5036using v8::Null;
37using v8::Number;
38using v8::Object;
39using v8::String;
40using v8::Undefined;
41using v8::Value;
42
abarth@chromium.orga22998a2013-11-10 05:00:5043typedef V8Test ConverterTest;
44
45TEST_F(ConverterTest, Bool) {
jochen@chromium.org1b93c232013-11-19 19:25:1246 HandleScope handle_scope(instance_->isolate());
abarth@chromium.orga22998a2013-11-10 05:00:5047
jochen@chromium.org1b93c232013-11-19 19:25:1248 EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), true)->StrictEquals(
jochen@chromium.org91cd4fe2013-11-28 09:31:5849 Boolean::New(instance_->isolate(), true)));
jochen@chromium.org1b93c232013-11-19 19:25:1250 EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), false)->StrictEquals(
jochen@chromium.org91cd4fe2013-11-28 09:31:5851 Boolean::New(instance_->isolate(), false)));
abarth@chromium.orga22998a2013-11-10 05:00:5052
53 struct {
tfarina777bfee2015-05-04 14:12:2954 Local<Value> input;
abarth@chromium.orga22998a2013-11-10 05:00:5055 bool expected;
56 } test_data[] = {
Yang Guo26b0f7772018-11-27 08:37:2057 {Boolean::New(instance_->isolate(), false).As<Value>(), false},
58 {Boolean::New(instance_->isolate(), true).As<Value>(), true},
59 {Number::New(instance_->isolate(), 0).As<Value>(), false},
60 {Number::New(instance_->isolate(), 1).As<Value>(), true},
61 {Number::New(instance_->isolate(), -1).As<Value>(), true},
62 {Number::New(instance_->isolate(), 0.1).As<Value>(), true},
63 {String::NewFromUtf8(instance_->isolate(), "", v8::NewStringType::kNormal)
64 .ToLocalChecked()
65 .As<Value>(),
66 false},
67 {String::NewFromUtf8(instance_->isolate(), "foo",
68 v8::NewStringType::kNormal)
69 .ToLocalChecked()
70 .As<Value>(),
71 true},
72 {Object::New(instance_->isolate()).As<Value>(), true},
73 {Null(instance_->isolate()).As<Value>(), false},
74 {Undefined(instance_->isolate()).As<Value>(), false},
abarth@chromium.orga22998a2013-11-10 05:00:5075 };
76
Daniel Chengef5f136902022-02-27 01:05:2577 for (size_t i = 0; i < std::size(test_data); ++i) {
abarth@chromium.orga22998a2013-11-10 05:00:5078 bool result = false;
aa@chromium.org7618ebbb2013-11-27 03:38:2679 EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
80 test_data[i].input, &result));
abarth@chromium.orga22998a2013-11-10 05:00:5081 EXPECT_EQ(test_data[i].expected, result);
82
83 result = true;
aa@chromium.org7618ebbb2013-11-27 03:38:2684 EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
85 test_data[i].input, &result));
abarth@chromium.orga22998a2013-11-10 05:00:5086 EXPECT_EQ(test_data[i].expected, result);
87 }
88}
89
Shelley Vohr4c679122019-09-06 00:41:3990TEST_F(ConverterTest, String16) {
91 v8::Isolate* isolate = instance_->isolate();
92
93 HandleScope handle_scope(isolate);
94
Jan Wilken Dörriec92a6d7242021-03-23 17:43:4895 EXPECT_TRUE(Converter<std::u16string>::ToV8(isolate, u"")
Shelley Vohr4c679122019-09-06 00:41:3996 ->StrictEquals(StringToV8(isolate, "")));
Jan Wilken Dörriec92a6d7242021-03-23 17:43:4897 EXPECT_TRUE(Converter<std::u16string>::ToV8(isolate, u"hello")
98 ->StrictEquals(StringToV8(isolate, "hello")));
Shelley Vohr4c679122019-09-06 00:41:3999
Jan Wilken Dörrie739ccc212021-03-11 18:13:05100 std::u16string result;
Shelley Vohr4c679122019-09-06 00:41:39101
102 ASSERT_FALSE(
Jan Wilken Dörrie739ccc212021-03-11 18:13:05103 Converter<std::u16string>::FromV8(isolate, v8::False(isolate), &result));
Shelley Vohr4c679122019-09-06 00:41:39104 ASSERT_FALSE(
Jan Wilken Dörrie739ccc212021-03-11 18:13:05105 Converter<std::u16string>::FromV8(isolate, v8::True(isolate), &result));
106 ASSERT_TRUE(Converter<std::u16string>::FromV8(
Shelley Vohr4c679122019-09-06 00:41:39107 isolate, v8::String::Empty(isolate), &result));
Jan Wilken Dörrie739ccc212021-03-11 18:13:05108 EXPECT_EQ(result, std::u16string());
109 ASSERT_TRUE(Converter<std::u16string>::FromV8(
Shelley Vohr4c679122019-09-06 00:41:39110 isolate, StringToV8(isolate, "hello"), &result));
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48111 EXPECT_EQ(result, u"hello");
Shelley Vohr4c679122019-09-06 00:41:39112}
113
abarth@chromium.orga22998a2013-11-10 05:00:50114TEST_F(ConverterTest, Int32) {
jochen@chromium.org1b93c232013-11-19 19:25:12115 HandleScope handle_scope(instance_->isolate());
abarth@chromium.orga22998a2013-11-10 05:00:50116
117 int test_data_to[] = {-1, 0, 1};
Daniel Chengef5f136902022-02-27 01:05:25118 for (size_t i = 0; i < std::size(test_data_to); ++i) {
jochen@chromium.orgadd8fb172014-01-03 15:13:49119 EXPECT_TRUE(Converter<int32_t>::ToV8(instance_->isolate(), test_data_to[i])
120 ->StrictEquals(
121 Integer::New(instance_->isolate(), test_data_to[i])));
abarth@chromium.orga22998a2013-11-10 05:00:50122 }
123
124 struct {
deepak.sfaaa1b62015-04-30 07:30:48125 v8::Local<v8::Value> input;
thestig259626c2015-11-23 20:18:11126 bool expect_success;
abarth@chromium.orga22998a2013-11-10 05:00:50127 int expected_result;
128 } test_data_from[] = {
Yang Guo26b0f7772018-11-27 08:37:20129 {Boolean::New(instance_->isolate(), false).As<Value>(), false, 0},
130 {Boolean::New(instance_->isolate(), true).As<Value>(), false, 0},
131 {Integer::New(instance_->isolate(), -1).As<Value>(), true, -1},
132 {Integer::New(instance_->isolate(), 0).As<Value>(), true, 0},
133 {Integer::New(instance_->isolate(), 1).As<Value>(), true, 1},
134 {Number::New(instance_->isolate(), -1).As<Value>(), true, -1},
135 {Number::New(instance_->isolate(), 1.1).As<Value>(), false, 0},
136 {String::NewFromUtf8(instance_->isolate(), "42",
137 v8::NewStringType::kNormal)
138 .ToLocalChecked()
139 .As<Value>(),
140 false, 0},
141 {String::NewFromUtf8(instance_->isolate(), "foo",
142 v8::NewStringType::kNormal)
143 .ToLocalChecked()
144 .As<Value>(),
145 false, 0},
146 {Object::New(instance_->isolate()).As<Value>(), false, 0},
147 {Array::New(instance_->isolate()).As<Value>(), false, 0},
148 {v8::Null(instance_->isolate()).As<Value>(), false, 0},
149 {v8::Undefined(instance_->isolate()).As<Value>(), false, 0},
abarth@chromium.orga22998a2013-11-10 05:00:50150 };
151
Daniel Chengef5f136902022-02-27 01:05:25152 for (size_t i = 0; i < std::size(test_data_from); ++i) {
abarth@chromium.orga22998a2013-11-10 05:00:50153 int32_t result = std::numeric_limits<int32_t>::min();
aa@chromium.org7618ebbb2013-11-27 03:38:26154 bool success = Converter<int32_t>::FromV8(instance_->isolate(),
155 test_data_from[i].input, &result);
thestig259626c2015-11-23 20:18:11156 EXPECT_EQ(test_data_from[i].expect_success, success) << i;
abarth@chromium.orga22998a2013-11-10 05:00:50157 if (success)
158 EXPECT_EQ(test_data_from[i].expected_result, result) << i;
159 }
160}
161
162TEST_F(ConverterTest, Vector) {
jochen@chromium.org1b93c232013-11-19 19:25:12163 HandleScope handle_scope(instance_->isolate());
abarth@chromium.orga22998a2013-11-10 05:00:50164
165 std::vector<int> expected;
166 expected.push_back(-1);
167 expected.push_back(0);
168 expected.push_back(1);
169
Jeremy Romaneb8a2f172018-01-29 17:33:40170 auto js_array =
171 Converter<std::vector<int>>::ToV8(instance_->isolate(), expected)
172 .As<Array>();
173 EXPECT_EQ(3u, js_array->Length());
Dan Elphickd7eeb4a2019-02-01 17:55:56174 v8::Local<v8::Context> context = instance_->isolate()->GetCurrentContext();
abarth@chromium.orga22998a2013-11-10 05:00:50175 for (size_t i = 0; i < expected.size(); ++i) {
Dan Elphickd7eeb4a2019-02-01 17:55:56176 EXPECT_TRUE(
177 Integer::New(instance_->isolate(), expected[i])
178 ->StrictEquals(
179 js_array->Get(context, static_cast<int>(i)).ToLocalChecked()));
abarth@chromium.orga22998a2013-11-10 05:00:50180 }
abarth@chromium.orga22998a2013-11-10 05:00:50181}
182
Jeremy Romaneb8a2f172018-01-29 17:33:40183TEST_F(ConverterTest, VectorOfVectors) {
184 HandleScope handle_scope(instance_->isolate());
185
186 std::vector<std::vector<int>> vector_of_vectors = {
187 {1, 2, 3}, {4, 5, 6},
188 };
189
190 v8::Local<v8::Value> v8_value =
191 ConvertToV8(instance_->isolate(), vector_of_vectors);
192 std::vector<std::vector<int>> out_value;
193 ASSERT_TRUE(ConvertFromV8(instance_->isolate(), v8_value, &out_value));
194 EXPECT_THAT(out_value, testing::ContainerEq(vector_of_vectors));
195}
196
197namespace {
198
199class MyObject : public Wrappable<MyObject> {
200 public:
201 static WrapperInfo kWrapperInfo;
202
203 static gin::Handle<MyObject> Create(v8::Isolate* isolate) {
204 return CreateHandle(isolate, new MyObject());
205 }
206};
207
208WrapperInfo MyObject::kWrapperInfo = {kEmbedderNativeGin};
209
210} // namespace
211
212TEST_F(ConverterTest, VectorOfWrappables) {
213 v8::Isolate* isolate = instance_->isolate();
214 v8::HandleScope handle_scope(isolate);
215
216 Handle<MyObject> obj = MyObject::Create(isolate);
217 std::vector<MyObject*> vector = {obj.get()};
218 v8::MaybeLocal<v8::Value> maybe = ConvertToV8(isolate, vector);
219 v8::Local<v8::Value> array;
220 ASSERT_TRUE(maybe.ToLocal(&array));
Jeremy Romanbc83c772018-03-16 17:16:55221 v8::Local<v8::Value> array2;
222 ASSERT_TRUE(TryConvertToV8(isolate, vector, &array2));
Jeremy Romaneb8a2f172018-01-29 17:33:40223
224 std::vector<MyObject*> out_value;
225 ASSERT_TRUE(ConvertFromV8(isolate, array, &out_value));
226 EXPECT_THAT(out_value, testing::ContainerEq(vector));
Jeremy Romanbc83c772018-03-16 17:16:55227 std::vector<MyObject*> out_value2;
228 ASSERT_TRUE(ConvertFromV8(isolate, array2, &out_value2));
229 EXPECT_THAT(out_value2, testing::ContainerEq(vector));
Jeremy Romaneb8a2f172018-01-29 17:33:40230}
231
Jeremy Apthorp789ac3b2020-04-01 01:06:45232namespace {
233
234class MoveOnlyObject {
235 public:
236 MoveOnlyObject() = default;
237 MoveOnlyObject(const MoveOnlyObject&) = delete;
238 MoveOnlyObject& operator=(const MoveOnlyObject&) = delete;
239
240 MoveOnlyObject(MoveOnlyObject&&) noexcept = default;
241 MoveOnlyObject& operator=(MoveOnlyObject&&) noexcept = default;
242};
243
244} // namespace
245
246template <>
247struct Converter<MoveOnlyObject> {
248 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, MoveOnlyObject in) {
249 return v8::Undefined(isolate);
250 }
251 static bool FromV8(v8::Isolate* isolate,
252 v8::Local<v8::Value> val,
253 MoveOnlyObject* out) {
254 *out = MoveOnlyObject();
255 return true;
256 }
257};
258
259TEST_F(ConverterTest, MoveOnlyParameters) {
260 v8::Isolate* isolate = instance_->isolate();
261 v8::HandleScope handle_scope(isolate);
262
263 auto receives_move_only_obj = [](MoveOnlyObject obj) {};
264 auto func_templ = gin::CreateFunctionTemplate(
265 isolate, base::BindRepeating(receives_move_only_obj));
266
267 v8::Local<v8::Context> context = instance_->isolate()->GetCurrentContext();
268 auto func = func_templ->GetFunction(context).ToLocalChecked();
269 v8::Local<v8::Value> argv[] = {v8::Undefined(isolate)};
270 func->Call(context, v8::Undefined(isolate), 1, argv).ToLocalChecked();
271}
272
Joel Klinghed99d2a1592023-11-07 19:22:32273TEST_F(ConverterTest, VectorOfMoveOnly) {
274 v8::Isolate* isolate = instance_->isolate();
275 v8::HandleScope handle_scope(isolate);
276
277 v8::Local<v8::Value> v8_value = v8::Array::New(instance_->isolate(), 1);
278 std::vector<MoveOnlyObject> out_value;
279 ASSERT_TRUE(ConvertFromV8(instance_->isolate(), v8_value, &out_value));
280 EXPECT_EQ(out_value.size(), 1u);
281}
282
abarth@chromium.orga22998a2013-11-10 05:00:50283} // namespace gin