blob: edbf0b66f8b15ee56ddb7277c3a7867af423c4ee [file] [log] [blame]
[email protected]b520e132013-11-29 03:21:481// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef GIN_OBJECT_TEMPLATE_BUILDER_H_
6#define GIN_OBJECT_TEMPLATE_BUILDER_H_
7
Jeremy Roman6a1242b2019-02-04 17:51:578#include <tuple>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
Jeremy Roman6a1242b2019-02-04 17:51:5710#include <utility>
vmpstr98a2fad2015-11-30 20:15:1711
[email protected]b520e132013-11-29 03:21:4812#include "base/bind.h"
[email protected]bf3dd3c2013-12-06 06:55:2513#include "base/callback.h"
[email protected]b520e132013-11-29 03:21:4814#include "base/strings/string_piece.h"
15#include "gin/converter.h"
16#include "gin/function_template.h"
[email protected]48c21632013-12-12 21:32:3417#include "gin/gin_export.h"
[email protected]b520e132013-11-29 03:21:4818#include "v8/include/v8.h"
19
20namespace gin {
21
Devlin Cronine9db9842018-04-09 17:51:0522namespace internal {
23
vmpstr98a2fad2015-11-30 20:15:1724template <typename T>
tzikc21a0dc2017-11-14 08:23:4425v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(v8::Isolate* isolate,
Devlin Cronine9db9842018-04-09 17:51:0526 T callback,
27 const char* type_name) {
tzikc21a0dc2017-11-14 08:23:4428 // 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
31 // normal parameter.
Devlin Cronine9db9842018-04-09 17:51:0532 InvokerOptions options;
33 if (std::is_member_function_pointer<T>::value) {
34 options.holder_is_first_argument = true;
35 options.holder_type = type_name;
36 }
37 return ::gin::CreateFunctionTemplate(
38 isolate, base::BindRepeating(std::move(callback)), std::move(options));
tzikc21a0dc2017-11-14 08:23:4439}
[email protected]bf3dd3c2013-12-06 06:55:2540
Devlin Cronine9db9842018-04-09 17:51:0541} // namespace internal
42
[email protected]b520e132013-11-29 03:21:4843// ObjectTemplateBuilder provides a handy interface to creating
44// v8::ObjectTemplate instances with various sorts of properties.
[email protected]48c21632013-12-12 21:32:3445class GIN_EXPORT ObjectTemplateBuilder {
[email protected]b520e132013-11-29 03:21:4846 public:
47 explicit ObjectTemplateBuilder(v8::Isolate* isolate);
Devlin Cronine9db9842018-04-09 17:51:0548 ObjectTemplateBuilder(v8::Isolate* isolate, const char* type_name);
Jeremy Apthorpe06e7142020-03-25 20:22:3649 ObjectTemplateBuilder(v8::Isolate* isolate,
50 const char* type_name,
51 v8::Local<v8::ObjectTemplate> tmpl);
vmpstr8ed6f862016-02-25 20:25:1452 ObjectTemplateBuilder(const ObjectTemplateBuilder& other);
[email protected]b520e132013-11-29 03:21:4853 ~ObjectTemplateBuilder();
54
55 // It's against Google C++ style to return a non-const ref, but we take some
56 // poetic license here in order that all calls to Set() can be via the '.'
57 // operator and line up nicely.
58 template<typename T>
59 ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) {
60 return SetImpl(name, ConvertToV8(isolate_, val));
61 }
62
[email protected]bf3dd3c2013-12-06 06:55:2563 // In the following methods, T and U can be function pointer, member function
64 // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to
65 // use one of the first two options. Also see gin::CreateFunctionTemplate()
66 // for creating raw function templates.
[email protected]b520e132013-11-29 03:21:4867 template<typename T>
68 ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
[email protected]bf3dd3c2013-12-06 06:55:2569 const T& callback) {
Devlin Cronine9db9842018-04-09 17:51:0570 return SetImpl(
71 name, internal::CreateFunctionTemplate(isolate_, callback, type_name_));
[email protected]bf3dd3c2013-12-06 06:55:2572 }
73 template<typename T>
74 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
75 const T& getter) {
Devlin Cronine9db9842018-04-09 17:51:0576 return SetPropertyImpl(
77 name, internal::CreateFunctionTemplate(isolate_, getter, type_name_),
78 v8::Local<v8::FunctionTemplate>());
[email protected]bf3dd3c2013-12-06 06:55:2579 }
80 template<typename T, typename U>
81 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
82 const T& getter, const U& setter) {
Devlin Cronine9db9842018-04-09 17:51:0583 return SetPropertyImpl(
84 name, internal::CreateFunctionTemplate(isolate_, getter, type_name_),
85 internal::CreateFunctionTemplate(isolate_, setter, type_name_));
[email protected]b520e132013-11-29 03:21:4886 }
Jeremy Roman6a1242b2019-02-04 17:51:5787
88 // Whereas SetProperty creates an accessor property, this creates what appears
89 // to be a data property but whose value is lazily computed the first time the
90 // [[Get]] operation occurs.
91 template <typename T>
92 ObjectTemplateBuilder& SetLazyDataProperty(const base::StringPiece& name,
93 const T& getter) {
94 InvokerOptions options;
95 if (std::is_member_function_pointer<T>::value) {
96 options.holder_is_first_argument = true;
97 options.holder_type = type_name_;
98 }
99 v8::AccessorNameGetterCallback callback;
100 v8::Local<v8::Value> data;
101 std::tie(callback, data) = CreateDataPropertyCallback(
102 isolate_, base::BindRepeating(getter), std::move(options));
103 return SetLazyDataPropertyImpl(name, callback, data);
104 }
105
[email protected]5c969b82014-03-12 04:59:05106 ObjectTemplateBuilder& AddNamedPropertyInterceptor();
107 ObjectTemplateBuilder& AddIndexedPropertyInterceptor();
[email protected]b520e132013-11-29 03:21:48108
109 v8::Local<v8::ObjectTemplate> Build();
110
111 private:
112 ObjectTemplateBuilder& SetImpl(const base::StringPiece& name,
deepak.sfaaa1b62015-04-30 07:30:48113 v8::Local<v8::Data> val);
[email protected]bf3dd3c2013-12-06 06:55:25114 ObjectTemplateBuilder& SetPropertyImpl(
deepak.sfaaa1b62015-04-30 07:30:48115 const base::StringPiece& name, v8::Local<v8::FunctionTemplate> getter,
116 v8::Local<v8::FunctionTemplate> setter);
Jeremy Roman6a1242b2019-02-04 17:51:57117 ObjectTemplateBuilder& SetLazyDataPropertyImpl(
118 const base::StringPiece& name,
119 v8::AccessorNameGetterCallback callback,
120 v8::Local<v8::Value> data);
[email protected]b520e132013-11-29 03:21:48121
122 v8::Isolate* isolate_;
123
Devlin Cronine9db9842018-04-09 17:51:05124 // If provided, |type_name_| will be used to give a user-friendly error
125 // message if a member function is invoked on the wrong type of object.
126 const char* type_name_ = nullptr;
127
[email protected]b520e132013-11-29 03:21:48128 // ObjectTemplateBuilder should only be used on the stack.
129 v8::Local<v8::ObjectTemplate> template_;
130};
131
132} // namespace gin
133
134#endif // GIN_OBJECT_TEMPLATE_BUILDER_H_