1{% extends 'interface_base.cc.tmpl' %}
2
3{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %}
4
5{##############################################################################}
6{% block indexed_property_getter %}
7{% if indexed_property_getter and not indexed_property_getter.is_custom %}
8{% set getter = indexed_property_getter %}
9static void IndexedPropertyGetter(
10    uint32_t index,
11    const v8::PropertyCallbackInfo<v8::Value>& info) {
12  {% if getter.is_raises_exception %}
13  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kIndexedGetterContext, "{{interface_name}}");
14  {% endif %}
15
16  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
17
18  // We assume that all the implementations support length() method, although
19  // the spec doesn't require that length() must exist.  It's okay that
20  // the interface does not have length attribute as long as the
21  // implementation supports length() member function.
22  if (index >= impl->length())
23    return;  // Returns undefined due to out-of-range.
24
25  {% set getter_name = getter.name or 'AnonymousIndexedGetter' %}
26  {% set getter_arguments = ['index'] %}
27  {% if getter.is_call_with_script_state %}
28  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
29  {% set getter_arguments = ['script_state'] + getter_arguments %}
30  {% endif %}
31  {% if getter.is_raises_exception %}
32  {% set getter_arguments = getter_arguments + ['exception_state'] %}
33  {% endif %}
34  {{getter.cpp_type}} result = impl->{{getter_name}}({{getter_arguments | join(', ')}});
35  {{getter.v8_set_return_value}};
36}
37
38{% endif %}
39{% endblock %}
40
41
42{##############################################################################}
43{% block indexed_property_getter_callback %}
44{% if indexed_property_getter or named_property_getter %}
45{% set getter = indexed_property_getter or named_property_getter %}
46void {{v8_class_or_partial}}::IndexedPropertyGetterCallback(
47    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
48  {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.indexed_property_getter_counter) }}
49  {% if indexed_property_getter %}
50
51  {% if getter.is_custom %}
52  {{v8_class}}::IndexedPropertyGetterCustom(index, info);
53  {% else %}
54  {{internal_namespace}}::IndexedPropertyGetter(index, info);
55  {% endif %}
56
57  {% else %}{# otherwise, named property #}
58
59  const AtomicString& property_name = AtomicString::Number(index);
60
61  {% if getter.is_custom %}
62  {{v8_class}}::NamedPropertyGetterCustom(property_name, info);
63  {% else %}
64  {{internal_namespace}}::NamedPropertyGetter(property_name, info);
65  {% endif %}
66
67  {% endif %}{# indexed_property_getter #}
68}
69
70{% endif %}
71{% endblock %}
72
73
74{##############################################################################}
75{% block indexed_property_setter %}
76{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
77{% if indexed_property_setter and not indexed_property_setter.is_custom %}
78{% set setter = indexed_property_setter %}
79static void IndexedPropertySetter(
80    uint32_t index,
81    v8::Local<v8::Value> v8_value,
82    const v8::PropertyCallbackInfo<v8::Value>& info) {
83  {% if setter.has_exception_state %}
84  ExceptionState exception_state(
85      info.GetIsolate(),
86      ExceptionState::kIndexedSetterContext,
87      "{{interface_name}}");
88  {% endif %}
89  {% if setter.is_ce_reactions %}
90  CEReactionsScope ce_reactions_scope;
91  {% endif %}
92
93  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
94  {{v8_value_to_local_cpp_value(setter) | trim | indent(2)}}
95  {% if setter.has_type_checking_interface %}
96  {# Type checking for interface types (if interface not implemented, throw
97     TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
98  if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) {
99    exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'.");
100    return;
101  }
102  {% endif %}
103
104  {% set setter_name = setter.name or 'AnonymousIndexedSetter' %}
105  {% set setter_arguments = ['index', 'property_value'] %}
106  {% if setter.is_call_with_script_state %}
107  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
108  {% set setter_arguments = ['script_state'] + setter_arguments %}
109  {% endif %}
110  {% if setter.is_raises_exception %}
111  {% set setter_arguments = setter_arguments + ['exception_state'] %}
112  {% endif %}
113  IndexedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}});
114  {% if setter.is_raises_exception %}
115  if (exception_state.HadException())
116    return;
117  {% endif %}
118  if (result == IndexedPropertySetterResult::kDidNotIntercept)
119    return;
120  V8SetReturnValue(info, v8_value);
121}
122
123{% endif %}
124{% endblock %}
125
126
127{##############################################################################}
128{% block indexed_property_setter_callback %}
129{% if indexed_property_getter or named_property_setter %}
130{% set setter = indexed_property_setter or named_property_setter %}
131void {{v8_class_or_partial}}::IndexedPropertySetterCallback(
132    uint32_t index,
133    v8::Local<v8::Value> v8_value,
134    const v8::PropertyCallbackInfo<v8::Value>& info) {
135  {% if indexed_property_setter %}
136
137  {% if setter.is_custom %}
138  {{v8_class}}::IndexedPropertySetterCustom(index, v8_value, info);
139  {% else %}
140  {{internal_namespace}}::IndexedPropertySetter(index, v8_value, info);
141  {% endif %}
142
143  {% elif not indexed_property_getter and named_property_setter %}
144
145  const AtomicString& property_name = AtomicString::Number(index);
146
147  {% if setter.is_custom %}
148  {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info);
149  {% else %}
150  {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info);
151  {% endif %}
152
153  {% else %}{# neither of indexed_property_setter nor named_property_setter #}
154
155  // No indexed property setter defined.  Do not fall back to the default
156  // setter.
157  V8SetReturnValue(info, v8::Null(info.GetIsolate()));
158  if (info.ShouldThrowOnError()) {
159    ExceptionState exception_state(info.GetIsolate(),
160                                   ExceptionState::kIndexedSetterContext,
161                                   "{{interface_name}}");
162    {% if setter.is_ce_reactions %}
163    CEReactionsScope ce_reactions_scope;
164    {% endif %}
165    exception_state.ThrowTypeError("Index property setter is not supported.");
166  }
167
168  {% endif %}{# indexed/named_property_setter #}
169}
170
171{% endif %}
172{% endblock %}
173
174
175{##############################################################################}
176{% block indexed_property_descriptor %}
177{% if indexed_property_getter %}
178static void IndexedPropertyDescriptor(
179    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
180  // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
181  // Steps 1.1 to 1.2.4 are covered here: we rely on indexedPropertyGetter() to
182  // call the getter function and check that |index| is a valid property index,
183  // in which case it will have set info.GetReturnValue() to something other
184  // than undefined.
185  {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info);
186  v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
187  if (!getter_value->IsUndefined()) {
188    // 1.2.5. Let |desc| be a newly created Property Descriptor with no fields.
189    // 1.2.6. Set desc.[[Value]] to the result of converting value to an
190    //        ECMAScript value.
191    // 1.2.7. If O implements an interface with an indexed property setter,
192    //        then set desc.[[Writable]] to true, otherwise set it to false.
193    v8::PropertyDescriptor desc(getter_value, {% if indexed_property_setter %}true{% else %}false{% endif %});
194    // 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
195    desc.set_enumerable(true);
196    desc.set_configurable(true);
197    // 1.2.9. Return |desc|.
198    V8SetReturnValue(info, desc);
199  }
200}
201
202{% endif %}
203{% endblock %}
204
205
206{##############################################################################}
207{% block named_property_descriptor %}
208{% if not indexed_property_getter and named_property_getter %}
209static void NamedPropertyDescriptor(
210    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
211  // This function is called when an IDL interface supports named properties
212  // but not indexed properties. When a numeric property is queried, V8 calls
213  // indexedPropertyDescriptorCallback(), which calls this function.
214
215  {% if named_property_getter.is_enumerable %}
216  // Since we initialize our indexed and named property handlers differently
217  // (the former use descriptors and definers, the latter uses a query
218  // callback), we need to inefficiently call the query callback and convert
219  // the v8::PropertyAttribute integer it returns into a v8::PropertyDescriptor
220  // expected by a descriptor callback.
221  // TODO(rakuco): remove this hack once we switch named property handlers to
222  // using descriptor and definer callbacks (bug 764633).
223  const AtomicString& index_as_name = AtomicString::Number(index);
224  {% if named_property_getter.is_custom_property_query %}
225  {{v8_class}}::NamedPropertyQueryCustom(index_as_name, info);
226  {% else %}
227  {{internal_namespace}}::NamedPropertyQuery(index_as_name, info);
228  {% endif %}
229  v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
230  if (!getter_value->IsUndefined()) {
231    DCHECK(getter_value->IsInt32());
232    const int32_t props =
233        getter_value->ToInt32(info.GetIsolate()->GetCurrentContext())
234            .ToLocalChecked()
235            ->Value();
236    v8::PropertyDescriptor desc(V8String(info.GetIsolate(), index_as_name),
237                                !(props & v8::ReadOnly));
238    desc.set_enumerable(!(props & v8::DontEnum));
239    desc.set_configurable(!(props & v8::DontDelete));
240    V8SetReturnValue(info, desc);
241  }
242  {% else %}{# TODO(rakuco): drop this once we remove [NotEnumerable] getters #}
243  // This IDL interface defines a [NotEnumerable] getter. We need to do
244  // something similar to indexedPropertyDescriptor(): call
245  // indexedPropertyGetterCallback, let it end up calling the named property
246  // getter and, if all goes well, we create a v8::PropertyDescriptor with the
247  // right values.
248  {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info);
249  v8::Local<v8::Value> getter_value = info.GetReturnValue().Get();
250  if (!getter_value->IsUndefined()) {
251    v8::PropertyDescriptor desc(getter_value, {% if named_property_setter %}true{% else %}false{% endif %});
252    desc.set_enumerable(false);
253    desc.set_configurable(true);
254    V8SetReturnValue(info, desc);
255  }
256  {% endif %}
257}
258
259{% endif %}
260{% endblock %}
261
262
263{##############################################################################}
264{% block indexed_property_descriptor_callback %}
265{% if indexed_property_getter or named_property_getter %}
266void {{v8_class_or_partial}}::IndexedPropertyDescriptorCallback(
267    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
268  {% if indexed_property_getter %}
269  {{internal_namespace}}::IndexedPropertyDescriptor(index, info);
270  {% else %}{# The interface only supports named properties. #}
271  {{internal_namespace}}::NamedPropertyDescriptor(index, info);
272  {% endif %}{# indexed_property_getter #}
273}
274
275{% endif %}
276{% endblock %}
277
278
279{##############################################################################}
280{% block indexed_property_deleter %}
281{% if indexed_property_deleter and not indexed_property_deleter.is_custom %}
282{% set deleter = indexed_property_deleter %}
283static void IndexedPropertyDeleter(
284    uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
285  {% if deleter.is_raises_exception %}
286  ExceptionState exception_state(
287      info.GetIsolate(),
288      ExceptionState::kIndexedDeletionContext,
289      "{{interface_name}}");
290  {% endif %}
291  {% if deleter.is_ce_reactions %}
292  CEReactionsScope ce_reactions_scope;
293  {% endif %}
294
295  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
296
297  {% set deleter_name = deleter.name or 'AnonymousIndexedDeleter' %}
298  {% set deleter_arguments = ['index'] %}
299  {% if deleter.is_call_with_script_state %}
300  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
301  {% set deleter_arguments = ['script_state'] + deleter_arguments %}
302  {% endif %}
303  {% if deleter.is_raises_exception %}
304  {% set deleter_arguments = deleter_arguments + ['exception_state'] %}
305  {% endif %}
306  NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}});
307  {% if deleter.is_raises_exception %}
308  if (exception_state.HadException())
309    return;
310  {% endif %}
311  if (result == NamedPropertyDeleterResult::kDidNotIntercept)
312    return;
313  V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted);
314}
315
316{% endif %}
317{% endblock %}
318
319
320{##############################################################################}
321{% block indexed_property_deleter_callback %}
322{% if indexed_property_deleter or named_property_deleter %}
323{% set deleter = indexed_property_deleter or named_property_deleter %}
324void {{v8_class_or_partial}}::IndexedPropertyDeleterCallback(
325    uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
326  {% if indexed_property_deleter %}
327
328  {% if deleter.is_custom %}
329  {{v8_class}}::IndexedPropertyDeleterCustom(index, info);
330  {% else %}
331  {{internal_namespace}}::IndexedPropertyDeleter(index, info);
332  {% endif %}
333
334  {% else %}{# otherwise, named property #}
335
336  const AtomicString& property_name = AtomicString::Number(index);
337
338  {% if deleter.is_custom %}
339  {{v8_class}}::NamedPropertyDeleterCustom(property_name, info);
340  {% else %}
341  {{internal_namespace}}::NamedPropertyDeleter(property_name, info);
342  {% endif %}
343
344  {% endif %}{# indexed_property_deleter #}
345}
346
347{% endif %}
348{% endblock %}
349
350
351{##############################################################################}
352{% block indexed_property_definer_callback %}
353{% if indexed_property_getter %}
354void {{v8_class_or_partial}}::IndexedPropertyDefinerCallback(
355    uint32_t index,
356    const v8::PropertyDescriptor& desc,
357    const v8::PropertyCallbackInfo<v8::Value>& info) {
358{% if indexed_property_setter %}
359  // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
360  // 3.9.3. [[DefineOwnProperty]]
361  // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then
362  //   return false.
363  if (desc.has_get() || desc.has_set()) {
364    V8SetReturnValue(info, v8::Null(info.GetIsolate()));
365    if (info.ShouldThrowOnError()) {
366      ExceptionState exception_state(info.GetIsolate(),
367                                     ExceptionState::kIndexedSetterContext,
368                                     "{{interface_name}}");
369      exception_state.ThrowTypeError("Accessor properties are not allowed.");
370    }
371    return;
372  }
373
374  // Return nothing and fall back to indexedPropertySetterCallback.
375{% else %}{# indexed_property_setter #}
376  // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
377  // 3.9.3. [[DefineOwnProperty]]
378  // step 1.2. If O does not implement an interface with an indexed property
379  //   setter, then return false.
380  //
381  // https://html.spec.whatwg.org/C/window-object.html#windowproxy-defineownproperty
382  // 7.4.6 [[DefineOwnProperty]] (P, Desc)
383  // step 2.1. If P is an array index property name, return false.
384  V8SetReturnValue(info, v8::Null(info.GetIsolate()));
385  if (info.ShouldThrowOnError()) {
386    ExceptionState exception_state(info.GetIsolate(),
387                                   ExceptionState::kIndexedSetterContext,
388                                   "{{interface_name}}");
389    exception_state.ThrowTypeError("Index property setter is not supported.");
390  }
391{% endif %}{# indexed_property_setter #}
392}
393
394{% endif %}{# indexed_property_getter #}
395{% endblock %}
396
397
398{##############################################################################}
399{% block named_property_getter %}
400{% if named_property_getter and not named_property_getter.is_custom %}
401{% set getter = named_property_getter %}
402static void NamedPropertyGetter(const AtomicString& name,
403                                const v8::PropertyCallbackInfo<v8::Value>& info) {
404  {% if getter.is_raises_exception %}
405  const std::string& name_in_utf8 = name.Utf8();
406  ExceptionState exception_state(
407      info.GetIsolate(),
408      ExceptionState::kGetterContext,
409      "{{interface_name}}",
410      name_in_utf8.c_str());
411  {% endif %}
412  {% if getter.is_call_with_script_state %}
413  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
414  {% endif %}
415
416  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
417  {% if getter.use_output_parameter_for_result %}
418  {{getter.cpp_type}} result;
419  {{getter.cpp_value}};
420  {% else %}
421  {{getter.cpp_type}} result = {{getter.cpp_value}};
422  {% endif %}
423  if ({{getter.is_null_expression}})
424    return;
425  {{getter.v8_set_return_value}};
426}
427
428{% endif %}
429{% endblock %}
430
431
432{##############################################################################}
433{% block named_property_getter_callback %}
434{% if named_property_getter %}
435{% set getter = named_property_getter %}
436void {{v8_class_or_partial}}::NamedPropertyGetterCallback(
437    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
438  {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_getter_counter) }}
439  if (!name->IsString())
440    return;
441  const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
442
443  {% if getter.is_custom %}
444  {{v8_class}}::NamedPropertyGetterCustom(property_name, info);
445  {% else %}
446  {{internal_namespace}}::NamedPropertyGetter(property_name, info);
447  {% endif %}
448}
449
450{% endif %}
451{% endblock %}
452
453
454{##############################################################################}
455{% block named_property_setter %}
456{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %}
457{% if named_property_setter and not named_property_setter.is_custom %}
458{% set setter = named_property_setter %}
459static void NamedPropertySetter(
460    const AtomicString& name,
461    v8::Local<v8::Value> v8_value,
462    const v8::PropertyCallbackInfo<v8::Value>& info) {
463  {% if setter.has_exception_state %}
464  const std::string& name_in_utf8 = name.Utf8();
465  ExceptionState exception_state(
466      info.GetIsolate(),
467      ExceptionState::kSetterContext,
468      "{{interface_name}}",
469      name_in_utf8.c_str());
470  {% endif %}
471  {% if setter.is_ce_reactions %}
472  CEReactionsScope ce_reactions_scope;
473  {% endif %}
474  {% if setter.is_call_with_script_state %}
475  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
476  {% endif %}
477
478  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
479  {{v8_value_to_local_cpp_value(setter) | trim | indent(2)}}
480  {% if setter.has_type_checking_interface %}
481  {# Type checking for interface types (if interface not implemented, throw
482     TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
483  if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) {
484    exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'.");
485    return;
486  }
487  {% endif %}
488
489  {% set setter_name = setter.name or 'AnonymousNamedSetter' %}
490  {% set setter_arguments = ['name', 'property_value'] %}
491  {% if setter.is_call_with_script_state %}
492  {% set setter_arguments = ['script_state'] + setter_arguments %}
493  {% endif %}
494  {% if setter.is_raises_exception %}
495  {% set setter_arguments =  setter_arguments + ['exception_state'] %}
496  {% endif %}
497  NamedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}});
498  {% if setter.is_raises_exception %}
499  if (exception_state.HadException())
500    return;
501  {% endif %}
502  if (result == NamedPropertySetterResult::kDidNotIntercept)
503    return;
504  V8SetReturnValue(info, v8_value);
505}
506
507{% endif %}
508{% endblock %}
509
510
511{##############################################################################}
512{% block named_property_setter_callback %}
513{% if named_property_setter %}
514{% set setter = named_property_setter %}
515void {{v8_class_or_partial}}::NamedPropertySetterCallback(
516    v8::Local<v8::Name> name,
517    v8::Local<v8::Value> v8_value,
518    const v8::PropertyCallbackInfo<v8::Value>& info) {
519  {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_setter_counter) }}
520  if (!name->IsString())
521    return;
522  const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
523
524  {% if setter.is_custom %}
525  {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info);
526  {% else %}
527  {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info);
528  {% endif %}
529}
530
531{% endif %}
532{% endblock %}
533
534
535{##############################################################################}
536{% block named_property_deleter %}
537{% if named_property_deleter and not named_property_deleter.is_custom %}
538{% set deleter = named_property_deleter %}
539static void NamedPropertyDeleter(
540    const AtomicString& name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
541  {% if deleter.is_raises_exception %}
542  const std::string& name_in_utf8 = name.Utf8();
543  ExceptionState exception_state(
544      info.GetIsolate(),
545      ExceptionState::kDeletionContext,
546      "{{interface_name}}",
547      name_in_utf8.c_str());
548  {% endif %}
549  {% if deleter.is_ce_reactions %}
550  CEReactionsScope ce_reactions_scope;
551  {% endif %}
552  {% if deleter.is_call_with_script_state %}
553  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
554  {% endif %}
555
556  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
557
558  {% set deleter_name = deleter.name or 'AnonymousNamedDeleter' %}
559  {% set deleter_arguments = ['name'] %}
560  {% if deleter.is_call_with_script_state %}
561  {% set deleter_arguments = ['script_state'] + deleter_arguments %}
562  {% endif %}
563  {% if deleter.is_raises_exception %}
564  {% set deleter_arguments = deleter_arguments + ['exception_state'] %}
565  {% endif %}
566  NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}});
567  {% if deleter.is_raises_exception %}
568  if (exception_state.HadException())
569    return;
570  {% endif %}
571  if (result == NamedPropertyDeleterResult::kDidNotIntercept)
572    return;
573  V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted);
574}
575
576{% endif %}
577{% endblock %}
578
579
580{##############################################################################}
581{% block named_property_deleter_callback %}
582{% if named_property_deleter %}
583{% set deleter = named_property_deleter %}
584void {{v8_class_or_partial}}::NamedPropertyDeleterCallback(
585    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
586  if (!name->IsString())
587    return;
588  const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
589
590  {% if deleter.is_custom %}
591  {{v8_class}}::NamedPropertyDeleterCustom(property_name, info);
592  {% else %}
593  {{internal_namespace}}::NamedPropertyDeleter(property_name, info);
594  {% endif %}
595}
596
597{% endif %}
598{% endblock %}
599
600
601{##############################################################################}
602{% block named_property_query %}
603{% if named_property_getter and named_property_getter.is_enumerable and
604      not named_property_getter.is_custom_property_query %}
605{% set getter = named_property_getter %}
606{# If there is an enumerator, there MUST be a query method to properly
607   communicate property attributes. #}
608{% if indexed_property_getter %}
609static void NamedPropertyQuery(
610    const AtomicString& name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
611{% else %}
612{# If we do not have an indexed property getter, this function is called #}
613{# from namedPropertyDescriptor(), whose v8::PropertyCallbackInfo has a #}
614{# v8::Value instead of a v8::Integer. We use this template trick to make #}
615{# the compiler accept the call. #}
616{# TODO(rakuco): remove this hack once we switch named property handlers to #}
617{# using descriptor and definer callbacks (bug 764633). #}
618template <typename T>
619static void NamedPropertyQuery(
620    const AtomicString& name, const v8::PropertyCallbackInfo<T>& info) {
621{% endif %}
622  const std::string& name_in_utf8 = name.Utf8();
623  ExceptionState exception_state(
624      info.GetIsolate(),
625      ExceptionState::kGetterContext,
626      "{{interface_name}}",
627      name_in_utf8.c_str());
628  {% if getter.is_call_with_script_state %}
629  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
630  {% endif %}
631
632  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
633
634  {% set getter_arguments = ['name', 'exception_state'] %}
635  {% if getter.is_call_with_script_state %}
636  {% set getter_arguments = ['script_state'] + getter_arguments %}
637  {% endif %}
638  bool result = impl->NamedPropertyQuery({{getter_arguments | join(', ')}});
639  if (!result)
640    return;
641  // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
642  // 2.7. If |O| implements an interface with a named property setter, then set
643  //      desc.[[Writable]] to true, otherwise set it to false.
644  // 2.8. If |O| implements an interface with the
645  //      [LegacyUnenumerableNamedProperties] extended attribute, then set
646  //      desc.[[Enumerable]] to false, otherwise set it to true.
647  {% if named_property_setter %}
648  {% set desc_properties = ['v8::None'] %}
649  {% else %}
650  {% set desc_properties = ['v8::ReadOnly'] %}
651  {% endif %}
652  {% if has_legacy_unenumerable_named_properties %}
653  {% set desc_properties = ['v8::DontEnum'] + desc_properties %}
654  {% endif %}
655  V8SetReturnValueInt(info, {{desc_properties | join(' | ')}});
656}
657
658{% endif %}
659{% endblock %}
660
661
662{##############################################################################}
663{% block named_property_query_callback %}
664{% if named_property_getter and named_property_getter.is_enumerable %}
665{% set getter = named_property_getter %}
666void {{v8_class_or_partial}}::NamedPropertyQueryCallback(
667    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
668  {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_query_counter) }}
669  if (!name->IsString())
670    return;
671  const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>());
672
673  {% if getter.is_custom_property_query %}
674  {{v8_class}}::NamedPropertyQueryCustom(property_name, info);
675  {% else %}
676  {{internal_namespace}}::NamedPropertyQuery(property_name, info);
677  {% endif %}
678}
679
680{% endif %}
681{% endblock %}
682
683
684{##############################################################################}
685{% block named_property_enumerator %}
686{% if named_property_getter and named_property_getter.is_enumerable and
687      not named_property_getter.is_custom_property_enumerator %}
688static void NamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
689  ExceptionState exception_state(
690      info.GetIsolate(),
691      ExceptionState::kEnumerationContext,
692      "{{interface_name}}");
693
694  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
695
696  Vector<String> names;
697  impl->NamedPropertyEnumerator(names, exception_state);
698  if (exception_state.HadException())
699    return;
700  V8SetReturnValue(info, ToV8(names, info.Holder(), info.GetIsolate()).As<v8::Array>());
701}
702
703{% endif %}
704{% endblock %}
705
706
707{##############################################################################}
708{% block named_property_enumerator_callback %}
709{% if named_property_getter and named_property_getter.is_enumerable %}
710{% set getter = named_property_getter %}
711void {{v8_class_or_partial}}::NamedPropertyEnumeratorCallback(
712    const v8::PropertyCallbackInfo<v8::Array>& info) {
713  {% if getter.is_custom_property_enumerator %}
714  {{v8_class}}::NamedPropertyEnumeratorCustom(info);
715  {% else %}
716  {{internal_namespace}}::NamedPropertyEnumerator(info);
717  {% endif %}
718}
719
720{% endif %}
721{% endblock %}
722
723
724{##############################################################################}
725{% block named_constructor %}
726{% from 'methods.cc.tmpl' import generate_constructor with context %}
727{% if named_constructor %}
728{% set active_scriptwrappable_inheritance =
729    'kInheritFromActiveScriptWrappable'
730    if active_scriptwrappable else
731    'kNotInheritFromActiveScriptWrappable' %}
732// Suppress warning: global constructors, because struct WrapperTypeInfo is trivial
733// and does not depend on another global objects.
734#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
735#pragma clang diagnostic push
736#pragma clang diagnostic ignored "-Wglobal-constructors"
737#endif
738const WrapperTypeInfo {{snake_case_v8_class}}_constructor_wrapper_type_info = {
739    gin::kEmbedderBlink,
740    {{v8_class}}Constructor::DomTemplate,
741    {{install_conditional_features_func or 'nullptr'}},
742    "{{interface_name}}",
743    nullptr,
744    WrapperTypeInfo::kWrapperTypeObjectPrototype,
745    WrapperTypeInfo::{{wrapper_class_id}},
746    WrapperTypeInfo::{{active_scriptwrappable_inheritance}},
747};
748#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
749#pragma clang diagnostic pop
750#endif
751
752{{generate_constructor(named_constructor)}}
753v8::Local<v8::FunctionTemplate> {{v8_class}}Constructor::DomTemplate(
754    v8::Isolate* isolate, const DOMWrapperWorld& world) {
755  static int dom_template_key; // This address is used for a key to look up the dom template.
756  V8PerIsolateData* data = V8PerIsolateData::From(isolate);
757  v8::Local<v8::FunctionTemplate> result =
758      data->FindInterfaceTemplate(world, &dom_template_key);
759  if (!result.IsEmpty())
760    return result;
761
762  result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback);
763  v8::Local<v8::ObjectTemplate> instance_template = result->InstanceTemplate();
764  instance_template->SetInternalFieldCount({{v8_class}}::kInternalFieldCount);
765  result->SetClassName(V8AtomicString(isolate, "{{named_constructor.name}}"));
766  result->Inherit({{v8_class}}::DomTemplate(isolate, world));
767  data->SetInterfaceTemplate(world, &dom_template_key, result);
768  return result;
769}
770
771void {{v8_class}}Constructor::NamedConstructorAttributeGetter(
772    v8::Local<v8::Name> property_name,
773    const v8::PropertyCallbackInfo<v8::Value>& info) {
774  v8::Local<v8::Context> creationContext = info.Holder()->CreationContext();
775  V8PerContextData* per_context_data = V8PerContextData::From(creationContext);
776  if (!per_context_data) {
777    // TODO(yukishiino): Return a valid named constructor even after the context is detached
778    return;
779  }
780
781  v8::Local<v8::Function> named_constructor =
782      per_context_data->ConstructorForType({{v8_class}}Constructor::GetWrapperTypeInfo());
783
784  // Set the prototype of named constructors to the regular constructor.
785  static const V8PrivateProperty::SymbolKey kPrivatePropertyInitialized;
786  auto private_property =
787      V8PrivateProperty::GetSymbol(
788          info.GetIsolate(), kPrivatePropertyInitialized);
789  v8::Local<v8::Context> current_context = info.GetIsolate()->GetCurrentContext();
790  v8::Local<v8::Value> private_value;
791
792  if (!private_property.GetOrUndefined(named_constructor).ToLocal(&private_value) ||
793      private_value->IsUndefined()) {
794    v8::Local<v8::Function> interface =
795        per_context_data->ConstructorForType({{v8_class}}::GetWrapperTypeInfo());
796    v8::Local<v8::Value> interface_prototype =
797        interface->Get(current_context, V8AtomicString(info.GetIsolate(), "prototype"))
798        .ToLocalChecked();
799    // https://heycam.github.io/webidl/#named-constructors
800    // 8. Perform ! DefinePropertyOrThrow(F, "prototype",
801    //        PropertyDescriptor{[[Value]]: proto, [[Writable]]: false,
802    //                           [[Enumerable]]: false,
803    //                           [Configurable]]: false}).
804    const v8::PropertyAttribute prototype_attributes =
805        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
806    bool result = named_constructor->DefineOwnProperty(
807        current_context, V8AtomicString(info.GetIsolate(), "prototype"),
808        interface_prototype, prototype_attributes).ToChecked();
809    CHECK(result);
810    private_property.Set(named_constructor, v8::True(info.GetIsolate()));
811  }
812
813  V8SetReturnValue(info, named_constructor);
814}
815
816{% endif %}
817{% endblock %}
818
819{##############################################################################}
820{% block overloaded_constructor %}
821{% if constructor_overloads %}
822static void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
823  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}");
824  {# This follows the overload resolution algorithm. #}
825  {# https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm #}
826  {# 3. Initialize argcount to be min(maxarg, n). #}
827  switch (std::min({{constructor_overloads.maxarg}}, info.Length())) {
828    {# 4. Remove from S all entries whose type list is not of length argcount. #}
829    {% for length, tests_constructors in constructor_overloads.length_tests_methods %}
830    {# 12. If i = d, then: #}
831    case {{length}}:
832      {# Then resolve by testing argument #}
833      {% for test, constructor in tests_constructors %}
834      if ({{test}}) {
835        {{internal_namespace}}::Constructor{{constructor.overload_index}}(info);
836        return;
837      }
838      {% if "exception_state" in test %}
839      if (exception_state.HadException()) {
840        exception_state.RethrowV8Exception(exception_state.GetException());
841        return;
842      }
843      {% endif %}
844      {% endfor %}
845      break;
846    {% endfor %}
847    default:
848      {# Invalid arity, throw error #}
849      {# Report full list of valid arities if gaps and above minimum #}
850      {% if constructor_overloads.valid_arities %}
851      if (info.Length() >= {{constructor_overloads.length}}) {
852        exception_state.ThrowTypeError(ExceptionMessages::InvalidArity("{{constructor_overloads.valid_arities}}", info.Length()));
853        return;
854      }
855      {% endif %}
856      {# Otherwise just report "not enough arguments" #}
857      exception_state.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{constructor_overloads.length}}, info.Length()));
858      return;
859  }
860  {# No match, throw error #}
861  exception_state.ThrowTypeError("No matching constructor signature.");
862}
863
864{% endif %}
865{% endblock %}
866
867
868{##############################################################################}
869{% block constructor_callback %}
870{% if constructors or has_custom_constructor or has_html_constructor %}
871{{exported}}void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
872  {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.constructor_counter) }}
873  {% if measure_as %}
874  ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate());
875  UseCounter::Count(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}});
876  {% if high_entropy %}
877  Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}});
878  {% endif %}
879  {% endif %}
880  if (!info.IsConstructCall()) {
881    V8ThrowException::ThrowTypeError(
882        info.GetIsolate(),
883        ExceptionMessages::ConstructorNotCallableAsFunction("{{interface_name}}"));
884    return;
885  }
886
887  if (ConstructorMode::Current(info.GetIsolate()) == ConstructorMode::kWrapExistingObject) {
888    V8SetReturnValue(info, info.Holder());
889    return;
890  }
891
892  {% if has_custom_constructor %}
893  {{v8_class}}::ConstructorCustom(info);
894  {% elif has_html_constructor %}
895  V8HTMLConstructor::HtmlConstructor(
896      info, *{{v8_class}}::GetWrapperTypeInfo(), HTMLElementType::k{{interface_name}});
897  {% else %}
898  {{internal_namespace}}::Constructor(info);
899  {% endif %}
900}
901
902{% endif %}
903{% endblock %}
904
905
906{##############################################################################}
907{% macro install_origin_safe_method(method, instance_template, prototype_template, interface_template, signature) %}
908{% from 'utilities.cc.tmpl' import property_location %}
909{# TODO(dcheng): Currently, bindings must create a function object for each
910   realm as a hack to support the incumbent realm. Clean this up when Blink
911   properly supports the incumbent realm. #}
912{% set function_callback =
913       '%s::%sMethodCallback' % (v8_class_or_partial, method.camel_case_name) %}
914{% set property_attribute =
915       'static_cast<v8::PropertyAttribute>(%s)' %
916       ' | '.join(method.property_attributes or ['v8::None']) %}
917{% set holder_check = 'V8DOMConfiguration::kCheckHolder' %}
918static const V8DOMConfiguration::MethodConfiguration k{{method.camel_case_name}}OriginSafeMethodConfiguration[] = {
919{% if method.is_per_world_bindings %}
920{% set function_callback_for_main_world = '%sForMainWorld' % function_callback %}
921    {
922        "{{method.name}}",
923        {{function_callback_for_main_world}},
924        {{method.length}},
925        {{property_attribute}},
926        {{property_location(method)}},
927        {{holder_check}},
928        V8DOMConfiguration::kCheckAccess,
929        V8DOMConfiguration::kHasSideEffect,
930        V8DOMConfiguration::MainWorld,
931    },
932    {
933        "{{method.name}}",
934        {{function_callback}},
935        {{method.length}},
936        {{property_attribute}},
937        {{property_location(method)}},
938        {{holder_check}},
939        V8DOMConfiguration::kCheckAccess,
940        V8DOMConfiguration::kHasSideEffect,
941        V8DOMConfiguration::NonMainWorlds,
942    }
943{% else %}
944    {
945        "{{method.name}}",
946        {{function_callback}},
947        {{method.length}},
948        {{property_attribute}},
949        {{property_location(method)}},
950        {{holder_check}},
951        V8DOMConfiguration::kCheckAccess,
952        V8DOMConfiguration::kHasSideEffect,
953        V8DOMConfiguration::kAllWorlds,
954    }
955{% endif %}
956};
957for (const auto& method_config : k{{method.camel_case_name}}OriginSafeMethodConfiguration)
958  V8DOMConfiguration::InstallMethod(isolate, world, {{instance_template}}, {{prototype_template}}, {{interface_template}}, {{signature}}, method_config);
959{%- endmacro %}
960
961
962{##############################################################################}
963{% macro install_indexed_property_handler(target) %}
964{% set indexed_property_getter_callback =
965       '%s::IndexedPropertyGetterCallback' % v8_class_or_partial %}
966{% set indexed_property_setter_callback =
967       '%s::IndexedPropertySetterCallback' % v8_class_or_partial
968       if indexed_property_getter or named_property_setter else 'nullptr' %}
969{% set indexed_property_descriptor_callback =
970       '%s::IndexedPropertyDescriptorCallback' % v8_class_or_partial
971       if indexed_property_getter or named_property_getter else 'nullptr' %}
972{% set indexed_property_deleter_callback =
973       '%s::IndexedPropertyDeleterCallback' % v8_class_or_partial
974       if indexed_property_deleter or named_property_deleter else 'nullptr' %}
975{% set indexed_property_enumerator_callback =
976       'IndexedPropertyEnumerator<%s>' % cpp_class
977       if indexed_property_getter.is_enumerable else 'nullptr' %}
978{% set indexed_property_definer_callback =
979       '%s::IndexedPropertyDefinerCallback' % v8_class_or_partial
980       if indexed_property_getter else 'nullptr' %}
981{% set property_handler_flags =
982       'v8::PropertyHandlerFlags::kHasNoSideEffect'
983       if indexed_property_getter.has_no_side_effect else 'v8::PropertyHandlerFlags::kNone' %}
984v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(
985    {{indexed_property_getter_callback}},
986    {{indexed_property_setter_callback}},
987    {{indexed_property_descriptor_callback}},
988    {{indexed_property_deleter_callback}},
989    {{indexed_property_enumerator_callback}},
990    {{indexed_property_definer_callback}},
991    v8::Local<v8::Value>(),
992    {{property_handler_flags}});
993{{target}}->SetHandler(indexedPropertyHandlerConfig);
994{%- endmacro %}
995
996
997{##############################################################################}
998{% macro install_named_property_handler(target) %}
999{% set named_property_getter_callback =
1000       '%s::NamedPropertyGetterCallback' % v8_class_or_partial %}
1001{% set named_property_setter_callback =
1002       '%s::NamedPropertySetterCallback' % v8_class_or_partial
1003       if named_property_setter else 'nullptr' %}
1004{% set named_property_query_callback =
1005       '%s::NamedPropertyQueryCallback' % v8_class_or_partial
1006       if named_property_getter.is_enumerable else 'nullptr' %}
1007{% set named_property_deleter_callback =
1008       '%s::NamedPropertyDeleterCallback' % v8_class_or_partial
1009       if named_property_deleter else 'nullptr' %}
1010{% set named_property_enumerator_callback =
1011       '%s::NamedPropertyEnumeratorCallback' % v8_class_or_partial
1012       if named_property_getter.is_enumerable else 'nullptr' %}
1013{% set property_handler_flags_list =
1014       ['int(v8::PropertyHandlerFlags::kOnlyInterceptStrings)'] %}
1015{% if not is_override_builtins %}
1016{% set property_handler_flags_list =
1017       property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kNonMasking)'] %}
1018{% endif %}
1019{% if named_property_getter.has_no_side_effect %}
1020{% set property_handler_flags_list =
1021       property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kHasNoSideEffect)'] %}
1022{% endif %}
1023{% set property_handler_flags =
1024       'static_cast<v8::PropertyHandlerFlags>(%s)' %
1025           ' | '.join(property_handler_flags_list) %}
1026v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}});
1027{{target}}->SetHandler(namedPropertyHandlerConfig);
1028{%- endmacro %}
1029
1030
1031{##############################################################################}
1032{% block get_dom_template %}
1033{% if not is_array_buffer_or_view %}
1034v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(
1035    v8::Isolate* isolate, const DOMWrapperWorld& world) {
1036  {% set install_template_function = '%s::install_%s_template_function_' % (v8_class, snake_case_v8_class) if has_partial_interface else 'Install%sTemplate' % v8_class %}
1037  return V8DOMConfiguration::DomClassTemplate(
1038      isolate, world, const_cast<WrapperTypeInfo*>({{v8_class}}::GetWrapperTypeInfo()),
1039      {{install_template_function}});
1040}
1041
1042{% endif %}
1043{% endblock %}
1044
1045
1046{##############################################################################}
1047{% block get_dom_template_for_named_properties_object %}
1048{% if has_named_properties_object %}
1049v8::Local<v8::FunctionTemplate>
1050{{v8_class}}::DomTemplateForNamedPropertiesObject(
1051    v8::Isolate* isolate, const DOMWrapperWorld& world) {
1052  v8::Local<v8::FunctionTemplate> parentTemplate =
1053      V8{{parent_interface}}::DomTemplate(isolate, world);
1054
1055  v8::Local<v8::FunctionTemplate> named_properties_function_template =
1056      v8::FunctionTemplate::New(isolate,
1057                                V8ObjectConstructor::IsValidConstructorMode);
1058  named_properties_function_template->SetClassName(
1059      V8AtomicString(isolate, "{{interface_name}}Properties"));
1060  named_properties_function_template->Inherit(parentTemplate);
1061
1062  v8::Local<v8::ObjectTemplate> named_properties_object_template =
1063      named_properties_function_template->PrototypeTemplate();
1064  named_properties_object_template->SetInternalFieldCount(
1065      {{v8_class}}::kInternalFieldCount);
1066  // Named Properties object has SetPrototype method of Immutable Prototype Exotic Objects
1067  named_properties_object_template->SetImmutableProto();
1068  V8DOMConfiguration::SetClassString(
1069      isolate, named_properties_object_template, "{{interface_name}}Properties");
1070  {{install_named_property_handler('named_properties_object_template') | trim | indent(2)}}
1071
1072  return named_properties_function_template;
1073}
1074
1075{% endif %}
1076{% endblock %}
1077
1078
1079{##############################################################################}
1080{% block has_instance %}
1081{% if not is_array_buffer_or_view %}
1082
1083bool {{v8_class}}::HasInstance(v8::Local<v8::Value> v8_value, v8::Isolate* isolate) {
1084  return V8PerIsolateData::From(isolate)->HasInstance({{v8_class}}::GetWrapperTypeInfo(), v8_value);
1085}
1086
1087v8::Local<v8::Object> {{v8_class}}::FindInstanceInPrototypeChain(
1088    v8::Local<v8::Value> v8_value, v8::Isolate* isolate) {
1089  return V8PerIsolateData::From(isolate)->FindInstanceInPrototypeChain(
1090      {{v8_class}}::GetWrapperTypeInfo(), v8_value);
1091}
1092
1093{% endif %}
1094{% endblock %}
1095
1096
1097{##############################################################################}
1098{% block to_impl %}
1099{% if interface_name == 'ArrayBuffer' or interface_name == 'SharedArrayBuffer' %}
1100{{cpp_class}}* V8{{interface_name}}::ToImpl(v8::Local<v8::Object> object) {
1101  DCHECK(object->Is{{interface_name}}());
1102  v8::Local<v8::{{interface_name}}> v8buffer = object.As<v8::{{interface_name}}>();
1103  // TODO(ahaas): The use of IsExternal is wrong here. Instead we should call
1104  // ToScriptWrappable(object)->ToImpl<ArrayBuffer>() and check for nullptr.
1105  // We can then also avoid the call to Externalize below.
1106  if (v8buffer->IsExternal()) {
1107    const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object);
1108    CHECK(wrapper_type);
1109    CHECK_EQ(wrapper_type->gin_embedder, gin::kEmbedderBlink);
1110    return ToScriptWrappable(object)->ToImpl<{{cpp_class}}>();
1111  }
1112
1113  // Transfer the ownership of the allocated memory to an {{interface_name}} without
1114  // copying.
1115  auto backing_store = v8buffer->GetBackingStore();
1116  v8buffer->Externalize(backing_store);
1117  ArrayBufferContents contents(std::move(backing_store));
1118  {{cpp_class}}* buffer = {{cpp_class}}::Create(contents);
1119  v8::Local<v8::Object> associatedWrapper = buffer->AssociateWithWrapper(v8::Isolate::GetCurrent(), buffer->GetWrapperTypeInfo(), object);
1120  DCHECK(associatedWrapper == object);
1121
1122  return buffer;
1123}
1124
1125{% elif interface_name == 'ArrayBufferView' %}
1126{{cpp_class}}* V8ArrayBufferView::ToImpl(v8::Local<v8::Object> object) {
1127  DCHECK(object->IsArrayBufferView());
1128  ScriptWrappable* script_wrappable = ToScriptWrappable(object);
1129  if (script_wrappable)
1130    return script_wrappable->ToImpl<{{cpp_class}}>();
1131
1132  if (object->IsInt8Array())
1133    return V8Int8Array::ToImpl(object);
1134  if (object->IsInt16Array())
1135    return V8Int16Array::ToImpl(object);
1136  if (object->IsInt32Array())
1137    return V8Int32Array::ToImpl(object);
1138  if (object->IsUint8Array())
1139    return V8Uint8Array::ToImpl(object);
1140  if (object->IsUint8ClampedArray())
1141    return V8Uint8ClampedArray::ToImpl(object);
1142  if (object->IsUint16Array())
1143    return V8Uint16Array::ToImpl(object);
1144  if (object->IsUint32Array())
1145    return V8Uint32Array::ToImpl(object);
1146  if (object->IsBigInt64Array())
1147    return V8BigInt64Array::ToImpl(object);
1148  if (object->IsBigUint64Array())
1149    return V8BigUint64Array::ToImpl(object);
1150  if (object->IsFloat32Array())
1151    return V8Float32Array::ToImpl(object);
1152  if (object->IsFloat64Array())
1153    return V8Float64Array::ToImpl(object);
1154  if (object->IsDataView())
1155    return V8DataView::ToImpl(object);
1156
1157  NOTREACHED();
1158  return nullptr;
1159}
1160
1161{% elif is_array_buffer_or_view %}
1162{{cpp_class}}* {{v8_class}}::ToImpl(v8::Local<v8::Object> object) {
1163  DCHECK(object->Is{{interface_name}}());
1164  ScriptWrappable* script_wrappable = ToScriptWrappable(object);
1165  if (script_wrappable)
1166    return script_wrappable->ToImpl<{{cpp_class}}>();
1167
1168  v8::Local<v8::{{interface_name}}> v8_view = object.As<v8::{{interface_name}}>();
1169  v8::Local<v8::Object> array_buffer = v8_view->Buffer();
1170  {{cpp_class}}* typed_array = nullptr;
1171  if (array_buffer->IsArrayBuffer()) {
1172    typed_array = {{cpp_class}}::Create(
1173        V8ArrayBuffer::ToImpl(array_buffer),
1174        v8_view->ByteOffset(),
1175        v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length());
1176  } else if (array_buffer->IsSharedArrayBuffer()) {
1177    typed_array = {{cpp_class}}::Create(
1178        V8SharedArrayBuffer::ToImpl(array_buffer),
1179        v8_view->ByteOffset(),
1180        v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length());
1181  } else {
1182    NOTREACHED();
1183  }
1184  v8::Local<v8::Object> associated_wrapper =
1185        typed_array->AssociateWithWrapper(
1186            v8::Isolate::GetCurrent(), typed_array->GetWrapperTypeInfo(), object);
1187  DCHECK(associated_wrapper == object);
1188
1189  return typed_array->ToImpl<{{cpp_class}}>();
1190}
1191
1192{% endif %}
1193{% endblock %}
1194
1195
1196{##############################################################################}
1197{% block to_impl_with_type_check %}
1198{{cpp_class}}* {{v8_class}}::ToImplWithTypeCheck(
1199    v8::Isolate* isolate, v8::Local<v8::Value> value) {
1200{% if is_array_buffer_or_view %}
1201  return value->Is{{interface_name}}() ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr;
1202{% else %}
1203  return HasInstance(value, isolate) ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr;
1204{% endif %}
1205}
1206
1207{% endblock %}
1208
1209
1210{##############################################################################}
1211{% block partial_interface %}
1212{% if has_partial_interface %}
1213{% if needs_runtime_enabled_installer %}
1214InstallRuntimeEnabledFeaturesFunction
1215{{v8_class}}::install_runtime_enabled_features_function_ =
1216    &{{v8_class}}::InstallRuntimeEnabledFeaturesImpl;
1217{% endif %}
1218{% if not is_array_buffer_or_view %}
1219InstallRuntimeEnabledFeaturesOnTemplateFunction
1220{{v8_class}}::install_runtime_enabled_features_on_template_function_ =
1221    &{{v8_class}}::InstallRuntimeEnabledFeaturesOnTemplate;
1222{% endif %}
1223
1224InstallTemplateFunction
1225{{v8_class}}::install_{{snake_case_v8_class}}_template_function_ =
1226    &{{v8_class}}::Install{{v8_class}}Template;
1227
1228void {{v8_class}}::UpdateWrapperTypeInfo(
1229    InstallTemplateFunction install_template_function,
1230    InstallRuntimeEnabledFeaturesFunction install_runtime_enabled_features_function,
1231    InstallRuntimeEnabledFeaturesOnTemplateFunction install_runtime_enabled_features_on_template_function,
1232    InstallConditionalFeaturesFunction install_conditional_features_function) {
1233  {{v8_class}}::install_{{snake_case_v8_class}}_template_function_ =
1234      install_template_function;
1235
1236  {% if needs_runtime_enabled_installer %}
1237  CHECK(install_runtime_enabled_features_function);
1238  {{v8_class}}::install_runtime_enabled_features_function_ =
1239      install_runtime_enabled_features_function;
1240
1241  {% endif %}
1242  {% if not is_array_buffer_or_view  %}
1243  CHECK(install_runtime_enabled_features_on_template_function);
1244  {{v8_class}}::install_runtime_enabled_features_on_template_function_ =
1245      install_runtime_enabled_features_on_template_function;
1246  {% endif %}
1247
1248  if (install_conditional_features_function) {
1249    {{v8_class}}::GetWrapperTypeInfo()->install_conditional_features_function =
1250        install_conditional_features_function;
1251  }
1252}
1253
1254{% for method in methods if method.overloads and method.overloads.has_partial_overloads %}
1255void {{v8_class}}::Register{{method.camel_case_name}}MethodForPartialInterface(void (*method)(const v8::FunctionCallbackInfo<v8::Value>&)) {
1256  {{internal_namespace}}::{{method.name}}MethodForPartialInterface = method;
1257}
1258
1259{% endfor %}
1260{% endif %}{# has_partial_interface #}
1261{% endblock %}
1262