Changeset 54400 in webkit
- Timestamp:
- Feb 4, 2010 7:39:09 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r54395 r54400 1 2010-01-27 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Alexey Proskuryakov and Darin Adler. 4 5 REGRESSION (r52082): Missing event handlers on JQuery demo page (33383) 6 https://bugs.webkit.org/show_bug.cgi?id=33383 7 <rdar://problem/7559449> 8 9 * fast/events/bogus-event-listener-invalidation-expected.txt: Added. 10 * fast/events/bogus-event-listener-invalidation.html: Added. 11 1 12 2010-02-04 Tony Chang <tony@chromium.org> 2 13 -
trunk/WebCore/ChangeLog
r54395 r54400 1 2010-02-04 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Alexey Proskuryakov and Darin Adler. 4 5 REGRESSION (r52082): Missing event handlers on JQuery demo page (33383) 6 https://bugs.webkit.org/show_bug.cgi?id=33383 7 <rdar://problem/7559449> 8 9 There were two bugs here: 10 11 1. A stale wrapper would invalidate a node's event listeners, even if 12 the node had a fresh wrapper keeping it alive. 13 14 The fix for this is for an event listener to keep a WeakGCPtr back-pointer 15 to the wrapper it expects to mark it. The wrapper destructor checks this 16 back-pointer, and only invalidates the event listener in the case of a match. 17 18 2. Conversely, a stale wrapper would not invalidate a node's event 19 listeners soon enough, if its destructor didn't have a chance to run 20 before an event fired on the node. (This can only happen in cases where 21 we've made some other error and failed to mark a wrapper that was circuitously 22 observable in the DOM. But we know we have edge case bugs like this, and 23 we don't want them to be crashes.) 24 25 The fix for this is to check the wrapper back-pointer before firing the 26 event listener. As long as the the wrapper back-pointer is not null, 27 it's safe to fire the listener. 28 29 * ForwardingHeaders/runtime/WeakGCPtr.h: Added. Appease build gods. 30 31 * bindings/js/JSAbstractWorkerCustom.cpp: 32 (WebCore::JSAbstractWorker::addEventListener): 33 (WebCore::JSAbstractWorker::removeEventListener): 34 * bindings/js/JSDOMApplicationCacheCustom.cpp: 35 (WebCore::JSDOMApplicationCache::addEventListener): 36 (WebCore::JSDOMApplicationCache::removeEventListener): 37 * bindings/js/JSDOMWindowCustom.cpp: 38 (WebCore::JSDOMWindow::markChildren): 39 (WebCore::JSDOMWindow::addEventListener): 40 (WebCore::JSDOMWindow::removeEventListener): Updated to pass a wrapper 41 to the JSEventListener constructor. 42 43 * bindings/js/JSEventListener.cpp: 44 (WebCore::JSEventListener::JSEventListener): 45 (WebCore::JSEventListener::initializeJSFunction): 46 (WebCore::JSEventListener::invalidateJSFunction): 47 * bindings/js/JSEventListener.h: 48 (WebCore::JSEventListener::create): 49 (WebCore::JSEventListener::isolatedWorld): 50 (WebCore::JSEventListener::wrapper): 51 (WebCore::JSEventListener::setWrapper): 52 (WebCore::JSEventListener::jsFunction): 53 (WebCore::createJSAttributeEventListener): Implemented the back-pointer 54 described above. Refactored the jsFunction() accessor to return 0 if 55 the wrapper back-pointer is 0. 56 57 * bindings/js/JSEventSourceCustom.cpp: 58 (WebCore::JSEventSource::addEventListener): 59 (WebCore::JSEventSource::removeEventListener): 60 * bindings/js/JSLazyEventListener.cpp: 61 (WebCore::JSLazyEventListener::JSLazyEventListener): 62 (WebCore::JSLazyEventListener::initializeJSFunction): 63 * bindings/js/JSLazyEventListener.h: 64 (WebCore::JSLazyEventListener::create): 65 * bindings/js/JSMessagePortCustom.cpp: 66 (WebCore::JSMessagePort::markChildren): 67 (WebCore::JSMessagePort::addEventListener): 68 (WebCore::JSMessagePort::removeEventListener): 69 * bindings/js/JSNodeCustom.cpp: 70 (WebCore::JSNode::addEventListener): 71 (WebCore::JSNode::removeEventListener): 72 (WebCore::JSNode::markChildren): 73 * bindings/js/JSSVGElementInstanceCustom.cpp: 74 (WebCore::JSSVGElementInstance::addEventListener): 75 (WebCore::JSSVGElementInstance::removeEventListener): 76 * bindings/js/JSWebSocketCustom.cpp: 77 (WebCore::JSWebSocket::addEventListener): 78 (WebCore::JSWebSocket::removeEventListener): 79 * bindings/js/JSWorkerContextCustom.cpp: 80 (WebCore::JSWorkerContext::markChildren): 81 (WebCore::JSWorkerContext::addEventListener): 82 (WebCore::JSWorkerContext::removeEventListener): 83 * bindings/js/JSXMLHttpRequestCustom.cpp: 84 (WebCore::JSXMLHttpRequest::markChildren): 85 (WebCore::JSXMLHttpRequest::addEventListener): 86 (WebCore::JSXMLHttpRequest::removeEventListener): 87 * bindings/js/JSXMLHttpRequestUploadCustom.cpp: 88 (WebCore::JSXMLHttpRequestUpload::markChildren): 89 (WebCore::JSXMLHttpRequestUpload::addEventListener): 90 (WebCore::JSXMLHttpRequestUpload::removeEventListener): Updated to pass a wrapper 91 to the JSEventListener constructor. 92 93 94 * bindings/js/ScriptEventListener.cpp: 95 (WebCore::createAttributeEventListener): Updated to pass a wrapper 96 to the JSEventListener constructor. 97 (WebCore::getEventListenerHandlerBody): Updated for the fact that jsFunction() 98 is no longer a virtual accessor on the EventHandler base class. 99 100 * bindings/scripts/CodeGeneratorJS.pm: Updated for the fact that jsFunction() 101 is no longer a virtual accessor on the EventHandler base class. Added a "JS" 102 to invalidateEventListeners and markEventListeners to clarify that these 103 actions are for JS event listeners only. Added a wrapper parameter to 104 invalidateEventListeners for the back-pointer check explained above. 105 106 * dom/EventListener.h: 107 (WebCore::EventListener::invalidateJSFunction): ditto 108 109 * dom/EventTarget.h: 110 (WebCore::EventTarget::markJSEventListeners): 111 (WebCore::EventTarget::invalidateJSEventListeners): ditto 112 1 113 2010-02-04 Tony Chang <tony@chromium.org> 2 114 -
trunk/WebCore/bindings/js/JSAbstractWorkerCustom.cpp
r49963 r54400 51 51 return jsUndefined(); 52 52 53 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));53 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 54 54 return jsUndefined(); 55 55 } … … 61 61 return jsUndefined(); 62 62 63 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));63 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 64 64 return jsUndefined(); 65 65 } -
trunk/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp
r49963 r54400 92 92 return jsUndefined(); 93 93 94 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));94 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 95 95 return jsUndefined(); 96 96 } … … 102 102 return jsUndefined(); 103 103 104 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));104 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 105 105 return jsUndefined(); 106 106 } -
trunk/WebCore/bindings/js/JSDOMWindowCustom.cpp
r54182 r54400 98 98 Base::markChildren(markStack); 99 99 100 impl()->mark EventListeners(markStack);100 impl()->markJSEventListeners(markStack); 101 101 102 102 JSGlobalData& globalData = *Heap::heap(this)->globalData(); … … 998 998 return jsUndefined(); 999 999 1000 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));1000 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 1001 1001 return jsUndefined(); 1002 1002 } … … 1012 1012 return jsUndefined(); 1013 1013 1014 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));1014 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 1015 1015 return jsUndefined(); 1016 1016 } -
trunk/WebCore/bindings/js/JSEventListener.cpp
r53046 r54400 32 32 namespace WebCore { 33 33 34 JSEventListener::JSEventListener(JSObject* function, bool isAttribute, DOMWrapperWorld* isolatedWorld)34 JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) 35 35 : EventListener(JSEventListenerType) 36 36 , m_jsFunction(function) 37 , m_wrapper(wrapper) 37 38 , m_isAttribute(isAttribute) 38 39 , m_isolatedWorld(isolatedWorld) … … 44 45 } 45 46 46 JSObject* JSEventListener::jsFunction(ScriptExecutionContext*) const 47 { 48 return m_jsFunction; 47 JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext*) const 48 { 49 ASSERT_NOT_REACHED(); 50 return 0; 49 51 } 50 52 … … 53 55 if (m_jsFunction) 54 56 markStack.append(m_jsFunction); 57 } 58 59 void JSEventListener::invalidateJSFunction(JSC::JSObject* wrapper) 60 { 61 // Since m_wrapper is a WeakGCPtr, it pretends to be null, and therefore != 62 // to wrapper, when it's awaiting destruction. So, we check for == wrapper 63 // or == null. 64 if (!m_wrapper || m_wrapper == wrapper) 65 m_wrapper = 0; 55 66 } 56 67 -
trunk/WebCore/bindings/js/JSEventListener.h
r53430 r54400 23 23 #include "EventListener.h" 24 24 #include "JSDOMWindow.h" 25 #include <runtime/ Protect.h>25 #include <runtime/WeakGCPtr.h> 26 26 27 27 namespace WebCore { … … 31 31 class JSEventListener : public EventListener { 32 32 public: 33 static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, bool isAttribute, DOMWrapperWorld* isolatedWorld)33 static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) 34 34 { 35 return adoptRef(new JSEventListener(listener, isAttribute, isolatedWorld));35 return adoptRef(new JSEventListener(listener, wrapper, isAttribute, isolatedWorld)); 36 36 } 37 37 … … 50 50 bool isAttribute() const { return m_isAttribute; } 51 51 52 virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const; 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::JSObject* wrapper) const { m_wrapper = wrapper; } 53 57 54 58 private: 59 virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const; 55 60 virtual void markJSFunction(JSC::MarkStack&); 61 virtual void invalidateJSFunction(JSC::JSObject*); 56 62 virtual void handleEvent(ScriptExecutionContext*, Event*); 57 63 virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber); 58 64 virtual bool virtualisAttribute() const; 59 void clearJSFunctionInline();60 65 61 66 protected: 62 JSEventListener(JSC::JSObject* function, bool isAttribute, DOMWrapperWorld* isolatedWorld);67 JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld); 63 68 69 private: 64 70 mutable JSC::JSObject* m_jsFunction; 71 mutable JSC::WeakGCPtr<JSC::JSObject> m_wrapper; 72 65 73 bool m_isAttribute; 66 74 RefPtr<DOMWrapperWorld> m_isolatedWorld; 67 75 }; 68 76 77 inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const 78 { 79 if (!m_jsFunction) 80 m_jsFunction = initializeJSFunction(scriptExecutionContext); 81 82 // Verify that we have a valid wrapper protecting our function from 83 // garbage collection. 84 ASSERT(m_wrapper || !m_jsFunction); 85 if (!m_wrapper) 86 return 0; 87 88 // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an 89 // event listener can be almost anything, but this makes test-writing easier). 90 ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction)->isObject()); 91 92 return m_jsFunction; 93 } 94 69 95 // Creates a JS EventListener for an "onXXX" event attribute. 70 inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener )96 inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper) 71 97 { 72 98 if (!listener.isObject()) 73 99 return 0; 74 100 75 return JSEventListener::create(asObject(listener), true, currentWorld(exec));101 return JSEventListener::create(asObject(listener), wrapper, true, currentWorld(exec)); 76 102 } 77 103 -
trunk/WebCore/bindings/js/JSEventSourceCustom.cpp
r49963 r54400 50 50 return jsUndefined(); 51 51 52 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));52 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 53 53 return jsUndefined(); 54 54 } … … 60 60 return jsUndefined(); 61 61 62 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));62 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 63 63 return jsUndefined(); 64 64 } -
trunk/WebCore/bindings/js/JSLazyEventListener.cpp
r53046 r54400 36 36 #endif 37 37 38 JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld)39 : JSEventListener(0, true, isolatedWorld)38 JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, JSObject* wrapper, DOMWrapperWorld* isolatedWorld) 39 : JSEventListener(0, wrapper, true, isolatedWorld) 40 40 , m_functionName(functionName) 41 41 , m_eventParameterName(eventParameterName) 42 42 , m_code(code) 43 , m_parsed(false)44 43 , m_sourceURL(sourceURL) 45 44 , m_lineNumber(lineNumber) … … 49 48 // will stay alive as long as this handler object is around 50 49 // and we need to avoid a reference cycle. If JS transfers 51 // this handler to another node, parseCode will be called and52 // then originalNode is no longer needed.50 // this handler to another node, initializeJSFunction will 51 // be called and then originalNode is no longer needed. 53 52 54 53 // A JSLazyEventListener can be created with a line number of zero when it is created with … … 69 68 } 70 69 71 JSObject* JSLazyEventListener::jsFunction(ScriptExecutionContext* executionContext) const 72 { 73 parseCode(executionContext); 74 return m_jsFunction; 75 } 76 77 void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) const 70 JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const 78 71 { 79 72 ASSERT(executionContext); 80 73 ASSERT(executionContext->isDocument()); 81 74 if (!executionContext) 82 return; 83 84 if (m_parsed) 85 return; 75 return 0; 86 76 87 77 Frame* frame = static_cast<Document*>(executionContext)->frame(); 88 78 if (!frame) 89 return ;79 return 0; 90 80 91 81 ScriptController* scriptController = frame->script(); 92 82 if (!scriptController->canExecuteScripts()) 93 return ;83 return 0; 94 84 95 JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, m_isolatedWorld.get());85 JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld()); 96 86 if (!globalObject) 97 return; 98 99 // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating. 100 if (m_originalNode) { 101 JSLock lock(SilenceAssertionsOnly); 102 // FIXME: Should pass the global object associated with the node 103 toJS(globalObject->globalExec(), globalObject, m_originalNode); 104 } 87 return 0; 105 88 106 89 if (executionContext->isDocument()) { … … 108 91 Frame* frame = window->impl()->frame(); 109 92 if (!frame) 110 return ;93 return 0; 111 94 // FIXME: Is this check needed for non-Document contexts? 112 95 ScriptController* script = frame->script(); 113 96 if (!script->canExecuteScripts() || script->isPaused()) 114 return ;97 return 0; 115 98 } 116 117 m_parsed = true;118 99 119 100 ExecState* exec = globalObject->globalExec(); … … 123 104 args.append(jsString(exec, m_code)); 124 105 125 m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok? 126 127 JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_jsFunction); 128 106 JSObject* jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok? 129 107 if (exec->hadException()) { 130 108 exec->clearException(); 109 return 0; 110 } 131 111 132 // failed to parse, so let's just make this listener a no-op 133 m_jsFunction = 0; 134 } else if (m_originalNode) { 112 JSFunction* listenerAsFunction = static_cast<JSFunction*>(jsFunction); 113 if (m_originalNode) { 114 if (!wrapper()) { 115 // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating. 116 JSLock lock(SilenceAssertionsOnly); 117 // FIXME: Should pass the global object associated with the node 118 setWrapper(asObject(toJS(globalObject->globalExec(), globalObject, m_originalNode))); 119 } 120 135 121 // Add the event's home element to the scope 136 122 // (and the document, and the form - see JSHTMLElement::eventHandlerScope) 137 123 ScopeChain scope = listenerAsFunction->scope(); 138 139 JSValue thisObj = toJS(exec, globalObject, m_originalNode); 140 if (thisObj.isObject()) { 141 static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope); 142 listenerAsFunction->setScope(scope); 143 } 124 static_cast<JSNode*>(wrapper())->pushEventHandlerScope(exec, scope); 125 listenerAsFunction->setScope(scope); 144 126 } 145 127 … … 149 131 m_eventParameterName = String(); 150 132 m_sourceURL = String(); 133 return jsFunction; 151 134 } 152 135 -
trunk/WebCore/bindings/js/JSLazyEventListener.h
r49963 r54400 30 30 class JSLazyEventListener : public JSEventListener { 31 31 public: 32 static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld)32 static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, JSC::JSObject* wrapper, DOMWrapperWorld* isolatedWorld) 33 33 { 34 return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber, isolatedWorld));34 return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber, wrapper, isolatedWorld)); 35 35 } 36 36 virtual ~JSLazyEventListener(); 37 37 38 38 private: 39 JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld);39 JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber, JSC::JSObject* wrapper, DOMWrapperWorld* isolatedWorld); 40 40 41 virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const;41 virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const; 42 42 virtual bool wasCreatedFromMarkup() const { return true; } 43 44 void parseCode(ScriptExecutionContext*) const;45 43 46 44 mutable String m_functionName; 47 45 mutable String m_eventParameterName; 48 46 mutable String m_code; 49 mutable bool m_parsed;50 47 mutable String m_sourceURL; 51 48 int m_lineNumber; -
trunk/WebCore/bindings/js/JSMessagePortCustom.cpp
r49963 r54400 50 50 markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), entangledPort); 51 51 52 m_impl->mark EventListeners(markStack);52 m_impl->markJSEventListeners(markStack); 53 53 } 54 54 … … 59 59 return jsUndefined(); 60 60 61 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));61 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 62 62 return jsUndefined(); 63 63 } … … 69 69 return jsUndefined(); 70 70 71 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));71 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 72 72 return jsUndefined(); 73 73 } -
trunk/WebCore/bindings/js/JSNodeCustom.cpp
r52082 r54400 115 115 return jsUndefined(); 116 116 117 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));117 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 118 118 return jsUndefined(); 119 119 } … … 125 125 return jsUndefined(); 126 126 127 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));127 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 128 128 return jsUndefined(); 129 129 } … … 138 138 139 139 Node* node = m_impl.get(); 140 node->mark EventListeners(markStack);140 node->markJSEventListeners(markStack); 141 141 142 142 // Nodes in the document are kept alive by JSDocument::mark, so, if we're in -
trunk/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
r50850 r54400 53 53 return jsUndefined(); 54 54 55 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));55 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 56 56 return jsUndefined(); 57 57 } … … 63 63 return jsUndefined(); 64 64 65 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));65 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 66 66 return jsUndefined(); 67 67 } -
trunk/WebCore/bindings/js/JSWebSocketCustom.cpp
r51377 r54400 66 66 return jsUndefined(); 67 67 68 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));68 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 69 69 return jsUndefined(); 70 70 } … … 76 76 return jsUndefined(); 77 77 78 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));78 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 79 79 return jsUndefined(); 80 80 } -
trunk/WebCore/bindings/js/JSWorkerContextCustom.cpp
r52892 r54400 61 61 markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator()); 62 62 63 impl()->mark EventListeners(markStack);63 impl()->markJSEventListeners(markStack); 64 64 } 65 65 … … 128 128 return jsUndefined(); 129 129 130 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));130 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 131 131 return jsUndefined(); 132 132 } … … 138 138 return jsUndefined(); 139 139 140 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));140 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 141 141 return jsUndefined(); 142 142 } -
trunk/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
r53574 r54400 57 57 markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), upload); 58 58 59 m_impl->mark EventListeners(markStack);59 m_impl->markJSEventListeners(markStack); 60 60 } 61 61 … … 154 154 return jsUndefined(); 155 155 156 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));156 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 157 157 return jsUndefined(); 158 158 } … … 164 164 return jsUndefined(); 165 165 166 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));166 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 167 167 return jsUndefined(); 168 168 } -
trunk/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp
r49963 r54400 49 49 markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), xmlHttpRequest); 50 50 51 m_impl->mark EventListeners(markStack);51 m_impl->markJSEventListeners(markStack); 52 52 } 53 53 … … 58 58 return jsUndefined(); 59 59 60 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec));60 impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); 61 61 return jsUndefined(); 62 62 } … … 68 68 return jsUndefined(); 69 69 70 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec));70 impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); 71 71 return jsUndefined(); 72 72 } -
trunk/WebCore/bindings/js/ScriptEventListener.cpp
r53564 r54400 38 38 #include "Frame.h" 39 39 #include "XSSAuditor.h" 40 #include <runtime/JSLock.h> 40 41 41 42 using namespace JSC; … … 59 60 int lineNumber = 1; 60 61 String sourceURL; 62 JSObject* wrapper = 0; 61 63 62 64 // FIXME: We should be able to provide accurate source information for frameless documents, too (e.g. for importing nodes from XMLHttpRequest.responseXML). … … 73 75 lineNumber = scriptController->eventHandlerLineNumber(); 74 76 sourceURL = node->document()->url().string(); 77 78 JSC::JSLock lock(SilenceAssertionsOnly); 79 JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(node->document(), mainThreadNormalWorld()); 80 wrapper = asObject(toJS(globalObject->globalExec(), globalObject, node)); 75 81 } 76 82 77 return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber, mainThreadNormalWorld());83 return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber, wrapper, mainThreadNormalWorld()); 78 84 } 79 85 … … 101 107 lineNumber = scriptController->eventHandlerLineNumber(); 102 108 sourceURL = frame->document()->url().string(); 103 return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber, mainThreadNormalWorld()); 109 JSObject* wrapper = toJSDOMWindow(frame, mainThreadNormalWorld()); 110 return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber, wrapper, mainThreadNormalWorld()); 104 111 } 105 112 106 113 String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener) 107 114 { 108 JSC::JSObject* functionObject = eventListener->jsFunction(context);109 if (! functionObject)115 const JSEventListener* jsListener = JSEventListener::cast(eventListener); 116 if (!jsListener) 110 117 return ""; 111 return functionObject->toString(scriptState); 118 JSC::JSObject* jsFunction = jsListener->jsFunction(context); 119 if (!jsFunction) 120 return ""; 121 return jsFunction->toString(scriptState); 112 122 } 113 123 -
trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm
r54182 r54400 1199 1199 if ($eventTarget) { 1200 1200 $implIncludes{"RegisteredEventListener.h"} = 1; 1201 push(@implContent, " impl()->invalidate EventListeners();\n");1201 push(@implContent, " impl()->invalidateJSEventListeners(this);\n"); 1202 1202 } 1203 1203 … … 1219 1219 push(@implContent, "{\n"); 1220 1220 push(@implContent, " Base::markChildren(markStack);\n"); 1221 push(@implContent, " impl()->mark EventListeners(markStack);\n");1221 push(@implContent, " impl()->markJSEventListeners(markStack);\n"); 1222 1222 push(@implContent, "}\n\n"); 1223 1223 } … … 1319 1319 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); 1320 1320 push(@implContent, " if (EventListener* listener = imp->$implGetterFunctionName()) {\n"); 1321 push(@implContent, " if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n"); 1321 1322 if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") { 1322 push(@implContent, " if (JSObject* jsFunction = listener->jsFunction(imp))\n");1323 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp))\n"); 1323 1324 } else { 1324 push(@implContent, " if (JSObject* jsFunction = listener->jsFunction(imp->scriptExecutionContext()))\n");1325 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(imp->scriptExecutionContext()))\n"); 1325 1326 } 1326 push(@implContent, " return jsFunction;\n"); 1327 push(@implContent, " return jsFunction;\n"); 1328 push(@implContent, " }\n"); 1327 1329 push(@implContent, " }\n"); 1328 1330 push(@implContent, " return jsNull();\n"); … … 1478 1480 push(@implContent, " UNUSED_PARAM(exec);\n"); 1479 1481 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); 1480 push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value ));\n");1482 push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n"); 1481 1483 } elsif ($attribute->signature->type =~ /Constructor$/) { 1482 1484 my $constructorType = $attribute->signature->type; -
trunk/WebCore/dom/EventListener.h
r48884 r54400 52 52 53 53 #if USE(JSC) 54 virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const { return 0; }55 54 virtual void markJSFunction(JSC::MarkStack&) { } 55 virtual void invalidateJSFunction(JSC::JSObject*) { } 56 56 #endif 57 57 -
trunk/WebCore/dom/EventTarget.h
r52282 r54400 141 141 142 142 #if USE(JSC) 143 void mark EventListeners(JSC::MarkStack&);144 void invalidate EventListeners();143 void markJSEventListeners(JSC::MarkStack&); 144 void invalidateJSEventListeners(JSC::JSObject*); 145 145 #endif 146 146 … … 186 186 187 187 #if USE(JSC) 188 inline void EventTarget::mark EventListeners(JSC::MarkStack& markStack)188 inline void EventTarget::markJSEventListeners(JSC::MarkStack& markStack) 189 189 { 190 190 EventTargetData* d = eventTargetData(); … … 200 200 } 201 201 202 inline void EventTarget::invalidate EventListeners()202 inline void EventTarget::invalidateJSEventListeners(JSC::JSObject* wrapper) 203 203 { 204 204 EventTargetData* d = eventTargetData(); … … 206 206 return; 207 207 208 deleteAllValues(d->eventListenerMap); 209 d->eventListenerMap.clear(); 208 EventListenerMap::iterator end = d->eventListenerMap.end(); 209 for (EventListenerMap::iterator it = d->eventListenerMap.begin(); it != end; ++it) { 210 EventListenerVector& entry = *it->second; 211 for (size_t i = 0; i < entry.size(); ++i) 212 entry[i].listener->invalidateJSFunction(wrapper); 213 } 210 214 } 211 215 #endif
Note: See TracChangeset
for help on using the changeset viewer.