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 #include "gin/object_template_builder.h"
9 #include "gin/interceptor.h"
10 #include "gin/per_isolate_data.h"
11 #include "gin/public/wrapper_info.h"
12 #include "v8/include/v8-exception.h"
13 #include "v8/include/v8-template.h"
19 WrappableBase* WrappableFromV8(v8::Isolate* isolate,
20 v8::Local<v8::Value> val) {
23 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(val);
24 WrapperInfo* info = WrapperInfo::From(obj);
26 // If this fails, the object is not managed by Gin.
30 // We don't further validate the type of the object, but assume it's derived
31 // from WrappableBase. We look up the pointer in a global registry, to make
32 // sure it's actually pointed to a valid life object.
33 return static_cast<WrappableBase*>(
34 obj->GetAlignedPointerFromInternalField(kEncodedValueIndex));
37 NamedPropertyInterceptor* NamedInterceptorFromV8(v8::Isolate* isolate,
38 v8::Local<v8::Value> val) {
39 WrappableBase* base = WrappableFromV8(isolate, val);
42 return PerIsolateData::From(isolate)->GetNamedPropertyInterceptor(base);
45 IndexedPropertyInterceptor* IndexedInterceptorFromV8(
47 v8::Local<v8::Value> val) {
48 WrappableBase* base = WrappableFromV8(isolate, val);
51 return PerIsolateData::From(isolate)->GetIndexedPropertyInterceptor(base);
54 void NamedPropertyGetter(v8::Local<v8::Name> property,
55 const v8::PropertyCallbackInfo<v8::Value>& info) {
56 v8::Isolate* isolate = info.GetIsolate();
57 NamedPropertyInterceptor* interceptor =
58 NamedInterceptorFromV8(isolate, info.Holder());
62 ConvertFromV8(isolate, property, &name);
63 info.GetReturnValue().Set(interceptor->GetNamedProperty(isolate, name));
66 void NamedPropertySetter(v8::Local<v8::Name> property,
67 v8::Local<v8::Value> value,
68 const v8::PropertyCallbackInfo<v8::Value>& info) {
69 v8::Isolate* isolate = info.GetIsolate();
70 NamedPropertyInterceptor* interceptor =
71 NamedInterceptorFromV8(isolate, info.Holder());
75 ConvertFromV8(isolate, property, &name);
76 if (interceptor->SetNamedProperty(isolate, name, value))
77 info.GetReturnValue().Set(value);
80 void NamedPropertyQuery(v8::Local<v8::Name> property,
81 const v8::PropertyCallbackInfo<v8::Integer>& info) {
82 v8::Isolate* isolate = info.GetIsolate();
83 NamedPropertyInterceptor* interceptor =
84 NamedInterceptorFromV8(isolate, info.Holder());
88 ConvertFromV8(isolate, property, &name);
89 if (interceptor->GetNamedProperty(isolate, name).IsEmpty())
91 info.GetReturnValue().Set(0);
94 void NamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
95 v8::Isolate* isolate = info.GetIsolate();
96 NamedPropertyInterceptor* interceptor =
97 NamedInterceptorFromV8(isolate, info.Holder());
100 v8::Local<v8::Value> properties;
101 if (!TryConvertToV8(isolate, interceptor->EnumerateNamedProperties(isolate),
104 info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(properties));
107 void IndexedPropertyGetter(uint32_t index,
108 const v8::PropertyCallbackInfo<v8::Value>& info) {
109 v8::Isolate* isolate = info.GetIsolate();
110 IndexedPropertyInterceptor* interceptor =
111 IndexedInterceptorFromV8(isolate, info.Holder());
114 info.GetReturnValue().Set(interceptor->GetIndexedProperty(isolate, index));
117 void IndexedPropertySetter(uint32_t index,
118 v8::Local<v8::Value> value,
119 const v8::PropertyCallbackInfo<v8::Value>& info) {
120 v8::Isolate* isolate = info.GetIsolate();
121 IndexedPropertyInterceptor* interceptor =
122 IndexedInterceptorFromV8(isolate, info.Holder());
125 if (interceptor->SetIndexedProperty(isolate, index, value))
126 info.GetReturnValue().Set(value);
129 void IndexedPropertyEnumerator(
130 const v8::PropertyCallbackInfo<v8::Array>& info) {
131 v8::Isolate* isolate = info.GetIsolate();
132 IndexedPropertyInterceptor* interceptor =
133 IndexedInterceptorFromV8(isolate, info.Holder());
136 v8::Local<v8::Value> properties;
137 if (!TryConvertToV8(isolate, interceptor->EnumerateIndexedProperties(isolate),
140 info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(properties));
143 void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
144 v8::Isolate* isolate = info.GetIsolate();
145 isolate->ThrowException(v8::Exception::Error(info.Data().As<v8::String>()));
150 ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate)
151 : ObjectTemplateBuilder(isolate, nullptr) {}
153 ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate,
154 const char* type_name)
156 type_name_(type_name),
157 constructor_template_(v8::FunctionTemplate::New(
163 ? base::StrCat({"Objects of type ", type_name,
164 " cannot be created using the constructor."})
165 : "Objects of this type cannot be created using the "
167 template_(constructor_template_->InstanceTemplate()) {
168 template_->SetInternalFieldCount(kNumberOfInternalFields);
171 #if defined(ENABLE_WRT_JS)
172 ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate,
173 const char* type_name,
174 v8::Local<v8::ObjectTemplate> tmpl)
175 : isolate_(isolate), type_name_(type_name), template_(tmpl) {
176 template_->SetInternalFieldCount(kNumberOfInternalFields);
180 ObjectTemplateBuilder::ObjectTemplateBuilder(
181 const ObjectTemplateBuilder& other) = default;
183 ObjectTemplateBuilder::~ObjectTemplateBuilder() = default;
185 ObjectTemplateBuilder& ObjectTemplateBuilder::AddNamedPropertyInterceptor() {
186 template_->SetHandler(v8::NamedPropertyHandlerConfiguration(
187 &NamedPropertyGetter, &NamedPropertySetter, &NamedPropertyQuery, nullptr,
188 &NamedPropertyEnumerator, v8::Local<v8::Value>(),
189 v8::PropertyHandlerFlags::kOnlyInterceptStrings));
193 ObjectTemplateBuilder& ObjectTemplateBuilder::AddIndexedPropertyInterceptor() {
194 template_->SetIndexedPropertyHandler(&IndexedPropertyGetter,
195 &IndexedPropertySetter,
198 &IndexedPropertyEnumerator);
202 ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(
203 const base::StringPiece& name, v8::Local<v8::Data> val) {
204 template_->Set(StringToSymbol(isolate_, name), val);
208 ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(v8::Local<v8::Name> name,
209 v8::Local<v8::Data> val) {
210 template_->Set(name, val);
214 ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl(
215 const base::StringPiece& name, v8::Local<v8::FunctionTemplate> getter,
216 v8::Local<v8::FunctionTemplate> setter) {
217 template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter,
222 ObjectTemplateBuilder& ObjectTemplateBuilder::SetLazyDataPropertyImpl(
223 const base::StringPiece& name,
224 v8::AccessorNameGetterCallback callback,
225 v8::Local<v8::Value> data) {
226 template_->SetLazyDataProperty(StringToSymbol(isolate_, name), callback,
231 v8::Local<v8::ObjectTemplate> ObjectTemplateBuilder::Build() {
232 v8::Local<v8::ObjectTemplate> result = template_;
234 constructor_template_.Clear();