diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index b504be9f2864ef426bf0a24af636f031dbbabbe6..e22c9e7b7cc86e09a75ab9d1c78ba089d9818220 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 00ca161234b5712eed90b9ad62fd5a0a89829c68..05b907fc8f1f5069b56c0f6a9e975d32cb2611bd 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 4006d1448822be66e9ad425b92c2e573b8e6e929..4478a01ec70a28dad65ffe3d330158a169f535ab 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 6997642a90d3b09920bc3f1ae1b76a47f91f6c75..a906771425c2c25ff4562dba2048934ccd1aedee 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 2732c264b845142dcc8f3296edeaa5371c6b631b..4ac8cefc59ebb518836c77719ab51fbcbf46a6ca 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 2ffaedd98c8c073e5a7292bbfa165acafefc47de..5e37d081d327c337191053c898dc39fe6c1e90bf 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 1ef77b503d18d24bd305849cd6d85f5363bfb7fc..b81f4817466811a68e0dfd60d8d305eee32ca1e8 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 e37126b8132d97b2a00c2896c50fba48f54259bd..89b0d817f3ac5958987f556664c853b957279aef 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 26ec20ef910cbd29d266cefe5cefd1c2d6f0f353..9e473214522d214eefc54c2f78a3c5fa73e52bb8 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 a366c56b41f11ee736ecc7bfd3317df4778777b1..1a2434dde3728d36b63045642208853a4e383532 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 7f6d27bf4f6fdc299c37c30aed43526a1622b66c..890c07399621903b517a772f56a48d17eba291d6 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 0ca150dbf54b2d71e03ed0c6c409c37a0ad08a57..d128db65aa890a5c42ed8b8206cc43c5649613a9 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 dc6902611bdde4c7f0706056ea46993ee5040f7d..93df592c188924059d720132d9cb48475191d737 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 743493d4eba284f458e9500c60beae6092bf39bc..bf20e96b97b8a0beec4c40cc2fcae24a3341a879 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 7dd64085937ef059da045ff060a1acdb38ef4dac..3113e9761479102eea3f683e9028f8f13a701c47 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 ef045b2f68ef874ef7a82c99cfeada43051261bb..659ec69116caeba67154e661030db89d93126954 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 662e9897beabab64f4cd4b2ec760f473d1051261..5dfd7b777fef843194b8cba3f8cc85d5d5c06c7c 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 b876667259519891ba446bda392b555154c724a9..d73eab8c8c7c1c4ee7e82e16e81696e8d28bad4b 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 eede574678cdf8dd7774fe52d6a66981e489739d..68126fe04a08df88636002138000256b612fba2d 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 6a2236b009d0ee307c32dec2d2a411c6ff0b3f8e..1dacb3a205dca7a7135b50ce22bcba946a55a68d 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 c5106e2514240560d5e84debe7980921a9678356..8c71e6be0fe498e6b25af17f5bfd75d26ef2befd 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 0000000000000000000000000000000000000000..f0de17ee43dc1e1bb9b24974fd12f71189381dd2 --- /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 0000000000000000000000000000000000000000..7b37ee596d33e54d387552ec21f9a71974a488e6 --- /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 63ceb0c39986f622bea41c7bee9b128f25be2444..db00d50c978bdfe024d01165572e543986433609 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 8becb94c811f44dc6042bd33e185d93bb76c0ae2..7e3b4edfca8f5a4074a860047b09317184ad7f82 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 ea31a41a907e8e767a2e5b9efcee612c3f5505ac..036d5a6813e1269ef1ee910ff18f820c8e28c4ea 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 848ebbd86b14ef3f7aa7da3b376bbfbf27d0e136..58a612051a9fa68bc2099538e4be8990f8e1e5ab 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 a88f436a7d06fea793c3f1781894cc252101b7d3..dada5281a642b76ebe8bf037ed975fb9120cccd0 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 5bbdf453c3a8085a0ae6888b01fe797608bac2cb..84d1fc00a3521d5917bce19ee1349fcc7a453214 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 11c322057412684183cb98c90686f3947883310b..4dd72f04244f31586d9ad31c4b36040bd0a44982 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 c5c33bad9c7b4bba4081d2c01a5022356ed16e5b..0d6d22a2d3080a9a79f6ae7dbbbf227e0151e8ce 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 c6461aab5bc134f513c00c9b3b94da9218a27b7b..fabbcb9c4fb8268015fcefacf9483fbcad4d5896 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 3286583030ce4c5bbc1e4a2f5ee252e83e9489f2..fc3088325d1c23b57f8376d5e238af0ef305f11a 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 7ad5735bbe0c9d568539f2a20977a54471892514..7161611ddecb882892f67031a5b9ade089643f5d 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 644f33d79c2ae605c82a3211cad819e74c3d9e72..23dc75aabf41ab83d5f053bc9835cc2cbcbe200b 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 e80e5aa486f20d2311625f6ee71a63c28a2ac4a6..f1685e280d752168b570b59897d3bb6b1e26a835 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 4a4c2334713a089ac2f6cf666d909cf1cab99509..fe56b729b90e11fd8d383ecd9087958721c3869f 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 d996582ac3ad4dbe64090fb5c55b9e1cb3a41bf9..f1f449beea1452bd38ec5e073c89d3dbf0de8ae8 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 5eed58c83c5e3acff4af14249ccf96d2e052310f..5b82db0ac283361acc9c83d9464cb11417c45dad 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 294e4f048396305bffa52be6b37f7e0ad651f201..0a36e19ef701f1204fd716eeb7b93f13693dd870 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 515d973faedbad3808080866911d8d3236fcc4d0..a5643e694e3a28a9e16213122596479c453f0817 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 82a873469e26e951c96f8671c681d4e5fc664cc1..6c0cba9edacd4bbc5780e61159c574db466fea4e 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 2e03264e6970a445d21c6dac9e4a0b9160011267..a4651d1dfa6b4bec949f9d8a46684b440c633adb 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 4b99548c05158b93f21ce3f870bf4af0bc3ec593..170beb09afb41071ccd29b959b99f599f82fccbb 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 900712d53804932f271be03effb278f4dbd78a86..1dfaff53910d1ea5e9d59d2fa2b190e44dc9892a 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 c783387f2fdcf6646ba6706e7408651d108c7082..407b0df004ffe960a792ffc7306945269eca704e 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 200038b0ce47e3e2a1d6079e5cbaea28ac7ed66a..f53dd542fc5b7274217fc7ceff83fc64e9a1ff2d 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 011b6b0fe0b6ed0d363c739cdf3be5a193a7dcb2..23f36f649a9caf04818feb748757443b6ca0fe0d 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 9cf44e9a10df62eb749a7627b04af6d040186fdd..78da48ce331e19abeb4bb5b966597653e96884f5 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 950759ddd9317c5ea44ce85a12c75bae880a8d8b..549dc93dc1f6efc92650c1541e8c6778e26911d7 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 3118f55eb0efc130799f66fa2f3e842ab662e812..19833a753e89231f2f4f58f305aa48e416c38fe9 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 f4fcf00dc5a1e242d899e1da44e33e95de5d14d1..5b85561d9c1de3ba0a993e87a44405fc580fa795 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 9cabc0d31a881f625b88e7bd525df3b8132fe9a2..4cb130503f83b6d3b50ee3d24bb6516711e54adb 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 7eb484267791013461d78a31bc6ae5df46ec1ae2..44036f66117420feffab297db697d148d8c49659 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 0e699a925b530a30eb6ca4209a0e418d788141ba..0a4ec18db177899f3ceea93e5c93baed1e78a780 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); //