1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifndef GIN_OBJECT_TEMPLATE_BUILDER_H_ 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define GIN_OBJECT_TEMPLATE_BUILDER_H_ 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/callback.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_piece.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/template_util.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "gin/converter.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "gin/function_template.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/gin_export.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "v8/include/v8.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace gin { 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Base template - used only for non-member function pointers. Other types 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// either go to one of the below specializations, or go here and fail to compile 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// because of base::Bind(). 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template<typename T, typename Enable = void> 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct CallbackTraits { 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) T callback) { 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CreateFunctionTemplate(isolate, base::Bind(callback)); 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void SetAsFunctionHandler(v8::Isolate* isolate, 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) v8::Local<v8::ObjectTemplate> tmpl, 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) T callback) { 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateFunctionHandler(isolate, tmpl, base::Bind(callback)); 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Specialization for base::Callback. 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template<typename T> 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct CallbackTraits<base::Callback<T> > { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static v8::Handle<v8::FunctionTemplate> CreateTemplate( 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Isolate* isolate, const base::Callback<T>& callback) { 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CreateFunctionTemplate(isolate, callback); 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void SetAsFunctionHandler(v8::Isolate* isolate, 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) v8::Local<v8::ObjectTemplate> tmpl, 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Callback<T>& callback) { 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateFunctionHandler(isolate, tmpl, callback); 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Specialization for member function pointers. We need to handle this case 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// specially because the first parameter for callbacks to MFP should typically 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// come from the the JavaScript "this" object the function was called on, not 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// from the first normal parameter. 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template<typename T> 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct CallbackTraits<T, typename base::enable_if< 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::is_member_function_pointer<T>::value>::type> { 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) T callback) { 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CreateFunctionTemplate(isolate, base::Bind(callback), 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HolderIsFirstArgument); 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void SetAsFunctionHandler(v8::Isolate* isolate, 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) v8::Local<v8::ObjectTemplate> tmpl, 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) T callback) { 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateFunctionHandler( 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) isolate, tmpl, base::Bind(callback), HolderIsFirstArgument); 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This specialization allows people to construct function templates directly if 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// they need to do fancier stuff. 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template<> 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct GIN_EXPORT CallbackTraits<v8::Handle<v8::FunctionTemplate> > { 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static v8::Handle<v8::FunctionTemplate> CreateTemplate( 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Handle<v8::FunctionTemplate> templ) { 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return templ; 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// ObjectTemplateBuilder provides a handy interface to creating 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// v8::ObjectTemplate instances with various sorts of properties. 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GIN_EXPORT ObjectTemplateBuilder { 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) explicit ObjectTemplateBuilder(v8::Isolate* isolate); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ~ObjectTemplateBuilder(); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // It's against Google C++ style to return a non-const ref, but we take some 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // poetic license here in order that all calls to Set() can be via the '.' 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // operator and line up nicely. 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) template<typename T> 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) { 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return SetImpl(name, ConvertToV8(isolate_, val)); 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // In the following methods, T and U can be function pointer, member function 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // use one of the first two options. Also see gin::CreateFunctionTemplate() 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // for creating raw function templates. 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) template<typename T> 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const T& callback) { 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback)); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) template<typename T> 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const T& getter) { 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return SetPropertyImpl(name, 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CallbackTraits<T>::CreateTemplate(isolate_, getter), 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Local<v8::FunctionTemplate>()); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) template<typename T, typename U> 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const T& getter, const U& setter) { 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return SetPropertyImpl(name, 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CallbackTraits<T>::CreateTemplate(isolate_, getter), 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CallbackTraits<U>::CreateTemplate(isolate_, setter)); 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) template<typename T> 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CallbackTraits<T>::SetAsFunctionHandler(isolate_, template_, callback); 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return *this; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ObjectTemplateBuilder& AddNamedPropertyInterceptor(); 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ObjectTemplateBuilder& AddIndexedPropertyInterceptor(); 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Local<v8::ObjectTemplate> Build(); 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Handle<v8::Data> val); 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObjectTemplateBuilder& SetPropertyImpl( 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter, 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Handle<v8::FunctionTemplate> setter); 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Isolate* isolate_; 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // ObjectTemplateBuilder should only be used on the stack. 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Local<v8::ObjectTemplate> template_; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace gin 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif // GIN_OBJECT_TEMPLATE_BUILDER_H_ 148