[go: nahoru, domu]

blob: 7a6392f9290f750947f91e9e08d9411415a3fa38 [file] [log] [blame]
abarth@chromium.orga22998a2013-11-10 05:00:501// Copyright 2013 The Chromium Authors. All rights reserved.
2// 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
Hans Wennborg5cd6d192020-06-18 11:14:5610#include <ostream>
abarth@chromium.orga22998a2013-11-10 05:00:5011#include <string>
Jeremy Romaneb8a2f172018-01-29 17:33:4012#include <type_traits>
abarth@chromium.orga22998a2013-11-10 05:00:5013#include <vector>
14
Hans Wennborgc8b134b2020-06-19 21:15:3915#include "base/check.h"
16#include "base/notreached.h"
aa@chromium.orgb520e132013-11-29 03:21:4817#include "base/strings/string_piece.h"
jochen@chromium.org48c21632013-12-12 21:32:3418#include "gin/gin_export.h"
Dan Elphick05acd602021-08-30 15:22:0719#include "v8/include/v8-container.h"
20#include "v8/include/v8-forward.h"
21#include "v8/include/v8-isolate.h"
abarth@chromium.orga22998a2013-11-10 05:00:5022
Keren Zhu1deb4672022-01-14 19:11:5123namespace base {
24class TimeTicks;
25}
26
abarth@chromium.orga22998a2013-11-10 05:00:5027namespace gin {
28
bashidbd2ef9bb2015-06-02 01:39:3229template<typename KeyType>
30bool SetProperty(v8::Isolate* isolate,
31 v8::Local<v8::Object> object,
32 KeyType key,
33 v8::Local<v8::Value> value) {
rdevlin.cronin415b73b2015-11-13 01:14:4734 auto maybe =
35 object->DefineOwnProperty(isolate->GetCurrentContext(), key, value);
bashidbd2ef9bb2015-06-02 01:39:3236 return !maybe.IsNothing() && maybe.FromJust();
37}
38
Ken Rockot2b0f07652017-04-12 19:10:4939template <typename T, typename Enable = void>
bashidbd2ef9bb2015-06-02 01:39:3240struct ToV8ReturnsMaybe {
41 static const bool value = false;
42};
43
aa@chromium.orgcf76c84a2013-12-06 14:07:0744template<typename T, typename Enable = void>
abarth@chromium.orga22998a2013-11-10 05:00:5045struct Converter {};
46
47template<>
jochen@chromium.org48c21632013-12-12 21:32:3448struct GIN_EXPORT Converter<bool> {
deepak.sfaaa1b62015-04-30 07:30:4849 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orga22998a2013-11-10 05:00:5050 bool val);
aa@chromium.org7618ebbb2013-11-27 03:38:2651 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4852 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:5053 bool* out);
54};
55
56template<>
jochen@chromium.org48c21632013-12-12 21:32:3457struct GIN_EXPORT Converter<int32_t> {
deepak.sfaaa1b62015-04-30 07:30:4858 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orga22998a2013-11-10 05:00:5059 int32_t val);
aa@chromium.org7618ebbb2013-11-27 03:38:2660 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4861 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:5062 int32_t* out);
63};
64
65template<>
jochen@chromium.org48c21632013-12-12 21:32:3466struct GIN_EXPORT Converter<uint32_t> {
deepak.sfaaa1b62015-04-30 07:30:4867 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orga22998a2013-11-10 05:00:5068 uint32_t val);
aa@chromium.org7618ebbb2013-11-27 03:38:2669 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4870 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:5071 uint32_t* out);
72};
73
74template<>
jochen@chromium.org48c21632013-12-12 21:32:3475struct GIN_EXPORT Converter<int64_t> {
abarth@chromium.orge87f3122013-11-12 00:41:2776 // Warning: JavaScript cannot represent 64 integers precisely.
deepak.sfaaa1b62015-04-30 07:30:4877 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orge87f3122013-11-12 00:41:2778 int64_t val);
aa@chromium.org7618ebbb2013-11-27 03:38:2679 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4880 v8::Local<v8::Value> val,
abarth@chromium.orge87f3122013-11-12 00:41:2781 int64_t* out);
82};
83
84template<>
jochen@chromium.org48c21632013-12-12 21:32:3485struct GIN_EXPORT Converter<uint64_t> {
abarth@chromium.orge87f3122013-11-12 00:41:2786 // Warning: JavaScript cannot represent 64 integers precisely.
deepak.sfaaa1b62015-04-30 07:30:4887 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orge87f3122013-11-12 00:41:2788 uint64_t val);
aa@chromium.org7618ebbb2013-11-27 03:38:2689 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4890 v8::Local<v8::Value> val,
abarth@chromium.orge87f3122013-11-12 00:41:2791 uint64_t* out);
92};
93
94template<>
aa@chromium.orgd73341d12013-12-21 00:48:4695struct GIN_EXPORT Converter<float> {
deepak.sfaaa1b62015-04-30 07:30:4896 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
aa@chromium.orgd73341d12013-12-21 00:48:4697 float val);
98 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:4899 v8::Local<v8::Value> val,
aa@chromium.orgd73341d12013-12-21 00:48:46100 float* out);
101};
102
103template<>
jochen@chromium.org48c21632013-12-12 21:32:34104struct GIN_EXPORT Converter<double> {
deepak.sfaaa1b62015-04-30 07:30:48105 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
abarth@chromium.orga22998a2013-11-10 05:00:50106 double val);
aa@chromium.org7618ebbb2013-11-27 03:38:26107 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48108 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:50109 double* out);
110};
111
112template<>
jochen@chromium.org48c21632013-12-12 21:32:34113struct GIN_EXPORT Converter<base::StringPiece> {
bashidbd2ef9bb2015-06-02 01:39:32114 // This crashes when val.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48115 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
aa@chromium.orgb520e132013-11-29 03:21:48116 const base::StringPiece& val);
117 // No conversion out is possible because StringPiece does not contain storage.
118};
119
120template<>
jochen@chromium.org48c21632013-12-12 21:32:34121struct GIN_EXPORT Converter<std::string> {
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,
abarth@chromium.orga22998a2013-11-10 05:00:50124 const std::string& val);
aa@chromium.org7618ebbb2013-11-27 03:38:26125 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48126 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:50127 std::string* out);
128};
129
Shimi Zhang15708bfc2019-08-13 19:24:48130template <>
Jan Wilken Dörrie739ccc212021-03-11 18:13:05131struct GIN_EXPORT Converter<std::u16string> {
Shimi Zhang15708bfc2019-08-13 19:24:48132 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Jan Wilken Dörrie739ccc212021-03-11 18:13:05133 const std::u16string& val);
Shimi Zhang15708bfc2019-08-13 19:24:48134 static bool FromV8(v8::Isolate* isolate,
135 v8::Local<v8::Value> val,
Jan Wilken Dörrie739ccc212021-03-11 18:13:05136 std::u16string* out);
Shimi Zhang15708bfc2019-08-13 19:24:48137};
138
Keren Zhu1deb4672022-01-14 19:11:51139// Converter for C++ TimeTicks to Javascript BigInt (unit: microseconds).
140// TimeTicks can't be converted using the existing Converter<int64_t> because
141// the target type will be Number and will lose precision.
142template <>
143struct GIN_EXPORT Converter<base::TimeTicks> {
144 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, base::TimeTicks val);
145};
146
Shimi Zhang15708bfc2019-08-13 19:24:48147template <>
148struct GIN_EXPORT Converter<v8::Local<v8::Function>> {
Nitish Sakhawalkarf7bbaa52019-02-11 16:19:09149 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
150 v8::Local<v8::Function> val);
aa@chromium.org7618ebbb2013-11-27 03:38:26151 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48152 v8::Local<v8::Value> val,
153 v8::Local<v8::Function>* out);
abarth@chromium.orga22998a2013-11-10 05:00:50154};
155
156template<>
deepak.sfaaa1b62015-04-30 07:30:48157struct GIN_EXPORT Converter<v8::Local<v8::Object> > {
158 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
159 v8::Local<v8::Object> val);
aa@chromium.org7618ebbb2013-11-27 03:38:26160 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48161 v8::Local<v8::Value> val,
162 v8::Local<v8::Object>* out);
abarth@chromium.orga22998a2013-11-10 05:00:50163};
164
Scott Grahamd2f4ed4b2018-10-17 01:57:27165template <>
166struct GIN_EXPORT Converter<v8::Local<v8::Promise>> {
167 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
168 v8::Local<v8::Promise> val);
169 static bool FromV8(v8::Isolate* isolate,
170 v8::Local<v8::Value> val,
171 v8::Local<v8::Promise>* out);
172};
173
abarth@chromium.org97f21ca2013-11-17 17:46:07174template<>
deepak.sfaaa1b62015-04-30 07:30:48175struct GIN_EXPORT Converter<v8::Local<v8::ArrayBuffer> > {
176 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
177 v8::Local<v8::ArrayBuffer> val);
aa@chromium.org7618ebbb2013-11-27 03:38:26178 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48179 v8::Local<v8::Value> val,
180 v8::Local<v8::ArrayBuffer>* out);
abarth@chromium.orgec95fdf2013-11-24 19:10:11181};
182
183template<>
deepak.sfaaa1b62015-04-30 07:30:48184struct GIN_EXPORT Converter<v8::Local<v8::External> > {
185 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
186 v8::Local<v8::External> val);
aa@chromium.org7618ebbb2013-11-27 03:38:26187 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48188 v8::Local<v8::Value> val,
189 v8::Local<v8::External>* out);
abarth@chromium.org97f21ca2013-11-17 17:46:07190};
191
192template<>
deepak.sfaaa1b62015-04-30 07:30:48193struct GIN_EXPORT Converter<v8::Local<v8::Value> > {
194 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
195 v8::Local<v8::Value> val);
aa@chromium.org7618ebbb2013-11-27 03:38:26196 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48197 v8::Local<v8::Value> val,
198 v8::Local<v8::Value>* out);
abarth@chromium.org97f21ca2013-11-17 17:46:07199};
200
abarth@chromium.orga22998a2013-11-10 05:00:50201template<typename T>
202struct Converter<std::vector<T> > {
Jeremy Romaneb8a2f172018-01-29 17:33:40203 static std::conditional_t<ToV8ReturnsMaybe<T>::value,
204 v8::MaybeLocal<v8::Value>,
205 v8::Local<v8::Value>>
206 ToV8(v8::Isolate* isolate, const std::vector<T>& val) {
207 v8::Local<v8::Context> context = isolate->GetCurrentContext();
deepak.sfaaa1b62015-04-30 07:30:48208 v8::Local<v8::Array> result(
jochen@chromium.org91cd4fe2013-11-28 09:31:58209 v8::Array::New(isolate, static_cast<int>(val.size())));
bashidbd2ef9bb2015-06-02 01:39:32210 for (uint32_t i = 0; i < val.size(); ++i) {
Jeremy Romaneb8a2f172018-01-29 17:33:40211 v8::MaybeLocal<v8::Value> maybe = Converter<T>::ToV8(isolate, val[i]);
212 v8::Local<v8::Value> element;
213 if (!maybe.ToLocal(&element))
214 return {};
215 bool property_created;
216 if (!result->CreateDataProperty(context, i, element)
217 .To(&property_created) ||
218 !property_created) {
219 NOTREACHED() << "CreateDataProperty should always succeed here.";
220 }
abarth@chromium.orga22998a2013-11-10 05:00:50221 }
222 return result;
223 }
224
aa@chromium.org7618ebbb2013-11-27 03:38:26225 static bool FromV8(v8::Isolate* isolate,
deepak.sfaaa1b62015-04-30 07:30:48226 v8::Local<v8::Value> val,
abarth@chromium.orga22998a2013-11-10 05:00:50227 std::vector<T>* out) {
228 if (!val->IsArray())
229 return false;
230
231 std::vector<T> result;
deepak.sfaaa1b62015-04-30 07:30:48232 v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
abarth@chromium.orga22998a2013-11-10 05:00:50233 uint32_t length = array->Length();
234 for (uint32_t i = 0; i < length; ++i) {
bashidbd2ef9bb2015-06-02 01:39:32235 v8::Local<v8::Value> v8_item;
236 if (!array->Get(isolate->GetCurrentContext(), i).ToLocal(&v8_item))
237 return false;
abarth@chromium.orga22998a2013-11-10 05:00:50238 T item;
bashidbd2ef9bb2015-06-02 01:39:32239 if (!Converter<T>::FromV8(isolate, v8_item, &item))
abarth@chromium.orga22998a2013-11-10 05:00:50240 return false;
241 result.push_back(item);
242 }
243
244 out->swap(result);
245 return true;
246 }
247};
248
bashidbd2ef9bb2015-06-02 01:39:32249template<typename T>
250struct ToV8ReturnsMaybe<std::vector<T>> {
Jeremy Romaneb8a2f172018-01-29 17:33:40251 static const bool value = ToV8ReturnsMaybe<T>::value;
bashidbd2ef9bb2015-06-02 01:39:32252};
253
abarth@chromium.orga22998a2013-11-10 05:00:50254// Convenience functions that deduce T.
Jeremy Romaneb8a2f172018-01-29 17:33:40255template <typename T>
256std::conditional_t<ToV8ReturnsMaybe<T>::value,
257 v8::MaybeLocal<v8::Value>,
258 v8::Local<v8::Value>>
Jeremy Apthorp6a3480292018-04-26 18:53:59259ConvertToV8(v8::Isolate* isolate, const T& input) {
abarth@chromium.orga22998a2013-11-10 05:00:50260 return Converter<T>::ToV8(isolate, input);
261}
262
Jeremy Roman44bda444b2018-03-16 17:33:45263template <typename T>
Jeremy Apthorp6a3480292018-04-26 18:53:59264std::enable_if_t<ToV8ReturnsMaybe<T>::value, bool> TryConvertToV8(
265 v8::Isolate* isolate,
266 const T& input,
267 v8::Local<v8::Value>* output) {
Jeremy Roman44bda444b2018-03-16 17:33:45268 return ConvertToV8(isolate, input).ToLocal(output);
269}
bashidbd2ef9bb2015-06-02 01:39:32270
271template <typename T>
Jeremy Apthorp6a3480292018-04-26 18:53:59272std::enable_if_t<!ToV8ReturnsMaybe<T>::value, bool> TryConvertToV8(
273 v8::Isolate* isolate,
274 const T& input,
275 v8::Local<v8::Value>* output) {
Jeremy Roman44bda444b2018-03-16 17:33:45276 *output = ConvertToV8(isolate, input);
277 return true;
bashidbd2ef9bb2015-06-02 01:39:32278}
279
280// This crashes when input.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48281GIN_EXPORT inline v8::Local<v8::String> StringToV8(
jochen@chromium.org48c21632013-12-12 21:32:34282 v8::Isolate* isolate,
283 const base::StringPiece& input) {
abarth@chromium.orga22998a2013-11-10 05:00:50284 return ConvertToV8(isolate, input).As<v8::String>();
285}
286
bashidbd2ef9bb2015-06-02 01:39:32287// This crashes when input.size() > v8::String::kMaxLength.
deepak.sfaaa1b62015-04-30 07:30:48288GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
jochen@chromium.org48c21632013-12-12 21:32:34289 const base::StringPiece& val);
abarth@chromium.orge87f3122013-11-12 00:41:27290
Shimi Zhang15708bfc2019-08-13 19:24:48291// This crashes when input.size() > v8::String::kMaxLength.
292GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
293 const base::StringPiece16& val);
294
abarth@chromium.orga22998a2013-11-10 05:00:50295template<typename T>
deepak.sfaaa1b62015-04-30 07:30:48296bool ConvertFromV8(v8::Isolate* isolate, v8::Local<v8::Value> input,
aa@chromium.org7618ebbb2013-11-27 03:38:26297 T* result) {
Dan Elphick712beaa2018-07-24 17:37:24298 DCHECK(isolate);
aa@chromium.org7618ebbb2013-11-27 03:38:26299 return Converter<T>::FromV8(isolate, input, result);
abarth@chromium.orga22998a2013-11-10 05:00:50300}
301
Dan Elphick38a508052018-07-23 22:19:53302GIN_EXPORT std::string V8ToString(v8::Isolate* isolate,
303 v8::Local<v8::Value> value);
abarth@chromium.org2f703422013-11-25 21:26:15304
abarth@chromium.orga22998a2013-11-10 05:00:50305} // namespace gin
306
307#endif // GIN_CONVERTER_H_