From 42e58c6dac82d22b20c3e042d57b1597c48f1f6b Mon Sep 17 00:00:00 2001 From: ggaren Date: Sat, 18 Mar 2006 02:04:37 +0000 Subject: [PATCH] LayoutTests: Reviewed by Darin. * fast/dom/prototype-chain-expected.txt: Updated to reflect new prototype chain. WebCore: Reviewed by Darin. - Fixed some crashes in event dispatch and settled the question of when getDocument() can return NULL, removing superfluous NULL checks. I promise to check in a test case soon, but I need to land this before the global rename happens, and I left the test file on my other machine. Here's what I did: (1) Removed NULL checks for getDocument() in cases where we know it should not return NULL (which turned out to be all but one). Replaced with ASSERT inside getDocument(). Tested to ensure there was no regression @ albertsons.com. (2) Added the EventTargetNode class, which represents Nodes that implement the DOM EventTarget interface. Discussed this design with Maciej and Hyatt. The previous dsign -- assuming that all Nodes were EventTargets -- made it possible to crash WebKit by, for example, dispatching a mouse event to a documentType node that was not associated with a document. (3) Reflected (2) into the JS bindings and touched JSDOMCore.cpp to force a re-build. (4) Using classInfo checking, strengthened type constraints on JavaScript method dispatch so that you can't finagle JavaScript into, for example, invoking a document-dependent method belonging to a node type that's guaranteed to have a document on a node type that may not have one. (5) Pushed some IE-specific JS bindings that depend on a node having a document down from DOMNode to DOMElement. (An element always has a document.) Tested that Firefox's behavior matched. Confirmed with MSDN. (6) Updated Objc bindigns to throw an exception if you try to use the event interface on a node that doesn't support it. Discussed this design with Maciej and TimH. (7) Consolidated repeated documentElement-finding code in the Position class into the Position::documentElement() method. Did the same for repeated top-level document finding and DocumentImpl::topDocument(). * WebCore+SVG/KDOMHeaders.h: * WebCore.xcodeproj/project.pbxproj: * bindings/js/JSDOMCore.cpp: * bindings/objc/DOM.mm: (-[DOMNode addEventListener:::]): (-[DOMNode removeEventListener:::]): (-[DOMNode dispatchEvent:]): (-[DOMNode KJS::Bindings::]): * bridge/mac/MacFrame.mm: (WebCore::MacFrame::keyEvent): (WebCore::MacFrame::dispatchCPPEvent): * bridge/mac/WebCoreFrameBridge.mm: (-[WebCoreFrameBridge setSelectedDOMRange:affinity:closeTyping:]): (-[WebCoreFrameBridge smartDeleteRangeForProposedRange:]): * css/css_base.cpp: (WebCore::StyleBaseImpl::baseURL): * css/css_computedstyle.cpp: (WebCore::CSSComputedStyleDeclarationImpl::getPropertyCSSValue): * css/css_valueimpl.cpp: (WebCore::CSSMutableStyleDeclarationImpl::removeProperty): (WebCore::CSSMutableStyleDeclarationImpl::setProperty): * css/cssstyleselector.cpp: (WebCore::CSSStyleSelector::applyProperty): * dom/Attr.idl: * dom/CharacterData.idl: * dom/CharacterDataImpl.cpp: (WebCore::CharacterDataImpl::CharacterDataImpl): (WebCore::CharacterDataImpl::rendererIsNeeded): (WebCore::CharacterDataImpl::dump): * dom/CharacterDataImpl.h: * dom/ContainerNodeImpl.cpp: (WebCore::ContainerNodeImpl::ContainerNodeImpl): (WebCore::ContainerNodeImpl::removeChild): (WebCore::ContainerNodeImpl::attach): (WebCore::ContainerNodeImpl::detach): (WebCore::ContainerNodeImpl::insertedIntoDocument): (WebCore::ContainerNodeImpl::removedFromDocument): (WebCore::ContainerNodeImpl::insertedIntoTree): (WebCore::ContainerNodeImpl::removedFromTree): (WebCore::ContainerNodeImpl::setFocus): (WebCore::ContainerNodeImpl::setActive): (WebCore::ContainerNodeImpl::setHovered): (WebCore::dispatchChildInsertionEvents): (WebCore::dispatchChildRemovalEvents): * dom/ContainerNodeImpl.h: * dom/DOMImplementationImpl.cpp: (WebCore::DOMImplementationImpl::createDocument): * dom/DocumentImpl.cpp: (WebCore::DocumentImpl::removeAllEventListenersFromAllNodes): (WebCore::DocumentImpl::removeAllDisconnectedNodeEventListeners): (WebCore::DocumentImpl::getAccObjectCache): (WebCore::DocumentImpl::setFocusNode): (WebCore::DocumentImpl::topDocument): * dom/Element.idl: * dom/EventTargetNodeImpl.cpp: Added. (WebCore::EventTargetNodeImpl::EventTargetNodeImpl): (WebCore::EventTargetNodeImpl::~EventTargetNodeImpl): (WebCore::EventTargetNodeImpl::insertedIntoDocument): (WebCore::EventTargetNodeImpl::removedFromDocument): (WebCore::EventTargetNodeImpl::addEventListener): (WebCore::EventTargetNodeImpl::removeEventListener): (WebCore::EventTargetNodeImpl::removeAllEventListeners): (WebCore::EventTargetNodeImpl::handleLocalEvents): (WebCore::EventTargetNodeImpl::dispatchGenericEvent): (WebCore::EventTargetNodeImpl::dispatchEvent): (WebCore::EventTargetNodeImpl::dispatchSubtreeModifiedEvent): (WebCore::EventTargetNodeImpl::dispatchWindowEvent): (WebCore::EventTargetNodeImpl::dispatchUIEvent): (WebCore::EventTargetNodeImpl::dispatchKeyEvent): (WebCore::EventTargetNodeImpl::dispatchMouseEvent): (WebCore::EventTargetNodeImpl::dispatchSimulatedMouseEvent): (WebCore::EventTargetNodeImpl::dispatchWheelEvent): (WebCore::EventTargetNodeImpl::dispatchHTMLEvent): (WebCore::EventTargetNodeImpl::removeHTMLEventListener): (WebCore::EventTargetNodeImpl::setHTMLEventListener): (WebCore::EventTargetNodeImpl::getHTMLEventListener): (WebCore::EventTargetNodeImpl::disabled): (WebCore::EventTargetNodeImpl::defaultEventHandler): (WebCore::EventTargetNodeImpl::dump): * dom/EventTargetNodeImpl.h: Added. (WebCore::EventTargetNodeImpl::isEventTargetNode): (WebCore::EventTargetNodeImpl::preDispatchEventHandler): (WebCore::EventTargetNodeImpl::postDispatchEventHandler): (WebCore::EventTarget): (WebCore::forbidEventDispatch): (WebCore::allowEventDispatch): (WebCore::eventDispatchForbidden): * dom/NodeImpl.cpp: (WebCore::NodeImpl::NodeImpl): (WebCore::NodeImpl::~NodeImpl): (WebCore::NodeImpl::dump): (WebCore::NodeImpl::detach): (WebCore::NodeImpl::insertedIntoDocument): (WebCore::NodeImpl::removedFromDocument): * dom/NodeImpl.h: (WebCore::NodeImpl::isEventTargetNode): (WebCore::NodeImpl::isLink): (WebCore::NodeImpl::getDocument): (WebCore::NodeImpl::inDocument): * dom/dom2_eventsimpl.cpp: (WebCore::MouseRelatedEventImpl::receivedTarget): * dom/dom2_rangeimpl.cpp: (WebCore::RangeImpl::commonAncestorContainer): * dom/dom_elementimpl.cpp: (WebCore::inHTMLDocument): (WebCore::ElementImpl::focus): (WebCore::ElementImpl::blur): (WebCore::StyledElementImpl::parseMappedAttribute): * dom/dom_position.cpp: (WebCore::Position::documentElement): * dom/dom_position.h: * editing/ReplaceSelectionCommand.cpp: (WebCore::computeAndStoreNodeDesiredStyle): * editing/SelectionController.cpp: (WebCore::SelectionController::needsCaretRepaint): * editing/visible_units.cpp: (WebCore::previousBoundary): (WebCore::nextBoundary): (WebCore::previousLinePosition): (WebCore::nextLinePosition): (WebCore::startOfDocument): (WebCore::endOfDocument): * khtml/ecma/kjs_dom.cpp: (KJS::DOMNode::mark): (KJS::DOMNode::getValueProperty): (KJS::DOMNode::putValueProperty): (KJS::DOMNodeProtoFunc::callAsFunction): (KJS::DOMEventTargetNode::DOMEventTargetNode): (KJS::DOMEventTargetNode::getOwnPropertySlot): (KJS::DOMEventTargetNode::getValueProperty): (KJS::DOMEventTargetNode::put): (KJS::DOMEventTargetNode::putValueProperty): (KJS::DOMEventTargetNode::setListener): (KJS::DOMEventTargetNode::getListener): (KJS::DOMEventTargetNode::pushEventHandlerScope): (KJS::DOMEventTargetNodeProtoFunc::callAsFunction): (KJS::): (KJS::DOMDocument::DOMDocument): (KJS::DOMDocument::getOwnPropertySlot): (KJS::DOMDocument::put): (KJS::DOMDocument::putValueProperty): (KJS::DOMDocumentProtoFunc::callAsFunction): (KJS::DOMElement::DOMElement): (KJS::DOMElement::getValueProperty): (KJS::DOMElement::put): (KJS::DOMElement::putValueProperty): (KJS::DOMElement::getOwnPropertySlot): (KJS::DOMElementProtoFunc::callAsFunction): (KJS::checkNodeSecurity): * khtml/ecma/kjs_dom.h: (KJS::DOMNode::): (KJS::DOMEventTargetNode::): (KJS::DOMElement::): * khtml/ecma/kjs_events.cpp: (KJS::JSLazyEventListener::parseCode): (KJS::getNodeEventListener): * khtml/ecma/kjs_html.cpp: (KJS::HTMLElement::bodyGetter): (KJS::HTMLElement::anchorGetter): (KJS::HTMLElement::getValueProperty): (KJS::HTMLElement::bodySetter): * khtml/ecma/kjs_views.cpp: (KJS::DOMAbstractViewProtoFunc::callAsFunction): * khtml/html/HTMLFormElementImpl.cpp: (WebCore::HTMLFormElementImpl::registerFormElement): (WebCore::HTMLFormElementImpl::removeFormElement): * khtml/html/HTMLGenericFormElementImpl.cpp: (WebCore::HTMLGenericFormElementImpl::insertedIntoTree): * khtml/html/HTMLInputElementImpl.cpp: (WebCore::HTMLInputElementImpl::~HTMLInputElementImpl): (WebCore::HTMLInputElementImpl::focus): * khtml/html/HTMLOptionElementImpl.cpp: (WebCore::HTMLOptionElementImpl::text): * khtml/html/HTMLSelectElementImpl.cpp: (WebCore::HTMLSelectElementImpl::~HTMLSelectElementImpl): * khtml/html/HTMLTextAreaElementImpl.cpp: (WebCore::HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl): * khtml/html/html_baseimpl.cpp: (WebCore::HTMLBodyElementImpl::insertedIntoDocument): (WebCore::HTMLFrameElementImpl::isURLAllowed): (WebCore::HTMLFrameElementImpl::openURL): (WebCore::HTMLFrameElementImpl::frameWidth): (WebCore::HTMLFrameElementImpl::frameHeight): * khtml/html/html_imageimpl.cpp: (WebCore::HTMLImageLoader::~HTMLImageLoader): (WebCore::HTMLImageLoader::updateFromElement): (WebCore::HTMLImageLoader::notifyFinished): (WebCore::HTMLImageElementImpl::width): (WebCore::HTMLImageElementImpl::height): (WebCore::HTMLMapElementImpl::~HTMLMapElementImpl): * khtml/html/html_inlineimpl.cpp: (WebCore::HTMLAnchorElementImpl::defaultEventHandler): * khtml/html/htmltokenizer.cpp: (WebCore::HTMLTokenizer::notifyFinished): * ksvg2/svg/SVGAnimateColorElementImpl.cpp: (SVGAnimateColorElementImpl::handleTimerEvent): * ksvg2/svg/SVGAnimateElementImpl.cpp: (SVGAnimateElementImpl::handleTimerEvent): * ksvg2/svg/SVGAnimateTransformElementImpl.cpp: (SVGAnimateTransformElementImpl::handleTimerEvent): * ksvg2/svg/SVGAnimationElementImpl.cpp: (SVGAnimationElementImpl::closeRenderer): * ksvg2/svg/SVGDOMImplementationImpl.cpp: * ksvg2/svg/SVGDocumentImpl.cpp: (WebCore::SVGDocumentImpl::dispatchRecursiveEvent): * ksvg2/svg/SVGDocumentImpl.h: * ksvg2/svg/SVGImageElementImpl.cpp: * ksvg2/svg/SVGSetElementImpl.cpp: (SVGSetElementImpl::handleTimerEvent): * kwq/KWQAccObject.mm: (-[KWQAccObject mouseButtonListener]): (-[KWQAccObject accessibilityPerformAction:]): * kwq/KWQTextArea.mm: (-[KWQTextAreaTextView dispatchHTMLEvent:]): * page/Frame.cpp: (WebCore::dispatchKHTMLEditableContentChanged): * page/FrameView.cpp: (WebCore::FrameView::dispatchDragEvent): (WebCore::FrameView::dispatchMouseEvent): (WebCore::FrameView::viewportWheelEvent): * rendering/render_layer.cpp: (WebCore::RenderLayer::scrollToOffset): * rendering/render_object.cpp: (WebCore::RenderObject::shouldSelect): (WebCore::RenderObject::backslashAsCurrencySymbol): * rendering/render_replaced.cpp: (WebCore::RenderWidget::sendConsumedMouseUp): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@13369 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- LayoutTests/ChangeLog | 7 + .../fast/dom/prototype-chain-expected.txt | 8 +- WebCore/ChangeLog | 273 ++++++ WebCore/WebCore+SVG/KDOMHeaders.h | 4 +- WebCore/WebCore.xcodeproj/project.pbxproj | 10 +- WebCore/bindings/js/JSDOMCore.cpp | 1 + WebCore/bindings/objc/DOM.mm | 33 +- WebCore/bridge/mac/MacFrame.mm | 6 +- WebCore/bridge/mac/WebCoreFrameBridge.mm | 2 - WebCore/css/css_base.cpp | 10 +- WebCore/css/css_computedstyle.cpp | 5 +- WebCore/css/css_valueimpl.cpp | 8 - WebCore/css/cssstyleselector.cpp | 2 +- WebCore/dom/Attr.idl | 2 +- WebCore/dom/CharacterData.idl | 2 +- WebCore/dom/CharacterDataImpl.cpp | 8 +- WebCore/dom/CharacterDataImpl.h | 4 +- WebCore/dom/ContainerNodeImpl.cpp | 43 +- WebCore/dom/ContainerNodeImpl.h | 4 +- WebCore/dom/DocumentImpl.cpp | 36 +- WebCore/dom/Element.idl | 2 +- WebCore/dom/EventTargetNodeImpl.cpp | 511 +++++++++++ WebCore/dom/EventTargetNodeImpl.h | 154 ++++ WebCore/dom/NodeImpl.cpp | 467 +--------- WebCore/dom/NodeImpl.h | 83 +- WebCore/dom/dom2_eventsimpl.cpp | 6 +- WebCore/dom/dom2_rangeimpl.cpp | 2 +- WebCore/dom/dom_elementimpl.cpp | 26 +- WebCore/dom/dom_position.cpp | 8 + WebCore/dom/dom_position.h | 1 + WebCore/editing/ReplaceSelectionCommand.cpp | 12 +- WebCore/editing/SelectionController.cpp | 3 - WebCore/editing/visible_units.cpp | 36 +- WebCore/khtml/ecma/kjs_dom.cpp | 858 ++++++++++-------- WebCore/khtml/ecma/kjs_dom.h | 70 +- WebCore/khtml/ecma/kjs_events.cpp | 4 +- WebCore/khtml/ecma/kjs_html.cpp | 14 +- WebCore/khtml/ecma/kjs_views.cpp | 3 +- WebCore/khtml/html/HTMLFormElementImpl.cpp | 4 +- .../khtml/html/HTMLGenericFormElementImpl.cpp | 8 +- WebCore/khtml/html/HTMLInputElementImpl.cpp | 14 +- WebCore/khtml/html/HTMLOptionElementImpl.cpp | 2 +- WebCore/khtml/html/HTMLSelectElementImpl.cpp | 3 +- .../khtml/html/HTMLTextAreaElementImpl.cpp | 2 +- WebCore/khtml/html/html_baseimpl.cpp | 26 +- WebCore/khtml/html/html_imageimpl.cpp | 35 +- WebCore/khtml/html/html_inlineimpl.cpp | 2 +- WebCore/khtml/html/htmltokenizer.cpp | 4 +- .../ksvg2/svg/SVGAnimateColorElementImpl.cpp | 12 +- WebCore/ksvg2/svg/SVGAnimateElementImpl.cpp | 12 +- .../svg/SVGAnimateTransformElementImpl.cpp | 12 +- WebCore/ksvg2/svg/SVGAnimationElementImpl.cpp | 3 +- .../ksvg2/svg/SVGDOMImplementationImpl.cpp | 11 +- WebCore/ksvg2/svg/SVGDocumentImpl.cpp | 4 +- WebCore/ksvg2/svg/SVGDocumentImpl.h | 9 +- WebCore/ksvg2/svg/SVGImageElementImpl.cpp | 5 +- WebCore/ksvg2/svg/SVGSetElementImpl.cpp | 12 +- WebCore/kwq/KWQAccObject.mm | 13 +- WebCore/kwq/KWQTextArea.mm | 2 +- WebCore/page/Frame.cpp | 2 +- WebCore/page/FrameView.cpp | 10 +- WebCore/rendering/render_layer.cpp | 2 +- WebCore/rendering/render_object.cpp | 22 +- WebCore/rendering/render_replaced.cpp | 2 +- 64 files changed, 1714 insertions(+), 1247 deletions(-) create mode 100644 WebCore/dom/EventTargetNodeImpl.cpp create mode 100644 WebCore/dom/EventTargetNodeImpl.h diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index b504be9f286..e22c9e7b7cc 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,10 @@ +2006-03-17 Geoffrey Garen + + Reviewed by Darin. + + * fast/dom/prototype-chain-expected.txt: Updated to reflect new + prototype chain. + 2006-03-17 Beth Dakin Reviewed by hyatt diff --git a/LayoutTests/fast/dom/prototype-chain-expected.txt b/LayoutTests/fast/dom/prototype-chain-expected.txt index 00ca161234b..05b907fc8f1 100644 --- a/LayoutTests/fast/dom/prototype-chain-expected.txt +++ b/LayoutTests/fast/dom/prototype-chain-expected.txt @@ -2,20 +2,24 @@ This page prints out the prototype chains of select DOM objects. Older versions NOTE: This test will start failing if you change the layout of a related prototype chain in WebCore. That does not necessarily mean that you have done something wrong; you may just need to check in new results. ------ [object HTMLDocument] (3 prototypes) ----- +----- [object HTMLDocument] (4 prototypes) ----- [object Object] [object DOMNode] +[object DOMEventTargetNode] + [object DOMDocument] ------ [object DIV] (4 prototypes) ----- +----- [object DIV] (5 prototypes) ----- [object Object] [object DOMNode] +[object DOMEventTargetNode] + [object DOMElement] [object JSElement] diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 4006d144882..4478a01ec70 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,276 @@ +2006-03-17 Geoffrey Garen + + Reviewed by Darin. + + - Fixed some crashes in event dispatch and settled the question of + when getDocument() can return NULL, removing superfluous NULL checks. + + I promise to check in a test case soon, but I need to land this before + the global rename happens, and I left the test file on my other machine. + + Here's what I did: + + (1) Removed NULL checks for getDocument() in cases where we know it + should not return NULL (which turned out to be all but one). Replaced + with ASSERT inside getDocument(). Tested to ensure there was no + regression @ albertsons.com. + + (2) Added the EventTargetNode class, which represents Nodes that + implement the DOM EventTarget interface. Discussed this design with + Maciej and Hyatt. The previous dsign -- assuming that all Nodes were + EventTargets -- made it possible to crash WebKit by, for example, + dispatching a mouse event to a documentType node that was not + associated with a document. + + (3) Reflected (2) into the JS bindings and touched JSDOMCore.cpp to + force a re-build. + + (4) Using classInfo checking, strengthened type constraints on + JavaScript method dispatch so that you can't finagle JavaScript into, + for example, invoking a document-dependent method belonging to a + node type that's guaranteed to have a document on a node type that may + not have one. + + (5) Pushed some IE-specific JS bindings that depend on a node having a + document down from DOMNode to DOMElement. (An element always has a + document.) Tested that Firefox's behavior matched. Confirmed with MSDN. + + (6) Updated Objc bindigns to throw an exception if you try to use + the event interface on a node that doesn't support it. Discussed this + design with Maciej and TimH. + + (7) Consolidated repeated documentElement-finding code in the Position + class into the Position::documentElement() method. Did the same for + repeated top-level document finding and DocumentImpl::topDocument(). + + * WebCore+SVG/KDOMHeaders.h: + * WebCore.xcodeproj/project.pbxproj: + * bindings/js/JSDOMCore.cpp: + * bindings/objc/DOM.mm: + (-[DOMNode addEventListener:::]): + (-[DOMNode removeEventListener:::]): + (-[DOMNode dispatchEvent:]): + (-[DOMNode KJS::Bindings::]): + * bridge/mac/MacFrame.mm: + (WebCore::MacFrame::keyEvent): + (WebCore::MacFrame::dispatchCPPEvent): + * bridge/mac/WebCoreFrameBridge.mm: + (-[WebCoreFrameBridge setSelectedDOMRange:affinity:closeTyping:]): + (-[WebCoreFrameBridge smartDeleteRangeForProposedRange:]): + * css/css_base.cpp: + (WebCore::StyleBaseImpl::baseURL): + * css/css_computedstyle.cpp: + (WebCore::CSSComputedStyleDeclarationImpl::getPropertyCSSValue): + * css/css_valueimpl.cpp: + (WebCore::CSSMutableStyleDeclarationImpl::removeProperty): + (WebCore::CSSMutableStyleDeclarationImpl::setProperty): + * css/cssstyleselector.cpp: + (WebCore::CSSStyleSelector::applyProperty): + * dom/Attr.idl: + * dom/CharacterData.idl: + * dom/CharacterDataImpl.cpp: + (WebCore::CharacterDataImpl::CharacterDataImpl): + (WebCore::CharacterDataImpl::rendererIsNeeded): + (WebCore::CharacterDataImpl::dump): + * dom/CharacterDataImpl.h: + * dom/ContainerNodeImpl.cpp: + (WebCore::ContainerNodeImpl::ContainerNodeImpl): + (WebCore::ContainerNodeImpl::removeChild): + (WebCore::ContainerNodeImpl::attach): + (WebCore::ContainerNodeImpl::detach): + (WebCore::ContainerNodeImpl::insertedIntoDocument): + (WebCore::ContainerNodeImpl::removedFromDocument): + (WebCore::ContainerNodeImpl::insertedIntoTree): + (WebCore::ContainerNodeImpl::removedFromTree): + (WebCore::ContainerNodeImpl::setFocus): + (WebCore::ContainerNodeImpl::setActive): + (WebCore::ContainerNodeImpl::setHovered): + (WebCore::dispatchChildInsertionEvents): + (WebCore::dispatchChildRemovalEvents): + * dom/ContainerNodeImpl.h: + * dom/DOMImplementationImpl.cpp: + (WebCore::DOMImplementationImpl::createDocument): + * dom/DocumentImpl.cpp: + (WebCore::DocumentImpl::removeAllEventListenersFromAllNodes): + (WebCore::DocumentImpl::removeAllDisconnectedNodeEventListeners): + (WebCore::DocumentImpl::getAccObjectCache): + (WebCore::DocumentImpl::setFocusNode): + (WebCore::DocumentImpl::topDocument): + * dom/Element.idl: + * dom/EventTargetNodeImpl.cpp: Added. + (WebCore::EventTargetNodeImpl::EventTargetNodeImpl): + (WebCore::EventTargetNodeImpl::~EventTargetNodeImpl): + (WebCore::EventTargetNodeImpl::insertedIntoDocument): + (WebCore::EventTargetNodeImpl::removedFromDocument): + (WebCore::EventTargetNodeImpl::addEventListener): + (WebCore::EventTargetNodeImpl::removeEventListener): + (WebCore::EventTargetNodeImpl::removeAllEventListeners): + (WebCore::EventTargetNodeImpl::handleLocalEvents): + (WebCore::EventTargetNodeImpl::dispatchGenericEvent): + (WebCore::EventTargetNodeImpl::dispatchEvent): + (WebCore::EventTargetNodeImpl::dispatchSubtreeModifiedEvent): + (WebCore::EventTargetNodeImpl::dispatchWindowEvent): + (WebCore::EventTargetNodeImpl::dispatchUIEvent): + (WebCore::EventTargetNodeImpl::dispatchKeyEvent): + (WebCore::EventTargetNodeImpl::dispatchMouseEvent): + (WebCore::EventTargetNodeImpl::dispatchSimulatedMouseEvent): + (WebCore::EventTargetNodeImpl::dispatchWheelEvent): + (WebCore::EventTargetNodeImpl::dispatchHTMLEvent): + (WebCore::EventTargetNodeImpl::removeHTMLEventListener): + (WebCore::EventTargetNodeImpl::setHTMLEventListener): + (WebCore::EventTargetNodeImpl::getHTMLEventListener): + (WebCore::EventTargetNodeImpl::disabled): + (WebCore::EventTargetNodeImpl::defaultEventHandler): + (WebCore::EventTargetNodeImpl::dump): + * dom/EventTargetNodeImpl.h: Added. + (WebCore::EventTargetNodeImpl::isEventTargetNode): + (WebCore::EventTargetNodeImpl::preDispatchEventHandler): + (WebCore::EventTargetNodeImpl::postDispatchEventHandler): + (WebCore::EventTarget): + (WebCore::forbidEventDispatch): + (WebCore::allowEventDispatch): + (WebCore::eventDispatchForbidden): + * dom/NodeImpl.cpp: + (WebCore::NodeImpl::NodeImpl): + (WebCore::NodeImpl::~NodeImpl): + (WebCore::NodeImpl::dump): + (WebCore::NodeImpl::detach): + (WebCore::NodeImpl::insertedIntoDocument): + (WebCore::NodeImpl::removedFromDocument): + * dom/NodeImpl.h: + (WebCore::NodeImpl::isEventTargetNode): + (WebCore::NodeImpl::isLink): + (WebCore::NodeImpl::getDocument): + (WebCore::NodeImpl::inDocument): + * dom/dom2_eventsimpl.cpp: + (WebCore::MouseRelatedEventImpl::receivedTarget): + * dom/dom2_rangeimpl.cpp: + (WebCore::RangeImpl::commonAncestorContainer): + * dom/dom_elementimpl.cpp: + (WebCore::inHTMLDocument): + (WebCore::ElementImpl::focus): + (WebCore::ElementImpl::blur): + (WebCore::StyledElementImpl::parseMappedAttribute): + * dom/dom_position.cpp: + (WebCore::Position::documentElement): + * dom/dom_position.h: + * editing/ReplaceSelectionCommand.cpp: + (WebCore::computeAndStoreNodeDesiredStyle): + * editing/SelectionController.cpp: + (WebCore::SelectionController::needsCaretRepaint): + * editing/visible_units.cpp: + (WebCore::previousBoundary): + (WebCore::nextBoundary): + (WebCore::previousLinePosition): + (WebCore::nextLinePosition): + (WebCore::startOfDocument): + (WebCore::endOfDocument): + * khtml/ecma/kjs_dom.cpp: + (KJS::DOMNode::mark): + (KJS::DOMNode::getValueProperty): + (KJS::DOMNode::putValueProperty): + (KJS::DOMNodeProtoFunc::callAsFunction): + (KJS::DOMEventTargetNode::DOMEventTargetNode): + (KJS::DOMEventTargetNode::getOwnPropertySlot): + (KJS::DOMEventTargetNode::getValueProperty): + (KJS::DOMEventTargetNode::put): + (KJS::DOMEventTargetNode::putValueProperty): + (KJS::DOMEventTargetNode::setListener): + (KJS::DOMEventTargetNode::getListener): + (KJS::DOMEventTargetNode::pushEventHandlerScope): + (KJS::DOMEventTargetNodeProtoFunc::callAsFunction): + (KJS::): + (KJS::DOMDocument::DOMDocument): + (KJS::DOMDocument::getOwnPropertySlot): + (KJS::DOMDocument::put): + (KJS::DOMDocument::putValueProperty): + (KJS::DOMDocumentProtoFunc::callAsFunction): + (KJS::DOMElement::DOMElement): + (KJS::DOMElement::getValueProperty): + (KJS::DOMElement::put): + (KJS::DOMElement::putValueProperty): + (KJS::DOMElement::getOwnPropertySlot): + (KJS::DOMElementProtoFunc::callAsFunction): + (KJS::checkNodeSecurity): + * khtml/ecma/kjs_dom.h: + (KJS::DOMNode::): + (KJS::DOMEventTargetNode::): + (KJS::DOMElement::): + * khtml/ecma/kjs_events.cpp: + (KJS::JSLazyEventListener::parseCode): + (KJS::getNodeEventListener): + * khtml/ecma/kjs_html.cpp: + (KJS::HTMLElement::bodyGetter): + (KJS::HTMLElement::anchorGetter): + (KJS::HTMLElement::getValueProperty): + (KJS::HTMLElement::bodySetter): + * khtml/ecma/kjs_views.cpp: + (KJS::DOMAbstractViewProtoFunc::callAsFunction): + * khtml/html/HTMLFormElementImpl.cpp: + (WebCore::HTMLFormElementImpl::registerFormElement): + (WebCore::HTMLFormElementImpl::removeFormElement): + * khtml/html/HTMLGenericFormElementImpl.cpp: + (WebCore::HTMLGenericFormElementImpl::insertedIntoTree): + * khtml/html/HTMLInputElementImpl.cpp: + (WebCore::HTMLInputElementImpl::~HTMLInputElementImpl): + (WebCore::HTMLInputElementImpl::focus): + * khtml/html/HTMLOptionElementImpl.cpp: + (WebCore::HTMLOptionElementImpl::text): + * khtml/html/HTMLSelectElementImpl.cpp: + (WebCore::HTMLSelectElementImpl::~HTMLSelectElementImpl): + * khtml/html/HTMLTextAreaElementImpl.cpp: + (WebCore::HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl): + * khtml/html/html_baseimpl.cpp: + (WebCore::HTMLBodyElementImpl::insertedIntoDocument): + (WebCore::HTMLFrameElementImpl::isURLAllowed): + (WebCore::HTMLFrameElementImpl::openURL): + (WebCore::HTMLFrameElementImpl::frameWidth): + (WebCore::HTMLFrameElementImpl::frameHeight): + * khtml/html/html_imageimpl.cpp: + (WebCore::HTMLImageLoader::~HTMLImageLoader): + (WebCore::HTMLImageLoader::updateFromElement): + (WebCore::HTMLImageLoader::notifyFinished): + (WebCore::HTMLImageElementImpl::width): + (WebCore::HTMLImageElementImpl::height): + (WebCore::HTMLMapElementImpl::~HTMLMapElementImpl): + * khtml/html/html_inlineimpl.cpp: + (WebCore::HTMLAnchorElementImpl::defaultEventHandler): + * khtml/html/htmltokenizer.cpp: + (WebCore::HTMLTokenizer::notifyFinished): + * ksvg2/svg/SVGAnimateColorElementImpl.cpp: + (SVGAnimateColorElementImpl::handleTimerEvent): + * ksvg2/svg/SVGAnimateElementImpl.cpp: + (SVGAnimateElementImpl::handleTimerEvent): + * ksvg2/svg/SVGAnimateTransformElementImpl.cpp: + (SVGAnimateTransformElementImpl::handleTimerEvent): + * ksvg2/svg/SVGAnimationElementImpl.cpp: + (SVGAnimationElementImpl::closeRenderer): + * ksvg2/svg/SVGDOMImplementationImpl.cpp: + * ksvg2/svg/SVGDocumentImpl.cpp: + (WebCore::SVGDocumentImpl::dispatchRecursiveEvent): + * ksvg2/svg/SVGDocumentImpl.h: + * ksvg2/svg/SVGImageElementImpl.cpp: + * ksvg2/svg/SVGSetElementImpl.cpp: + (SVGSetElementImpl::handleTimerEvent): + * kwq/KWQAccObject.mm: + (-[KWQAccObject mouseButtonListener]): + (-[KWQAccObject accessibilityPerformAction:]): + * kwq/KWQTextArea.mm: + (-[KWQTextAreaTextView dispatchHTMLEvent:]): + * page/Frame.cpp: + (WebCore::dispatchKHTMLEditableContentChanged): + * page/FrameView.cpp: + (WebCore::FrameView::dispatchDragEvent): + (WebCore::FrameView::dispatchMouseEvent): + (WebCore::FrameView::viewportWheelEvent): + * rendering/render_layer.cpp: + (WebCore::RenderLayer::scrollToOffset): + * rendering/render_object.cpp: + (WebCore::RenderObject::shouldSelect): + (WebCore::RenderObject::backslashAsCurrencySymbol): + * rendering/render_replaced.cpp: + (WebCore::RenderWidget::sendConsumedMouseUp): + 2006-03-17 David Hyatt Fix for 7837, make opacity work with table rows. Make transparent backgrounds diff --git a/WebCore/WebCore+SVG/KDOMHeaders.h b/WebCore/WebCore+SVG/KDOMHeaders.h index 6997642a90d..a906771425c 100644 --- a/WebCore/WebCore+SVG/KDOMHeaders.h +++ b/WebCore/WebCore+SVG/KDOMHeaders.h @@ -4,14 +4,14 @@ namespace khtml { } namespace DOM { - class NodeImpl; + class EventTargetNodeImpl; } namespace KDOM { using namespace DOM; using namespace khtml; typedef khtml::StyleListImpl CSSStyleSelectorList; - typedef NodeImpl EventTargetImpl; + typedef EventTargetNodeImpl EventTargetImpl; } #include "Shared.h" diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj index 2732c264b84..4ac8cefc59e 100644 --- a/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/WebCore/WebCore.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 14EC267F09CA07E000E1EEEC /* EventTargetNodeImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 14EC267D09CA07E000E1EEEC /* EventTargetNodeImpl.h */; }; + 14EC268009CA07E000E1EEEC /* EventTargetNodeImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14EC267E09CA07E000E1EEEC /* EventTargetNodeImpl.cpp */; }; 1A2154EE099A11A800343DF8 /* JSDOMCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2154EC099A11A800343DF8 /* JSDOMCore.cpp */; }; 1A2154EF099A11A800343DF8 /* JSDOMEvents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2154ED099A11A800343DF8 /* JSDOMEvents.cpp */; }; 1A69D381085627410009880D /* domparser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A69D37F085627410009880D /* domparser.h */; }; @@ -1124,6 +1126,8 @@ /* End PBXBuildStyle section */ /* Begin PBXFileReference section */ + 14EC267D09CA07E000E1EEEC /* EventTargetNodeImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventTargetNodeImpl.h; sourceTree = ""; }; + 14EC267E09CA07E000E1EEEC /* EventTargetNodeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventTargetNodeImpl.cpp; sourceTree = ""; }; 1A2154EC099A11A800343DF8 /* JSDOMCore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JSDOMCore.cpp; path = bindings/js/JSDOMCore.cpp; sourceTree = ""; }; 1A2154ED099A11A800343DF8 /* JSDOMEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JSDOMEvents.cpp; path = bindings/js/JSDOMEvents.cpp; sourceTree = ""; }; 1A69D37F085627410009880D /* domparser.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = domparser.h; sourceTree = ""; tabWidth = 8; usesTabs = 0; }; @@ -1577,7 +1581,7 @@ A81872110977D3C0005826D9 /* ContainerNodeImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ContainerNodeImpl.h; sourceTree = ""; }; A81872120977D3C0005826D9 /* NodeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = NodeImpl.cpp; sourceTree = ""; }; A81872130977D3C0005826D9 /* NameNodeListImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NameNodeListImpl.h; sourceTree = ""; }; - A81872140977D3C0005826D9 /* ContainerNodeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ContainerNodeImpl.cpp; sourceTree = ""; }; + A81872140977D3C0005826D9 /* ContainerNodeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContainerNodeImpl.cpp; sourceTree = ""; }; A81872150977D3C0005826D9 /* ChildNodeListImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ChildNodeListImpl.h; sourceTree = ""; }; A81872160977D3C0005826D9 /* NodeListImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = NodeListImpl.cpp; sourceTree = ""; }; A81872170977D3C0005826D9 /* NodeImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NodeImpl.h; sourceTree = ""; }; @@ -3847,6 +3851,8 @@ 93EEC1F709C2877700C515D1 /* WheelEvent.idl */, F523D30902DE4476018635CA /* xml_tokenizer.cpp */, F523D30A02DE4476018635CA /* xml_tokenizer.h */, + 14EC267D09CA07E000E1EEEC /* EventTargetNodeImpl.h */, + 14EC267E09CA07E000E1EEEC /* EventTargetNodeImpl.cpp */, ); path = dom; sourceTree = ""; @@ -4446,6 +4452,7 @@ 9352071E09BD3BBB00F2038D /* WebCoreWidgetHolder.h in Headers */, 935207BE09BD410A00F2038D /* LocalizedStrings.h in Headers */, 9352088209BD45E900F2038D /* CookieJar.h in Headers */, + 14EC267F09CA07E000E1EEEC /* EventTargetNodeImpl.h in Headers */, 93EEC1FA09C2877700C515D1 /* DocPtr.h in Headers */, 93EEC20009C2877700C515D1 /* CanvasRenderingContext2D.h in Headers */, 93EEC20109C2877700C515D1 /* CanvasStyle.h in Headers */, @@ -5600,6 +5607,7 @@ 935207C009BD412100F2038D /* LocalizedStringsMac.mm in Sources */, 9352084509BD43B900F2038D /* Language.mm in Sources */, 9352087709BD453400F2038D /* CookieJar.mm in Sources */, + 14EC268009CA07E000E1EEEC /* EventTargetNodeImpl.cpp in Sources */, 93E47C5C09BE2BBB0019C5C1 /* PageMac.mm in Sources */, 93EEC1FF09C2877700C515D1 /* CanvasRenderingContext2D.cpp in Sources */, 93EEC20209C2877700C515D1 /* CanvasGradient.cpp in Sources */, diff --git a/WebCore/bindings/js/JSDOMCore.cpp b/WebCore/bindings/js/JSDOMCore.cpp index 2ffaedd98c8..5e37d081d32 100644 --- a/WebCore/bindings/js/JSDOMCore.cpp +++ b/WebCore/bindings/js/JSDOMCore.cpp @@ -2,6 +2,7 @@ // The files below are all generated by a script. + #include "JSAttr.cpp" #include "JSCharacterData.cpp" #include "JSDocumentType.cpp" diff --git a/WebCore/bindings/objc/DOM.mm b/WebCore/bindings/objc/DOM.mm index 1ef77b503d1..b81f4817466 100644 --- a/WebCore/bindings/objc/DOM.mm +++ b/WebCore/bindings/objc/DOM.mm @@ -412,21 +412,30 @@ static ListenerMap *listenerMap; - (void)addEventListener:(NSString *)type :(id )listener :(BOOL)useCapture { + if (![self _nodeImpl]->isEventTargetNode()) + raiseDOMException(DOM_NOT_SUPPORTED_ERR); + EventListener *wrapper = ObjCEventListener::create(listener); - [self _nodeImpl]->addEventListener(type, wrapper, useCapture); + EventTargetNodeCast([self _nodeImpl])->addEventListener(type, wrapper, useCapture); wrapper->deref(); } - (void)removeEventListener:(NSString *)type :(id )listener :(BOOL)useCapture { + if (![self _nodeImpl]->isEventTargetNode()) + raiseDOMException(DOM_NOT_SUPPORTED_ERR); + if (EventListener *wrapper = ObjCEventListener::find(listener)) - [self _nodeImpl]->removeEventListener(type, wrapper, useCapture); + EventTargetNodeCast([self _nodeImpl])->removeEventListener(type, wrapper, useCapture); } - (BOOL)dispatchEvent:(DOMEvent *)event { + if (![self _nodeImpl]->isEventTargetNode()) + raiseDOMException(DOM_NOT_SUPPORTED_ERR); + ExceptionCode ec = 0; - BOOL result = [self _nodeImpl]->dispatchEvent([event _eventImpl], ec); + BOOL result = EventTargetNodeCast([self _nodeImpl])->dispatchEvent([event _eventImpl], ec); raiseOnDOMError(ec); return result; } @@ -657,19 +666,11 @@ static ListenerMap *listenerMap; - (const KJS::Bindings::RootObject *)_executionContext { - NodeImpl *n = [self _nodeImpl]; - if (!n) - return 0; - - DocumentImpl *doc = n->getDocument(); - if (!doc) - return 0; - - MacFrame *p = Mac(doc->frame()); - if (!p) - return 0; - - return p->executionContextForDOM(); + if (NodeImpl *n = [self _nodeImpl]) + if (MacFrame *f = Mac(n->getDocument()->frame())) + return f->executionContextForDOM(); + + return 0; } @end diff --git a/WebCore/bridge/mac/MacFrame.mm b/WebCore/bridge/mac/MacFrame.mm index e37126b8132..89b0d817f3a 100644 --- a/WebCore/bridge/mac/MacFrame.mm +++ b/WebCore/bridge/mac/MacFrame.mm @@ -1369,7 +1369,7 @@ bool MacFrame::keyEvent(NSEvent *event) _currentEvent = KWQRetain(event); KeyEvent qEvent(event); - result = !node->dispatchKeyEvent(qEvent); + result = !EventTargetNodeCast(node)->dispatchKeyEvent(qEvent); // We want to send both a down and a press for the initial key event. // To get KHTML to do this, we send a second KeyPress with "is repeat" set to true, @@ -1377,7 +1377,7 @@ bool MacFrame::keyEvent(NSEvent *event) // That's not a great hack; it would be good to do this in a better way. if ([event type] == NSKeyDown && ![event isARepeat]) { KeyEvent repeatEvent(event, true); - if (!node->dispatchKeyEvent(repeatEvent)) + if (!EventTargetNodeCast(node)->dispatchKeyEvent(repeatEvent)) result = true; } @@ -1784,7 +1784,7 @@ bool MacFrame::dispatchCPPEvent(const AtomicString &eventType, KWQClipboard::Acc ExceptionCode ec = 0; RefPtr evt = new ClipboardEventImpl(eventType, true, true, clipboard.get()); - target->dispatchEvent(evt, ec, true); + EventTargetNodeCast(target)->dispatchEvent(evt, ec, true); bool noDefaultProcessing = evt->defaultPrevented(); // invalidate clipboard here for security diff --git a/WebCore/bridge/mac/WebCoreFrameBridge.mm b/WebCore/bridge/mac/WebCoreFrameBridge.mm index 26ec20ef910..9e473214522 100644 --- a/WebCore/bridge/mac/WebCoreFrameBridge.mm +++ b/WebCore/bridge/mac/WebCoreFrameBridge.mm @@ -1700,7 +1700,6 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element) NodeImpl *endContainer = [[range endContainer] _nodeImpl]; ASSERT(startContainer); ASSERT(endContainer); - ASSERT(startContainer->getDocument()); ASSERT(startContainer->getDocument() == endContainer->getDocument()); m_frame->document()->updateLayoutIgnorePendingStylesheets(); @@ -1849,7 +1848,6 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element) if (startContainer == nil || endContainer == nil) return nil; - ASSERT(startContainer->getDocument()); ASSERT(startContainer->getDocument() == endContainer->getDocument()); m_frame->document()->updateLayoutIgnorePendingStylesheets(); diff --git a/WebCore/css/css_base.cpp b/WebCore/css/css_base.cpp index a366c56b41f..1a2434dde37 100644 --- a/WebCore/css/css_base.cpp +++ b/WebCore/css/css_base.cpp @@ -59,13 +59,13 @@ DOMString StyleBaseImpl::baseURL() return sheet->href(); // find parent - if(sheet->parent()) return sheet->parent()->baseURL(); + if(sheet->parent()) + return sheet->parent()->baseURL(); - if(!sheet->ownerNode()) return DOMString(); + if(!sheet->ownerNode()) + return DOMString(); - DocumentImpl *doc = sheet->ownerNode()->getDocument(); - - return doc->baseURL(); + return sheet->ownerNode()->getDocument()->baseURL(); } // ------------------------------------------------------------------------------ diff --git a/WebCore/css/css_computedstyle.cpp b/WebCore/css/css_computedstyle.cpp index 7f6d27bf4f6..890c0739962 100644 --- a/WebCore/css/css_computedstyle.cpp +++ b/WebCore/css/css_computedstyle.cpp @@ -315,9 +315,8 @@ PassRefPtr CSSComputedStyleDeclarationImpl::getPropertyCSSValue(in return 0; // Make sure our layout is up to date before we allow a query on these attributes. - DocumentImpl* docimpl = node->getDocument(); - if (docimpl && updateLayout) - docimpl->updateLayout(); + if (updateLayout) + node->getDocument()->updateLayout(); RenderObject* renderer = node->renderer(); if (!renderer) diff --git a/WebCore/css/css_valueimpl.cpp b/WebCore/css/css_valueimpl.cpp index 0ca150dbf54..d128db65aa8 100644 --- a/WebCore/css/css_valueimpl.cpp +++ b/WebCore/css/css_valueimpl.cpp @@ -346,11 +346,6 @@ String CSSMutableStyleDeclarationImpl::removeProperty(int propertyID, bool notif { ec = 0; - if (m_node && !m_node->getDocument()) - return ""; // FIXME: This (not well-understood) situation happens on albertsons.com. - // We don't really know how they managed to run a script on a node - // with no document pointer, but this sidesteps the crash. - String value; QValueListIterator end; @@ -431,9 +426,6 @@ String CSSMutableStyleDeclarationImpl::removeProperty(int propertyID, ExceptionC bool CSSMutableStyleDeclarationImpl::setProperty(int propertyID, const String &value, bool important, bool notifyChanged, ExceptionCode& ec) { - if (m_node && !m_node->getDocument()) - return false; // FIXME: This (not well-understood) situation happens on albertsons.com. We don't really know how they managed to run a script on a node - // with no document pointer, but this sidesteps the crash. ec = 0; removeProperty(propertyID); diff --git a/WebCore/css/cssstyleselector.cpp b/WebCore/css/cssstyleselector.cpp index dc6902611bd..93df592c188 100644 --- a/WebCore/css/cssstyleselector.cpp +++ b/WebCore/css/cssstyleselector.cpp @@ -3921,7 +3921,7 @@ void CSSStyleSelector::applyProperty( int id, CSSValueImpl *value ) region = region->m_next.get(); } - element->getDocument()->setHasDashboardRegions (true); + element->getDocument()->setHasDashboardRegions(true); break; } diff --git a/WebCore/dom/Attr.idl b/WebCore/dom/Attr.idl index 743493d4eba..bf20e96b97b 100644 --- a/WebCore/dom/Attr.idl +++ b/WebCore/dom/Attr.idl @@ -19,7 +19,7 @@ module core { - interface [LegacyParent=KJS::DOMNode] Attr : Node { + interface [LegacyParent=KJS::DOMEventTargetNode] Attr : EventTargetNode { // DOM Level 1 diff --git a/WebCore/dom/CharacterData.idl b/WebCore/dom/CharacterData.idl index 7dd64085937..3113e976147 100644 --- a/WebCore/dom/CharacterData.idl +++ b/WebCore/dom/CharacterData.idl @@ -19,7 +19,7 @@ module core { - interface [LegacyParent=KJS::DOMNode] CharacterData : Node { + interface [LegacyParent=KJS::DOMEventTargetNode] CharacterData : EventTargetNode { attribute DOMString data raises (DOMException); diff --git a/WebCore/dom/CharacterDataImpl.cpp b/WebCore/dom/CharacterDataImpl.cpp index ef045b2f68e..659ec69116c 100644 --- a/WebCore/dom/CharacterDataImpl.cpp +++ b/WebCore/dom/CharacterDataImpl.cpp @@ -36,13 +36,13 @@ namespace WebCore { using namespace EventNames; CharacterDataImpl::CharacterDataImpl(DocumentImpl *doc) - : NodeImpl(doc) + : EventTargetNodeImpl(doc) { str = 0; } CharacterDataImpl::CharacterDataImpl(DocumentImpl *doc, const DOMString &_text) - : NodeImpl(doc) + : EventTargetNodeImpl(doc) { str = _text.impl() ? _text.impl() : new DOMStringImpl((QChar*)0, 0); str->ref(); @@ -275,7 +275,7 @@ bool CharacterDataImpl::rendererIsNeeded(RenderStyle *style) { if (!str || str->l == 0) return false; - return NodeImpl::rendererIsNeeded(style); + return EventTargetNodeImpl::rendererIsNeeded(style); } bool CharacterDataImpl::offsetInCharacters() const @@ -288,7 +288,7 @@ void CharacterDataImpl::dump(QTextStream *stream, QString ind) const { *stream << " str=\"" << DOMString(str).qstring().ascii() << "\""; - NodeImpl::dump(stream,ind); + EventTargetNodeImpl::dump(stream,ind); } #endif diff --git a/WebCore/dom/CharacterDataImpl.h b/WebCore/dom/CharacterDataImpl.h index 662e9897bea..5dfd7b777fe 100644 --- a/WebCore/dom/CharacterDataImpl.h +++ b/WebCore/dom/CharacterDataImpl.h @@ -25,11 +25,11 @@ #ifndef DOM_CharacterDataImpl_h #define DOM_CharacterDataImpl_h -#include "NodeImpl.h" +#include "EventTargetNodeImpl.h" namespace WebCore { -class CharacterDataImpl : public NodeImpl { +class CharacterDataImpl : public EventTargetNodeImpl { public: CharacterDataImpl(DocumentImpl*, const String& text); CharacterDataImpl(DocumentImpl*); diff --git a/WebCore/dom/ContainerNodeImpl.cpp b/WebCore/dom/ContainerNodeImpl.cpp index b8766672595..d73eab8c8c7 100644 --- a/WebCore/dom/ContainerNodeImpl.cpp +++ b/WebCore/dom/ContainerNodeImpl.cpp @@ -44,7 +44,7 @@ static void dispatchChildInsertionEvents(NodeImpl*, ExceptionCode&); static void dispatchChildRemovalEvents(NodeImpl*, ExceptionCode&); ContainerNodeImpl::ContainerNodeImpl(DocumentImpl* doc) - : NodeImpl(doc), m_firstChild(0), m_lastChild(0) + : EventTargetNodeImpl(doc), m_firstChild(0), m_lastChild(0) { } @@ -364,7 +364,7 @@ bool ContainerNodeImpl::removeChild(NodeImpl* oldChild, ExceptionCode& ec) // dispatch pre-removal mutation events if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) { - child->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent, true, false, + EventTargetNodeCast(child.get())->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent, true, false, this, DOMString(), DOMString(), DOMString(), 0), ec, true); if (ec) return false; @@ -571,33 +571,33 @@ void ContainerNodeImpl::attach() { for (NodeImpl* child = m_firstChild; child; child = child->nextSibling()) child->attach(); - NodeImpl::attach(); + EventTargetNodeImpl::attach(); } void ContainerNodeImpl::detach() { for (NodeImpl* child = m_firstChild; child; child = child->nextSibling()) child->detach(); - NodeImpl::detach(); + EventTargetNodeImpl::detach(); } void ContainerNodeImpl::insertedIntoDocument() { - NodeImpl::insertedIntoDocument(); + EventTargetNodeImpl::insertedIntoDocument(); for (NodeImpl *child = m_firstChild; child; child = child->nextSibling()) child->insertedIntoDocument(); } void ContainerNodeImpl::removedFromDocument() { - NodeImpl::removedFromDocument(); + EventTargetNodeImpl::removedFromDocument(); for (NodeImpl *child = m_firstChild; child; child = child->nextSibling()) child->removedFromDocument(); } void ContainerNodeImpl::insertedIntoTree(bool deep) { - NodeImpl::insertedIntoTree(deep); + EventTargetNodeImpl::insertedIntoTree(deep); if (deep) { for (NodeImpl *child = m_firstChild; child; child = child->nextSibling()) child->insertedIntoTree(deep); @@ -606,7 +606,7 @@ void ContainerNodeImpl::insertedIntoTree(bool deep) void ContainerNodeImpl::removedFromTree(bool deep) { - NodeImpl::removedFromTree(deep); + EventTargetNodeImpl::removedFromTree(deep); if (deep) { for (NodeImpl *child = m_firstChild; child; child = child->nextSibling()) child->removedFromTree(deep); @@ -754,7 +754,7 @@ void ContainerNodeImpl::setFocus(bool received) { if (m_focused == received) return; - NodeImpl::setFocus(received); + EventTargetNodeImpl::setFocus(received); // note that we need to recalc the style setChanged(); @@ -764,7 +764,7 @@ void ContainerNodeImpl::setActive(bool down, bool pause) { if (down == active()) return; - NodeImpl::setActive(down); + EventTargetNodeImpl::setActive(down); // note that we need to recalc the style // FIXME: Move to ElementImpl @@ -804,7 +804,7 @@ void ContainerNodeImpl::setHovered(bool over) { if (over == hovered()) return; - NodeImpl::setHovered(over); + EventTargetNodeImpl::setHovered(over); // note that we need to recalc the style // FIXME: Move to ElementImpl @@ -846,9 +846,11 @@ static void dispatchChildInsertionEvents(NodeImpl* child, ExceptionCode& ec) else c->insertedIntoTree(true); - if (c->parentNode() && doc->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) { + if (c->parentNode() && + doc->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER) && + c->isEventTargetNode()) { ec = 0; - child->dispatchEvent(new MutationEventImpl(DOMNodeInsertedEvent, true, false, + EventTargetNodeCast(c.get())->dispatchEvent(new MutationEventImpl(DOMNodeInsertedEvent, true, false, c->parentNode(), DOMString(), DOMString(), DOMString(), 0), ec, true); if (ec) return; @@ -857,8 +859,11 @@ static void dispatchChildInsertionEvents(NodeImpl* child, ExceptionCode& ec) // dispatch the DOMNodeInsertedIntoDocument event to all descendants if (c->inDocument() && doc->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { + if (!c->isEventTargetNode()) + continue; + ec = 0; - c->dispatchEvent(new MutationEventImpl(DOMNodeInsertedIntoDocumentEvent, false, false, + EventTargetNodeCast(c.get())->dispatchEvent(new MutationEventImpl(DOMNodeInsertedIntoDocumentEvent, false, false, 0, DOMString(), DOMString(), DOMString(), 0), ec, true); if (ec) return; @@ -874,9 +879,11 @@ static void dispatchChildRemovalEvents(NodeImpl* child, ExceptionCode& ec) doc->notifyBeforeNodeRemoval(child); // ### use events instead // dispatch pre-removal mutation events - if (c->parentNode() && doc->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) { + if (c->parentNode() && + doc->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER) && + c->isEventTargetNode()) { ec = 0; - child->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent, true, false, + EventTargetNodeCast(c.get())->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent, true, false, c->parentNode(), DOMString(), DOMString(), DOMString(), 0), ec, true); if (ec) return; @@ -885,8 +892,10 @@ static void dispatchChildRemovalEvents(NodeImpl* child, ExceptionCode& ec) // dispatch the DOMNodeRemovedFromDocument event to all descendants if (c->inDocument() && doc->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { + if (!c->isEventTargetNode()) + continue; ec = 0; - c->dispatchEvent(new MutationEventImpl(DOMNodeRemovedFromDocumentEvent, false, false, + EventTargetNodeCast(c.get())->dispatchEvent(new MutationEventImpl(DOMNodeRemovedFromDocumentEvent, false, false, 0, DOMString(), DOMString(), DOMString(), 0), ec, true); if (ec) return; diff --git a/WebCore/dom/ContainerNodeImpl.h b/WebCore/dom/ContainerNodeImpl.h index eede574678c..68126fe04a0 100644 --- a/WebCore/dom/ContainerNodeImpl.h +++ b/WebCore/dom/ContainerNodeImpl.h @@ -26,11 +26,11 @@ #ifndef DOM_ContainerNodeImpl_h #define DOM_ContainerNodeImpl_h -#include "NodeImpl.h" +#include "EventTargetNodeImpl.h" namespace DOM { -class ContainerNodeImpl : public NodeImpl +class ContainerNodeImpl : public EventTargetNodeImpl { public: ContainerNodeImpl(DocumentImpl *doc); diff --git a/WebCore/dom/DocumentImpl.cpp b/WebCore/dom/DocumentImpl.cpp index 6a2236b009d..1dacb3a205d 100644 --- a/WebCore/dom/DocumentImpl.cpp +++ b/WebCore/dom/DocumentImpl.cpp @@ -966,7 +966,9 @@ void DocumentImpl::removeAllEventListenersFromAllNodes() m_windowEventListeners.clear(); removeAllDisconnectedNodeEventListeners(); for (NodeImpl *n = this; n; n = n->traverseNextNode()) { - n->removeAllEventListeners(); + if (!n->isEventTargetNode()) + continue; + EventTargetNodeCast(n)->removeAllEventListeners(); } } @@ -984,7 +986,7 @@ void DocumentImpl::removeAllDisconnectedNodeEventListeners() { NodeSet::iterator end = m_disconnectedNodesWithEventListeners.end(); for (NodeSet::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i) - (*i)->removeAllEventListeners(); + EventTargetNodeCast((*i))->removeAllEventListeners(); m_disconnectedNodesWithEventListeners.clear(); } @@ -1007,19 +1009,11 @@ KWQAccObjectCache* DocumentImpl::getAccObjectCache() delete m_accCache; m_accCache = 0; } - - // look for top-level document - ElementImpl *element = ownerElement(); - if (element) { - DocumentImpl *doc; - while (element) { - doc = element->getDocument(); - element = doc->ownerElement(); - } - - // ask the top-level document for its cache + + // ask the top-level document for its cache + DocumentImpl *doc = topDocument(); + if (doc != this) return doc->getAccObjectCache(); - } // this is the top-level document, so install a new cache m_accCache = new KWQAccObjectCache; @@ -2044,12 +2038,12 @@ bool DocumentImpl::setFocusNode(PassRefPtr newFocusNode) // Dispatch a change event for text fields or textareas that have been edited RenderObject *r = static_cast(oldFocusNode.get()->renderer()); if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) { - oldFocusNode->dispatchHTMLEvent(changeEvent, true, false); + EventTargetNodeCast(oldFocusNode.get())->dispatchHTMLEvent(changeEvent, true, false); if ((r = static_cast(oldFocusNode.get()->renderer()))) r->setEdited(false); } - oldFocusNode->dispatchHTMLEvent(blurEvent, false, false); + EventTargetNodeCast(oldFocusNode.get())->dispatchHTMLEvent(blurEvent, false, false); if (m_focusNode) { // handler shifted focus @@ -2057,7 +2051,7 @@ bool DocumentImpl::setFocusNode(PassRefPtr newFocusNode) newFocusNode = 0; } clearSelectionIfNeeded(newFocusNode.get()); - oldFocusNode->dispatchUIEvent(DOMFocusOutEvent); + EventTargetNodeCast(oldFocusNode.get())->dispatchUIEvent(DOMFocusOutEvent); if (m_focusNode) { // handler shifted focus focusChangeBlocked = true; @@ -2079,13 +2073,13 @@ bool DocumentImpl::setFocusNode(PassRefPtr newFocusNode) } // Set focus on the new node m_focusNode = newFocusNode.get(); - m_focusNode->dispatchHTMLEvent(focusEvent, false, false); + EventTargetNodeCast(m_focusNode.get())->dispatchHTMLEvent(focusEvent, false, false); if (m_focusNode != newFocusNode) { // handler shifted focus focusChangeBlocked = true; goto SetFocusNodeDone; } - m_focusNode->dispatchUIEvent(DOMFocusInEvent); + EventTargetNodeCast(m_focusNode.get())->dispatchUIEvent(DOMFocusInEvent); if (m_focusNode != newFocusNode) { // handler shifted focus focusChangeBlocked = true; @@ -2933,10 +2927,8 @@ DocumentImpl *DocumentImpl::topDocument() const { DocumentImpl *doc = const_cast(this); ElementImpl *element; - while ((element = doc->ownerElement()) != 0) { + while ((element = doc->ownerElement()) != 0) doc = element->getDocument(); - element = doc ? doc->ownerElement() : 0; - } return doc; } diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl index c5106e25142..8c71e6be0fe 100644 --- a/WebCore/dom/Element.idl +++ b/WebCore/dom/Element.idl @@ -19,7 +19,7 @@ module core { - interface [LegacyParent=KJS::DOMElement] Element : Node { + interface [LegacyParent=KJS::DOMElement] Element : EventTargetNode { // DOM Level 1 diff --git a/WebCore/dom/EventTargetNodeImpl.cpp b/WebCore/dom/EventTargetNodeImpl.cpp new file mode 100644 index 00000000000..f0de17ee43d --- /dev/null +++ b/WebCore/dom/EventTargetNodeImpl.cpp @@ -0,0 +1,511 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include "EventTargetNodeImpl.h" + +#include "DocumentImpl.h" +#include "EventListener.h" +#include "EventNames.h" +#include "Frame.h" +#include "FrameView.h" +#include "MouseEvent.h" +#include "WheelEvent.h" +#include "dom2_eventsimpl.h" +#include "kjs_proxy.h" +#include "htmlnames.h" +#include +#include + +namespace WebCore { + +using namespace EventNames; +using namespace HTMLNames; + +EventTargetNodeImpl::EventTargetNodeImpl(DocumentImpl *doc) + : NodeImpl(doc) + , m_regdListeners(0) +{ +} + +EventTargetNodeImpl::~EventTargetNodeImpl() +{ + if (m_regdListeners && !m_regdListeners->isEmpty() && !inDocument()) + getDocument()->unregisterDisconnectedNodeWithEventListeners(this); + delete m_regdListeners; +} + +void EventTargetNodeImpl::insertedIntoDocument() +{ + if (m_regdListeners && !m_regdListeners->isEmpty()) + getDocument()->unregisterDisconnectedNodeWithEventListeners(this); + + NodeImpl::insertedIntoDocument(); +} + +void EventTargetNodeImpl::removedFromDocument() +{ + if (m_regdListeners && !m_regdListeners->isEmpty()) + getDocument()->registerDisconnectedNodeWithEventListeners(this); + + NodeImpl::removedFromDocument(); +} + +void EventTargetNodeImpl::addEventListener(const AtomicString &eventType, PassRefPtr listener, const bool useCapture) +{ + if (!getDocument()->attached()) + return; + + DocumentImpl::ListenerType type = static_cast(0); + if (eventType == DOMSubtreeModifiedEvent) + type = DocumentImpl::DOMSUBTREEMODIFIED_LISTENER; + else if (eventType == DOMNodeInsertedEvent) + type = DocumentImpl::DOMNODEINSERTED_LISTENER; + else if (eventType == DOMNodeRemovedEvent) + type = DocumentImpl::DOMNODEREMOVED_LISTENER; + else if (eventType == DOMNodeRemovedFromDocumentEvent) + type = DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER; + else if (eventType == DOMNodeInsertedIntoDocumentEvent) + type = DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER; + else if (eventType == DOMAttrModifiedEvent) + type = DocumentImpl::DOMATTRMODIFIED_LISTENER; + else if (eventType == DOMCharacterDataModifiedEvent) + type = DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER; + if (type) + getDocument()->addListenerType(type); + + if (!m_regdListeners) { + m_regdListeners = new QPtrList; + m_regdListeners->setAutoDelete(true); + } + + // Remove existing identical listener set with identical arguments. + // The DOM2 spec says that "duplicate instances are discarded" in this case. + removeEventListener(eventType, listener.get(), useCapture); + + // adding the first one + if (m_regdListeners->isEmpty() && !inDocument()) + getDocument()->registerDisconnectedNodeWithEventListeners(this); + + m_regdListeners->append(new RegisteredEventListener(eventType, listener.get(), useCapture)); +} + +void EventTargetNodeImpl::removeEventListener(const AtomicString &eventType, EventListener *listener, bool useCapture) +{ + if (!m_regdListeners) // nothing to remove + return; + + RegisteredEventListener rl(eventType, listener, useCapture); + + QPtrListIterator it(*m_regdListeners); + for (; it.current(); ++it) + if (*(it.current()) == rl) { + m_regdListeners->removeRef(it.current()); + // removed last + if (m_regdListeners->isEmpty() && !inDocument()) + getDocument()->unregisterDisconnectedNodeWithEventListeners(this); + return; + } +} + +void EventTargetNodeImpl::removeAllEventListeners() +{ + delete m_regdListeners; + m_regdListeners = 0; +} + +void EventTargetNodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture) +{ + if (!m_regdListeners) + return; + + if (disabled() && evt->isMouseEvent()) + return; + + QPtrList listenersCopy = *m_regdListeners; + QPtrListIterator it(listenersCopy); + for (; it.current(); ++it) + if (it.current()->eventType() == evt->type() && it.current()->useCapture() == useCapture) + it.current()->listener()->handleEvent(evt, false); +} + +bool EventTargetNodeImpl::dispatchGenericEvent(PassRefPtr e, ExceptionCode&, bool tempEvent) +{ + RefPtr evt(e); + assert(!eventDispatchForbidden()); + assert(evt->target()); + + // ### check that type specified + + // work out what nodes to send event to + QPtrList nodeChain; + NodeImpl *n; + for (n = this; n; n = n->parentNode()) { + n->ref(); + nodeChain.prepend(n); + } + + QPtrListIterator it(nodeChain); + + // Before we begin dispatching events, give the target node a chance to do some work prior + // to the DOM event handlers getting a crack. + void* data = preDispatchEventHandler(evt.get()); + + // trigger any capturing event handlers on our way down + evt->setEventPhase(EventImpl::CAPTURING_PHASE); + + it.toFirst(); + // Handle window events for capture phase + if (it.current()->isDocumentNode() && !evt->propagationStopped()) { + static_cast(it.current())->handleWindowEvent(evt.get(), true); + } + + for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) { + evt->setCurrentTarget(it.current()); + EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), true); + } + + // dispatch to the actual target node + it.toLast(); + if (!evt->propagationStopped()) { + evt->setEventPhase(EventImpl::AT_TARGET); + evt->setCurrentTarget(it.current()); + + if (!evt->propagationStopped()) + EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), false); + } + --it; + + // ok, now bubble up again (only non-capturing event handlers will be called) + // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers) + // no. the DOM specs says: + // The chain of EventTargets from the event target to the top of the tree + // is determined before the initial dispatch of the event. + // If modifications occur to the tree during event processing, + // event flow will proceed based on the initial state of the tree. + // + // since the initial dispatch is before the capturing phase, + // there's no need to recalculate the node chain. + // (tobias) + + if (evt->bubbles()) { + evt->setEventPhase(EventImpl::BUBBLING_PHASE); + for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) { + evt->setCurrentTarget(it.current()); + EventTargetNodeCast(it.current())->handleLocalEvents(evt.get(), false); + } + // Handle window events for bubbling phase + it.toFirst(); + if (it.current()->isDocumentNode() && !evt->propagationStopped() && !evt->getCancelBubble()) { + evt->setCurrentTarget(it.current()); + static_cast(it.current())->handleWindowEvent(evt.get(), false); + } + } + + evt->setCurrentTarget(0); + evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say + // anything about the default event handler phase. + + + // Now call the post dispatch. + postDispatchEventHandler(evt.get(), data); + + // now we call all default event handlers (this is not part of DOM - it is internal to khtml) + + it.toLast(); + if (evt->bubbles()) + for (; it.current() && !evt->defaultPrevented() && !evt->defaultHandled(); --it) + EventTargetNodeCast(it.current())->defaultEventHandler(evt.get()); + else if (!evt->defaultPrevented() && !evt->defaultHandled()) + EventTargetNodeCast(it.current())->defaultEventHandler(evt.get()); + + // deref all nodes in chain + it.toFirst(); + for (; it.current(); ++it) + it.current()->deref(); // this may delete us + + DocumentImpl::updateDocumentsRendering(); + + // If tempEvent is true, this means that the DOM implementation + // will not be storing a reference to the event, i.e. there is no + // way to retrieve it from javascript if a script does not already + // have a reference to it in a variable. So there is no need for + // the interpreter to keep the event in it's cache + Frame *frame = getDocument()->frame(); + if (tempEvent && frame && frame->jScript()) + frame->jScript()->finishedWithEvent(evt.get()); + + return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent? +} + +bool EventTargetNodeImpl::dispatchEvent(PassRefPtr e, ExceptionCode& ec, bool tempEvent) +{ + RefPtr evt(e); + assert(!eventDispatchForbidden()); + if (!evt || evt->type().isEmpty()) { + ec = UNSPECIFIED_EVENT_TYPE_ERR; + return false; + } + evt->setTarget(this); + + RefPtr view = getDocument()->view(); + + return dispatchGenericEvent(evt.release(), ec, tempEvent); +} + +bool EventTargetNodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged) +{ + assert(!eventDispatchForbidden()); + + // FIXME: Pull this whole if clause out of this function. + if (sendChildrenChanged) { + notifyNodeListsChildrenChanged(); + childrenChanged(); + } else + notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing. + + if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER)) + return false; + ExceptionCode ec = 0; + return dispatchEvent(new MutationEventImpl(DOMSubtreeModifiedEvent, + true,false,0,DOMString(),DOMString(),DOMString(),0),ec,true); +} + +void EventTargetNodeImpl::dispatchWindowEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg) +{ + assert(!eventDispatchForbidden()); + ExceptionCode ec = 0; + RefPtr evt = new EventImpl(eventType, canBubbleArg, cancelableArg); + RefPtr doc = getDocument(); + evt->setTarget(doc.get()); + doc->handleWindowEvent(evt.get(), false); + + if (eventType == loadEvent) { + // For onload events, send a separate load event to the enclosing frame only. + // This is a DOM extension and is independent of bubbling/capturing rules of + // the DOM. + ElementImpl* ownerElement = doc->ownerElement(); + if (ownerElement) { + RefPtr ownerEvent = new EventImpl(eventType, false, cancelableArg); + ownerEvent->setTarget(ownerElement); + ownerElement->dispatchGenericEvent(ownerEvent.release(), ec, true); + } + } +} + +bool EventTargetNodeImpl::dispatchUIEvent(const AtomicString &eventType, int detail) +{ + assert(!eventDispatchForbidden()); + assert(eventType == DOMFocusInEvent || eventType == DOMFocusOutEvent || eventType == DOMActivateEvent); + + bool cancelable = eventType == DOMActivateEvent; + + ExceptionCode ec = 0; + UIEventImpl* evt = new UIEventImpl(eventType, true, cancelable, getDocument()->defaultView(), detail); + return dispatchEvent(evt, ec, true); +} + +bool EventTargetNodeImpl::dispatchKeyEvent(const KeyEvent& key) +{ + assert(!eventDispatchForbidden()); + ExceptionCode ec = 0; + RefPtr keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView()); + bool r = dispatchEvent(keyboardEventImpl,ec,true); + + // we want to return false if default is prevented (already taken care of) + // or if the element is default-handled by the DOM. Otherwise we let it just + // let it get handled by AppKit + if (keyboardEventImpl->defaultHandled()) + r = false; + + return r; +} + +bool EventTargetNodeImpl::dispatchMouseEvent(const MouseEvent& _mouse, const AtomicString& eventType, + int detail, NodeImpl* relatedTarget) +{ + assert(!eventDispatchForbidden()); + + int clientX = 0; + int clientY = 0; + if (FrameView *view = getDocument()->view()) + view->viewportToContents(_mouse.x(), _mouse.y(), clientX, clientY); + + return dispatchMouseEvent(eventType, _mouse.button(), detail, + clientX, clientY, _mouse.globalX(), _mouse.globalY(), + _mouse.ctrlKey(), _mouse.altKey(), _mouse.shiftKey(), _mouse.metaKey(), + false, relatedTarget); +} + +bool EventTargetNodeImpl::dispatchSimulatedMouseEvent(const AtomicString &eventType) +{ + assert(!eventDispatchForbidden()); + // Like Gecko, we just pass 0 for everything when we make a fake mouse event. + // Internet Explorer instead gives the current mouse position and state. + return dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, false, false, false, false, true); +} + +bool EventTargetNodeImpl::dispatchMouseEvent(const AtomicString& eventType, int button, int detail, + int clientX, int clientY, int screenX, int screenY, + bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, + bool isSimulated, NodeImpl* relatedTarget) +{ + assert(!eventDispatchForbidden()); + if (disabled()) // Don't even send DOM events for disabled controls.. + return true; + + if (eventType.isEmpty()) + return false; // Shouldn't happen. + + // Dispatching the first event can easily result in this node being destroyed. + // Since we dispatch up to three events here, we need to make sure we're referenced + // so the pointer will be good for the two subsequent ones. + RefPtr protect(this); + + bool cancelable = eventType != mousemoveEvent; + + ExceptionCode ec = 0; + + bool swallowEvent = false; + + RefPtr me = new MouseEventImpl(eventType, true, cancelable, getDocument()->defaultView(), + detail, screenX, screenY, clientX, clientY, + ctrlKey, altKey, shiftKey, metaKey, button, + relatedTarget, 0, isSimulated); + + dispatchEvent(me, ec, true); + bool defaultHandled = me->defaultHandled(); + bool defaultPrevented = me->defaultPrevented(); + if (defaultHandled || defaultPrevented) + swallowEvent = true; + + // Special case: If it's a double click event, we also send the KHTML_DBLCLICK event. This is not part + // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated + // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same. + if (eventType == clickEvent && detail == 2) { + me = new MouseEventImpl(dblclickEvent, true, cancelable, getDocument()->defaultView(), + detail, screenX, screenY, clientX, clientY, + ctrlKey, altKey, shiftKey, metaKey, button, + relatedTarget, 0, isSimulated); + if (defaultHandled) + me->setDefaultHandled(); + dispatchEvent(me, ec, true); + if (me->defaultHandled() || me->defaultPrevented()) + swallowEvent = true; + } + + // Also send a DOMActivate event, which causes things like form submissions to occur. + if (eventType == clickEvent && !defaultPrevented) + dispatchUIEvent(DOMActivateEvent, detail); + + return swallowEvent; +} + +void EventTargetNodeImpl::dispatchWheelEvent(WheelEvent& e) +{ + assert(!eventDispatchForbidden()); + if (e.delta() == 0) + return; + + FrameView *view = getDocument()->view(); + if (!view) + return; + + int x; + int y; + view->viewportToContents(e.x(), e.y(), x, y); + + RefPtr we = new WheelEventImpl(e.isHorizontal(), e.delta(), + getDocument()->defaultView(), e.globalX(), e.globalY(), x, y, + e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey()); + + ExceptionCode ec = 0; + if (!dispatchEvent(we, ec, true)) + e.accept(); +} + +bool EventTargetNodeImpl::dispatchHTMLEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg) +{ + assert(!eventDispatchForbidden()); + ExceptionCode ec = 0; + return dispatchEvent(new EventImpl(eventType, canBubbleArg, cancelableArg), ec, true); +} + +void EventTargetNodeImpl::removeHTMLEventListener(const AtomicString &eventType) +{ + if (!m_regdListeners) // nothing to remove + return; + + QPtrListIterator it(*m_regdListeners); + for (; it.current(); ++it) + if (it.current()->eventType() == eventType && it.current()->listener()->isHTMLEventListener()) { + m_regdListeners->removeRef(it.current()); + // removed last + if (m_regdListeners->isEmpty() && !inDocument()) + getDocument()->unregisterDisconnectedNodeWithEventListeners(this); + return; + } +} + +void EventTargetNodeImpl::setHTMLEventListener(const AtomicString &eventType, PassRefPtr listener) +{ + // In case we are the only one holding a reference to it, we don't want removeHTMLEventListener to destroy it. + removeHTMLEventListener(eventType); + if (listener) + addEventListener(eventType, listener.get(), false); +} + +EventListener *EventTargetNodeImpl::getHTMLEventListener(const AtomicString &eventType) +{ + if (!m_regdListeners) + return 0; + + QPtrListIterator it(*m_regdListeners); + for (; it.current(); ++it) + if (it.current()->eventType() == eventType && it.current()->listener()->isHTMLEventListener()) + return it.current()->listener(); + return 0; +} + +bool EventTargetNodeImpl::disabled() const +{ + return false; +} + +void EventTargetNodeImpl::defaultEventHandler(EventImpl *evt) +{ +} + +#ifndef NDEBUG +void EventTargetNodeImpl::dump(QTextStream *stream, QString ind) const +{ + if (m_regdListeners) + *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail + + NodeImpl::dump(stream,ind); +} +#endif + +} // namespace WebCore diff --git a/WebCore/dom/EventTargetNodeImpl.h b/WebCore/dom/EventTargetNodeImpl.h new file mode 100644 index 00000000000..7b37ee596d3 --- /dev/null +++ b/WebCore/dom/EventTargetNodeImpl.h @@ -0,0 +1,154 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef DOM_EventTargetNodeImpl_h +#define DOM_EventTargetNodeImpl_h + +#include "DocPtr.h" +#include "NodeImpl.h" +#include "Shared.h" +#include "PlatformString.h" +#include +#include +#include + +class QStringList; +class QTextStream; +class RenderArena; + +template class QPtrList; + +namespace WebCore { + +class AtomicString; +class ContainerNodeImpl; +class DocumentImpl; +class ElementImpl; +class EventImpl; +class EventListener; +class IntRect; +class KeyEvent; +class MouseEvent; +class NamedAttrMapImpl; +class NodeListImpl; +class QualifiedName; +class RegisteredEventListener; +class RenderObject; +class RenderStyle; +class WheelEvent; + +typedef int ExceptionCode; + +class EventTargetNodeImpl : public NodeImpl +{ + friend class DocumentImpl; +public: + EventTargetNodeImpl(DocumentImpl*); + virtual ~EventTargetNodeImpl(); + + virtual bool isEventTargetNode() const { return true; } + + void addEventListener(const AtomicString& eventType, PassRefPtr, bool useCapture); + void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); + void removeAllEventListeners(); + + void setHTMLEventListener(const AtomicString& eventType, PassRefPtr); + void removeHTMLEventListener(const AtomicString& eventType); + bool dispatchHTMLEvent(const AtomicString& eventType, bool canBubble, bool cancelable); + EventListener *getHTMLEventListener(const AtomicString& eventType); + + bool dispatchGenericEvent(PassRefPtr, ExceptionCode&, bool tempEvent = false); + bool dispatchEvent(PassRefPtr, ExceptionCode&, bool tempEvent = false); + bool dispatchSubtreeModifiedEvent(bool childrenChanged = true); + void dispatchWindowEvent(const AtomicString& eventType, bool canBubble, bool cancelable); + bool dispatchUIEvent(const AtomicString& eventType, int detail = 0); + bool dispatchKeyEvent(const KeyEvent&); + void dispatchWheelEvent(WheelEvent&); + bool dispatchMouseEvent(const MouseEvent&, const AtomicString& eventType, + int clickCount = 0, NodeImpl* relatedTarget = 0); + bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount, + int clientX, int clientY, int screenX, int screenY, + bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, + bool isSimulated = false, NodeImpl* relatedTarget = 0); + bool dispatchSimulatedMouseEvent(const AtomicString& eventType); + + void handleLocalEvents(EventImpl*, bool useCapture); + + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event + // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. + virtual void* preDispatchEventHandler(EventImpl*) { return 0; } + virtual void postDispatchEventHandler(EventImpl*, void* data) { } + + /** + * Perform the default action for an event e.g. submitting a form + */ + virtual void defaultEventHandler(EventImpl*); + + /** + * Used for disabled form elements; if true, prevents mouse events from being dispatched + * to event listeners, and prevents DOMActivate events from being sent at all. + */ + virtual bool disabled() const; + +#ifndef NDEBUG + virtual void dump(QTextStream*, QString indent = "") const; +#endif + +protected: + QPtrList* m_regdListeners; +}; + +inline EventTargetNodeImpl* EventTargetNodeCast(NodeImpl* n) +{ + ASSERT(n->isEventTargetNode()); + return static_cast(n); +} + +inline const EventTargetNodeImpl* EventTargetNodeCast(const NodeImpl* n) +{ + ASSERT(n->isEventTargetNode()); + return static_cast(n); +} + +#ifndef NDEBUG + +extern int gEventDispatchForbidden; +inline void forbidEventDispatch() { ++gEventDispatchForbidden; } +inline void allowEventDispatch() { if (gEventDispatchForbidden > 0) --gEventDispatchForbidden; } +inline bool eventDispatchForbidden() { return gEventDispatchForbidden > 0; } + +#else + +inline void forbidEventDispatch() { } +inline void allowEventDispatch() { } + +#endif NDEBUG + +} //namespace WebCore + +#endif diff --git a/WebCore/dom/NodeImpl.cpp b/WebCore/dom/NodeImpl.cpp index 63ceb0c3998..db00d50c978 100644 --- a/WebCore/dom/NodeImpl.cpp +++ b/WebCore/dom/NodeImpl.cpp @@ -29,27 +29,19 @@ #include "ChildNodeListImpl.h" #include "DOMImplementationImpl.h" #include "DocumentImpl.h" -#include "EventListener.h" -#include "EventNames.h" #include "ExceptionCode.h" #include "Frame.h" #include "FrameView.h" -#include "MouseEvent.h" #include "TextImpl.h" -#include "WheelEvent.h" -#include "dom2_eventsimpl.h" #include "htmlediting.h" #include "htmlnames.h" #include "kjs_binding.h" -#include "kjs_proxy.h" #include "render_object.h" #include -#include #include namespace WebCore { -using namespace EventNames; using namespace HTMLNames; /** @@ -118,7 +110,6 @@ NodeImpl::NodeImpl(DocumentImpl *doc) m_previous(0), m_next(0), m_renderer(0), - m_regdListeners(0), m_nodeLists(0), m_tabIndex(0), m_hasId(false), @@ -158,9 +149,6 @@ NodeImpl::~NodeImpl() #endif if (renderer()) detach(); - if (m_regdListeners && !m_regdListeners->isEmpty() && getDocument() && !inDocument()) - getDocument()->unregisterDisconnectedNodeWithEventListeners(this); - delete m_regdListeners; delete m_nodeLists; if (m_previous) m_previous->setNextSibling(0); @@ -385,353 +373,6 @@ unsigned NodeImpl::nodeIndex() const return count; } -void NodeImpl::addEventListener(const AtomicString &eventType, PassRefPtr listener, const bool useCapture) -{ - if (getDocument() && !getDocument()->attached()) - return; - - DocumentImpl::ListenerType type = static_cast(0); - if (eventType == DOMSubtreeModifiedEvent) - type = DocumentImpl::DOMSUBTREEMODIFIED_LISTENER; - else if (eventType == DOMNodeInsertedEvent) - type = DocumentImpl::DOMNODEINSERTED_LISTENER; - else if (eventType == DOMNodeRemovedEvent) - type = DocumentImpl::DOMNODEREMOVED_LISTENER; - else if (eventType == DOMNodeRemovedFromDocumentEvent) - type = DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER; - else if (eventType == DOMNodeInsertedIntoDocumentEvent) - type = DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER; - else if (eventType == DOMAttrModifiedEvent) - type = DocumentImpl::DOMATTRMODIFIED_LISTENER; - else if (eventType == DOMCharacterDataModifiedEvent) - type = DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER; - if (type) - getDocument()->addListenerType(type); - - if (!m_regdListeners) { - m_regdListeners = new QPtrList; - m_regdListeners->setAutoDelete(true); - } - - // Remove existing identical listener set with identical arguments. - // The DOM2 spec says that "duplicate instances are discarded" in this case. - removeEventListener(eventType, listener.get(), useCapture); - - // adding the first one - if (m_regdListeners->isEmpty() && getDocument() && !inDocument()) - getDocument()->registerDisconnectedNodeWithEventListeners(this); - - m_regdListeners->append(new RegisteredEventListener(eventType, listener.get(), useCapture)); -} - -void NodeImpl::removeEventListener(const AtomicString &eventType, EventListener *listener, bool useCapture) -{ - if (!m_regdListeners) // nothing to remove - return; - - RegisteredEventListener rl(eventType, listener, useCapture); - - QPtrListIterator it(*m_regdListeners); - for (; it.current(); ++it) - if (*(it.current()) == rl) { - m_regdListeners->removeRef(it.current()); - // removed last - if (m_regdListeners->isEmpty() && getDocument() && !inDocument()) - getDocument()->unregisterDisconnectedNodeWithEventListeners(this); - return; - } -} - -void NodeImpl::removeAllEventListeners() -{ - delete m_regdListeners; - m_regdListeners = 0; -} - -void NodeImpl::removeHTMLEventListener(const AtomicString &eventType) -{ - if (!m_regdListeners) // nothing to remove - return; - - QPtrListIterator it(*m_regdListeners); - for (; it.current(); ++it) - if (it.current()->eventType() == eventType && it.current()->listener()->isHTMLEventListener()) { - m_regdListeners->removeRef(it.current()); - // removed last - if (m_regdListeners->isEmpty() && getDocument() && !inDocument()) - getDocument()->unregisterDisconnectedNodeWithEventListeners(this); - return; - } -} - -void NodeImpl::setHTMLEventListener(const AtomicString &eventType, PassRefPtr listener) -{ - // In case we are the only one holding a reference to it, we don't want removeHTMLEventListener to destroy it. - removeHTMLEventListener(eventType); - if (listener) - addEventListener(eventType, listener.get(), false); -} - -EventListener *NodeImpl::getHTMLEventListener(const AtomicString &eventType) -{ - if (!m_regdListeners) - return 0; - - QPtrListIterator it(*m_regdListeners); - for (; it.current(); ++it) - if (it.current()->eventType() == eventType && it.current()->listener()->isHTMLEventListener()) - return it.current()->listener(); - return 0; -} - - -bool NodeImpl::dispatchEvent(PassRefPtr e, ExceptionCode& ec, bool tempEvent) -{ - RefPtr evt(e); - assert(!eventDispatchForbidden()); - if (!evt || evt->type().isEmpty()) { - ec = UNSPECIFIED_EVENT_TYPE_ERR; - return false; - } - evt->setTarget(this); - - RefPtr view = getDocument()->view(); - - return dispatchGenericEvent(evt.release(), ec, tempEvent); -} - -bool NodeImpl::dispatchGenericEvent(PassRefPtr e, ExceptionCode&, bool tempEvent) -{ - RefPtr evt(e); - assert(!eventDispatchForbidden()); - assert(evt->target()); - - // ### check that type specified - - // work out what nodes to send event to - QPtrList nodeChain; - NodeImpl *n; - for (n = this; n; n = n->parentNode()) { - n->ref(); - nodeChain.prepend(n); - } - - QPtrListIterator it(nodeChain); - - // Before we begin dispatching events, give the target node a chance to do some work prior - // to the DOM event handlers getting a crack. - void* data = preDispatchEventHandler(evt.get()); - - // trigger any capturing event handlers on our way down - evt->setEventPhase(EventImpl::CAPTURING_PHASE); - - it.toFirst(); - // Handle window events for capture phase - if (it.current()->isDocumentNode() && !evt->propagationStopped()) { - static_cast(it.current())->handleWindowEvent(evt.get(), true); - } - - for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) { - evt->setCurrentTarget(it.current()); - it.current()->handleLocalEvents(evt.get(), true); - } - - // dispatch to the actual target node - it.toLast(); - if (!evt->propagationStopped()) { - evt->setEventPhase(EventImpl::AT_TARGET); - evt->setCurrentTarget(it.current()); - - if (!evt->propagationStopped()) - it.current()->handleLocalEvents(evt.get(), false); - } - --it; - - // ok, now bubble up again (only non-capturing event handlers will be called) - // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers) - // no. the DOM specs says: - // The chain of EventTargets from the event target to the top of the tree - // is determined before the initial dispatch of the event. - // If modifications occur to the tree during event processing, - // event flow will proceed based on the initial state of the tree. - // - // since the initial dispatch is before the capturing phase, - // there's no need to recalculate the node chain. - // (tobias) - - if (evt->bubbles()) { - evt->setEventPhase(EventImpl::BUBBLING_PHASE); - for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) { - evt->setCurrentTarget(it.current()); - it.current()->handleLocalEvents(evt.get(), false); - } - // Handle window events for bubbling phase - it.toFirst(); - if (it.current()->isDocumentNode() && !evt->propagationStopped() && !evt->getCancelBubble()) { - evt->setCurrentTarget(it.current()); - static_cast(it.current())->handleWindowEvent(evt.get(), false); - } - } - - evt->setCurrentTarget(0); - evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say - // anything about the default event handler phase. - - - // Now call the post dispatch. - postDispatchEventHandler(evt.get(), data); - - // now we call all default event handlers (this is not part of DOM - it is internal to khtml) - - it.toLast(); - if (evt->bubbles()) - for (; it.current() && !evt->defaultPrevented() && !evt->defaultHandled(); --it) - it.current()->defaultEventHandler(evt.get()); - else if (!evt->defaultPrevented() && !evt->defaultHandled()) - it.current()->defaultEventHandler(evt.get()); - - // deref all nodes in chain - it.toFirst(); - for (; it.current(); ++it) - it.current()->deref(); // this may delete us - - DocumentImpl::updateDocumentsRendering(); - - // If tempEvent is true, this means that the DOM implementation - // will not be storing a reference to the event, i.e. there is no - // way to retrieve it from javascript if a script does not already - // have a reference to it in a variable. So there is no need for - // the interpreter to keep the event in it's cache - Frame *frame = getDocument()->frame(); - if (tempEvent && frame && frame->jScript()) - frame->jScript()->finishedWithEvent(evt.get()); - - return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent? -} - -bool NodeImpl::dispatchHTMLEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg) -{ - assert(!eventDispatchForbidden()); - ExceptionCode ec = 0; - return dispatchEvent(new EventImpl(eventType, canBubbleArg, cancelableArg), ec, true); -} - -void NodeImpl::dispatchWindowEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg) -{ - assert(!eventDispatchForbidden()); - ExceptionCode ec = 0; - RefPtr evt = new EventImpl(eventType, canBubbleArg, cancelableArg); - RefPtr doc = getDocument(); - evt->setTarget(doc.get()); - doc->handleWindowEvent(evt.get(), false); - - if (eventType == loadEvent) { - // For onload events, send a separate load event to the enclosing frame only. - // This is a DOM extension and is independent of bubbling/capturing rules of - // the DOM. - ElementImpl* ownerElement = doc->ownerElement(); - if (ownerElement) { - RefPtr ownerEvent = new EventImpl(eventType, false, cancelableArg); - ownerEvent->setTarget(ownerElement); - ownerElement->dispatchGenericEvent(ownerEvent.release(), ec, true); - } - } -} - -bool NodeImpl::dispatchMouseEvent(const MouseEvent& _mouse, const AtomicString& eventType, - int clickCount, NodeImpl* relatedTarget) -{ - assert(!eventDispatchForbidden()); - - int clientX = 0; - int clientY = 0; - if (FrameView *view = getDocument()->view()) - view->viewportToContents(_mouse.x(), _mouse.y(), clientX, clientY); - - return dispatchMouseEvent(eventType, _mouse.button(), clickCount, - clientX, clientY, _mouse.globalX(), _mouse.globalY(), - _mouse.ctrlKey(), _mouse.altKey(), _mouse.shiftKey(), _mouse.metaKey(), - false, relatedTarget); -} - -bool NodeImpl::dispatchSimulatedMouseEvent(const AtomicString &eventType) -{ - assert(!eventDispatchForbidden()); - // Like Gecko, we just pass 0 for everything when we make a fake mouse event. - // Internet Explorer instead gives the current mouse position and state. - return dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, false, false, false, false, true); -} - -bool NodeImpl::dispatchMouseEvent(const AtomicString &eventType, int button, int clickCount, - int clientX, int clientY, int screenX, int screenY, - bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated, NodeImpl* relatedTarget) -{ - assert(!eventDispatchForbidden()); - if (disabled()) // Don't even send DOM events for disabled controls.. - return true; - - if (eventType.isEmpty()) - return false; // Shouldn't happen. - - // Dispatching the first event can easily result in this node being destroyed. - // Since we dispatch up to three events here, we need to make sure we're referenced - // so the pointer will be good for the two subsequent ones. - RefPtr protect(this); - - bool cancelable = eventType != mousemoveEvent; - - ExceptionCode ec = 0; - - bool swallowEvent = false; - - RefPtr me = new MouseEventImpl(eventType, true, cancelable, getDocument()->defaultView(), - clickCount, screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, button, - relatedTarget, 0, isSimulated); - - dispatchEvent(me, ec, true); - bool defaultHandled = me->defaultHandled(); - bool defaultPrevented = me->defaultPrevented(); - if (defaultHandled || defaultPrevented) - swallowEvent = true; - - // Special case: If it's a double click event, we also send the "dblclick" event. This is not part - // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated - // as a separate event in other browsers like Firefox, WinIE, & Opera, so we do the same. - if (eventType == clickEvent && clickCount == 2) { - me = new MouseEventImpl(dblclickEvent, true, cancelable, getDocument()->defaultView(), - clickCount, screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, button, - relatedTarget, 0, isSimulated); - if (defaultHandled) - me->setDefaultHandled(); - dispatchEvent(me, ec, true); - if (me->defaultHandled() || me->defaultPrevented()) - swallowEvent = true; - } - - // Also send a DOMActivate event, which causes things like form submissions to occur. - if (eventType == clickEvent && !defaultPrevented) - dispatchUIEvent(DOMActivateEvent, clickCount); - - return swallowEvent; -} - -bool NodeImpl::dispatchUIEvent(const AtomicString &eventType, int detail) -{ - assert(!eventDispatchForbidden()); - assert(eventType == DOMFocusInEvent || eventType == DOMFocusOutEvent || eventType == DOMActivateEvent); - - if (!getDocument()) - return false; - - bool cancelable = eventType == DOMActivateEvent; - - ExceptionCode ec = 0; - UIEventImpl* evt = new UIEventImpl(eventType, true, cancelable, getDocument()->defaultView(), detail); - return dispatchEvent(evt, ec, true); -} - void NodeImpl::registerNodeList(NodeListImpl* list) { if (!m_nodeLists) @@ -778,86 +419,6 @@ void NodeImpl::notifyNodeListsChildrenChanged() n->notifyLocalNodeListsChildrenChanged(); } -bool NodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged) -{ - assert(!eventDispatchForbidden()); - - // FIXME: Pull this whole if clause out of this function. - if (sendChildrenChanged) { - notifyNodeListsChildrenChanged(); - childrenChanged(); - } else - notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing. - - if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER)) - return false; - ExceptionCode ec = 0; - return dispatchEvent(new MutationEventImpl(DOMSubtreeModifiedEvent, - true,false,0,DOMString(),DOMString(),DOMString(),0),ec,true); -} - -bool NodeImpl::dispatchKeyEvent(const KeyEvent& key) -{ - assert(!eventDispatchForbidden()); - ExceptionCode ec = 0; - RefPtr keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView()); - bool r = dispatchEvent(keyboardEventImpl,ec,true); - - // we want to return false if default is prevented (already taken care of) - // or if the element is default-handled by the DOM. Otherwise we let it just - // let it get handled by AppKit - if (keyboardEventImpl->defaultHandled()) - r = false; - - return r; -} - -void NodeImpl::dispatchWheelEvent(WheelEvent& e) -{ - assert(!eventDispatchForbidden()); - if (e.delta() == 0) - return; - - DocumentImpl* doc = getDocument(); - if (!doc) - return; - - FrameView* view = getDocument()->view(); - if (!view) - return; - - int x; - int y; - view->viewportToContents(e.x(), e.y(), x, y); - - RefPtr we = new WheelEventImpl(e.isHorizontal(), e.delta(), - getDocument()->defaultView(), e.globalX(), e.globalY(), x, y, - e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey()); - - ExceptionCode ec = 0; - if (!dispatchEvent(we, ec, true)) - e.accept(); -} - -void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture) -{ - if (!m_regdListeners) - return; - - if (disabled() && evt->isMouseEvent()) - return; - - QPtrList listenersCopy = *m_regdListeners; - QPtrListIterator it(listenersCopy); - for (; it.current(); ++it) - if (it.current()->eventType() == evt->type() && it.current()->useCapture() == useCapture) - it.current()->listener()->handleEvent(evt, false); -} - -void NodeImpl::defaultEventHandler(EventImpl *evt) -{ -} - unsigned NodeImpl::childNodeCount() const { return 0; @@ -1094,8 +655,6 @@ void NodeImpl::dump(QTextStream *stream, QString ind) const if (m_implicit) { *stream << " implicit"; } *stream << " tabIndex=" << m_tabIndex; - if (m_regdListeners) - *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail *stream << endl; NodeImpl *child = firstChild(); @@ -1129,13 +688,12 @@ void NodeImpl::detach() setRenderer(0); DocumentImpl* doc = getDocument(); - if (doc) { - if (m_hovered) - doc->hoveredNodeDetached(this); - if (m_inActiveChain) - doc->activeChainNodeDetached(this); - doc->incDOMTreeVersion(); - } + if (m_hovered) + doc->hoveredNodeDetached(this); + if (m_inActiveChain) + doc->activeChainNodeDetached(this); + doc->incDOMTreeVersion(); + m_active = false; m_hovered = false; m_inActiveChain = false; @@ -1159,21 +717,13 @@ void NodeImpl::restoreState(QStringList &/*states*/) void NodeImpl::insertedIntoDocument() { - if (m_regdListeners && !m_regdListeners->isEmpty() && getDocument()) - getDocument()->unregisterDisconnectedNodeWithEventListeners(this); - setInDocument(true); - insertedIntoTree(false); } void NodeImpl::removedFromDocument() { - if (m_regdListeners && !m_regdListeners->isEmpty() && getDocument()) - getDocument()->registerDisconnectedNodeWithEventListeners(this); - setInDocument(false); - removedFromTree(false); } @@ -1181,11 +731,6 @@ void NodeImpl::childrenChanged() { } -bool NodeImpl::disabled() const -{ - return false; -} - bool NodeImpl::isReadOnly() { // Entity & Entity Reference nodes and their descendants are read-only diff --git a/WebCore/dom/NodeImpl.h b/WebCore/dom/NodeImpl.h index 8becb94c811..7e3b4edfca8 100644 --- a/WebCore/dom/NodeImpl.h +++ b/WebCore/dom/NodeImpl.h @@ -29,6 +29,7 @@ #include "DocPtr.h" #include "Shared.h" #include "PlatformString.h" +#include #include #include @@ -97,7 +98,6 @@ public: virtual NodeImpl* lastChild() const; virtual bool hasAttributes() const; virtual NamedAttrMapImpl* attributes() const; - virtual DocumentImpl* ownerDocument() const; // These should all actually return a node, but this is only important for language bindings, // which will already know and hold a ref on the right node to return. Returning bool allows @@ -141,6 +141,7 @@ public: virtual bool isTextNode() const { return false; } virtual bool isCommentNode() const { return false; } virtual bool isDocumentNode() const { return false; } + virtual bool isEventTargetNode() const { return false; } bool isBlockFlow() const; bool isBlockFlowOrBlockTable() const; @@ -210,9 +211,6 @@ public: bool changed() const { return m_changed; } bool hasChangedChild() const { return m_hasChangedChild; } bool isLink() const { return m_isLink; } - // FIXME: Should inDocument also make sure a document exists in case the document - // has been destroyed before the node is removed from the document? - bool inDocument() const { return document.get() && m_inDocument; } bool styleElement() const { return m_styleElement; } bool implicitNode() const { return m_implicit; } void setHasID(bool b = true) { m_hasId = b; } @@ -250,53 +248,27 @@ public: unsigned nodeIndex() const; - // Returns the document that this node is associated with. This is guaranteed to always be non-null, as opposed to - // DOM's ownerDocument() which is null for Document nodes (and sometimes DocumentType nodes). - DocumentImpl* getDocument() const { return document.get(); } + // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case + // of (1) a Document node or (2) a DocumentType node that is not used with any Document yet. + virtual DocumentImpl* ownerDocument() const; + // Returns the document associated with this node. This method never returns NULL, except in the case + // of a DocumentType node that is not used with any Document yet. A Document node returns itself. + DocumentImpl* getDocument() const + { + ASSERT(document || nodeType() == DOCUMENT_TYPE_NODE && !inDocument()); + return document.get(); + } void setDocument(DocumentImpl*); - void addEventListener(const AtomicString& eventType, PassRefPtr, bool useCapture); - void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - void removeHTMLEventListener(const AtomicString& eventType); - void setHTMLEventListener(const AtomicString& eventType, PassRefPtr); - EventListener *getHTMLEventListener(const AtomicString& eventType); - void removeAllEventListeners(); - - bool dispatchEvent(PassRefPtr, ExceptionCode&, bool tempEvent = false); - bool dispatchGenericEvent(PassRefPtr, ExceptionCode&, bool tempEvent = false); - bool dispatchHTMLEvent(const AtomicString& eventType, bool canBubble, bool cancelable); - void dispatchWindowEvent(const AtomicString& eventType, bool canBubble, bool cancelable); - bool dispatchMouseEvent(const MouseEvent&, const AtomicString& eventType, - int clickCount = 0, NodeImpl* relatedTarget = 0); - bool dispatchSimulatedMouseEvent(const AtomicString& eventType); - bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount, - int clientX, int clientY, int screenX, int screenY, - bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - bool isSimulated = false, NodeImpl* relatedTarget = 0); - bool dispatchUIEvent(const AtomicString& eventType, int detail = 0); - bool dispatchSubtreeModifiedEvent(bool childrenChanged = true); - bool dispatchKeyEvent(const KeyEvent&); - void dispatchWheelEvent(WheelEvent&); - - void handleLocalEvents(EventImpl*, bool useCapture); - - // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event - // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. - virtual void* preDispatchEventHandler(EventImpl*) { return 0; } - virtual void postDispatchEventHandler(EventImpl*, void* data) { } - - /** - * Perform the default action for an event e.g. submitting a form - */ - virtual void defaultEventHandler(EventImpl*); - - /** - * Used for disabled form elements; if true, prevents mouse events from being dispatched - * to event listeners, and prevents DOMActivate events from being sent at all. - */ - virtual bool disabled() const; - + // Returns true if this node is associated with a document and is in its associated document's + // node tree, false otherwise. + bool inDocument() const + { + ASSERT(document || !m_inDocument); + return m_inDocument; + } + virtual bool isReadOnly(); virtual bool childTypeAllowed(NodeType) { return false; } virtual unsigned childNodeCount() const; @@ -478,7 +450,6 @@ private: // members NodeImpl* m_next; RenderObject* m_renderer; protected: - QPtrList* m_regdListeners; typedef HashSet NodeListSet; NodeListSet* m_nodeLists; @@ -509,20 +480,8 @@ private: }; #ifndef NDEBUG - void showTree(const NodeImpl *node); - -extern int gEventDispatchForbidden; -inline void forbidEventDispatch() { ++gEventDispatchForbidden; } -inline void allowEventDispatch() { if (gEventDispatchForbidden > 0) --gEventDispatchForbidden; } -inline bool eventDispatchForbidden() { return gEventDispatchForbidden > 0; } - -#else - -inline void forbidEventDispatch() { } -inline void allowEventDispatch() { } - -#endif NDEBUG +#endif } //namespace diff --git a/WebCore/dom/dom2_eventsimpl.cpp b/WebCore/dom/dom2_eventsimpl.cpp index ea31a41a907..036d5a6813e 100644 --- a/WebCore/dom/dom2_eventsimpl.cpp +++ b/WebCore/dom/dom2_eventsimpl.cpp @@ -259,15 +259,11 @@ void MouseRelatedEventImpl::receivedTarget() m_layerX = m_pageX; m_layerY = m_pageY; - // Can't do anything if the target is not in a document. NodeImpl* targ = target(); ASSERT(targ); - DocumentImpl* doc = targ->getDocument(); - if (!doc) - return; // Must have an updated render tree for this math to work correctly. - doc->updateRendering(); + targ->getDocument()->updateRendering(); // FIXME: clientX/Y should not be the same as pageX/Y! // Currently the passed-in clientX and clientY are incorrectly actually diff --git a/WebCore/dom/dom2_rangeimpl.cpp b/WebCore/dom/dom2_rangeimpl.cpp index 848ebbd86b1..58a612051a9 100644 --- a/WebCore/dom/dom2_rangeimpl.cpp +++ b/WebCore/dom/dom2_rangeimpl.cpp @@ -122,7 +122,7 @@ NodeImpl *RangeImpl::commonAncestorContainer(NodeImpl *containerA, NodeImpl *con break; } - if (!parentStart && containerA->getDocument()) + if (!parentStart) return containerA->getDocument()->documentElement(); return parentStart; diff --git a/WebCore/dom/dom_elementimpl.cpp b/WebCore/dom/dom_elementimpl.cpp index a88f436a7d0..dada5281a64 100644 --- a/WebCore/dom/dom_elementimpl.cpp +++ b/WebCore/dom/dom_elementimpl.cpp @@ -384,7 +384,7 @@ void ElementImpl::scrollIntoViewIfNeeded(bool centerIfNeeded) static inline bool inHTMLDocument(const ElementImpl* e) { - return e && e->getDocument() && e->getDocument()->isHTMLDocument(); + return e && e->getDocument()->isHTMLDocument(); } const AtomicString& ElementImpl::getAttribute(const String& name) const @@ -835,24 +835,22 @@ CSSStyleDeclarationImpl *ElementImpl::style() void ElementImpl::focus() { DocumentImpl* doc = getDocument(); - if (doc) { - doc->updateLayout(); - if (isFocusable()) { - doc->setFocusNode(this); - if (rootEditableElement() == this) { - // FIXME: we should restore the previous selection if there is one, instead of always selecting all. - if (doc->frame()->selectContentsOfNode(this)) - doc->frame()->revealSelection(); - } else if (renderer() && !renderer()->isWidget()) - renderer()->enclosingLayer()->scrollRectToVisible(getRect()); - } + doc->updateLayout(); + if (isFocusable()) { + doc->setFocusNode(this); + if (rootEditableElement() == this) { + // FIXME: we should restore the previous selection if there is one, instead of always selecting all. + if (doc->frame()->selectContentsOfNode(this)) + doc->frame()->revealSelection(); + } else if (renderer() && !renderer()->isWidget()) + renderer()->enclosingLayer()->scrollRectToVisible(getRect()); } } void ElementImpl::blur() { DocumentImpl* doc = getDocument(); - if (doc && doc->focusNode() == this) + if (doc->focusNode() == this) doc->setFocusNode(0); } @@ -1379,7 +1377,7 @@ void StyledElementImpl::parseMappedAttribute(MappedAttributeImpl *attr) if (namedAttrMap) { if (attr->isNull()) namedAttrMap->setID(nullAtom); - else if (getDocument() && getDocument()->inCompatMode() && !attr->value().impl()->isLower()) + else if (getDocument()->inCompatMode() && !attr->value().impl()->isLower()) namedAttrMap->setID(AtomicString(attr->value().domString().lower())); else namedAttrMap->setID(attr->value()); diff --git a/WebCore/dom/dom_position.cpp b/WebCore/dom/dom_position.cpp index 5bbdf453c3a..84d1fc00a35 100644 --- a/WebCore/dom/dom_position.cpp +++ b/WebCore/dom/dom_position.cpp @@ -90,6 +90,14 @@ void Position::clear() m_offset = 0; } +ElementImpl* Position::documentElement() const +{ + if (NodeImpl* n = node()) + if (ElementImpl* e = n->getDocument()->documentElement()) + return e; + return 0; +} + ElementImpl *Position::element() const { NodeImpl *n; diff --git a/WebCore/dom/dom_position.h b/WebCore/dom/dom_position.h index 11c32205741..4dd72f04244 100644 --- a/WebCore/dom/dom_position.h +++ b/WebCore/dom/dom_position.h @@ -46,6 +46,7 @@ public: void clear(); NodeImpl *node() const { return m_node.get(); } + ElementImpl* documentElement() const; int offset() const { return m_offset; } bool isNull() const { return m_node == 0; } diff --git a/WebCore/editing/ReplaceSelectionCommand.cpp b/WebCore/editing/ReplaceSelectionCommand.cpp index c5c33bad9c7..0d6d22a2d30 100644 --- a/WebCore/editing/ReplaceSelectionCommand.cpp +++ b/WebCore/editing/ReplaceSelectionCommand.cpp @@ -380,13 +380,11 @@ static void computeAndStoreNodeDesiredStyle(DOM::NodeImpl *node, QValueListgetDocument() ? node->getDocument()->documentElement() : 0; - if (documentElement) { - RefPtr documentStyle = Position(documentElement, 0).computedStyle(); - bool match = (documentStyle->getPropertyValue(CSS_PROP_COLOR) == style->getPropertyValue(CSS_PROP_COLOR)); - if (match) - style->setProperty(CSS_PROP__KHTML_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR, matchNearestBlockquoteColorString()); - } + NodeImpl *documentElement = node->getDocument()->documentElement(); + RefPtr documentStyle = Position(documentElement, 0).computedStyle(); + bool match = (documentStyle->getPropertyValue(CSS_PROP_COLOR) == style->getPropertyValue(CSS_PROP_COLOR)); + if (match) + style->setProperty(CSS_PROP__KHTML_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR, matchNearestBlockquoteColorString()); } void ReplacementFragment::computeStylesUsingTestRendering(NodeImpl *holder) diff --git a/WebCore/editing/SelectionController.cpp b/WebCore/editing/SelectionController.cpp index c6461aab5bc..fabbcb9c4fb 100644 --- a/WebCore/editing/SelectionController.cpp +++ b/WebCore/editing/SelectionController.cpp @@ -793,9 +793,6 @@ void SelectionController::needsCaretRepaint() if (!isCaret()) return; - if (!m_sel.start().node()->getDocument()) - return; - FrameView *v = m_sel.start().node()->getDocument()->view(); if (!v) return; diff --git a/WebCore/editing/visible_units.cpp b/WebCore/editing/visible_units.cpp index 3286583030c..fc3088325d1 100644 --- a/WebCore/editing/visible_units.cpp +++ b/WebCore/editing/visible_units.cpp @@ -48,8 +48,6 @@ static VisiblePosition previousBoundary(const VisiblePosition &c, unsigned (*sea if (!n) return VisiblePosition(); DocumentImpl *d = n->getDocument(); - if (!d) - return VisiblePosition(); NodeImpl *de = d->documentElement(); if (!de) return VisiblePosition(); @@ -129,8 +127,6 @@ static VisiblePosition nextBoundary(const VisiblePosition &c, unsigned (*searchF if (!n) return VisiblePosition(); DocumentImpl *d = n->getDocument(); - if (!d) - return VisiblePosition(); NodeImpl *de = d->documentElement(); if (!de) return VisiblePosition(); @@ -376,7 +372,7 @@ VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int { Position p = visiblePosition.deepEquivalent(); NodeImpl *node = p.node(); - if (!node || !node->getDocument()) + if (!node) return VisiblePosition(); node->getDocument()->updateLayoutIgnorePendingStylesheets(); @@ -439,7 +435,7 @@ VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x) { Position p = visiblePosition.deepEquivalent(); NodeImpl *node = p.node(); - if (!node || !node->getDocument()) + if (!node) return VisiblePosition(); node->getDocument()->updateLayoutIgnorePendingStylesheets(); @@ -738,34 +734,14 @@ bool isEndOfBlock(const VisiblePosition &pos) VisiblePosition startOfDocument(const VisiblePosition &c) { - Position p = c.deepEquivalent(); - NodeImpl *node = p.node(); - if (!node) - return VisiblePosition(); - - DocumentImpl *doc = node->getDocument(); - if (!doc) - return VisiblePosition(); - - return VisiblePosition(doc->documentElement(), 0, DOWNSTREAM); + ElementImpl* documentElement = c.deepEquivalent().documentElement(); + return documentElement ? VisiblePosition(documentElement, 0, DOWNSTREAM) : VisiblePosition(); } VisiblePosition endOfDocument(const VisiblePosition &c) { - Position p = c.deepEquivalent(); - NodeImpl *node = p.node(); - if (!node) - return VisiblePosition(); - - DocumentImpl *doc = node->getDocument(); - if (!doc) - return VisiblePosition(); - - NodeImpl *docElem = doc->documentElement(); - if (!node) - return VisiblePosition(); - - return VisiblePosition(docElem, docElem->childNodeCount(), DOWNSTREAM); + ElementImpl* documentElement = c.deepEquivalent().documentElement(); + return documentElement ? VisiblePosition(documentElement, documentElement->childNodeCount(), DOWNSTREAM) : VisiblePosition(); } bool inSameDocument(const VisiblePosition &a, const VisiblePosition &b) diff --git a/WebCore/khtml/ecma/kjs_dom.cpp b/WebCore/khtml/ecma/kjs_dom.cpp index 7ad5735bbe0..7161611ddec 100644 --- a/WebCore/khtml/ecma/kjs_dom.cpp +++ b/WebCore/khtml/ecma/kjs_dom.cpp @@ -70,7 +70,7 @@ namespace KJS { // ------------------------------------------------------------------------- /* Source for DOMNodeProtoTable. Use "make hashtables" to regenerate. -@begin DOMNodeProtoTable 18 +@begin DOMNodeProtoTable 25 insertBefore DOMNode::InsertBefore DontDelete|Function 2 replaceChild DOMNode::ReplaceChild DontDelete|Function 2 removeChild DOMNode::RemoveChild DontDelete|Function 1 @@ -87,10 +87,7 @@ namespace KJS { isDefaultNamespace DOMNode::IsDefaultNamespace DontDelete|Function 1 lookupNamespaceURI DOMNode::LookupNamespaceURI DontDelete|Function 1 lookupPrefix DOMNode::LookupPrefix DontDelete|Function 1 -# from the EventTarget interface - addEventListener DOMNode::AddEventListener DontDelete|Function 3 - removeEventListener DOMNode::RemoveEventListener DontDelete|Function 3 - dispatchEvent DOMNode::DispatchEvent DontDelete|Function 1 +# IE extension contains DOMNode::Contains DontDelete|Function 1 # "DOM level 0" (from Gecko DOM reference; also in WinIE) item DOMNode::Item DontDelete|Function 1 @@ -146,12 +143,10 @@ void DOMNode::mark() return; } - DocumentImpl *document = m_impl->getDocument(); - // Mark the whole tree; use the global set of roots to avoid reentering. markingRoots.add(root); for (NodeImpl *nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) { - DOMNode *wrapper = ScriptInterpreter::getDOMNodeForDocument(document, nodeToMark); + DOMNode *wrapper = ScriptInterpreter::getDOMNodeForDocument(m_impl->getDocument(), nodeToMark); if (wrapper) { if (!wrapper->marked()) wrapper->mark(); @@ -177,7 +172,7 @@ bool DOMNode::toBoolean(ExecState *) const } /* Source for DOMNodeTable. Use "make hashtables" to regenerate. -@begin DOMNodeTable 69 +@begin DOMNodeTable 25 nodeName DOMNode::NodeName DontDelete|ReadOnly nodeValue DOMNode::NodeValue DontDelete nodeType DOMNode::NodeType DontDelete|ReadOnly @@ -196,61 +191,6 @@ bool DOMNode::toBoolean(ExecState *) const ownerDocument DOMNode::OwnerDocument DontDelete|ReadOnly # DOM3 textContent DOMNode::TextContent DontDelete -# - onabort DOMNode::OnAbort DontDelete - onblur DOMNode::OnBlur DontDelete - onchange DOMNode::OnChange DontDelete - onclick DOMNode::OnClick DontDelete - oncontextmenu DOMNode::OnContextMenu DontDelete - ondblclick DOMNode::OnDblClick DontDelete - onbeforecut DOMNode::OnBeforeCut DontDelete - oncut DOMNode::OnCut DontDelete - onbeforecopy DOMNode::OnBeforeCopy DontDelete - oncopy DOMNode::OnCopy DontDelete - onbeforepaste DOMNode::OnBeforePaste DontDelete - onpaste DOMNode::OnPaste DontDelete - ondrag DOMNode::OnDrag DontDelete - ondragdrop DOMNode::OnDragDrop DontDelete - ondragend DOMNode::OnDragEnd DontDelete - ondragenter DOMNode::OnDragEnter DontDelete - ondragleave DOMNode::OnDragLeave DontDelete - ondragover DOMNode::OnDragOver DontDelete - ondragstart DOMNode::OnDragStart DontDelete - ondrop DOMNode::OnDrop DontDelete - onerror DOMNode::OnError DontDelete - onfocus DOMNode::OnFocus DontDelete - oninput DOMNode::OnInput DontDelete - onkeydown DOMNode::OnKeyDown DontDelete - onkeypress DOMNode::OnKeyPress DontDelete - onkeyup DOMNode::OnKeyUp DontDelete - onload DOMNode::OnLoad DontDelete - onmousedown DOMNode::OnMouseDown DontDelete - onmousemove DOMNode::OnMouseMove DontDelete - onmouseout DOMNode::OnMouseOut DontDelete - onmouseover DOMNode::OnMouseOver DontDelete - onmouseup DOMNode::OnMouseUp DontDelete - onmousewheel DOMNode::OnMouseWheel DontDelete - onmove DOMNode::OnMove DontDelete - onreset DOMNode::OnReset DontDelete - onresize DOMNode::OnResize DontDelete - onscroll DOMNode::OnScroll DontDelete - onsearch DOMNode::OnSearch DontDelete - onselect DOMNode::OnSelect DontDelete - onselectstart DOMNode::OnSelectStart DontDelete - onsubmit DOMNode::OnSubmit DontDelete - onunload DOMNode::OnUnload DontDelete -# IE extensions - offsetLeft DOMNode::OffsetLeft DontDelete|ReadOnly - offsetTop DOMNode::OffsetTop DontDelete|ReadOnly - offsetWidth DOMNode::OffsetWidth DontDelete|ReadOnly - offsetHeight DOMNode::OffsetHeight DontDelete|ReadOnly - offsetParent DOMNode::OffsetParent DontDelete|ReadOnly - clientWidth DOMNode::ClientWidth DontDelete|ReadOnly - clientHeight DOMNode::ClientHeight DontDelete|ReadOnly - scrollLeft DOMNode::ScrollLeft DontDelete - scrollTop DOMNode::ScrollTop DontDelete - scrollWidth DOMNode::ScrollWidth DontDelete|ReadOnly - scrollHeight DOMNode::ScrollHeight DontDelete|ReadOnly @end */ bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) @@ -293,132 +233,9 @@ JSValue *DOMNode::getValueProperty(ExecState *exec, int token) const return toJS(exec,node.ownerDocument()); case TextContent: return jsStringOrNull(node.textContent()); - case OnAbort: - return getListener(abortEvent); - case OnBlur: - return getListener(blurEvent); - case OnChange: - return getListener(changeEvent); - case OnClick: - return getListener(clickEvent); - case OnContextMenu: - return getListener(contextmenuEvent); - case OnDblClick: - return getListener(dblclickEvent); - case OnDragDrop: - return getListener(khtmlDragdropEvent); - case OnError: - return getListener(khtmlErrorEvent); - case OnFocus: - return getListener(focusEvent); - case OnInput: - return getListener(inputEvent); - case OnKeyDown: - return getListener(keydownEvent); - case OnKeyPress: - return getListener(keypressEvent); - case OnKeyUp: - return getListener(keyupEvent); - case OnLoad: - return getListener(loadEvent); - case OnMouseDown: - return getListener(mousedownEvent); - case OnMouseMove: - return getListener(mousemoveEvent); - case OnMouseOut: - return getListener(mouseoutEvent); - case OnMouseOver: - return getListener(mouseoverEvent); - case OnMouseUp: - return getListener(mouseupEvent); - case OnMouseWheel: - return getListener(mousewheelEvent); - case OnBeforeCut: - return getListener(beforecutEvent); - case OnCut: - return getListener(cutEvent); - case OnBeforeCopy: - return getListener(beforecopyEvent); - case OnCopy: - return getListener(copyEvent); - case OnBeforePaste: - return getListener(beforepasteEvent); - case OnPaste: - return getListener(pasteEvent); - case OnDragEnter: - return getListener(dragenterEvent); - case OnDragOver: - return getListener(dragoverEvent); - case OnDragLeave: - return getListener(dragleaveEvent); - case OnDrop: - return getListener(dropEvent); - case OnDragStart: - return getListener(dragstartEvent); - case OnDrag: - return getListener(dragEvent); - case OnDragEnd: - return getListener(dragendEvent); - case OnMove: - return getListener(khtmlMoveEvent); - case OnReset: - return getListener(resetEvent); - case OnResize: - return getListener(resizeEvent); - case OnScroll: - return getListener(scrollEvent); - case OnSearch: - return getListener(searchEvent); - case OnSelect: - return getListener(selectEvent); - case OnSelectStart: - return getListener(selectstartEvent); - case OnSubmit: - return getListener(submitEvent); - case OnUnload: - return getListener(unloadEvent); - default: - // no DOM standard, found in IE only - - // Make sure our layout is up to date before we allow a query on these attributes. - DOM::DocumentImpl* docimpl = node.getDocument(); - if (docimpl) { - docimpl->updateLayoutIgnorePendingStylesheets(); - } - - RenderObject *rend = node.renderer(); - - switch (token) { - case OffsetLeft: - return rend ? jsNumber(rend->offsetLeft()) : static_cast(jsUndefined()); - case OffsetTop: - return rend ? jsNumber(rend->offsetTop()) : static_cast(jsUndefined()); - case OffsetWidth: - return rend ? jsNumber(rend->offsetWidth()) : static_cast(jsUndefined()); - case OffsetHeight: - return rend ? jsNumber(rend->offsetHeight()) : static_cast(jsUndefined()); - case OffsetParent: { - RenderObject* par = rend ? rend->offsetParent() : 0; - return toJS(exec, par ? par->element() : 0); - } - case ClientWidth: - return rend ? jsNumber(rend->clientWidth()) : static_cast(jsUndefined()); - case ClientHeight: - return rend ? jsNumber(rend->clientHeight()) : static_cast(jsUndefined()); - case ScrollWidth: - return rend ? jsNumber(rend->scrollWidth()) : static_cast(jsUndefined()); - case ScrollHeight: - return rend ? jsNumber(rend->scrollHeight()) : static_cast(jsUndefined()); - case ScrollLeft: - return jsNumber(rend && rend->layer() ? rend->layer()->scrollXOffset() : 0); - case ScrollTop: - return jsNumber(rend && rend->layer() ? rend->layer()->scrollYOffset() : 0); - default: - break; - } } - return NULL; + return jsUndefined(); } void DOMNode::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr) @@ -440,144 +257,6 @@ void DOMNode::putValueProperty(ExecState *exec, int token, JSValue *value, int / case TextContent: node.setTextContent(valueToStringWithNullCheck(exec, value), exception); break; - case OnAbort: - setListener(exec,abortEvent,value); - break; - case OnBlur: - setListener(exec,blurEvent,value); - break; - case OnChange: - setListener(exec,changeEvent,value); - break; - case OnClick: - setListener(exec,clickEvent,value); - break; - case OnContextMenu: - setListener(exec,contextmenuEvent,value); - break; - case OnDblClick: - setListener(exec,dblclickEvent,value); - break; - case OnDragDrop: - setListener(exec,khtmlDragdropEvent,value); - break; - case OnError: - setListener(exec,khtmlErrorEvent,value); - break; - case OnFocus: - setListener(exec,focusEvent,value); - break; - case OnInput: - setListener(exec,inputEvent,value); - break; - case OnKeyDown: - setListener(exec,keydownEvent,value); - break; - case OnKeyPress: - setListener(exec,keypressEvent,value); - break; - case OnKeyUp: - setListener(exec,keyupEvent,value); - break; - case OnLoad: - setListener(exec,loadEvent,value); - break; - case OnMouseDown: - setListener(exec,mousedownEvent,value); - break; - case OnMouseMove: - setListener(exec,mousemoveEvent,value); - break; - case OnMouseOut: - setListener(exec,mouseoutEvent,value); - break; - case OnMouseOver: - setListener(exec,mouseoverEvent,value); - break; - case OnMouseUp: - setListener(exec,mouseupEvent,value); - break; - case OnMouseWheel: - setListener(exec,mousewheelEvent,value); - break; - case OnBeforeCut: - setListener(exec,beforecutEvent,value); - break; - case OnCut: - setListener(exec,cutEvent,value); - break; - case OnBeforeCopy: - setListener(exec,beforecopyEvent,value); - break; - case OnCopy: - setListener(exec,copyEvent,value); - break; - case OnBeforePaste: - setListener(exec,beforepasteEvent,value); - break; - case OnPaste: - setListener(exec,pasteEvent,value); - break; - case OnDragEnter: - setListener(exec,dragenterEvent,value); - break; - case OnDragOver: - setListener(exec,dragoverEvent,value); - break; - case OnDragLeave: - setListener(exec,dragleaveEvent,value); - break; - case OnDrop: - setListener(exec,dropEvent,value); - break; - case OnDragStart: - setListener(exec,dragstartEvent,value); - break; - case OnDrag: - setListener(exec,dragEvent,value); - break; - case OnDragEnd: - setListener(exec,dragendEvent,value); - break; - case OnMove: - setListener(exec,khtmlMoveEvent,value); - break; - case OnReset: - setListener(exec,resetEvent,value); - break; - case OnResize: - setListener(exec,resizeEvent,value); - break; - case OnScroll: - setListener(exec,scrollEvent,value); - break; - case OnSearch: - setListener(exec,searchEvent,value); - break; - case OnSelect: - setListener(exec,selectEvent,value); - break; - case OnSelectStart: - setListener(exec,selectstartEvent,value); - break; - case OnSubmit: - setListener(exec,submitEvent,value); - break; - case OnUnload: - setListener(exec, unloadEvent, value); - break; - case ScrollTop: { - RenderObject *rend = node.renderer(); - if (rend && rend->hasOverflowClip()) - rend->layer()->scrollToYOffset(value->toInt32(exec)); - break; - } - case ScrollLeft: { - RenderObject *rend = node.renderer(); - if (rend && rend->hasOverflowClip()) - rend->layer()->scrollToXOffset(value->toInt32(exec)); - break; - } } } @@ -596,25 +275,6 @@ UString DOMNode::toString(ExecState *) const return "[object " + (m_impl->isElementNode() ? m_impl->nodeName() : className()) + "]"; } -void DOMNode::setListener(ExecState *exec, const AtomicString &eventType, JSValue *func) const -{ - m_impl->setHTMLEventListener(eventType, Window::retrieveActive(exec)->getJSEventListener(func, true)); -} - -JSValue *DOMNode::getListener(const AtomicString &eventType) const -{ - DOM::EventListener *listener = m_impl->getHTMLEventListener(eventType); - JSEventListener *jsListener = static_cast(listener); - if (jsListener && jsListener->listenerObj()) - return jsListener->listenerObj(); - else - return jsNull(); -} - -void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const -{ -} - JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { if (!thisObj->inherits(&DOMNode::info)) @@ -644,20 +304,6 @@ JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, co return jsStringOrNull(node.lookupNamespaceURI(valueToStringWithNullCheck(exec, args[0]))); case DOMNode::LookupPrefix: return jsStringOrNull(node.lookupPrefix(valueToStringWithNullCheck(exec, args[0]))); - case DOMNode::AddEventListener: { - JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); - if (listener) - node.addEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec)); - return jsUndefined(); - } - case DOMNode::RemoveEventListener: { - JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); - if (listener) - node.removeEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec)); - return jsUndefined(); - } - case DOMNode::DispatchEvent: - return jsBoolean(node.dispatchEvent(toEvent(args[0]), exception)); case DOMNode::AppendChild: if (node.appendChild(toNode(args[0]), exception)) return args[0]; @@ -695,6 +341,359 @@ NodeImpl *toNode(JSValue *val) return static_cast(val)->impl(); } + +// ------------------------------------------------------------------------- + +/* Source for DOMEventTargetNodeTable +@begin DOMEventTargetNodeTable 50 +onabort DOMEventTargetNode::OnAbort DontDelete +onblur DOMEventTargetNode::OnBlur DontDelete +onchange DOMEventTargetNode::OnChange DontDelete +onclick DOMEventTargetNode::OnClick DontDelete +oncontextmenu DOMEventTargetNode::OnContextMenu DontDelete +ondblclick DOMEventTargetNode::OnDblClick DontDelete +onbeforecut DOMEventTargetNode::OnBeforeCut DontDelete +oncut DOMEventTargetNode::OnCut DontDelete +onbeforecopy DOMEventTargetNode::OnBeforeCopy DontDelete +oncopy DOMEventTargetNode::OnCopy DontDelete +onbeforepaste DOMEventTargetNode::OnBeforePaste DontDelete +onpaste DOMEventTargetNode::OnPaste DontDelete +ondrag DOMEventTargetNode::OnDrag DontDelete +ondragdrop DOMEventTargetNode::OnDragDrop DontDelete +ondragend DOMEventTargetNode::OnDragEnd DontDelete +ondragenter DOMEventTargetNode::OnDragEnter DontDelete +ondragleave DOMEventTargetNode::OnDragLeave DontDelete +ondragover DOMEventTargetNode::OnDragOver DontDelete +ondragstart DOMEventTargetNode::OnDragStart DontDelete +ondrop DOMEventTargetNode::OnDrop DontDelete +onerror DOMEventTargetNode::OnError DontDelete +onfocus DOMEventTargetNode::OnFocus DontDelete +oninput DOMEventTargetNode::OnInput DontDelete +onkeydown DOMEventTargetNode::OnKeyDown DontDelete +onkeypress DOMEventTargetNode::OnKeyPress DontDelete +onkeyup DOMEventTargetNode::OnKeyUp DontDelete +onload DOMEventTargetNode::OnLoad DontDelete +onmousedown DOMEventTargetNode::OnMouseDown DontDelete +onmousemove DOMEventTargetNode::OnMouseMove DontDelete +onmouseout DOMEventTargetNode::OnMouseOut DontDelete +onmouseover DOMEventTargetNode::OnMouseOver DontDelete +onmouseup DOMEventTargetNode::OnMouseUp DontDelete +onmousewheel DOMEventTargetNode::OnMouseWheel DontDelete +onmove DOMEventTargetNode::OnMove DontDelete +onreset DOMEventTargetNode::OnReset DontDelete +onresize DOMEventTargetNode::OnResize DontDelete +onscroll DOMEventTargetNode::OnScroll DontDelete +onsearch DOMEventTargetNode::OnSearch DontDelete +onselect DOMEventTargetNode::OnSelect DontDelete +onselectstart DOMEventTargetNode::OnSelectStart DontDelete +onsubmit DOMEventTargetNode::OnSubmit DontDelete +onunload DOMEventTargetNode::OnUnload DontDelete +@end +*/ + +DOMEventTargetNode::DOMEventTargetNode(NodeImpl* n) + : DOMNode(n) +{ +} + +DOMEventTargetNode::DOMEventTargetNode(ExecState *exec, NodeImpl *n) + : DOMNode(n) +{ + setPrototype(DOMEventTargetNodeProto::self(exec)); +} + +bool DOMEventTargetNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticValueSlot(exec, &DOMEventTargetNodeTable, this, propertyName, slot); +} + +JSValue *DOMEventTargetNode::getValueProperty(ExecState *exec, int token) const +{ + switch (token) { + case OnAbort: + return getListener(abortEvent); + case OnBlur: + return getListener(blurEvent); + case OnChange: + return getListener(changeEvent); + case OnClick: + return getListener(clickEvent); + case OnContextMenu: + return getListener(contextmenuEvent); + case OnDblClick: + return getListener(dblclickEvent); + case OnDragDrop: + return getListener(khtmlDragdropEvent); + case OnError: + return getListener(khtmlErrorEvent); + case OnFocus: + return getListener(focusEvent); + case OnInput: + return getListener(inputEvent); + case OnKeyDown: + return getListener(keydownEvent); + case OnKeyPress: + return getListener(keypressEvent); + case OnKeyUp: + return getListener(keyupEvent); + case OnLoad: + return getListener(loadEvent); + case OnMouseDown: + return getListener(mousedownEvent); + case OnMouseMove: + return getListener(mousemoveEvent); + case OnMouseOut: + return getListener(mouseoutEvent); + case OnMouseOver: + return getListener(mouseoverEvent); + case OnMouseUp: + return getListener(mouseupEvent); + case OnMouseWheel: + return getListener(mousewheelEvent); + case OnBeforeCut: + return getListener(beforecutEvent); + case OnCut: + return getListener(cutEvent); + case OnBeforeCopy: + return getListener(beforecopyEvent); + case OnCopy: + return getListener(copyEvent); + case OnBeforePaste: + return getListener(beforepasteEvent); + case OnPaste: + return getListener(pasteEvent); + case OnDragEnter: + return getListener(dragenterEvent); + case OnDragOver: + return getListener(dragoverEvent); + case OnDragLeave: + return getListener(dragleaveEvent); + case OnDrop: + return getListener(dropEvent); + case OnDragStart: + return getListener(dragstartEvent); + case OnDrag: + return getListener(dragEvent); + case OnDragEnd: + return getListener(dragendEvent); + case OnMove: + return getListener(khtmlMoveEvent); + case OnReset: + return getListener(resetEvent); + case OnResize: + return getListener(resizeEvent); + case OnScroll: + return getListener(scrollEvent); + case OnSearch: + return getListener(searchEvent); + case OnSelect: + return getListener(selectEvent); + case OnSelectStart: + return getListener(selectstartEvent); + case OnSubmit: + return getListener(submitEvent); + case OnUnload: + return getListener(unloadEvent); + } + + return jsUndefined(); +} + +void DOMEventTargetNode::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr) +{ + lookupPut(exec, propertyName, value, attr, &DOMEventTargetNodeTable, this); +} + +void DOMEventTargetNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) +{ + switch (token) { + case OnAbort: + setListener(exec, abortEvent, value); + break; + case OnBlur: + setListener(exec, blurEvent, value); + break; + case OnChange: + setListener(exec, changeEvent, value); + break; + case OnClick: + setListener(exec, clickEvent, value); + break; + case OnContextMenu: + setListener(exec, contextmenuEvent, value); + break; + case OnDblClick: + setListener(exec, dblclickEvent, value); + break; + case OnDragDrop: + setListener(exec, khtmlDragdropEvent, value); + break; + case OnError: + setListener(exec, khtmlErrorEvent, value); + break; + case OnFocus: + setListener(exec, focusEvent, value); + break; + case OnInput: + setListener(exec, inputEvent, value); + break; + case OnKeyDown: + setListener(exec, keydownEvent, value); + break; + case OnKeyPress: + setListener(exec, keypressEvent, value); + break; + case OnKeyUp: + setListener(exec, keyupEvent, value); + break; + case OnLoad: + setListener(exec, loadEvent, value); + break; + case OnMouseDown: + setListener(exec, mousedownEvent, value); + break; + case OnMouseMove: + setListener(exec, mousemoveEvent, value); + break; + case OnMouseOut: + setListener(exec, mouseoutEvent, value); + break; + case OnMouseOver: + setListener(exec, mouseoverEvent, value); + break; + case OnMouseUp: + setListener(exec, mouseupEvent, value); + break; + case OnMouseWheel: + setListener(exec, mousewheelEvent, value); + break; + case OnBeforeCut: + setListener(exec, beforecutEvent, value); + break; + case OnCut: + setListener(exec, cutEvent, value); + break; + case OnBeforeCopy: + setListener(exec, beforecopyEvent, value); + break; + case OnCopy: + setListener(exec, copyEvent, value); + break; + case OnBeforePaste: + setListener(exec, beforepasteEvent, value); + break; + case OnPaste: + setListener(exec, pasteEvent, value); + break; + case OnDragEnter: + setListener(exec, dragenterEvent, value); + break; + case OnDragOver: + setListener(exec, dragoverEvent, value); + break; + case OnDragLeave: + setListener(exec, dragleaveEvent, value); + break; + case OnDrop: + setListener(exec, dropEvent, value); + break; + case OnDragStart: + setListener(exec, dragstartEvent, value); + break; + case OnDrag: + setListener(exec, dragEvent, value); + break; + case OnDragEnd: + setListener(exec, dragendEvent, value); + break; + case OnMove: + setListener(exec, khtmlMoveEvent, value); + break; + case OnReset: + setListener(exec, resetEvent, value); + break; + case OnResize: + setListener(exec, resizeEvent, value); + break; + case OnScroll: + setListener(exec, scrollEvent, value); + break; + case OnSearch: + setListener(exec, searchEvent, value); + break; + case OnSelect: + setListener(exec, selectEvent, value); + break; + case OnSelectStart: + setListener(exec, selectstartEvent, value); + break; + case OnSubmit: + setListener(exec, submitEvent, value); + break; + case OnUnload: + setListener(exec, unloadEvent, value); + break; + } +} + +void DOMEventTargetNode::setListener(ExecState *exec, const AtomicString &eventType, JSValue *func) const +{ + EventTargetNodeCast(impl())->setHTMLEventListener(eventType, Window::retrieveActive(exec)->getJSEventListener(func, true)); +} + +JSValue *DOMEventTargetNode::getListener(const AtomicString &eventType) const +{ + DOM::EventListener *listener = EventTargetNodeCast(impl())->getHTMLEventListener(eventType); + JSEventListener *jsListener = static_cast(listener); + if (jsListener && jsListener->listenerObj()) + return jsListener->listenerObj(); + else + return jsNull(); +} + +void DOMEventTargetNode::pushEventHandlerScope(ExecState *, ScopeChain &) const +{ +} + +/* +@begin DOMEventTargetNodeProtoTable 5 +# from the EventTarget interface +addEventListener DOMEventTargetNode::AddEventListener DontDelete|Function 3 +removeEventListener DOMEventTargetNode::RemoveEventListener DontDelete|Function 3 +dispatchEvent DOMEventTargetNode::DispatchEvent DontDelete|Function 1 +@end +*/ + +KJS_IMPLEMENT_PROTOFUNC(DOMEventTargetNodeProtoFunc) +KJS_IMPLEMENT_PROTOTYPE("DOMEventTargetNode", DOMEventTargetNodeProto, DOMEventTargetNodeProtoFunc) + +JSValue *DOMEventTargetNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) +{ + if (!thisObj->inherits(&DOMEventTargetNode::info)) + return throwError(exec, TypeError); + DOMExceptionTranslator exception(exec); + DOMEventTargetNode* DOMNode = static_cast(thisObj); + EventTargetNodeImpl* node = static_cast(DOMNode->impl()); + switch (id) { + case DOMEventTargetNode::AddEventListener: { + JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); + if (listener) + node->addEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec)); + return jsUndefined(); + } + case DOMEventTargetNode::RemoveEventListener: { + JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); + if (listener) + node->removeEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec)); + return jsUndefined(); + } + case DOMEventTargetNode::DispatchEvent: + return jsBoolean(node->dispatchEvent(toEvent(args[0]), exception)); + } + + return jsUndefined(); +} + // ------------------------------------------------------------------------- /* @@ -833,14 +832,14 @@ AttrImpl *toAttr(JSValue *val) queryCommandValue DOMDocument::QueryCommandValue DontDelete|Function 1 @end */ -KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMDocumentProto, DOMNodeProto) +KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMDocumentProto, DOMEventTargetNodeProto) KJS_IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc) KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc) -const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 }; +const ClassInfo DOMDocument::info = { "Document", &DOMEventTargetNode::info, &DOMDocumentTable, 0 }; /* Source for DOMDocumentTable. Use "make hashtables" to regenerate. -@begin DOMDocumentTable 4 +@begin DOMDocumentTable 17 doctype DOMDocument::DocType DontDelete|ReadOnly implementation DOMDocument::Implementation DontDelete|ReadOnly documentElement DOMDocument::DocumentElement DontDelete|ReadOnly @@ -858,13 +857,13 @@ const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTa */ DOMDocument::DOMDocument(ExecState *exec, DocumentImpl *d) - : DOMNode(d) + : DOMEventTargetNode(d) { setPrototype(DOMDocumentProto::self(exec)); } DOMDocument::DOMDocument(DocumentImpl *d) - : DOMNode(d) + : DOMEventTargetNode(d) { } @@ -875,7 +874,7 @@ DOMDocument::~DOMDocument() bool DOMDocument::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { - return getStaticValueSlot(exec, &DOMDocumentTable, this, propertyName, slot); + return getStaticValueSlot(exec, &DOMDocumentTable, this, propertyName, slot); } JSValue *DOMDocument::getValueProperty(ExecState *exec, int token) const @@ -925,10 +924,10 @@ JSValue *DOMDocument::getValueProperty(ExecState *exec, int token) const void DOMDocument::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr) { - lookupPut(exec, propertyName, value, attr, &DOMDocumentTable, this); + lookupPut(exec, propertyName, value, attr, &DOMDocumentTable, this); } -void DOMDocument::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) +void DOMDocument::putValueProperty(ExecState *exec, int token, JSValue *value, int) { DocumentImpl &doc = *static_cast(impl()); switch (token) { @@ -943,7 +942,7 @@ void DOMDocument::putValueProperty(ExecState *exec, int token, JSValue *value, i JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { - if (!thisObj->inherits(&KJS::DOMNode::info)) + if (!thisObj->inherits(&KJS::DOMDocument::info)) return throwError(exec, TypeError); DOMExceptionTranslator exception(exec); NodeImpl &node = *static_cast(thisObj)->impl(); @@ -1048,46 +1047,116 @@ JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj // ------------------------------------------------------------------------- /* Source for DOMElementProtoTable. Use "make hashtables" to regenerate. -@begin DOMElementProtoTable 17 - scrollIntoView DOMElement::ScrollIntoView DontDelete|Function 1 +@begin DOMElementProtoTable 8 + scrollIntoView DOMElement::ScrollIntoView DontDelete|Function 1 scrollIntoViewIfNeeded DOMElement::ScrollIntoViewIfNeeded DontDelete|Function 1 # extension for Safari RSS scrollByLines DOMElement::ScrollByLines DontDelete|Function 1 scrollByPages DOMElement::ScrollByPages DontDelete|Function 1 - @end */ KJS_IMPLEMENT_PROTOFUNC(DOMElementProtoFunc) KJS_IMPLEMENT_PROTOTYPE("DOMElement", DOMElementProto, DOMElementProtoFunc) -const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 }; +const ClassInfo DOMElement::info = { "Element", &DOMEventTargetNode::info, &DOMElementTable, 0 }; /* Source for DOMElementTable. Use "make hashtables" to regenerate. -@begin DOMElementTable 3 - tagName DOMElement::TagName DontDelete|ReadOnly +@begin DOMElementTable 17 + tagName DOMElement::TagName DontDelete|ReadOnly + +# IE extensions + offsetLeft DOMElement::OffsetLeft DontDelete|ReadOnly + offsetTop DOMElement::OffsetTop DontDelete|ReadOnly + offsetWidth DOMElement::OffsetWidth DontDelete|ReadOnly + offsetHeight DOMElement::OffsetHeight DontDelete|ReadOnly + offsetParent DOMElement::OffsetParent DontDelete|ReadOnly + clientWidth DOMElement::ClientWidth DontDelete|ReadOnly + clientHeight DOMElement::ClientHeight DontDelete|ReadOnly + scrollLeft DOMElement::ScrollLeft DontDelete + scrollTop DOMElement::ScrollTop DontDelete + scrollWidth DOMElement::ScrollWidth DontDelete|ReadOnly + scrollHeight DOMElement::ScrollHeight DontDelete|ReadOnly @end */ DOMElement::DOMElement(ExecState *exec, ElementImpl *e) - : DOMNode(e) + : DOMEventTargetNode(e) { setPrototype(DOMElementProto::self(exec)); } DOMElement::DOMElement(ElementImpl *e) - : DOMNode(e) + : DOMEventTargetNode(e) { } JSValue *DOMElement::getValueProperty(ExecState *exec, int token) const { - ElementImpl *element = static_cast(impl()); - switch (token) { - case TagName: - return jsStringOrNull(element->nodeName()); - default: - assert(0); + ElementImpl *element = static_cast(impl()); + switch (token) { + case TagName: + return jsStringOrNull(element->nodeName()); + + default: + // no DOM standard -- IE extension + + // Make sure our layout is up to date before we allow a query on these attributes. + element->getDocument()->updateLayoutIgnorePendingStylesheets(); + + RenderObject *rend = element->renderer(); + + switch (token) { + case OffsetLeft: + return rend ? jsNumber(rend->offsetLeft()) : static_cast(jsUndefined()); + case OffsetTop: + return rend ? jsNumber(rend->offsetTop()) : static_cast(jsUndefined()); + case OffsetWidth: + return rend ? jsNumber(rend->offsetWidth()) : static_cast(jsUndefined()); + case OffsetHeight: + return rend ? jsNumber(rend->offsetHeight()) : static_cast(jsUndefined()); + case OffsetParent: { + RenderObject* par = rend ? rend->offsetParent() : 0; + return toJS(exec, par ? par->element() : 0); + } + case ClientWidth: + return rend ? jsNumber(rend->clientWidth()) : static_cast(jsUndefined()); + case ClientHeight: + return rend ? jsNumber(rend->clientHeight()) : static_cast(jsUndefined()); + case ScrollWidth: + return rend ? jsNumber(rend->scrollWidth()) : static_cast(jsUndefined()); + case ScrollHeight: + return rend ? jsNumber(rend->scrollHeight()) : static_cast(jsUndefined()); + case ScrollLeft: + return jsNumber(rend && rend->layer() ? rend->layer()->scrollXOffset() : 0); + case ScrollTop: + return jsNumber(rend && rend->layer() ? rend->layer()->scrollYOffset() : 0); + } + } + return jsUndefined(); - } +} + +void DOMElement::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr) +{ + lookupPut(exec, propertyName, value, attr, &DOMElementTable, this); +} + +void DOMElement::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) +{ + NodeImpl &node = *m_impl; + switch (token) { + case ScrollTop: { + RenderObject *rend = node.renderer(); + if (rend && rend->hasOverflowClip()) + rend->layer()->scrollToYOffset(value->toInt32(exec)); + break; + } + case ScrollLeft: { + RenderObject *rend = node.renderer(); + if (rend && rend->hasOverflowClip()) + rend->layer()->scrollToXOffset(value->toInt32(exec)); + break; + } + } } JSValue *DOMElement::attributeGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot) @@ -1107,10 +1176,10 @@ bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyN return true; } - // We have to check in DOMNode before giving access to attributes, otherwise + // We have to check in DOMEventTargetNode before giving access to attributes, otherwise // onload="..." would make onload return the string (attribute value) instead of // the listener object (function). - if (DOMNode::getOwnPropertySlot(exec, propertyName, slot)) + if (DOMEventTargetNode::getOwnPropertySlot(exec, propertyName, slot)) return true; JSValue *proto = prototype(); @@ -1132,7 +1201,7 @@ bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyN JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { - if (!thisObj->inherits(&KJS::DOMNode::info)) + if (!thisObj->inherits(&KJS::DOMElement::info)) return throwError(exec, TypeError); DOMExceptionTranslator exception(exec); NodeImpl &node = *static_cast(thisObj)->impl(); @@ -1147,8 +1216,7 @@ JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, return jsUndefined(); case DOMElement::ScrollByLines: case DOMElement::ScrollByPages: - if (DocumentImpl* doc = element.getDocument()) { - doc->updateLayoutIgnorePendingStylesheets(); + element.getDocument()->updateLayoutIgnorePendingStylesheets(); if (RenderObject *rend = element.renderer()) if (rend->hasOverflowClip()) { KWQScrollDirection direction = KWQScrollDown; @@ -1160,11 +1228,10 @@ JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, KWQScrollGranularity granularity = id == DOMElement::ScrollByLines ? KWQScrollLine : KWQScrollPage; rend->layer()->scroll(direction, granularity, multiplier); } - } - return jsUndefined(); - default: - return jsUndefined(); + return jsUndefined(); } + + return jsUndefined(); } ElementImpl *toElement(JSValue *val) @@ -1184,7 +1251,7 @@ DocumentTypeImpl *toDocumentType(JSValue *val) // ------------------------------------------------------------------------- /* Source for DOMNamedNodeMapProtoTable. Use "make hashtables" to regenerate. -@begin DOMNamedNodeMapProtoTable 7 +@begin DOMNamedNodeMapProtoTable 10 getNamedItem DOMNamedNodeMap::GetNamedItem DontDelete|Function 1 setNamedItem DOMNamedNodeMap::SetNamedItem DontDelete|Function 1 removeNamedItem DOMNamedNodeMap::RemoveNamedItem DontDelete|Function 1 @@ -1317,10 +1384,7 @@ bool checkNodeSecurity(ExecState *exec, NodeImpl *n) return false; // Check to see if the currently executing interpreter is allowed to access the specified node - Frame *frame = n->getDocument()->frame(); - if (!frame) - return false; - Window *win = Window::retrieveWindow(frame); + Window *win = Window::retrieveWindow(n->getDocument()->frame()); return win && win->isSafeScript(exec); } diff --git a/WebCore/khtml/ecma/kjs_dom.h b/WebCore/khtml/ecma/kjs_dom.h index 644f33d79c2..23dc75aabf4 100644 --- a/WebCore/khtml/ecma/kjs_dom.h +++ b/WebCore/khtml/ecma/kjs_dom.h @@ -21,11 +21,11 @@ #ifndef KJS_DOM_H #define KJS_DOM_H -#include "kjs_binding.h" - -#include #include "NodeListImpl.h" #include "Shared.h" +#include "kjs_binding.h" +#include + namespace DOM { class AtomicString; @@ -35,6 +35,7 @@ namespace DOM { class DOMImplementationImpl; class ElementImpl; class EntityImpl; + class EventTargetNodeImpl; class NamedNodeMapImpl; class NotationImpl; class ProcessingInstructionImpl; @@ -61,32 +62,52 @@ namespace KJS { virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UndefinedType) const; virtual UString toString(ExecState *exec) const; - void setListener(ExecState *exec, const DOM::AtomicString &eventType, JSValue *func) const; - JSValue *getListener(const DOM::AtomicString &eventType) const; - virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const; enum { NodeName, NodeValue, NodeType, ParentNode, ParentElement, ChildNodes, FirstChild, LastChild, PreviousSibling, NextSibling, Item, Attributes, NamespaceURI, Prefix, LocalName, OwnerDocument, InsertBefore, ReplaceChild, RemoveChild, AppendChild, HasAttributes, HasChildNodes, - CloneNode, Normalize, IsSupported, AddEventListener, RemoveEventListener, - DispatchEvent, Contains, IsSameNode, IsEqualNode, TextContent, + CloneNode, Normalize, IsSupported, Contains, IsSameNode, IsEqualNode, TextContent, IsDefaultNamespace, LookupNamespaceURI, LookupPrefix, - OnAbort, OnBlur, OnChange, OnClick, OnContextMenu, OnDblClick, OnDragDrop, OnError, - OnDragEnter, OnDragOver, OnDragLeave, OnDrop, OnDragStart, OnDrag, OnDragEnd, - OnBeforeCut, OnCut, OnBeforeCopy, OnCopy, OnBeforePaste, OnPaste, OnSelectStart, - OnFocus, OnInput, OnKeyDown, OnKeyPress, OnKeyUp, OnLoad, OnMouseDown, - OnMouseMove, OnMouseOut, OnMouseOver, OnMouseUp, OnMouseWheel, OnMove, OnReset, - OnResize, OnScroll, OnSearch, OnSelect, OnSubmit, OnUnload, - OffsetLeft, OffsetTop, OffsetWidth, OffsetHeight, OffsetParent, - ClientWidth, ClientHeight, ScrollLeft, ScrollTop, ScrollWidth, ScrollHeight, - ScrollIntoView, ScrollIntoViewIfNeeded }; + }; protected: // Constructor for inherited classes; doesn't set up a prototype. DOMNode(DOM::NodeImpl *n); RefPtr m_impl; }; + + KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMEventTargetNodeProto, DOMNodeProto) + + class DOMEventTargetNode : public DOMNode + { + public: + + DOMEventTargetNode(ExecState *exec, DOM::NodeImpl *n); + + void setListener(ExecState* exec, const DOM::AtomicString &eventType, JSValue* func) const; + JSValue* getListener(const DOM::AtomicString &eventType) const; + virtual void pushEventHandlerScope(ExecState* exec, ScopeChain &scope) const; + + bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot); + JSValue* getValueProperty(ExecState* exec, int token) const; + virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr); + void putValueProperty(ExecState* exec, int token, JSValue* value, int); + + enum { + AddEventListener, RemoveEventListener, DispatchEvent, + OnAbort, OnBlur, OnChange, OnClick, OnContextMenu, OnDblClick, OnDragDrop, OnError, + OnDragEnter, OnDragOver, OnDragLeave, OnDrop, OnDragStart, OnDrag, OnDragEnd, + OnBeforeCut, OnCut, OnBeforeCopy, OnCopy, OnBeforePaste, OnPaste, OnSelectStart, + OnFocus, OnInput, OnKeyDown, OnKeyPress, OnKeyUp, OnLoad, OnMouseDown, + OnMouseMove, OnMouseOut, OnMouseOver, OnMouseUp, OnMouseWheel, OnMove, OnReset, + OnResize, OnScroll, OnSearch, OnSelect, OnSubmit, OnUnload + }; + +protected: + // Constructor for inherited classes; doesn't set up a prototype. + DOMEventTargetNode(DOM::NodeImpl *n); + }; DOM::NodeImpl *toNode(JSValue *); // returns 0 if passed-in value is not a DOMNode object @@ -114,7 +135,7 @@ namespace KJS { RefPtr m_impl; }; - class DOMDocument : public DOMNode { + class DOMDocument : public DOMEventTargetNode { public: DOMDocument(ExecState *exec, DOM::DocumentImpl *d); ~DOMDocument(); @@ -145,17 +166,22 @@ namespace KJS { DOM::AttrImpl *toAttr(JSValue *); // returns 0 if passed-in value is not a DOMAttr object - KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMElementProto, DOMNodeProto) + KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMElementProto, DOMEventTargetNodeProto) - class DOMElement : public DOMNode { + class DOMElement : public DOMEventTargetNode { public: DOMElement(ExecState *exec, DOM::ElementImpl *e); virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); JSValue *getValueProperty(ExecState *exec, int token) const; - // no put - all read-only + void putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/); + virtual void put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr = None); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - enum { TagName, ScrollByLines, ScrollByPages, ScrollIntoView }; + enum { + TagName, ScrollByLines, ScrollByPages, ScrollIntoView, ScrollIntoViewIfNeeded, + OffsetLeft, OffsetTop, OffsetWidth, OffsetHeight, OffsetParent, + ClientWidth, ClientHeight, ScrollLeft, ScrollTop, ScrollWidth, ScrollHeight + }; protected: // Constructor for inherited classes; doesn't set up a prototype. DOMElement(DOM::ElementImpl *e); diff --git a/WebCore/khtml/ecma/kjs_events.cpp b/WebCore/khtml/ecma/kjs_events.cpp index e80e5aa486f..f1685e280d7 100644 --- a/WebCore/khtml/ecma/kjs_events.cpp +++ b/WebCore/khtml/ecma/kjs_events.cpp @@ -274,7 +274,7 @@ void JSLazyEventListener::parseCode() const JSValue* thisObj = toJS(exec, originalNode); if (thisObj->isObject()) { - static_cast(thisObj)->pushEventHandlerScope(exec, scope); + static_cast(thisObj)->pushEventHandlerScope(exec, scope); listener->setScope(scope); } } @@ -287,7 +287,7 @@ void JSLazyEventListener::parseCode() const windowObj()->jsEventListeners.set(listener, const_cast(this)); } -JSValue* getNodeEventListener(NodeImpl* n, const AtomicString& eventType) +JSValue* getNodeEventListener(EventTargetNodeImpl* n, const AtomicString& eventType) { if (JSAbstractEventListener* listener = static_cast(n->getHTMLEventListener(eventType))) if (JSValue* obj = listener->listenerObj()) diff --git a/WebCore/khtml/ecma/kjs_html.cpp b/WebCore/khtml/ecma/kjs_html.cpp index 4a4c2334713..fe56b729b90 100644 --- a/WebCore/khtml/ecma/kjs_html.cpp +++ b/WebCore/khtml/ecma/kjs_html.cpp @@ -1447,9 +1447,8 @@ JSValue *HTMLElement::bodyGetter(ExecState* exec, int token) const default: { // Update the document's layout before we compute these attributes. DocumentImpl *doc = body.getDocument(); - if (doc) - doc->updateLayoutIgnorePendingStylesheets(); - FrameView *view = doc ? doc->view() : 0; + doc->updateLayoutIgnorePendingStylesheets(); + FrameView *view = doc->view(); switch (token) { case BodyScrollLeft: return jsNumber(view ? view->contentsX() : 0); @@ -1823,8 +1822,7 @@ JSValue *HTMLElement::anchorGetter(ExecState* exec, int token) const case AnchorTarget: return jsString(anchor.target()); case AnchorType: return jsString(anchor.type()); case AnchorText: - if (DocumentImpl* doc = anchor.getDocument()) - doc->updateLayoutIgnorePendingStylesheets(); + anchor.getDocument()->updateLayoutIgnorePendingStylesheets(); return jsString(anchor.innerText()); } return jsUndefined(); @@ -2147,8 +2145,7 @@ JSValue *HTMLElement::getValueProperty(ExecState *exec, int token) const case ElementInnerHTML: return jsString(element.innerHTML()); case ElementInnerText: - if (DocumentImpl* doc = impl()->getDocument()) - doc->updateLayoutIgnorePendingStylesheets(); + impl()->getDocument()->updateLayoutIgnorePendingStylesheets(); return jsString(element.innerText()); case ElementOuterHTML: return jsString(element.outerHTML()); @@ -2544,8 +2541,7 @@ void HTMLElement::bodySetter(ExecState *exec, int token, JSValue *value, const D FrameView* sview = body.ownerDocument()->view(); if (sview) { // Update the document's layout before we compute these attributes. - if (DocumentImpl* doc = body.getDocument()) - doc->updateLayoutIgnorePendingStylesheets(); + body.getDocument()->updateLayoutIgnorePendingStylesheets(); if (token == BodyScrollLeft) sview->setContentsPos(value->toInt32(exec), sview->contentsY()); else diff --git a/WebCore/khtml/ecma/kjs_views.cpp b/WebCore/khtml/ecma/kjs_views.cpp index d996582ac3a..f1f449beea1 100644 --- a/WebCore/khtml/ecma/kjs_views.cpp +++ b/WebCore/khtml/ecma/kjs_views.cpp @@ -88,8 +88,7 @@ JSValue *DOMAbstractViewProtoFunc::callAsFunction(ExecState *exec, JSObject *thi if (!arg0) return jsUndefined(); // throw exception? else { - if (DocumentImpl* doc = arg0->getDocument()) - doc->updateLayoutIgnorePendingStylesheets(); + arg0->getDocument()->updateLayoutIgnorePendingStylesheets(); return toJS(exec, abstractView.getComputedStyle(arg0, args[1]->toString(exec).domString().impl())); } } diff --git a/WebCore/khtml/html/HTMLFormElementImpl.cpp b/WebCore/khtml/html/HTMLFormElementImpl.cpp index 5eed58c83c5..5b82db0ac28 100644 --- a/WebCore/khtml/html/HTMLFormElementImpl.cpp +++ b/WebCore/khtml/html/HTMLFormElementImpl.cpp @@ -497,7 +497,7 @@ unsigned HTMLFormElementImpl::formElementIndex(HTMLGenericFormElementImpl *e) void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl* e) { DocumentImpl* doc = getDocument(); - if (doc && e->isRadioButton() && !e->name().isEmpty()) { + if (e->isRadioButton() && !e->name().isEmpty()) { HTMLGenericFormElementImpl* currentCheckedRadio = doc->checkedRadioButtonForGroup(e->name().impl(), 0); if (currentCheckedRadio == e) doc->removeRadioButtonGroup(e->name().impl(), 0); @@ -509,7 +509,7 @@ void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl* e) void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl* e) { - if (!e->name().isEmpty() && getDocument()) { + if (!e->name().isEmpty()) { HTMLGenericFormElementImpl* currentCheckedRadio = getDocument()->checkedRadioButtonForGroup(e->name().impl(), this); if (currentCheckedRadio == e) getDocument()->removeRadioButtonGroup(e->name().impl(), this); diff --git a/WebCore/khtml/html/HTMLGenericFormElementImpl.cpp b/WebCore/khtml/html/HTMLGenericFormElementImpl.cpp index 294e4f04839..0a36e19ef70 100644 --- a/WebCore/khtml/html/HTMLGenericFormElementImpl.cpp +++ b/WebCore/khtml/html/HTMLGenericFormElementImpl.cpp @@ -108,11 +108,9 @@ void HTMLGenericFormElementImpl::insertedIntoTree(bool deep) m_form = getForm(); if (m_form) m_form->registerFormElement(this); - else { - DocumentImpl *doc = getDocument(); - if (doc && isRadioButton() && !name().isEmpty() && isChecked()) - doc->radioButtonChecked((HTMLInputElementImpl*)this, m_form); - } + else + if (isRadioButton() && !name().isEmpty() && isChecked()) + getDocument()->radioButtonChecked((HTMLInputElementImpl*)this, m_form); } HTMLElementImpl::insertedIntoTree(deep); diff --git a/WebCore/khtml/html/HTMLInputElementImpl.cpp b/WebCore/khtml/html/HTMLInputElementImpl.cpp index 515d973faed..a5643e694e3 100644 --- a/WebCore/khtml/html/HTMLInputElementImpl.cpp +++ b/WebCore/khtml/html/HTMLInputElementImpl.cpp @@ -91,7 +91,7 @@ void HTMLInputElementImpl::init() HTMLInputElementImpl::~HTMLInputElementImpl() { - if (getDocument()) getDocument()->deregisterMaintainsState(this); + getDocument()->deregisterMaintainsState(this); delete m_imageLoader; } @@ -132,13 +132,11 @@ void HTMLInputElementImpl::focus() { if ((m_type == TEXT || m_type == PASSWORD) && renderer() && renderer()->style()->appearance() == TextFieldAppearance) { DocumentImpl* doc = getDocument(); - if (doc) { - doc->updateLayout(); - if (isFocusable()) { - doc->setFocusNode(this); - select(); - doc->frame()->revealSelection(); - } + doc->updateLayout(); + if (isFocusable()) { + doc->setFocusNode(this); + select(); + doc->frame()->revealSelection(); } } else HTMLGenericFormElementImpl::focus(); diff --git a/WebCore/khtml/html/HTMLOptionElementImpl.cpp b/WebCore/khtml/html/HTMLOptionElementImpl.cpp index 82a873469e2..6c0cba9edac 100644 --- a/WebCore/khtml/html/HTMLOptionElementImpl.cpp +++ b/WebCore/khtml/html/HTMLOptionElementImpl.cpp @@ -57,7 +57,7 @@ DOMString HTMLOptionElementImpl::text() const DOMString text; // WinIE does not use the label attribute, so as a quirk, we ignore it. - if (getDocument() && !getDocument()->inCompatMode()) { + if (!getDocument()->inCompatMode()) { DOMString text = getAttribute(labelAttr); if (!text.isEmpty()) return text; diff --git a/WebCore/khtml/html/HTMLSelectElementImpl.cpp b/WebCore/khtml/html/HTMLSelectElementImpl.cpp index 2e03264e697..a4651d1dfa6 100644 --- a/WebCore/khtml/html/HTMLSelectElementImpl.cpp +++ b/WebCore/khtml/html/HTMLSelectElementImpl.cpp @@ -56,8 +56,7 @@ HTMLSelectElementImpl::HTMLSelectElementImpl(const QualifiedName& tagName, Docum HTMLSelectElementImpl::~HTMLSelectElementImpl() { - if (getDocument()) - getDocument()->deregisterMaintainsState(this); + getDocument()->deregisterMaintainsState(this); } bool HTMLSelectElementImpl::checkDTD(const NodeImpl* newChild) diff --git a/WebCore/khtml/html/HTMLTextAreaElementImpl.cpp b/WebCore/khtml/html/HTMLTextAreaElementImpl.cpp index 4b99548c051..170beb09afb 100644 --- a/WebCore/khtml/html/HTMLTextAreaElementImpl.cpp +++ b/WebCore/khtml/html/HTMLTextAreaElementImpl.cpp @@ -51,7 +51,7 @@ HTMLTextAreaElementImpl::HTMLTextAreaElementImpl(DocumentImpl *doc, HTMLFormElem HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl() { - if (getDocument()) getDocument()->deregisterMaintainsState(this); + getDocument()->deregisterMaintainsState(this); } DOMString HTMLTextAreaElementImpl::type() const diff --git a/WebCore/khtml/html/html_baseimpl.cpp b/WebCore/khtml/html/html_baseimpl.cpp index 900712d5380..1dfaff53910 100644 --- a/WebCore/khtml/html/html_baseimpl.cpp +++ b/WebCore/khtml/html/html_baseimpl.cpp @@ -164,8 +164,7 @@ void HTMLBodyElementImpl::insertedIntoDocument() // FIXME: perhaps this code should be in attach() instead of here - DocumentImpl *d = getDocument(); - FrameView *w = d ? d->view() : 0; + FrameView *w = getDocument()->view(); if (w && w->marginWidth() != -1) { QString s; s.sprintf("%d", w->marginWidth()); @@ -276,16 +275,12 @@ HTMLFrameElementImpl::~HTMLFrameElementImpl() bool HTMLFrameElementImpl::isURLAllowed(const AtomicString &URLString) const { - if (URLString.isEmpty()) { + if (URLString.isEmpty()) return true; - } - DocumentImpl *d = getDocument(); - FrameView *w = d ? d->view() : 0; - - if (!w) { + FrameView *w = getDocument()->view(); + if (!w) return false; - } KURL newURL(getDocument()->completeURL(URLString.qstring())); newURL.setRef(QString::null); @@ -321,8 +316,7 @@ bool HTMLFrameElementImpl::isURLAllowed(const AtomicString &URLString) const void HTMLFrameElementImpl::openURL() { - DocumentImpl *d = getDocument(); - FrameView *w = d ? d->view() : 0; + FrameView *w = getDocument()->view(); if (!w) return; @@ -604,21 +598,19 @@ void HTMLFrameElementImpl::setSrc(const DOMString &value) int HTMLFrameElementImpl::frameWidth() const { - DocumentImpl* d = getDocument(); - if (!d || !renderer()) + if (!renderer()) return 0; - d->updateLayoutIgnorePendingStylesheets(); + getDocument()->updateLayoutIgnorePendingStylesheets(); return renderer()->width(); } int HTMLFrameElementImpl::frameHeight() const { - DocumentImpl* d = getDocument(); - if (!d || !renderer()) + if (!renderer()) return 0; - d->updateLayoutIgnorePendingStylesheets(); + getDocument()->updateLayoutIgnorePendingStylesheets(); return renderer()->height(); } diff --git a/WebCore/khtml/html/html_imageimpl.cpp b/WebCore/khtml/html/html_imageimpl.cpp index c783387f2fd..407b0df004f 100644 --- a/WebCore/khtml/html/html_imageimpl.cpp +++ b/WebCore/khtml/html/html_imageimpl.cpp @@ -49,8 +49,7 @@ HTMLImageLoader::~HTMLImageLoader() { if (m_image) m_image->deref(this); - if (m_element->getDocument()) - m_element->getDocument()->removeImage(this); + m_element->getDocument()->removeImage(this); } void HTMLImageLoader::setLoadingImage(CachedImage *loadingImage) @@ -66,7 +65,7 @@ void HTMLImageLoader::updateFromElement() // down the raw HTML parsing case by loading images we don't intend to display. ElementImpl* elem = element(); DocumentImpl* doc = elem->getDocument(); - if (!doc || !doc->renderer()) + if (!doc->renderer()) return; AtomicString attr = elem->getAttribute(elem->hasLocalName(objectTag) ? dataAttr : srcAttr); @@ -105,13 +104,12 @@ void HTMLImageLoader::notifyFinished(CachedObject *image) { m_imageComplete = true; ElementImpl* elem = element(); - if (DocumentImpl* doc = elem->getDocument()) { - doc->dispatchImageLoadEventSoon(this); + DocumentImpl* doc = elem->getDocument(); + doc->dispatchImageLoadEventSoon(this); #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!doc->ownerElement()) printf("Image loaded at %d\n", doc->elapsedTime()); #endif - } if (RenderImage* renderer = static_cast(elem->renderer())) renderer->setCachedImage(m_image); } @@ -271,12 +269,11 @@ int HTMLImageElementImpl::width(bool ignorePendingStylesheets) const return m_imageLoader.image()->imageSize().width(); } - if (DocumentImpl* doc = getDocument()) { - if (ignorePendingStylesheets) - doc->updateLayoutIgnorePendingStylesheets(); - else - doc->updateLayout(); - } + DocumentImpl* doc = getDocument(); + if (ignorePendingStylesheets) + doc->updateLayoutIgnorePendingStylesheets(); + else + doc->updateLayout(); return renderer() ? renderer()->contentWidth() : 0; } @@ -295,12 +292,11 @@ int HTMLImageElementImpl::height(bool ignorePendingStylesheets) const return m_imageLoader.image()->imageSize().height(); } - if (DocumentImpl* doc = getDocument()) { - if (ignorePendingStylesheets) - doc->updateLayoutIgnorePendingStylesheets(); - else - doc->updateLayout(); - } + DocumentImpl* doc = getDocument(); + if (ignorePendingStylesheets) + doc->updateLayoutIgnorePendingStylesheets(); + else + doc->updateLayout(); return renderer() ? renderer()->contentHeight() : 0; } @@ -457,8 +453,7 @@ HTMLMapElementImpl::HTMLMapElementImpl(DocumentImpl *doc) HTMLMapElementImpl::~HTMLMapElementImpl() { - if (getDocument()) - getDocument()->removeImageMap(this); + getDocument()->removeImageMap(this); } bool HTMLMapElementImpl::checkDTD(const NodeImpl* newChild) diff --git a/WebCore/khtml/html/html_inlineimpl.cpp b/WebCore/khtml/html/html_inlineimpl.cpp index 200038b0ce4..f53dd542fc5 100644 --- a/WebCore/khtml/html/html_inlineimpl.cpp +++ b/WebCore/khtml/html/html_inlineimpl.cpp @@ -168,7 +168,7 @@ void HTMLAnchorElementImpl::defaultEventHandler(EventImpl *evt) } } if (!evt->defaultPrevented()) { - if (getDocument() && getDocument()->frame()) + if (getDocument()->frame()) getDocument()->frame()->urlSelected(url, utarget); } evt->setDefaultHandled(); diff --git a/WebCore/khtml/html/htmltokenizer.cpp b/WebCore/khtml/html/htmltokenizer.cpp index 011b6b0fe0b..23f36f649a9 100644 --- a/WebCore/khtml/html/htmltokenizer.cpp +++ b/WebCore/khtml/html/htmltokenizer.cpp @@ -1719,10 +1719,10 @@ void HTMLTokenizer::notifyFinished(CachedObject */*finishedObj*/) #endif if (errorOccurred) - n->dispatchHTMLEvent(errorEvent, false, false); + EventTargetNodeCast(n.get())->dispatchHTMLEvent(errorEvent, false, false); else { m_state = scriptExecution(scriptSource.qstring(), m_state, cachedScriptUrl); - n->dispatchHTMLEvent(loadEvent, false, false); + EventTargetNodeCast(n.get())->dispatchHTMLEvent(loadEvent, false, false); } // The state of pendingScripts.isEmpty() can change inside the scriptExecution() diff --git a/WebCore/ksvg2/svg/SVGAnimateColorElementImpl.cpp b/WebCore/ksvg2/svg/SVGAnimateColorElementImpl.cpp index 9cf44e9a10d..78da48ce331 100644 --- a/WebCore/ksvg2/svg/SVGAnimateColorElementImpl.cpp +++ b/WebCore/ksvg2/svg/SVGAnimateColorElementImpl.cpp @@ -128,10 +128,8 @@ void SVGAnimateColorElementImpl::handleTimerEvent(double timePercentage) } } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); - m_connected = true; - } + getDocument()->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); + m_connected = true; return; } @@ -222,10 +220,8 @@ void SVGAnimateColorElementImpl::handleTimerEvent(double timePercentage) return; } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); - m_connected = false; - } + getDocument()->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); + m_connected = false; // Reset... m_currentItem = -1; diff --git a/WebCore/ksvg2/svg/SVGAnimateElementImpl.cpp b/WebCore/ksvg2/svg/SVGAnimateElementImpl.cpp index 950759ddd93..549dc93dc1f 100644 --- a/WebCore/ksvg2/svg/SVGAnimateElementImpl.cpp +++ b/WebCore/ksvg2/svg/SVGAnimateElementImpl.cpp @@ -118,10 +118,8 @@ void SVGAnimateElementImpl::handleTimerEvent(double timePercentage) } } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); - m_connected = true; - } + getDocument()->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); + m_connected = true; return; } @@ -204,10 +202,8 @@ void SVGAnimateElementImpl::handleTimerEvent(double timePercentage) return; } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); - m_connected = false; - } + getDocument()->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); + m_connected = false; // Reset... m_currentItem = -1; diff --git a/WebCore/ksvg2/svg/SVGAnimateTransformElementImpl.cpp b/WebCore/ksvg2/svg/SVGAnimateTransformElementImpl.cpp index 3118f55eb0e..19833a753e8 100644 --- a/WebCore/ksvg2/svg/SVGAnimateTransformElementImpl.cpp +++ b/WebCore/ksvg2/svg/SVGAnimateTransformElementImpl.cpp @@ -168,10 +168,8 @@ void SVGAnimateTransformElementImpl::handleTimerEvent(double timePercentage) } } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); - m_connected = true; - } + getDocument()->accessSVGExtensions()->timeScheduler()->connectIntervalTimer(this); + m_connected = true; return; } @@ -322,10 +320,8 @@ void SVGAnimateTransformElementImpl::handleTimerEvent(double timePercentage) return; } - if (DocumentImpl *doc = getDocument()) { - doc->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); - m_connected = false; - } + getDocument()->accessSVGExtensions()->timeScheduler()->disconnectIntervalTimer(this); + m_connected = false; // Reset... m_currentItem = -1; diff --git a/WebCore/ksvg2/svg/SVGAnimationElementImpl.cpp b/WebCore/ksvg2/svg/SVGAnimationElementImpl.cpp index f4fcf00dc5a..5b85561d9c1 100644 --- a/WebCore/ksvg2/svg/SVGAnimationElementImpl.cpp +++ b/WebCore/ksvg2/svg/SVGAnimationElementImpl.cpp @@ -416,8 +416,7 @@ double SVGAnimationElementImpl::parseClockValue(const QString &data) const void SVGAnimationElementImpl::closeRenderer() { - if (DocumentImpl *doc = getDocument()) - doc->accessSVGExtensions()->timeScheduler()->addTimer(this, lround(getStartTime())); + getDocument()->accessSVGExtensions()->timeScheduler()->addTimer(this, lround(getStartTime())); } DOMString SVGAnimationElementImpl::targetAttribute() const diff --git a/WebCore/ksvg2/svg/SVGDOMImplementationImpl.cpp b/WebCore/ksvg2/svg/SVGDOMImplementationImpl.cpp index 9cabc0d31a8..4cb130503f8 100644 --- a/WebCore/ksvg2/svg/SVGDOMImplementationImpl.cpp +++ b/WebCore/ksvg2/svg/SVGDOMImplementationImpl.cpp @@ -25,6 +25,12 @@ #if SVG_SUPPORT #include "SVGDOMImplementationImpl.h" +#include +#include +#include +#include +#include + #include "DocumentImpl.h" #include "DocumentTypeImpl.h" #include "ExceptionCode.h" @@ -34,11 +40,6 @@ #include "SVGSVGElementImpl.h" #include "css_stylesheetimpl.h" #include "ksvg.h" -#include -#include -#include -#include -#include using namespace WebCore; diff --git a/WebCore/ksvg2/svg/SVGDocumentImpl.cpp b/WebCore/ksvg2/svg/SVGDocumentImpl.cpp index 7eb48426779..44036f66117 100644 --- a/WebCore/ksvg2/svg/SVGDocumentImpl.cpp +++ b/WebCore/ksvg2/svg/SVGDocumentImpl.cpp @@ -158,10 +158,10 @@ void SVGDocumentImpl::dispatchRecursiveEvent(EventImpl *event, NodeImpl *obj) dispatchRecursiveEvent(event, n->lastChild()); // Dispatch, locally - n->dispatchEvent(event, ec); + EventTargetNodeCast(n)->dispatchEvent(event, ec); } else - n->dispatchEvent(event, ec); + EventTargetNodeCast(n)->dispatchEvent(event, ec); } } diff --git a/WebCore/ksvg2/svg/SVGDocumentImpl.h b/WebCore/ksvg2/svg/SVGDocumentImpl.h index 0e699a925b5..0a4ec18db17 100644 --- a/WebCore/ksvg2/svg/SVGDocumentImpl.h +++ b/WebCore/ksvg2/svg/SVGDocumentImpl.h @@ -26,12 +26,13 @@ #include -#include "DocumentImpl.h" #include #include - +#include #include +#include "DocumentImpl.h" + namespace WebCore { class SVGElementImpl; @@ -71,8 +72,8 @@ namespace WebCore { virtual CSSStyleSelector *createStyleSelector(const QString &); private: - void dispatchUIEvent(NodeImpl *target, const AtomicString &type); - void dispatchMouseEvent(NodeImpl *target, const AtomicString &type); + void dispatchUIEvent(EventTargetImpl *target, const AtomicString &type); + void dispatchMouseEvent(EventTargetImpl *target, const AtomicString &type); //