// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!

#include "config.h"
#if ENABLE(CONDITION)
#include "V8TestInterfacePartial.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/PrivateScriptRunner.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8DOMConfiguration.h"
#include "bindings/core/v8/V8Document.h"
#include "bindings/core/v8/V8HiddenValue.h"
#include "bindings/core/v8/V8Node.h"
#include "bindings/core/v8/V8ObjectConstructor.h"
#include "bindings/core/v8/V8TestInterface.h"
#include "bindings/core/v8/V8TestInterfaceEmpty.h"
#include "bindings/core/v8/V8Window.h"
#include "bindings/tests/idls/modules/TestPartialInterfaceImplementation3.h"
#include "core/dom/ContextFeatures.h"
#include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/TraceEvent.h"
#include "wtf/GetPtr.h"
#include "wtf/RefPtr.h"

namespace blink {

namespace TestInterfaceImplementationPartialV8Internal {

static void voidMethodPartialOverload3Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
    V8StringResource<> value;
    {
        TOSTRING_VOID_INTERNAL(value, info[0]);
    }
    TestPartialInterfaceImplementation3::voidMethodPartialOverload(*impl, value);
}

static void voidMethodPartialOverloadMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "voidMethodPartialOverload", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (true) {
            voidMethodPartialOverload3Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        exceptionState.throwIfNeeded();
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    exceptionState.throwIfNeeded();
}

static void staticVoidMethodPartialOverload2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    V8StringResource<> value;
    {
        TOSTRING_VOID_INTERNAL(value, info[0]);
    }
    TestPartialInterfaceImplementation3::staticVoidMethodPartialOverload(value);
}

static void staticVoidMethodPartialOverloadMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "staticVoidMethodPartialOverload", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (true) {
            staticVoidMethodPartialOverload2Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        exceptionState.throwIfNeeded();
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    exceptionState.throwIfNeeded();
}

static void promiseMethodPartialOverload3Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
    Document* document;
    {
        if (info.Length() > 0 && !V8Document::hasInstance(info[0], info.GetIsolate())) {
            v8SetReturnValue(info, ScriptPromise::rejectRaw(info.GetIsolate(), V8ThrowException::createTypeError(info.GetIsolate(), ExceptionMessages::failedToExecute("promiseMethodPartialOverload", "TestInterface", "parameter 1 is not of type 'Document'."))));
            return;
        }
        document = V8Document::toImpl(v8::Handle<v8::Object>::Cast(info[0]));
    }
    v8SetReturnValue(info, TestPartialInterfaceImplementation3::promiseMethodPartialOverload(*impl, document).v8Value());
}

static void promiseMethodPartialOverloadMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "promiseMethodPartialOverload", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (V8Document::hasInstance(info[0], info.GetIsolate())) {
            promiseMethodPartialOverload3Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolate())).v8Value());
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolate())).v8Value());
}

static void staticPromiseMethodPartialOverload2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "staticPromiseMethodPartialOverload", "TestInterface", info.Holder(), info.GetIsolate());
    V8StringResource<> value;
    {
        TOSTRING_VOID_EXCEPTIONSTATE_PROMISE_INTERNAL(value, info[0], exceptionState, info, ScriptState::current(info.GetIsolate()));
    }
    v8SetReturnValue(info, TestPartialInterfaceImplementation3::staticPromiseMethodPartialOverload(value).v8Value());
}

static void staticPromiseMethodPartialOverloadMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "staticPromiseMethodPartialOverload", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (true) {
            staticPromiseMethodPartialOverload2Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolate())).v8Value());
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolate())).v8Value());
}

static void partial2VoidMethod2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
    V8StringResource<> value;
    {
        TOSTRING_VOID_INTERNAL(value, info[0]);
    }
    TestPartialInterfaceImplementation3::partial2VoidMethod(*impl, value);
}

static void partial2VoidMethod3Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
    Node* node;
    {
        if (info.Length() > 0 && !V8Node::hasInstance(info[0], info.GetIsolate())) {
            V8ThrowException::throwTypeError(ExceptionMessages::failedToExecute("partial2VoidMethod", "TestInterface", "parameter 1 is not of type 'Node'."), info.GetIsolate());
            return;
        }
        node = V8Node::toImpl(v8::Handle<v8::Object>::Cast(info[0]));
    }
    TestPartialInterfaceImplementation3::partial2VoidMethod(*impl, node);
}

static void partial2VoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "partial2VoidMethod", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (V8Node::hasInstance(info[0], info.GetIsolate())) {
            partial2VoidMethod3Method(info);
            return;
        }
        if (true) {
            partial2VoidMethod2Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        exceptionState.throwIfNeeded();
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    exceptionState.throwIfNeeded();
}

static void partial2StaticVoidMethod2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    V8StringResource<> value;
    {
        TOSTRING_VOID_INTERNAL(value, info[0]);
    }
    TestPartialInterfaceImplementation3::partial2StaticVoidMethod(value);
}

static void partial2StaticVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "partial2StaticVoidMethod", "TestInterface", info.Holder(), info.GetIsolate());
    switch (std::min(1, info.Length())) {
    case 0:
        break;
    case 1:
        if (true) {
            partial2StaticVoidMethod2Method(info);
            return;
        }
        break;
    default:
        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(0, info.Length()));
        exceptionState.throwIfNeeded();
        return;
    }
    exceptionState.throwTypeError("No function was found that matched the signature provided.");
    exceptionState.throwIfNeeded();
}

} // namespace TestInterfaceImplementationPartialV8Internal

void V8TestInterfacePartial::installV8TestInterfaceTemplate(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate)
{
    V8TestInterface::installV8TestInterfaceTemplate(functionTemplate, isolate);

    v8::Local<v8::Signature> defaultSignature;
    if (!RuntimeEnabledFeatures::featureNameEnabled())
        defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, "", v8::Local<v8::FunctionTemplate>(), V8TestInterface::internalFieldCount, 0, 0, 0, 0, 0, 0, isolate);
    else
        defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, "TestInterface", v8::Local<v8::FunctionTemplate>(), V8TestInterface::internalFieldCount,
            0, 0,
            0, 0,
            0, 0,
            isolate);
    v8::Local<v8::ObjectTemplate> instanceTemplate = functionTemplate->InstanceTemplate();
    ALLOW_UNUSED_LOCAL(instanceTemplate);
    v8::Local<v8::ObjectTemplate> prototypeTemplate = functionTemplate->PrototypeTemplate();
    ALLOW_UNUSED_LOCAL(prototypeTemplate);
    static const V8DOMConfiguration::ConstantConfiguration V8TestInterfaceConstants[] = {
        {"PARTIAL3_UNSIGNED_SHORT", 0, 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
    };
    V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, V8TestInterfaceConstants, WTF_ARRAY_LENGTH(V8TestInterfaceConstants), isolate);
    functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler(V8TestInterface::legacyCallCustom);
}

void V8TestInterfacePartial::installConditionallyEnabledMethods(v8::Handle<v8::Object> prototypeObject, v8::Isolate* isolate)
{
    V8TestInterface::installConditionallyEnabledMethods(prototypeObject, isolate);
}

bool V8TestInterface::PrivateScript::shortMethodWithShortArgumentImplementedInPrivateScriptMethod(LocalFrame* frame, TestInterface* holderImpl, int value, int* result)
{
    if (!frame)
        return false;
    v8::HandleScope handleScope(toIsolate(frame));
    ScriptForbiddenScope::AllowUserAgentScript script;
    v8::Handle<v8::Context> contextInPrivateScript = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
    if (contextInPrivateScript.IsEmpty())
        return false;
    ScriptState* scriptState = ScriptState::from(contextInPrivateScript);
    ScriptState* scriptStateInUserScript = ScriptState::forMainWorld(frame);
    if (!scriptState->executionContext())
        return false;

    ScriptState::Scope scope(scriptState);
    v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());

    v8::Handle<v8::Value> valueHandle = v8::Integer::New(scriptState->isolate(), value);
    v8::Handle<v8::Value> argv[] = { valueHandle };
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "shortMethodWithShortArgumentImplementedInPrivateScript", "TestInterfaceImplementation", scriptState->context()->Global(), scriptState->isolate());
    v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMMethod(scriptState, scriptStateInUserScript, "TestInterfaceImplementation", "shortMethodWithShortArgumentImplementedInPrivateScript", holder, 1, argv);
    if (v8Value.IsEmpty())
        return false;
    TONATIVE_DEFAULT_EXCEPTIONSTATE(int, cppValue, toInt16(v8Value, exceptionState), exceptionState, false);
    *result = cppValue;
    RELEASE_ASSERT(!exceptionState.hadException());
    return true;
}

void V8TestInterfacePartial::initialize()
{
    // Should be invoked from initModules.
    V8TestInterface::updateWrapperTypeInfo(
        &V8TestInterfacePartial::installV8TestInterfaceTemplate,
        &V8TestInterfacePartial::installConditionallyEnabledMethods);
    V8TestInterface::registerVoidMethodPartialOverloadMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::voidMethodPartialOverloadMethod);
    V8TestInterface::registerStaticVoidMethodPartialOverloadMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::staticVoidMethodPartialOverloadMethod);
    V8TestInterface::registerPromiseMethodPartialOverloadMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::promiseMethodPartialOverloadMethod);
    V8TestInterface::registerStaticPromiseMethodPartialOverloadMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::staticPromiseMethodPartialOverloadMethod);
    V8TestInterface::registerPartial2VoidMethodMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::partial2VoidMethodMethod);
    V8TestInterface::registerPartial2StaticVoidMethodMethodForPartialInterface(&TestInterfaceImplementationPartialV8Internal::partial2StaticVoidMethodMethod);
}

} // namespace blink
#endif // ENABLE(CONDITION)
