summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/Document.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom/Document.cpp')
-rw-r--r--WebCore/dom/Document.cpp574
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 &marker;
- }
- }
-
- 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)