// Copyright (c) 2013 GitHub, Inc. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMMON_V8_CONVERSIONS_H_ #define COMMON_V8_CONVERSIONS_H_ #include #include #include #include "base/files/file_path.h" #include "base/string16.h" #include "browser/api/atom_api_window.h" #include "ui/gfx/rect.h" #include "v8/include/v8.h" // Convert V8 value to arbitrary supported types. struct FromV8Value { explicit FromV8Value(v8::Handle value) : value_(value) {} operator int() { return value_->IntegerValue(); } operator bool() { return value_->BooleanValue(); } operator std::string() { return *v8::String::Utf8Value(value_); } operator string16() { v8::String::Value s(value_); return string16(reinterpret_cast(*s), s.length()); } operator base::FilePath() { return base::FilePath::FromUTF8Unsafe(FromV8Value(value_)); } operator gfx::Rect() { v8::Handle rect = value_->ToObject(); v8::Handle x = rect->Get(v8::String::New("x")); v8::Handle y = rect->Get(v8::String::New("y")); v8::Handle width = rect->Get(v8::String::New("width")); v8::Handle height = rect->Get(v8::String::New("height")); if (!x->IsNumber() || !y->IsNumber() || !width->IsNumber() || !height->IsNumber()) return gfx::Rect(); else return gfx::Rect(x->IntegerValue(), y->IntegerValue(), width->IntegerValue(), height->IntegerValue()); } operator std::vector() { std::vector array; v8::Handle v8_array = v8::Handle::Cast(value_); for (uint32_t i = 0; i < v8_array->Length(); ++i) array.push_back(FromV8Value(v8_array->Get(i))); return array; } operator std::map() { std::map dict; v8::Handle v8_dict = value_->ToObject(); v8::Handle v8_keys = v8_dict->GetOwnPropertyNames(); for (uint32_t i = 0; i < v8_keys->Length(); ++i) { v8::Handle v8_key = v8_keys->Get(i); std::string key = FromV8Value(v8_key); dict[key] = std::string(FromV8Value(v8_dict->Get(v8_key))); } return dict; } operator atom::NativeWindow*() { using atom::api::Window; if (value_->IsObject()) { Window* window = Window::Unwrap(value_->ToObject()); if (window && window->window()) return window->window(); } return NULL; } operator v8::Persistent() { return v8::Persistent::New( node::node_isolate, v8::Handle::Cast(value_)); } v8::Handle value_; }; // Convert arbitrary supported native type to V8 value. inline v8::Handle ToV8Value(int i) { return v8::Integer::New(i); } inline v8::Handle ToV8Value(bool b) { return v8::Boolean::New(b); } inline v8::Handle ToV8Value(const char* s) { return v8::String::New(s); } inline v8::Handle ToV8Value(const std::string& s) { return v8::String::New(s.data(), s.size()); } inline v8::Handle ToV8Value(const string16& s) { return v8::String::New(reinterpret_cast(s.data()), s.size()); } inline v8::Handle ToV8Value(const base::FilePath& path) { std::string path_string(path.AsUTF8Unsafe()); return v8::String::New(path_string.data(), path_string.size()); } inline v8::Handle ToV8Value(void* whatever) { return v8::Undefined(); } inline v8::Handle ToV8Value(const std::vector& paths) { v8::Handle result = v8::Array::New(paths.size()); for (size_t i = 0; i < paths.size(); ++i) result->Set(i, ToV8Value(paths[i])); return result; } // Check if a V8 Value is of specified type. template inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return false; } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return value->IsNumber(); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return value->IsBoolean(); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return value->IsString(); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return V8ValueCanBeConvertedTo(value); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return V8ValueCanBeConvertedTo(value); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { return value->IsObject(); } template<> inline bool V8ValueCanBeConvertedTo>( v8::Handle value) { return value->IsArray(); } template<> inline bool V8ValueCanBeConvertedTo>( v8::Handle value) { return value->IsObject(); } template<> inline bool V8ValueCanBeConvertedTo(v8::Handle value) { using atom::api::Window; if (value->IsObject()) { Window* window = Window::Unwrap(value->ToObject()); if (window && window->window()) return true; } return false; } template<> inline bool V8ValueCanBeConvertedTo>( v8::Handle value) { return value->IsFunction(); } // Check and convert V8's Arguments to native types. template inline bool FromV8Arguments(const v8::Arguments& args, T1* value, int index = 0) { if (!V8ValueCanBeConvertedTo(args[index])) return false; *value = static_cast(FromV8Value(args[index])); return true; } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2) { return FromV8Arguments(args, a1) && FromV8Arguments(args, a2, 1); } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2, T3* a3) { return FromV8Arguments(args, a1, a2) && FromV8Arguments(args, a3, 2); } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2, T3* a3, T4* a4) { return FromV8Arguments(args, a1, a2, a3) && FromV8Arguments(args, a4, 3); } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2, T3* a3, T4* a4, T5* a5) { return FromV8Arguments(args, a1, a2, a3, a4) && FromV8Arguments(args, a5, 4); } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2, T3* a3, T4* a4, T5* a5, T6* a6) { return FromV8Arguments(args, a1, a2, a3, a4, a5) && FromV8Arguments(args, a6, 5); } template inline bool FromV8Arguments(const v8::Arguments& args, T1* a1, T2* a2, T3* a3, T4* a4, T5* a5, T6* a6, T7* a7) { return FromV8Arguments(args, a1, a2, a3, a4, a5, a6) && FromV8Arguments(args, a7, 6); } #endif // COMMON_V8_CONVERSIONS_H_