{#
 # 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.";
  {% if parent %}
  FromJSValue(context, value, conversion_flags, exception_state,
      static_cast<{{parent}}*>(out_dictionary));
  {% 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<::cobalt::script::ValueHandle >::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 %}
