Node.cpp 76.1 KB
Newer Older
darin's avatar
darin committed
1
/*
kocienda's avatar
kocienda committed
2 3
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
kocienda's avatar
kocienda committed
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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
ddkilzer's avatar
ddkilzer committed
21 22
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
kocienda's avatar
kocienda committed
23 24
 */

mjs's avatar
mjs committed
25
#include "config.h"
darin's avatar
darin committed
26
#include "Node.h"
darin's avatar
darin committed
27

28
#include "AXObjectCache.h"
darin@apple.com's avatar
darin@apple.com committed
29
#include "Attr.h"
30
#include "Attribute.h"
31
#include "BeforeLoadEvent.h"
32
#include "ChildListMutationScope.h"
33 34
#include "Chrome.h"
#include "ChromeClient.h"
35
#include "CSSParser.h"
dsmith@webkit.org's avatar
dsmith@webkit.org committed
36
#include "CSSRule.h"
37
#include "CSSSelector.h"
38
#include "CSSSelectorList.h"
dsmith@webkit.org's avatar
dsmith@webkit.org committed
39 40
#include "CSSStyleRule.h"
#include "CSSStyleSheet.h"
darin's avatar
darin committed
41
#include "ChildNodeList.h"
weinig@apple.com's avatar
weinig@apple.com committed
42
#include "ClassNodeList.h"
43
#include "ContainerNodeAlgorithms.h"
44
#include "ContextMenuController.h"
darin's avatar
darin committed
45
#include "DOMImplementation.h"
46
#include "DOMSettableTokenList.h"
darin's avatar
darin committed
47
#include "Document.h"
48
#include "DocumentFragment.h"
49
#include "DocumentType.h"
darin's avatar
darin committed
50
#include "Element.h"
51
#include "ElementIterator.h"
52
#include "ElementRareData.h"
53
#include "Event.h"
54
#include "EventContext.h"
55
#include "EventDispatchMediator.h"
56
#include "EventDispatcher.h"
57 58 59 60
#include "EventException.h"
#include "EventHandler.h"
#include "EventListener.h"
#include "EventNames.h"
darin's avatar
darin committed
61
#include "ExceptionCode.h"
62
#include "ExceptionCodePlaceholder.h"
63
#include "FlowThreadController.h"
darin's avatar
darin committed
64
#include "Frame.h"
65
#include "FrameView.h"
66
#include "HTMLElement.h"
67
#include "HTMLFrameOwnerElement.h"
68
#include "HTMLImageElement.h"
weinig's avatar
weinig committed
69
#include "HTMLNames.h"
70
#include "HTMLStyleElement.h"
71
#include "InsertionPoint.h"
72
#include "InspectorCounters.h"
73
#include "KeyboardEvent.h"
74
#include "LabelsNodeList.h"
75
#include "LiveNodeList.h"
ggaren's avatar
ggaren committed
76
#include "Logging.h"
77 78
#include "MouseEvent.h"
#include "MutationEvent.h"
weinig@apple.com's avatar
weinig@apple.com committed
79
#include "NameNodeList.h"
80
#include "NamedNodeMap.h"
81
#include "NodeRareData.h"
82
#include "NodeTraversal.h"
83 84 85
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
ap@webkit.org's avatar
ap@webkit.org committed
86
#include "ProcessingInstruction.h"
87
#include "ProgressEvent.h"
88
#include "RadioNodeList.h"
89
#include "RegisteredEventListener.h"
90
#include "RenderBlock.h"
91
#include "RenderBox.h"
92
#include "RenderTextControl.h"
93
#include "RenderView.h"
94
#include "ScopedEventQueue.h"
95
#include "SelectorQuery.h"
96
#include "Settings.h"
97
#include "ShadowRoot.h"
98
#include "StorageEvent.h"
99
#include "StyleResolver.h"
100
#include "TagNodeList.h"
101
#include "TemplateContentDocumentFragment.h"
darin's avatar
darin committed
102
#include "Text.h"
103
#include "TextEvent.h"
104
#include "TouchEvent.h"
105
#include "TreeScopeAdopter.h"
106 107 108
#include "UIEvent.h"
#include "UIEventWithKeyState.h"
#include "WheelEvent.h"
109
#include "WindowEventContext.h"
rwlbuis's avatar
rwlbuis committed
110
#include "XMLNames.h"
111
#include "htmlediting.h"
112
#include <wtf/HashSet.h>
113
#include <wtf/PassOwnPtr.h>
114
#include <wtf/RefCountedLeakCounter.h>
115
#include <wtf/Vector.h>
116
#include <wtf/text/CString.h>
117
#include <wtf/text/StringBuilder.h>
harrison's avatar
harrison committed
118

119 120 121 122
#if ENABLE(GESTURE_EVENTS)
#include "GestureEvent.h"
#endif

123 124 125 126
#if ENABLE(INDIE_UI)
#include "UIRequestEvent.h"
#endif

127 128 129 130
#if ENABLE(INSPECTOR)
#include "InspectorController.h"
#endif

ggaren@apple.com's avatar
ggaren@apple.com committed
131
#include <runtime/VM.h>
132
#include <runtime/Operations.h>
133

134 135
using namespace std;

darin's avatar
darin committed
136
namespace WebCore {
darin's avatar
darin committed
137 138 139

using namespace HTMLNames;

ggaren's avatar
ggaren committed
140 141
bool Node::isSupported(const String& feature, const String& version)
{
weinig@apple.com's avatar
weinig@apple.com committed
142
    return DOMImplementation::hasFeature(feature, version);
ggaren's avatar
ggaren committed
143 144
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
#if DUMP_NODE_STATISTICS
static HashSet<Node*> liveNodeSet;
#endif

void Node::dumpStatistics()
{
#if DUMP_NODE_STATISTICS
    size_t nodesWithRareData = 0;

    size_t elementNodes = 0;
    size_t attrNodes = 0;
    size_t textNodes = 0;
    size_t cdataNodes = 0;
    size_t commentNodes = 0;
    size_t entityReferenceNodes = 0;
    size_t entityNodes = 0;
    size_t piNodes = 0;
    size_t documentNodes = 0;
    size_t docTypeNodes = 0;
    size_t fragmentNodes = 0;
    size_t notationNodes = 0;
    size_t xpathNSNodes = 0;
167
    size_t shadowRootNodes = 0;
168 169 170 171 172

    HashMap<String, size_t> perTagCount;

    size_t attributes = 0;
    size_t attributesWithAttr = 0;
173
    size_t elementsWithAttributeStorage = 0;
174
    size_t elementsWithRareData = 0;
175
    size_t elementsWithNamedNodeMap = 0;
176

177
    for (HashSet<Node*>::iterator it = liveNodeSet.begin(); it != liveNodeSet.end(); ++it) {
178 179
        Node* node = *it;

180
        if (node->hasRareData()) {
181
            ++nodesWithRareData;
182 183 184 185 186 187
            if (node->isElementNode()) {
                ++elementsWithRareData;
                if (toElement(node)->hasNamedNodeMap())
                    ++elementsWithNamedNodeMap;
            }
        }
188 189 190 191 192 193

        switch (node->nodeType()) {
            case ELEMENT_NODE: {
                ++elementNodes;

                // Tag stats
194
                Element* element = toElement(node);
195 196
                HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
                if (!result.isNewEntry)
197
                    result.iterator->value++;
198

199 200
                if (ElementData* elementData = element->elementData()) {
                    attributes += elementData->length();
201
                    ++elementsWithAttributeStorage;
202
                    for (unsigned i = 0; i < elementData->length(); ++i) {
203 204
                        Attribute& attr = elementData->attributeAt(i);
                        if (attr.attr())
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
                            ++attributesWithAttr;
                    }
                }
                break;
            }
            case ATTRIBUTE_NODE: {
                ++attrNodes;
                break;
            }
            case TEXT_NODE: {
                ++textNodes;
                break;
            }
            case CDATA_SECTION_NODE: {
                ++cdataNodes;
                break;
            }
            case COMMENT_NODE: {
                ++commentNodes;
                break;
            }
            case ENTITY_REFERENCE_NODE: {
                ++entityReferenceNodes;
                break;
            }
            case ENTITY_NODE: {
                ++entityNodes;
                break;
            }
            case PROCESSING_INSTRUCTION_NODE: {
                ++piNodes;
                break;
            }
            case DOCUMENT_NODE: {
                ++documentNodes;
                break;
            }
            case DOCUMENT_TYPE_NODE: {
                ++docTypeNodes;
                break;
            }
            case DOCUMENT_FRAGMENT_NODE: {
247 248 249 250
                if (node->isShadowRoot())
                    ++shadowRootNodes;
                else
                    ++fragmentNodes;
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
                break;
            }
            case NOTATION_NODE: {
                ++notationNodes;
                break;
            }
            case XPATH_NAMESPACE_NODE: {
                ++xpathNSNodes;
                break;
            }
        }
    }

    printf("Number of Nodes: %d\n\n", liveNodeSet.size());
    printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);

267
    printf("NodeType distribution:\n");
268 269 270 271 272 273 274 275 276 277 278 279 280
    printf("  Number of Element nodes: %zu\n", elementNodes);
    printf("  Number of Attribute nodes: %zu\n", attrNodes);
    printf("  Number of Text nodes: %zu\n", textNodes);
    printf("  Number of CDATASection nodes: %zu\n", cdataNodes);
    printf("  Number of Comment nodes: %zu\n", commentNodes);
    printf("  Number of EntityReference nodes: %zu\n", entityReferenceNodes);
    printf("  Number of Entity nodes: %zu\n", entityNodes);
    printf("  Number of ProcessingInstruction nodes: %zu\n", piNodes);
    printf("  Number of Document nodes: %zu\n", documentNodes);
    printf("  Number of DocumentType nodes: %zu\n", docTypeNodes);
    printf("  Number of DocumentFragment nodes: %zu\n", fragmentNodes);
    printf("  Number of Notation nodes: %zu\n", notationNodes);
    printf("  Number of XPathNS nodes: %zu\n", xpathNSNodes);
281
    printf("  Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
282 283

    printf("Element tag name distibution:\n");
284
    for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
285
        printf("  Number of <%s> tags: %zu\n", it->key.utf8().data(), it->value);
286

287
    printf("Attributes:\n");
288 289
    printf("  Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
    printf("  Number of Attributes with an Attr: %zu\n", attributesWithAttr);
290
    printf("  Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
291
    printf("  Number of Elements with RareData: %zu\n", elementsWithRareData);
292
    printf("  Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
293 294 295
#endif
}

296 297
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode"));
DEFINE_DEBUG_ONLY_GLOBAL(HashSet<Node*>, ignoreSet, );
ggaren's avatar
ggaren committed
298

299
#ifndef NDEBUG
ggaren's avatar
ggaren committed
300 301 302 303 304 305 306
static bool shouldIgnoreLeaks = false;
#endif

void Node::startIgnoringLeaks()
{
#ifndef NDEBUG
    shouldIgnoreLeaks = true;
darin's avatar
darin committed
307
#endif
ggaren's avatar
ggaren committed
308 309 310 311 312 313 314 315
}

void Node::stopIgnoringLeaks()
{
#ifndef NDEBUG
    shouldIgnoreLeaks = false;
#endif
}
mjs's avatar
mjs committed
316

317
void Node::trackForDebugging()
318
{
mjs's avatar
mjs committed
319
#ifndef NDEBUG
ggaren's avatar
ggaren committed
320 321 322
    if (shouldIgnoreLeaks)
        ignoreSet.add(this);
    else
323
        nodeCounter.increment();
mjs's avatar
mjs committed
324
#endif
325

326 327 328
#if DUMP_NODE_STATISTICS
    liveNodeSet.add(this);
#endif
mjs's avatar
mjs committed
329 330
}

darin's avatar
darin committed
331
Node::~Node()
kocienda's avatar
kocienda committed
332
{
mjs's avatar
mjs committed
333
#ifndef NDEBUG
334
    if (!ignoreSet.remove(this))
335
        nodeCounter.decrement();
mjs's avatar
mjs committed
336
#endif
337 338 339 340 341

#if DUMP_NODE_STATISTICS
    liveNodeSet.remove(this);
#endif

342
    ASSERT(!renderer());
343 344 345
    ASSERT(!parentNode());
    ASSERT(!m_previous);
    ASSERT(!m_next);
346

347 348
    if (hasRareData())
        clearRareData();
weinig@apple.com's avatar
weinig@apple.com committed
349

350 351 352
    if (!isContainerNode()) {
        if (Document* document = documentInternal())
            willBeDeletedFrom(document);
353
    }
354

355
    m_treeScope->selfOnlyDeref();
356 357

    InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
kocienda's avatar
kocienda committed
358 359
}

360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
void Node::willBeDeletedFrom(Document* document)
{
    if (hasEventTargetData()) {
#if ENABLE(TOUCH_EVENT_TRACKING)
        if (document)
            document->didRemoveEventTargetNode(this);
#endif
        clearEventTargetData();
    }

    if (document) {
        if (AXObjectCache* cache = document->existingAXObjectCache())
            cache->remove(this);
    }
}

376
NodeRareData* Node::rareData() const
377 378
{
    ASSERT(hasRareData());
379
    return static_cast<NodeRareData*>(m_data.m_rareData);
380 381
}

382
NodeRareData& Node::ensureRareData()
383 384
{
    if (hasRareData())
385
        return *rareData();
386

387 388
    NodeRareData* data;
    if (isElementNode())
389
        data = ElementRareData::create(toRenderElement(m_data.m_renderer)).leakPtr();
390 391
    else
        data = NodeRareData::create(m_data.m_renderer).leakPtr();
392
    ASSERT(data);
393

394
    m_data.m_rareData = data;
395
    setFlag(HasRareDataFlag);
396
    return *data;
397
}
398

399 400 401
void Node::clearRareData()
{
    ASSERT(hasRareData());
402
    ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
403

404
    RenderObject* renderer = m_data.m_rareData->renderer();
405 406 407
    if (isElementNode())
        delete static_cast<ElementRareData*>(m_data.m_rareData);
    else
408
        delete static_cast<NodeRareData*>(m_data.m_rareData);
409
    m_data.m_renderer = renderer;
410
    clearFlag(HasRareDataFlag);
411 412
}

413 414 415 416 417
Node* Node::toNode()
{
    return this;
}

418 419 420 421 422 423 424 425 426
HTMLInputElement* Node::toInputElement()
{
    // If one of the below ASSERTs trigger, you are calling this function
    // directly or indirectly from a constructor or destructor of this object.
    // Don't do this!
    ASSERT(!(isHTMLElement() && hasTagName(inputTag)));
    return 0;
}

darin's avatar
darin committed
427
String Node::nodeValue() const
kocienda's avatar
kocienda committed
428
{
429
    return String();
kocienda's avatar
kocienda committed
430 431
}

darin's avatar
darin committed
432
void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
kocienda's avatar
kocienda committed
433
{
434
    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
adele's avatar
adele committed
435
    if (isReadOnlyNode()) {
darin's avatar
darin committed
436
        ec = NO_MODIFICATION_ALLOWED_ERR;
437 438 439
        return;
    }

440
    // By default, setting nodeValue has no effect.
kocienda's avatar
kocienda committed
441 442
}

darin's avatar
darin committed
443
PassRefPtr<NodeList> Node::childNodes()
kocienda's avatar
kocienda committed
444
{
445
    return ensureRareData().ensureNodeLists().ensureChildNodeList(this);
kocienda's avatar
kocienda committed
446 447
}

darin's avatar
darin committed
448
Node *Node::lastDescendant() const
kocienda's avatar
kocienda committed
449
{
darin's avatar
darin committed
450
    Node *n = const_cast<Node *>(this);
kocienda's avatar
kocienda committed
451 452 453 454 455
    while (n && n->lastChild())
        n = n->lastChild();
    return n;
}

justing's avatar
justing committed
456 457 458 459 460 461 462 463
Node* Node::firstDescendant() const
{
    Node *n = const_cast<Node *>(this);
    while (n && n->firstChild())
        n = n->firstChild();
    return n;
}

464
bool Node::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, AttachBehavior attachBehavior)
kocienda's avatar
kocienda committed
465
{
466 467 468 469
    if (!isContainerNode()) {
        ec = HIERARCHY_REQUEST_ERR;
        return false;
    }
470
    return toContainerNode(this)->insertBefore(newChild, refChild, ec, attachBehavior);
kocienda's avatar
kocienda committed
471 472
}

473
bool Node::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, AttachBehavior attachBehavior)
kocienda's avatar
kocienda committed
474
{
475 476 477 478
    if (!isContainerNode()) {
        ec = HIERARCHY_REQUEST_ERR;
        return false;
    }
479
    return toContainerNode(this)->replaceChild(newChild, oldChild, ec, attachBehavior);
kocienda's avatar
kocienda committed
480 481
}

482
bool Node::removeChild(Node* oldChild, ExceptionCode& ec)
kocienda's avatar
kocienda committed
483
{
484 485 486 487 488
    if (!isContainerNode()) {
        ec = NOT_FOUND_ERR;
        return false;
    }
    return toContainerNode(this)->removeChild(oldChild, ec);
kocienda's avatar
kocienda committed
489 490
}

491
bool Node::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, AttachBehavior attachBehavior)
kocienda's avatar
kocienda committed
492
{
493 494 495 496
    if (!isContainerNode()) {
        ec = HIERARCHY_REQUEST_ERR;
        return false;
    }
497
    return toContainerNode(this)->appendChild(newChild, ec, attachBehavior);
kocienda's avatar
kocienda committed
498 499
}

darin's avatar
darin committed
500
void Node::remove(ExceptionCode& ec)
kocienda's avatar
kocienda committed
501
{
502 503
    if (ContainerNode* parent = parentNode())
        parent->removeChild(this, ec);
kocienda's avatar
kocienda committed
504 505
}

darin@apple.com's avatar
darin@apple.com committed
506 507 508
void Node::normalize()
{
    // Go through the subtree beneath us, normalizing all nodes. This means that
darin@apple.com's avatar
darin@apple.com committed
509
    // any two adjacent text nodes are merged and any empty text nodes are removed.
darin@apple.com's avatar
darin@apple.com committed
510 511 512 513

    RefPtr<Node> node = this;
    while (Node* firstChild = node->firstChild())
        node = firstChild;
darin@apple.com's avatar
darin@apple.com committed
514
    while (node) {
darin@apple.com's avatar
darin@apple.com committed
515 516
        NodeType type = node->nodeType();
        if (type == ELEMENT_NODE)
517
            toElement(node.get())->normalizeAttributes();
darin@apple.com's avatar
darin@apple.com committed
518 519 520 521

        if (node == this)
            break;

darin@apple.com's avatar
darin@apple.com committed
522
        if (type != TEXT_NODE) {
523
            node = NodeTraversal::nextPostOrder(node.get());
darin@apple.com's avatar
darin@apple.com committed
524 525 526
            continue;
        }

527
        RefPtr<Text> text = toText(node.get());
darin@apple.com's avatar
darin@apple.com committed
528 529 530 531

        // Remove empty text nodes.
        if (!text->length()) {
            // Care must be taken to get the next node before removing the current node.
532
            node = NodeTraversal::nextPostOrder(node.get());
533
            text->remove(IGNORE_EXCEPTION);
darin@apple.com's avatar
darin@apple.com committed
534 535 536 537 538
            continue;
        }

        // Merge text nodes.
        while (Node* nextSibling = node->nextSibling()) {
539
            if (nextSibling->nodeType() != TEXT_NODE)
darin@apple.com's avatar
darin@apple.com committed
540
                break;
541
            RefPtr<Text> nextText = toText(nextSibling);
darin@apple.com's avatar
darin@apple.com committed
542 543 544

            // Remove empty text nodes.
            if (!nextText->length()) {
545
                nextText->remove(IGNORE_EXCEPTION);
darin@apple.com's avatar
darin@apple.com committed
546
                continue;
darin@apple.com's avatar
darin@apple.com committed
547
            }
darin@apple.com's avatar
darin@apple.com committed
548 549 550

            // Both non-empty text nodes. Merge them.
            unsigned offset = text->length();
551
            text->appendData(nextText->data(), IGNORE_EXCEPTION);
552
            document().textNodesMerged(nextText.get(), offset);
553
            nextText->remove(IGNORE_EXCEPTION);
554
        }
darin@apple.com's avatar
darin@apple.com committed
555

556
        node = NodeTraversal::nextPostOrder(node.get());
557 558 559
    }
}

560
const AtomicString& Node::prefix() const
561 562
{
    // For nodes other than elements and attributes, the prefix is always null
563
    return nullAtom;
564 565
}

darin's avatar
darin committed
566
void Node::setPrefix(const AtomicString& /*prefix*/, ExceptionCode& ec)
kocienda's avatar
kocienda committed
567
{
568 569
    // The spec says that for nodes other than elements and attributes, prefix is always null.
    // It does not say what to do when the user tries to set the prefix on another type of
darin's avatar
darin committed
570
    // node, however Mozilla throws a NAMESPACE_ERR exception.
darin's avatar
darin committed
571
    ec = NAMESPACE_ERR;
572 573
}

574
const AtomicString& Node::localName() const
575
{
eric@webkit.org's avatar
eric@webkit.org committed
576
    return nullAtom;
kocienda's avatar
kocienda committed
577 578
}

579
const AtomicString& Node::namespaceURI() const
darin's avatar
darin committed
580
{
581
    return nullAtom;
darin's avatar
darin committed
582 583
}

584
bool Node::isContentEditable(UserSelectAllTreatment treatment)
585
{
586
    document().updateStyleIfNeeded();
587
    return rendererIsEditable(Editable, treatment);
588 589
}

590 591
bool Node::isContentRichlyEditable()
{
592
    document().updateStyleIfNeeded();
593
    return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
594 595
}

596 597 598
void Node::inspect()
{
#if ENABLE(INSPECTOR)
599 600
    if (document().page())
        document().page()->inspectorController()->inspect(this);
601 602 603
#endif
}

604
bool Node::rendererIsEditable(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
kocienda's avatar
kocienda committed
605
{
606
    if (document().frame() && document().frame()->page() && document().frame()->page()->isEditable() && !containingShadowRoot())
607
        return true;
kocienda's avatar
kocienda committed
608

609 610 611
    if (isPseudoElement())
        return false;

612 613
    // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
    // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
614
    // would fire in the middle of Document::setFocusedElement().
615

616 617
    for (const Node* node = this; node; node = node->parentNode()) {
        if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
618 619 620
#if ENABLE(USERSELECT_ALL)
            // Elements with user-select: all style are considered atomic
            // therefore non editable.
621
            if (treatment == UserSelectAllIsAlwaysNonEditable && node->renderer()->style()->userSelect() == SELECT_ALL)
622
                return false;
623 624
#else
            UNUSED_PARAM(treatment);
625
#endif
626 627 628 629 630 631 632
            switch (node->renderer()->style()->userModify()) {
            case READ_ONLY:
                return false;
            case READ_WRITE:
                return true;
            case READ_WRITE_PLAINTEXT_ONLY:
                return editableLevel != RichlyEditable;
633
            }
634 635
            ASSERT_NOT_REACHED();
            return false;
636 637 638 639
        }
    }

    return false;
justing's avatar
justing committed
640 641
}

642 643 644 645 646 647 648 649 650 651
bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
{
    if (rendererIsEditable(editableLevel))
        return true;

    // FIXME: Respect editableLevel for ARIA editable elements.
    if (editableLevel == RichlyEditable)
        return false;

    ASSERT(AXObjectCache::accessibilityEnabled());
652
    ASSERT(document().existingAXObjectCache());
653

654 655
    if (AXObjectCache* cache = document().existingAXObjectCache())
        return cache->rootAXEditableElement(this);
656 657 658 659

    return false;
}

hyatt@apple.com's avatar
hyatt@apple.com committed
660 661
RenderBox* Node::renderBox() const
{
662 663
    RenderObject* renderer = this->renderer();
    return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
664 665 666 667
}

RenderBoxModelObject* Node::renderBoxModelObject() const
{
668 669
    RenderObject* renderer = this->renderer();
    return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
hyatt@apple.com's avatar
hyatt@apple.com committed
670 671
}

672
LayoutRect Node::boundingBox() const
kocienda's avatar
kocienda committed
673
{
hyatt@apple.com's avatar
hyatt@apple.com committed
674
    if (renderer())
675
        return renderer()->absoluteBoundingBoxRect();
676
    return LayoutRect();
kocienda's avatar
kocienda committed
677
}
678
    
679
LayoutRect Node::renderRect(bool* isReplaced)
680 681 682 683 684 685 686
{    
    RenderObject* hitRenderer = this->renderer();
    ASSERT(hitRenderer);
    RenderObject* renderer = hitRenderer;
    while (renderer && !renderer->isBody() && !renderer->isRoot()) {
        if (renderer->isRenderBlock() || renderer->isInlineBlockOrInlineTable() || renderer->isReplaced()) {
            *isReplaced = renderer->isReplaced();
687
            return renderer->absoluteBoundingBoxRect();
688 689 690
        }
        renderer = renderer->parent();
    }
691
    return LayoutRect();    
692
}
kocienda's avatar
kocienda committed
693

694
void Node::markAncestorsWithChildNeedsStyleRecalc()
695
{
696 697 698
    ContainerNode* ancestor = isPseudoElement() ? toPseudoElement(this)->hostElement() : parentOrShadowHostNode();
    for (; ancestor && !ancestor->childNeedsStyleRecalc(); ancestor = ancestor->parentOrShadowHostNode())
        ancestor->setChildNeedsStyleRecalc();
699

700 701
    if (document().childNeedsStyleRecalc())
        document().scheduleStyleRecalc();
702 703
}

704 705 706 707 708 709 710 711 712 713
void Node::refEventTarget()
{
    ref();
}

void Node::derefEventTarget()
{
    deref();
}

714
void Node::setNeedsStyleRecalc(StyleChangeType changeType)
kocienda's avatar
kocienda committed
715
{
716 717
    ASSERT(changeType != NoStyleChange);
    if (!attached()) // changed compared to what?
kocienda's avatar
kocienda committed
718 719
        return;

720 721
    StyleChangeType existingChangeType = styleChangeType();
    if (changeType > existingChangeType)
722
        setStyleChange(changeType);
bdakin's avatar
bdakin committed
723

724 725
    if (existingChangeType == NoStyleChange)
        markAncestorsWithChildNeedsStyleRecalc();
kocienda's avatar
kocienda committed
726 727
}

darin's avatar
darin committed
728
unsigned Node::nodeIndex() const
kocienda's avatar
kocienda committed
729
{
darin's avatar
darin committed
730
    Node *_tempNode = previousSibling();
adele's avatar
adele committed
731
    unsigned count=0;
732
    for ( count=0; _tempNode; count++ )
733 734
        _tempNode = _tempNode->previousSibling();
    return count;
kocienda's avatar
kocienda committed
735 736
}

737 738 739
template<unsigned type>
bool shouldInvalidateNodeListCachesForAttr(const unsigned nodeListCounts[], const QualifiedName& attrName)
{
740
    if (nodeListCounts[type] && LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), attrName))
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
        return true;
    return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeListCounts, attrName);
}

template<>
bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(const unsigned[], const QualifiedName&)
{
    return false;
}

bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
{
    if (attrName)
        return shouldInvalidateNodeListCachesForAttr<DoNotInvalidateOnAttributeChanges + 1>(m_nodeListCounts, *attrName);

    for (int type = 0; type < numNodeListInvalidationTypes; type++) {
        if (m_nodeListCounts[type])
            return true;
    }

    return false;
}

void Document::invalidateNodeListCaches(const QualifiedName* attrName)
{
766 767
    HashSet<LiveNodeListBase*>::iterator end = m_listsInvalidatedAtDocument.end();
    for (HashSet<LiveNodeListBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
768 769 770
        (*it)->invalidateCache(attrName);
}

771
void Node::invalidateNodeListCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement)
mjs's avatar
mjs committed
772
{
773 774 775 776
    if (hasRareData() && (!attrName || isAttributeNode())) {
        if (NodeListsNodeData* lists = rareData()->nodeLists())
            lists->clearChildNodeListCache();
    }
777

778
    // Modifications to attributes that are not associated with an Element can't invalidate NodeList caches.
779
    if (attrName && !attributeOwnerElement)
780 781
        return;

782
    if (!document().shouldInvalidateNodeListCaches(attrName))
783 784
        return;

785
    document().invalidateNodeListCaches(attrName);
786

787 788 789 790
    for (Node* node = this; node; node = node->parentNode()) {
        if (!node->hasRareData())
            continue;
        NodeRareData* data = node->rareData();
791
        if (data->nodeLists())
792
            data->nodeLists()->invalidateCaches(attrName);
793
    }
794 795
}

rniwa@webkit.org's avatar
rniwa@webkit.org committed
796
NodeListsNodeData* Node::nodeLists()
797
{
rniwa@webkit.org's avatar
rniwa@webkit.org committed
798
    return hasRareData() ? rareData()->nodeLists() : 0;
799 800
}

801 802 803 804 805
void Node::clearNodeLists()
{
    rareData()->clearNodeLists();
}

ap@apple.com's avatar
ap@apple.com committed
806
void Node::checkSetPrefix(const AtomicString& prefix, ExceptionCode& ec)
807 808
{
    // Perform error checking as required by spec for setting Node.prefix. Used by
darin's avatar
darin committed
809
    // Element::setPrefix() and Attr::setPrefix()
810

811
    if (!prefix.isEmpty() && !Document::isValidName(prefix)) {
812 813 814 815
        ec = INVALID_CHARACTER_ERR;
        return;
    }

adele's avatar
adele committed
816
    if (isReadOnlyNode()) {
darin's avatar
darin committed
817
        ec = NO_MODIFICATION_ALLOWED_ERR;
818 819 820
        return;
    }

ap@apple.com's avatar
ap@apple.com committed
821 822 823 824
    // FIXME: Raise NAMESPACE_ERR if prefix is malformed per the Namespaces in XML specification.

    const AtomicString& nodeNamespaceURI = namespaceURI();
    if ((nodeNamespaceURI.isEmpty() && !prefix.isEmpty())
ap@apple.com's avatar
ap@apple.com committed
825
        || (prefix == xmlAtom && nodeNamespaceURI != XMLNames::xmlNamespaceURI)) {
darin's avatar
darin committed
826
        ec = NAMESPACE_ERR;
827
        return;
ap@apple.com's avatar
ap@apple.com committed
828 829
    }
    // Attribute-specific checks are in Attr::setPrefix().
830
}
kocienda's avatar
kocienda committed
831

justing's avatar
justing committed
832
bool Node::isDescendantOf(const Node *other) const
kocienda's avatar
kocienda committed
833
{
darin's avatar
darin committed
834
    // Return true if other is an ancestor of this, otherwise false
835
    if (!other || !other->hasChildNodes() || inDocument() != other->inDocument())
darin's avatar
darin committed
836
        return false;