summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl
blob: a0bf43f0c09cb206892e87d3b490cd4dd0b5d1b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
{% from 'callback_invoke.cc.tmpl' import callback_invoke %}
{% filter format_blink_cpp_source_code %}

{% include 'copyright_block.txt' %}

#include "{{this_include_header_path}}"

{% for filename in cpp_includes %}
#include "{{filename}}"
{% endfor %}

namespace blink {

{% if is_legacy_callback_interface %}
// Support of "legacy callback interface"

// Suppress warning: global constructors, because struct WrapperTypeInfo is
// trivial and does not depend on another global objects.
#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
const WrapperTypeInfo {{snake_case_v8_class}}_wrapper_type_info = {
    gin::kEmbedderBlink,
    {{v8_class}}::DomTemplate,
    nullptr,
    "{{interface_name}}",
    nullptr,
    WrapperTypeInfo::kWrapperTypeNoPrototype,
    WrapperTypeInfo::kObjectClassId,
    WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
};
#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
#pragma clang diagnostic pop
#endif

{% from 'constants.cc.tmpl' import install_constants with context %}
static void Install{{v8_class}}Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interface_template) {
  // Legacy callback interface must not have a prototype object.
  interface_template->RemovePrototype();

  // Initialize the interface object's template.
  V8DOMConfiguration::InitializeDOMInterfaceTemplate(
      isolate, interface_template,
      {{v8_class}}::GetWrapperTypeInfo()->interface_name,
      v8::Local<v8::FunctionTemplate>(),
      kV8DefaultWrapperInternalFieldCount);
  interface_template->SetLength(0);

  // Register IDL constants.
  {# |install_constants| requires |interface_template| and |prototype_template|. #}
  v8::Local<v8::ObjectTemplate> prototype_template =
      interface_template->PrototypeTemplate();
  {{install_constants() | trim | indent(2)}}
}

// static
v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world) {
  return V8DOMConfiguration::DomClassTemplate(
      isolate,
      world,
      const_cast<WrapperTypeInfo*>(GetWrapperTypeInfo()),
      Install{{v8_class}}Template);
}
{% endif %}{# is_legacy_callback_interface #}

const char* {{v8_class}}::NameInHeapSnapshot() const {
  return "{{v8_class}}";
}

{% for method in methods %}

v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) {
{{callback_invoke(
    'callback interface', None,
    method.cpp_type, method.native_value_traits_tag, method.arguments,
    False, False,
    interface_name, method.name)}}
}

{% endfor %}

{% if methods|length == 1 and methods[0].idl_type == 'void' %}
void {{v8_class}}::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
  v8::TryCatch try_catch(GetIsolate());
  try_catch.SetVerbose(true);

  v8::Maybe<void> maybe_result =
      {{methods[0].name}}({{
          (['callback_this_value'] +
           (methods[0].arguments|map(attribute='name')|list)
          )|join(', ')
      }});
  // An exception if any is killed with the v8::TryCatch above.
  ALLOW_UNUSED_LOCAL(maybe_result);
}
{% endif %}

{% if interface_name == 'EventListener' %}
bool {{v8_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) {
  ScriptState* callback_relevant_script_state =
      CallbackRelevantScriptState();

  bool is_runnable =
      ignore_pause == IgnorePause::kIgnore ?
      IsCallbackFunctionRunnableIgnoringPause(
          callback_relevant_script_state, IncumbentScriptState()) :
      IsCallbackFunctionRunnable(
          callback_relevant_script_state, IncumbentScriptState());
  if (is_runnable)
    return true;

  // Wrapper-tracing for the callback function makes the function object and
  // its creation context alive. Thus it's safe to use the creation context
  // of the callback function here.
  ScriptState::Scope scope(callback_relevant_script_state);
  V8ThrowException::ThrowError(
      GetIsolate(),
      ExceptionMessages::FailedToExecute(
          "{{methods[0].name}}",
          "{{interface_name}}",
          "The provided callback is no longer runnable."));
  return false;
}

v8::Maybe<{{methods[0].cpp_type}}> {{v8_class}}::InvokeWithoutRunnabilityCheck({{methods[0].argument_declarations | join(', ')}}) {
{{callback_invoke(
    'callback interface', None,
    methods[0].cpp_type, methods[0].native_value_traits_tag, methods[0].arguments,
    False, True,
    interface_name, methods[0].name)}}
}
{% endif %}

{% for method in methods %}
v8::Maybe<{{method.cpp_type}}> V8PersistentCallbackInterface<{{v8_class}}>::{{method.name}}({{method.argument_declarations | join(', ')}}) {
  return Proxy()->{{method.name}}(
      {{
         (['callback_this_value'] +
          (method.arguments|map(attribute='name')|list)
         )|join(', ')
      }});
}

{% endfor %}

{% if methods|length == 1 and methods[0].idl_type == 'void' %}
void V8PersistentCallbackInterface<{{v8_class}}>::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
  Proxy()->InvokeAndReportException(
      {{
         (['callback_this_value'] +
          (methods[0].arguments|map(attribute='name')|list)
         )|join(', ')
      }});
}
{% endif %}

}  // namespace blink

{% endfilter %}{# format_blink_cpp_source_code #}