{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %}

{##############################################################################}
{% macro runtime_timer_scope(counter) %}
RUNTIME_CALL_TIMER_SCOPE(info.GetIsolate(), RuntimeCallStats::CounterId::{{counter}});
{% endmacro %}

{% macro runtime_timer_scope_disabled_by_default(counter) %}
RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "{{counter}}");
{% endmacro %}

{% macro generate_method(method, world_suffix) %}
static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
  {% filter format_remove_duplicates([
      'ExceptionState exceptionState',
      'ScriptState* scriptState = ']) %}
  {% set define_exception_state -%}
  ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "{{interface_name}}", "{{method.name}}");
  {%- endset %}

  {% if method.is_ce_reactions %}
  CEReactionsScope ceReactionsScope;
  {% endif %}

  {% set function_call = func_call_with_prep_of_args(method, world_suffix) %}

  {% if 'exceptionState' in function_call or
        (method.returns_promise and not method.is_static) %}
  {{define_exception_state}}
  {% if method.returns_promise %}
  ExceptionToRejectPromiseScope rejectPromiseScope(info, exceptionState);
  {% endif %}
  {% endif %}

  {% if not method.is_static %}
  {% if method.returns_promise %}
  // V8DOMConfiguration::kDoNotCheckHolder
  // Make sure that info.Holder() really points to an instance of the type.
  if (!{{v8_class}}::hasInstance(info.Holder(), info.GetIsolate())) {
    {{throw_type_error(method, '"Illegal invocation"')}}
    return;
  }
  {% endif %}
  {% if interface_name == 'Window' and not method.is_cross_origin %}
  // Same-origin methods are never exposed via the cross-origin interceptors.
  // Since same-origin access requires a LocalDOMWindow, it is safe to downcast
  // here.
  LocalDOMWindow* impl = ToLocalDOMWindow({{v8_class}}::ToImpl(info.Holder()));
  {% else %}
  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
  {% endif %}{# interface_name == 'Window' and not method.is_cross_origin #}
  {% endif %}{# not method.is_static #}

  {# Security checks #}
  {% if method.is_check_security_for_return_value %}
  {{define_exception_state}}
  if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), {{method.cpp_value}}, BindingSecurity::ErrorReportOption::kDoNotReport)) {
    UseCounter::Count(CurrentExecutionContext(info.GetIsolate()),
                      WebFeature::kCrossOrigin{{interface_name}}{{method.name|blink_capitalize}});
    V8SetReturnValueNull(info);
    return;
  }
  {% endif %}

  {% if 'scriptState' in function_call %}
  {% if method.is_static %}
  ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
  {% else %}
  ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
  {% endif %}
  {% endif %}

  {% if method.is_custom_element_callbacks %}
  V0CustomElementProcessingStack::CallbackDeliveryScope deliveryScope;
  {% endif %}

  {{function_call | trim | indent(2)}}
}
{% endfilter %}
{% endmacro %}


{######################################}
{% macro func_call_with_prep_of_args(method, world_suffix) %}
{{generate_arguments(method, world_suffix)}}
{% if world_suffix %}
{{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value)}}
{% else %}
{{cpp_method_call(method, method.v8_set_return_value, method.cpp_value)}}
{% endif %}
{% endmacro %}


{######################################}
{% macro generate_arguments(method, world_suffix) %}
{% if method.arguments %}

{# Overloaded methods/constructors have length checked during overload resolution #}
{% if method.number_of_required_arguments and not method.overload_index %}
if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
  {{throw_type_error(method,
        'ExceptionMessages::NotEnoughArguments(%(expected)d, info.Length())'
        | format(expected=method.number_of_required_arguments))}}
  return;
}
{% endif %}

{% for argument in method.arguments %}
{{argument.cpp_type}} {{argument.name}};
{% endfor %}
{% if method.has_optional_argument_without_default_value %}
{# Count the effective number of arguments.  (arg1, arg2, undefined) is
   interpreted as two arguments are passed and (arg1, undefined, arg3) is
   interpreted as three arguments are passed. #}
int numArgsPassed = info.Length();
while (numArgsPassed > 0) {
  if (!info[numArgsPassed - 1]->IsUndefined())
    break;
  --numArgsPassed;
}
{% endif %}
{% for argument in method.arguments %}
{% if argument.set_default_value %}
if (!info[{{argument.index}}]->IsUndefined()) {
  {{generate_argument(method, argument, world_suffix) | trim | indent(2)}}
} else {
  {{argument.set_default_value | trim | indent(2)}};
}
{% else %}
{{generate_argument(method, argument, world_suffix)}}
{% endif %}
{% endfor %}

{% endif %}{# method.arguments #}
{% endmacro %}


{######################################}
{% macro generate_argument(method, argument, world_suffix) %}
{% if argument.is_optional_without_default_value %}
{# Optional arguments without a default value generate an early call with
   fewer arguments if they are omitted.
   Optional Dictionary arguments default to empty dictionary. #}
if (UNLIKELY(numArgsPassed <= {{argument.index}})) {
  {% if world_suffix %}
  {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argument.cpp_value) | trim | indent(2)}}
  {% else %}
  {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | trim | indent(2)}}
  {% endif %}
  return;
}
{% endif %}
{% if argument.is_callback_interface %}
{# FIXME: remove EventListener special case. crbug.com/630986 #}
{% if argument.idl_type == 'EventListener' %}
if (!IsUndefinedOrNull(info[{{argument.index}}]) && !info[{{argument.index}}]->IsObject()) {
  {{throw_argument_error(method, argument, "The callback provided as parameter %(index)d is not an object.")}}
  return;
}
{% if method.name == 'removeEventListener' or method.name == 'removeListener' %}
{{argument.name}} = V8EventListenerHelper::GetEventListener(ScriptState::Current(info.GetIsolate()), info[{{argument.index}}], false, kListenerFindOnly);
{% else %}{# method.name == 'AddEventListener' #}
{{argument.name}} = V8EventListenerHelper::GetEventListener(ScriptState::Current(info.GetIsolate()), info[{{argument.index}}], false, kListenerFindOrCreate);
{% endif %}{# method.name #}
{% else %}{# argument.idl_type == 'EventListener' #}
if (info[{{argument.index}}]->IsObject()) {
  {{argument.name}} = V8{{argument.idl_type}}::Create(info[{{argument.index}}].As<v8::Object>());
{% if argument.is_nullable %}
} else if (info[{{argument.index}}]->IsNullOrUndefined()) {
  {{argument.name}} = nullptr;
{% elif argument.is_optional %}
} else if (info[{{argument.index}}]->IsUndefined()) {
  {{argument.name}} = nullptr;
{% endif %}
} else {
  {{throw_argument_error(method, argument, "The callback provided as parameter %(index)d is not an object.")}}
  return;
}
{% endif %}{# argument.idl_type == 'EventListener' #}
{% elif argument.is_callback_function %}
if (info[{{argument.index}}]->IsFunction()) {
  {{v8_value_to_local_cpp_value(argument)}}
{% if argument.is_nullable %}
} else if (info[{{argument.index}}]->IsNullOrUndefined()) {
  {{argument.name}} = nullptr;
{% elif argument.is_optional %}
} else if (info[{{argument.index}}]->IsUndefined()) {
  {{argument.name}} = nullptr;
{% endif %}
} else {
  {{throw_argument_error(method, argument, "The callback provided as parameter %(index)d is not a function.")}}
  return;
}
{% elif argument.is_variadic_wrapper_type %}
for (int i = {{argument.index}}; i < info.Length(); ++i) {
  if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) {
    {{throw_argument_error(method, argument, "parameter %(index)d is not of type '%(type)s'.")}}
    return;
  }
  {{argument.name}}.push_back(V8{{argument.idl_type}}::ToImpl(v8::Local<v8::Object>::Cast(info[i])));
}
{% elif argument.is_dictionary %}
{% if not argument.use_permissive_dictionary_conversion %}
{# Dictionaries must have type Undefined, Null or Object:
   http://heycam.github.io/webidl/#es-dictionary #}
if (!info[{{argument.index}}]->IsNullOrUndefined() && !info[{{argument.index}}]->IsObject()) {
  {{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
  return;
}
{% endif %}{# not argument.use_permissive_dictionary_conversion #}
{{v8_value_to_local_cpp_value(argument)}}
{% elif argument.is_explicit_nullable %}
if (!info[{{argument.index}}]->IsNullOrUndefined()) {
  {{v8_value_to_local_cpp_value(argument) | trim | indent(2)}}
}
{% else %}{# argument is something else #}
{{v8_value_to_local_cpp_value(argument)}}
{% endif %}{# end of the dispatch by the argument type #}
{# Type checking, possibly throw a TypeError, per:
   http://www.w3.org/TR/WebIDL/#es-type-mapping #}
{% if argument.has_type_checking_interface and not argument.is_variadic_wrapper_type %}
{# Type checking for wrapper interface types (if interface not implemented,
   throw a TypeError), per http://www.w3.org/TR/WebIDL/#es-interface
   Note: for variadic arguments, the type checking is done for each matched
   argument instead; see argument.is_variadic_wrapper_type code-path above. #}
if (!{{argument.name}}{% if argument.is_nullable %} && !IsUndefinedOrNull(info[{{argument.index}}]){% endif %}) {
  {{throw_argument_error(method, argument, "parameter %(index)d is not of type '%(type)s'.")}}
  return;
}
{% elif argument.enum_values %}
{# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
{% set enum_variable = 'valid' + argument.name[0].upper() + argument.name[1:] + 'Values' %}
{{declare_enum_validation_variable(argument.enum_values, enum_variable)}}
if (!IsValidEnum({{argument.name}}, {{enum_variable}}, base::size({{enum_variable}}), "{{argument.enum_type}}", exceptionState)) {
  return;
}
{% elif argument.idl_type == 'Promise' %}
{# We require this for our implementation of promises, though not in spec:
http://heycam.github.io/webidl/#es-promise #}
if (!{{argument.name}}.IsUndefinedOrNull() && !{{argument.name}}.IsObject()) {
  {{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
  return;
}
{% endif %}
{% endmacro %}


{######################################}
{% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
{% if method.is_custom_call_prologue %}
{{v8_class}}::{{method.name}}MethodPrologueCustom(info, impl);
{% endif %}
{# Local variables #}
{% if method.is_call_with_execution_context %}
{# [ConstructorCallWith=ExecutionContext] or [CallWith=ExecutionContext] #}
{% if method.is_constructor %}
ExecutionContext* executionContext = ToExecutionContext(
    info.NewTarget().As<v8::Object>()->CreationContext());
{% elif method.is_static %}
ExecutionContext* executionContext = ExecutionContext::ForCurrentRealm(info);
{% else %}
ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info);
{% endif %}
{% endif %}
{% if method.is_call_with_script_arguments %}
{# [CallWith=ScriptArguments] #}
ScriptArguments* scriptArguments(ScriptArguments::Create(scriptState, info, {{method.number_of_arguments}}));
{% endif %}
{% if method.is_call_with_document %}
{# [ConstructorCallWith=Document] #}
Document& document = *ToDocument(ToExecutionContext(
    info.NewTarget().As<v8::Object>()->CreationContext()));
{% endif %}
{# Call #}
{% if method.idl_type == 'void' %}
{{cpp_value}};
{% elif method.use_output_parameter_for_result %}
{{method.cpp_type}} result;
{{cpp_value}};
{% elif method.is_constructor %}
{{method.cpp_type}} impl = {{cpp_value}};
{% elif method.use_local_result %}
{{method.cpp_type}} result = {{cpp_value}};
{% endif %}
{# Post-call #}
{% if method.is_raises_exception %}
if (exceptionState.HadException()) {
  return;
}
{% endif %}
{# Set return value #}
{% if method.is_new_object and not method.do_not_test_new_object %}
{% if not method.returns_promise %}
{# We currently only add the DCHECK for IDL interfaces. Even though #}
{# [NewObject] also applies to promises, there is nothing for us to check at #}
{# the moment. #}
// [NewObject] must always create a new wrapper.  Check that a wrapper
// does not exist yet.
DCHECK(!result || DOMDataStore::GetWrapper(result, info.GetIsolate()).IsEmpty());
{% endif %}{# not method.returns_promise #}
{% endif %}
{% if method.is_constructor %}
{{generate_constructor_wrapper(method)}}
{%- elif v8_set_return_value %}
{% if method.is_explicit_nullable %}
if (!result)
  V8SetReturnValueNull(info);
else
  {{v8_set_return_value}};
{% else %}
{{v8_set_return_value}};
{% endif %}
{%- endif %}{# None for void #}
{% if method.is_custom_call_epilogue %}
{{v8_class}}::{{method.name}}MethodEpilogueCustom(info, impl);
{% endif %}
{% endmacro %}


{##############################################################################}
{% macro throw_type_error(method, error_message) %}
{% if method.has_exception_state or method.returns_promise %}
exceptionState.ThrowTypeError({{error_message}});
{%- elif method.is_constructor %}
V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToConstruct("{{interface_name}}", {{error_message}}));
{%- else %}
V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}));
{%- endif %}
{%- endmacro %}


{##############################################################################}
{% macro throw_argument_error(method, argument, error_message) %}
{% set quoted_message = '"%s"' % (error_message | replace('\"', '\\\"')) %}
{{throw_type_error(method, quoted_message | format(index=(argument.index + 1), name=argument.name, type=argument.idl_type))}}
{%- endmacro %}


{##############################################################################}
{% macro runtime_determined_length_method(overloads) %}
static int {{overloads.name}}MethodLength() {
  {% for length, runtime_enabled_features in overloads.runtime_determined_lengths %}
  {% for runtime_enabled_feature in runtime_enabled_features %}
  {% filter runtime_enabled(runtime_enabled_feature) %}
  return {{length}};
  {% endfilter %}
  {% endfor %}
  {% endfor %}
}
{% endmacro %}


{##############################################################################}
{% macro runtime_determined_maxarg_method(overloads) %}
static int {{overloads.name}}MethodMaxArg() {
  {% for length, runtime_enabled_features in overloads.runtime_determined_maxargs %}
  {% for name in runtime_enabled_features %}
  {% filter runtime_enabled(name) %}
  return {{length}};
  {% endfilter %}
  {% endfor %}
  {% endfor %}
}
{% endmacro %}


{##############################################################################}
{% macro overload_resolution_method(overloads, world_suffix) %}
static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
  {% set fall_through_to_partial_overloads = not is_partial and overloads.has_partial_overloads %}

  {% if overloads.measure_all_as %}
  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.measure_all_as}});
  {% endif %}
  {% if overloads.deprecate_all_as %}
  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.deprecate_all_as}});
  {% endif %}

  {# First resolve by length #}
  {% if not fall_through_to_partial_overloads %}
  bool isArityError = false;
  {% endif %}

  {# This follows the overload resolution algorithm. #}
  {# https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm #}
  {# 3. Initialize argcount to be min(maxarg, n). #}
  switch (std::min({{overloads.maxarg}}, info.Length())) {
    {# 4. Remove from S all entries whose type list is not of length argcount. #}
    {% for length, tests_methods in overloads.length_tests_methods %}
    {# 12. If i = d, then: #}
    case {{length}}:
      {# Then resolve by testing argument #}
      {% for test, method in tests_methods %}
      {% if method.visible %}
      {% filter runtime_enabled(not overloads.runtime_enabled_all and method.runtime_enabled_feature_name) %}
      {% if "exceptionState" in test %}
      {
        ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext,
                                      "{{interface_name}}", "{{overloads.name}}");
        {{ test_and_call_overloaded_method(test, method, overloads, world_suffix) | trim | indent(8) }}
        if (exceptionState.HadException()) {
          exceptionState.RethrowV8Exception(exceptionState.GetException());
          return;
        }
      }
      {% else %}{# exceptionState #}
      {{ test_and_call_overloaded_method(test, method, overloads, world_suffix) | trim | indent(6) }}
      {% endif %}{# exceptionState #}
      {% endfilter %}
      {% endif %}
      {% endfor %}
      break;
    {% endfor %}{# length, tests_methods #}
    {% if not fall_through_to_partial_overloads %}
    default:
      {# 12.19. Otherwise: throw a TypeError. #}
      isArityError = true;
    {% endif %}
  }

  {% if fall_through_to_partial_overloads %}
  DCHECK({{overloads.name}}MethodForPartialInterface);
  ({{overloads.name}}MethodForPartialInterface)(info);
  {% else %}{# fall_through_to_partial_overloads #}
  ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "{{interface_name}}", "{{overloads.name}}");
  {% if overloads.returns_promise_all %}
  ExceptionToRejectPromiseScope rejectPromiseScope(info, exceptionState);
  {% endif %}
  if (isArityError) {
    {% if overloads.length != 0 %}
    if (info.Length() < {{overloads.length}}) {
      exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{overloads.length}}, info.Length()));
      return;
    }
    {% endif %}
    {% if overloads.valid_arities %}
    if (info.Length() >= {{overloads.length}}) {
      exceptionState.ThrowTypeError(ExceptionMessages::InvalidArity("{{overloads.valid_arities}}", info.Length()));
      return;
    }
    {% endif %}
  }
  exceptionState.ThrowTypeError("No function was found that matched the signature provided.");
  {% endif %}{# fall_through_to_partial_overloads #}
}
{% endmacro %}

{% macro test_and_call_overloaded_method(test, method, overloads, world_suffix) %}
if ({{test}}) {
  {% if method.measure_as and not overloads.measure_all_as %}
  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}});
  {% endif %}
  {% if method.deprecate_as and not overloads.deprecate_all_as %}
  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
  {% endif %}
  {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
  return;
}
{% endmacro %}


{##############################################################################}
{% macro generate_post_message_impl(method) %}
static void postMessageImpl(const char* interfaceName, {{cpp_class}}* instance, const v8::FunctionCallbackInfo<v8::Value>& info) {
  ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, interfaceName, "postMessage");
  if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
    exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{method.number_of_required_arguments}}, info.Length()));
    return;
  }

  Transferables transferables;
  if (info.Length() > 1) {
    const int transferablesArgIndex = 1;
    if (!SerializedScriptValue::ExtractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, transferables, exceptionState)) {
      return;
    }
  }

  scoped_refptr<SerializedScriptValue> message;
  if (instance->CanTransferArrayBuffersAndImageBitmaps()) {
    // This instance supports sending array buffers by move semantics.
    SerializedScriptValue::SerializeOptions options;
    options.transferables = &transferables;
    message = SerializedScriptValue::Serialize(info.GetIsolate(), info[0], options, exceptionState);
    if (exceptionState.HadException())
      return;
  } else {
    // This instance doesn't support sending array buffers and image bitmaps
    // by move semantics. Emulate it by copy-and-neuter semantics that sends
    // array buffers and image bitmaps via structured clone and then neuters
    // the original objects

    // Clear references to array buffers and image bitmaps from transferables
    // so that the serializer can consider the array buffers as
    // non-transferable and serialize them into the message.
    ArrayBufferArray transferableArrayBuffers = SerializedScriptValue::ExtractNonSharedArrayBuffers(transferables);
    ImageBitmapArray transferableImageBitmaps = transferables.image_bitmaps;
    transferables.image_bitmaps.clear();
    SerializedScriptValue::SerializeOptions options;
    options.transferables = &transferables;
    message = SerializedScriptValue::Serialize(info.GetIsolate(), info[0], options, exceptionState);
    if (exceptionState.HadException())
      return;

    // Neuter the original array buffers on the sender context.
    SerializedScriptValue::TransferArrayBufferContents(info.GetIsolate(), transferableArrayBuffers, exceptionState);
    if (exceptionState.HadException())
      return;
    // Neuter the original image bitmaps on the sender context.
    SerializedScriptValue::TransferImageBitmapContents(info.GetIsolate(), transferableImageBitmaps, exceptionState);
    if (exceptionState.HadException())
      return;
  }

  // FIXME: Only pass scriptState/exceptionState if instance really requires it.
  ScriptState* scriptState = ScriptState::Current(info.GetIsolate());
  message->UnregisterMemoryAllocatedWithCurrentScriptContext();
  instance->postMessage(scriptState, std::move(message), transferables.message_ports, exceptionState);
}
{% endmacro %}


{##############################################################################}
{% macro method_callback(method, world_suffix) %}
void {{v8_class_or_partial}}::{{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
  {% if method.runtime_call_stats.extended_attribute_defined %}
  {{ runtime_timer_scope(method.runtime_call_stats.method_counter) | trim | indent(2) }}
  {% else %}
  {{ runtime_timer_scope_disabled_by_default(method.runtime_call_stats.method_counter) }}
  {% endif %}
  {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #}
  {% if method.measure_as %}
  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}});
  {% endif %}
  {% if method.deprecate_as %}
  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
  {% endif %}
  {% endif %}{# not method.overloads #}
  {% if world_suffix in method.activity_logging_world_list %}
  {% if method.is_static %}
  ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
  {% else %}
  ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
  {% endif %}
  V8PerContextData* contextData = scriptState->PerContextData();
  if (contextData && contextData->ActivityLogger()) {
    contextData->ActivityLogger()->LogMethod("{{interface_name}}.{{method.name}}", info);
  }
  {% endif %}
  {% if method.is_custom %}
  {{v8_class}}::{{method.name}}MethodCustom(info);
  {% elif method.is_post_message %}
  {{cpp_class_or_partial}}V8Internal::postMessageImpl("{{interface_name}}", {{v8_class}}::ToImpl(info.Holder()), info);
  {% else %}
  {{cpp_class_or_partial}}V8Internal::{{method.name}}Method{{world_suffix}}(info);
  {% endif %}
}
{% endmacro %}


{##############################################################################}
{% macro origin_safe_method_getter(method, world_suffix) %}
{# TODO(dcheng): Currently, bindings must create a function object for each
   realm as a hack to support the incumbent realm. Clean this up when Blink
   properly supports the incumbent realm. #}
static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info) {
  static int domTemplateKey; // This address is used for a key to look up the dom template.
  V8PerIsolateData* data = V8PerIsolateData::From(info.GetIsolate());
  const DOMWrapperWorld& world = DOMWrapperWorld::World(info.GetIsolate()->GetCurrentContext());
  v8::Local<v8::FunctionTemplate> interfaceTemplate = data->FindInterfaceTemplate(world, &{{v8_class}}::wrapperTypeInfo);
  v8::Local<v8::Signature> signature = v8::Signature::New(info.GetIsolate(), interfaceTemplate);

  v8::Local<v8::FunctionTemplate> methodTemplate = data->FindOrCreateOperationTemplate(world, &domTemplateKey, {{v8_class_or_partial}}::{{method.name}}MethodCallback{{world_suffix}}, V8Undefined(), signature, {{method.length}});
  // Return the function by default, unless the user script has overwritten it.
  V8SetReturnValue(info, methodTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());

  {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
  if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), impl, BindingSecurity::ErrorReportOption::kDoNotReport)) {
    return;
  }

  {% raw %}
  // {{method.name}} must be same with |methodName| (=name) in
  // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl.
  {% endraw %}
  V8PrivateProperty::Symbol propertySymbol =
      V8PrivateProperty::GetSymbol(info.GetIsolate(), "{{method.name}}");
  v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder());
  if (propertySymbol.HasValue(holder)) {
    V8SetReturnValue(info, propertySymbol.GetOrUndefined(holder));
  }
}
{% endmacro %}

{% macro origin_safe_method_getter_callback(method, world_suffix) %}
void {{v8_class_or_partial}}::{{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
  {{ runtime_timer_scope_disabled_by_default(method.runtime_call_stats.origin_safe_method_getter_counter) }}
  {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix}}(info);
}
{% endmacro %}


{##############################################################################}
{% macro generate_constructor(constructor) %}
{% set name = '%sConstructorCallback' % v8_class
              if constructor.is_named_constructor else
              'constructor%s' % (constructor.overload_index or '') %}
static void {{name}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
  {{ runtime_timer_scope_disabled_by_default(constructor.rcs_counter) }}
  {% set function_call = func_call_with_prep_of_args(constructor) %}

  {% if constructor.is_named_constructor %}
  if (!info.IsConstructCall()) {
    V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::ConstructorNotCallableAsFunction("{{constructor.name}}"));
    return;
  }

  if (ConstructorMode::Current(info.GetIsolate()) == ConstructorMode::kWrapExistingObject) {
    V8SetReturnValue(info, info.Holder());
    return;
  }
  {% endif %}

  {% if 'exceptionState' in function_call %}
  ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}");
  {% endif %}
  {% if 'scriptState' in function_call %}
  ScriptState* scriptState = ScriptState::From(
      info.NewTarget().As<v8::Object>()->CreationContext());
  {% endif %}

  {{function_call | trim | indent(2)}}
}
{% endmacro %}


{##############################################################################}
{% macro generate_constructor_wrapper(constructor) %}
{% set constructor_class = v8_class + ('Constructor'
                                       if constructor.is_named_constructor else
                                       '') %}
v8::Local<v8::Object> wrapper = info.Holder();
wrapper = impl->AssociateWithWrapper(info.GetIsolate(), &{{constructor_class}}::wrapperTypeInfo, wrapper);
V8SetReturnValue(info, wrapper);
{% endmacro %}


{##############################################################################}
{% macro method_configuration(method) %}
{% from 'utilities.cpp.tmpl' import property_location %}
{% set method_callback =
       '%s::%sMethodCallback' % (v8_class_or_partial, method.name) %}
{% set method_callback_for_main_world =
       '%s::%sMethodCallbackForMainWorld' % (v8_class_or_partial, method.name)
       if method.is_per_world_bindings else 'nullptr' %}
{% set property_attribute =
       'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(method.property_attributes)
       if method.property_attributes else 'v8::None' %}
{% set holder_check = 'V8DOMConfiguration::kDoNotCheckHolder'
       if method.returns_promise else 'V8DOMConfiguration::kCheckHolder' %}
{% set access_check = 'V8DOMConfiguration::kCheckAccess'
       if method.is_check_security_for_receiver else 'V8DOMConfiguration::kDoNotCheckAccess' %}
{% if method.is_per_world_bindings %}
{% set method_callback_for_main_world =
       '%s::%sMethodCallbackForMainWorld' % (v8_class_or_partial, method.name) %}
{"{{method.name}}", {{method_callback_for_main_world}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kMainWorld},
{"{{method.name}}", {{method_callback}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kNonMainWorlds}
{%- else %}
{"{{method.name}}", {{method_callback}}, {{method.length}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, {{access_check}}, {{method.side_effect_type}}, V8DOMConfiguration::kAllWorlds}
{%- endif %}
{%- endmacro %}


{######################################}
{% macro install_custom_signature(method, instance_template, prototype_template, interface_template, signature) %}
const V8DOMConfiguration::MethodConfiguration {{method.name}}MethodConfiguration[] = {
  {{method_configuration(method) | trim | indent(2)}}
};
for (const auto& methodConfig : {{method.name}}MethodConfiguration)
  V8DOMConfiguration::InstallMethod(isolate, world, {{instance_template}}, {{prototype_template}}, {{interface_template}}, {{signature}}, methodConfig);
{%- endmacro %}


{######################################}
{% macro install_conditional_methods() %}
{% for method in conditional_methods %}
{% filter secure_context(method.overloads.secure_context_test_all
                         if method.overloads else
                         method.secure_context_test) %}
{% filter exposed(method.overloads.exposed_test_all
                  if method.overloads else
                  method.exposed_test) %}
{% filter runtime_enabled(method.overloads.runtime_enabled_all
                          if method.overloads else
                          method.runtime_enabled_feature_name) %}
const V8DOMConfiguration::MethodConfiguration {{method.name}}MethodConfiguration[] = {
  {{method_configuration(method) | trim | indent(2)}}
};
for (const auto& methodConfig : {{method.name}}MethodConfiguration)
  V8DOMConfiguration::InstallMethod(isolate, world, v8::Local<v8::Object>(), prototypeObject, interfaceObject, signature, methodConfig);
{% endfilter %}{# runtime_enabled() #}
{% endfilter %}{# exposed() #}
{% endfilter %}{# secure_context() #}
{% endfor %}
{%- endmacro %}
