// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. #ifndef NATIVE_MATE_CONVERTER_H_ #define NATIVE_MATE_CONVERTER_H_ #include #include #include #include #include "base/strings/string_piece.h" #include "native_mate/compat.h" #include "v8/include/v8.h" namespace mate { template bool SetProperty(v8::Isolate* isolate, v8::Local object, KeyType key, v8::Local value) { auto maybe = object->Set(isolate->GetCurrentContext(), key, value); return !maybe.IsNothing() && maybe.FromJust(); } template struct ToV8ReturnsMaybe { static const bool value = false; }; template struct Converter {}; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, void* val) { return MATE_UNDEFINED(isolate); } }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, bool val); static bool FromV8(v8::Isolate* isolate, v8::Local val, bool* out); }; #if !defined(OS_LINUX) template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, unsigned long val); static bool FromV8(v8::Isolate* isolate, v8::Local val, unsigned long* out); }; #endif template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, int32_t val); static bool FromV8(v8::Isolate* isolate, v8::Local val, int32_t* out); }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, uint32_t val); static bool FromV8(v8::Isolate* isolate, v8::Local val, uint32_t* out); }; template<> struct Converter { // Warning: JavaScript cannot represent 64 integers precisely. static v8::Local ToV8(v8::Isolate* isolate, int64_t val); static bool FromV8(v8::Isolate* isolate, v8::Local val, int64_t* out); }; template<> struct Converter { // Warning: JavaScript cannot represent 64 integers precisely. static v8::Local ToV8(v8::Isolate* isolate, uint64_t val); static bool FromV8(v8::Isolate* isolate, v8::Local val, uint64_t* out); }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, float val); static bool FromV8(v8::Isolate* isolate, v8::Local val, float* out); }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, double val); static bool FromV8(v8::Isolate* isolate, v8::Local val, double* out); }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, const char* val); }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, const base::StringPiece& val); // No conversion out is possible because StringPiece does not contain storage. }; template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, const std::string& val); static bool FromV8(v8::Isolate* isolate, v8::Local val, std::string* out); }; v8::Local StringToSymbol(v8::Isolate* isolate, const base::StringPiece& input); std::string V8ToString(v8::Local value); template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template<> struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, v8::Local val); static bool FromV8(v8::Isolate* isolate, v8::Local val, v8::Local* out); }; template struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, const std::vector& val) { v8::Local result( MATE_ARRAY_NEW(isolate, static_cast(val.size()))); for (size_t i = 0; i < val.size(); ++i) { result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); } return result; } static bool FromV8(v8::Isolate* isolate, v8::Local val, std::vector* out) { if (!val->IsArray()) return false; std::vector result; v8::Local array(v8::Local::Cast(val)); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { T item; if (!Converter::FromV8(isolate, array->Get(i), &item)) return false; result.push_back(item); } out->swap(result); return true; } }; template struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, const std::set& val) { v8::Local result( MATE_ARRAY_NEW(isolate, static_cast(val.size()))); typename std::set::const_iterator it; int i; for (i = 0, it = val.begin(); it != val.end(); ++it, ++i) result->Set(i, Converter::ToV8(isolate, *it)); return result; } static bool FromV8(v8::Isolate* isolate, v8::Local val, std::set* out) { if (!val->IsArray()) return false; std::set result; v8::Local array(v8::Local::Cast(val)); uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { T item; if (!Converter::FromV8(isolate, array->Get(i), &item)) return false; result.insert(item); } out->swap(result); return true; } }; template struct Converter > { static bool FromV8(v8::Isolate* isolate, v8::Local val, std::map * out) { if (!val->IsObject()) return false; v8::Local dict = val->ToObject(); v8::Local keys = dict->GetOwnPropertyNames(); for (uint32_t i = 0; i < keys->Length(); ++i) { v8::Local key = keys->Get(i); T value; if (Converter::FromV8(isolate, dict->Get(key), &value)) (*out)[V8ToString(key)] = std::move(value); } return true; } static v8::Local ToV8(v8::Isolate* isolate, const std::map& val) { v8::Local result = v8::Object::New(isolate); for (auto i = val.begin(); i != val.end(); i++) { result->Set(Converter::ToV8(isolate, i->first), Converter::ToV8(isolate, i->second)); } return result; } }; // Convenience functions that deduce T. template v8::Local ConvertToV8(v8::Isolate* isolate, const T& input) { return Converter::ToV8(isolate, input); } inline v8::Local ConvertToV8(v8::Isolate* isolate, const char* input) { return Converter::ToV8(isolate, input); } template v8::MaybeLocal ConvertToV8(v8::Local context, const T& input) { return Converter::ToV8(context, input); } template::value> struct ToV8Traits; template struct ToV8Traits { static bool TryConvertToV8(v8::Isolate* isolate, const T& input, v8::Local* output) { auto maybe = ConvertToV8(isolate->GetCurrentContext(), input); if (maybe.IsEmpty()) return false; *output = maybe.ToLocalChecked(); return true; } }; template struct ToV8Traits { static bool TryConvertToV8(v8::Isolate* isolate, const T& input, v8::Local* output) { *output = ConvertToV8(isolate, input); return true; } }; template bool TryConvertToV8(v8::Isolate* isolate, T input, v8::Local* output) { return ToV8Traits::TryConvertToV8(isolate, input, output); } template bool ConvertFromV8(v8::Isolate* isolate, v8::Local input, T* result) { return Converter::FromV8(isolate, input, result); } inline v8::Local StringToV8( v8::Isolate* isolate, const base::StringPiece& input) { return ConvertToV8(isolate, input).As(); } } // namespace mate #endif // NATIVE_MATE_CONVERTER_H_