/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "bindings/core/v8/V8DOMConfiguration.h"

#include "bindings/core/v8/GeneratedCodeHelper.h"  // just for DCHECK
#include "bindings/core/v8/V8ObjectConstructor.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "platform/tracing/TraceEvent.h"

namespace blink {

namespace {

void installAttributeInternal(
    v8::Isolate* isolate,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const V8DOMConfiguration::AttributeConfiguration& attribute,
    const DOMWrapperWorld& world) {
  if (attribute.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = v8AtomicString(isolate, attribute.name);
  v8::AccessorNameGetterCallback getter = attribute.getter;
  v8::AccessorNameSetterCallback setter = attribute.setter;
  if (world.isMainWorld()) {
    if (attribute.getterForMainWorld)
      getter = attribute.getterForMainWorld;
    if (attribute.setterForMainWorld)
      setter = attribute.setterForMainWorld;
  }
  v8::Local<v8::Value> data =
      v8::External::New(isolate, const_cast<WrapperTypeInfo*>(attribute.data));

  DCHECK(attribute.propertyLocationConfiguration);
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnInstance)
    instanceTemplate->SetNativeDataProperty(
        name, getter, setter, data,
        static_cast<v8::PropertyAttribute>(attribute.attribute),
        v8::Local<v8::AccessorSignature>(),
        static_cast<v8::AccessControl>(attribute.settings));
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnPrototype)
    prototypeTemplate->SetNativeDataProperty(
        name, getter, setter, data,
        static_cast<v8::PropertyAttribute>(attribute.attribute),
        v8::Local<v8::AccessorSignature>(),
        static_cast<v8::AccessControl>(attribute.settings));
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnInterface)
    NOTREACHED();
}

void installAttributeInternal(
    v8::Isolate* isolate,
    v8::Local<v8::Object> instance,
    v8::Local<v8::Object> prototype,
    const V8DOMConfiguration::AttributeConfiguration& attribute,
    const DOMWrapperWorld& world) {
  if (attribute.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = v8AtomicString(isolate, attribute.name);

  // This method is only being used for installing interfaces which are
  // enabled through origin trials. Assert here that it is being called with
  // an attribute configuration for a constructor.
  // TODO(iclelland): Relax this constraint and allow arbitrary data-type
  // properties to be added here.
  DCHECK_EQ(&v8ConstructorAttributeGetter, attribute.getter);

  V8PerContextData* perContextData =
      V8PerContextData::from(isolate->GetCurrentContext());
  v8::Local<v8::Function> data =
      perContextData->constructorForType(attribute.data);

  DCHECK(attribute.propertyLocationConfiguration);
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnInstance)
    instance
        ->DefineOwnProperty(
            isolate->GetCurrentContext(), name, data,
            static_cast<v8::PropertyAttribute>(attribute.attribute))
        .ToChecked();
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnPrototype)
    prototype
        ->DefineOwnProperty(
            isolate->GetCurrentContext(), name, data,
            static_cast<v8::PropertyAttribute>(attribute.attribute))
        .ToChecked();
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnInterface)
    NOTREACHED();
}

void installLazyDataAttributeInternal(
    v8::Isolate* isolate,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const V8DOMConfiguration::AttributeConfiguration& attribute,
    const DOMWrapperWorld& world) {
  if (attribute.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = v8AtomicString(isolate, attribute.name);
  v8::AccessorNameGetterCallback getter = attribute.getter;
  DCHECK(!attribute.setter);
  DCHECK(!attribute.getterForMainWorld);
  DCHECK(!attribute.setterForMainWorld);
  v8::Local<v8::Value> data =
      v8::External::New(isolate, const_cast<WrapperTypeInfo*>(attribute.data));
  DCHECK(static_cast<v8::AccessControl>(attribute.settings) == v8::DEFAULT);

  DCHECK(attribute.propertyLocationConfiguration);
  if (attribute.propertyLocationConfiguration &
      V8DOMConfiguration::OnInstance) {
    instanceTemplate->SetLazyDataProperty(
        name, getter, data,
        static_cast<v8::PropertyAttribute>(attribute.attribute));
  }
  if (attribute.propertyLocationConfiguration &
      V8DOMConfiguration::OnPrototype) {
    prototypeTemplate->SetLazyDataProperty(
        name, getter, data,
        static_cast<v8::PropertyAttribute>(attribute.attribute));
  }
  if (attribute.propertyLocationConfiguration & V8DOMConfiguration::OnInterface)
    NOTREACHED();
}

template <class FunctionOrTemplate>
v8::Local<FunctionOrTemplate> createAccessorFunctionOrTemplate(
    v8::Isolate*,
    v8::FunctionCallback,
    V8DOMConfiguration::CachedAccessorCallback,
    v8::Local<v8::Value> data,
    v8::Local<v8::Signature>,
    int length);

template <>
v8::Local<v8::FunctionTemplate>
createAccessorFunctionOrTemplate<v8::FunctionTemplate>(
    v8::Isolate* isolate,
    v8::FunctionCallback callback,
    V8DOMConfiguration::CachedAccessorCallback cachedAccessorCallback,
    v8::Local<v8::Value> data,
    v8::Local<v8::Signature> signature,
    int length) {
  v8::Local<v8::FunctionTemplate> functionTemplate;
  if (callback) {
    if (cachedAccessorCallback) {
      functionTemplate = v8::FunctionTemplate::NewWithCache(
          isolate, callback, cachedAccessorCallback(isolate), data, signature,
          length);
    } else {
      functionTemplate =
          v8::FunctionTemplate::New(isolate, callback, data, signature, length);
    }

    if (!functionTemplate.IsEmpty()) {
      functionTemplate->RemovePrototype();
      functionTemplate->SetAcceptAnyReceiver(false);
    }
  }
  return functionTemplate;
}

template <>
v8::Local<v8::Function> createAccessorFunctionOrTemplate<v8::Function>(
    v8::Isolate* isolate,
    v8::FunctionCallback callback,
    V8DOMConfiguration::CachedAccessorCallback,
    v8::Local<v8::Value> data,
    v8::Local<v8::Signature> signature,
    int length) {
  if (!callback)
    return v8::Local<v8::Function>();

  v8::Local<v8::FunctionTemplate> functionTemplate =
      createAccessorFunctionOrTemplate<v8::FunctionTemplate>(
          isolate, callback, nullptr, data, signature, length);
  if (functionTemplate.IsEmpty())
    return v8::Local<v8::Function>();

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Function> function;
  if (!functionTemplate->GetFunction(context).ToLocal(&function))
    return v8::Local<v8::Function>();
  return function;
}

template <class ObjectOrTemplate, class FunctionOrTemplate>
void installAccessorInternal(
    v8::Isolate* isolate,
    v8::Local<ObjectOrTemplate> instanceOrTemplate,
    v8::Local<ObjectOrTemplate> prototypeOrTemplate,
    v8::Local<FunctionOrTemplate> interfaceOrTemplate,
    v8::Local<v8::Signature> signature,
    const V8DOMConfiguration::AccessorConfiguration& accessor,
    const DOMWrapperWorld& world) {
  if (accessor.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = v8AtomicString(isolate, accessor.name);
  v8::FunctionCallback getterCallback = accessor.getter;
  v8::FunctionCallback setterCallback = accessor.setter;
  V8DOMConfiguration::CachedAccessorCallback cachedAccessorCallback = nullptr;
  if (world.isMainWorld()) {
    if (accessor.getterForMainWorld)
      getterCallback = accessor.getterForMainWorld;
    if (accessor.setterForMainWorld)
      setterCallback = accessor.setterForMainWorld;
    cachedAccessorCallback = accessor.cachedAccessorCallback;
  }

  // Support [LenientThis] by not specifying the signature.  V8 does not do
  // the type checking against holder if no signature is specified.  Note that
  // info.Holder() passed to callbacks will be *unsafe*.
  if (accessor.holderCheckConfiguration == V8DOMConfiguration::DoNotCheckHolder)
    signature = v8::Local<v8::Signature>();
  v8::Local<v8::Value> data =
      v8::External::New(isolate, const_cast<WrapperTypeInfo*>(accessor.data));

  DCHECK(accessor.propertyLocationConfiguration);
  if (accessor.propertyLocationConfiguration &
      (V8DOMConfiguration::OnInstance | V8DOMConfiguration::OnPrototype)) {
    v8::Local<FunctionOrTemplate> getter =
        createAccessorFunctionOrTemplate<FunctionOrTemplate>(
            isolate, getterCallback, cachedAccessorCallback, data, signature,
            0);
    v8::Local<FunctionOrTemplate> setter =
        createAccessorFunctionOrTemplate<FunctionOrTemplate>(
            isolate, setterCallback, nullptr, data, signature, 1);
    if (accessor.propertyLocationConfiguration & V8DOMConfiguration::OnInstance)
      instanceOrTemplate->SetAccessorProperty(
          name, getter, setter,
          static_cast<v8::PropertyAttribute>(accessor.attribute),
          static_cast<v8::AccessControl>(accessor.settings));
    if (accessor.propertyLocationConfiguration &
        V8DOMConfiguration::OnPrototype)
      prototypeOrTemplate->SetAccessorProperty(
          name, getter, setter,
          static_cast<v8::PropertyAttribute>(accessor.attribute),
          static_cast<v8::AccessControl>(accessor.settings));
  }
  if (accessor.propertyLocationConfiguration &
      V8DOMConfiguration::OnInterface) {
    // Attributes installed on the interface object must be static
    // attributes, so no need to specify a signature, i.e. no need to do
    // type check against a holder.
    v8::Local<FunctionOrTemplate> getter =
        createAccessorFunctionOrTemplate<FunctionOrTemplate>(
            isolate, getterCallback, nullptr, data, v8::Local<v8::Signature>(),
            0);
    v8::Local<FunctionOrTemplate> setter =
        createAccessorFunctionOrTemplate<FunctionOrTemplate>(
            isolate, setterCallback, nullptr, data, v8::Local<v8::Signature>(),
            1);
    interfaceOrTemplate->SetAccessorProperty(
        name, getter, setter,
        static_cast<v8::PropertyAttribute>(accessor.attribute),
        static_cast<v8::AccessControl>(accessor.settings));
  }
}

v8::Local<v8::Primitive> valueForConstant(
    v8::Isolate* isolate,
    const V8DOMConfiguration::ConstantConfiguration& constant) {
  v8::Local<v8::Primitive> value;
  switch (constant.type) {
    case V8DOMConfiguration::ConstantTypeShort:
    case V8DOMConfiguration::ConstantTypeLong:
    case V8DOMConfiguration::ConstantTypeUnsignedShort:
      value = v8::Integer::New(isolate, constant.ivalue);
      break;
    case V8DOMConfiguration::ConstantTypeUnsignedLong:
      value = v8::Integer::NewFromUnsigned(isolate, constant.ivalue);
      break;
    case V8DOMConfiguration::ConstantTypeFloat:
    case V8DOMConfiguration::ConstantTypeDouble:
      value = v8::Number::New(isolate, constant.dvalue);
      break;
    default:
      NOTREACHED();
  }
  return value;
}

void installConstantInternal(
    v8::Isolate* isolate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const V8DOMConfiguration::ConstantConfiguration& constant) {
  v8::Local<v8::String> constantName = v8AtomicString(isolate, constant.name);
  v8::PropertyAttribute attributes =
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
  v8::Local<v8::Primitive> value = valueForConstant(isolate, constant);
  interfaceTemplate->Set(constantName, value, attributes);
  prototypeTemplate->Set(constantName, value, attributes);
}

void installConstantInternal(
    v8::Isolate* isolate,
    v8::Local<v8::Function> interface,
    v8::Local<v8::Object> prototype,
    const V8DOMConfiguration::ConstantConfiguration& constant) {
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Name> name = v8AtomicString(isolate, constant.name);
  v8::PropertyAttribute attributes =
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
  v8::Local<v8::Primitive> value = valueForConstant(isolate, constant);
  interface->DefineOwnProperty(context, name, value, attributes).ToChecked();
  prototype->DefineOwnProperty(context, name, value, attributes).ToChecked();
}

template <class Configuration>
void installMethodInternal(v8::Isolate* isolate,
                           v8::Local<v8::ObjectTemplate> instanceTemplate,
                           v8::Local<v8::ObjectTemplate> prototypeTemplate,
                           v8::Local<v8::FunctionTemplate> interfaceTemplate,
                           v8::Local<v8::Signature> signature,
                           const Configuration& method,
                           const DOMWrapperWorld& world) {
  if (method.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = method.methodName(isolate);
  v8::FunctionCallback callback = method.callbackForWorld(world);
  // Promise-returning functions need to return a reject promise when
  // an exception occurs.  This includes a case that the receiver object is not
  // of the type.  So, we disable the type check of the receiver object on V8
  // side so that V8 won't throw.  Instead, we do the check on Blink side and
  // convert an exception to a reject promise.
  if (method.holderCheckConfiguration == V8DOMConfiguration::DoNotCheckHolder)
    signature = v8::Local<v8::Signature>();

  DCHECK(method.propertyLocationConfiguration);
  if (method.propertyLocationConfiguration &
      (V8DOMConfiguration::OnInstance | V8DOMConfiguration::OnPrototype)) {
    v8::Local<v8::FunctionTemplate> functionTemplate =
        v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
                                  signature, method.length);
    functionTemplate->RemovePrototype();
    if (method.propertyLocationConfiguration & V8DOMConfiguration::OnInstance)
      instanceTemplate->Set(
          name, functionTemplate,
          static_cast<v8::PropertyAttribute>(method.attribute));
    if (method.propertyLocationConfiguration & V8DOMConfiguration::OnPrototype)
      prototypeTemplate->Set(
          name, functionTemplate,
          static_cast<v8::PropertyAttribute>(method.attribute));
  }
  if (method.propertyLocationConfiguration & V8DOMConfiguration::OnInterface) {
    // Operations installed on the interface object must be static
    // operations, so no need to specify a signature, i.e. no need to do
    // type check against a holder.
    v8::Local<v8::FunctionTemplate> functionTemplate =
        v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
                                  v8::Local<v8::Signature>(), method.length);
    functionTemplate->RemovePrototype();
    interfaceTemplate->Set(
        name, functionTemplate,
        static_cast<v8::PropertyAttribute>(method.attribute));
  }
}

void installMethodInternal(
    v8::Isolate* isolate,
    v8::Local<v8::Object> instance,
    v8::Local<v8::Object> prototype,
    v8::Local<v8::Function> interface,
    v8::Local<v8::Signature> signature,
    const V8DOMConfiguration::MethodConfiguration& method,
    const DOMWrapperWorld& world) {
  if (method.exposeConfiguration ==
          V8DOMConfiguration::OnlyExposedToPrivateScript &&
      !world.isPrivateScriptIsolatedWorld())
    return;

  v8::Local<v8::Name> name = method.methodName(isolate);
  v8::FunctionCallback callback = method.callbackForWorld(world);
  // Promise-returning functions need to return a reject promise when
  // an exception occurs.  This includes a case that the receiver object is not
  // of the type.  So, we disable the type check of the receiver object on V8
  // side so that V8 won't throw.  Instead, we do the check on Blink side and
  // convert an exception to a reject promise.
  if (method.holderCheckConfiguration == V8DOMConfiguration::DoNotCheckHolder)
    signature = v8::Local<v8::Signature>();

  DCHECK(method.propertyLocationConfiguration);
  if (method.propertyLocationConfiguration &
      (V8DOMConfiguration::OnInstance | V8DOMConfiguration::OnPrototype)) {
    v8::Local<v8::FunctionTemplate> functionTemplate =
        v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
                                  signature, method.length);
    functionTemplate->RemovePrototype();
    v8::Local<v8::Function> function =
        functionTemplate->GetFunction(isolate->GetCurrentContext())
            .ToLocalChecked();
    if (method.propertyLocationConfiguration & V8DOMConfiguration::OnInstance)
      instance
          ->DefineOwnProperty(
              isolate->GetCurrentContext(), name, function,
              static_cast<v8::PropertyAttribute>(method.attribute))
          .ToChecked();
    if (method.propertyLocationConfiguration & V8DOMConfiguration::OnPrototype)
      prototype
          ->DefineOwnProperty(
              isolate->GetCurrentContext(), name, function,
              static_cast<v8::PropertyAttribute>(method.attribute))
          .ToChecked();
  }
  if (method.propertyLocationConfiguration & V8DOMConfiguration::OnInterface) {
    // Operations installed on the interface object must be static
    // operations, so no need to specify a signature, i.e. no need to do
    // type check against a holder.
    v8::Local<v8::FunctionTemplate> functionTemplate =
        v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(),
                                  v8::Local<v8::Signature>(), method.length);
    functionTemplate->RemovePrototype();
    v8::Local<v8::Function> function =
        functionTemplate->GetFunction(isolate->GetCurrentContext())
            .ToLocalChecked();
    interface->DefineOwnProperty(isolate->GetCurrentContext(), name, function, static_cast<v8::PropertyAttribute>(method.attribute)).ToChecked();
  }
}

}  // namespace

void V8DOMConfiguration::installAttributes(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const AttributeConfiguration* attributes,
    size_t attributeCount) {
  for (size_t i = 0; i < attributeCount; ++i)
    installAttributeInternal(isolate, instanceTemplate, prototypeTemplate,
                             attributes[i], world);
}

void V8DOMConfiguration::installAttribute(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const AttributeConfiguration& attribute) {
  installAttributeInternal(isolate, instanceTemplate, prototypeTemplate,
                           attribute, world);
}

void V8DOMConfiguration::installAttribute(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::Object> instance,
    v8::Local<v8::Object> prototype,
    const AttributeConfiguration& attribute) {
  installAttributeInternal(isolate, instance, prototype, attribute, world);
}

void V8DOMConfiguration::installLazyDataAttributes(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const AttributeConfiguration* attributes,
    size_t attributeCount) {
  for (size_t i = 0; i < attributeCount; ++i) {
    installLazyDataAttributeInternal(isolate, instanceTemplate,
                                     prototypeTemplate, attributes[i], world);
  }
}

void V8DOMConfiguration::installAccessors(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::Signature> signature,
    const AccessorConfiguration* accessors,
    size_t accessorCount) {
  for (size_t i = 0; i < accessorCount; ++i)
    installAccessorInternal(isolate, instanceTemplate, prototypeTemplate,
                            interfaceTemplate, signature, accessors[i], world);
}

void V8DOMConfiguration::installAccessor(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::Signature> signature,
    const AccessorConfiguration& accessor) {
  installAccessorInternal(isolate, instanceTemplate, prototypeTemplate,
                          interfaceTemplate, signature, accessor, world);
}

void V8DOMConfiguration::installAccessor(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::Object> instance,
    v8::Local<v8::Object> prototype,
    v8::Local<v8::Function> interface,
    v8::Local<v8::Signature> signature,
    const AccessorConfiguration& accessor) {
  installAccessorInternal(isolate, instance, prototype, interface, signature,
                          accessor, world);
}

void V8DOMConfiguration::installConstants(
    v8::Isolate* isolate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const ConstantConfiguration* constants,
    size_t constantCount) {
  for (size_t i = 0; i < constantCount; ++i)
    installConstantInternal(isolate, interfaceTemplate, prototypeTemplate,
                            constants[i]);
}

void V8DOMConfiguration::installConstant(
    v8::Isolate* isolate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const ConstantConfiguration& constant) {
  installConstantInternal(isolate, interfaceTemplate, prototypeTemplate,
                          constant);
}

void V8DOMConfiguration::installConstant(
    v8::Isolate* isolate,
    v8::Local<v8::Function> interface,
    v8::Local<v8::Object> prototype,
    const ConstantConfiguration& constant) {
  installConstantInternal(isolate, interface, prototype, constant);
}

void V8DOMConfiguration::installConstantWithGetter(
    v8::Isolate* isolate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    const char* name,
    v8::AccessorNameGetterCallback getter) {
  v8::Local<v8::String> constantName = v8AtomicString(isolate, name);
  v8::PropertyAttribute attributes =
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
  interfaceTemplate->SetNativeDataProperty(constantName, getter, 0,
                                           v8::Local<v8::Value>(), attributes);
  prototypeTemplate->SetNativeDataProperty(constantName, getter, 0,
                                           v8::Local<v8::Value>(), attributes);
}

void V8DOMConfiguration::installMethods(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::Signature> signature,
    const MethodConfiguration* methods,
    size_t methodCount) {
  for (size_t i = 0; i < methodCount; ++i)
    installMethodInternal(isolate, instanceTemplate, prototypeTemplate,
                          interfaceTemplate, signature, methods[i], world);
}

void V8DOMConfiguration::installMethod(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> instanceTemplate,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    v8::Local<v8::Signature> signature,
    const MethodConfiguration& method) {
  installMethodInternal(isolate, instanceTemplate, prototypeTemplate,
                        interfaceTemplate, signature, method, world);
}

void V8DOMConfiguration::installMethod(v8::Isolate* isolate,
                                       const DOMWrapperWorld& world,
                                       v8::Local<v8::Object> instance,
                                       v8::Local<v8::Object> prototype,
                                       v8::Local<v8::Function> interface,
                                       v8::Local<v8::Signature> signature,
                                       const MethodConfiguration& method) {
  installMethodInternal(isolate, instance, prototype, interface, signature,
                        method, world);
}

void V8DOMConfiguration::installMethod(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    v8::Local<v8::ObjectTemplate> prototypeTemplate,
    v8::Local<v8::Signature> signature,
    const SymbolKeyedMethodConfiguration& method) {
  installMethodInternal(isolate, v8::Local<v8::ObjectTemplate>(),
                        prototypeTemplate, v8::Local<v8::FunctionTemplate>(),
                        signature, method, world);
}

void V8DOMConfiguration::initializeDOMInterfaceTemplate(
    v8::Isolate* isolate,
    v8::Local<v8::FunctionTemplate> interfaceTemplate,
    const char* interfaceName,
    v8::Local<v8::FunctionTemplate> parentInterfaceTemplate,
    size_t v8InternalFieldCount) {
  interfaceTemplate->SetClassName(v8AtomicString(isolate, interfaceName));
  interfaceTemplate->ReadOnlyPrototype();
  v8::Local<v8::ObjectTemplate> instanceTemplate =
      interfaceTemplate->InstanceTemplate();
  v8::Local<v8::ObjectTemplate> prototypeTemplate =
      interfaceTemplate->PrototypeTemplate();
  instanceTemplate->SetInternalFieldCount(v8InternalFieldCount);
  // TODO(yukishiino): We should set the class string to the platform object
  // (|instanceTemplate|), too.  The reason that we don't set it is that
  // it prevents minor GC to collect unreachable DOM objects (a layout test
  // fast/dom/minor-dom-gc.html fails if we set the class string).
  // See also http://heycam.github.io/webidl/#es-platform-objects
  setClassString(isolate, prototypeTemplate, interfaceName);
  if (!parentInterfaceTemplate.IsEmpty()) {
    interfaceTemplate->Inherit(parentInterfaceTemplate);
    // Marks the prototype object as one of native-backed objects.
    // This is needed since bug 110436 asks WebKit to tell native-initiated
    // prototypes from pure-JS ones.  This doesn't mark kinds "root" classes
    // like Node, where setting this changes prototype chain structure.
    prototypeTemplate->SetInternalFieldCount(v8PrototypeInternalFieldcount);
  }
}

v8::Local<v8::FunctionTemplate> V8DOMConfiguration::domClassTemplate(
    v8::Isolate* isolate,
    const DOMWrapperWorld& world,
    WrapperTypeInfo* wrapperTypeInfo,
    InstallTemplateFunction configureDOMClassTemplate) {
  V8PerIsolateData* data = V8PerIsolateData::from(isolate);
  v8::Local<v8::FunctionTemplate> result =
      data->findInterfaceTemplate(world, wrapperTypeInfo);
  if (!result.IsEmpty())
    return result;

  result = v8::FunctionTemplate::New(
      isolate, V8ObjectConstructor::isValidConstructorMode);
  configureDOMClassTemplate(isolate, world, result);
  data->setInterfaceTemplate(world, wrapperTypeInfo, result);
  return result;
}

void V8DOMConfiguration::setClassString(
    v8::Isolate* isolate,
    v8::Local<v8::ObjectTemplate> objectTemplate,
    const char* classString) {
  objectTemplate->Set(
      v8::Symbol::GetToStringTag(isolate), v8AtomicString(isolate, classString),
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
}

}  // namespace blink
