blob: 2afca004074a039e740908e85813ec8c07b480c7 [file] [log] [blame]
Avi Drissman468e51b62022-09-13 20:47:011// Copyright 2013 The Chromium Authors
[email protected]a22998a2013-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#ifndef GIN_CONVERTER_H_
6#define GIN_CONVERTER_H_
7
avi90e658dd2015-12-21 07:16:198#include <stdint.h>
9
Jeremy Romanee67271a2023-11-14 16:36:2210#include <concepts>
Hans Wennborg5cd6d192020-06-18 11:14:5611#include <ostream>
[email protected]a22998a2013-11-10 05:00:5012#include <string>
Jeremy Romaneb8a2f172018-01-29 17:33:4013#include <type_traits>
Joel Klinghed99d2a1592023-11-07 19:22:3214#include <utility>
[email protected]a22998a2013-11-10 05:00:5015#include <vector>
16
Hans Wennborgc8b134b2020-06-19 21:15:3917#include "base/check.h"
18#include "base/notreached.h"
[email protected]b520e132013-11-29 03:21:4819#include "base/strings/string_piece.h"
[email protected]48c21632013-12-12 21:32:3420#include "gin/gin_export.h"
Dan Elphick05acd602021-08-30 15:22:0721#include "v8/include/v8-container.h"
22#include "v8/include/v8-forward.h"
23#include "v8/include/v8-isolate.h"
[email protected]a22998a2013-11-10 05:00:5024
Keren Zhu1deb4672022-01-14 19:11:5125namespace base {
26class TimeTicks;
27}
28
[email protected]a22998a2013-11-10 05:00:5029namespace gin {
30
bashidbd2ef9bb2015-06-02 01:39:3231template<typename KeyType>
32bool SetProperty(v8::Isolate* isolate,
33 v8::Local<v8::Object> object,
34 KeyType key,
35 v8::Local<v8::Value> value) {
rdevlin.cronin415b73b2015-11-13 01:14:4736 auto maybe =
37 object->DefineOwnProperty(isolate->GetCurrentContext(), key, value);
bashidbd2ef9bb2015-06-02 01:39:3238 return !maybe.IsNothing() && maybe.FromJust();
39}
40
[email protected]cf76c84a2013-12-06 14:07:0741template<typename T, typename Enable = void>
[email protected]a22998a2013-11-10 05:00:5042struct Converter {};
43
Jeremy Romanee67271a2023-11-14 16:36:2244namespace internal {
45
46template <typename T>
47concept ToV8ReturnsMaybe = requires(v8::Isolate* isolate, T value) {
48 {
49 Converter<T>::ToV8(isolate, value)
50 } -> std::same_as<v8::MaybeLocal<v8::Value>>;
51};
52
53} // namespace internal
54
[email protected]a22998a2013-11-10 05:00:5055template<>
[email protected]48c21632013-12-12 21:32:3456struct GIN_EXPORT Converter<bool> {
deepak.sfaaa1b62015-04-30 07:30:4857 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]a22998a2013-11-10 05:00:5058 bool val);
[email protected]7618ebbb2013-11-27 03:38:2659 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4860 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:5061 bool* out);
62};
63
64template<>
[email protected]48c21632013-12-12 21:32:3465struct GIN_EXPORT Converter<int32_t> {
deepak.sfaaa1b62015-04-30 07:30:4866 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]a22998a2013-11-10 05:00:5067 int32_t val);
[email protected]7618ebbb2013-11-27 03:38:2668 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4869 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:5070 int32_t* out);
71};
72
73template<>
[email protected]48c21632013-12-12 21:32:3474struct GIN_EXPORT Converter<uint32_t> {
deepak.sfaaa1b62015-04-30 07:30:4875 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]a22998a2013-11-10 05:00:5076 uint32_t val);
[email protected]7618ebbb2013-11-27 03:38:2677 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4878 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:5079 uint32_t* out);
80};
81
82template<>
[email protected]48c21632013-12-12 21:32:3483struct GIN_EXPORT Converter<int64_t> {
[email protected]e87f3122013-11-12 00:41:2784 // Warning: JavaScript cannot represent 64 integers precisely.
deepak.sfaaa1b62015-04-30 07:30:4885 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]e87f3122013-11-12 00:41:2786 int64_t val);
[email protected]7618ebbb2013-11-27 03:38:2687 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4888 v8::Local<v8::Value> val,
[email protected]e87f3122013-11-12 00:41:2789 int64_t* out);
90};
91
92template<>
[email protected]48c21632013-12-12 21:32:3493struct GIN_EXPORT Converter<uint64_t> {
[email protected]e87f3122013-11-12 00:41:2794 // Warning: JavaScript cannot represent 64 integers precisely.
deepak.sfaaa1b62015-04-30 07:30:4895 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]e87f3122013-11-12 00:41:2796 uint64_t val);
[email protected]7618ebbb2013-11-27 03:38:2697 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4898 v8::Local<v8::Value> val,
[email protected]e87f3122013-11-12 00:41:2799 uint64_t* out);
100};
101
102template<>
[email protected]d73341d12013-12-21 00:48:46103struct GIN_EXPORT Converter<float> {
deepak.sfaaa1b62015-04-30 07:30:48104 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]d73341d12013-12-21 00:48:46105 float val);
106 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48107 v8::Local<v8::Value> val,
[email protected]d73341d12013-12-21 00:48:46108 float* out);
109};
110
111template<>
[email protected]48c21632013-12-12 21:32:34112struct GIN_EXPORT Converter<double> {
deepak.sfaaa1b62015-04-30 07:30:48113 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]a22998a2013-11-10 05:00:50114 double val);
[email protected]7618ebbb2013-11-27 03:38:26115 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48116 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:50117 double* out);
118};
119
120template<>
[email protected]48c21632013-12-12 21:32:34121struct GIN_EXPORT Converter<base::StringPiece> {
bashidbd2ef9bb2015-06-02 01:39:32122 // This crashes when val.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48123 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]b520e132013-11-29 03:21:48124 const base::StringPiece& val);
125 // No conversion out is possible because StringPiece does not contain storage.
126};
127
128template<>
[email protected]48c21632013-12-12 21:32:34129struct GIN_EXPORT Converter<std::string> {
bashidbd2ef9bb2015-06-02 01:39:32130 // This crashes when val.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48131 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
[email protected]a22998a2013-11-10 05:00:50132 const std::string& val);
[email protected]7618ebbb2013-11-27 03:38:26133 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48134 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:50135 std::string* out);
136};
137
Shimi Zhang15708bfc2019-08-13 19:24:48138template <>
Jan Wilken Dörrie739ccc212021-03-11 18:13:05139struct GIN_EXPORT Converter<std::u16string> {
Shimi Zhang15708bfc2019-08-13 19:24:48140 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Jan Wilken Dörrie739ccc212021-03-11 18:13:05141 const std::u16string& val);
Shimi Zhang15708bfc2019-08-13 19:24:48142 static bool FromV8(v8::Isolate* isolate,
143 v8::Local<v8::Value> val,
Jan Wilken Dörrie739ccc212021-03-11 18:13:05144 std::u16string* out);
Shimi Zhang15708bfc2019-08-13 19:24:48145};
146
Keren Zhu1deb4672022-01-14 19:11:51147// Converter for C++ TimeTicks to Javascript BigInt (unit: microseconds).
148// TimeTicks can't be converted using the existing Converter<int64_t> because
149// the target type will be Number and will lose precision.
150template <>
151struct GIN_EXPORT Converter<base::TimeTicks> {
152 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, base::TimeTicks val);
153};
154
Shimi Zhang15708bfc2019-08-13 19:24:48155template <>
156struct GIN_EXPORT Converter<v8::Local<v8::Function>> {
Nitish Sakhawalkarf7bbaa522019-02-11 16:19:09157 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
158 v8::Local<v8::Function> val);
[email protected]7618ebbb2013-11-27 03:38:26159 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48160 v8::Local<v8::Value> val,
161 v8::Local<v8::Function>* out);
[email protected]a22998a2013-11-10 05:00:50162};
163
164template<>
deepak.sfaaa1b62015-04-30 07:30:48165struct GIN_EXPORT Converter<v8::Local<v8::Object> > {
166 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
167 v8::Local<v8::Object> val);
[email protected]7618ebbb2013-11-27 03:38:26168 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48169 v8::Local<v8::Value> val,
170 v8::Local<v8::Object>* out);
[email protected]a22998a2013-11-10 05:00:50171};
172
Scott Grahamd2f4ed4b2018-10-17 01:57:27173template <>
174struct GIN_EXPORT Converter<v8::Local<v8::Promise>> {
175 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
176 v8::Local<v8::Promise> val);
177 static bool FromV8(v8::Isolate* isolate,
178 v8::Local<v8::Value> val,
179 v8::Local<v8::Promise>* out);
180};
181
[email protected]97f21ca2013-11-17 17:46:07182template<>
deepak.sfaaa1b62015-04-30 07:30:48183struct GIN_EXPORT Converter<v8::Local<v8::ArrayBuffer> > {
184 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
185 v8::Local<v8::ArrayBuffer> val);
[email protected]7618ebbb2013-11-27 03:38:26186 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48187 v8::Local<v8::Value> val,
188 v8::Local<v8::ArrayBuffer>* out);
[email protected]ec95fdf2013-11-24 19:10:11189};
190
191template<>
deepak.sfaaa1b62015-04-30 07:30:48192struct GIN_EXPORT Converter<v8::Local<v8::External> > {
193 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
194 v8::Local<v8::External> val);
[email protected]7618ebbb2013-11-27 03:38:26195 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48196 v8::Local<v8::Value> val,
197 v8::Local<v8::External>* out);
[email protected]97f21ca2013-11-17 17:46:07198};
199
200template<>
deepak.sfaaa1b62015-04-30 07:30:48201struct GIN_EXPORT Converter<v8::Local<v8::Value> > {
202 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
203 v8::Local<v8::Value> val);
[email protected]7618ebbb2013-11-27 03:38:26204 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48205 v8::Local<v8::Value> val,
206 v8::Local<v8::Value>* out);
[email protected]97f21ca2013-11-17 17:46:07207};
208
[email protected]a22998a2013-11-10 05:00:50209template<typename T>
210struct Converter<std::vector<T> > {
Jeremy Romanee67271a2023-11-14 16:36:22211 static std::conditional_t<internal::ToV8ReturnsMaybe<T>,
Jeremy Romaneb8a2f172018-01-29 17:33:40212 v8::MaybeLocal<v8::Value>,
213 v8::Local<v8::Value>>
214 ToV8(v8::Isolate* isolate, const std::vector<T>& val) {
215 v8::Local<v8::Context> context = isolate->GetCurrentContext();
deepak.sfaaa1b62015-04-30 07:30:48216 v8::Local<v8::Array> result(
[email protected]91cd4fe2013-11-28 09:31:58217 v8::Array::New(isolate, static_cast<int>(val.size())));
bashidbd2ef9bb2015-06-02 01:39:32218 for (uint32_t i = 0; i < val.size(); ++i) {
Jeremy Romaneb8a2f172018-01-29 17:33:40219 v8::MaybeLocal<v8::Value> maybe = Converter<T>::ToV8(isolate, val[i]);
220 v8::Local<v8::Value> element;
221 if (!maybe.ToLocal(&element))
222 return {};
223 bool property_created;
224 if (!result->CreateDataProperty(context, i, element)
225 .To(&property_created) ||
226 !property_created) {
227 NOTREACHED() << "CreateDataProperty should always succeed here.";
228 }
[email protected]a22998a2013-11-10 05:00:50229 }
230 return result;
231 }
232
[email protected]7618ebbb2013-11-27 03:38:26233 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48234 v8::Local<v8::Value> val,
[email protected]a22998a2013-11-10 05:00:50235 std::vector<T>* out) {
236 if (!val->IsArray())
237 return false;
238
239 std::vector<T> result;
deepak.sfaaa1b62015-04-30 07:30:48240 v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
[email protected]a22998a2013-11-10 05:00:50241 uint32_t length = array->Length();
242 for (uint32_t i = 0; i < length; ++i) {
bashidbd2ef9bb2015-06-02 01:39:32243 v8::Local<v8::Value> v8_item;
244 if (!array->Get(isolate->GetCurrentContext(), i).ToLocal(&v8_item))
245 return false;
[email protected]a22998a2013-11-10 05:00:50246 T item;
bashidbd2ef9bb2015-06-02 01:39:32247 if (!Converter<T>::FromV8(isolate, v8_item, &item))
[email protected]a22998a2013-11-10 05:00:50248 return false;
Joel Klinghed99d2a1592023-11-07 19:22:32249 result.push_back(std::move(item));
[email protected]a22998a2013-11-10 05:00:50250 }
251
252 out->swap(result);
253 return true;
254 }
255};
256
Nikolaos Papaspyrou5ce2a2f2023-10-19 09:09:00257template <typename T>
258struct Converter<v8::LocalVector<T>> {
Jeremy Romanee67271a2023-11-14 16:36:22259 static std::conditional_t<internal::ToV8ReturnsMaybe<v8::Local<T>>,
Nikolaos Papaspyrou5ce2a2f2023-10-19 09:09:00260 v8::MaybeLocal<v8::Value>,
261 v8::Local<v8::Value>>
262 ToV8(v8::Isolate* isolate, const v8::LocalVector<T>& val) {
263 v8::Local<v8::Context> context = isolate->GetCurrentContext();
264 v8::Local<v8::Array> result(
265 v8::Array::New(isolate, static_cast<int>(val.size())));
266 for (uint32_t i = 0; i < val.size(); ++i) {
267 v8::MaybeLocal<v8::Value> maybe =
268 Converter<v8::Local<T>>::ToV8(isolate, val[i]);
269 v8::Local<v8::Value> element;
270 if (!maybe.ToLocal(&element)) {
271 return {};
272 }
273 bool property_created;
274 if (!result->CreateDataProperty(context, i, element)
275 .To(&property_created) ||
276 !property_created) {
277 NOTREACHED() << "CreateDataProperty should always succeed here.";
278 }
279 }
280 return result;
281 }
282
283 static bool FromV8(v8::Isolate* isolate,
284 v8::Local<v8::Value> val,
285 v8::LocalVector<T>* out) {
286 if (!val->IsArray()) {
287 return false;
288 }
289
290 v8::LocalVector<T> result(isolate);
291 v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
292 uint32_t length = array->Length();
293 for (uint32_t i = 0; i < length; ++i) {
294 v8::Local<v8::Value> v8_item;
295 if (!array->Get(isolate->GetCurrentContext(), i).ToLocal(&v8_item)) {
296 return false;
297 }
298 v8::Local<T> item;
299 if (!Converter<v8::Local<T>>::FromV8(isolate, v8_item, &item)) {
300 return false;
301 }
302 result.push_back(item);
303 }
304
305 out->swap(result);
306 return true;
307 }
308};
309
[email protected]a22998a2013-11-10 05:00:50310// Convenience functions that deduce T.
Jeremy Romaneb8a2f172018-01-29 17:33:40311template <typename T>
Jeremy Romanee67271a2023-11-14 16:36:22312std::conditional_t<internal::ToV8ReturnsMaybe<T>,
Jeremy Romaneb8a2f172018-01-29 17:33:40313 v8::MaybeLocal<v8::Value>,
314 v8::Local<v8::Value>>
Jeremy Apthorp6a3480292018-04-26 18:53:59315ConvertToV8(v8::Isolate* isolate, const T& input) {
[email protected]a22998a2013-11-10 05:00:50316 return Converter<T>::ToV8(isolate, input);
317}
318
Jeremy Roman44bda444b2018-03-16 17:33:45319template <typename T>
Jeremy Romanee67271a2023-11-14 16:36:22320bool TryConvertToV8(v8::Isolate* isolate,
321 const T& input,
322 v8::Local<v8::Value>* output) {
323 if constexpr (internal::ToV8ReturnsMaybe<T>) {
324 return ConvertToV8(isolate, input).ToLocal(output);
325 } else {
326 *output = ConvertToV8(isolate, input);
327 return true;
328 }
bashidbd2ef9bb2015-06-02 01:39:32329}
330
331// This crashes when input.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48332GIN_EXPORT inline v8::Local<v8::String> StringToV8(
[email protected]48c21632013-12-12 21:32:34333 v8::Isolate* isolate,
334 const base::StringPiece& input) {
[email protected]a22998a2013-11-10 05:00:50335 return ConvertToV8(isolate, input).As<v8::String>();
336}
337
bashidbd2ef9bb2015-06-02 01:39:32338// This crashes when input.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48339GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
[email protected]48c21632013-12-12 21:32:34340 const base::StringPiece& val);
[email protected]e87f3122013-11-12 00:41:27341
Shimi Zhang15708bfc2019-08-13 19:24:48342// This crashes when input.size() > v8::String::kMaxLength.
343GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
344 const base::StringPiece16& val);
345
[email protected]a22998a2013-11-10 05:00:50346template<typename T>
deepak.sfaaa1b62015-04-30 07:30:48347bool ConvertFromV8(v8::Isolate* isolate, v8::Local<v8::Value> input,
[email protected]7618ebbb2013-11-27 03:38:26348 T* result) {
Dan Elphick712beaa2018-07-24 17:37:24349 DCHECK(isolate);
[email protected]7618ebbb2013-11-27 03:38:26350 return Converter<T>::FromV8(isolate, input, result);
[email protected]a22998a2013-11-10 05:00:50351}
352
Dan Elphick38a508052018-07-23 22:19:53353GIN_EXPORT std::string V8ToString(v8::Isolate* isolate,
354 v8::Local<v8::Value> value);
[email protected]2f703422013-11-25 21:26:15355
[email protected]a22998a2013-11-10 05:00:50356} // namespace gin
357
358#endif // GIN_CONVERTER_H_