/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
 *  Copyright (C) 2009 Google, Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef JSDOMBinding_h
#define JSDOMBinding_h

#include "JSDOMGlobalObject.h"
#include "JSDOMWrapper.h"
#include "DOMWrapperWorld.h"
#include "Document.h"
#include <heap/Weak.h>
#include <runtime/Completion.h>
#include <runtime/Lookup.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>

namespace JSC {
    class JSGlobalData;
    class DebuggerCallFrame;
}

namespace WebCore {

    class Document;
    class Frame;
    class JSNode;
    class KURL;
    class Node;
    class ScriptController;
    class ScriptCachedFrameData;

    typedef int ExceptionCode;

    // FIXME: This class should collapse into JSDOMWrapper once all JSDOMWrappers are
    // updated to store a globalObject pointer.
    class JSDOMWrapperWithGlobalPointer : public JSDOMWrapper {
    public:
        JSDOMGlobalObject* globalObject() const
        {
            return static_cast<JSDOMGlobalObject*>(JSDOMWrapper::globalObject());
        }

        ScriptExecutionContext* scriptExecutionContext() const
        {
            // FIXME: Should never be 0, but can be due to bug 27640.
            return globalObject()->scriptExecutionContext();
        }

        static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
        {
            return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
        }

    protected:
        JSDOMWrapperWithGlobalPointer(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
            : JSDOMWrapper(globalObject, structure)
        {
            // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create
            // new JavaScript objects on detached windows due to DOMWindow::document()
            // needing to reach through the frame to get to the Document*.  See bug 27640.
            // ASSERT(globalObject->scriptExecutionContext());
        }
    };

    // Base class for all constructor objects in the JSC bindings.
    class DOMConstructorObject : public JSDOMWrapperWithGlobalPointer {
    public:
        static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
        {
            return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
        }

    protected:
        static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesMarkChildren | JSDOMWrapperWithGlobalPointer::StructureFlags;
        DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
            : JSDOMWrapperWithGlobalPointer(structure, globalObject)
        {
        }
    };

    // Constructors using this base class depend on being in a Document and
    // can never be used from a WorkerContext.
    class DOMConstructorWithDocument : public DOMConstructorObject {
    public:
        Document* document() const
        {
            return static_cast<Document*>(scriptExecutionContext());
        }

    protected:
        DOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
            : DOMConstructorObject(structure, globalObject)
        {
            ASSERT(globalObject->scriptExecutionContext()->isDocument());
        }
    };
    
    void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
    void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);

    JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
    JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, JSC::Structure*, const JSC::ClassInfo*);

    inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
    {
        // FIXME: Callers to this function should be using the global object
        // from which the object is being created, instead of assuming the lexical one.
        // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
        return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
    }

    template<class WrapperClass> inline JSC::Structure* getDOMStructure(JSC::ExecState* exec, JSDOMGlobalObject* globalObject)
    {
        if (JSC::Structure* structure = getCachedDOMStructure(globalObject, &WrapperClass::s_info))
            return structure;
        return cacheDOMStructure(globalObject, WrapperClass::createStructure(exec->globalData(), WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info);
    }

    template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
    {
        // FIXME: This function is wrong.  It uses the wrong global object for creating the prototype structure.
        return getDOMStructure<WrapperClass>(exec, deprecatedGlobalObjectForPrototype(exec));
    }

    template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
    {
        return static_cast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(exec, static_cast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
    }

    // Overload these functions to provide a fast path for wrapper access.
    inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld*, void*) { return 0; }
    inline bool setInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }
    inline bool clearInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }

    // Overload these functions to provide a custom WeakHandleOwner.
    inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld* world, void*) { return world->defaultWrapperOwner(); }
    inline void* wrapperContext(DOMWrapperWorld*, void* domObject) { return domObject; }

    template <typename DOMClass> inline JSDOMWrapper* getCachedWrapper(DOMWrapperWorld* world, DOMClass* domObject)
    {
        if (JSDOMWrapper* wrapper = getInlineCachedWrapper(world, domObject))
            return wrapper;
        return world->m_wrappers.get(domObject).get();
    }

    template <typename DOMClass> inline void cacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
    {
        if (setInlineCachedWrapper(world, domObject, wrapper))
            return;
        ASSERT(!world->m_wrappers.contains(domObject));
        world->m_wrappers.set(domObject, JSC::Weak<JSDOMWrapper>(*world->globalData(), wrapper, wrapperOwner(world, domObject), wrapperContext(world, domObject)));
    }

    template <typename DOMClass> inline void uncacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
    {
        if (clearInlineCachedWrapper(world, domObject, wrapper))
            return;
        ASSERT(world->m_wrappers.find(domObject)->second.get() == wrapper);
        world->m_wrappers.remove(domObject);
    }
    
    #define CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
    #define CREATE_DOM_NODE_WRAPPER(exec, globalObject, className, object) static_cast<JSNode*>(createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object)))
    template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
    {
        ASSERT(node);
        ASSERT(!getCachedWrapper(currentWorld(exec), node));
        WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node);
        // FIXME: The entire function can be removed, once we fix caching.
        // This function is a one-off hack to make Nodes cache in the right global object.
        cacheWrapper(currentWorld(exec), node, wrapper);
        return wrapper;
    }

    template<class WrapperClass, class DOMClass> inline JSC::JSValue wrap(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject)
    {
        if (!domObject)
            return JSC::jsNull();
        if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), domObject))
            return wrapper;
        return createWrapper<WrapperClass>(exec, globalObject, domObject);
    }

    const JSC::HashTable* getHashTableForGlobalData(JSC::JSGlobalData&, const JSC::HashTable* staticTable);

    void reportException(JSC::ExecState*, JSC::JSValue exception);
    void reportCurrentException(JSC::ExecState*);

    // Convert a DOM implementation exception code into a JavaScript exception in the execution state.
    void setDOMException(JSC::ExecState*, ExceptionCode);

    JSC::JSValue jsString(JSC::ExecState*, const String&); // empty if the string is null
    JSC::JSValue jsStringSlowCase(JSC::ExecState*, JSStringCache&, StringImpl*);
    JSC::JSValue jsString(JSC::ExecState*, const KURL&); // empty if the URL is null
    inline JSC::JSValue jsString(JSC::ExecState* exec, const AtomicString& s)
    { 
        return jsString(exec, s.string());
    }
        
    JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null
    JSC::JSValue jsStringOrNull(JSC::ExecState*, const KURL&); // null if the URL is null

    JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const String&); // undefined if the string is null
    JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const KURL&); // undefined if the URL is null

    JSC::JSValue jsStringOrFalse(JSC::ExecState*, const String&); // boolean false if the string is null
    JSC::JSValue jsStringOrFalse(JSC::ExecState*, const KURL&); // boolean false if the URL is null

    // See JavaScriptCore for explanation: Should be used for any string that is already owned by another
    // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory.
    JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const String&); 

    String identifierToString(const JSC::Identifier&);
    String ustringToString(const JSC::UString&);
    JSC::UString stringToUString(const String&);

    AtomicString identifierToAtomicString(const JSC::Identifier&);
    AtomicString ustringToAtomicString(const JSC::UString&);
    AtomicStringImpl* findAtomicString(const JSC::Identifier&);

    String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null
    String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined

    inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
    {
        double number = value.toNumber(exec);
        okay = isfinite(number);
        return JSC::toInt32(number);
    }

    // Returns a Date instance for the specified value, or null if the value is NaN or infinity.
    JSC::JSValue jsDateOrNull(JSC::ExecState*, double);
    // NaN if the value can't be converted to a date.
    double valueToDate(JSC::ExecState*, JSC::JSValue);

    // FIXME: These are a stop-gap until all toJS calls can be converted to pass a globalObject
    template <typename T>
    inline JSC::JSValue toJS(JSC::ExecState* exec, T* ptr)
    {
        return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr);
    }
    template <typename T>
    inline JSC::JSValue toJS(JSC::ExecState* exec, PassRefPtr<T> ptr)
    {
        return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr.get());
    }
    template <typename T>
    inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* exec, T* ptr)
    {
        return toJSNewlyCreated(exec, deprecatedGlobalObjectForPrototype(exec), ptr);
    }

    template <typename T>
    inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr)
    {
        return toJS(exec, globalObject, ptr.get());
    }

    // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
    JSC::JSObject* toJSSequence(JSC::ExecState*, JSC::JSValue, unsigned&);

    bool checkNodeSecurity(JSC::ExecState*, Node*);

    // Helpers for Window, History, and Location classes to implement cross-domain policy.
    // Besides the cross-domain check, they need non-caching versions of staticFunctionGetter for
    // because we do not want current property values involved at all.
    // FIXME: These functions should be named frameAllowsAccessFrom, because the access is *to* the frame.
    bool allowsAccessFromFrame(JSC::ExecState*, Frame*);
    bool allowsAccessFromFrame(JSC::ExecState*, Frame*, String& message);
    DOMWindow* activeDOMWindow(JSC::ExecState*);
    DOMWindow* firstDOMWindow(JSC::ExecState*);

    void printErrorMessageForFrame(Frame*, const String& message);
    JSC::JSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier& propertyName);

    Frame* toDynamicFrame(JSC::ExecState*);
    bool processingUserGesture();
    
    inline JSC::JSValue jsString(JSC::ExecState* exec, const String& s)
    {
        StringImpl* stringImpl = s.impl();
        if (!stringImpl || !stringImpl->length())
            return jsEmptyString(exec);

        if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF)
            return jsString(exec, stringToUString(s));

        JSStringCache& stringCache = currentWorld(exec)->m_stringCache;
        if (JSC::JSString* wrapper = stringCache.get(stringImpl))
            return wrapper;

        return jsStringSlowCase(exec, stringCache, stringImpl);
    }

    inline DOMObjectWrapperMap& domObjectWrapperMapFor(JSC::ExecState* exec)
    {
        return currentWorld(exec)->m_wrappers;
    }

    inline String ustringToString(const JSC::UString& u)
    {
        return u.impl();
    }

    inline JSC::UString stringToUString(const String& s)
    {
        return JSC::UString(s.impl());
    }

    inline String identifierToString(const JSC::Identifier& i)
    {
        return i.impl();
    }

    inline AtomicString ustringToAtomicString(const JSC::UString& u)
    {
        return AtomicString(u.impl());
    }

    inline AtomicString identifierToAtomicString(const JSC::Identifier& identifier)
    {
        return AtomicString(identifier.impl());
    }

} // namespace WebCore

#endif // JSDOMBinding_h
