{#
 # Copyright 2017 Google Inc. 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.
 #}
// Copyright {{today.year}} Google Inc. 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.

// clang-format off

// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY!
// Auto-generated from template: {{template_path}}

{% if conditional %}
#if defined({{conditional}})

{% endif %}
{% block includes %}
#include "{{generated_conversion_include}}"

#include "{{header_file}}"

#include "cobalt/script/exception_state.h"
#include "third_party/mozjs-45/js/src/jsapi.h"
{% for include in includes %}
#include "{{include}}"
{% endfor %}
{% endblock includes %}

using {{components|join('::')}}::{{class_name}};
{% for used_class in forward_declarations %}
{% if used_class.conditional %}
#if defined({{used_class.conditional}})
{% endif %}
using {{used_class.fully_qualified_name}};
{% if used_class.conditional %}
#endif  // defined({{used_class.conditional}})
{% endif %}
{% endfor %}

namespace cobalt {
namespace script {
namespace mozjs {

void ToJSValue(
    JSContext* context,
    const {{class_name}}& in_dictionary,
    JS::MutableHandleValue out_value) {
  // Create a new object that will hold the dictionary values.
  JS::RootedObject dictionary_object(
      context, JS_NewObject(context, nullptr));
  const int kPropertyAttributes = JSPROP_ENUMERATE;
{% for member in members %}
  if (in_dictionary.has_{{member.name}}()) {
    JS::RootedValue member_value(context);
    ToJSValue(context, in_dictionary.{{member.name}}(), &member_value);
    if (!JS_DefineProperty(context, dictionary_object,
                           "{{member.idl_name}}",
                           member_value, kPropertyAttributes, nullptr, nullptr)) {
      // Some internal error occurred.
      NOTREACHED();
      return;
    }
  }
{% endfor %}
  out_value.setObject(*dictionary_object);
}

void FromJSValue(JSContext* context, JS::HandleValue value,
                 int conversion_flags, ExceptionState* exception_state,
                 {{class_name}}* out_dictionary) {
  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
  MozjsExceptionState* mozjs_exception_state = base::polymorphic_downcast<MozjsExceptionState*>(exception_state);
  DCHECK(!mozjs_exception_state->is_exception_set());

  {% if parent %}
  FromJSValue(context, value, conversion_flags, exception_state,
      static_cast<{{parent}}*>(out_dictionary));
  if (mozjs_exception_state->is_exception_set()) {
    return;
  }
  {% endif %}
  // https://heycam.github.io/webidl/#es-dictionary

  if (value.isUndefined() || value.isNull()) {
    // The default constructor will assign appropriate values to dictionary
    // members with default values and leave the others unset.
    *out_dictionary = {{class_name}}();
    return;
  }
  if (!value.isObject()) {
    // 1. If Type(V) is not Undefined, Null or Object, then throw a TypeError.
    exception_state->SetSimpleException(kNotObjectType);
    return;
  }
  JS::RootedObject dictionary_object(context, &value.toObject());
{% for member in members %}
  JS::RootedValue {{member.name}}(context);
  if (!JS_GetProperty(context, dictionary_object,
                      "{{member.idl_name}}",
                      &{{member.name}})) {
    exception_state->SetSimpleException(kSimpleError);
    return;
  }
  if (!{{member.name}}.isUndefined()) {
  {% if not member.is_script_value %}
    {{member.type}} converted_value;
    FromJSValue(context,
                {{member.name}},
                {{member.conversion_flags}},
                exception_state,
                &converted_value);
    if (context->isExceptionPending()) {
      return;
    }
    out_dictionary->set_{{member.name}}(converted_value);
  {% else %}
    TypeTraits<{{member.type}}>::ConversionType converted_value;
    FromJSValue(context,
                {{member.name}},
                {{member.conversion_flags}},
                exception_state,
                &converted_value);
    if (context->isExceptionPending()) {
      return;
    }
    out_dictionary->set_{{member.name}}(&converted_value);
  {% endif %}
  }
{% endfor %}
}

}  // namespace mozjs
}  // namespace script
}  // namespace cobalt

{% if conditional %}
#endif  // defined({{conditional}})
{% endif %}
