summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/dom
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r--Source/WebCore/dom/ClientRect.h4
-rw-r--r--Source/WebCore/dom/DOMAllInOne.cpp1
-rw-r--r--Source/WebCore/dom/DeviceMotionController.cpp4
-rw-r--r--Source/WebCore/dom/DeviceMotionController.h4
-rw-r--r--Source/WebCore/dom/DeviceOrientationController.cpp4
-rw-r--r--Source/WebCore/dom/DeviceOrientationController.h4
-rw-r--r--Source/WebCore/dom/Document.cpp221
-rw-r--r--Source/WebCore/dom/Document.h64
-rw-r--r--Source/WebCore/dom/DocumentMarker.h12
-rw-r--r--Source/WebCore/dom/DocumentMarkerController.cpp40
-rw-r--r--Source/WebCore/dom/DocumentMarkerController.h16
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.cpp151
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.h83
-rw-r--r--Source/WebCore/dom/Element.cpp63
-rw-r--r--Source/WebCore/dom/Element.h17
-rw-r--r--Source/WebCore/dom/Event.cpp10
-rw-r--r--Source/WebCore/dom/Event.h2
-rw-r--r--Source/WebCore/dom/EventQueue.cpp35
-rw-r--r--Source/WebCore/dom/EventQueue.h21
-rw-r--r--Source/WebCore/dom/EventTarget.cpp4
-rw-r--r--Source/WebCore/dom/EventTarget.h2
-rw-r--r--Source/WebCore/dom/InputElement.h2
-rw-r--r--Source/WebCore/dom/NamedNodeMap.cpp2
-rw-r--r--Source/WebCore/dom/Node.cpp16
-rw-r--r--Source/WebCore/dom/Position.cpp2
-rw-r--r--Source/WebCore/dom/ProcessingInstruction.cpp2
-rw-r--r--Source/WebCore/dom/Range.cpp262
-rw-r--r--Source/WebCore/dom/Range.h1
-rw-r--r--Source/WebCore/dom/RequestAnimationFrameCallback.h2
-rw-r--r--Source/WebCore/dom/RequestAnimationFrameCallback.idl2
-rw-r--r--Source/WebCore/dom/ScriptElement.cpp6
-rw-r--r--Source/WebCore/dom/ScriptExecutionContext.cpp72
-rw-r--r--Source/WebCore/dom/ScriptExecutionContext.h10
-rw-r--r--Source/WebCore/dom/ScriptableDocumentParser.cpp2
-rw-r--r--Source/WebCore/dom/ScriptableDocumentParser.h10
-rw-r--r--Source/WebCore/dom/SelectElement.cpp18
-rw-r--r--Source/WebCore/dom/SelectorNodeList.cpp4
-rw-r--r--Source/WebCore/dom/Text.cpp8
-rw-r--r--Source/WebCore/dom/TextEvent.h1
-rw-r--r--Source/WebCore/dom/TextEventInputType.h1
-rw-r--r--Source/WebCore/dom/ViewportArguments.cpp51
41 files changed, 779 insertions, 457 deletions
diff --git a/Source/WebCore/dom/ClientRect.h b/Source/WebCore/dom/ClientRect.h
index f9acef0..f739497 100644
--- a/Source/WebCore/dom/ClientRect.h
+++ b/Source/WebCore/dom/ClientRect.h
@@ -42,8 +42,8 @@ namespace WebCore {
static PassRefPtr<ClientRect> create(const FloatRect& rect) { return adoptRef(new ClientRect(rect)); }
float top() const { return m_rect.y(); }
- float right() const { return m_rect.right(); }
- float bottom() const { return m_rect.bottom(); }
+ float right() const { return m_rect.maxX(); }
+ float bottom() const { return m_rect.maxY(); }
float left() const { return m_rect.x(); }
float width() const { return m_rect.width(); }
float height() const { return m_rect.height(); }
diff --git a/Source/WebCore/dom/DOMAllInOne.cpp b/Source/WebCore/dom/DOMAllInOne.cpp
index aa85bfb..c88aecf 100644
--- a/Source/WebCore/dom/DOMAllInOne.cpp
+++ b/Source/WebCore/dom/DOMAllInOne.cpp
@@ -60,6 +60,7 @@
#include "Document.cpp"
#include "DocumentFragment.cpp"
#include "DocumentMarkerController.cpp"
+#include "DocumentOrderedMap.cpp"
#include "DocumentParser.cpp"
#include "DocumentType.cpp"
#include "DynamicNodeList.cpp"
diff --git a/Source/WebCore/dom/DeviceMotionController.cpp b/Source/WebCore/dom/DeviceMotionController.cpp
index 3385167..28e201e 100644
--- a/Source/WebCore/dom/DeviceMotionController.cpp
+++ b/Source/WebCore/dom/DeviceMotionController.cpp
@@ -54,7 +54,7 @@ void DeviceMotionController::timerFired(Timer<DeviceMotionController>* timer)
RefPtr<DeviceMotionData> deviceMotionData = m_client ? m_client->currentDeviceMotion() : DeviceMotionData::create();
RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData.get());
- Vector<DOMWindow*> listenersVector;
+ Vector<RefPtr<DOMWindow> > listenersVector;
copyToVector(m_newListeners, listenersVector);
m_newListeners.clear();
for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -100,7 +100,7 @@ void DeviceMotionController::removeAllListeners(DOMWindow* window)
void DeviceMotionController::didChangeDeviceMotion(DeviceMotionData* deviceMotionData)
{
RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData);
- Vector<DOMWindow*> listenersVector;
+ Vector<RefPtr<DOMWindow> > listenersVector;
copyToVector(m_listeners, listenersVector);
for (size_t i = 0; i < listenersVector.size(); ++i)
listenersVector[i]->dispatchEvent(event);
diff --git a/Source/WebCore/dom/DeviceMotionController.h b/Source/WebCore/dom/DeviceMotionController.h
index 70c948e..80c9d94 100644
--- a/Source/WebCore/dom/DeviceMotionController.h
+++ b/Source/WebCore/dom/DeviceMotionController.h
@@ -52,9 +52,9 @@ private:
void timerFired(Timer<DeviceMotionController>*);
DeviceMotionClient* m_client;
- typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
+ typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
ListenersCountedSet m_listeners;
- typedef HashSet<DOMWindow*> ListenersSet;
+ typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
ListenersSet m_newListeners;
Timer<DeviceMotionController> m_timer;
};
diff --git a/Source/WebCore/dom/DeviceOrientationController.cpp b/Source/WebCore/dom/DeviceOrientationController.cpp
index 60fcf13..da42bec 100644
--- a/Source/WebCore/dom/DeviceOrientationController.cpp
+++ b/Source/WebCore/dom/DeviceOrientationController.cpp
@@ -54,7 +54,7 @@ void DeviceOrientationController::timerFired(Timer<DeviceOrientationController>*
RefPtr<DeviceOrientation> orientation = m_client->lastOrientation();
RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation.get());
- Vector<DOMWindow*> listenersVector;
+ Vector<RefPtr<DOMWindow> > listenersVector;
copyToVector(m_newListeners, listenersVector);
m_newListeners.clear();
for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -102,7 +102,7 @@ void DeviceOrientationController::removeAllListeners(DOMWindow* window)
void DeviceOrientationController::didChangeDeviceOrientation(DeviceOrientation* orientation)
{
RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation);
- Vector<DOMWindow*> listenersVector;
+ Vector<RefPtr<DOMWindow> > listenersVector;
copyToVector(m_listeners, listenersVector);
for (size_t i = 0; i < listenersVector.size(); ++i)
listenersVector[i]->dispatchEvent(event);
diff --git a/Source/WebCore/dom/DeviceOrientationController.h b/Source/WebCore/dom/DeviceOrientationController.h
index 4fa9006..5e06771 100644
--- a/Source/WebCore/dom/DeviceOrientationController.h
+++ b/Source/WebCore/dom/DeviceOrientationController.h
@@ -55,9 +55,9 @@ private:
Page* m_page;
DeviceOrientationClient* m_client;
- typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
+ typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
ListenersCountedSet m_listeners;
- typedef HashSet<DOMWindow*> ListenersSet;
+ typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
ListenersSet m_newListeners;
Timer<DeviceOrientationController> m_timer;
};
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 0bdd603..6b1b90d 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -55,6 +55,7 @@
#include "DocumentType.h"
#include "EditingText.h"
#include "Editor.h"
+#include "Element.h"
#include "EntityReference.h"
#include "Event.h"
#include "EventHandler.h"
@@ -102,6 +103,7 @@
#include "MouseEventWithHitTestResults.h"
#include "MutationEvent.h"
#include "NameNodeList.h"
+#include "NestingLevelIncrementer.h"
#include "NodeFilter.h"
#include "NodeIterator.h"
#include "NodeWithIndex.h"
@@ -143,7 +145,6 @@
#include "XMLHttpRequest.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
-#include "XSSAuditor.h"
#include "htmlediting.h"
#include <wtf/CurrentTime.h>
#include <wtf/HashFunctions.h>
@@ -235,16 +236,13 @@ using namespace HTMLNames;
// #define INSTRUMENT_LAYOUT_SCHEDULING 1
+static const unsigned cMaxWriteRecursionDepth = 21;
+
// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
// FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high
// for dual G5s. :)
static const int cLayoutScheduleThreshold = 250;
-// These functions can't have internal linkage because they are used as template arguments.
-bool keyMatchesId(AtomicStringImpl*, Element*);
-bool keyMatchesMapName(AtomicStringImpl*, Element*);
-bool keyMatchesLowercasedMapName(AtomicStringImpl*, Element*);
-
// DOM Level 2 says (letters added):
//
// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
@@ -383,7 +381,7 @@ private:
Document* m_document;
};
-Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, const KURL& baseURL)
+Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
: ContainerNode(0)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
@@ -430,7 +428,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con
, m_normalWorldWrapperCache(0)
#endif
, m_usingGeolocation(false)
- , m_eventQueue(adoptPtr(new EventQueue))
+ , m_eventQueue(EventQueue::create(this))
#if ENABLE(WML)
, m_containsWMLContent(false)
#endif
@@ -446,6 +444,8 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con
, m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
, m_directionSetOnDocumentElement(false)
, m_writingModeSetOnDocumentElement(false)
+ , m_writeRecursionIsTooDeep(false)
+ , m_writeRecursionDepth(0)
#if ENABLE(REQUEST_ANIMATION_FRAME)
, m_nextRequestAnimationFrameCallbackId(0)
#endif
@@ -460,16 +460,25 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con
m_ignoreAutofocus = false;
m_frame = frame;
-
- if (frame || !url.isEmpty())
+ m_documentLoader = frame ? frame->loader()->activeDocumentLoader() : 0;
+
+ // We depend on the url getting immediately set in subframes, but we
+ // also depend on the url NOT getting immediately set in opened windows.
+ // See fast/dom/early-frame-url.html
+ // and fast/dom/location-new-window-no-crash.html, respectively.
+ // FIXME: Can/should we unify this behavior?
+ if ((frame && frame->ownerElement()) || !url.isEmpty())
setURL(url);
+<<<<<<< HEAD
// Setting of m_baseURL needs to happen after the setURL call, since that
// calls updateBaseURL, which would clobber the passed in value.
if (!baseURL.isNull())
m_baseURL = baseURL;
#if !PLATFORM(ANDROID)
+=======
+>>>>>>> webkit.org at r78450
m_axObjectCache = 0;
#endif
@@ -521,12 +530,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con
#endif
}
-inline void Document::DocumentOrderedMap::clear()
-{
- m_map.clear();
- m_duplicateCounts.clear();
-}
-
void Document::removedLastRef()
{
ASSERT(!m_deletionHasBegun);
@@ -736,10 +739,7 @@ void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* a
void Document::cacheDocumentElement() const
{
ASSERT(!m_documentElement);
- Node* n = firstChild();
- while (n && !n->isElementNode())
- n = n->nextSibling();
- m_documentElement = static_cast<Element*>(n);
+ m_documentElement = firstElementChild(this);
}
PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
@@ -1019,87 +1019,11 @@ PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const
return createElement(qName, false);
}
-inline void Document::DocumentOrderedMap::add(AtomicStringImpl* key, Element* element)
-{
- ASSERT(key);
- ASSERT(element);
-
- if (!m_duplicateCounts.contains(key)) {
- // Fast path. The key is not already in m_duplicateCounts, so we assume that it's
- // also not already in m_map and try to add it. If that add succeeds, we're done.
- pair<Map::iterator, bool> addResult = m_map.add(key, element);
- if (addResult.second)
- return;
-
- // The add failed, so this key was already cached in m_map.
- // There are multiple elements with this key. Remove the m_map
- // cache for this key so get searches for it next time it is called.
- m_map.remove(addResult.first);
- m_duplicateCounts.add(key);
- } else {
- // There are multiple elements with this key. Remove the m_map
- // cache for this key so get will search for it next time it is called.
- Map::iterator cachedItem = m_map.find(key);
- if (cachedItem != m_map.end()) {
- m_map.remove(cachedItem);
- m_duplicateCounts.add(key);
- }
- }
-
- m_duplicateCounts.add(key);
-}
-
-inline void Document::DocumentOrderedMap::remove(AtomicStringImpl* key, Element* element)
-{
- ASSERT(key);
- ASSERT(element);
-
- m_map.checkConsistency();
- Map::iterator cachedItem = m_map.find(key);
- if (cachedItem != m_map.end() && cachedItem->second == element)
- m_map.remove(cachedItem);
- else
- m_duplicateCounts.remove(key);
-}
-
-template<bool keyMatches(AtomicStringImpl*, Element*)> inline Element* Document::DocumentOrderedMap::get(AtomicStringImpl* key, const Document* document) const
-{
- ASSERT(key);
-
- m_map.checkConsistency();
-
- Element* element = m_map.get(key);
- if (element)
- return element;
-
- if (m_duplicateCounts.contains(key)) {
- // We know there's at least one node that matches; iterate to find the first one.
- for (Node* node = document->firstChild(); node; node = node->traverseNextNode()) {
- if (!node->isElementNode())
- continue;
- element = static_cast<Element*>(node);
- if (!keyMatches(key, element))
- continue;
- m_duplicateCounts.remove(key);
- m_map.set(key, element);
- return element;
- }
- ASSERT_NOT_REACHED();
- }
-
- return 0;
-}
-
-inline bool keyMatchesId(AtomicStringImpl* key, Element* element)
-{
- return element->hasID() && element->getIdAttribute().impl() == key;
-}
-
Element* Document::getElementById(const AtomicString& elementId) const
{
if (elementId.isEmpty())
return 0;
- return m_elementsById.get<keyMatchesId>(elementId.impl(), this);
+ return m_elementsById.getElementById(elementId.impl(), this);
}
String Document::readyState() const
@@ -1209,7 +1133,7 @@ void Document::setContent(const String& content)
open();
m_parser->append(content);
m_parser->finish();
- close();
+ explicitClose();
}
// FIXME: We need to discuss the DOM API here at some point. Ideas:
@@ -2038,6 +1962,8 @@ void Document::open(Document* ownerDocument)
removeAllEventListeners();
implicitOpen();
+ if (ScriptableDocumentParser* parser = scriptableDocumentParser())
+ parser->setWasCreatedByScript(true);
if (DOMWindow* domWindow = this->domWindow())
domWindow->removeAllEventListeners();
@@ -2056,14 +1982,15 @@ void Document::detachParser()
void Document::cancelParsing()
{
- if (m_parser) {
- // We have to clear the parser to avoid possibly triggering
- // 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
- detachParser();
- close();
- }
+ if (!m_parser)
+ return;
+
+ // We have to clear the parser to avoid possibly triggering
+ // 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
+ detachParser();
+ explicitClose();
}
void Document::implicitOpen()
@@ -2078,10 +2005,6 @@ void Document::implicitOpen()
setParsing(true);
setReadyState(Loading);
- ScriptableDocumentParser* parser = scriptableDocumentParser();
- if (m_frame && parser)
- parser->setXSSAuditor(m_frame->script()->xssAuditor());
-
// If we reload, the animation controller sticks around and has
// a stale animation time. We need to update it here.
if (m_frame && m_frame->animation())
@@ -2098,12 +2021,12 @@ HTMLElement* Document::body() const
Node* body = 0;
for (Node* i = de->firstChild(); i; i = i->nextSibling()) {
if (i->hasTagName(framesetTag))
- return static_cast<HTMLElement*>(i);
+ return toHTMLElement(i);
if (i->hasTagName(bodyTag) && !body)
body = i;
}
- return static_cast<HTMLElement*>(body);
+ return toHTMLElement(body);
}
void Document::setBody(PassRefPtr<HTMLElement> newBody, ExceptionCode& ec)
@@ -2135,18 +2058,28 @@ HTMLHeadElement* Document::head()
void Document::close()
{
- Frame* frame = this->frame();
- if (frame) {
- // This code calls implicitClose() if all loading has completed.
- FrameLoader* frameLoader = frame->loader();
- frameLoader->writer()->endIfNotLoadingMainResource();
- frameLoader->checkCompleted();
- } else {
+ // FIXME: We should follow the specification more closely:
+ // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
+
+ if (!scriptableDocumentParser() || !scriptableDocumentParser()->wasCreatedByScript())
+ return;
+
+ explicitClose();
+}
+
+void Document::explicitClose()
+{
+ if (!m_frame) {
// Because we have no frame, we don't know if all loading has completed,
// so we just call implicitClose() immediately. FIXME: This might fire
// the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
implicitClose();
+ return;
}
+
+ // This code calls implicitClose() if all loading has completed.
+ loader()->writer()->endIfNotLoadingMainResource();
+ m_frame->loader()->checkCompleted();
}
void Document::implicitClose()
@@ -2297,6 +2230,14 @@ int Document::elapsedTime() const
void Document::write(const SegmentedString& text, Document* ownerDocument)
{
+ NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
+
+ m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
+ m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
+
+ if (m_writeRecursionIsTooDeep)
+ return;
+
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!ownerElement())
printf("Beginning a document.write at %d\n", elapsedTime());
@@ -2421,7 +2362,7 @@ void Document::processBaseElement()
KURL baseElementURL;
if (href) {
String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
- if (!strippedHref.isEmpty() && (!frame() || frame()->script()->xssAuditor()->canSetBaseElementURL(*href)))
+ if (!strippedHref.isEmpty())
baseElementURL = KURL(url(), strippedHref);
}
if (m_baseElementURL != baseElementURL) {
@@ -2698,7 +2639,7 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
String url;
if (frame && parseHTTPRefresh(content, true, delay, url)) {
if (url.isEmpty())
- url = frame->loader()->url().string();
+ url = m_url.string();
else
url = completeURL(url).string();
frame->navigationScheduler()->scheduleRedirect(delay, url);
@@ -2979,12 +2920,11 @@ void Document::removePendingSheet()
styleSelectorChanged(RecalcStyleImmediately);
- ScriptableDocumentParser* parser = scriptableDocumentParser();
- if (parser)
+ if (ScriptableDocumentParser* parser = scriptableDocumentParser())
parser->executeScriptsWaitingForStylesheets();
if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
- view()->scrollToFragment(m_frame->loader()->url());
+ view()->scrollToFragment(m_url);
}
void Document::styleSelectorChanged(StyleSelectorUpdateFlag updateFlag)
@@ -3037,6 +2977,9 @@ void Document::styleSelectorChanged(StyleSelectorUpdateFlag updateFlag)
void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser)
{
+ if (!node->inDocument())
+ return;
+
// Until the <body> exists, we have no choice but to compare document positions,
// since styles outside of the body and head continue to be shunted into the head
// (and thus can shift to end up before dynamically added DOM content that is also
@@ -3825,7 +3768,7 @@ String Document::lastModified() const
DateComponents date;
bool foundDate = false;
if (m_frame) {
- String httpLastModified = m_frame->loader()->documentLoader()->response().httpHeaderField("Last-Modified");
+ String httpLastModified = m_documentLoader->response().httpHeaderField("Last-Modified");
if (!httpLastModified.isEmpty()) {
date.setMillisecondsSinceEpochForDateTime(parseDate(httpLastModified));
foundDate = true;
@@ -3957,16 +3900,6 @@ void Document::removeImageMap(HTMLMapElement* imageMap)
m_imageMapsByName.remove(name, imageMap);
}
-inline bool keyMatchesMapName(AtomicStringImpl* key, Element* element)
-{
- return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().impl() == key;
-}
-
-inline bool keyMatchesLowercasedMapName(AtomicStringImpl* key, Element* element)
-{
- return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().lower().impl() == key;
-}
-
HTMLMapElement* Document::getImageMap(const String& url) const
{
if (url.isNull())
@@ -3974,8 +3907,8 @@ HTMLMapElement* Document::getImageMap(const String& url) const
size_t hashPos = url.find('#');
String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
if (isHTMLDocument())
- return static_cast<HTMLMapElement*>(m_imageMapsByName.get<keyMatchesLowercasedMapName>(AtomicString(name.lower()).impl(), this));
- return static_cast<HTMLMapElement*>(m_imageMapsByName.get<keyMatchesMapName>(AtomicString(name).impl(), this));
+ return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
+ return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
}
void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
@@ -4338,7 +4271,7 @@ void Document::finishedParsing()
f->loader()->finishedParsing();
- InspectorInstrumentation::mainResourceFiredDOMContentEvent(f, url());
+ InspectorInstrumentation::domContentLoadedEventFired(f, url());
}
}
@@ -4551,8 +4484,7 @@ void Document::initSecurityContext()
// load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756
// and https://bugs.webkit.org/show_bug.cgi?id=19760 for further
// discussion.
- DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
- if (documentLoader && documentLoader->substituteData().isValid())
+ if (m_documentLoader->substituteData().isValid())
securityOrigin()->grantLoadLocalResources();
}
@@ -4629,10 +4561,9 @@ void Document::updateURLForPushOrReplaceState(const KURL& url)
if (!f)
return;
- // FIXME: Eliminate this redundancy.
setURL(url);
- f->loader()->setURL(url);
- f->loader()->documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
+ f->loader()->setOutgoingReferrer(url);
+ m_documentLoader->replaceRequestURLForSameDocumentNavigation(url);
}
void Document::statePopped(SerializedScriptValue* stateObject)
@@ -5048,7 +4979,7 @@ void Document::webkitCancelRequestAnimationFrame(int id)
}
}
-void Document::serviceScriptedAnimations()
+void Document::serviceScriptedAnimations(DOMTimeStamp time)
{
if (!m_requestAnimationFrameCallbacks)
return;
@@ -5076,7 +5007,7 @@ void Document::serviceScriptedAnimations()
RequestAnimationFrameCallback* callback = callbacks[i].get();
if (!callback->m_firedOrCancelled && (!callback->m_element || callback->m_element->renderer())) {
callback->m_firedOrCancelled = true;
- callback->handleEvent();
+ callback->handleEvent(time);
firedCallback = true;
callbacks.remove(i);
break;
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index c9c8d38..9ace93d 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -32,15 +32,19 @@
#include "CollectionType.h"
#include "Color.h"
#include "ContainerNode.h"
+#include "ContentSecurityPolicy.h"
+#include "DOMTimeStamp.h"
+#include "DocumentLoader.h"
+#include "DocumentOrderedMap.h"
#include "DocumentTiming.h"
#include "QualifiedName.h"
#include "ScriptExecutionContext.h"
#include "Timer.h"
#include "ViewportArguments.h"
#include <wtf/FixedArray.h>
-#include <wtf/HashCountedSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
#if USE(JSC)
#include <runtime/WeakGCMap.h>
@@ -347,7 +351,6 @@ public:
String defaultCharset() const;
- // Synonyms backing similar DOM attributes. Use Document::encoding() to avoid virtual dispatch.
String inputEncoding() const { return Document::encoding(); }
String charset() const { return Document::encoding(); }
String characterSet() const { return Document::encoding(); }
@@ -429,6 +432,7 @@ public:
#endif
virtual bool isFrameSet() const { return false; }
+ CSSStyleSelector* styleSelectorIfExists() const { return m_styleSelector.get(); }
CSSStyleSelector* styleSelector()
{
if (!m_styleSelector)
@@ -554,11 +558,22 @@ public:
// to get visually ordered hebrew and arabic pages right
void setVisuallyOrdered();
bool visuallyOrdered() const { return m_visuallyOrdered; }
+
+ void setDocumentLoader(DocumentLoader* documentLoader) { m_documentLoader = documentLoader; }
+ DocumentLoader* loader() const { return m_documentLoader; }
void open(Document* ownerDocument = 0);
void implicitOpen();
+
+ // close() is the DOM API document.close()
void close();
+ // In some situations (see the code), we ignore document.close().
+ // explicitClose() bypass these checks and actually tries to close the
+ // input stream.
+ void explicitClose();
+ // implicitClose() actually does the work of closing the input stream.
void implicitClose();
+
void cancelParsing();
void write(const SegmentedString& text, Document* ownerDocument = 0);
@@ -952,7 +967,7 @@ public:
virtual void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously.
#if USE(JSC)
- typedef JSC::WeakGCMap<WebCore::Node*, JSNode*> JSWrapperCache;
+ typedef JSC::WeakGCMap<WebCore::Node*, JSNode> JSWrapperCache;
typedef HashMap<DOMWrapperWorld*, JSWrapperCache*> JSWrapperCacheMap;
JSWrapperCacheMap& wrapperCacheMap() { return m_wrapperCacheMap; }
JSWrapperCache* getWrapperCache(DOMWrapperWorld* world);
@@ -1091,7 +1106,7 @@ public:
#if ENABLE(REQUEST_ANIMATION_FRAME)
int webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback>, Element*);
void webkitCancelRequestAnimationFrame(int id);
- void serviceScriptedAnimations();
+ void serviceScriptedAnimations(DOMTimeStamp);
#endif
bool mayCauseFlashOfUnstyledContent() const;
@@ -1101,35 +1116,15 @@ public:
void initDNSPrefetch();
+ ContentSecurityPolicy* contentSecurityPolicy() { return &m_contentSecurityPolicy; }
+
protected:
- Document(Frame*, const KURL& url, bool isXHTML, bool isHTML, const KURL& baseURL = KURL());
+ Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
void clearXMLVersion() { m_xmlVersion = String(); }
private:
- class DocumentOrderedMap {
- public:
- void add(AtomicStringImpl*, Element*);
- void remove(AtomicStringImpl*, Element*);
- void clear();
-
- bool contains(AtomicStringImpl*) const;
- bool containsMultiple(AtomicStringImpl*) const;
- template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const Document*) const;
-
- void checkConsistency() const;
-
- private:
- typedef HashMap<AtomicStringImpl*, Element*> Map;
-
- // We maintain the invariant that m_duplicateCounts is the count of all elements with a given key
- // excluding the one referenced in m_map, if any. This means it one less than the total count
- // when the first node with a given key is cached, otherwise the same as the total count.
- mutable Map m_map;
- mutable HashCountedSet<AtomicStringImpl*> m_duplicateCounts;
- };
-
friend class IgnoreDestructiveWriteCountIncrementer;
void detachParser();
@@ -1172,6 +1167,7 @@ private:
bool m_didCalculateStyleSelector;
Frame* m_frame;
+ DocumentLoader* m_documentLoader;
OwnPtr<CachedResourceLoader> m_cachedResourceLoader;
RefPtr<DocumentParser> m_parser;
bool m_wellFormed;
@@ -1422,23 +1418,17 @@ private:
DocumentTiming m_documentTiming;
RefPtr<MediaQueryMatcher> m_mediaQueryMatcher;
+ bool m_writeRecursionIsTooDeep;
+ unsigned m_writeRecursionDepth;
#if ENABLE(REQUEST_ANIMATION_FRAME)
typedef Vector<RefPtr<RequestAnimationFrameCallback> > RequestAnimationFrameCallbackList;
OwnPtr<RequestAnimationFrameCallbackList> m_requestAnimationFrameCallbacks;
int m_nextRequestAnimationFrameCallbackId;
#endif
-};
-inline bool Document::DocumentOrderedMap::contains(AtomicStringImpl* id) const
-{
- return m_map.contains(id) || m_duplicateCounts.contains(id);
-}
-
-inline bool Document::DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
-{
- return m_duplicateCounts.contains(id);
-}
+ ContentSecurityPolicy m_contentSecurityPolicy;
+};
inline bool Document::hasElementWithId(AtomicStringImpl* id) const
{
diff --git a/Source/WebCore/dom/DocumentMarker.h b/Source/WebCore/dom/DocumentMarker.h
index 2be60f8..76b85bb 100644
--- a/Source/WebCore/dom/DocumentMarker.h
+++ b/Source/WebCore/dom/DocumentMarker.h
@@ -37,10 +37,20 @@ struct DocumentMarker {
Spelling = 1 << 0,
Grammar = 1 << 1,
TextMatch = 1 << 2,
+ // Text has been modified by spell correction. On some platforms, this prevents the text
+ // to be autocorrected again.
Replacement = 1 << 3,
+ // Renderer needs to add underline indicating that the text has been modified by spell
+ // correction. Text with Replacement marker doesn't necessarily has CorrectionIndicator
+ // marker. For instance, after some text has been corrected, it will have both Replacement
+ // and CorrectionIndicator. However, if user further modifies such text, we would remove
+ // CorrectionIndicator marker, but retain Replacement marker.
CorrectionIndicator = 1 << 4,
+ // Correction suggestion has been offered, but got rejected by user.
RejectedCorrection = 1 << 5,
- AllMarkers = Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection
+ // On some platforms, this prevents the text to be spellchecked again.
+ SpellCheckingExemption = 1 << 6,
+ AllMarkers = Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | SpellCheckingExemption
};
MarkerType type;
typedef unsigned MarkerTypes;
diff --git a/Source/WebCore/dom/DocumentMarkerController.cpp b/Source/WebCore/dom/DocumentMarkerController.cpp
index 5f88631..1bc7cb4 100644
--- a/Source/WebCore/dom/DocumentMarkerController.cpp
+++ b/Source/WebCore/dom/DocumentMarkerController.cpp
@@ -57,21 +57,16 @@ void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerTyp
}
}
-void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
{
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);
+ for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
+ RefPtr<Range> textPiece = markedText.range();
+ int startOffset = textPiece->startOffset();
+ int endOffset = textPiece->endOffset();
+ removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
}
}
@@ -185,7 +180,7 @@ void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset,
dstNode->renderer()->repaint();
}
-void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
{
if (length <= 0)
return;
@@ -207,7 +202,7 @@ void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, i
break;
// skip marker that is wrong type or before target
- if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) {
+ if (marker.endOffset <= startOffset || !(marker.type & markerTypes)) {
i++;
continue;
}
@@ -219,6 +214,10 @@ void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, i
markers.remove(i);
rects.remove(i);
+ if (shouldRemovePartiallyOverlappingMarker)
+ // Stop here. Don't add resulting slices back.
+ continue;
+
// add either of the resulting slices that are left after removing target
if (startOffset > marker.startOffset) {
DocumentMarker newLeft = marker;
@@ -321,14 +320,14 @@ Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker
return result;
}
-void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
{
MarkerMap::iterator iterator = m_markers.find(node);
if (iterator != m_markers.end())
- removeMarkersFromMarkerMapVectorPair(node, iterator->second, markerType);
+ removeMarkersFromMarkerMapVectorPair(node, iterator->second, markerTypes);
}
-void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
{
// outer loop: process each markered node in the document
MarkerMap markerMapCopy = m_markers;
@@ -336,14 +335,14 @@ void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerType markerTy
for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) {
Node* node = i->first.get();
MarkerMapVectorPair* vectorPair = i->second;
- removeMarkersFromMarkerMapVectorPair(node, vectorPair, markerType);
+ removeMarkersFromMarkerMapVectorPair(node, vectorPair, markerTypes);
}
}
// This function may release node and vectorPair.
-void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node, MarkerMapVectorPair* vectorPair, DocumentMarker::MarkerType markerType)
+void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node, MarkerMapVectorPair* vectorPair, DocumentMarker::MarkerTypes markerTypes)
{
- if (markerType == DocumentMarker::AllMarkers) {
+ if (!~(markerTypes & DocumentMarker::AllMarkers)) {
delete vectorPair;
m_markers.remove(node);
if (RenderObject* renderer = node->renderer())
@@ -357,7 +356,7 @@ void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node,
DocumentMarker marker = markers[i];
// skip nodes that are not of the specified type
- if (marker.type != markerType) {
+ if (!(marker.type & markerTypes)) {
++i;
continue;
}
@@ -566,7 +565,6 @@ bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy
}
return false;
}
-
#ifndef NDEBUG
void DocumentMarkerController::showMarkers() const
{
diff --git a/Source/WebCore/dom/DocumentMarkerController.h b/Source/WebCore/dom/DocumentMarkerController.h
index 2dc2b9e..21b351b 100644
--- a/Source/WebCore/dom/DocumentMarkerController.h
+++ b/Source/WebCore/dom/DocumentMarkerController.h
@@ -49,10 +49,16 @@ public:
void addMarker(Node*, DocumentMarker);
void copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
bool hasMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
- void removeMarkers(Range*, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(Node*, unsigned startOffset, int length, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(Node*, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
+
+ // When a marker partially overlaps with range, if removePartiallyOverlappingMarkers is true, we completely
+ // remove the marker. If the argument is false, we will adjust the span of the marker so that it retains
+ // the portion that is outside of the range.
+ enum RemovePartiallyOverlappingMarkerOrNot { DoNotRemovePartiallyOverlappingMarker, RemovePartiallyOverlappingMarker };
+ void removeMarkers(Range*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers, RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
+ void removeMarkers(Node*, unsigned startOffset, int length, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers, RemovePartiallyOverlappingMarkerOrNot = DoNotRemovePartiallyOverlappingMarker);
+
+ void removeMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
+ void removeMarkers(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers);
void repaintMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
void setRenderedRectForMarker(Node*, const DocumentMarker&, const IntRect&);
void invalidateRenderedRectsForMarkersInRect(const IntRect&);
@@ -72,7 +78,7 @@ private:
typedef std::pair<Vector<DocumentMarker>, Vector<IntRect> > MarkerMapVectorPair;
typedef HashMap<RefPtr<Node>, MarkerMapVectorPair*> MarkerMap;
MarkerMap m_markers;
- void removeMarkersFromMarkerMapVectorPair(Node*, MarkerMapVectorPair*, DocumentMarker::MarkerType);
+ void removeMarkersFromMarkerMapVectorPair(Node*, MarkerMapVectorPair*, DocumentMarker::MarkerTypes);
};
} // namespace WebCore
diff --git a/Source/WebCore/dom/DocumentOrderedMap.cpp b/Source/WebCore/dom/DocumentOrderedMap.cpp
new file mode 100644
index 0000000..787fcf4
--- /dev/null
+++ b/Source/WebCore/dom/DocumentOrderedMap.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DocumentOrderedMap.h"
+
+#include "Element.h"
+#include "HTMLMapElement.h"
+#include "HTMLNames.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+inline bool keyMatchesId(AtomicStringImpl* key, Element* element)
+{
+ return element->hasID() && element->getIdAttribute().impl() == key;
+}
+
+inline bool keyMatchesMapName(AtomicStringImpl* key, Element* element)
+{
+ return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().impl() == key;
+}
+
+inline bool keyMatchesLowercasedMapName(AtomicStringImpl* key, Element* element)
+{
+ return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().lower().impl() == key;
+}
+
+void DocumentOrderedMap::clear()
+{
+ m_map.clear();
+ m_duplicateCounts.clear();
+}
+
+void DocumentOrderedMap::add(AtomicStringImpl* key, Element* element)
+{
+ ASSERT(key);
+ ASSERT(element);
+
+ if (!m_duplicateCounts.contains(key)) {
+ // Fast path. The key is not already in m_duplicateCounts, so we assume that it's
+ // also not already in m_map and try to add it. If that add succeeds, we're done.
+ pair<Map::iterator, bool> addResult = m_map.add(key, element);
+ if (addResult.second)
+ return;
+
+ // The add failed, so this key was already cached in m_map.
+ // There are multiple elements with this key. Remove the m_map
+ // cache for this key so get searches for it next time it is called.
+ m_map.remove(addResult.first);
+ m_duplicateCounts.add(key);
+ } else {
+ // There are multiple elements with this key. Remove the m_map
+ // cache for this key so get will search for it next time it is called.
+ Map::iterator cachedItem = m_map.find(key);
+ if (cachedItem != m_map.end()) {
+ m_map.remove(cachedItem);
+ m_duplicateCounts.add(key);
+ }
+ }
+
+ m_duplicateCounts.add(key);
+}
+
+void DocumentOrderedMap::remove(AtomicStringImpl* key, Element* element)
+{
+ ASSERT(key);
+ ASSERT(element);
+
+ m_map.checkConsistency();
+ Map::iterator cachedItem = m_map.find(key);
+ if (cachedItem != m_map.end() && cachedItem->second == element)
+ m_map.remove(cachedItem);
+ else
+ m_duplicateCounts.remove(key);
+}
+
+template<bool keyMatches(AtomicStringImpl*, Element*)>
+inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const Document* document) const
+{
+ ASSERT(key);
+
+ m_map.checkConsistency();
+
+ Element* element = m_map.get(key);
+ if (element)
+ return element;
+
+ if (m_duplicateCounts.contains(key)) {
+ // We know there's at least one node that matches; iterate to find the first one.
+ for (Node* node = document->firstChild(); node; node = node->traverseNextNode()) {
+ if (!node->isElementNode())
+ continue;
+ element = static_cast<Element*>(node);
+ if (!keyMatches(key, element))
+ continue;
+ m_duplicateCounts.remove(key);
+ m_map.set(key, element);
+ return element;
+ }
+ ASSERT_NOT_REACHED();
+ }
+
+ return 0;
+}
+
+Element* DocumentOrderedMap::getElementById(AtomicStringImpl* key, const Document* document) const
+{
+ return get<keyMatchesId>(key, document);
+}
+
+Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const Document* document) const
+{
+ return get<keyMatchesMapName>(key, document);
+}
+
+Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key, const Document* document) const
+{
+ return get<keyMatchesLowercasedMapName>(key, document);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/dom/DocumentOrderedMap.h b/Source/WebCore/dom/DocumentOrderedMap.h
new file mode 100644
index 0000000..58767c6
--- /dev/null
+++ b/Source/WebCore/dom/DocumentOrderedMap.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DocumentOrderedMap_h
+#define DocumentOrderedMap_h
+
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicStringImpl.h>
+
+namespace WebCore {
+
+class Document;
+class Element;
+
+class DocumentOrderedMap {
+public:
+ void add(AtomicStringImpl*, Element*);
+ void remove(AtomicStringImpl*, Element*);
+ void clear();
+
+ bool contains(AtomicStringImpl*) const;
+ bool containsMultiple(AtomicStringImpl*) const;
+ // concrete instantiations of the get<>() method template
+ Element* getElementById(AtomicStringImpl*, const Document*) const;
+ Element* getElementByMapName(AtomicStringImpl*, const Document*) const;
+ Element* getElementByLowercasedMapName(AtomicStringImpl*, const Document*) const;
+
+ void checkConsistency() const;
+
+private:
+ template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const Document*) const;
+
+ typedef HashMap<AtomicStringImpl*, Element*> Map;
+
+ // We maintain the invariant that m_duplicateCounts is the count of all elements with a given key
+ // excluding the one referenced in m_map, if any. This means it one less than the total count
+ // when the first node with a given key is cached, otherwise the same as the total count.
+ mutable Map m_map;
+ mutable HashCountedSet<AtomicStringImpl*> m_duplicateCounts;
+};
+
+inline bool DocumentOrderedMap::contains(AtomicStringImpl* id) const
+{
+ return m_map.contains(id) || m_duplicateCounts.contains(id);
+}
+
+inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
+{
+ return m_duplicateCounts.contains(id);
+}
+
+} // namespace WebCore
+
+#endif // DocumentOrderedMap_h
+
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 276a409..142febd 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -68,6 +68,34 @@ namespace WebCore {
using namespace HTMLNames;
using namespace XMLNames;
+class StyleSelectorParentPusher {
+public:
+ StyleSelectorParentPusher(Element* parent)
+ : m_parent(parent)
+ , m_pushedStyleSelector(0)
+ {
+ }
+ void push()
+ {
+ if (m_pushedStyleSelector)
+ return;
+ m_pushedStyleSelector = m_parent->document()->styleSelector();
+ m_pushedStyleSelector->pushParent(m_parent);
+ }
+ ~StyleSelectorParentPusher()
+ {
+
+ if (!m_pushedStyleSelector)
+ return;
+ ASSERT(m_pushedStyleSelector == m_parent->document()->styleSelector());
+ m_pushedStyleSelector->popParent(m_parent);
+ }
+
+private:
+ Element* m_parent;
+ CSSStyleSelector* m_pushedStyleSelector;
+};
+
PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
{
return adoptRef(new Element(tagName, document, CreateElement));
@@ -124,7 +152,7 @@ PassRefPtr<DocumentFragment> Element::deprecatedCreateContextualFragment(const S
for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
nextNode = node->nextSibling();
if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
- HTMLElement* element = static_cast<HTMLElement*>(node.get());
+ HTMLElement* element = toHTMLElement(node.get());
Node* firstChild = element->firstChild();
if (firstChild)
nextNode = firstChild;
@@ -917,9 +945,15 @@ void Element::attach()
RenderWidget::suspendWidgetHierarchyUpdates();
createRendererIfNeeded();
+
+ StyleSelectorParentPusher parentPusher(this);
+ if (firstChild())
+ parentPusher.push();
ContainerNode::attach();
- if (Node* shadow = shadowRoot())
+ if (Node* shadow = shadowRoot()) {
+ parentPusher.push();
shadow->attach();
+ }
if (hasRareData()) {
ElementRareData* data = rareData();
if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
@@ -1075,7 +1109,7 @@ void Element::recalcStyle(StyleChange change)
change = ch;
}
}
-
+ StyleSelectorParentPusher parentPusher(this);
// FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
// For now we will just worry about the common case, since it's a lot trickier to get the second case right
// without doing way too much re-resolution.
@@ -1084,15 +1118,19 @@ void Element::recalcStyle(StyleChange change)
bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
if (forceCheckOfNextElementSibling && n->isElementNode())
n->setNeedsStyleRecalc();
- if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
+ if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc()) {
+ parentPusher.push();
n->recalcStyle(change);
+ }
if (n->isElementNode())
forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
}
// FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
if (Node* shadow = shadowRoot()) {
- if (change >= Inherit || shadow->isTextNode() || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc())
+ if (change >= Inherit || shadow->isTextNode() || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
+ parentPusher.push();
shadow->recalcStyle(change);
+ }
}
clearNeedsStyleRecalc();
@@ -1238,12 +1276,22 @@ void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af
if (!changedByParser)
checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
}
+
+void Element::beginParsingChildren()
+{
+ clearIsParsingChildrenFinished();
+ CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
+ if (styleSelector && attached())
+ styleSelector->pushParent(this);
+}
void Element::finishParsingChildren()
{
ContainerNode::finishParsingChildren();
setIsParsingChildrenFinished();
checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
+ if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
+ styleSelector->popParent(this);
}
void Element::dispatchAttrRemovalEvent(Attribute*)
@@ -1632,10 +1680,7 @@ void Element::normalizeAttributes()
// ElementTraversal API
Element* Element::firstElementChild() const
{
- Node* n = firstChild();
- while (n && !n->isElementNode())
- n = n->nextSibling();
- return static_cast<Element*>(n);
+ return WebCore::firstElementChild(this);
}
Element* Element::lastElementChild() const
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index 4510478..a85f8cd 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -232,7 +232,7 @@ public:
Node* shadowRoot();
void setShadowRoot(PassRefPtr<Node>);
- virtual AtomicString shadowPseudoId() const;
+ virtual const AtomicString& shadowPseudoId() const;
RenderStyle* computedStyle(PseudoId = NOPSEUDO);
@@ -276,7 +276,7 @@ public:
bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
virtual void finishParsingChildren();
- virtual void beginParsingChildren() { clearIsParsingChildrenFinished(); }
+ virtual void beginParsingChildren();
// ElementTraversal API
Element* firstElementChild() const;
@@ -510,9 +510,18 @@ inline void Element::setIdAttribute(const AtomicString& value)
setAttribute(document()->idAttributeName(), value);
}
-inline AtomicString Element::shadowPseudoId() const
+inline const AtomicString& Element::shadowPseudoId() const
{
- return AtomicString();
+ return nullAtom;
+}
+
+inline Element* firstElementChild(const ContainerNode* container)
+{
+ ASSERT_ARG(container, container);
+ Node* child = container->firstChild();
+ while (child && !child->isElementNode())
+ child = child->nextSibling();
+ return static_cast<Element*>(child);
}
} // namespace
diff --git a/Source/WebCore/dom/Event.cpp b/Source/WebCore/dom/Event.cpp
index 0e11c69..bdc1c58 100644
--- a/Source/WebCore/dom/Event.cpp
+++ b/Source/WebCore/dom/Event.cpp
@@ -193,6 +193,16 @@ bool Event::isStorageEvent() const
#endif
#if ENABLE(INDEXED_DATABASE)
+bool Event::isIDBAbortEvent() const
+{
+ return false;
+}
+
+bool Event::isIDBCompleteEvent() const
+{
+ return false;
+}
+
bool Event::isIDBErrorEvent() const
{
return false;
diff --git a/Source/WebCore/dom/Event.h b/Source/WebCore/dom/Event.h
index 45b879d..81f9e6b 100644
--- a/Source/WebCore/dom/Event.h
+++ b/Source/WebCore/dom/Event.h
@@ -126,6 +126,8 @@ namespace WebCore {
virtual bool isStorageEvent() const;
#endif
#if ENABLE(INDEXED_DATABASE)
+ virtual bool isIDBAbortEvent() const;
+ virtual bool isIDBCompleteEvent() const;
virtual bool isIDBErrorEvent() const;
virtual bool isIDBSuccessEvent() const;
#endif
diff --git a/Source/WebCore/dom/EventQueue.cpp b/Source/WebCore/dom/EventQueue.cpp
index a43929e..5a1abe8 100644
--- a/Source/WebCore/dom/EventQueue.cpp
+++ b/Source/WebCore/dom/EventQueue.cpp
@@ -28,24 +28,41 @@
#include "EventQueue.h"
#include "DOMWindow.h"
-#include "Document.h"
#include "Event.h"
#include "EventNames.h"
+#include "ScriptExecutionContext.h"
+#include "SuspendableTimer.h"
namespace WebCore {
-EventQueue::EventQueue()
- : m_pendingEventTimer(this, &EventQueue::pendingEventTimerFired)
+class EventQueueTimer : public SuspendableTimer {
+ WTF_MAKE_NONCOPYABLE(EventQueueTimer);
+public:
+ EventQueueTimer(EventQueue* eventQueue, ScriptExecutionContext* context)
+ : SuspendableTimer(context)
+ , m_eventQueue(eventQueue) { }
+
+private:
+ virtual void fired() { m_eventQueue->pendingEventTimerFired(); }
+ EventQueue* m_eventQueue;
+};
+
+EventQueue::EventQueue(ScriptExecutionContext* context)
+ : m_pendingEventTimer(adoptPtr(new EventQueueTimer(this, context)))
+{
+}
+
+EventQueue::~EventQueue()
{
}
void EventQueue::enqueueEvent(PassRefPtr<Event> event)
{
- ASSERT(event->target()->toNode() || event->target()->toDOMWindow());
+ ASSERT(event->target());
m_queuedEvents.append(event);
- if (!m_pendingEventTimer.isActive())
- m_pendingEventTimer.startOneShot(0);
+ if (!m_pendingEventTimer->isActive())
+ m_pendingEventTimer->startOneShot(0);
}
void EventQueue::enqueueScrollEvent(PassRefPtr<Node> target, ScrollEventTargetType targetType)
@@ -60,9 +77,9 @@ void EventQueue::enqueueScrollEvent(PassRefPtr<Node> target, ScrollEventTargetTy
enqueueEvent(scrollEvent.release());
}
-void EventQueue::pendingEventTimerFired(Timer<EventQueue>*)
+void EventQueue::pendingEventTimerFired()
{
- ASSERT(!m_pendingEventTimer.isActive());
+ ASSERT(!m_pendingEventTimer->isActive());
Vector<RefPtr<Event> > queuedEvents;
queuedEvents.swap(m_queuedEvents);
@@ -81,7 +98,7 @@ void EventQueue::dispatchEvent(PassRefPtr<Event> event)
else if (eventTarget->toDOMWindow())
eventTarget->toDOMWindow()->dispatchEvent(event, 0);
else
- ASSERT_NOT_REACHED();
+ eventTarget->dispatchEvent(event);
}
}
diff --git a/Source/WebCore/dom/EventQueue.h b/Source/WebCore/dom/EventQueue.h
index 7f8d5fb..a589ed8 100644
--- a/Source/WebCore/dom/EventQueue.h
+++ b/Source/WebCore/dom/EventQueue.h
@@ -27,38 +27,51 @@
#ifndef EventQueue_h
#define EventQueue_h
-#include "Timer.h"
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
class Event;
+class EventQueueTimer;
class Node;
+class ScriptExecutionContext;
class EventQueue {
WTF_MAKE_NONCOPYABLE(EventQueue);
+
public:
enum ScrollEventTargetType {
ScrollEventDocumentTarget,
ScrollEventElementTarget
};
- EventQueue();
+ static PassOwnPtr<EventQueue> create(ScriptExecutionContext* context)
+ {
+ return adoptPtr(new EventQueue(context));
+ }
+
+ ~EventQueue();
void enqueueEvent(PassRefPtr<Event>);
void enqueueScrollEvent(PassRefPtr<Node>, ScrollEventTargetType);
private:
- void pendingEventTimerFired(Timer<EventQueue>*);
+ explicit EventQueue(ScriptExecutionContext*);
+
+ void pendingEventTimerFired();
void dispatchEvent(PassRefPtr<Event>);
- Timer<EventQueue> m_pendingEventTimer;
+ OwnPtr<EventQueueTimer> m_pendingEventTimer;
Vector<RefPtr<Event> > m_queuedEvents;
HashSet<Node*> m_nodesWithQueuedScrollEvents;
+
+ friend class EventQueueTimer;
};
}
diff --git a/Source/WebCore/dom/EventTarget.cpp b/Source/WebCore/dom/EventTarget.cpp
index 5f2f8a7..ed5995c 100644
--- a/Source/WebCore/dom/EventTarget.cpp
+++ b/Source/WebCore/dom/EventTarget.cpp
@@ -181,6 +181,10 @@ FileWriter* EventTarget::toFileWriter()
#endif
#if ENABLE(INDEXED_DATABASE)
+IDBDatabase* EventTarget::toIDBDatabase()
+{
+ return 0;
+}
IDBRequest* EventTarget::toIDBRequest()
{
return 0;
diff --git a/Source/WebCore/dom/EventTarget.h b/Source/WebCore/dom/EventTarget.h
index 81eeb7f..a03801b 100644
--- a/Source/WebCore/dom/EventTarget.h
+++ b/Source/WebCore/dom/EventTarget.h
@@ -49,6 +49,7 @@ namespace WebCore {
class EventSource;
class FileReader;
class FileWriter;
+ class IDBDatabase;
class IDBRequest;
class IDBTransaction;
class JavaScriptAudioNode;
@@ -138,6 +139,7 @@ namespace WebCore {
#endif
#if ENABLE(INDEXED_DATABASE)
+ virtual IDBDatabase* toIDBDatabase();
virtual IDBRequest* toIDBRequest();
virtual IDBTransaction* toIDBTransaction();
#endif
diff --git a/Source/WebCore/dom/InputElement.h b/Source/WebCore/dom/InputElement.h
index 2d5606d..02ac5cf 100644
--- a/Source/WebCore/dom/InputElement.h
+++ b/Source/WebCore/dom/InputElement.h
@@ -59,6 +59,8 @@ public:
virtual String value() const = 0;
virtual void setValue(const String&, bool sendChangeEvent = false) = 0;
virtual void setValueForUser(const String&) = 0;
+ // The value which is drawn by a renderer.
+ virtual String visibleValue() const = 0;
// Returns true if the specified string can be set as the value of InputElement.
virtual bool isAcceptableValue(const String&) const = 0;
diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp
index 0e2861e..2861226 100644
--- a/Source/WebCore/dom/NamedNodeMap.cpp
+++ b/Source/WebCore/dom/NamedNodeMap.cpp
@@ -357,7 +357,7 @@ bool NamedNodeMap::mappedMapsEquivalent(const NamedNodeMap* otherMap) const
ASSERT(attr->isMappedAttribute());
Attribute* otherAttr = otherMap->getAttributeItem(attr->name());
- if (!otherAttr || attr->value() != otherAttr->value())
+ if (!otherAttr || !otherAttr->decl() || attr->value() != otherAttr->value())
return false;
if (!attr->decl()->propertiesEqual(otherAttr->decl()))
return false;
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index 275e370..72592ae 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -1641,7 +1641,7 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
// FIXME: we could also optimize for the the [id="foo"] case
if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
- Element* element = document()->getElementById(querySelectorList.first()->m_value);
+ Element* element = document()->getElementById(querySelectorList.first()->value());
if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
return element;
return 0;
@@ -2913,6 +2913,18 @@ void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents,
gNodesDispatchingSimulatedClicks->remove(this);
}
+// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
+// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
+static Node* pullOutOfShadow(Node* node)
+{
+ Node* outermostShadowBoundary = node;
+ for (Node* n = node; n; n = n->parentOrHostNode()) {
+ if (n->isShadowRoot())
+ outermostShadowBoundary = n->parentOrHostNode();
+ }
+ return outermostShadowBoundary;
+}
+
bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int detail,
int pageX, int pageY, int screenX, int screenY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
@@ -2935,7 +2947,7 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det
bool swallowEvent = false;
// Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored.
- RefPtr<Node> relatedTarget = relatedTargetArg;
+ RefPtr<Node> relatedTarget = pullOutOfShadow(relatedTargetArg);
int adjustedPageX = pageX;
int adjustedPageY = pageY;
diff --git a/Source/WebCore/dom/Position.cpp b/Source/WebCore/dom/Position.cpp
index 6749ca9..cbad302 100644
--- a/Source/WebCore/dom/Position.cpp
+++ b/Source/WebCore/dom/Position.cpp
@@ -27,7 +27,6 @@
#include "Position.h"
#include "CSSComputedStyleDeclaration.h"
-#include "CharacterNames.h"
#include "Logging.h"
#include "PositionIterator.h"
#include "RenderBlock.h"
@@ -38,6 +37,7 @@
#include "visible_units.h"
#include <stdio.h>
#include <wtf/text/CString.h>
+#include <wtf/unicode/CharacterNames.h>
namespace WebCore {
diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp
index e7dea48..ed329bc 100644
--- a/Source/WebCore/dom/ProcessingInstruction.cpp
+++ b/Source/WebCore/dom/ProcessingInstruction.cpp
@@ -168,7 +168,7 @@ void ProcessingInstruction::checkStyleSheet()
{
String charset = attrs.get("charset");
if (charset.isEmpty())
- charset = document()->frame()->loader()->writer()->encoding();
+ charset = document()->charset();
m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(url, charset);
}
diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp
index a41fc49..e224843 100644
--- a/Source/WebCore/dom/Range.cpp
+++ b/Source/WebCore/dom/Range.cpp
@@ -594,6 +594,21 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
return true; // all other cases
}
+static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot)
+{
+ if (node == commonRoot)
+ return 0;
+
+ ASSERT(commonRoot->contains(node));
+
+ while (node->parentNode() != commonRoot)
+ node = node->parentNode();
+
+ return node;
+}
+
+static inline unsigned lengthOfContentsInNode() { return numeric_limits<unsigned>::max(); }
+
PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
{
typedef Vector<RefPtr<Node> > NodeVector;
@@ -601,7 +616,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
RefPtr<DocumentFragment> fragment;
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
fragment = DocumentFragment::create(m_ownerDocument.get());
-
+
ec = 0;
if (collapsed(ec))
return fragment.release();
@@ -613,68 +628,16 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
return 0;
ASSERT(commonRoot);
- // what is the highest node that partially selects the start of the range?
- Node* partialStart = 0;
- if (m_start.container() != commonRoot) {
- partialStart = m_start.container();
- while (partialStart->parentNode() != commonRoot)
- partialStart = partialStart->parentNode();
- }
-
- // what is the highest node that partially selects the end of the range?
- Node* partialEnd = 0;
- if (m_end.container() != commonRoot) {
- partialEnd = m_end.container();
- while (partialEnd->parentNode() != commonRoot)
- partialEnd = partialEnd->parentNode();
- }
-
- // Simple case: the start and end containers are the same. We just grab
- // everything >= start offset and < end offset
if (m_start.container() == m_end.container()) {
- Node::NodeType startNodeType = m_start.container()->nodeType();
- if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));
- c->deleteData(m_end.offset(), c->length() - m_end.offset(), ec);
- c->deleteData(0, m_start.offset(), ec);
- fragment->appendChild(c.release(), ec);
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterData*>(m_start.container())->deleteData(m_start.offset(), m_end.offset() - m_start.offset(), ec);
- } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));
- c->setData(c->data().substring(m_start.offset(), m_end.offset() - m_start.offset()), ec);
- fragment->appendChild(c.release(), ec);
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());
- String data(pi->data());
- data.remove(m_start.offset(), m_end.offset() - m_start.offset());
- pi->setData(data, ec);
- }
- } else {
- RefPtr<Node> n = m_start.container()->firstChild();
- int i;
- for (i = 0; n && i < m_start.offset(); i++) // skip until start offset
- n = n->nextSibling();
- int endOffset = m_end.offset();
- RefPtr<Node> next;
- for (; n && i < endOffset; n = next, i++) { // delete until end offset
- next = n->nextSibling();
- if (action == EXTRACT_CONTENTS)
- fragment->appendChild(n, ec); // will remove n from its parent
- else if (action == CLONE_CONTENTS)
- fragment->appendChild(n->cloneNode(true), ec);
- else
- toContainerNode(m_start.container())->removeChild(n.get(), ec);
- }
- }
- return fragment.release();
+ processContentsBetweenOffsets(action, fragment, m_start.container(), m_start.offset(), m_end.offset(), ec);
+ return fragment;
}
- // Complex case: Start and end containers are different.
+ // what is the highest node that partially selects the start / end of the range?
+ Node* partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot);
+ Node* partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot);
+
+ // Start and end containers are different.
// There are three possibilities here:
// 1. Start container == commonRoot (End container must be a descendant)
// 2. End container == commonRoot (Start container must be a descendant)
@@ -693,49 +656,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
RefPtr<Node> leftContents;
if (m_start.container() != commonRoot) {
- // process the left-hand side of the range, up until the last ancestor of
- // start container before commonRoot
- Node::NodeType startNodeType = m_start.container()->nodeType();
- if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));
- c->deleteData(0, m_start.offset(), ec);
- leftContents = c.release();
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterData*>(m_start.container())->deleteData(
- m_start.offset(), static_cast<CharacterData*>(m_start.container())->length() - m_start.offset(), ec);
- } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));
- c->setData(c->data().substring(m_start.offset()), ec);
- leftContents = c.release();
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());
- String data(pi->data());
- pi->setData(data.left(m_start.offset()), ec);
- }
- } else {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
- leftContents = m_start.container()->cloneNode(false);
- NodeVector nodes;
- Node* n = m_start.container()->firstChild();
- for (int i = 0; n; n = n->nextSibling(), i++) {
- if (i < m_start.offset())
- continue; // Skip until start offset.
- nodes.append(n);
- }
- for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) {
- Node* n = it->get();
- if (action == EXTRACT_CONTENTS)
- leftContents->appendChild(n, ec); // Will remove n from start container.
- else if (action == CLONE_CONTENTS)
- leftContents->appendChild(n->cloneNode(true), ec);
- else
- toContainerNode(m_start.container())->removeChild(n, ec);
- }
- }
+ leftContents = processContentsBetweenOffsets(action, 0, m_start.container(), m_start.offset(), lengthOfContentsInNode(), ec);
NodeVector ancestorNodes;
for (ContainerNode* n = m_start.container()->parentNode(); n && n != commonRoot; n = n->parentNode())
@@ -767,46 +688,7 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
RefPtr<Node> rightContents;
if (m_end.container() != commonRoot) {
- // delete the right-hand side of the range, up until the last ancestor of
- // end container before commonRoot
- Node::NodeType endNodeType = m_end.container()->nodeType();
- if (endNodeType == Node::TEXT_NODE || endNodeType == Node::CDATA_SECTION_NODE || endNodeType == Node::COMMENT_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_end.container()->cloneNode(true));
- c->deleteData(m_end.offset(), static_cast<CharacterData*>(m_end.container())->length() - m_end.offset(), ec);
- rightContents = c;
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterData*>(m_end.container())->deleteData(0, m_end.offset(), ec);
- } else if (endNodeType == Node::PROCESSING_INSTRUCTION_NODE) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_end.container()->cloneNode(true));
- c->setData(c->data().left(m_end.offset()), ec);
- rightContents = c.release();
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_end.container());
- pi->setData(pi->data().substring(m_end.offset()), ec);
- }
- } else {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
- rightContents = m_end.container()->cloneNode(false);
- Node* n = m_end.container()->firstChild();
- if (n && m_end.offset()) {
- NodeVector nodes;
- for (int i = 0; i < m_end.offset() && n; i++, n = n->nextSibling())
- nodes.append(n);
- for (int i = nodes.size() - 1; i >= 0; i--) {
- n = nodes[i].get();
- if (action == EXTRACT_CONTENTS)
- rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent
- else if (action == CLONE_CONTENTS)
- rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec);
- else
- toContainerNode(m_end.container())->removeChild(n, ec);
- }
- }
- }
+ rightContents = processContentsBetweenOffsets(action, 0, m_end.container(), 0, m_end.offset(), ec);
ContainerNode* rightParent = m_end.container()->parentNode();
Node* n = m_end.container()->previousSibling();
@@ -892,6 +774,98 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
return fragment.release();
}
+PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment,
+ Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
+{
+ ASSERT(container);
+ ASSERT(startOffset <= endOffset);
+
+ RefPtr<Node> result;
+ switch (container->nodeType()) {
+ case Node::TEXT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::COMMENT_NODE:
+ ASSERT(endOffset <= static_cast<CharacterData*>(container)->length() || endOffset == lengthOfContentsInNode());
+ if (endOffset == lengthOfContentsInNode())
+ endOffset = static_cast<CharacterData*>(container)->length();
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true));
+ if (c->length() - endOffset)
+ c->deleteData(endOffset, c->length() - endOffset, ec);
+ if (startOffset)
+ c->deleteData(0, startOffset, ec);
+ if (fragment) {
+ result = fragment;
+ result->appendChild(c.release(), ec);
+ } else
+ result = c.release();
+ }
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
+ static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, ec);
+ break;
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length() || endOffset == lengthOfContentsInNode());
+ if (endOffset == lengthOfContentsInNode())
+ endOffset = static_cast<ProcessingInstruction*>(container)->data().length();
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true));
+ c->setData(c->data().substring(startOffset, endOffset - startOffset), ec);
+ if (fragment) {
+ result = fragment;
+ result->appendChild(c.release(), ec);
+ } else
+ result = c.release();
+ }
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
+ ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container);
+ String data(pi->data());
+ data.remove(startOffset, endOffset - startOffset);
+ pi->setData(data, ec);
+ }
+ break;
+ case Node::ELEMENT_NODE:
+ case Node::ATTRIBUTE_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ case Node::ENTITY_NODE:
+ case Node::DOCUMENT_NODE:
+ case Node::DOCUMENT_TYPE_NODE:
+ case Node::DOCUMENT_FRAGMENT_NODE:
+ case Node::NOTATION_NODE:
+ case Node::XPATH_NAMESPACE_NODE:
+ // FIXME: Should we assert that some nodes never appear here?
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ if (fragment)
+ result = fragment;
+ else
+ result = container->cloneNode(false);
+ }
+
+ Node* n = container->firstChild();
+ Vector<RefPtr<Node> > nodes;
+ for (unsigned i = startOffset; n && i; i--)
+ n = n->nextSibling();
+ for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling())
+ nodes.append(n);
+
+ for (unsigned i = 0; i < nodes.size(); i++) {
+ switch (action) {
+ case DELETE_CONTENTS:
+ container->removeChild(nodes[i].get(), ec);
+ break;
+ case EXTRACT_CONTENTS:
+ result->appendChild(nodes[i].release(), ec); // will remove n from its parent
+ break;
+ case CLONE_CONTENTS:
+ result->appendChild(nodes[i]->cloneNode(true), ec);
+ break;
+ }
+ }
+ break;
+ }
+
+ return result;
+}
+
PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
{
checkDeleteExtract(ec);
@@ -1079,7 +1053,7 @@ PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku
// Logic from deprecatedCreateContextualFragment should just be moved into
// this function. Range::createContextualFragment semantics do not make
// sense for the rest of the DOM implementation to use.
- RefPtr<DocumentFragment> fragment = static_cast<HTMLElement*>(element)->deprecatedCreateContextualFragment(markup);
+ RefPtr<DocumentFragment> fragment = toHTMLElement(element)->deprecatedCreateContextualFragment(markup);
if (!fragment) {
ec = NOT_SUPPORTED_ERR;
return 0;
diff --git a/Source/WebCore/dom/Range.h b/Source/WebCore/dom/Range.h
index aea76e1..86c1354 100644
--- a/Source/WebCore/dom/Range.h
+++ b/Source/WebCore/dom/Range.h
@@ -147,6 +147,7 @@ private:
enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS };
PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&);
+ PassRefPtr<Node> processContentsBetweenOffsets(ActionType, PassRefPtr<DocumentFragment>, Node*, unsigned startOffset, unsigned endOffset, ExceptionCode&);
RefPtr<Document> m_ownerDocument;
RangeBoundaryPoint m_start;
diff --git a/Source/WebCore/dom/RequestAnimationFrameCallback.h b/Source/WebCore/dom/RequestAnimationFrameCallback.h
index 819e495..3edeb9e 100644
--- a/Source/WebCore/dom/RequestAnimationFrameCallback.h
+++ b/Source/WebCore/dom/RequestAnimationFrameCallback.h
@@ -40,7 +40,7 @@ namespace WebCore {
class RequestAnimationFrameCallback : public RefCounted<RequestAnimationFrameCallback> {
public:
virtual ~RequestAnimationFrameCallback() { }
- virtual bool handleEvent() = 0;
+ virtual bool handleEvent(DOMTimeStamp) = 0;
RefPtr<Element> m_element;
int m_id;
diff --git a/Source/WebCore/dom/RequestAnimationFrameCallback.idl b/Source/WebCore/dom/RequestAnimationFrameCallback.idl
index 8d232e5..1905193 100644
--- a/Source/WebCore/dom/RequestAnimationFrameCallback.idl
+++ b/Source/WebCore/dom/RequestAnimationFrameCallback.idl
@@ -32,6 +32,6 @@ module core {
interface [
Callback=FunctionOnly,Conditional=REQUEST_ANIMATION_FRAME
] RequestAnimationFrameCallback{
- boolean handleEvent();
+ boolean handleEvent(in DOMTimeStamp time);
};
}
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 747f7a1..1939a08 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -292,10 +292,8 @@ String ScriptElement::scriptCharset() const
String charset = charsetAttributeValue().stripWhiteSpace();
// If charset has not been declared in script tag, fall back to frame encoding.
- if (charset.isEmpty()) {
- if (Frame* frame = m_element->document()->frame())
- charset = frame->loader()->writer()->encoding();
- }
+ if (charset.isEmpty())
+ charset = m_element->document()->charset();
return charset;
}
diff --git a/Source/WebCore/dom/ScriptExecutionContext.cpp b/Source/WebCore/dom/ScriptExecutionContext.cpp
index 9fdf85e..19267c6 100644
--- a/Source/WebCore/dom/ScriptExecutionContext.cpp
+++ b/Source/WebCore/dom/ScriptExecutionContext.cpp
@@ -30,6 +30,7 @@
#include "ActiveDOMObject.h"
#include "Blob.h"
#include "BlobURL.h"
+#include "DOMURL.h"
#include "Database.h"
#include "DatabaseTask.h"
#include "DatabaseThread.h"
@@ -83,7 +84,9 @@ public:
};
ScriptExecutionContext::ScriptExecutionContext()
- : m_inDispatchErrorEvent(false)
+ : m_iteratingActiveDOMObjects(false)
+ , m_inDestructor(false)
+ , m_inDispatchErrorEvent(false)
#if ENABLE(DATABASE)
, m_hasOpenDatabases(false)
#endif
@@ -92,10 +95,12 @@ ScriptExecutionContext::ScriptExecutionContext()
ScriptExecutionContext::~ScriptExecutionContext()
{
- HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
- for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
- ASSERT(iter->first->scriptExecutionContext() == this);
- iter->first->contextDestroyed();
+ m_inDestructor = true;
+ for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != m_activeDOMObjects.end(); iter = m_activeDOMObjects.begin()) {
+ ActiveDOMObject* object = iter->first;
+ m_activeDOMObjects.remove(iter);
+ ASSERT(object->scriptExecutionContext() == this);
+ object->contextDestroyed();
}
HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end();
@@ -120,6 +125,12 @@ ScriptExecutionContext::~ScriptExecutionContext()
HashSet<String>::iterator publicBlobURLsEnd = m_publicBlobURLs.end();
for (HashSet<String>::iterator iter = m_publicBlobURLs.begin(); iter != publicBlobURLsEnd; ++iter)
ThreadableBlobRegistry::unregisterBlobURL(KURL(ParsedURLString, *iter));
+
+ HashSet<DOMURL*>::iterator domUrlsEnd = m_domUrls.end();
+ for (HashSet<DOMURL*>::iterator iter = m_domUrls.begin(); iter != domUrlsEnd; ++iter) {
+ ASSERT((*iter)->scriptExecutionContext() == this);
+ (*iter)->contextDestroyed();
+ }
#endif
}
@@ -194,46 +205,70 @@ void ScriptExecutionContext::destroyedMessagePort(MessagePort* port)
m_messagePorts.remove(port);
}
+#if ENABLE(BLOB)
+void ScriptExecutionContext::createdDomUrl(DOMURL* url)
+{
+ ASSERT(url);
+ m_domUrls.add(url);
+}
+
+void ScriptExecutionContext::destroyedDomUrl(DOMURL* url)
+{
+ ASSERT(url);
+ m_domUrls.remove(url);
+}
+#endif
+
bool ScriptExecutionContext::canSuspendActiveDOMObjects()
{
// No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS.
+ m_iteratingActiveDOMObjects = true;
HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
ASSERT(iter->first->scriptExecutionContext() == this);
- if (!iter->first->canSuspend())
+ if (!iter->first->canSuspend()) {
+ m_iteratingActiveDOMObjects = false;
return false;
- }
+ }
+ }
+ m_iteratingActiveDOMObjects = false;
return true;
}
void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
{
// No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS.
+ m_iteratingActiveDOMObjects = true;
HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
ASSERT(iter->first->scriptExecutionContext() == this);
iter->first->suspend(why);
}
+ m_iteratingActiveDOMObjects = false;
}
void ScriptExecutionContext::resumeActiveDOMObjects()
{
// No protection against m_activeDOMObjects changing during iteration: resume() shouldn't execute arbitrary JS.
+ m_iteratingActiveDOMObjects = true;
HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
ASSERT(iter->first->scriptExecutionContext() == this);
iter->first->resume();
}
+ m_iteratingActiveDOMObjects = false;
}
void ScriptExecutionContext::stopActiveDOMObjects()
{
// No protection against m_activeDOMObjects changing during iteration: stop() shouldn't execute arbitrary JS.
+ m_iteratingActiveDOMObjects = true;
HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
ASSERT(iter->first->scriptExecutionContext() == this);
iter->first->stop();
}
+ m_iteratingActiveDOMObjects = false;
// Also close MessagePorts. If they were ActiveDOMObjects (they could be) then they could be stopped instead.
closeMessagePorts();
@@ -243,12 +278,17 @@ void ScriptExecutionContext::createdActiveDOMObject(ActiveDOMObject* object, voi
{
ASSERT(object);
ASSERT(upcastPointer);
+ ASSERT(!m_inDestructor);
+ if (m_iteratingActiveDOMObjects)
+ CRASH();
m_activeDOMObjects.add(object, upcastPointer);
}
void ScriptExecutionContext::destroyedActiveDOMObject(ActiveDOMObject* object)
{
ASSERT(object);
+ if (m_iteratingActiveDOMObjects)
+ CRASH();
m_activeDOMObjects.remove(object);
}
@@ -265,6 +305,17 @@ void ScriptExecutionContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securi
m_securityOrigin = securityOrigin;
}
+bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL)
+{
+ KURL targetURL = completeURL(sourceURL);
+ if (securityOrigin()->canRequest(targetURL))
+ return false;
+ errorMessage = "Script error.";
+ sourceURL = String();
+ lineNumber = 0;
+ return true;
+}
+
void ScriptExecutionContext::reportException(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack> callStack)
{
if (m_inDispatchErrorEvent) {
@@ -294,9 +345,14 @@ bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int
if (!target)
return false;
+ String message = errorMessage;
+ int line = lineNumber;
+ String sourceName = sourceURL;
+ sanitizeScriptError(message, line, sourceName);
+
ASSERT(!m_inDispatchErrorEvent);
m_inDispatchErrorEvent = true;
- RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(errorMessage, sourceURL, lineNumber);
+ RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line);
target->dispatchEvent(errorEvent);
m_inDispatchErrorEvent = false;
return errorEvent->defaultPrevented();
diff --git a/Source/WebCore/dom/ScriptExecutionContext.h b/Source/WebCore/dom/ScriptExecutionContext.h
index b57b75a..642906c 100644
--- a/Source/WebCore/dom/ScriptExecutionContext.h
+++ b/Source/WebCore/dom/ScriptExecutionContext.h
@@ -60,6 +60,7 @@ namespace WebCore {
class FileThread;
#endif
class MessagePort;
+ class DOMURL;
class SecurityOrigin;
class ScriptCallStack;
@@ -90,6 +91,7 @@ namespace WebCore {
SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
+ bool sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL);
void reportException(const String& errorMessage, int lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack>);
virtual void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL, PassRefPtr<ScriptCallStack>) = 0;
@@ -112,6 +114,11 @@ namespace WebCore {
void destroyedMessagePort(MessagePort*);
const HashSet<MessagePort*>& messagePorts() const { return m_messagePorts; }
+#if ENABLE(BLOB)
+ void createdDomUrl(DOMURL*);
+ void destroyedDomUrl(DOMURL*);
+ const HashSet<DOMURL*>& domUrls() const { return m_domUrls; }
+#endif
void ref() { refScriptExecutionContext(); }
void deref() { derefScriptExecutionContext(); }
@@ -166,11 +173,14 @@ namespace WebCore {
HashSet<MessagePort*> m_messagePorts;
HashMap<ActiveDOMObject*, void*> m_activeDOMObjects;
+ bool m_iteratingActiveDOMObjects;
+ bool m_inDestructor;
HashMap<int, DOMTimer*> m_timeouts;
#if ENABLE(BLOB)
HashSet<String> m_publicBlobURLs;
+ HashSet<DOMURL*> m_domUrls;
#endif
virtual void refScriptExecutionContext() = 0;
diff --git a/Source/WebCore/dom/ScriptableDocumentParser.cpp b/Source/WebCore/dom/ScriptableDocumentParser.cpp
index 0712a15..708dc1d 100644
--- a/Source/WebCore/dom/ScriptableDocumentParser.cpp
+++ b/Source/WebCore/dom/ScriptableDocumentParser.cpp
@@ -30,7 +30,7 @@ namespace WebCore {
ScriptableDocumentParser::ScriptableDocumentParser(Document* document)
: DecodedDataDocumentParser(document)
- , m_xssAuditor(0)
+ , m_wasCreatedByScript(false)
{
}
diff --git a/Source/WebCore/dom/ScriptableDocumentParser.h b/Source/WebCore/dom/ScriptableDocumentParser.h
index d9bf85c..35c2767 100644
--- a/Source/WebCore/dom/ScriptableDocumentParser.h
+++ b/Source/WebCore/dom/ScriptableDocumentParser.h
@@ -31,8 +31,6 @@
namespace WebCore {
-class XSSAuditor;
-
class ScriptableDocumentParser : public DecodedDataDocumentParser {
public:
// Only used by Document::open for deciding if its safe to act on a
@@ -49,8 +47,8 @@ public:
virtual int lineNumber() const = 0;
virtual TextPosition0 textPosition() const = 0;
- XSSAuditor* xssAuditor() const { return m_xssAuditor; }
- void setXSSAuditor(XSSAuditor* auditor) { m_xssAuditor = auditor; }
+ void setWasCreatedByScript(bool wasCreatedByScript) { m_wasCreatedByScript = wasCreatedByScript; }
+ bool wasCreatedByScript() const { return m_wasCreatedByScript; }
protected:
explicit ScriptableDocumentParser(Document*);
@@ -58,8 +56,8 @@ protected:
private:
virtual ScriptableDocumentParser* asScriptableDocumentParser() { return this; }
- // The XSSAuditor associated with this document parser.
- XSSAuditor* m_xssAuditor;
+ // http://www.whatwg.org/specs/web-apps/current-work/#script-created-parser
+ bool m_wasCreatedByScript;
};
}
diff --git a/Source/WebCore/dom/SelectElement.cpp b/Source/WebCore/dom/SelectElement.cpp
index 661ba88..a4da0ae 100644
--- a/Source/WebCore/dom/SelectElement.cpp
+++ b/Source/WebCore/dom/SelectElement.cpp
@@ -22,7 +22,6 @@
#include "SelectElement.h"
#include "Attribute.h"
-#include "CharacterNames.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "Element.h"
@@ -31,7 +30,6 @@
#include "FormDataList.h"
#include "Frame.h"
#include "HTMLFormElement.h"
-#include "HTMLKeygenElement.h"
#include "HTMLNames.h"
#include "HTMLSelectElement.h"
#include "KeyboardEvent.h"
@@ -43,6 +41,7 @@
#include "RenderMenuList.h"
#include "SpatialNavigation.h"
#include <wtf/Assertions.h>
+#include <wtf/unicode/CharacterNames.h>
#if ENABLE(WML)
#include "WMLNames.h"
@@ -315,11 +314,14 @@ int SelectElement::selectedIndex(const SelectElementData& data, const Element* e
void SelectElement::setSelectedIndex(SelectElementData& data, Element* element, int optionIndex, bool deselect, bool fireOnChangeNow, bool userDrivenChange)
{
- const Vector<Element*>& items = data.listItems(element);
- int listIndex = optionToListIndex(data, element, optionIndex);
+ if (optionIndex == -1 && !deselect && !data.multiple())
+ optionIndex = nextSelectableListIndex(data, element, -1);
if (!data.multiple())
deselect = true;
+ const Vector<Element*>& items = data.listItems(element);
+ int listIndex = optionToListIndex(data, element, optionIndex);
+
Element* excludeElement = 0;
if (OptionElement* optionElement = (listIndex >= 0 ? toOptionElement(items[listIndex]) : 0)) {
excludeElement = items[listIndex];
@@ -1024,12 +1026,8 @@ const Vector<Element*>& SelectElementData::listItems(const Element* element) con
SelectElement* toSelectElement(Element* element)
{
- if (element->isHTMLElement()) {
- if (element->hasTagName(HTMLNames::selectTag))
- return static_cast<HTMLSelectElement*>(element);
- if (element->hasTagName(HTMLNames::keygenTag))
- return static_cast<HTMLKeygenElement*>(element);
- }
+ if (element->isHTMLElement() && element->hasTagName(HTMLNames::selectTag))
+ return static_cast<HTMLSelectElement*>(element);
#if ENABLE(WML)
if (element->isWMLElement() && element->hasTagName(WMLNames::selectTag))
diff --git a/Source/WebCore/dom/SelectorNodeList.cpp b/Source/WebCore/dom/SelectorNodeList.cpp
index 039a29f..7611488 100644
--- a/Source/WebCore/dom/SelectorNodeList.cpp
+++ b/Source/WebCore/dom/SelectorNodeList.cpp
@@ -50,8 +50,8 @@ PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelec
CSSStyleSelector::SelectorChecker selectorChecker(document, strictParsing);
- if (strictParsing && rootNode->inDocument() && onlySelector && onlySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(onlySelector->m_value)) {
- Element* element = document->getElementById(onlySelector->m_value);
+ if (strictParsing && rootNode->inDocument() && onlySelector && onlySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(onlySelector->value())) {
+ Element* element = document->getElementById(onlySelector->value());
if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode)) && selectorChecker.checkSelector(onlySelector, element))
nodes.append(element);
} else {
diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp
index 47c532e..34266f1 100644
--- a/Source/WebCore/dom/Text.cpp
+++ b/Source/WebCore/dom/Text.cpp
@@ -23,6 +23,7 @@
#include "Text.h"
#include "ExceptionCode.h"
+#include "RenderCombineText.h"
#include "RenderText.h"
#include "TextBreakIterator.h"
#include <wtf/text/CString.h>
@@ -237,7 +238,7 @@ bool Text::rendererIsNeeded(RenderStyle *style)
return true;
}
-RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
+RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle* style)
{
#if ENABLE(SVG)
Node* parentOrHost = parentOrHostNode();
@@ -248,7 +249,10 @@ RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
)
return new (arena) RenderSVGInlineText(this, dataImpl());
#endif
-
+
+ if (style->hasTextCombine())
+ return new (arena) RenderCombineText(this, dataImpl());
+
return new (arena) RenderText(this, dataImpl());
}
diff --git a/Source/WebCore/dom/TextEvent.h b/Source/WebCore/dom/TextEvent.h
index d770d38..26c8b93 100644
--- a/Source/WebCore/dom/TextEvent.h
+++ b/Source/WebCore/dom/TextEvent.h
@@ -51,6 +51,7 @@ namespace WebCore {
virtual bool isTextEvent() const;
bool isLineBreak() const { return m_inputType == TextEventInputLineBreak; }
+ bool isComposition() const { return m_inputType == TextEventInputComposition; }
bool isBackTab() const { return m_inputType == TextEventInputBackTab; }
bool isPaste() const { return m_inputType == TextEventInputPaste; }
bool isDrop() const { return m_inputType == TextEventInputDrop; }
diff --git a/Source/WebCore/dom/TextEventInputType.h b/Source/WebCore/dom/TextEventInputType.h
index 2522ec4..f5a05eb 100644
--- a/Source/WebCore/dom/TextEventInputType.h
+++ b/Source/WebCore/dom/TextEventInputType.h
@@ -31,6 +31,7 @@ namespace WebCore {
enum TextEventInputType {
TextEventInputKeyboard, // any newline characters in the text are line breaks only, not paragraph separators.
TextEventInputLineBreak, // any tab characters in the text are backtabs.
+ TextEventInputComposition,
TextEventInputBackTab,
TextEventInputPaste,
TextEventInputDrop,
diff --git a/Source/WebCore/dom/ViewportArguments.cpp b/Source/WebCore/dom/ViewportArguments.cpp
index d3026e7..6dd1b8a 100644
--- a/Source/WebCore/dom/ViewportArguments.cpp
+++ b/Source/WebCore/dom/ViewportArguments.cpp
@@ -50,30 +50,6 @@ ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktop
ASSERT(availableWidth > 0 && availableHeight > 0);
- switch (int(args.width)) {
- case ViewportArguments::ValueDesktopWidth:
- args.width = desktopWidth;
- break;
- case ViewportArguments::ValueDeviceWidth:
- args.width = deviceWidth;
- break;
- case ViewportArguments::ValueDeviceHeight:
- args.width = deviceHeight;
- break;
- }
-
- switch (int(args.height)) {
- case ViewportArguments::ValueDesktopWidth:
- args.height = desktopWidth;
- break;
- case ViewportArguments::ValueDeviceWidth:
- args.height = deviceWidth;
- break;
- case ViewportArguments::ValueDeviceHeight:
- args.height = deviceHeight;
- break;
- }
-
switch (int(args.targetDensityDpi)) {
case ViewportArguments::ValueDeviceDPI:
args.targetDensityDpi = deviceDPI;
@@ -98,11 +74,30 @@ ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktop
availableHeight /= result.devicePixelRatio;
deviceWidth /= result.devicePixelRatio;
deviceHeight /= result.devicePixelRatio;
+ }
- if (args.width != ViewportArguments::ValueAuto)
- args.width /= result.devicePixelRatio;
- if (args.height != ViewportArguments::ValueAuto)
- args.height /= result.devicePixelRatio;
+ switch (int(args.width)) {
+ case ViewportArguments::ValueDesktopWidth:
+ args.width = desktopWidth;
+ break;
+ case ViewportArguments::ValueDeviceWidth:
+ args.width = deviceWidth;
+ break;
+ case ViewportArguments::ValueDeviceHeight:
+ args.width = deviceHeight;
+ break;
+ }
+
+ switch (int(args.height)) {
+ case ViewportArguments::ValueDesktopWidth:
+ args.height = desktopWidth;
+ break;
+ case ViewportArguments::ValueDeviceWidth:
+ args.height = deviceWidth;
+ break;
+ case ViewportArguments::ValueDeviceHeight:
+ args.height = deviceHeight;
+ break;
}
// Clamp values to range defined by spec and resolve minimum-scale and maximum-scale values