diff options
Diffstat (limited to 'WebCore/dom/Document.cpp')
-rw-r--r-- | WebCore/dom/Document.cpp | 574 |
1 files changed, 61 insertions, 513 deletions
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index 20c6b16..03ad8e7 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -89,7 +89,6 @@ #include "InspectorController.h" #include "InspectorTimelineAgent.h" #include "KeyboardEvent.h" -#include "LegacyHTMLTreeBuilder.h" #include "Logging.h" #include "MessageEvent.h" #include "MouseEvent.h" @@ -123,7 +122,6 @@ #include "StaticHashSetNodeList.h" #include "StyleSheetList.h" #include "TextEvent.h" -#include "TextIterator.h" #include "TextResourceDecoder.h" #include "Timer.h" #include "TransformSource.h" @@ -165,10 +163,6 @@ #include "XSLTProcessor.h" #endif -#if ENABLE(XBL) -#include "XBLBindingManager.h" -#endif - #if ENABLE(SVG) #include "SVGDocumentExtensions.h" #include "SVGElementFactory.h" @@ -394,9 +388,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) , m_asyncScriptRunner(AsyncScriptRunner::create()) , m_xmlVersion("1.0") , m_xmlStandalone(false) -#if ENABLE(XBL) - , m_bindingManager(new XBLBindingManager(this)) -#endif , m_savedRenderer(0) , m_designMode(inherit) , m_selfOnlyRefCount(0) @@ -441,8 +432,14 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) #if !PLATFORM(ANDROID) m_axObjectCache = 0; +<<<<<<< HEAD #endif +======= + + m_markers = new DocumentMarkerController(); + +>>>>>>> webkit.org at r66079 m_docLoader = new DocLoader(this); m_visuallyOrdered = false; @@ -515,10 +512,9 @@ void Document::removedLastRef() removeAllChildren(); - deleteAllValues(m_markers); - m_markers.clear(); + m_markers->detach(); - m_parser.clear(); + detachParser(); m_cssCanvasElements.clear(); @@ -551,18 +547,19 @@ Document::~Document() destroyAllWrapperCaches(); #endif - m_parser.clear(); + // Currently we believe that Document can never outlive the parser. + // Although the Document may be replaced synchronously, DocumentParsers + // generally keep at least one reference to an Element which would in turn + // has a reference to the Document. If you hit this ASSERT, then that + // assumption is wrong. DocumentParser::detach() should ensure that even + // if the DocumentParser outlives the Document it won't cause badness. + ASSERT(!m_parser || m_parser->refCount() == 1); + detachParser(); m_document = 0; m_docLoader.clear(); m_renderArena.clear(); -#if ENABLE(XBL) - m_bindingManager.clear(); -#endif - - deleteAllValues(m_markers); - clearAXObjectCache(); m_decoder = 0; @@ -1009,8 +1006,11 @@ void Document::setXMLVersion(const String& version, ExceptionCode& ec) ec = NOT_SUPPORTED_ERR; return; } - - // FIXME: Also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document. + + if (!XMLDocumentParser::supportsXMLVersion(version)) { + ec = NOT_SUPPORTED_ERR; + return; + } m_xmlVersion = version; } @@ -1514,6 +1514,8 @@ bail_out: void Document::updateStyleIfNeeded() { + ASSERT(!view() || (!view()->isInLayout() && !view()->isPainting())); + if (!childNeedsStyleRecalc() || inPageCache()) return; @@ -1822,10 +1824,10 @@ void Document::setVisuallyOrdered() renderer()->style()->setVisuallyOrdered(true); } -DocumentParser* Document::createParser() +PassRefPtr<DocumentParser> Document::createParser() { // FIXME: this should probably pass the frame instead - return new XMLDocumentParser(this, view()); + return XMLDocumentParser::create(this, view()); } ScriptableDocumentParser* Document::scriptableDocumentParser() const @@ -1859,6 +1861,14 @@ void Document::open(Document* ownerDocument) m_frame->loader()->didExplicitOpen(); } +void Document::detachParser() +{ + if (!m_parser) + return; + m_parser->detach(); + m_parser.clear(); +} + void Document::cancelParsing() { if (m_parser) { @@ -1866,7 +1876,7 @@ void Document::cancelParsing() // the onload handler when closing as a side effect of a cancel-style // change, such as opening a new document or closing the window while // still parsing - m_parser.clear(); + detachParser(); close(); } } @@ -1875,8 +1885,6 @@ void Document::implicitOpen() { cancelParsing(); - m_parser.clear(); - removeChildren(); m_parser = createParser(); @@ -1953,6 +1961,26 @@ void Document::close() } } +// FIXME: These settings probably don't work anymore. We should either remove +// them or make them work properly. +#ifdef BUILDING_ON_LEOPARD +static bool shouldCreateImplicitHead(Document* document) +{ + ASSERT(document); + Settings* settings = document->page() ? document->page()->settings() : 0; + return settings ? !settings->needsLeopardMailQuirks() : true; +} +#elif defined(BUILDING_ON_TIGER) +static bool shouldCreateImplicitHead(Document* document) +{ + ASSERT(document); + Settings* settings = document->page() ? document->page()->settings() : 0; + return settings ? !settings->needsTigerMailQuirks() : true; +} +#else +inline bool shouldCreateImplicitHead(Document*) { return true; } +#endif + void Document::implicitClose() { // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached. @@ -1974,7 +2002,7 @@ void Document::implicitClose() // We have to clear the parser, in case someone document.write()s from the // onLoad event handler, as in Radar 3206524. - m_parser.clear(); + detachParser(); // Parser should have picked up all preloads by now m_docLoader->clearPreloads(); @@ -3233,7 +3261,7 @@ void Document::textInserted(Node* text, unsigned offset, unsigned length) } // Update the markers for spelling and grammar checking. - shiftMarkers(text, offset, length); + m_markers->shiftMarkers(text, offset, length); } void Document::textRemoved(Node* text, unsigned offset, unsigned length) @@ -3245,8 +3273,8 @@ void Document::textRemoved(Node* text, unsigned offset, unsigned length) } // Update the markers for spelling and grammar checking. - removeMarkers(text, offset, length); - shiftMarkers(text, offset + length, 0 - length); + m_markers->removeMarkers(text, offset, length); + m_markers->shiftMarkers(text, offset + length, 0 - length); } void Document::textNodesMerged(Text* oldNode, unsigned offset) @@ -3822,6 +3850,9 @@ static Editor::Command command(Document* document, const String& commandName, bo Frame* frame = document->frame(); if (!frame || frame->document() != document) return Editor::Command(); + + document->updateStyleIfNeeded(); + return frame->editor()->command(commandName, userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM); } @@ -3856,489 +3887,6 @@ String Document::queryCommandValue(const String& commandName) return command(this, commandName).value(); } -static IntRect placeholderRectForMarker() -{ - return IntRect(-1, -1, -1, -1); -} - -void Document::addMarker(Range* range, DocumentMarker::MarkerType type, String description) -{ - // Use a TextIterator to visit the potentially multiple nodes the range covers. - for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) { - RefPtr<Range> textPiece = markedText.range(); - int exception = 0; - DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description, false}; - addMarker(textPiece->startContainer(exception), marker); - } -} - -void Document::removeMarkers(Range* range, DocumentMarker::MarkerType markerType) -{ - if (m_markers.isEmpty()) - return; - - ExceptionCode ec = 0; - Node* startContainer = range->startContainer(ec); - Node* endContainer = range->endContainer(ec); - - Node* pastLastNode = range->pastLastNode(); - for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { - int startOffset = node == startContainer ? range->startOffset(ec) : 0; - int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX; - int length = endOffset - startOffset; - removeMarkers(node, startOffset, length, markerType); - } -} - -// Markers are stored in order sorted by their start offset. -// Markers of the same type do not overlap each other. - -void Document::addMarker(Node* node, DocumentMarker newMarker) -{ - ASSERT(newMarker.endOffset >= newMarker.startOffset); - if (newMarker.endOffset == newMarker.startOffset) - return; - - MarkerMapVectorPair* vectorPair = m_markers.get(node); - - if (!vectorPair) { - vectorPair = new MarkerMapVectorPair; - vectorPair->first.append(newMarker); - vectorPair->second.append(placeholderRectForMarker()); - m_markers.set(node, vectorPair); - } else { - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - size_t numMarkers = markers.size(); - ASSERT(numMarkers == rects.size()); - size_t i; - // Iterate over all markers whose start offset is less than or equal to the new marker's. - // If one of them is of the same type as the new marker and touches it or intersects with it - // (there is at most one), remove it and adjust the new marker's start offset to encompass it. - for (i = 0; i < numMarkers; ++i) { - DocumentMarker marker = markers[i]; - if (marker.startOffset > newMarker.startOffset) - break; - if (marker.type == newMarker.type && marker.endOffset >= newMarker.startOffset) { - newMarker.startOffset = marker.startOffset; - markers.remove(i); - rects.remove(i); - numMarkers--; - break; - } - } - size_t j = i; - // Iterate over all markers whose end offset is less than or equal to the new marker's, - // removing markers of the same type as the new marker which touch it or intersect with it, - // adjusting the new marker's end offset to cover them if necessary. - while (j < numMarkers) { - DocumentMarker marker = markers[j]; - if (marker.startOffset > newMarker.endOffset) - break; - if (marker.type == newMarker.type) { - markers.remove(j); - rects.remove(j); - if (newMarker.endOffset <= marker.endOffset) { - newMarker.endOffset = marker.endOffset; - break; - } - numMarkers--; - } else - j++; - } - // At this point i points to the node before which we want to insert. - markers.insert(i, newMarker); - rects.insert(i, placeholderRectForMarker()); - } - - // repaint the affected node - if (node->renderer()) - node->renderer()->repaint(); -} - -// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is -// useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. -void Document::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta, DocumentMarker::MarkerType markerType) -{ - if (length <= 0) - return; - - MarkerMapVectorPair* vectorPair = m_markers.get(srcNode); - if (!vectorPair) - return; - - ASSERT(vectorPair->first.size() == vectorPair->second.size()); - - bool docDirty = false; - unsigned endOffset = startOffset + length - 1; - Vector<DocumentMarker>& markers = vectorPair->first; - for (size_t i = 0; i != markers.size(); ++i) { - DocumentMarker marker = markers[i]; - - // stop if we are now past the specified range - if (marker.startOffset > endOffset) - break; - - // skip marker that is before the specified range or is the wrong type - if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) - continue; - - // pin the marker to the specified range and apply the shift delta - docDirty = true; - if (marker.startOffset < startOffset) - marker.startOffset = startOffset; - if (marker.endOffset > endOffset) - marker.endOffset = endOffset; - marker.startOffset += delta; - marker.endOffset += delta; - - addMarker(dstNode, marker); - } - - // repaint the affected node - if (docDirty && dstNode->renderer()) - dstNode->renderer()->repaint(); -} - -void Document::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType) -{ - if (length <= 0) - return; - - MarkerMapVectorPair* vectorPair = m_markers.get(node); - if (!vectorPair) - return; - - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - ASSERT(markers.size() == rects.size()); - bool docDirty = false; - unsigned endOffset = startOffset + length; - for (size_t i = 0; i < markers.size();) { - DocumentMarker marker = markers[i]; - - // markers are returned in order, so stop if we are now past the specified range - if (marker.startOffset >= endOffset) - break; - - // skip marker that is wrong type or before target - if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) { - i++; - continue; - } - - // at this point we know that marker and target intersect in some way - docDirty = true; - - // pitch the old marker and any associated rect - markers.remove(i); - rects.remove(i); - - // add either of the resulting slices that are left after removing target - if (startOffset > marker.startOffset) { - DocumentMarker newLeft = marker; - newLeft.endOffset = startOffset; - markers.insert(i, newLeft); - rects.insert(i, placeholderRectForMarker()); - // i now points to the newly-inserted node, but we want to skip that one - i++; - } - if (marker.endOffset > endOffset) { - DocumentMarker newRight = marker; - newRight.startOffset = endOffset; - markers.insert(i, newRight); - rects.insert(i, placeholderRectForMarker()); - // i now points to the newly-inserted node, but we want to skip that one - i++; - } - } - - if (markers.isEmpty()) { - ASSERT(rects.isEmpty()); - m_markers.remove(node); - delete vectorPair; - } - - // repaint the affected node - if (docDirty && node->renderer()) - node->renderer()->repaint(); -} - -DocumentMarker* Document::markerContainingPoint(const IntPoint& point, DocumentMarker::MarkerType markerType) -{ - // outer loop: process each node that contains any markers - MarkerMap::iterator end = m_markers.end(); - for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { - // inner loop; process each marker in this node - MarkerMapVectorPair* vectorPair = nodeIterator->second; - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - ASSERT(markers.size() == rects.size()); - unsigned markerCount = markers.size(); - for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { - DocumentMarker& marker = markers[markerIndex]; - - // skip marker that is wrong type - if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) - continue; - - IntRect& r = rects[markerIndex]; - - // skip placeholder rects - if (r == placeholderRectForMarker()) - continue; - - if (r.contains(point)) - return ▮ - } - } - - return 0; -} - -Vector<DocumentMarker> Document::markersForNode(Node* node) -{ - MarkerMapVectorPair* vectorPair = m_markers.get(node); - if (vectorPair) - return vectorPair->first; - return Vector<DocumentMarker>(); -} - -Vector<IntRect> Document::renderedRectsForMarkers(DocumentMarker::MarkerType markerType) -{ - Vector<IntRect> result; - - // outer loop: process each node - MarkerMap::iterator end = m_markers.end(); - for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { - // inner loop; process each marker in this node - MarkerMapVectorPair* vectorPair = nodeIterator->second; - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - ASSERT(markers.size() == rects.size()); - unsigned markerCount = markers.size(); - for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { - DocumentMarker marker = markers[markerIndex]; - - // skip marker that is wrong type - if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) - continue; - - IntRect r = rects[markerIndex]; - // skip placeholder rects - if (r == placeholderRectForMarker()) - continue; - - result.append(r); - } - } - - return result; -} - -void Document::removeMarkers(Node* node) -{ - MarkerMap::iterator i = m_markers.find(node); - if (i != m_markers.end()) { - delete i->second; - m_markers.remove(i); - if (RenderObject* renderer = node->renderer()) - renderer->repaint(); - } -} - -void Document::removeMarkers(DocumentMarker::MarkerType markerType) -{ - // outer loop: process each markered node in the document - MarkerMap markerMapCopy = m_markers; - MarkerMap::iterator end = markerMapCopy.end(); - for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) { - Node* node = i->first.get(); - bool nodeNeedsRepaint = false; - - // inner loop: process each marker in the current node - MarkerMapVectorPair* vectorPair = i->second; - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - ASSERT(markers.size() == rects.size()); - for (size_t i = 0; i != markers.size();) { - DocumentMarker marker = markers[i]; - - // skip nodes that are not of the specified type - if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) { - ++i; - continue; - } - - // pitch the old marker - markers.remove(i); - rects.remove(i); - nodeNeedsRepaint = true; - // markerIterator now points to the next node - } - - // Redraw the node if it changed. Do this before the node is removed from m_markers, since - // m_markers might contain the last reference to the node. - if (nodeNeedsRepaint) { - RenderObject* renderer = node->renderer(); - if (renderer) - renderer->repaint(); - } - - // delete the node's list if it is now empty - if (markers.isEmpty()) { - ASSERT(rects.isEmpty()); - m_markers.remove(node); - delete vectorPair; - } - } -} - -void Document::repaintMarkers(DocumentMarker::MarkerType markerType) -{ - // outer loop: process each markered node in the document - MarkerMap::iterator end = m_markers.end(); - for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { - Node* node = i->first.get(); - - // inner loop: process each marker in the current node - MarkerMapVectorPair* vectorPair = i->second; - Vector<DocumentMarker>& markers = vectorPair->first; - bool nodeNeedsRepaint = false; - for (size_t i = 0; i != markers.size(); ++i) { - DocumentMarker marker = markers[i]; - - // skip nodes that are not of the specified type - if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) { - nodeNeedsRepaint = true; - break; - } - } - - if (!nodeNeedsRepaint) - continue; - - // cause the node to be redrawn - if (RenderObject* renderer = node->renderer()) - renderer->repaint(); - } -} - -void Document::setRenderedRectForMarker(Node* node, const DocumentMarker& marker, const IntRect& r) -{ - MarkerMapVectorPair* vectorPair = m_markers.get(node); - if (!vectorPair) { - ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about - return; - } - - Vector<DocumentMarker>& markers = vectorPair->first; - ASSERT(markers.size() == vectorPair->second.size()); - unsigned markerCount = markers.size(); - for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { - DocumentMarker m = markers[markerIndex]; - if (m == marker) { - vectorPair->second[markerIndex] = r; - return; - } - } - - ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about -} - -void Document::invalidateRenderedRectsForMarkersInRect(const IntRect& r) -{ - // outer loop: process each markered node in the document - MarkerMap::iterator end = m_markers.end(); - for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { - - // inner loop: process each rect in the current node - MarkerMapVectorPair* vectorPair = i->second; - Vector<IntRect>& rects = vectorPair->second; - - unsigned rectCount = rects.size(); - for (unsigned rectIndex = 0; rectIndex < rectCount; ++rectIndex) - if (rects[rectIndex].intersects(r)) - rects[rectIndex] = placeholderRectForMarker(); - } -} - -void Document::shiftMarkers(Node* node, unsigned startOffset, int delta, DocumentMarker::MarkerType markerType) -{ - MarkerMapVectorPair* vectorPair = m_markers.get(node); - if (!vectorPair) - return; - - Vector<DocumentMarker>& markers = vectorPair->first; - Vector<IntRect>& rects = vectorPair->second; - ASSERT(markers.size() == rects.size()); - - bool docDirty = false; - for (size_t i = 0; i != markers.size(); ++i) { - DocumentMarker& marker = markers[i]; - if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) { - ASSERT((int)marker.startOffset + delta >= 0); - marker.startOffset += delta; - marker.endOffset += delta; - docDirty = true; - - // Marker moved, so previously-computed rendered rectangle is now invalid - rects[i] = placeholderRectForMarker(); - } - } - - // repaint the affected node - if (docDirty && node->renderer()) - node->renderer()->repaint(); -} - -void Document::setMarkersActive(Range* range, bool active) -{ - if (m_markers.isEmpty()) - return; - - ExceptionCode ec = 0; - Node* startContainer = range->startContainer(ec); - Node* endContainer = range->endContainer(ec); - - Node* pastLastNode = range->pastLastNode(); - for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { - int startOffset = node == startContainer ? range->startOffset(ec) : 0; - int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX; - setMarkersActive(node, startOffset, endOffset, active); - } -} - -void Document::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active) -{ - MarkerMapVectorPair* vectorPair = m_markers.get(node); - if (!vectorPair) - return; - - Vector<DocumentMarker>& markers = vectorPair->first; - ASSERT(markers.size() == vectorPair->second.size()); - - bool docDirty = false; - for (size_t i = 0; i != markers.size(); ++i) { - DocumentMarker& marker = markers[i]; - - // Markers are returned in order, so stop if we are now past the specified range. - if (marker.startOffset >= endOffset) - break; - - // Skip marker that is wrong type or before target. - if (marker.endOffset < startOffset || marker.type != DocumentMarker::TextMatch) - continue; - - marker.activeMatch = active; - docDirty = true; - } - - // repaint the affected node - if (docDirty && node->renderer()) - node->renderer()->repaint(); -} - #if ENABLE(XSLT) void Document::applyXSLTransform(ProcessingInstruction* pi) |