1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef GIN_OBJECT_TEMPLATE_BUILDER_H_
6 #define GIN_OBJECT_TEMPLATE_BUILDER_H_
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/strings/string_piece.h"
15 #include "gin/converter.h"
16 #include "gin/function_template.h"
17 #include "gin/gin_export.h"
18 #include "v8/include/v8-forward.h"
25 v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(v8::Isolate* isolate,
27 const char* type_name) {
28 // We need to handle member function pointers case specially because the first
29 // parameter for callbacks to MFP should typically come from the the
30 // JavaScript "this" object the function was called on, not from the first
32 InvokerOptions options;
33 if (std::is_member_function_pointer<T>::value) {
34 options.holder_is_first_argument = true;
35 options.holder_type = type_name;
37 return ::gin::CreateFunctionTemplate(
38 isolate, base::BindRepeating(std::move(callback)), std::move(options));
41 } // namespace internal
43 // ObjectTemplateBuilder provides a handy interface to creating
44 // v8::ObjectTemplate instances with various sorts of properties.
45 class GIN_EXPORT ObjectTemplateBuilder {
47 explicit ObjectTemplateBuilder(v8::Isolate* isolate);
48 ObjectTemplateBuilder(v8::Isolate* isolate, const char* type_name);
49 #if defined(ENABLE_WRT_JS)
50 ObjectTemplateBuilder(v8::Isolate* isolate,
51 const char* type_name,
52 v8::Local<v8::ObjectTemplate> tmpl);
54 ObjectTemplateBuilder(const ObjectTemplateBuilder& other);
55 ~ObjectTemplateBuilder();
57 // It's against Google C++ style to return a non-const ref, but we take some
58 // poetic license here in order that all calls to Set() can be via the '.'
59 // operator and line up nicely.
61 ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) {
62 return SetImpl(name, ConvertToV8(isolate_, val));
65 // In the following methods, T and U can be function pointer, member function
66 // pointer, base::RepeatingCallback, or v8::FunctionTemplate. Most clients
67 // will want to use one of the first two options. Also see
68 // gin::CreateFunctionTemplate() for creating raw function templates.
70 ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
73 name, internal::CreateFunctionTemplate(isolate_, callback, type_name_));
77 ObjectTemplateBuilder& SetMethod(v8::Local<v8::Name> name,
80 name, internal::CreateFunctionTemplate(isolate_, callback, type_name_));
84 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
86 return SetPropertyImpl(
87 name, internal::CreateFunctionTemplate(isolate_, getter, type_name_),
88 v8::Local<v8::FunctionTemplate>());
90 template<typename T, typename U>
91 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
92 const T& getter, const U& setter) {
93 return SetPropertyImpl(
94 name, internal::CreateFunctionTemplate(isolate_, getter, type_name_),
95 internal::CreateFunctionTemplate(isolate_, setter, type_name_));
98 // Whereas SetProperty creates an accessor property, this creates what appears
99 // to be a data property but whose value is lazily computed the first time the
100 // [[Get]] operation occurs.
101 template <typename T>
102 ObjectTemplateBuilder& SetLazyDataProperty(const base::StringPiece& name,
104 InvokerOptions options;
105 if (std::is_member_function_pointer<T>::value) {
106 options.holder_is_first_argument = true;
107 options.holder_type = type_name_;
109 auto [callback, data] = CreateDataPropertyCallback(
110 isolate_, base::BindRepeating(getter), std::move(options));
111 return SetLazyDataPropertyImpl(name, callback, data);
114 ObjectTemplateBuilder& AddNamedPropertyInterceptor();
115 ObjectTemplateBuilder& AddIndexedPropertyInterceptor();
117 v8::Local<v8::ObjectTemplate> Build();
120 ObjectTemplateBuilder& SetImpl(const base::StringPiece& name,
121 v8::Local<v8::Data> val);
122 ObjectTemplateBuilder& SetImpl(v8::Local<v8::Name> name,
123 v8::Local<v8::Data> val);
124 ObjectTemplateBuilder& SetPropertyImpl(
125 const base::StringPiece& name, v8::Local<v8::FunctionTemplate> getter,
126 v8::Local<v8::FunctionTemplate> setter);
127 ObjectTemplateBuilder& SetLazyDataPropertyImpl(
128 const base::StringPiece& name,
129 v8::AccessorNameGetterCallback callback,
130 v8::Local<v8::Value> data);
132 raw_ptr<v8::Isolate> isolate_;
134 // If provided, |type_name_| will be used to give a user-friendly error
135 // message if a member function is invoked on the wrong type of object.
136 const char* type_name_ = nullptr;
138 // ObjectTemplateBuilder should only be used on the stack.
139 v8::Local<v8::FunctionTemplate> constructor_template_;
140 v8::Local<v8::ObjectTemplate> template_;
145 #endif // GIN_OBJECT_TEMPLATE_BUILDER_H_