{% 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 %}

}  // namespace blink

{% endfilter %}{# format_blink_cpp_source_code #}
