converter.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // 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. #ifndef GIN_CONVERTER_H_
  5. #define GIN_CONVERTER_H_
  6. #include <stdint.h>
  7. #include <ostream>
  8. #include <string>
  9. #include <type_traits>
  10. #include <vector>
  11. #include "base/check.h"
  12. #include "base/notreached.h"
  13. #include "base/strings/string_piece.h"
  14. #include "gin/gin_export.h"
  15. #include "v8/include/v8-container.h"
  16. #include "v8/include/v8-forward.h"
  17. #include "v8/include/v8-isolate.h"
  18. namespace base {
  19. class TimeTicks;
  20. }
  21. namespace gin {
  22. template<typename KeyType>
  23. bool SetProperty(v8::Isolate* isolate,
  24. v8::Local<v8::Object> object,
  25. KeyType key,
  26. v8::Local<v8::Value> value) {
  27. auto maybe =
  28. object->DefineOwnProperty(isolate->GetCurrentContext(), key, value);
  29. return !maybe.IsNothing() && maybe.FromJust();
  30. }
  31. template <typename T, typename Enable = void>
  32. struct ToV8ReturnsMaybe {
  33. static const bool value = false;
  34. };
  35. template<typename T, typename Enable = void>
  36. struct Converter {};
  37. template<>
  38. struct GIN_EXPORT Converter<bool> {
  39. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  40. bool val);
  41. static bool FromV8(v8::Isolate* isolate,
  42. v8::Local<v8::Value> val,
  43. bool* out);
  44. };
  45. template<>
  46. struct GIN_EXPORT Converter<int32_t> {
  47. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  48. int32_t val);
  49. static bool FromV8(v8::Isolate* isolate,
  50. v8::Local<v8::Value> val,
  51. int32_t* out);
  52. };
  53. template<>
  54. struct GIN_EXPORT Converter<uint32_t> {
  55. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  56. uint32_t val);
  57. static bool FromV8(v8::Isolate* isolate,
  58. v8::Local<v8::Value> val,
  59. uint32_t* out);
  60. };
  61. template<>
  62. struct GIN_EXPORT Converter<int64_t> {
  63. // Warning: JavaScript cannot represent 64 integers precisely.
  64. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  65. int64_t val);
  66. static bool FromV8(v8::Isolate* isolate,
  67. v8::Local<v8::Value> val,
  68. int64_t* out);
  69. };
  70. template<>
  71. struct GIN_EXPORT Converter<uint64_t> {
  72. // Warning: JavaScript cannot represent 64 integers precisely.
  73. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  74. uint64_t val);
  75. static bool FromV8(v8::Isolate* isolate,
  76. v8::Local<v8::Value> val,
  77. uint64_t* out);
  78. };
  79. template<>
  80. struct GIN_EXPORT Converter<float> {
  81. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  82. float val);
  83. static bool FromV8(v8::Isolate* isolate,
  84. v8::Local<v8::Value> val,
  85. float* out);
  86. };
  87. template<>
  88. struct GIN_EXPORT Converter<double> {
  89. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  90. double val);
  91. static bool FromV8(v8::Isolate* isolate,
  92. v8::Local<v8::Value> val,
  93. double* out);
  94. };
  95. template<>
  96. struct GIN_EXPORT Converter<base::StringPiece> {
  97. // This crashes when val.size() > v8::String::kMaxLength.
  98. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  99. const base::StringPiece& val);
  100. // No conversion out is possible because StringPiece does not contain storage.
  101. };
  102. template<>
  103. struct GIN_EXPORT Converter<std::string> {
  104. // This crashes when val.size() > v8::String::kMaxLength.
  105. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  106. const std::string& val);
  107. static bool FromV8(v8::Isolate* isolate,
  108. v8::Local<v8::Value> val,
  109. std::string* out);
  110. };
  111. template <>
  112. struct GIN_EXPORT Converter<std::u16string> {
  113. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  114. const std::u16string& val);
  115. static bool FromV8(v8::Isolate* isolate,
  116. v8::Local<v8::Value> val,
  117. std::u16string* out);
  118. };
  119. // Converter for C++ TimeTicks to Javascript BigInt (unit: microseconds).
  120. // TimeTicks can't be converted using the existing Converter<int64_t> because
  121. // the target type will be Number and will lose precision.
  122. template <>
  123. struct GIN_EXPORT Converter<base::TimeTicks> {
  124. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, base::TimeTicks val);
  125. };
  126. template <>
  127. struct GIN_EXPORT Converter<v8::Local<v8::Function>> {
  128. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  129. v8::Local<v8::Function> val);
  130. static bool FromV8(v8::Isolate* isolate,
  131. v8::Local<v8::Value> val,
  132. v8::Local<v8::Function>* out);
  133. };
  134. template<>
  135. struct GIN_EXPORT Converter<v8::Local<v8::Object> > {
  136. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  137. v8::Local<v8::Object> val);
  138. static bool FromV8(v8::Isolate* isolate,
  139. v8::Local<v8::Value> val,
  140. v8::Local<v8::Object>* out);
  141. };
  142. template <>
  143. struct GIN_EXPORT Converter<v8::Local<v8::Promise>> {
  144. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  145. v8::Local<v8::Promise> val);
  146. static bool FromV8(v8::Isolate* isolate,
  147. v8::Local<v8::Value> val,
  148. v8::Local<v8::Promise>* out);
  149. };
  150. template<>
  151. struct GIN_EXPORT Converter<v8::Local<v8::ArrayBuffer> > {
  152. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  153. v8::Local<v8::ArrayBuffer> val);
  154. static bool FromV8(v8::Isolate* isolate,
  155. v8::Local<v8::Value> val,
  156. v8::Local<v8::ArrayBuffer>* out);
  157. };
  158. template<>
  159. struct GIN_EXPORT Converter<v8::Local<v8::External> > {
  160. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  161. v8::Local<v8::External> val);
  162. static bool FromV8(v8::Isolate* isolate,
  163. v8::Local<v8::Value> val,
  164. v8::Local<v8::External>* out);
  165. };
  166. template<>
  167. struct GIN_EXPORT Converter<v8::Local<v8::Value> > {
  168. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  169. v8::Local<v8::Value> val);
  170. static bool FromV8(v8::Isolate* isolate,
  171. v8::Local<v8::Value> val,
  172. v8::Local<v8::Value>* out);
  173. };
  174. template<typename T>
  175. struct Converter<std::vector<T> > {
  176. static std::conditional_t<ToV8ReturnsMaybe<T>::value,
  177. v8::MaybeLocal<v8::Value>,
  178. v8::Local<v8::Value>>
  179. ToV8(v8::Isolate* isolate, const std::vector<T>& val) {
  180. v8::Local<v8::Context> context = isolate->GetCurrentContext();
  181. v8::Local<v8::Array> result(
  182. v8::Array::New(isolate, static_cast<int>(val.size())));
  183. for (uint32_t i = 0; i < val.size(); ++i) {
  184. v8::MaybeLocal<v8::Value> maybe = Converter<T>::ToV8(isolate, val[i]);
  185. v8::Local<v8::Value> element;
  186. if (!maybe.ToLocal(&element))
  187. return {};
  188. bool property_created;
  189. if (!result->CreateDataProperty(context, i, element)
  190. .To(&property_created) ||
  191. !property_created) {
  192. NOTREACHED() << "CreateDataProperty should always succeed here.";
  193. }
  194. }
  195. return result;
  196. }
  197. static bool FromV8(v8::Isolate* isolate,
  198. v8::Local<v8::Value> val,
  199. std::vector<T>* out) {
  200. if (!val->IsArray())
  201. return false;
  202. std::vector<T> result;
  203. v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
  204. uint32_t length = array->Length();
  205. for (uint32_t i = 0; i < length; ++i) {
  206. v8::Local<v8::Value> v8_item;
  207. if (!array->Get(isolate->GetCurrentContext(), i).ToLocal(&v8_item))
  208. return false;
  209. T item;
  210. if (!Converter<T>::FromV8(isolate, v8_item, &item))
  211. return false;
  212. result.push_back(item);
  213. }
  214. out->swap(result);
  215. return true;
  216. }
  217. };
  218. template<typename T>
  219. struct ToV8ReturnsMaybe<std::vector<T>> {
  220. static const bool value = ToV8ReturnsMaybe<T>::value;
  221. };
  222. // Convenience functions that deduce T.
  223. template <typename T>
  224. std::conditional_t<ToV8ReturnsMaybe<T>::value,
  225. v8::MaybeLocal<v8::Value>,
  226. v8::Local<v8::Value>>
  227. ConvertToV8(v8::Isolate* isolate, const T& input) {
  228. return Converter<T>::ToV8(isolate, input);
  229. }
  230. template <typename T>
  231. std::enable_if_t<ToV8ReturnsMaybe<T>::value, bool> TryConvertToV8(
  232. v8::Isolate* isolate,
  233. const T& input,
  234. v8::Local<v8::Value>* output) {
  235. return ConvertToV8(isolate, input).ToLocal(output);
  236. }
  237. template <typename T>
  238. std::enable_if_t<!ToV8ReturnsMaybe<T>::value, bool> TryConvertToV8(
  239. v8::Isolate* isolate,
  240. const T& input,
  241. v8::Local<v8::Value>* output) {
  242. *output = ConvertToV8(isolate, input);
  243. return true;
  244. }
  245. // This crashes when input.size() > v8::String::kMaxLength.
  246. GIN_EXPORT inline v8::Local<v8::String> StringToV8(
  247. v8::Isolate* isolate,
  248. const base::StringPiece& input) {
  249. return ConvertToV8(isolate, input).As<v8::String>();
  250. }
  251. // This crashes when input.size() > v8::String::kMaxLength.
  252. GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
  253. const base::StringPiece& val);
  254. // This crashes when input.size() > v8::String::kMaxLength.
  255. GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
  256. const base::StringPiece16& val);
  257. template<typename T>
  258. bool ConvertFromV8(v8::Isolate* isolate, v8::Local<v8::Value> input,
  259. T* result) {
  260. DCHECK(isolate);
  261. return Converter<T>::FromV8(isolate, input, result);
  262. }
  263. GIN_EXPORT std::string V8ToString(v8::Isolate* isolate,
  264. v8::Local<v8::Value> value);
  265. } // namespace gin
  266. #endif // GIN_CONVERTER_H_