/*
 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2007, 2008, 2009 Google, Inc.  All rights reserved.
 * Copyright (C) 2014 Opera Software ASA. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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 "config.h"
#include "bindings/core/v8/NPV8Object.h"

#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8NPUtils.h"
#include "bindings/core/v8/V8ObjectConstructor.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "bindings/core/v8/WrapperTypeInfo.h"
#include "bindings/core/v8/npruntime_impl.h"
#include "bindings/core/v8/npruntime_priv.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "platform/UserGestureIndicator.h"
#include "wtf/OwnPtr.h"
#include "wtf/StringExtras.h"
#include "wtf/text/WTFString.h"
#include <stdio.h>

using namespace blink;

namespace {

void trace(Visitor*, ScriptWrappableBase*)
{
}

} // namespace

namespace blink {

const WrapperTypeInfo* npObjectTypeInfo()
{
    static const WrapperTypeInfo typeInfo = { gin::kEmbedderBlink, 0, 0, 0, trace, 0, 0, 0, 0, 0, 0, WrapperTypeInfo::WrapperTypeObjectPrototype, WrapperTypeInfo::ObjectClassId, WrapperTypeInfo::Dependent, WrapperTypeInfo::RefCountedObject };
    return &typeInfo;
}

// FIXME: Comments on why use malloc and free.
static NPObject* allocV8NPObject(NPP, NPClass*)
{
    return static_cast<NPObject*>(malloc(sizeof(V8NPObject)));
}

static void freeV8NPObject(NPObject* npObject)
{
    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);
    disposeUnderlyingV8Object(v8::Isolate::GetCurrent(), npObject);
    free(v8NpObject);
}

static NPClass V8NPObjectClass = {
    NP_CLASS_STRUCT_VERSION,
    allocV8NPObject,
    freeV8NPObject,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static ScriptState* mainWorldScriptState(v8::Isolate* isolate, NPP npp, NPObject* npObject)
{
    ASSERT(npObject->_class == &V8NPObjectClass);
    V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);
    LocalDOMWindow* window = object->rootObject;
    if (!window || !window->isCurrentlyDisplayedInFrame())
        return 0;
    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Context> context = toV8Context(object->rootObject->frame(), DOMWrapperWorld::mainWorld());
    return ScriptState::from(context);
}

static PassOwnPtr<v8::Handle<v8::Value>[]> createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner, v8::Isolate* isolate)
{
    OwnPtr<v8::Handle<v8::Value>[]> argv = adoptArrayPtr(new v8::Handle<v8::Value>[argumentCount]);
    for (uint32_t index = 0; index < argumentCount; index++) {
        const NPVariant* arg = &arguments[index];
        argv[index] = convertNPVariantToV8Object(isolate, arg, owner);
    }
    return argv.release();
}

// Create an identifier (null terminated utf8 char*) from the NPIdentifier.
static v8::Local<v8::String> npIdentifierToV8Identifier(v8::Isolate* isolate, NPIdentifier name)
{
    PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name);
    if (identifier->isString)
        return v8AtomicString(isolate, static_cast<const char*>(identifier->value.string));

    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%d", identifier->value.number);
    return v8AtomicString(isolate, buffer);
}

NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object)
{
    return reinterpret_cast<NPObject*>(toScriptWrappableBase(object));
}

bool isWrappedNPObject(v8::Handle<v8::Object> object)
{
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex));
        return typeInfo == npObjectTypeInfo();
    }
    return false;
}

NPObject* npCreateV8ScriptObject(v8::Isolate* isolate, NPP npp, v8::Handle<v8::Object> object, LocalDOMWindow* root)
{
    // Check to see if this object is already wrapped.
    if (isWrappedNPObject(object)) {
        NPObject* returnValue = v8ObjectToNPObject(object);
        _NPN_RetainObject(returnValue);
        return returnValue;
    }

    V8NPObjectVector* objectVector = 0;
    if (V8PerContextData* perContextData = V8PerContextData::from(object->CreationContext())) {
        int v8ObjectHash = object->GetIdentityHash();
        ASSERT(v8ObjectHash);
        V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap();
        V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash);
        if (iter != v8NPObjectMap->end()) {
            V8NPObjectVector& objects = iter->value;
            for (size_t index = 0; index < objects.size(); ++index) {
                V8NPObject* v8npObject = objects.at(index);
                if (v8npObject->v8Object == object && v8npObject->rootObject == root) {
                    _NPN_RetainObject(&v8npObject->object);
                    return reinterpret_cast<NPObject*>(v8npObject);
                }
            }
            objectVector = &iter->value;
        } else {
            objectVector = &v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).storedValue->value;
        }
    }

    V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
    // This is uninitialized memory, we need to clear it so that
    // Persistent::Reset won't try to Dispose anything bogus.
    new (&v8npObject->v8Object) v8::Persistent<v8::Object>();
    v8npObject->v8Object.Reset(isolate, object);
    v8npObject->rootObject = root;

    if (objectVector)
        objectVector->append(v8npObject);

    return reinterpret_cast<NPObject*>(v8npObject);
}

V8NPObject* npObjectToV8NPObject(NPObject* npObject)
{
    if (npObject->_class != &V8NPObjectClass)
        return 0;
    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);
    if (v8NpObject->v8Object.IsEmpty())
        return 0;
    return v8NpObject;
}

ScriptWrappableBase* npObjectToScriptWrappableBase(NPObject* npObject)
{
    return reinterpret_cast<ScriptWrappableBase*>(npObject);
}

void disposeUnderlyingV8Object(v8::Isolate* isolate, NPObject* npObject)
{
    ASSERT(npObject);
    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject)
        return;
    v8::HandleScope scope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object);
    ASSERT(!v8Object->CreationContext().IsEmpty());
    if (V8PerContextData* perContextData = V8PerContextData::from(v8Object->CreationContext())) {
        V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap();
        int v8ObjectHash = v8Object->GetIdentityHash();
        ASSERT(v8ObjectHash);
        V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash);
        if (iter != v8NPObjectMap->end()) {
            V8NPObjectVector& objects = iter->value;
            for (size_t index = 0; index < objects.size(); ++index) {
                if (objects.at(index) == v8NpObject) {
                    objects.remove(index);
                    break;
                }
            }
            if (objects.isEmpty())
                v8NPObjectMap->remove(v8ObjectHash);
        }
    }
    v8NpObject->v8Object.Reset();
    v8NpObject->rootObject = 0;
}

} // namespace blink

bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject) {
        if (npObject->_class->invoke)
            return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result);

        VOID_TO_NPVARIANT(*result);
        return true;
    }

    PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName);
    if (!identifier->isString)
        return false;

    if (!strcmp(identifier->value.string, "eval")) {
        if (argumentCount != 1)
            return false;
        if (arguments[0].type != NPVariantType_String)
            return false;
        return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result);
    }

    // FIXME: should use the plugin's owner frame as the security context.
    ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
    if (!scriptState)
        return false;

    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object);
    v8::Handle<v8::Value> functionObject = v8Object->Get(v8AtomicString(isolate, identifier->value.string));
    if (functionObject.IsEmpty() || functionObject->IsNull()) {
        NULL_TO_NPVARIANT(*result);
        return false;
    }
    if (functionObject->IsUndefined()) {
        VOID_TO_NPVARIANT(*result);
        return false;
    }

    LocalFrame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    // Call the function object.
    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject);
    OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
    v8::Local<v8::Value> resultObject = frame->script().callFunction(function, v8Object, argumentCount, argv.get());

    // If we had an error, return false.  The spec is a little unclear here, but says "Returns true if the method was
    // successfully invoked".  If we get an error return value, was that successfully invoked?
    if (resultObject.IsEmpty())
        return false;

    convertV8ObjectToNPVariant(isolate, resultObject, npObject, result);
    return true;
}

// FIXME: Fix it same as _NPN_Invoke (HandleScope and such).
bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject) {
        if (npObject->_class->invokeDefault)
            return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result);

        VOID_TO_NPVARIANT(*result);
        return true;
    }

    VOID_TO_NPVARIANT(*result);

    ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
    if (!scriptState)
        return false;

    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    // Lookup the function object and call it.
    v8::Local<v8::Object> functionObject = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object);
    if (!functionObject->IsFunction())
        return false;

    v8::Local<v8::Value> resultObject;
    v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(functionObject);
    if (!function->IsNull()) {
        LocalFrame* frame = v8NpObject->rootObject->frame();
        ASSERT(frame);

        OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
        resultObject = frame->script().callFunction(function, functionObject, argumentCount, argv.get());
    }
    // If we had an error, return false.  The spec is a little unclear here, but says "Returns true if the method was
    // successfully invoked".  If we get an error return value, was that successfully invoked?
    if (resultObject.IsEmpty())
        return false;

    convertV8ObjectToNPVariant(isolate, resultObject, npObject, result);
    return true;
}

bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    // FIXME: Give the embedder a way to control this.
    bool popupsAllowed = false;
    return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result);
}

bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    VOID_TO_NPVARIANT(*result);
    if (!npObject)
        return false;

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
    if (!scriptState)
        return false;

    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    // FIXME: Is this branch still needed after switching to using UserGestureIndicator?
    String filename;
    if (!popupsAllowed)
        filename = "npscript";

    LocalFrame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);

    UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture);
    v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(scriptState->context(), ScriptSourceCode(script, KURL(ParsedURLString, filename)));

    if (v8result.IsEmpty())
        return false;

    if (_NPN_IsAlive(npObject))
        convertV8ObjectToNPVariant(isolate, v8result, npObject, result);
    return true;
}

bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
{
    if (!npObject)
        return false;

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;

        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
        v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(isolate, propertyName));

        if (v8result.IsEmpty())
            return false;

        convertV8ObjectToNPVariant(isolate, v8result, npObject, result);
        return true;
    }

    if (npObject->_class->hasProperty && npObject->_class->getProperty) {
        if (npObject->_class->hasProperty(npObject, propertyName))
            return npObject->_class->getProperty(npObject, propertyName, result);
    }

    VOID_TO_NPVARIANT(*result);
    return false;
}

bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
{
    if (!npObject)
        return false;

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;

        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
        obj->Set(npIdentifierToV8Identifier(isolate, propertyName), convertNPVariantToV8Object(isolate, value, object->rootObject->frame()->script().windowScriptNPObject()));
        return true;
    }

    if (npObject->_class->setProperty)
        return npObject->_class->setProperty(npObject, propertyName, value);

    return false;
}

bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    if (!npObject)
        return false;

    V8NPObject* object = npObjectToV8NPObject(npObject);
    if (!object)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
    if (!scriptState)
        return false;
    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
    // FIXME: Verify that setting to undefined is right.
    obj->Set(npIdentifierToV8Identifier(isolate, propertyName), v8::Undefined(isolate));
    return true;
}

bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    if (!npObject)
        return false;

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;
        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
        return obj->Has(npIdentifierToV8Identifier(isolate, propertyName));
    }

    if (npObject->_class->hasProperty)
        return npObject->_class->hasProperty(npObject, propertyName);
    return false;
}

bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
{
    if (!npObject)
        return false;

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;
        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
        v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(isolate, methodName));
        return prop->IsFunction();
    }

    if (npObject->_class->hasMethod)
        return npObject->_class->hasMethod(npObject, methodName);
    return false;
}

void _NPN_SetException(NPObject* npObject, const NPUTF8 *message)
{
    if (!npObject || !npObjectToV8NPObject(npObject)) {
        // We won't be able to find a proper scope for this exception, so just throw it.
        // This is consistent with JSC, which throws a global exception all the time.
        V8ThrowException::throwGeneralError(v8::Isolate::GetCurrent(), message);
        return;
    }

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    ScriptState* scriptState = mainWorldScriptState(isolate, 0, npObject);
    if (!scriptState)
        return;

    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    V8ThrowException::throwGeneralError(isolate, message);
}

bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count)
{
    if (!npObject)
        return false;

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;
        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);

        // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method when it exists, instead of evaluating javascript.

        // FIXME: Figure out how to cache this helper function.  Run a helper function that collects the properties
        // on the object into an array.
        const char enumeratorCode[] =
            "(function (obj) {"
            "  var props = [];"
            "  for (var prop in obj) {"
            "    props[props.length] = prop;"
            "  }"
            "  return props;"
            "});";
        v8::Handle<v8::String> source = v8AtomicString(isolate, enumeratorCode);
        v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, isolate);
        ASSERT(!result.IsEmpty());
        ASSERT(result->IsFunction());
        v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(result);
        v8::Handle<v8::Value> argv[] = { obj };
        v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, isolate);
        if (propsObj.IsEmpty())
            return false;

        // Convert the results into an array of NPIdentifiers.
        v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj);
        *count = props->Length();
        *identifier = static_cast<NPIdentifier*>(calloc(*count, sizeof(NPIdentifier)));
        for (uint32_t i = 0; i < *count; ++i) {
            v8::Local<v8::Value> name = props->Get(v8::Integer::New(isolate, i));
            (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name));
        }
        return true;
    }

    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate)
       return npObject->_class->enumerate(npObject, identifier, count);

    return false;
}

bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();

    if (V8NPObject* object = npObjectToV8NPObject(npObject)) {
        ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
        if (!scriptState)
            return false;
        ScriptState::Scope scope(scriptState);
        ExceptionCatcher exceptionCatcher;

        // Lookup the constructor function.
        v8::Handle<v8::Object> ctorObj = v8::Local<v8::Object>::New(isolate, object->v8Object);
        if (!ctorObj->IsFunction())
            return false;

        // Call the constructor.
        v8::Local<v8::Value> resultObject;
        v8::Handle<v8::Function> ctor = v8::Handle<v8::Function>::Cast(ctorObj);
        if (!ctor->IsNull()) {
            LocalFrame* frame = object->rootObject->frame();
            ASSERT(frame);
            OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
            resultObject = V8ObjectConstructor::newInstanceInDocument(isolate, ctor, argumentCount, argv.get(), frame ? frame->document() : 0);
        }

        if (resultObject.IsEmpty())
            return false;

        convertV8ObjectToNPVariant(isolate, resultObject, npObject, result);
        return true;
    }

    if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct)
        return npObject->_class->construct(npObject, arguments, argumentCount, result);

    return false;
}
