Home | History | Annotate | Download | only in js
      1 /*
      2  *  Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      3  *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Lesser General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Lesser General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Lesser General Public
     16  *  License along with this library; if not, write to the Free Software
     17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18  */
     19 
     20 #ifndef JSEventListener_h
     21 #define JSEventListener_h
     22 
     23 #include "EventListener.h"
     24 #include "JSDOMWindow.h"
     25 #include <heap/Weak.h>
     26 
     27 namespace WebCore {
     28 
     29     class JSDOMGlobalObject;
     30 
     31     class JSEventListener : public EventListener {
     32     public:
     33         static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld)
     34         {
     35             return adoptRef(new JSEventListener(listener, wrapper, isAttribute, isolatedWorld));
     36         }
     37 
     38         static const JSEventListener* cast(const EventListener* listener)
     39         {
     40             return listener->type() == JSEventListenerType
     41                 ? static_cast<const JSEventListener*>(listener)
     42                 : 0;
     43         }
     44 
     45         virtual ~JSEventListener();
     46 
     47         virtual bool operator==(const EventListener& other);
     48 
     49         // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
     50         bool isAttribute() const { return m_isAttribute; }
     51 
     52         JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
     53         DOMWrapperWorld* isolatedWorld() const { return m_isolatedWorld.get(); }
     54 
     55         JSC::JSObject* wrapper() const { return m_wrapper.get(); }
     56         void setWrapper(JSC::JSGlobalData& globalData, JSC::JSObject* wrapper) const { m_wrapper.set(globalData, wrapper, 0); }
     57 
     58     private:
     59         virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
     60         virtual void markJSFunction(JSC::MarkStack&);
     61         virtual bool virtualisAttribute() const;
     62 
     63     protected:
     64         JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld);
     65         virtual void handleEvent(ScriptExecutionContext*, Event*);
     66 
     67     private:
     68         mutable JSC::WriteBarrier<JSC::JSObject> m_jsFunction;
     69         mutable JSC::Weak<JSC::JSObject> m_wrapper;
     70 
     71         bool m_isAttribute;
     72         RefPtr<DOMWrapperWorld> m_isolatedWorld;
     73     };
     74 
     75     inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
     76     {
     77         if (!m_jsFunction)
     78             m_jsFunction.set(*scriptExecutionContext->globalData(), m_wrapper.get(), initializeJSFunction(scriptExecutionContext));
     79 
     80         // Verify that we have a valid wrapper protecting our function from
     81         // garbage collection.
     82         ASSERT(m_wrapper || !m_jsFunction);
     83         if (!m_wrapper)
     84             return 0;
     85 
     86         // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an
     87         // event listener can be almost anything, but this makes test-writing easier).
     88         ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject());
     89 
     90         return m_jsFunction.get();
     91     }
     92 
     93     // Creates a JS EventListener for an "onXXX" event attribute.
     94     inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper)
     95     {
     96         if (!listener.isObject())
     97             return 0;
     98 
     99         return JSEventListener::create(asObject(listener), wrapper, true, currentWorld(exec));
    100     }
    101 
    102 
    103 } // namespace WebCore
    104 
    105 #endif // JSEventListener_h
    106