Reviewed by Darin Adler.
https://bugs.webkit.org/show_bug.cgi?id=21970
Make MessagePort event dispatch work in workers
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::JSDOMGlobalObjectData::JSDOMGlobalObjectData):
(WebCore::JSDOMGlobalObject::~JSDOMGlobalObject):
(WebCore::JSDOMGlobalObject::findJSEventListener):
(WebCore::JSDOMGlobalObject::findOrCreateJSEventListener):
(WebCore::JSDOMGlobalObject::findJSUnprotectedEventListener):
(WebCore::JSDOMGlobalObject::findOrCreateJSUnprotectedEventListener):
(WebCore::JSDOMGlobalObject::jsEventListeners):
(WebCore::JSDOMGlobalObject::jsInlineEventListeners):
(WebCore::JSDOMGlobalObject::jsUnprotectedEventListeners):
(WebCore::JSDOMGlobalObject::jsUnprotectedInlineEventListeners):
(WebCore::JSDOMGlobalObject::setCurrentEvent):
(WebCore::JSDOMGlobalObject::currentEvent):
(WebCore::toJSDOMGlobalObject):
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData):
(WebCore::JSDOMWindowBase::~JSDOMWindowBase):
(WebCore::JSDOMWindowBase::clearHelperObjectProperties):
* bindings/js/JSDOMWindowBase.h:
Moved event listener tracking from JSDOMWindow to JSDOMGlobalObject.
* bindings/js/JSEventListener.cpp:
(WebCore::JSAbstractEventListener::handleEvent):
(WebCore::JSUnprotectedEventListener::JSUnprotectedEventListener):
(WebCore::JSUnprotectedEventListener::~JSUnprotectedEventListener):
(WebCore::JSUnprotectedEventListener::globalObject):
(WebCore::JSUnprotectedEventListener::clearGlobalObject):
(WebCore::JSEventListener::JSEventListener):
(WebCore::JSEventListener::~JSEventListener):
(WebCore::JSEventListener::globalObject):
(WebCore::JSEventListener::clearGlobalObject):
(WebCore::JSLazyEventListener::JSLazyEventListener):
(WebCore::JSLazyEventListener::parseCode):
* bindings/js/JSEventListener.h:
(WebCore::JSUnprotectedEventListener::create):
(WebCore::JSEventListener::create):
(WebCore::JSLazyEventListener::create):
Changed to use JSDOMGlobalObject and ScriptExecutionContext.
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::JSMessagePort::startConversation):
(WebCore::JSMessagePort::addEventListener):
(WebCore::JSMessagePort::removeEventListener):
(WebCore::JSMessagePort::setOnmessage):
(WebCore::JSMessagePort::setOnclose):
Updated bindings to work with JSDOMGlobalObject. Next step is to make code generator emit
such code, and stop using a custom implementation for JSMessagePort inline event handler
getters and setters.
* dom/Document.cpp:
(WebCore::Document::virtualURL):
* dom/Document.h:
* dom/ScriptExecutionContext.h:
Expose url() method on ScriptExecutionContext (necessary for compiling scripts in
JSLazyEventListener).
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 66480bd..ca7179e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,67 @@
+2008-10-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ https://bugs.webkit.org/show_bug.cgi?id=21970
+ Make MessagePort event dispatch work in workers
+
+ * bindings/js/JSDOMGlobalObject.cpp:
+ (WebCore::JSDOMGlobalObject::JSDOMGlobalObjectData::JSDOMGlobalObjectData):
+ (WebCore::JSDOMGlobalObject::~JSDOMGlobalObject):
+ (WebCore::JSDOMGlobalObject::findJSEventListener):
+ (WebCore::JSDOMGlobalObject::findOrCreateJSEventListener):
+ (WebCore::JSDOMGlobalObject::findJSUnprotectedEventListener):
+ (WebCore::JSDOMGlobalObject::findOrCreateJSUnprotectedEventListener):
+ (WebCore::JSDOMGlobalObject::jsEventListeners):
+ (WebCore::JSDOMGlobalObject::jsInlineEventListeners):
+ (WebCore::JSDOMGlobalObject::jsUnprotectedEventListeners):
+ (WebCore::JSDOMGlobalObject::jsUnprotectedInlineEventListeners):
+ (WebCore::JSDOMGlobalObject::setCurrentEvent):
+ (WebCore::JSDOMGlobalObject::currentEvent):
+ (WebCore::toJSDOMGlobalObject):
+ * bindings/js/JSDOMGlobalObject.h:
+ * bindings/js/JSDOMWindowBase.cpp:
+ (WebCore::JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData):
+ (WebCore::JSDOMWindowBase::~JSDOMWindowBase):
+ (WebCore::JSDOMWindowBase::clearHelperObjectProperties):
+ * bindings/js/JSDOMWindowBase.h:
+ Moved event listener tracking from JSDOMWindow to JSDOMGlobalObject.
+
+ * bindings/js/JSEventListener.cpp:
+ (WebCore::JSAbstractEventListener::handleEvent):
+ (WebCore::JSUnprotectedEventListener::JSUnprotectedEventListener):
+ (WebCore::JSUnprotectedEventListener::~JSUnprotectedEventListener):
+ (WebCore::JSUnprotectedEventListener::globalObject):
+ (WebCore::JSUnprotectedEventListener::clearGlobalObject):
+ (WebCore::JSEventListener::JSEventListener):
+ (WebCore::JSEventListener::~JSEventListener):
+ (WebCore::JSEventListener::globalObject):
+ (WebCore::JSEventListener::clearGlobalObject):
+ (WebCore::JSLazyEventListener::JSLazyEventListener):
+ (WebCore::JSLazyEventListener::parseCode):
+ * bindings/js/JSEventListener.h:
+ (WebCore::JSUnprotectedEventListener::create):
+ (WebCore::JSEventListener::create):
+ (WebCore::JSLazyEventListener::create):
+ Changed to use JSDOMGlobalObject and ScriptExecutionContext.
+
+ * bindings/js/JSMessagePortCustom.cpp:
+ (WebCore::JSMessagePort::startConversation):
+ (WebCore::JSMessagePort::addEventListener):
+ (WebCore::JSMessagePort::removeEventListener):
+ (WebCore::JSMessagePort::setOnmessage):
+ (WebCore::JSMessagePort::setOnclose):
+ Updated bindings to work with JSDOMGlobalObject. Next step is to make code generator emit
+ such code, and stop using a custom implementation for JSMessagePort inline event handler
+ getters and setters.
+
+ * dom/Document.cpp:
+ (WebCore::Document::virtualURL):
+ * dom/Document.h:
+ * dom/ScriptExecutionContext.h:
+ Expose url() method on ScriptExecutionContext (necessary for compiling scripts in
+ JSLazyEventListener).
+
2008-10-31 Cameron Zwarich <zwarich@apple.com>
Not reviewed.
@@ -170,6 +234,7 @@
doesn't really fix a bug, since we can't really get into a situation where we move to a different
topBlockquote, but it simplifies the code.
+>>>>>>> .r38031
2008-10-30 Dirk Schulze <vbs85@gmx.de>
Reviewed by Alp Toker.
diff --git a/WebCore/bindings/js/JSDOMGlobalObject.cpp b/WebCore/bindings/js/JSDOMGlobalObject.cpp
index 8260459..d9dae37 100644
--- a/WebCore/bindings/js/JSDOMGlobalObject.cpp
+++ b/WebCore/bindings/js/JSDOMGlobalObject.cpp
@@ -27,15 +27,48 @@
#include "config.h"
#include "JSDOMGlobalObject.h"
+#include "Document.h"
+#include "JSDOMWindow.h"
+#include "JSEventListener.h"
+
using namespace JSC;
namespace WebCore {
+JSDOMGlobalObject::JSDOMGlobalObjectData::JSDOMGlobalObjectData()
+ : evt(0)
+{
+}
+
JSDOMGlobalObject::JSDOMGlobalObject(PassRefPtr<StructureID> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue)
: JSGlobalObject(structure, data, thisValue)
{
}
+JSDOMGlobalObject::~JSDOMGlobalObject()
+{
+ // Clear any backpointers to the window
+ ListenersMap::iterator i1 = d()->jsEventListeners.begin();
+ ListenersMap::iterator e1 = d()->jsEventListeners.end();
+ for (; i1 != e1; ++i1)
+ i1->second->clearGlobalObject();
+
+ i1 = d()->jsInlineEventListeners.begin();
+ e1 = d()->jsInlineEventListeners.end();
+ for (; i1 != e1; ++i1)
+ i1->second->clearGlobalObject();
+
+ UnprotectedListenersMap::iterator i2 = d()->jsUnprotectedEventListeners.begin();
+ UnprotectedListenersMap::iterator e2 = d()->jsUnprotectedEventListeners.end();
+ for (; i2 != e2; ++i2)
+ i2->second->clearGlobalObject();
+
+ i2 = d()->jsUnprotectedInlineEventListeners.begin();
+ e2 = d()->jsUnprotectedInlineEventListeners.end();
+ for (; i2 != e2; ++i2)
+ i2->second->clearGlobalObject();
+}
+
void JSDOMGlobalObject::mark()
{
Base::mark();
@@ -51,4 +84,85 @@
}
}
+JSEventListener* JSDOMGlobalObject::findJSEventListener(JSValue* val, bool isInline)
+{
+ if (!val->isObject())
+ return 0;
+ JSObject* object = asObject(val);
+ ListenersMap& listeners = isInline ? d()->jsInlineEventListeners : d()->jsEventListeners;
+ return listeners.get(object);
+}
+
+PassRefPtr<JSEventListener> JSDOMGlobalObject::findOrCreateJSEventListener(ExecState* exec, JSValue* val, bool isInline)
+{
+ if (JSEventListener* listener = findJSEventListener(val, isInline))
+ return listener;
+
+ if (!val->isObject())
+ return 0;
+
+ // The JSEventListener constructor adds it to our jsEventListeners map.
+ return JSEventListener::create(asObject(val), this, isInline).get();
+}
+
+JSUnprotectedEventListener* JSDOMGlobalObject::findJSUnprotectedEventListener(ExecState* exec, JSValue* val, bool isInline)
+{
+ if (!val->isObject())
+ return 0;
+
+ UnprotectedListenersMap& listeners = isInline ? d()->jsUnprotectedInlineEventListeners : d()->jsUnprotectedEventListeners;
+ return listeners.get(asObject(val));
+}
+
+PassRefPtr<JSUnprotectedEventListener> JSDOMGlobalObject::findOrCreateJSUnprotectedEventListener(ExecState* exec, JSValue* val, bool isInline)
+{
+ if (JSUnprotectedEventListener* listener = findJSUnprotectedEventListener(exec, val, isInline))
+ return listener;
+
+ if (!val->isObject())
+ return 0;
+
+ // The JSUnprotectedEventListener constructor adds it to our jsUnprotectedEventListeners map.
+ return JSUnprotectedEventListener::create(asObject(val), this, isInline).get();
+}
+
+JSDOMGlobalObject::ListenersMap& JSDOMGlobalObject::jsEventListeners()
+{
+ return d()->jsEventListeners;
+}
+
+JSDOMGlobalObject::ListenersMap& JSDOMGlobalObject::jsInlineEventListeners()
+{
+ return d()->jsInlineEventListeners;
+}
+
+JSDOMGlobalObject::UnprotectedListenersMap& JSDOMGlobalObject::jsUnprotectedEventListeners()
+{
+ return d()->jsUnprotectedEventListeners;
+}
+
+JSDOMGlobalObject::UnprotectedListenersMap& JSDOMGlobalObject::jsUnprotectedInlineEventListeners()
+{
+ return d()->jsUnprotectedInlineEventListeners;
+}
+
+void JSDOMGlobalObject::setCurrentEvent(Event* evt)
+{
+ d()->evt = evt;
+}
+
+Event* JSDOMGlobalObject::currentEvent()
+{
+ return d()->evt;
+}
+
+JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext)
+{
+ if (scriptExecutionContext->isDocument())
+ return toJSDOMWindow(static_cast<Document*>(scriptExecutionContext)->frame());
+
+ // Not implemented yet.
+ return 0;
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSDOMGlobalObject.h b/WebCore/bindings/js/JSDOMGlobalObject.h
index f31b9a5..3c210bb 100644
--- a/WebCore/bindings/js/JSDOMGlobalObject.h
+++ b/WebCore/bindings/js/JSDOMGlobalObject.h
@@ -31,6 +31,9 @@
namespace WebCore {
+ class Event;
+ class JSEventListener;
+ class JSUnprotectedEventListener;
class ScriptExecutionContext;
typedef HashMap<const JSC::ClassInfo*, RefPtr<JSC::StructureID> > JSDOMStructureMap;
@@ -39,12 +42,10 @@
class JSDOMGlobalObject : public JSC::JSGlobalObject {
typedef JSC::JSGlobalObject Base;
protected:
- struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData {
- JSDOMStructureMap structures;
- JSDOMConstructorMap constructors;
- };
+ struct JSDOMGlobalObjectData;
JSDOMGlobalObject(PassRefPtr<JSC::StructureID>, JSDOMGlobalObjectData*, JSC::JSObject* thisValue);
+ virtual ~JSDOMGlobalObject();
public:
JSDOMStructureMap& structures() { return d()->structures; }
@@ -52,8 +53,46 @@
virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
+ // Finds a wrapper of a JS EventListener, returns 0 if no existing one.
+ JSEventListener* findJSEventListener(JSC::JSValue*, bool isInline = false);
+
+ // Finds or creates a wrapper of a JS EventListener. JS EventListener object is GC-protected.
+ PassRefPtr<JSEventListener> findOrCreateJSEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
+
+ // Finds a wrapper of a GC-unprotected JS EventListener, returns 0 if no existing one.
+ JSUnprotectedEventListener* findJSUnprotectedEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
+
+ // Finds or creates a wrapper of a JS EventListener. JS EventListener object is *NOT* GC-protected.
+ PassRefPtr<JSUnprotectedEventListener> findOrCreateJSUnprotectedEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
+
+ typedef HashMap<JSC::JSObject*, JSEventListener*> ListenersMap;
+ typedef HashMap<JSC::JSObject*, JSUnprotectedEventListener*> UnprotectedListenersMap;
+
+ ListenersMap& jsEventListeners();
+ ListenersMap& jsInlineEventListeners();
+ UnprotectedListenersMap& jsUnprotectedEventListeners();
+ UnprotectedListenersMap& jsUnprotectedInlineEventListeners();
+
+ void setCurrentEvent(Event*);
+ Event* currentEvent();
+
virtual void mark();
+ protected:
+ struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData {
+ JSDOMGlobalObjectData();
+
+ JSDOMStructureMap structures;
+ JSDOMConstructorMap constructors;
+
+ JSDOMGlobalObject::ListenersMap jsEventListeners;
+ JSDOMGlobalObject::ListenersMap jsInlineEventListeners;
+ JSDOMGlobalObject::UnprotectedListenersMap jsUnprotectedEventListeners;
+ JSDOMGlobalObject::UnprotectedListenersMap jsUnprotectedInlineEventListeners;
+
+ Event* evt;
+ };
+
private:
JSDOMGlobalObjectData* d() const { return static_cast<JSDOMGlobalObjectData*>(JSC::JSVariableObject::d); }
};
@@ -79,6 +118,8 @@
return constructor;
}
+ JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*);
+
} // namespace WebCore
#endif // JSDOMGlobalObject_h
diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp
index bbc3139..c1bac66 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -167,7 +167,6 @@
JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
: impl(window)
- , evt(0)
, returnValueSlot(0)
, shell(shell)
{
@@ -200,27 +199,6 @@
d()->impl->frame()->script()->clearFormerWindow(asJSDOMWindow(this));
clearAllTimeouts();
-
- // Clear any backpointers to the window
- ListenersMap::iterator i2 = d()->jsEventListeners.begin();
- ListenersMap::iterator e2 = d()->jsEventListeners.end();
- for (; i2 != e2; ++i2)
- i2->second->clearWindow();
-
- i2 = d()->jsInlineEventListeners.begin();
- e2 = d()->jsInlineEventListeners.end();
- for (; i2 != e2; ++i2)
- i2->second->clearWindow();
-
- UnprotectedListenersMap::iterator i1 = d()->jsUnprotectedEventListeners.begin();
- UnprotectedListenersMap::iterator e1 = d()->jsUnprotectedEventListeners.end();
- for (; i1 != e1; ++i1)
- i1->second->clearWindow();
-
- i1 = d()->jsUnprotectedInlineEventListeners.begin();
- e1 = d()->jsUnprotectedInlineEventListeners.end();
- for (; i1 != e1; ++i1)
- i1->second->clearWindow();
}
ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
@@ -736,51 +714,9 @@
return page->chrome()->shouldInterruptJavaScript();
}
-JSEventListener* JSDOMWindowBase::findJSEventListener(JSValue* val, bool isInline)
-{
- if (!val->isObject())
- return 0;
- JSObject* object = asObject(val);
- ListenersMap& listeners = isInline ? d()->jsInlineEventListeners : d()->jsEventListeners;
- return listeners.get(object);
-}
-
-PassRefPtr<JSEventListener> JSDOMWindowBase::findOrCreateJSEventListener(ExecState* exec, JSValue* val, bool isInline)
-{
- if (JSEventListener* listener = findJSEventListener(val, isInline))
- return listener;
-
- if (!val->isObject())
- return 0;
-
- // The JSEventListener constructor adds it to our jsEventListeners map.
- return JSEventListener::create(asObject(val), static_cast<JSDOMWindow*>(this), isInline).get();
-}
-
-JSUnprotectedEventListener* JSDOMWindowBase::findJSUnprotectedEventListener(ExecState* exec, JSValue* val, bool isInline)
-{
- if (!val->isObject())
- return 0;
-
- UnprotectedListenersMap& listeners = isInline ? d()->jsUnprotectedInlineEventListeners : d()->jsUnprotectedEventListeners;
- return listeners.get(asObject(val));
-}
-
-PassRefPtr<JSUnprotectedEventListener> JSDOMWindowBase::findOrCreateJSUnprotectedEventListener(ExecState* exec, JSValue* val, bool isInline)
-{
- if (JSUnprotectedEventListener* listener = findJSUnprotectedEventListener(exec, val, isInline))
- return listener;
-
- if (!val->isObject())
- return 0;
-
- // The JSUnprotectedEventListener constructor adds it to our jsUnprotectedEventListeners map.
- return JSUnprotectedEventListener::create(asObject(val), static_cast<JSDOMWindow*>(this), isInline).get();
-}
-
void JSDOMWindowBase::clearHelperObjectProperties()
{
- d()->evt = 0;
+ setCurrentEvent(0);
}
void JSDOMWindowBase::clear()
@@ -794,16 +730,6 @@
clearHelperObjectProperties();
}
-void JSDOMWindowBase::setCurrentEvent(Event* evt)
-{
- d()->evt = evt;
-}
-
-Event* JSDOMWindowBase::currentEvent()
-{
- return d()->evt;
-}
-
JSObject* JSDOMWindowBase::toThisObject(ExecState*) const
{
return shell();
@@ -1057,26 +983,6 @@
clearAllTimeouts();
}
-JSDOMWindowBase::ListenersMap& JSDOMWindowBase::jsEventListeners()
-{
- return d()->jsEventListeners;
-}
-
-JSDOMWindowBase::ListenersMap& JSDOMWindowBase::jsInlineEventListeners()
-{
- return d()->jsInlineEventListeners;
-}
-
-JSDOMWindowBase::UnprotectedListenersMap& JSDOMWindowBase::jsUnprotectedEventListeners()
-{
- return d()->jsUnprotectedEventListeners;
-}
-
-JSDOMWindowBase::UnprotectedListenersMap& JSDOMWindowBase::jsUnprotectedInlineEventListeners()
-{
- return d()->jsUnprotectedInlineEventListeners;
-}
-
void DOMWindowTimer::fired()
{
timerNestingLevel = m_nestingLevel;
diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h
index 0cd0ae3..f345f47 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.h
+++ b/WebCore/bindings/js/JSDOMWindowBase.h
@@ -76,34 +76,11 @@
void timerFired(DOMWindowTimer*);
- // Finds a wrapper of a JS EventListener, returns 0 if no existing one.
- JSEventListener* findJSEventListener(JSC::JSValue*, bool isInline = false);
-
- // Finds or creates a wrapper of a JS EventListener. JS EventListener object is GC-protected.
- PassRefPtr<JSEventListener> findOrCreateJSEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
-
- // Finds a wrapper of a GC-unprotected JS EventListener, returns 0 if no existing one.
- JSUnprotectedEventListener* findJSUnprotectedEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
-
- // Finds or creates a wrapper of a JS EventListener. JS EventListener object is *NOT* GC-protected.
- PassRefPtr<JSUnprotectedEventListener> findOrCreateJSUnprotectedEventListener(JSC::ExecState*, JSC::JSValue*, bool isInline = false);
-
void clear();
- void setCurrentEvent(Event*);
- Event* currentEvent();
-
// Set a place to put a dialog return value when the window is cleared.
void setReturnValueSlot(JSC::JSValue** slot);
- typedef HashMap<JSC::JSObject*, JSEventListener*> ListenersMap;
- typedef HashMap<JSC::JSObject*, JSUnprotectedEventListener*> UnprotectedListenersMap;
-
- ListenersMap& jsEventListeners();
- ListenersMap& jsInlineEventListeners();
- UnprotectedListenersMap& jsUnprotectedEventListeners();
- UnprotectedListenersMap& jsUnprotectedInlineEventListeners();
-
virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
static const JSC::ClassInfo s_info;
@@ -135,11 +112,6 @@
RefPtr<DOMWindow> impl;
- JSDOMWindowBase::ListenersMap jsEventListeners;
- JSDOMWindowBase::ListenersMap jsInlineEventListeners;
- JSDOMWindowBase::UnprotectedListenersMap jsUnprotectedEventListeners;
- JSDOMWindowBase::UnprotectedListenersMap jsUnprotectedInlineEventListeners;
- Event* evt;
JSC::JSValue** returnValueSlot;
JSDOMWindowShell* shell;
diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp
index b720d62..0944816 100644
--- a/WebCore/bindings/js/JSEventListener.cpp
+++ b/WebCore/bindings/js/JSEventListener.cpp
@@ -53,23 +53,34 @@
if (!listener)
return;
- JSDOMWindow* window = this->window();
- // Null check as clearWindow() can clear this and we still get called back by
+ JSDOMGlobalObject* globalObject = this->globalObject();
+ // Null check as clearGlobalObject() can clear this and we still get called back by
// xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
- if (!window)
- return;
- Frame* frame = window->impl()->frame();
- if (!frame)
- return;
- // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
- // FIXME: A better fix for this may be to change DMOWindow::frame() to not return a frame the detached window used to be in.
- if (frame->domWindow() != window->impl())
- return;
- ScriptController* script = frame->script();
- if (!script->isEnabled() || script->isPaused())
+ // FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called.
+ if (!globalObject)
return;
- ExecState* exec = window->globalExec();
+ ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
+ if (!scriptExecutionContext)
+ return;
+
+ Frame* frame = 0;
+ if (scriptExecutionContext->isDocument()) {
+ JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
+ frame = window->impl()->frame();
+ if (!frame)
+ return;
+ // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
+ // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
+ if (frame->domWindow() != window->impl())
+ return;
+ // FIXME: Is this check needed for other contexts?
+ ScriptController* script = frame->script();
+ if (!script->isEnabled() || script->isPaused())
+ return;
+ }
+
+ ExecState* exec = globalObject->globalExec();
JSValue* handleEventFunction = listener->get(exec, Identifier(exec, "handleEvent"));
CallData callData;
@@ -85,29 +96,31 @@
ArgList args;
args.append(toJS(exec, event));
- Event* savedEvent = window->currentEvent();
- window->setCurrentEvent(event);
+ Event* savedEvent = globalObject->currentEvent();
+ globalObject->setCurrentEvent(event);
JSValue* retval;
if (handleEventFunction) {
- window->startTimeoutCheck();
+ globalObject->startTimeoutCheck();
retval = call(exec, handleEventFunction, callType, callData, listener, args);
} else {
JSValue* thisValue;
if (isWindowEvent)
- thisValue = window->shell();
+ thisValue = globalObject->toThisObject(exec);
else
thisValue = toJS(exec, event->currentTarget());
- window->startTimeoutCheck();
+ globalObject->startTimeoutCheck();
retval = call(exec, listener, callType, callData, thisValue, args);
}
- window->stopTimeoutCheck();
+ globalObject->stopTimeoutCheck();
- window->setCurrentEvent(savedEvent);
+ globalObject->setCurrentEvent(savedEvent);
- if (exec->hadException())
- frame->domWindow()->console()->reportCurrentException(exec);
- else {
+ if (exec->hadException()) {
+ // FIXME: Report exceptions in non-Document contexts.
+ if (frame)
+ frame->domWindow()->console()->reportCurrentException(exec);
+ } else {
if (!retval->isUndefinedOrNull() && event->storesResultAsString())
event->storeResult(retval->toString(exec));
if (m_isInline) {
@@ -129,23 +142,23 @@
// -------------------------------------------------------------------------
-JSUnprotectedEventListener::JSUnprotectedEventListener(JSObject* listener, JSDOMWindow* window, bool isInline)
+JSUnprotectedEventListener::JSUnprotectedEventListener(JSObject* listener, JSDOMGlobalObject* globalObject, bool isInline)
: JSAbstractEventListener(isInline)
, m_listener(listener)
- , m_window(window)
+ , m_globalObject(globalObject)
{
if (m_listener) {
JSDOMWindow::UnprotectedListenersMap& listeners = isInline
- ? window->jsUnprotectedInlineEventListeners() : window->jsUnprotectedEventListeners();
+ ? globalObject->jsUnprotectedInlineEventListeners() : globalObject->jsUnprotectedEventListeners();
listeners.set(m_listener, this);
}
}
JSUnprotectedEventListener::~JSUnprotectedEventListener()
{
- if (m_listener && m_window) {
+ if (m_listener && m_globalObject) {
JSDOMWindow::UnprotectedListenersMap& listeners = isInline()
- ? m_window->jsUnprotectedInlineEventListeners() : m_window->jsUnprotectedEventListeners();
+ ? m_globalObject->jsUnprotectedInlineEventListeners() : m_globalObject->jsUnprotectedEventListeners();
listeners.remove(m_listener);
}
}
@@ -155,14 +168,14 @@
return m_listener;
}
-JSDOMWindow* JSUnprotectedEventListener::window() const
+JSDOMGlobalObject* JSUnprotectedEventListener::globalObject() const
{
- return m_window;
+ return m_globalObject;
}
-void JSUnprotectedEventListener::clearWindow()
+void JSUnprotectedEventListener::clearGlobalObject()
{
- m_window = 0;
+ m_globalObject = 0;
}
void JSUnprotectedEventListener::mark()
@@ -177,14 +190,14 @@
// -------------------------------------------------------------------------
-JSEventListener::JSEventListener(JSObject* listener, JSDOMWindow* window, bool isInline)
+JSEventListener::JSEventListener(JSObject* listener, JSDOMGlobalObject* globalObject, bool isInline)
: JSAbstractEventListener(isInline)
, m_listener(listener)
- , m_window(window)
+ , m_globalObject(globalObject)
{
if (m_listener) {
JSDOMWindow::ListenersMap& listeners = isInline
- ? m_window->jsInlineEventListeners() : m_window->jsEventListeners();
+ ? m_globalObject->jsInlineEventListeners() : m_globalObject->jsEventListeners();
listeners.set(m_listener, this);
}
#ifndef NDEBUG
@@ -194,9 +207,9 @@
JSEventListener::~JSEventListener()
{
- if (m_listener && m_window) {
+ if (m_listener && m_globalObject) {
JSDOMWindow::ListenersMap& listeners = isInline()
- ? m_window->jsInlineEventListeners() : m_window->jsEventListeners();
+ ? m_globalObject->jsInlineEventListeners() : m_globalObject->jsEventListeners();
listeners.remove(m_listener);
}
#ifndef NDEBUG
@@ -209,20 +222,20 @@
return m_listener;
}
-JSDOMWindow* JSEventListener::window() const
+JSDOMGlobalObject* JSEventListener::globalObject() const
{
- return m_window;
+ return m_globalObject;
}
-void JSEventListener::clearWindow()
+void JSEventListener::clearGlobalObject()
{
- m_window = 0;
+ m_globalObject = 0;
}
// -------------------------------------------------------------------------
-JSLazyEventListener::JSLazyEventListener(LazyEventListenerType type, const String& functionName, const String& code, JSDOMWindow* window, Node* node, int lineNumber)
- : JSEventListener(0, window, true)
+JSLazyEventListener::JSLazyEventListener(LazyEventListenerType type, const String& functionName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
+ : JSEventListener(0, globalObject, true)
, m_functionName(functionName)
, m_code(code)
, m_parsed(false)
@@ -269,19 +282,24 @@
if (m_parsed)
return;
- Frame* frame = window()->impl()->frame();
- if (!frame)
- return;
- ScriptController* script = frame->script();
- if (!script->isEnabled() || script->isPaused())
- return;
+ Frame* frame = 0;
+ if (globalObject()->scriptExecutionContext()->isDocument()) {
+ JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject());
+ frame = window->impl()->frame();
+ if (!frame)
+ return;
+ // FIXME: Is this check needed for non-Document contexts?
+ ScriptController* script = frame->script();
+ if (!script->isEnabled() || script->isPaused())
+ return;
+ }
m_parsed = true;
- ExecState* exec = window()->globalExec();
+ ExecState* exec = globalObject()->globalExec();
ArgList args;
- UString sourceURL(frame->loader()->url().string());
+ UString sourceURL(globalObject()->scriptExecutionContext()->url().string());
args.append(eventParameterName(m_type, exec));
args.append(jsString(exec, m_code));
@@ -314,7 +332,7 @@
if (m_listener) {
ASSERT(isInline());
- JSDOMWindow::ListenersMap& listeners = window()->jsInlineEventListeners();
+ JSDOMWindow::ListenersMap& listeners = globalObject()->jsInlineEventListeners();
listeners.set(m_listener, const_cast<JSLazyEventListener*>(this));
}
}
diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h
index 326a518..3c9edd0 100644
--- a/WebCore/bindings/js/JSEventListener.h
+++ b/WebCore/bindings/js/JSEventListener.h
@@ -27,7 +27,7 @@
namespace WebCore {
class Event;
- class JSDOMWindow;
+ class JSDOMGlobalObject;
class Node;
class JSAbstractEventListener : public EventListener {
@@ -35,7 +35,7 @@
virtual void handleEvent(Event*, bool isWindowEvent);
virtual bool isInline() const;
virtual JSC::JSObject* listenerObj() const = 0;
- virtual JSDOMWindow* window() const = 0;
+ virtual JSDOMGlobalObject* globalObject() const = 0;
protected:
JSAbstractEventListener(bool isInline)
@@ -49,43 +49,43 @@
class JSUnprotectedEventListener : public JSAbstractEventListener {
public:
- static PassRefPtr<JSUnprotectedEventListener> create(JSC::JSObject* listener, JSDOMWindow* window, bool isInline)
+ static PassRefPtr<JSUnprotectedEventListener> create(JSC::JSObject* listener, JSDOMGlobalObject* globalObject, bool isInline)
{
- return adoptRef(new JSUnprotectedEventListener(listener, window, isInline));
+ return adoptRef(new JSUnprotectedEventListener(listener, globalObject, isInline));
}
virtual ~JSUnprotectedEventListener();
virtual JSC::JSObject* listenerObj() const;
- virtual JSDOMWindow* window() const;
- void clearWindow();
+ virtual JSDOMGlobalObject* globalObject() const;
+ void clearGlobalObject();
void mark();
private:
- JSUnprotectedEventListener(JSC::JSObject* listener, JSDOMWindow*, bool isInline);
+ JSUnprotectedEventListener(JSC::JSObject* listener, JSDOMGlobalObject*, bool isInline);
JSC::JSObject* m_listener;
- JSDOMWindow* m_window;
+ JSDOMGlobalObject* m_globalObject;
};
class JSEventListener : public JSAbstractEventListener {
public:
- static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSDOMWindow* window, bool isInline)
+ static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSDOMGlobalObject* globalObject, bool isInline)
{
- return adoptRef(new JSEventListener(listener, window, isInline));
+ return adoptRef(new JSEventListener(listener, globalObject, isInline));
}
virtual ~JSEventListener();
virtual JSC::JSObject* listenerObj() const;
- virtual JSDOMWindow* window() const;
- void clearWindow();
+ virtual JSDOMGlobalObject* globalObject() const;
+ void clearGlobalObject();
protected:
- JSEventListener(JSC::JSObject* listener, JSDOMWindow*, bool isInline);
+ JSEventListener(JSC::JSObject* listener, JSDOMGlobalObject*, bool isInline);
mutable JSC::ProtectedPtr<JSC::JSObject> m_listener;
private:
- JSC::ProtectedPtr<JSDOMWindow> m_window;
+ JSC::ProtectedPtr<JSDOMGlobalObject> m_globalObject;
};
class JSLazyEventListener : public JSEventListener {
@@ -99,14 +99,14 @@
virtual bool wasCreatedFromMarkup() const { return true; }
- static PassRefPtr<JSLazyEventListener> create(LazyEventListenerType type, const String& functionName, const String& code, JSDOMWindow* window, Node* node, int lineNumber)
+ static PassRefPtr<JSLazyEventListener> create(LazyEventListenerType type, const String& functionName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
{
- return adoptRef(new JSLazyEventListener(type, functionName, code, window, node, lineNumber));
+ return adoptRef(new JSLazyEventListener(type, functionName, code, globalObject, node, lineNumber));
}
virtual JSC::JSObject* listenerObj() const;
protected:
- JSLazyEventListener(LazyEventListenerType type, const String& functionName, const String& code, JSDOMWindow*, Node*, int lineNumber);
+ JSLazyEventListener(LazyEventListenerType type, const String& functionName, const String& code, JSDOMGlobalObject*, Node*, int lineNumber);
private:
void parseCode() const;
diff --git a/WebCore/bindings/js/JSMessagePortCustom.cpp b/WebCore/bindings/js/JSMessagePortCustom.cpp
index e7027ea..711cd30 100644
--- a/WebCore/bindings/js/JSMessagePortCustom.cpp
+++ b/WebCore/bindings/js/JSMessagePortCustom.cpp
@@ -29,7 +29,7 @@
#include "AtomicString.h"
#include "Event.h"
#include "Frame.h"
-#include "JSDOMWindowCustom.h"
+#include "JSDOMGlobalObject.h"
#include "JSEvent.h"
#include "JSEventListener.h"
#include "MessagePort.h"
@@ -67,18 +67,18 @@
JSValue* JSMessagePort::startConversation(ExecState* exec, const ArgList& args)
{
- DOMWindow* window = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
+ JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
const UString& message = args.at(exec, 0)->toString(exec);
- return toJS(exec, impl()->startConversation(window->document(), message).get());
+ return toJS(exec, impl()->startConversation(globalObject->scriptExecutionContext(), message).get());
}
JSValue* JSMessagePort::addEventListener(ExecState* exec, const ArgList& args)
{
- Frame* frame = impl()->associatedFrame();
- if (!frame)
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
return jsUndefined();
- RefPtr<JSUnprotectedEventListener> listener = toJSDOMWindow(frame)->findOrCreateJSUnprotectedEventListener(exec, args.at(exec, 1));
+ RefPtr<JSUnprotectedEventListener> listener = globalObject->findOrCreateJSUnprotectedEventListener(exec, args.at(exec, 1));
if (!listener)
return jsUndefined();
impl()->addEventListener(args.at(exec, 0)->toString(exec), listener.release(), args.at(exec, 2)->toBoolean(exec));
@@ -87,10 +87,10 @@
JSValue* JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args)
{
- Frame* frame = impl()->associatedFrame();
- if (!frame)
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
return jsUndefined();
- JSUnprotectedEventListener* listener = toJSDOMWindow(frame)->findJSUnprotectedEventListener(exec, args.at(exec, 1));
+ JSUnprotectedEventListener* listener = globalObject->findJSUnprotectedEventListener(exec, args.at(exec, 1));
if (!listener)
return jsUndefined();
impl()->removeEventListener(args.at(exec, 0)->toString(exec), listener, args.at(exec, 2)->toBoolean(exec));
@@ -100,10 +100,10 @@
void JSMessagePort::setOnmessage(ExecState* exec, JSValue* value)
{
- Frame* frame = impl()->associatedFrame();
- if (!frame)
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
return;
- impl()->setOnmessage(toJSDOMWindow(frame)->findOrCreateJSUnprotectedEventListener(exec, value, true));
+ impl()->setOnmessage(globalObject->findOrCreateJSUnprotectedEventListener(exec, value, true));
}
JSValue* JSMessagePort::onmessage(ExecState*) const
@@ -116,10 +116,10 @@
void JSMessagePort::setOnclose(ExecState* exec, JSValue* value)
{
- Frame* frame = impl()->associatedFrame();
- if (!frame)
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
return;
- impl()->setOnclose(toJSDOMWindow(frame)->findOrCreateJSUnprotectedEventListener(exec, value, true));
+ impl()->setOnclose(globalObject->findOrCreateJSUnprotectedEventListener(exec, value, true));
}
JSValue* JSMessagePort::onclose(ExecState*) const
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index 03cc8b8..df7153a 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -1703,6 +1703,11 @@
m_windowEventListeners.clear();
}
+const KURL& Document::virtualURL() const
+{
+ return m_url;
+}
+
void Document::setURL(const KURL& url)
{
const KURL& newURL = url.isEmpty() ? blankURL() : url;
diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h
index ab01ab3..2e9f5b8 100644
--- a/WebCore/dom/Document.h
+++ b/WebCore/dom/Document.h
@@ -779,6 +779,8 @@
virtual void refScriptExecutionContext() { ref(); }
virtual void derefScriptExecutionContext() { deref(); }
+ virtual const KURL& virtualURL() const; // Same as url(), but needed for ScriptExecutionContext to implement it without a performance loss for direct calls.
+
CSSStyleSelector* m_styleSelector;
bool m_didCalculateStyleSelector;
diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h
index 13ea763..565dbe0 100644
--- a/WebCore/dom/ScriptExecutionContext.h
+++ b/WebCore/dom/ScriptExecutionContext.h
@@ -46,6 +46,8 @@
virtual bool isDocument() const { return false; }
virtual bool isWorkerContext() const { return false; }
+ const KURL& url() const { return virtualURL(); }
+
// Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
void stopActiveDOMObjects();
void createdActiveDOMObject(ActiveDOMObject*, void* upcastPointer);
@@ -63,6 +65,8 @@
void deref() { derefScriptExecutionContext(); }
private:
+ virtual const KURL& virtualURL() const = 0;
+
bool m_firedMessagePortTimer;
HashSet<MessagePort*> m_messagePorts;