

// Copyright 2018 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 bindings/code_generator_cobalt.py. DO NOT MODIFY!
// Auto-generated from template: bindings/v8c/templates/interface.cc.template

#include "cobalt/bindings/testing/v8c_numeric_types_test_interface.h"

#include "base/debug/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/script_value.h"
#include "cobalt/script/value_handle.h"

#include "v8c_gen_type_conversion.h"

#include "cobalt/script/callback_interface_traits.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/native_promise.h"
#include "cobalt/script/v8c/type_traits.h"
#include "cobalt/script/v8c/v8c_callback_function.h"
#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"


namespace {
using cobalt::bindings::testing::NumericTypesTestInterface;
using cobalt::bindings::testing::V8cNumericTypesTestInterface;
using cobalt::script::CallbackInterfaceTraits;
using cobalt::script::GlobalEnvironment;
using cobalt::script::ScriptValue;
using cobalt::script::ValueHandle;
using cobalt::script::ValueHandle;
using cobalt::script::ValueHandleHolder;
using cobalt::script::Wrappable;

using cobalt::script::v8c::EntryScope;
using cobalt::script::v8c::EscapableEntryScope;
using cobalt::script::v8c::FromJSValue;
using cobalt::script::v8c::InterfaceData;
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::ToJSValue;
using cobalt::script::v8c::TypeTraits;
using cobalt::script::v8c::V8cExceptionState;
using cobalt::script::v8c::V8cGlobalEnvironment;
using cobalt::script::v8c::WrapperFactory;
using cobalt::script::v8c::WrapperPrivate;

v8::Local<v8::Object> DummyFunctor(v8::Isolate*, const scoped_refptr<Wrappable>&) {
  NOTIMPLEMENTED();
  return {};
}

}  // namespace

namespace cobalt {
namespace bindings {
namespace testing {


namespace {



void bytePropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->byte_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void bytePropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int8_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_byte_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void byteClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->byte_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void byteClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int8_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_byte_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void octetPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->octet_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void octetPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint8_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_octet_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void octetClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->octet_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void octetClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint8_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_octet_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void shortPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->short_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void shortPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int16_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_short_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void shortClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->short_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void shortClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int16_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_short_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedShortPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_short_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedShortPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint16_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_short_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedShortClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_short_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedShortClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint16_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_short_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void longPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->long_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void longPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int32_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_long_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void longClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->long_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void longClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int32_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_long_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedLongPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_long_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedLongPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint32_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_long_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedLongClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_long_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedLongClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint32_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_long_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void longLongPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->long_long_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void longLongPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int64_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_long_long_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void longLongClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->long_long_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void longLongClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<int64_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_long_long_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedLongLongPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_long_long_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedLongLongPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint64_t >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_long_long_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unsignedLongLongClampPropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unsigned_long_long_clamp_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unsignedLongLongClampPropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<uint64_t >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagClamped), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unsigned_long_long_clamp_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void doublePropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->double_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void doublePropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<double >::ConversionType value;
  FromJSValue(isolate, v8_value, (kConversionFlagRestricted), &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_double_property(value);
  result_value = v8::Undefined(isolate);
  return;
}

void unrestrictedDoublePropertyAttributeGetter(
    v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();


  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->unrestricted_double_property(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }
}

void unrestrictedDoublePropertyAttributeSetter(
    v8::Local<v8::String> property,
    v8::Local<v8::Value> v8_value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();

  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  TypeTraits<double >::ConversionType value;
  FromJSValue(isolate, v8_value, kNoConversionFlags, &exception_state,
              &value);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->set_unrestricted_double_property(value);
  result_value = v8::Undefined(isolate);
  return;
}



void byteArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<int8_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->ByteArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void byteReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->ByteReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void doubleArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<double >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              (kConversionFlagRestricted),
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->DoubleArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void doubleReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->DoubleReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void longArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<int32_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->LongArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void longLongArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<int64_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->LongLongArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void longLongReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->LongLongReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void longReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->LongReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void octetArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<uint8_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->OctetArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void octetReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->OctetReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void shortArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<int16_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->ShortArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void shortReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->ShortReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void unrestrictedDoubleArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<double >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->UnrestrictedDoubleArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void unrestrictedDoubleReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->UnrestrictedDoubleReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void unsignedLongArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<uint32_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->UnsignedLongArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void unsignedLongLongArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<uint64_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->UnsignedLongLongArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void unsignedLongLongReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->UnsignedLongLongReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void unsignedLongReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->UnsignedLongReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}



void unsignedShortArgumentOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();
  const size_t kMinArguments = 1;
  if (info.Length() < kMinArguments) {
    exception_state.SetSimpleException(script::kInvalidNumberOfArguments);
    return;
  }
  // Non-optional arguments
  TypeTraits<uint16_t >::ConversionType arg1;
  DCHECK_LT(0, info.Length());
  v8::Local<v8::Value> non_optional_value0 = info[0];
  FromJSValue(isolate,
              non_optional_value0,
              kNoConversionFlags,
              &exception_state, &arg1);
  if (exception_state.is_exception_set()) {
    return;
  }

  impl->UnsignedShortArgumentOperation(arg1);
  result_value = v8::Undefined(isolate);

}



void unsignedShortReturnOperationMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Object> object = info.This();
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  WrapperFactory* wrapper_factory = global_environment->wrapper_factory();
  if (!wrapper_factory->DoesObjectImplementInterface(
        object, base::GetTypeId<NumericTypesTestInterface>())) {
    V8cExceptionState exception(isolate);
    exception.SetSimpleException(script::kDoesNotImplementInterface);
    return;
  }
  V8cExceptionState exception_state{isolate};
  v8::Local<v8::Value> result_value;

  WrapperPrivate* wrapper_private =
      WrapperPrivate::GetFromWrapperObject(object);
  if (!wrapper_private) {
    NOTIMPLEMENTED();
    return;
  }
  NumericTypesTestInterface* impl =
      wrapper_private->wrappable<NumericTypesTestInterface>().get();

  if (!exception_state.is_exception_set()) {
    ToJSValue(isolate,
              impl->UnsignedShortReturnOperation(),
              &result_value);
  }
  if (!exception_state.is_exception_set()) {
    info.GetReturnValue().Set(result_value);
  }

}


void InitializeTemplateAndInterfaceObject(v8::Isolate* isolate, InterfaceData* interface_data) {
  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(isolate);
  function_template->SetClassName(
    v8::String::NewFromUtf8(isolate, "NumericTypesTestInterface",
        v8::NewStringType::kInternalized).ToLocalChecked());
  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
  instance_template->SetInternalFieldCount(WrapperPrivate::kInternalFieldCount);


  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();


  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "byteProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    bytePropertyAttributeGetter
    ,bytePropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "byteClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    byteClampPropertyAttributeGetter
    ,byteClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "octetProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    octetPropertyAttributeGetter
    ,octetPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "octetClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    octetClampPropertyAttributeGetter
    ,octetClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "shortProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    shortPropertyAttributeGetter
    ,shortPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "shortClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    shortClampPropertyAttributeGetter
    ,shortClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedShortProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedShortPropertyAttributeGetter
    ,unsignedShortPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedShortClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedShortClampPropertyAttributeGetter
    ,unsignedShortClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "longProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    longPropertyAttributeGetter
    ,longPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "longClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    longClampPropertyAttributeGetter
    ,longClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedLongProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedLongPropertyAttributeGetter
    ,unsignedLongPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedLongClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedLongClampPropertyAttributeGetter
    ,unsignedLongClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "longLongProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    longLongPropertyAttributeGetter
    ,longLongPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "longLongClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    longLongClampPropertyAttributeGetter
    ,longLongClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedLongLongProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedLongLongPropertyAttributeGetter
    ,unsignedLongLongPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unsignedLongLongClampProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unsignedLongLongClampPropertyAttributeGetter
    ,unsignedLongLongClampPropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "doubleProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    doublePropertyAttributeGetter
    ,doublePropertyAttributeSetter
  );
  instance_template->SetAccessor(
    v8::String::NewFromUtf8(isolate, "unrestrictedDoubleProperty",
                              v8::NewStringType::kInternalized)
          .ToLocalChecked(),
    unrestrictedDoublePropertyAttributeGetter
    ,unrestrictedDoublePropertyAttributeSetter
  );

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, byteArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "byteArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, byteReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "byteReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, doubleArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "doubleArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, doubleReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "doubleReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "longArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longLongArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "longLongArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longLongReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "longLongReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, longReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "longReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, octetArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "octetArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, octetReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "octetReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, shortArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "shortArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, shortReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "shortReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unrestrictedDoubleArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unrestrictedDoubleArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unrestrictedDoubleReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unrestrictedDoubleReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedLongArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongLongArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedLongLongArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongLongReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedLongLongReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedLongReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedLongReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedShortArgumentOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedShortArgumentOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }

  {
    v8::Local<v8::FunctionTemplate> method_template = v8::FunctionTemplate::New(isolate, unsignedShortReturnOperationMethod);
    method_template->RemovePrototype();
    prototype_template->Set(
        v8::String::NewFromUtf8(
            isolate,
            "unsignedShortReturnOperation",
            v8::NewStringType::kInternalized).ToLocalChecked(),
        method_template);
  }


  interface_data->function_template.Set(isolate, function_template);
}

inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* global_environment) {
  const int kInterfaceUniqueId = 38;
  // By convention, the |V8cGlobalEnvironment| that we are associated with
  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
  // for it to be there in the first place, and could not have conflicted with
  // any other interface.
  return global_environment->GetInterfaceData(kInterfaceUniqueId);
}

}  // namespace

v8::Local<v8::Object> V8cNumericTypesTestInterface::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);
  InterfaceData* interface_data = GetInterfaceData(global_environment);
  if (interface_data->function_template.IsEmpty()) {
    InitializeTemplateAndInterfaceObject(isolate, interface_data);
  }
  DCHECK(!interface_data->function_template.IsEmpty());

  v8::Local<v8::FunctionTemplate> function_template = interface_data->function_template.Get(isolate);
  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);
}

v8::Local<v8::FunctionTemplate> V8cNumericTypesTestInterface::CreateTemplate(v8::Isolate* isolate) {
  V8cGlobalEnvironment* global_environment = V8cGlobalEnvironment::GetFromIsolate(isolate);
  InterfaceData* interface_data = GetInterfaceData(global_environment);
  if (interface_data->function_template.IsEmpty()) {
    InitializeTemplateAndInterfaceObject(isolate, interface_data);
  }

  return interface_data->function_template.Get(isolate);
}


}  // namespace testing
}  // namespace bindings
}  // namespace cobalt


