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