{#
 # Copyright 2017 The Cobalt Authors. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
 #     http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #}

{% from 'macros.cc.template' import add_extra_arguments %}
{% from 'macros.cc.template' import call_cobalt_function %}
{% from 'macros.cc.template' import check_if_object_implements_interface with context %}
{% from 'macros.cc.template' import constructor_implementation with context %}
{% from 'macros.cc.template' import function_implementation with context %}
{% from 'macros.cc.template' import get_impl_class_instance %}
{% from 'macros.cc.template' import nonstatic_function_prologue %}
{% from 'macros.cc.template' import overload_resolution_implementation with context %}
{% from 'macros.cc.template' import set_attribute_implementation with context %}
{% from 'macros.cc.template' import static_function_prologue %}

{% extends "interface-base.cc.template" %}

{% block includes %}
{{ super() }}
#include "{{generated_conversion_include}}"

#include "cobalt/script/callback_interface_traits.h"
#include "cobalt/script/v8c/v8c_array_buffer.h"
#include "cobalt/script/v8c/v8c_array_buffer_view.h"
#include "cobalt/script/v8c/callback_function_conversion.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
#include "cobalt/script/v8c/helpers.h"
#include "cobalt/script/v8c/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_typed_arrays.h"
#include "cobalt/script/v8c/v8c_data_view.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_engine.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "cobalt/script/v8c/v8c_property_enumerator.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"

{% endblock includes %}

{% block using_directives %}
{{ super() }}
using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
using cobalt::script::v8c::kConversionFlagClamped;
using cobalt::script::v8c::kConversionFlagNullable;
using cobalt::script::v8c::kConversionFlagObjectOnly;
using cobalt::script::v8c::kConversionFlagRestricted;
using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
using cobalt::script::v8c::kNoConversionFlags;
using cobalt::script::v8c::NewInternalString;
using cobalt::script::v8c::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
using cobalt::script::v8c::V8cPropertyEnumerator;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;
{% endblock using_directives %}

{% block enumeration_declarations %}
{% if enumerations|length %}
// Declare and define these in the same namespace that the other overloads
// were brought into with the using declaration.
{% for enumeration in enumerations %}
void ToJSValue(
    v8::Isolate* isolate,
    {{impl_class}}::{{enumeration.name}} in_enum,
    v8::Local<v8::Value>* out_value);
void FromJSValue(v8::Isolate* context, v8::Local<v8::Value> value,
                 int conversion_flags, ExceptionState* exception_state,
                 {{impl_class}}::{{enumeration.name}}* out_enum);
{% endfor %}
{% endif %}
{% endblock enumeration_declarations %}

{% block top_level_unnamed_namespace %}
{% endblock top_level_unnamed_namespace %}

{% block implementation %}

namespace {

const int kInterfaceUniqueId = {{unique_id}};

{% if named_property_getter %}

void NamedPropertyGetterCallback(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  std::string property_name = *v8::String::Utf8Value(isolate, property);
  if (!impl->CanQueryNamedProperty(property_name)) {
    return;
  }
{{ call_cobalt_function(impl_class, named_property_getter.type,
                        named_property_getter.name, ["property_name"],
                        named_property_getter.raises_exception,
                        named_property_getter.call_with) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(result_value);
}

{% if not indexed_property_getter %}
void IndexedPropertyGetterCallback(
    uint32_t index,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString();
  NamedPropertyGetterCallback(as_string, info);
}
{% endif %}

void NamedPropertyQueryCallback(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Integer>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ get_impl_class_instance(impl_class) }}
  std::string property_name = *v8::String::Utf8Value(isolate, property);
  bool result = impl->CanQueryNamedProperty(property_name);
  if (!result) {
    return;
  }

  // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
  int properties = v8::None;
  // 2.7. If |O| implements an interface with a named property setter, then set
  //      desc.[[Writable]] to true, otherwise set it to false.
{% if named_property_setter %}
{% else %}
  properties |= v8::ReadOnly;
{% endif %}
  // 2.8. If |O| implements an interface with the
  //      [LegacyUnenumerableNamedProperties] extended attribute, then set
  //      desc.[[Enumerable]] to false, otherwise set it to true.
{% if has_legacy_unenumerable_named_properties %}
  // TODO: Note that this is never true at the moment, as Cobalt's IDLs and
  // IDL compiler do not support this.
  properties |= v8::DontEnum;
{% endif %}

  info.GetReturnValue().Set(properties);
}

{% if not indexed_property_getter %}
void IndexedPropertyDescriptorCallback(
    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
  // TODO: Figure out under what conditions this gets called.  It's not
  // getting called in our tests.
  NOTIMPLEMENTED();
}
{% endif %}

void NamedPropertyEnumeratorCallback(
    const v8::PropertyCallbackInfo<v8::Array>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ get_impl_class_instance(impl_class) }}
  v8::Local<v8::Array> array = v8::Array::New(isolate);
  V8cPropertyEnumerator property_enumerator(isolate, &array);
  impl->EnumerateNamedProperties(&property_enumerator);
  info.GetReturnValue().Set(array);
}

{% endif %}

{% if named_property_setter %}
void NamedPropertySetterCallback(
    v8::Local<v8::Name> property,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  std::string property_name = *v8::String::Utf8Value(isolate, property);
  TypeTraits<{{named_property_setter.type}}>::ConversionType native_value;
  FromJSValue(isolate, value, {{named_property_setter.conversion_flags}},
              &exception_state, &native_value);
  if (exception_state.is_exception_set()) {
    return;
  }
{{ call_cobalt_function(impl_class, "void",
                        named_property_setter.name, ["property_name", "native_value"],
                        named_property_setter.raises_exception,
                        named_property_setter.call_with) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(value);
}

{% if not indexed_property_setter %}
void IndexedPropertySetterCallback(
    uint32_t index,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString();
  NamedPropertySetterCallback(as_string, value, info);
}
{% endif %}

{% endif %}

{% if named_property_deleter %}
void NamedPropertyDeleterCallback(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  std::string property_name = *v8::String::Utf8Value(isolate, property);
  if (!impl->CanQueryNamedProperty(property_name)) {
    return;
  }
{{ call_cobalt_function(impl_class, "void",
                        named_property_deleter.name, ["property_name"],
                        named_property_deleter.raises_exception,
                        named_property_deleter.call_with) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(true);
}

{% if not indexed_property_deleter %}
void IndexedPropertyDeleterCallback(
    uint32_t index,
    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString();
  NamedPropertyDeleterCallback(as_string, info);
}
{% endif %}

{% endif %}

{% if indexed_property_getter %}

void IndexedPropertyGetterCallback(
    uint32_t index,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  if (index >= impl->length()) {
    // |index| is out of bounds, so return undefined.
    return;
  }
{{ call_cobalt_function(impl_class, indexed_property_getter.type,
                        indexed_property_getter.name, ["index"],
                        indexed_property_getter.raises_exception,
                        indexed_property_getter.call_with) }}
  info.GetReturnValue().Set(result_value);
}

void IndexedPropertyDescriptorCallback(
    uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
  // TODO: Figure out under what conditions this gets called.  It's not
  // getting called in our tests.
  NOTIMPLEMENTED();
}

void IndexedPropertyEnumeratorCallback(
    const v8::PropertyCallbackInfo<v8::Array>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ get_impl_class_instance(impl_class) }}
  const uint32_t length = impl->length();
  v8::Local<v8::Array> array = v8::Array::New(isolate, length);
  for (uint32_t i = 0; i < length; ++i) {
    array->Set(i, v8::Integer::New(isolate, i));
  }
  info.GetReturnValue().Set(array);
}

void IndexedPropertyDefinerCallback(
    uint32_t index, const v8::PropertyDescriptor& desc,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  // TODO: Figure out under what conditions this gets called.  It's not
  // getting called in our tests.
  NOTIMPLEMENTED();
}

{% endif %}

{% if indexed_property_setter %}
void IndexedPropertySetterCallback(
    uint32_t index,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  if (index >= impl->length()) {
    return;
  }
  TypeTraits<{{indexed_property_setter.type}}>::ConversionType native_value;
  FromJSValue(isolate, value, {{indexed_property_setter.conversion_flags}},
              &exception_state, &native_value);
  if (exception_state.is_exception_set()) {
    return;
  }
{{ call_cobalt_function(impl_class, "void",
                        indexed_property_setter.name, ["index", "native_value"],
                        indexed_property_setter.raises_exception,
                        indexed_property_setter.call_with) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(value);
}
{% endif %}

{% if indexed_property_deleter %}
void IndexedPropertyDeleterCallback(
    uint32_t index,
    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
{{ nonstatic_function_prologue(impl_class) }}
  if (index >= impl->length()) {
    return;
  }
{{ call_cobalt_function(impl_class, "void",
                        indexed_property_deleter.name, ["index"],
                        indexed_property_deleter.raises_exception,
                        indexed_property_deleter.call_with) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(v8::Boolean::New(isolate, true));
}
{% endif %}

{% if constructor %}

{% for overload in constructor.overloads if constructor.overloads|length > 1 %}
void Constructor{{overload.overload_index}}(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
{{ constructor_implementation(overload) -}}
}
{% endfor %}

void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
{% if constructor.overloads|length == 1 %}
  v8::Isolate* isolate = info.GetIsolate();
{{ constructor_implementation(constructor.overloads[0]) -}}
{% else %}
{{ overload_resolution_implementation(constructor, "Constructor")}}
{% endif %}
}

{% else %}

void DummyConstructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
  V8cExceptionState exception(info.GetIsolate());
  exception.SetSimpleException(
      script::kTypeError, "{{interface_name}} is not constructible.");
}

{% endif %}

{% for attribute in attributes + static_attributes %}
{% if attribute.conditional %}
#if defined({{attribute.conditional}})
{% endif %}

{% if attribute.is_constructor_attribute %}
// Nothing for {{attribute}}.  We will just give them the v8::FunctionTemplate.
{% else %}
void {{attribute.idl_name}}AttributeGetter(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();

{% if attribute.is_static %}
{{ static_function_prologue() -}}
{% endif %}

{% if not attribute.is_static %}
{{ check_if_object_implements_interface() }}
{{ nonstatic_function_prologue(impl_class) }}
{% endif %}

{{ call_cobalt_function(impl_class, attribute.type,
                        attribute.getter_function_name, [],
                        attribute.raises_exception, attribute.call_with,
                        attribute.is_static) }}
  if (exception_state.is_exception_set()) {
    return;
  }
  info.GetReturnValue().Set(result_value);
}

{% if attribute.has_setter %}
void {{attribute.idl_name}}AttributeSetter(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
  v8::Local<v8::Value> v8_value = info[0];

{% if attribute.is_static %}
{{ static_function_prologue() }}
{% else %}
{{ check_if_object_implements_interface() }}
{{ nonstatic_function_prologue(impl_class)}}
{% endif %} {#- attribute.is_static #}
{{ set_attribute_implementation(attribute, impl_class) -}}
}
{% endif %} {#- attribute.has_setter #}

{% endif %}
{% if attribute.conditional %}
#endif  // {{attribute.conditional}}
{% endif %} {#- attribute.is_constructor_attribute #}
{% endfor %} {#- for attribute in attributes + static_attributes #}

{%- for operation in operations + static_operations %}
{% if operation.conditional %}
#if defined({{operation.conditional}})
{% endif %}
{% set boundFunctionSuffix = "StaticMethod" if operation.is_static else "Method" %}

{% for overload in operation.overloads if operation.overloads|length > 1 %}
void {{operation.idl_name}}{{boundFunctionSuffix}}{{overload.overload_index}}(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
{{ function_implementation(overload) -}}
}
{% endfor %}

void {{operation.idl_name}}{{boundFunctionSuffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
{% if operation.overloads|length == 1 %}
{{ function_implementation(operation.overloads[0]) -}}
{% else %}
{{ overload_resolution_implementation(operation, operation.idl_name + boundFunctionSuffix) }}
{% endif %}
}

{% if operation.conditional %}
#endif  // {{operation.conditional}}
{% endif %}
{% endfor %}

{% if stringifier %}
void Stringifier(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.Holder();
  V8cExceptionState exception_state(isolate);

  {{ check_if_object_implements_interface() }}

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);

  // |WrapperPrivate::GetFromObject| can fail if |object| is not a |Wrapper|
  // object.
  if (!wrapper_private) {
    exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
    return;
  }

  {{impl_class}}* impl =
      wrapper_private->wrappable<{{impl_class}}>().get();
  if (!impl) {
    exception_state.SetSimpleException(cobalt::script::kStringifierProblem);
    NOTREACHED();
    return;
  }
  std::string stringified = impl->{{stringifier.name}}();

  v8::Local<v8::Value> v8_stringified;
  ToJSValue(isolate, stringified, &v8_stringified);

  info.GetReturnValue().Set(v8_stringified);
}
{% endif %}

void InitializeTemplate(v8::Isolate* isolate) {
  // https://heycam.github.io/webidl/#interface-object
  // 3.6.1. Interface object
  //
  // The interface object for a given interface is a built-in function object.
  // It has properties that correspond to the constants and static operations
  // defined on that interface, as described in sections 3.6.6 Constants and
  // 3.6.8 Operations.
  //
  // If the interface is declared with a [Constructor] extended attribute,
  // then the interface object can be called as a constructor to create an
  // object that implements that interface. Calling that interface as a
  // function will throw an exception.
  //
  // Interface objects whose interfaces are not declared with a [Constructor]
  // extended attribute will throw when called, both as a function and as a
  // constructor.
  //
  // An interface object for a non-callback interface has an associated object
  // called the interface prototype object. This object has properties that
  // correspond to the regular attributes and regular operations defined on
  // the interface, and is described in more detail in 3.6.3 Interface
  // prototype object.
{% if constructor %}
  v8::Local<v8::FunctionTemplate> function_template =
      v8::FunctionTemplate::New(
          isolate,
          Constructor,
          v8::Local<v8::Value>(),
          v8::Local<v8::Signature>(),
          {{constructor.length}});
  function_template->SetLength({{constructor.length}});
{% else %}
  v8::Local<v8::FunctionTemplate> function_template =
      v8::FunctionTemplate::New(
          isolate,
          DummyConstructor,
          v8::Local<v8::Value>(),
          v8::Local<v8::Signature>(),
          0);
{% endif %}
  function_template->SetClassName(NewInternalString(isolate, "{{interface_name}}"));
  function_template->ReadOnlyPrototype();

  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
  instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  global_environment->AddInterfaceData(kInterfaceUniqueId, function_template);

{% if parent_interface %}
  {
    // An interface can be defined to inherit from another interface. If the
    // identifier of the interface is followed by a U+003A COLON (":") character
    // and an identifier, then that identifier identifies the inherited
    // interface. An object that implements an interface that inherits from
    // another also implements that inherited interface. The object therefore
    // will also have members that correspond to the interface members from the
    // inherited interface.
    v8::Local<v8::FunctionTemplate> parent_template = {{parent_interface}}::GetTemplate(isolate);
    function_template->Inherit(parent_template);
    static_assert(
        std::is_base_of<{{parent_interface_name}}, {{interface_name}}>::value,
        "Expected {{interface_name}} to have C++ parent class "
        "{{parent_interface_name}}, because that is its WebIDL parent.");
  }
{% elif is_exception_interface %}
  {
    // A spicy hack from Chromium in order to achieve
    // https://heycam.github.io/webidl/#es-DOMException-specialness
    // See https://cs.chromium.org/chromium/src/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl?l=630&rcl=0f7c2c752bb24ad08c17017e4e68401093fe76a0
    v8::Local<v8::FunctionTemplate> intrinsic_error_prototype_interface_template =
        v8::FunctionTemplate::New(isolate);
    intrinsic_error_prototype_interface_template->RemovePrototype();
    intrinsic_error_prototype_interface_template->SetIntrinsicDataProperty(
        NewInternalString(isolate, "prototype"), v8::kErrorPrototype);
    function_template->Inherit(intrinsic_error_prototype_interface_template);
  }
{% endif %}

  // https://heycam.github.io/webidl/#es-constants
  // 3.6.6. Constants
  //
  // For each exposed constant defined on an interface A, there must be a
  // corresponding property. The property has the following characteristics:
{% for constant in constants %}
  {
    // The name of the property is the identifier of the constant.
    v8::Local<v8::String> name = NewInternalString(
        isolate,
        "{{constant.idl_name}}");

    // The value of the property is that which is obtained by converting the
    // constant's IDL value to an ECMAScript value.
    v8::Local<v8::Value> constant_value;
    ToJSValue(isolate, {{constant.value}}, &constant_value);

    // The property has attributes { [[Writable]]: false, [[Enumerable]]: true,
    // [[Configurable]]: false }.
    v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
        v8::ReadOnly | v8::DontDelete);

    // The location of the property is determined as follows:
{% if is_global_interface %}
    // If the interface was declared with the [Global] extended attribute, then
    // the property exists on the single object that implements the interface.
    instance_template->Set(name, constant_value, attributes);

{% else %}
    // Otherwise, if the interface has an interface prototype object, then the
    // property exists on it.
    prototype_template->Set(name, constant_value, attributes);
{% endif %}

    // In addition, a property with the same characteristics must exist on the
    // interface object or the legacy callback interface object, if either of
    // those objects exists.
    function_template->Set(name, constant_value, attributes);
  }
{% endfor %}

  // https://heycam.github.io/webidl/#es-attributes
  // 3.6.7. Attributes
  //
  // For each exposed attribute of the interface there must exist a
  // corresponding property. The characteristics of this property are as
  // follows:
{% for attribute in all_attributes_v8_order_quirk %}
{% if attribute.conditional %}
#if defined({{attribute.conditional}})
{% endif %}
  {
    // The name of the property is the identifier of the attribute.
    v8::Local<v8::String> name = NewInternalString(
        isolate,
        "{{attribute.idl_name}}");

    // The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
    // true, [[Configurable]]: configurable }, where: configurable is false if
    // the attribute was declared with the [Unforgeable] extended attribute and
    // true otherwise;
    bool configurable = {{ "false" if attribute.is_unforgeable else "true"}};
    v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
        configurable ? v8::None : v8::DontDelete);

    // G is the attribute getter created given the attribute, the interface, and
    // the relevant Realm of the object that is the location of the property;
    // and
    //
    // S is the attribute setter created given the attribute, the interface, and
    // the relevant Realm of the object that is the location of the property.
{% if not attribute.is_constructor_attribute %}
    v8::Local<v8::FunctionTemplate> getter =
        v8::FunctionTemplate::New(isolate, {{attribute.idl_name}}AttributeGetter);
{% if attribute.has_setter %}
    v8::Local<v8::FunctionTemplate> setter =
        v8::FunctionTemplate::New(isolate, {{attribute.idl_name}}AttributeSetter);
{% else %}
    v8::Local<v8::FunctionTemplate> setter;
{% endif %}

    // The location of the property is determined as follows:
{% if attribute.on_interface %}
    // Operations installed on the interface object must be static methods, so
    // no need to specify a signature, i.e. no need to do type check against a
    // holder.

    // If the attribute is a static attribute, then there is a single
    // corresponding property and it exists on the interface's interface object.
    function_template->
{% elif attribute.on_instance %}
    // Otherwise, if the attribute is unforgeable on the interface or if the
    // interface was declared with the [Global] extended attribute, then the
    // property exists on every object that implements the interface.
    instance_template->
{% else %}
    // Otherwise, the property exists solely on the interface's interface
    // prototype object.
    prototype_template->
{% endif %}
        SetAccessorProperty(
            name,
            getter,
            setter,
            attributes);

{% else %} {#- not attribute.is_constructor_attribute #}
    {
      v8::Local<v8::String> name = NewInternalString(
          isolate,
          "{{attribute.idl_name}}");
      instance_template->Set(
          name,
{% if attribute.interface_name == interface_name %}
          function_template
{% else %}
          // Note that we use "attribute.interface_name", and not
          // "attribute.idl_name", because of named constructors.
          V8c{{attribute.interface_name}}::GetTemplate(isolate)
{% endif %}
      );
    }

{% endif %} {#- not attribute.is_constructor_attribute #}
  }
{% if attribute.conditional %}
#endif  // {{attribute.conditional}}
{% endif %}
{% endfor %}

  // https://heycam.github.io/webidl/#es-operations
  // 3.6.8. Operations
  //
  // For each unique identifier of an exposed operation defined on the
  // interface, there must exist a corresponding property, unless the effective
  // overload set for that identifier and operation and with an argument count
  // of 0 has no entries.
  //
  // The characteristics of this property are as follows:
{% for operation in operations + static_operations %}
{% if operation.conditional %}
#if defined({{operation.conditional}})
{% endif %}
  {
    // The name of the property is the identifier.
    v8::Local<v8::String> name = NewInternalString(
        isolate,
        "{{operation.idl_name}}");

    // The property has attributes { [[Writable]]: B, [[Enumerable]]: true,
    // [[Configurable]]: B }, where B is false if the operation is unforgeable
    // on the interface, and true otherwise.
    bool B = {{ "false" if operation.is_unforgeable else "true"}};
    v8::PropertyAttribute attributes = static_cast<v8::PropertyAttribute>(
        B ? v8::None : (v8::ReadOnly | v8::DontDelete));

    v8::Local<v8::FunctionTemplate> method_template =
        v8::FunctionTemplate::New(isolate, {{operation.idl_name}}{{"Static" if operation.is_static else ""}}Method);
    method_template->RemovePrototype();
    method_template->SetLength({{operation.length}});

    // The location of the property is determined as follows:
{% if operation.on_interface %}
    // If the operation is static, then the property exists on the interface
    // object.
    function_template->
{% elif operation.on_instance %}
    // Otherwise, if the operation is unforgeable on the interface or if the
    // interface was declared with the [Global] extended attribute, then the
    // property exists on every object that implements the interface.
    instance_template->
{% else %}
    // Otherwise, the property exists solely on the interface's interface
    // prototype object.
    prototype_template->
{% endif %}
        Set(name, method_template);

    // The value of the property is the result of creating an operation function
    // given the operation, the interface, and the relevant Realm of the object
    // that is the location of the property.

    // Note: that is, even if an includes statement was used to make an
    // operation available on the interface, we pass in the interface which
    // includes the interface mixin, and not the interface mixin on which the
    // operation was originally declared.
  }
{% if operation.conditional %}
#endif  // {{operation.conditional}}
{% endif %}
{% endfor %}

  // https://heycam.github.io/webidl/#es-stringifier
  // 3.6.8.2. Stringifiers
  prototype_template->Set(
      v8::Symbol::GetToStringTag(isolate),
      NewInternalString(isolate, "{{interface_name}}"),
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));

{% if stringifier %}
  {
    v8::Local<v8::String> name = NewInternalString(isolate, "toString");
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, Stringifier);
    prototype_template->Set(
      NewInternalString(isolate, "toString"),
      method_template);
  }
{% endif %}

{% if named_property_getter %}
  {
    v8::NamedPropertyHandlerConfiguration named_property_handler_configuration = {
      NamedPropertyGetterCallback,
      {{ "NamedPropertySetterCallback" if named_property_setter else "nullptr" }},
      NamedPropertyQueryCallback,
      {{ "NamedPropertyDeleterCallback" if named_property_deleter else "nullptr" }},
      NamedPropertyEnumeratorCallback,
      v8::Local<v8::Value>(),
      static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kNonMasking) | int(v8::PropertyHandlerFlags::kOnlyInterceptStrings))
    };
    instance_template->SetHandler(named_property_handler_configuration);
  }
{% endif %}

{% if named_property_getter and not indexed_property_getter %}
  {
    v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
      IndexedPropertyGetterCallback,
      {{ "IndexedPropertySetterCallback" if named_property_setter else "nullptr" }},
      IndexedPropertyDescriptorCallback,
      {{ "IndexedPropertyDeleterCallback" if named_property_deleter else "nullptr" }},
      nullptr,
      nullptr
    };
    instance_template->SetHandler(indexed_property_handler_configuration);
  }
{% endif %}

{% if indexed_property_getter %}
  {
    v8::IndexedPropertyHandlerConfiguration indexed_property_handler_configuration = {
      IndexedPropertyGetterCallback,
      {{ "IndexedPropertySetterCallback" if indexed_property_setter else "nullptr" }},
      IndexedPropertyDescriptorCallback,
      {{ "IndexedPropertyDeleterCallback" if indexed_property_deleter else "nullptr" }},
      IndexedPropertyEnumeratorCallback,
      IndexedPropertyDefinerCallback
    };
    instance_template->SetHandler(indexed_property_handler_configuration);
  }
{% endif %}

}

}  // namespace

{% if is_global_interface %}

// The global interface is special.  Just give them the global object proxy.
v8::Local<v8::Object> {{binding_class}}::CreateWrapper(
    v8::Isolate* isolate, const scoped_refptr<Wrappable>&) {
  return isolate->GetCurrentContext()->Global();
}

{% else %}

v8::Local<v8::Object> {{binding_class}}::CreateWrapper(
    v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable) {
  EscapableEntryScope entry_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
    InitializeTemplate(isolate);
  }
  v8::Local<v8::FunctionTemplate> function_template = global_environment->GetInterfaceData(kInterfaceUniqueId);

  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);
  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
  DCHECK(object->InternalFieldCount() == WrapperPrivate::kInternalFieldCount);

  // This |WrapperPrivate|'s lifetime will be managed by V8.
  new WrapperPrivate(isolate, wrappable, object);
  return entry_scope.Escape(object);
}

{% endif %}

v8::Local<v8::FunctionTemplate> {{binding_class}}::GetTemplate(v8::Isolate* isolate) {
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  if (!global_environment->HasInterfaceData(kInterfaceUniqueId)) {
    InitializeTemplate(isolate);
  }
  return global_environment->GetInterfaceData(kInterfaceUniqueId);
}

{% endblock implementation %}

{% block create_global_object_impl %}

namespace cobalt {
namespace script {
namespace v8c {

template <typename GlobalInterface>
void V8cGlobalEnvironment::CreateGlobalObject(
    const scoped_refptr<GlobalInterface>& global_interface,
    EnvironmentSettings* environment_settings) {
  TRACE_EVENT0("cobalt::script", "V8cGlobalEnvironment::CreateGlobalObject()");
  // Intentionally not an |EntryScope|, since the context doesn't exist yet.
  v8::Isolate::Scope isolate_scope(isolate_);
  v8::HandleScope handle_scope(isolate_);
  v8::Local<v8::ObjectTemplate> global_object_template = {{binding_class}}::GetTemplate(isolate_)->InstanceTemplate();

  v8::Local<v8::Context> context =
      v8::Context::New(isolate_, nullptr, global_object_template);
  context_.Reset(isolate_, context);
  v8::Context::Scope context_scope(context);

  global_wrappable_ = global_interface;

  DCHECK(!environment_settings_);
  DCHECK(environment_settings);
  environment_settings_ = environment_settings;
  EvaluateAutomatics();

  v8::Local<v8::Object> global_object = context->Global();
  new WrapperPrivate(isolate_, global_interface, global_object);

  auto actual_global_object = global_object->GetPrototype()->ToObject();
  new WrapperPrivate(isolate_, global_interface, actual_global_object);

{% for interface in all_interfaces %}
{% if interface.conditional %}
#if defined({{interface.conditional}})
{% endif %}
  wrapper_factory_->RegisterWrappableType(
      {{interface.name}}::{{interface.name}}WrappableType(),
      base::Bind(V8c{{interface.name}}::CreateWrapper),
      base::Bind(V8c{{interface.name}}::GetTemplate));
{% if interface.conditional %}
#endif  // defined({{interface.conditional}})
{% endif %}
{% endfor %}

}

}  // namespace v8c

template<>
void GlobalEnvironment::CreateGlobalObject<{{impl_class}}>(
    const scoped_refptr<{{impl_class}}>& global_interface,
    EnvironmentSettings* environment_settings) {
  base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(this)->CreateGlobalObject(global_interface, environment_settings);
}

}  // namespace script
}  // namespace cobalt

{% endblock create_global_object_impl %}

{%  block enumeration_definitions %}
// enum block
{% for enumeration in enumerations %}

inline void ToJSValue(
    v8::Isolate* isolate,
    {{impl_class}}::{{enumeration.name}} in_enum,
    v8::Local<v8::Value>* out_value) {
  switch (in_enum) {
{% for value, idl_value in enumeration.value_pairs %}
    case {{impl_class}}::{{value}}:
      ToJSValue(isolate, std::string("{{idl_value}}"), out_value);
      return;
{% endfor %}
    default:
      NOTREACHED();
      *out_value = v8::Undefined(isolate);
  }
}

inline void FromJSValue(
    v8::Isolate* isolate, v8::Local<v8::Value> value,
    int conversion_flags, ExceptionState* exception_state,
    {{impl_class}}::{{enumeration.name}}* out_enum) {
  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
  // Value -> IDL enum algorithm described here:
  // http://heycam.github.io/webidl/#es-enumeration
  // 1. Let S be the result of calling ToString(V).
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::MaybeLocal<v8::String> maybe_string = value->ToString(context);
  v8::Local<v8::String> string;
  if (!maybe_string.ToLocal(&string)) {
    exception_state->SetSimpleException(cobalt::script::kConvertToEnumFailed);
    return;
  }

  bool match = false;
// 3. Return the enumeration value of type E that is equal to S.
{% for value, idl_value in enumeration.value_pairs %}
{{-" else " if not loop.first}}
  if (string == NewInternalString(isolate, "{{id_value}}")) {
    *out_enum = {{impl_class}}::{{value}};
  }
{% endfor %}
  else {
    // 2. If S is not one of E's enumeration values, then throw a TypeError.
    exception_state->SetSimpleException(cobalt::script::kConvertToEnumFailed);
    return;
  }
}

{% endfor %}

{% endblock enumeration_definitions %}
