auto import from //depot/cupcake/@135843
diff --git a/WebCore/xml/DOMParser.cpp b/WebCore/xml/DOMParser.cpp
new file mode 100644
index 0000000..448dcb1
--- /dev/null
+++ b/WebCore/xml/DOMParser.cpp
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "DOMParser.h"
+
+#include "DOMImplementation.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+    
+PassRefPtr<Document> DOMParser::parseFromString(const String& str, const String& contentType)
+{
+    if (!DOMImplementation::isXMLMIMEType(contentType))
+        return 0;
+
+    RefPtr<Document> doc = DOMImplementation::createDocument(contentType, 0, false);
+
+    doc->open();
+    doc->write(str);
+    doc->finishParsing();
+    doc->close();
+        
+    return doc.release();
+}
+
+}
diff --git a/WebCore/xml/DOMParser.h b/WebCore/xml/DOMParser.h
new file mode 100644
index 0000000..5036d22
--- /dev/null
+++ b/WebCore/xml/DOMParser.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef DOMParser_h
+#define DOMParser_h
+
+#include <wtf/RefCounted.h>
+#include "Document.h"
+
+namespace WebCore {
+
+    class String;
+    
+    class DOMParser : public RefCounted<DOMParser> {
+    public:
+        static PassRefPtr<DOMParser> create() { return adoptRef(new DOMParser); }
+        
+        PassRefPtr<Document> parseFromString(const String& str, const String& contentType);
+        
+    private:
+        DOMParser() { }        
+    };
+
+}
+
+#endif // XMLSerializer.h
diff --git a/WebCore/xml/DOMParser.idl b/WebCore/xml/DOMParser.idl
new file mode 100644
index 0000000..9caaa21
--- /dev/null
+++ b/WebCore/xml/DOMParser.idl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+    interface [GenerateConstructor, CanBeConstructed] DOMParser {
+        Document parseFromString(in DOMString str, in DOMString contentType);
+    };
+}
diff --git a/WebCore/xml/NativeXPathNSResolver.cpp b/WebCore/xml/NativeXPathNSResolver.cpp
new file mode 100644
index 0000000..11faea6
--- /dev/null
+++ b/WebCore/xml/NativeXPathNSResolver.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov ([email protected])
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "NativeXPathNSResolver.h"
+
+#if ENABLE(XPATH)
+
+#include "Node.h"
+#include "PlatformString.h"
+#include "XMLNames.h"
+
+namespace WebCore {
+
+NativeXPathNSResolver::NativeXPathNSResolver(PassRefPtr<Node> node)
+    : m_node(node)
+{
+}
+
+NativeXPathNSResolver::~NativeXPathNSResolver()
+{
+}
+
+String NativeXPathNSResolver::lookupNamespaceURI(const String& prefix)
+{
+    // This is not done by Node::lookupNamespaceURI as per the DOM3 Core spec,
+    // but the XPath spec says that we should do it for XPathNSResolver.
+    if (prefix == "xml")
+        return XMLNames::xmlNamespaceURI;
+    
+    return m_node ? m_node->lookupNamespaceURI(prefix) : String();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/NativeXPathNSResolver.h b/WebCore/xml/NativeXPathNSResolver.h
new file mode 100644
index 0000000..212b929
--- /dev/null
+++ b/WebCore/xml/NativeXPathNSResolver.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov ([email protected])
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 NativeXPathNSResolver_h
+#define NativeXPathNSResolver_h
+
+#if ENABLE(XPATH)
+
+#include "XPathNSResolver.h"
+#include "Node.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+    class NativeXPathNSResolver : public XPathNSResolver {
+    public:
+        static PassRefPtr<NativeXPathNSResolver> create(PassRefPtr<Node> node) { return adoptRef(new NativeXPathNSResolver(node)); }
+        virtual ~NativeXPathNSResolver();
+
+        virtual String lookupNamespaceURI(const String& prefix);
+
+    private:
+        NativeXPathNSResolver(PassRefPtr<Node>);
+        RefPtr<Node> m_node;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(XPATH)
+
+#endif // NativeXPathNSResolver_h
diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp
new file mode 100644
index 0000000..67aba0b
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequest.cpp
@@ -0,0 +1,1317 @@
+/*
+ *  Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005-2007 Alexey Proskuryakov <[email protected]>
+ *  Copyright (C) 2007, 2008 Julien Chaffraix <[email protected]>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "XMLHttpRequest.h"
+
+#include "CString.h"
+#include "Console.h"
+#include "DOMImplementation.h"
+#include "DOMWindow.h"
+#include "Event.h"
+#include "EventException.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "File.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTTPParsers.h"
+#include "InspectorController.h"
+#include "JSDOMBinding.h"
+#include "JSDOMWindow.h"
+#include "KURL.h"
+#include "KURLHash.h"
+#include "Page.h"
+#include "Settings.h"
+#include "SubresourceLoader.h"
+#include "SystemTime.h"
+#include "TextResourceDecoder.h"
+#include "XMLHttpRequestException.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include "XMLHttpRequestUpload.h"
+#include "markup.h"
+#include <runtime/JSLock.h>
+
+namespace WebCore {
+
+struct PreflightResultCacheItem {
+    PreflightResultCacheItem(unsigned expiryDelta, bool credentials, HashSet<String>* methods, HashSet<String, CaseFoldingHash>* headers)
+        : m_absoluteExpiryTime(currentTime() + expiryDelta)
+        , m_credentials(credentials)
+        , m_methods(methods)
+        , m_headers(headers)
+    {
+    }
+
+    // FIXME: A better solution to holding onto the absolute expiration time might be
+    // to start a timer for the expiration delta, that removes this from the cache when
+    // it fires.
+    double m_absoluteExpiryTime;
+    bool m_credentials;
+    OwnPtr<HashSet<String> > m_methods;
+    OwnPtr<HashSet<String, CaseFoldingHash> > m_headers;
+};
+
+typedef HashMap<std::pair<String, KURL>, PreflightResultCacheItem*> PreflightResultCache;
+
+static PreflightResultCache& preflightResultCache()
+{
+    static PreflightResultCache cache;
+    return cache;
+}
+
+static void appendPreflightResultCacheEntry(String origin, KURL url, unsigned expiryDelta, 
+                                            bool credentials, HashSet<String>* methods, HashSet<String, CaseFoldingHash>* headers)
+{
+    ASSERT(!preflightResultCache().contains(std::make_pair(origin, url)));
+
+    PreflightResultCacheItem* item = new PreflightResultCacheItem(expiryDelta, credentials, methods, headers);
+    preflightResultCache().set(std::make_pair(origin, url), item);
+}
+
+static bool isSafeRequestHeader(const String& name)
+{
+    static HashSet<String, CaseFoldingHash> forbiddenHeaders;
+    static String proxyString("proxy-");
+    static String secString("sec-");
+    
+    if (forbiddenHeaders.isEmpty()) {
+        forbiddenHeaders.add("accept-charset");
+        forbiddenHeaders.add("accept-encoding");
+        forbiddenHeaders.add("connection");
+        forbiddenHeaders.add("content-length");
+        forbiddenHeaders.add("content-transfer-encoding");
+        forbiddenHeaders.add("date");
+        forbiddenHeaders.add("expect");
+        forbiddenHeaders.add("host");
+        forbiddenHeaders.add("keep-alive");
+        forbiddenHeaders.add("referer");
+        forbiddenHeaders.add("te");
+        forbiddenHeaders.add("trailer");
+        forbiddenHeaders.add("transfer-encoding");
+        forbiddenHeaders.add("upgrade");
+        forbiddenHeaders.add("via");
+    }
+    
+    return !forbiddenHeaders.contains(name) && !name.startsWith(proxyString, false) &&
+           !name.startsWith(secString, false);
+}
+
+static bool isOnAccessControlSimpleRequestHeaderWhitelist(const String& name)
+{
+    return equalIgnoringCase(name, "accept") || equalIgnoringCase(name, "accept-language") || equalIgnoringCase(name, "content-type");
+}
+
+static bool isOnAccessControlResponseHeaderWhitelist(const String& name)
+{
+    static HashSet<String, CaseFoldingHash> allowedHeaders;
+    if (allowedHeaders.isEmpty()) {
+        allowedHeaders.add("cache-control");
+        allowedHeaders.add("content-language");
+        allowedHeaders.add("content-type");
+        allowedHeaders.add("expires");
+        allowedHeaders.add("last-modified");
+        allowedHeaders.add("pragma");
+    }
+
+    return allowedHeaders.contains(name);
+}
+
+// Determines if a string is a valid token, as defined by
+// "token" in section 2.2 of RFC 2616.
+static bool isValidToken(const String& name)
+{
+    unsigned length = name.length();
+    for (unsigned i = 0; i < length; i++) {
+        UChar c = name[i];
+        
+        if (c >= 127 || c <= 32)
+            return false;
+        
+        if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
+            c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
+            c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
+            c == '{' || c == '}')
+            return false;
+    }
+    
+    return true;
+}
+    
+static bool isValidHeaderValue(const String& name)
+{
+    // FIXME: This should really match name against 
+    // field-value in section 4.2 of RFC 2616.
+        
+    return !name.contains('\r') && !name.contains('\n');
+}
+
+XMLHttpRequest::XMLHttpRequest(Document* doc)
+    : ActiveDOMObject(doc, this)
+    , m_async(true)
+    , m_includeCredentials(false)
+    , m_state(UNSENT)
+    , m_identifier(std::numeric_limits<unsigned long>::max())
+    , m_responseText("")
+    , m_createdDocument(false)
+    , m_error(false)
+    , m_uploadComplete(false)
+    , m_sameOriginRequest(true)
+    , m_inPreflight(false)
+    , m_receivedLength(0)
+    , m_lastSendLineNumber(0)
+{
+    ASSERT(document());
+}
+
+XMLHttpRequest::~XMLHttpRequest()
+{
+    if (m_upload)
+        m_upload->disconnectXMLHttpRequest();
+}
+
+Document* XMLHttpRequest::document() const
+{
+    ASSERT(scriptExecutionContext()->isDocument());
+    return static_cast<Document*>(scriptExecutionContext());
+}
+
+XMLHttpRequest::State XMLHttpRequest::readyState() const
+{
+    return m_state;
+}
+
+const JSC::UString& XMLHttpRequest::responseText() const
+{
+    return m_responseText;
+}
+
+Document* XMLHttpRequest::responseXML() const
+{
+    if (m_state != DONE)
+        return 0;
+
+    if (!m_createdDocument) {
+        if (m_response.isHTTP() && !responseIsXML()) {
+            // The W3C spec requires this.
+            m_responseXML = 0;
+        } else {
+            m_responseXML = document()->implementation()->createDocument(0);
+            m_responseXML->open();
+            m_responseXML->setURL(m_url);
+            // FIXME: set Last-Modified and cookies (currently, those are only available for HTMLDocuments).
+            m_responseXML->write(String(m_responseText));
+            m_responseXML->finishParsing();
+            m_responseXML->close();
+            
+            if (!m_responseXML->wellFormed())
+                m_responseXML = 0;
+        }
+        m_createdDocument = true;
+    }
+
+    return m_responseXML.get();
+}
+
+XMLHttpRequestUpload* XMLHttpRequest::upload()
+{
+    if (!m_upload)
+        m_upload = XMLHttpRequestUpload::create(this);
+    return m_upload.get();
+}
+
+void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
+{
+    EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+    if (iter == m_eventListeners.end()) {
+        ListenerVector listeners;
+        listeners.append(eventListener);
+        m_eventListeners.add(eventType, listeners);
+    } else {
+        ListenerVector& listeners = iter->second;
+        for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
+            if (*listenerIter == eventListener)
+                return;
+        
+        listeners.append(eventListener);
+        m_eventListeners.add(eventType, listeners);
+    }
+}
+
+void XMLHttpRequest::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
+{
+    EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+    if (iter == m_eventListeners.end())
+        return;
+
+    ListenerVector& listeners = iter->second;
+    for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
+        if (*listenerIter == eventListener) {
+            listeners.remove(listenerIter - listeners.begin());
+            return;
+        }
+}
+
+bool XMLHttpRequest::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec)
+{
+    // FIXME: check for other error conditions enumerated in the spec.
+    if (evt->type().isEmpty()) {
+        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+        return true;
+    }
+
+    ListenerVector listenersCopy = m_eventListeners.get(evt->type());
+    for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
+        evt->setTarget(this);
+        evt->setCurrentTarget(this);
+        listenerIter->get()->handleEvent(evt.get(), false);
+    }
+
+    return !evt->defaultPrevented();
+}
+
+void XMLHttpRequest::changeState(State newState)
+{
+    if (m_state != newState) {
+        m_state = newState;
+        callReadyStateChangeListener();
+    }
+}
+
+void XMLHttpRequest::callReadyStateChangeListener()
+{
+    if (!document() || !document()->frame())
+        return;
+
+    dispatchReadyStateChangeEvent();
+
+    if (m_state == DONE)
+        dispatchLoadEvent();
+}
+
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
+{
+    internalAbort();
+    State previousState = m_state;
+    m_state = UNSENT;
+    m_error = false;
+
+    m_uploadComplete = false;
+
+    // clear stuff from possible previous load
+    clearResponse();
+    clearRequest();
+
+    ASSERT(m_state == UNSENT);
+
+    if (!isValidToken(method)) {
+        ec = SYNTAX_ERR;
+        return;
+    }
+    
+    // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
+    String methodUpper(method.upper());
+    
+    if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
+        ec = SECURITY_ERR;
+        return;
+    }
+
+    m_url = url;
+
+    if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
+        || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
+        || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT" 
+        || methodUpper == "UNLOCK")
+        m_method = methodUpper;
+    else
+        m_method = method;
+
+    m_async = async;
+
+    ASSERT(!m_loader);
+
+    // Check previous state to avoid dispatching readyState event
+    // when calling open several times in a row.
+    if (previousState != OPENED)
+        changeState(OPENED);
+    else
+        m_state = OPENED;
+}
+
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec)
+{
+    KURL urlWithCredentials(url);
+    urlWithCredentials.setUser(user);
+    
+    open(method, urlWithCredentials, async, ec);
+}
+
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
+{
+    KURL urlWithCredentials(url);
+    urlWithCredentials.setUser(user);
+    urlWithCredentials.setPass(password);
+    
+    open(method, urlWithCredentials, async, ec);
+}
+
+bool XMLHttpRequest::initSend(ExceptionCode& ec)
+{
+    if (!document())
+        return false;
+
+    if (m_state != OPENED || m_loader) {
+        ec = INVALID_STATE_ERR;
+        return false;
+    }
+
+    m_error = false;
+    return true;
+}
+
+void XMLHttpRequest::send(ExceptionCode& ec)
+{
+    send(String(), ec);
+}
+
+void XMLHttpRequest::send(Document* document, ExceptionCode& ec)
+{
+    ASSERT(document);
+
+    if (!initSend(ec))
+        return;
+
+    if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+        String contentType = getRequestHeader("Content-Type");
+        if (contentType.isEmpty()) {
+#if ENABLE(DASHBOARD_SUPPORT)
+            Settings* settings = document->settings();
+            if (settings && settings->usesDashboardBackwardCompatibilityMode())
+                setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
+            else
+#endif
+                // FIXME: this should include the charset used for encoding.
+                setRequestHeaderInternal("Content-Type", "application/xml");
+        }
+
+        // FIXME: According to XMLHttpRequest Level 2, this should use the Document.innerHTML algorithm
+        // from the HTML5 specification to serialize the document.
+        String body = createMarkup(document);
+
+        // FIXME: this should use value of document.inputEncoding to determine the encoding to use.
+        TextEncoding encoding = UTF8Encoding();
+        m_requestEntityBody = FormData::create(encoding.encode(body.characters(), body.length(), EntitiesForUnencodables));
+        if (m_upload)
+            m_requestEntityBody->setAlwaysStream(true);
+    }
+
+    createRequest(ec);
+}
+
+void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
+{
+    if (!initSend(ec))
+        return;
+
+    if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+        String contentType = getRequestHeader("Content-Type");
+        if (contentType.isEmpty()) {
+#if ENABLE(DASHBOARD_SUPPORT)
+            Settings* settings = document()->settings();
+            if (settings && settings->usesDashboardBackwardCompatibilityMode())
+                setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
+            else
+#endif
+                setRequestHeaderInternal("Content-Type", "application/xml");
+        }
+
+        m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));
+        if (m_upload)
+            m_requestEntityBody->setAlwaysStream(true);
+    }
+
+    createRequest(ec);
+}
+
+void XMLHttpRequest::send(File* body, ExceptionCode& ec)
+{
+    if (!initSend(ec))
+        return;
+
+    if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+        // FIXME: Should we set a Content-Type if one is not set.
+        // FIXME: add support for uploading bundles.
+        m_requestEntityBody = FormData::create();
+        m_requestEntityBody->appendFile(body->path(), false);
+    }
+
+    createRequest(ec);
+}
+
+void XMLHttpRequest::createRequest(ExceptionCode& ec)
+{
+    if (m_async) {
+        dispatchLoadStartEvent();
+        if (m_requestEntityBody && m_upload)
+            m_upload->dispatchLoadStartEvent();
+    }
+
+    m_sameOriginRequest = document()->securityOrigin()->canRequest(m_url);
+
+    if (!m_sameOriginRequest) {
+        makeCrossSiteAccessRequest(ec);
+        return;
+    }
+
+    makeSameOriginRequest(ec);
+}
+
+void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec)
+{
+    ASSERT(m_sameOriginRequest);
+
+    ResourceRequest request(m_url);
+    request.setHTTPMethod(m_method);
+
+    if (m_requestEntityBody) {
+        ASSERT(m_method != "GET");
+        request.setHTTPBody(m_requestEntityBody.release());
+    }
+
+    if (m_requestHeaders.size() > 0)
+        request.addHTTPHeaderFields(m_requestHeaders);
+
+    if (m_async)
+        loadRequestAsynchronously(request);
+    else
+        loadRequestSynchronously(request, ec);
+}
+
+bool XMLHttpRequest::isSimpleCrossSiteAccessRequest() const
+{
+    if (m_method != "GET" && m_method != "POST")
+        return false;
+
+    HTTPHeaderMap::const_iterator end = m_requestHeaders.end();
+    for (HTTPHeaderMap::const_iterator it = m_requestHeaders.begin(); it != end; ++it) {
+        if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->first))
+            return false;
+    }
+
+    return true;
+}
+
+void XMLHttpRequest::makeCrossSiteAccessRequest(ExceptionCode& ec)
+{
+    ASSERT(!m_sameOriginRequest);
+
+    if (isSimpleCrossSiteAccessRequest())
+        makeSimpleCrossSiteAccessRequest(ec);
+    else
+        makeCrossSiteAccessRequestWithPreflight(ec);
+}
+
+void XMLHttpRequest::makeSimpleCrossSiteAccessRequest(ExceptionCode& ec)
+{
+    ASSERT(isSimpleCrossSiteAccessRequest());
+
+    KURL url = m_url;
+    url.setUser(String());
+    url.setPass(String());
+ 
+    ResourceRequest request(url);
+    request.setHTTPMethod(m_method);
+    request.setAllowHTTPCookies(m_includeCredentials);
+    request.setHTTPOrigin(document()->securityOrigin()->toString());
+
+    if (m_requestHeaders.size() > 0)
+        request.addHTTPHeaderFields(m_requestHeaders);
+
+    if (m_async)
+        loadRequestAsynchronously(request);
+    else
+        loadRequestSynchronously(request, ec);
+}
+
+static bool canSkipPrelight(PreflightResultCache::iterator cacheIt, bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders)
+{
+    PreflightResultCacheItem* item = cacheIt->second;
+    if (item->m_absoluteExpiryTime < currentTime())
+        return false;
+    if (includeCredentials && !item->m_credentials)
+        return false;
+    if (!item->m_methods->contains(method) && method != "GET" && method != "POST")
+        return false;
+    HTTPHeaderMap::const_iterator end = requestHeaders.end();
+    for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) {
+        if (!item->m_headers->contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first))
+            return false;
+    }
+
+    return true;
+}
+
+void XMLHttpRequest::makeCrossSiteAccessRequestWithPreflight(ExceptionCode& ec)
+{
+    String origin = document()->securityOrigin()->toString();
+    KURL url = m_url;
+    url.setUser(String());
+    url.setPass(String());
+
+    bool skipPreflight = false;
+
+    PreflightResultCache::iterator cacheIt = preflightResultCache().find(std::make_pair(origin, url));
+    if (cacheIt != preflightResultCache().end()) {
+        skipPreflight = canSkipPrelight(cacheIt, m_includeCredentials, m_method, m_requestHeaders);
+        if (!skipPreflight) {
+            delete cacheIt->second;
+            preflightResultCache().remove(cacheIt);
+        }
+    }
+
+    if (!skipPreflight) {
+        m_inPreflight = true;
+        ResourceRequest preflightRequest(url);
+        preflightRequest.setHTTPMethod("OPTIONS");
+        preflightRequest.setHTTPHeaderField("Origin", origin);
+        preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", m_method);
+
+        if (m_requestHeaders.size() > 0) {
+            Vector<UChar> headerBuffer;
+            HTTPHeaderMap::const_iterator it = m_requestHeaders.begin();
+            append(headerBuffer, it->first);
+            ++it;
+
+            HTTPHeaderMap::const_iterator end = m_requestHeaders.end();
+            for (; it != end; ++it) {
+                headerBuffer.append(',');
+                headerBuffer.append(' ');
+                append(headerBuffer, it->first);
+            }
+
+            preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));
+            preflightRequest.addHTTPHeaderFields(m_requestHeaders);
+        }
+
+        if (m_async) {
+            loadRequestAsynchronously(preflightRequest);
+            return;
+        }
+
+        loadRequestSynchronously(preflightRequest, ec);
+        m_inPreflight = false;
+
+        if (ec)
+            return;
+    }
+
+    // Send the actual request.
+    ResourceRequest request(url);
+    request.setHTTPMethod(m_method);
+    request.setAllowHTTPCookies(m_includeCredentials);
+    request.setHTTPHeaderField("Origin", origin);
+
+    if (m_requestHeaders.size() > 0)
+        request.addHTTPHeaderFields(m_requestHeaders);
+
+    if (m_requestEntityBody) {
+        ASSERT(m_method != "GET");
+        request.setHTTPBody(m_requestEntityBody.release());
+    }
+
+    if (m_async) {
+        loadRequestAsynchronously(request);
+        return;
+    }
+
+    loadRequestSynchronously(request, ec);
+}
+
+void XMLHttpRequest::handleAsynchronousPreflightResult()
+{
+    ASSERT(m_inPreflight);
+    ASSERT(m_async);
+
+    m_inPreflight = false;
+
+    KURL url = m_url;
+    url.setUser(String());
+    url.setPass(String());
+
+    ResourceRequest request(url);
+    request.setHTTPMethod(m_method);
+    request.setAllowHTTPCookies(m_includeCredentials);
+    request.setHTTPOrigin(document()->securityOrigin()->toString());
+
+    if (m_requestHeaders.size() > 0)
+        request.addHTTPHeaderFields(m_requestHeaders);
+
+    if (m_requestEntityBody) {
+        ASSERT(m_method != "GET");
+        request.setHTTPBody(m_requestEntityBody.release());
+    }
+
+    loadRequestAsynchronously(request);
+}
+
+void XMLHttpRequest::loadRequestSynchronously(ResourceRequest& request, ExceptionCode& ec)
+{
+    ASSERT(!m_async);
+    Vector<char> data;
+    ResourceError error;
+    ResourceResponse response;
+
+    if (document()->frame())
+        m_identifier = document()->frame()->loader()->loadResourceSynchronously(request, error, response, data);
+
+    m_loader = 0;
+
+    // No exception for file:/// resources, see <rdar://problem/4962298>.
+    // Also, if we have an HTTP response, then it wasn't a network error in fact.
+    if (error.isNull() || request.url().isLocalFile() || response.httpStatusCode() > 0) {
+        processSyncLoadResults(data, response, ec);
+        return;
+    }
+
+    if (error.isCancellation()) {
+        abortError();
+        ec = XMLHttpRequestException::ABORT_ERR;
+        return;
+    }
+
+    networkError();
+    ec = XMLHttpRequestException::NETWORK_ERR;
+}
+
+
+void XMLHttpRequest::loadRequestAsynchronously(ResourceRequest& request)
+{
+    ASSERT(m_async);
+    // SubresourceLoader::create can return null here, for example if we're no longer attached to a page.
+    // This is true while running onunload handlers.
+    // FIXME: We need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
+    // FIXME: Maybe create can return null for other reasons too?
+    // We need to keep content sniffing enabled for local files due to CFNetwork not providing a MIME type
+    // for local files otherwise, <rdar://problem/5671813>.
+    bool sendResourceLoadCallbacks = !m_inPreflight;
+    m_loader = SubresourceLoader::create(document()->frame(), this, request, false, sendResourceLoadCallbacks, request.url().isLocalFile());
+
+    if (m_loader) {
+        // Neither this object nor the JavaScript wrapper should be deleted while
+        // a request is in progress because we need to keep the listeners alive,
+        // and they are referenced by the JavaScript wrapper.
+        setPendingActivity(this);
+    }
+}
+
+void XMLHttpRequest::abort()
+{
+    bool sendFlag = m_loader;
+
+    internalAbort();
+
+    // Clear headers as required by the spec
+    m_requestHeaders.clear();
+    
+    if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
+        m_state = UNSENT;
+     else {
+        ASSERT(!m_loader);
+        changeState(DONE);
+        m_state = UNSENT;
+    }
+
+    dispatchAbortEvent();
+    if (!m_uploadComplete) {
+        m_uploadComplete = true;
+        if (m_upload)
+            m_upload->dispatchAbortEvent();
+    }
+}
+
+void XMLHttpRequest::internalAbort()
+{
+    bool hadLoader = m_loader;
+
+    m_error = true;
+
+    // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization.
+    m_receivedLength = 0;
+
+    if (hadLoader) {
+        m_loader->cancel();
+        m_loader = 0;
+    }
+
+    m_decoder = 0;
+
+    if (hadLoader)
+        dropProtection();
+}
+
+void XMLHttpRequest::clearResponse()
+{
+    m_response = ResourceResponse();
+    {
+        JSC::JSLock lock(false);
+        m_responseText = "";
+    }
+    m_createdDocument = false;
+    m_responseXML = 0;
+}
+
+void XMLHttpRequest::clearRequest()
+{
+    m_requestHeaders.clear();
+    m_requestEntityBody = 0;
+}
+
+void XMLHttpRequest::genericError()
+{
+    clearResponse();
+    clearRequest();
+    m_error = true;
+
+    // The spec says we should "Synchronously switch the state to DONE." and then "Synchronously dispatch a readystatechange event on the object"
+    // but this does not match Firefox.
+}
+
+void XMLHttpRequest::networkError()
+{
+    genericError();
+    dispatchErrorEvent();
+    if (!m_uploadComplete) {
+        m_uploadComplete = true;
+        if (m_upload)
+            m_upload->dispatchErrorEvent();
+    }
+}
+
+void XMLHttpRequest::abortError()
+{
+    genericError();
+    dispatchAbortEvent();
+    if (!m_uploadComplete) {
+        m_uploadComplete = true;
+        if (m_upload)
+            m_upload->dispatchAbortEvent();
+    }
+}
+
+void XMLHttpRequest::dropProtection()        
+{
+    // The XHR object itself holds on to the responseText, and
+    // thus has extra cost even independent of any
+    // responseText or responseXML objects it has handed
+    // out. But it is protected from GC while loading, so this
+    // can't be recouped until the load is done, so only
+    // report the extra cost at that point.
+
+    if (JSDOMWindow* window = toJSDOMWindow(document()->frame())) {
+        if (JSC::JSValue* wrapper = getCachedDOMObjectWrapper(*window->globalData(), this))
+            JSC::Heap::heap(wrapper)->reportExtraMemoryCost(m_responseText.size() * 2);
+    }
+
+    unsetPendingActivity(this);
+}
+
+void XMLHttpRequest::overrideMimeType(const String& override)
+{
+    m_mimeTypeOverride = override;
+}
+    
+void XMLHttpRequest::setRequestHeader(const String& name, const String& value, ExceptionCode& ec)
+{
+    if (m_state != OPENED || m_loader) {
+#if ENABLE(DASHBOARD_SUPPORT)
+        Settings* settings = document() ? document()->settings() : 0;
+        if (settings && settings->usesDashboardBackwardCompatibilityMode())
+            return;
+#endif
+
+        ec = INVALID_STATE_ERR;
+        return;
+    }
+
+    if (!isValidToken(name) || !isValidHeaderValue(value)) {
+        ec = SYNTAX_ERR;
+        return;
+    }
+
+    // A privileged script (e.g. a Dashboard widget) can set any headers.
+    if (!document()->securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
+        if (document() && document()->frame())
+            document()->frame()->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Refused to set unsafe header \"" + name + "\"", 1, String());
+        return;
+    }
+
+    setRequestHeaderInternal(name, value);
+}
+
+void XMLHttpRequest::setRequestHeaderInternal(const String& name, const String& value)
+{
+    pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value); 
+    if (!result.second)
+        result.first->second += ", " + value;
+}
+
+String XMLHttpRequest::getRequestHeader(const String& name) const
+{
+    return m_requestHeaders.get(name);
+}
+
+String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
+{
+    if (m_state < LOADING) {
+        ec = INVALID_STATE_ERR;
+        return "";
+    }
+
+    Vector<UChar> stringBuilder;
+    String separator(": ");
+
+    HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
+    for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
+        if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->first))
+            continue;
+
+        stringBuilder.append(it->first.characters(), it->first.length());
+        stringBuilder.append(separator.characters(), separator.length());
+        stringBuilder.append(it->second.characters(), it->second.length());
+        stringBuilder.append((UChar)'\r');
+        stringBuilder.append((UChar)'\n');
+    }
+
+    return String::adopt(stringBuilder);
+}
+
+String XMLHttpRequest::getResponseHeader(const String& name, ExceptionCode& ec) const
+{
+    if (m_state < LOADING) {
+        ec = INVALID_STATE_ERR;
+        return "";
+    }
+
+    if (!isValidToken(name))
+        return "";
+
+    if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name))
+        return "";
+
+    return m_response.httpHeaderField(name);
+}
+
+String XMLHttpRequest::responseMIMEType() const
+{
+    String mimeType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
+    if (mimeType.isEmpty()) {
+        if (m_response.isHTTP())
+            mimeType = extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
+        else
+            mimeType = m_response.mimeType();
+    }
+    if (mimeType.isEmpty())
+        mimeType = "text/xml";
+    
+    return mimeType;
+}
+
+bool XMLHttpRequest::responseIsXML() const
+{
+    return DOMImplementation::isXMLMIMEType(responseMIMEType());
+}
+
+int XMLHttpRequest::status(ExceptionCode& ec) const
+{
+    if (m_response.httpStatusCode())
+        return m_response.httpStatusCode();
+
+    if (m_state == OPENED) {
+        // Firefox only raises an exception in this state; we match it.
+        // Note the case of local file requests, where we have no HTTP response code! Firefox never raises an exception for those, but we match HTTP case for consistency.
+        ec = INVALID_STATE_ERR;
+    }
+
+    return 0;
+}
+
+String XMLHttpRequest::statusText(ExceptionCode& ec) const
+{
+    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=3547> XMLHttpRequest.statusText returns always "OK".
+    if (m_response.httpStatusCode())
+        return "OK";
+
+    if (m_state == OPENED) {
+        // See comments in getStatus() above.
+        ec = INVALID_STATE_ERR;
+    }
+
+    return String();
+}
+
+void XMLHttpRequest::processSyncLoadResults(const Vector<char>& data, const ResourceResponse& response, ExceptionCode& ec)
+{
+    if (m_sameOriginRequest && !document()->securityOrigin()->canRequest(response.url())) {
+        abort();
+        return;
+    }
+    
+    didReceiveResponse(0, response);
+    changeState(HEADERS_RECEIVED);
+
+    const char* bytes = static_cast<const char*>(data.data());
+    int len = static_cast<int>(data.size());
+    didReceiveData(0, bytes, len);
+
+    didFinishLoading(0);
+    if (m_error)
+        ec = XMLHttpRequestException::NETWORK_ERR;
+}
+
+void XMLHttpRequest::didFail(SubresourceLoader* loader, const ResourceError& error)
+{
+    // If we are already in an error state, for instance we called abort(), bail out early.
+    if (m_error)
+        return;
+
+    if (error.isCancellation()) {
+        abortError();
+        return;
+    }
+
+    networkError();
+    return;
+}
+
+void XMLHttpRequest::didFinishLoading(SubresourceLoader* loader)
+{
+    if (m_error)
+        return;
+
+    if (m_inPreflight) {
+        didFinishLoadingPreflight(loader);
+        return;
+    }
+
+    ASSERT(loader == m_loader);
+
+    if (m_state < HEADERS_RECEIVED)
+        changeState(HEADERS_RECEIVED);
+
+    {
+        JSC::JSLock lock(false);
+        if (m_decoder)
+            m_responseText += m_decoder->flush();
+    }
+
+    if (Frame* frame = document()->frame()) {
+        if (Page* page = frame->page()) {
+            page->inspectorController()->resourceRetrievedByXMLHttpRequest(m_loader ? m_loader->identifier() : m_identifier, m_responseText);
+            page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, "XHR finished loading: \"" + m_url + "\".", m_lastSendLineNumber, m_lastSendURL);
+        }
+    }
+
+    bool hadLoader = m_loader;
+    m_loader = 0;
+
+    changeState(DONE);
+    m_decoder = 0;
+
+    if (hadLoader)
+        dropProtection();
+}
+
+void XMLHttpRequest::didFinishLoadingPreflight(SubresourceLoader* loader)
+{
+    ASSERT(m_inPreflight);
+    ASSERT(!m_sameOriginRequest);
+
+    // FIXME: this can probably be moved to didReceiveResponsePreflight.
+    if (m_async)
+        handleAsynchronousPreflightResult();
+
+    if (m_loader)
+        unsetPendingActivity(this);
+}
+
+void XMLHttpRequest::willSendRequest(SubresourceLoader*, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+    // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
+    if (!document()->securityOrigin()->canRequest(request.url())) {
+        internalAbort();
+        networkError();
+    }
+}
+
+void XMLHttpRequest::didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+    if (!m_upload)
+        return;
+
+    m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent);
+
+    if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
+        m_uploadComplete = true;
+        m_upload->dispatchLoadEvent();
+    }
+}
+
+bool XMLHttpRequest::accessControlCheck(const ResourceResponse& response)
+{
+    const String& accessControlOriginString = response.httpHeaderField("Access-Control-Origin");
+    if (accessControlOriginString == "*" && !m_includeCredentials)
+        return true;
+
+    KURL accessControlOriginURL(accessControlOriginString);
+    if (!accessControlOriginURL.isValid())
+        return false;
+
+    RefPtr<SecurityOrigin> accessControlOrigin = SecurityOrigin::create(accessControlOriginURL);
+    if (!accessControlOrigin->isSameSchemeHostPort(document()->securityOrigin()))
+        return false;
+
+    if (m_includeCredentials) {
+        const String& accessControlCredentialsString = response.httpHeaderField("Access-Control-Credentials");
+        if (accessControlCredentialsString != "true")
+            return false;
+    }
+
+    return true;
+}
+
+void XMLHttpRequest::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response)
+{
+    if (m_inPreflight) {
+        didReceiveResponsePreflight(loader, response);
+        return;
+    }
+
+    if (!m_sameOriginRequest) {
+        if (!accessControlCheck(response)) {
+            networkError();
+            return;
+        }
+    }
+
+    m_response = response;
+    m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
+    if (m_responseEncoding.isEmpty())
+        m_responseEncoding = response.textEncodingName();
+}
+
+template<class HashType>
+static bool parseAccessControlAllowList(const String& string, HashSet<String, HashType>* set)
+{
+    int start = 0;
+    int end;
+    while ((end = string.find(',', start)) != -1) {
+        if (start == end)
+            return false;
+
+        // FIXME: this could be made more efficient by not not allocating twice.
+        set->add(string.substring(start, end - start).stripWhiteSpace());
+        start = end + 1;
+    }
+    if (start != static_cast<int>(string.length()))
+        set->add(string.substring(start).stripWhiteSpace());
+
+    return true;
+}
+
+static bool parseAccessControlMaxAge(const String& string, unsigned& expiryDelta)
+{
+    // FIXME: this will not do the correct thing for a number starting with a '+'
+    bool ok = false;
+    expiryDelta = string.toUIntStrict(&ok);
+    return ok;
+}
+
+void XMLHttpRequest::didReceiveResponsePreflight(SubresourceLoader*, const ResourceResponse& response)
+{
+    ASSERT(m_inPreflight);
+    ASSERT(!m_sameOriginRequest);
+
+    if (!accessControlCheck(response)) {
+        networkError();
+        return;
+    }
+
+    OwnPtr<HashSet<String> > methods(new HashSet<String>);
+    if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Methods"), methods.get())) {
+        networkError();
+        return;
+    }
+
+    if (!methods->contains(m_method) && m_method != "GET" && m_method != "POST") {
+        networkError();
+        return;
+    }
+
+    OwnPtr<HashSet<String, CaseFoldingHash> > headers(new HashSet<String, CaseFoldingHash>);
+    if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Headers"), headers.get())) {
+        networkError();
+        return;
+    }
+
+    HTTPHeaderMap::const_iterator end = m_requestHeaders.end();
+    for (HTTPHeaderMap::const_iterator it = m_requestHeaders.begin(); it != end; ++it) {
+        if (!headers->contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first)) {
+            networkError();
+            return;
+        }
+    }
+
+    unsigned expiryDelta = 0;
+    if (!parseAccessControlMaxAge(response.httpHeaderField("Access-Control-Max-Age"), expiryDelta))
+        expiryDelta = 5;
+
+    appendPreflightResultCacheEntry(document()->securityOrigin()->toString(), m_url, expiryDelta, m_includeCredentials, methods.release(), headers.release());
+}
+
+void XMLHttpRequest::receivedCancellation(SubresourceLoader*, const AuthenticationChallenge& challenge)
+{
+    m_response = challenge.failureResponse();
+}
+
+void XMLHttpRequest::didReceiveData(SubresourceLoader*, const char* data, int len)
+{
+    if (m_inPreflight)
+        return;
+
+    if (m_state < HEADERS_RECEIVED)
+        changeState(HEADERS_RECEIVED);
+  
+    if (!m_decoder) {
+        if (!m_responseEncoding.isEmpty())
+            m_decoder = TextResourceDecoder::create("text/plain", m_responseEncoding);
+        // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
+        else if (responseIsXML())
+            m_decoder = TextResourceDecoder::create("application/xml");
+        else if (responseMIMEType() == "text/html")
+            m_decoder = TextResourceDecoder::create("text/html", "UTF-8");
+        else
+            m_decoder = TextResourceDecoder::create("text/plain", "UTF-8");
+    }
+    if (len == 0)
+        return;
+
+    if (len == -1)
+        len = strlen(data);
+
+    String decoded = m_decoder->decode(data, len);
+
+    {
+        JSC::JSLock lock(false);
+        m_responseText += decoded;
+    }
+
+    if (!m_error) {
+        updateAndDispatchOnProgress(len);
+
+        if (m_state != LOADING)
+            changeState(LOADING);
+        else
+            // Firefox calls readyStateChanged every time it receives data, 4449442
+            callReadyStateChangeListener();
+    }
+}
+
+void XMLHttpRequest::updateAndDispatchOnProgress(unsigned int len)
+{
+    long long expectedLength = m_response.expectedContentLength();
+    m_receivedLength += len;
+
+    // FIXME: the spec requires that we dispatch the event according to the least
+    // frequent method between every 350ms (+/-200ms) and for every byte received.
+    dispatchProgressEvent(expectedLength);
+}
+
+void XMLHttpRequest::dispatchReadyStateChangeEvent()
+{
+    RefPtr<Event> evt = Event::create(eventNames().readystatechangeEvent, false, false);
+    if (m_onReadyStateChangeListener) {
+        evt->setTarget(this);
+        evt->setCurrentTarget(this);
+        m_onReadyStateChangeListener->handleEvent(evt.get(), false);
+    }
+
+    ExceptionCode ec = 0;
+    dispatchEvent(evt.release(), ec);
+    ASSERT(!ec);
+}
+
+void XMLHttpRequest::dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+{
+    RefPtr<XMLHttpRequestProgressEvent> evt = XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total);
+    if (listener) {
+        evt->setTarget(this);
+        evt->setCurrentTarget(this);
+        listener->handleEvent(evt.get(), false);
+    }
+
+    ExceptionCode ec = 0;
+    dispatchEvent(evt.release(), ec);
+    ASSERT(!ec);
+}
+
+void XMLHttpRequest::dispatchAbortEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onAbortListener.get(), eventNames().abortEvent, false, 0, 0);
+}
+
+void XMLHttpRequest::dispatchErrorEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onErrorListener.get(), eventNames().errorEvent, false, 0, 0);
+}
+
+void XMLHttpRequest::dispatchLoadEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onLoadListener.get(), eventNames().loadEvent, false, 0, 0);
+}
+
+void XMLHttpRequest::dispatchLoadStartEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onLoadStartListener.get(), eventNames().loadstartEvent, false, 0, 0);
+}
+
+void XMLHttpRequest::dispatchProgressEvent(long long expectedLength)
+{
+    dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, 
+                                        static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength));
+}
+
+void XMLHttpRequest::stop()
+{
+    internalAbort();
+}
+
+void XMLHttpRequest::contextDestroyed()
+{
+    ActiveDOMObject::contextDestroyed();
+    internalAbort();
+}
+
+ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
+{
+    return ActiveDOMObject::scriptExecutionContext();
+}
+
+} // namespace WebCore 
diff --git a/WebCore/xml/XMLHttpRequest.h b/WebCore/xml/XMLHttpRequest.h
new file mode 100644
index 0000000..6962ab1
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequest.h
@@ -0,0 +1,232 @@
+/*
+ *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006 Alexey Proskuryakov <[email protected]>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XMLHttpRequest_h
+#define XMLHttpRequest_h
+
+#include "ActiveDOMObject.h"
+#include "AtomicStringHash.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include "FormData.h"
+#include "ResourceResponse.h"
+#include "SubresourceLoaderClient.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class Document;
+class File;
+class TextResourceDecoder;
+
+class XMLHttpRequest : public RefCounted<XMLHttpRequest>, public EventTarget, private SubresourceLoaderClient, public ActiveDOMObject {
+public:
+    static PassRefPtr<XMLHttpRequest> create(Document* document) { return adoptRef(new XMLHttpRequest(document)); }
+    ~XMLHttpRequest();
+
+    // These exact numeric values are important because JS expects them.
+    enum State {
+        UNSENT = 0,
+        OPENED = 1,
+        HEADERS_RECEIVED = 2,
+        LOADING = 3,
+        DONE = 4
+    };
+
+    virtual XMLHttpRequest* toXMLHttpRequest() { return this; }
+
+    virtual void contextDestroyed();
+    virtual void stop();
+
+    virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+    String statusText(ExceptionCode&) const;
+    int status(ExceptionCode&) const;
+    State readyState() const;
+    void open(const String& method, const KURL&, bool async, ExceptionCode&);
+    void open(const String& method, const KURL&, bool async, const String& user, ExceptionCode&);
+    void open(const String& method, const KURL&, bool async, const String& user, const String& password, ExceptionCode&);
+    void send(ExceptionCode&);
+    void send(Document*, ExceptionCode&);
+    void send(const String&, ExceptionCode&);
+    void send(File*, ExceptionCode&);
+    void abort();
+    void setRequestHeader(const String& name, const String& value, ExceptionCode&);
+    void overrideMimeType(const String& override);
+    String getAllResponseHeaders(ExceptionCode&) const;
+    String getResponseHeader(const String& name, ExceptionCode&) const;
+    const JSC::UString& responseText() const;
+    Document* responseXML() const;
+    void setLastSendLineNumber(unsigned lineNumber) { m_lastSendLineNumber = lineNumber; }
+    void setLastSendURL(JSC::UString url) { m_lastSendURL = url; }
+
+    XMLHttpRequestUpload* upload();
+    XMLHttpRequestUpload* optionalUpload() const { return m_upload.get(); }
+
+    void setOnreadystatechange(PassRefPtr<EventListener> eventListener) { m_onReadyStateChangeListener = eventListener; }
+    EventListener* onreadystatechange() const { return m_onReadyStateChangeListener.get(); }
+
+    void setOnabort(PassRefPtr<EventListener> eventListener) { m_onAbortListener = eventListener; }
+    EventListener* onabort() const { return m_onAbortListener.get(); }
+
+    void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
+    EventListener* onerror() const { return m_onErrorListener.get(); }
+
+    void setOnload(PassRefPtr<EventListener> eventListener) { m_onLoadListener = eventListener; }
+    EventListener* onload() const { return m_onLoadListener.get(); }
+
+    void setOnloadstart(PassRefPtr<EventListener> eventListener) { m_onLoadStartListener = eventListener; }
+    EventListener* onloadstart() const { return m_onLoadStartListener.get(); }
+
+    void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; }
+    EventListener* onprogress() const { return m_onProgressListener.get(); }
+
+    typedef Vector<RefPtr<EventListener> > ListenerVector;
+    typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
+
+    // useCapture is not used, even for add/remove pairing (for Firefox compatibility).
+    virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+    virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+    virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
+    EventListenersMap& eventListeners() { return m_eventListeners; }
+
+    using RefCounted<XMLHttpRequest>::ref;
+    using RefCounted<XMLHttpRequest>::deref;
+
+private:
+    XMLHttpRequest(Document*);
+    
+    virtual void refEventTarget() { ref(); }
+    virtual void derefEventTarget() { deref(); }
+
+    Document* document() const;
+
+    virtual void willSendRequest(SubresourceLoader*, ResourceRequest& request, const ResourceResponse& redirectResponse);
+    virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+    virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&);
+    virtual void didReceiveData(SubresourceLoader*, const char* data, int size);
+    virtual void didFail(SubresourceLoader*, const ResourceError&);
+    virtual void didFinishLoading(SubresourceLoader*);
+    virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&);
+
+    // Special versions for the preflight
+    void didReceiveResponsePreflight(SubresourceLoader*, const ResourceResponse&);
+    void didFinishLoadingPreflight(SubresourceLoader*);
+
+    void processSyncLoadResults(const Vector<char>& data, const ResourceResponse&, ExceptionCode&);
+    void updateAndDispatchOnProgress(unsigned int len);
+
+    String responseMIMEType() const;
+    bool responseIsXML() const;
+
+    bool initSend(ExceptionCode&);
+
+    String getRequestHeader(const String& name) const;
+    void setRequestHeaderInternal(const String& name, const String& value);
+
+    void changeState(State newState);
+    void callReadyStateChangeListener();
+    void dropProtection();
+    void internalAbort();
+    void clearResponse();
+    void clearRequest();
+
+    void createRequest(ExceptionCode&);
+
+    void makeSameOriginRequest(ExceptionCode&);
+    void makeCrossSiteAccessRequest(ExceptionCode&);
+
+    void makeSimpleCrossSiteAccessRequest(ExceptionCode&);
+    void makeCrossSiteAccessRequestWithPreflight(ExceptionCode&);
+    void handleAsynchronousPreflightResult();
+
+    void loadRequestSynchronously(ResourceRequest&, ExceptionCode&);
+    void loadRequestAsynchronously(ResourceRequest&);
+
+    bool isSimpleCrossSiteAccessRequest() const;
+    String accessControlOrigin() const;
+    bool accessControlCheck(const ResourceResponse&);
+
+    void genericError();
+    void networkError();
+    void abortError();
+
+    void dispatchReadyStateChangeEvent();
+    void dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total);
+    void dispatchAbortEvent();
+    void dispatchErrorEvent();
+    void dispatchLoadEvent();
+    void dispatchLoadStartEvent();
+    void dispatchProgressEvent(long long expectedLength);
+
+    RefPtr<EventListener> m_onReadyStateChangeListener;
+    RefPtr<EventListener> m_onAbortListener;
+    RefPtr<EventListener> m_onErrorListener;
+    RefPtr<EventListener> m_onLoadListener;
+    RefPtr<EventListener> m_onLoadStartListener;
+    RefPtr<EventListener> m_onProgressListener;
+    EventListenersMap m_eventListeners;
+
+    RefPtr<XMLHttpRequestUpload> m_upload;
+
+    KURL m_url;
+    String m_method;
+    HTTPHeaderMap m_requestHeaders;
+    RefPtr<FormData> m_requestEntityBody;
+    String m_mimeTypeOverride;
+    bool m_async;
+    bool m_includeCredentials;
+
+    RefPtr<SubresourceLoader> m_loader;
+    State m_state;
+
+    ResourceResponse m_response;
+    String m_responseEncoding;
+
+    RefPtr<TextResourceDecoder> m_decoder;
+    unsigned long m_identifier;
+
+    // Unlike most strings in the DOM, we keep this as a JSC::UString, not a WebCore::String.
+    // That's because these strings can easily get huge (they are filled from the network with
+    // no parsing) and because JS can easily observe many intermediate states, so it's very useful
+    // to be able to share the buffer with JavaScript versions of the whole or partial string.
+    // In contrast, this string doesn't interact much with the rest of the engine so it's not that
+    // big a cost that it isn't a String.
+    JSC::UString m_responseText;
+    mutable bool m_createdDocument;
+    mutable RefPtr<Document> m_responseXML;
+
+    bool m_error;
+
+    bool m_uploadComplete;
+
+    bool m_sameOriginRequest;
+    bool m_allowAccess;
+    bool m_inPreflight;
+
+    // Used for onprogress tracking
+    long long m_receivedLength;
+    
+    unsigned m_lastSendLineNumber;
+    JSC::UString m_lastSendURL;
+};
+
+} // namespace WebCore
+
+#endif // XMLHttpRequest_h
diff --git a/WebCore/xml/XMLHttpRequest.idl b/WebCore/xml/XMLHttpRequest.idl
new file mode 100644
index 0000000..fa6b9ca
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequest.idl
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+module xml {
+
+    interface [
+        CustomMarkFunction
+    ] XMLHttpRequest {
+        // From XMLHttpRequestEventTarget
+        // event handler attributes
+        attribute EventListener onabort;
+        attribute EventListener onerror;
+        attribute EventListener onload;
+        attribute EventListener onloadstart;
+        attribute EventListener onprogress;
+
+        // event handler attributes
+        attribute EventListener onreadystatechange;
+
+        // state
+        const unsigned short UNSENT = 0;
+        const unsigned short OPENED = 1;
+        const unsigned short HEADERS_RECEIVED = 2;
+        const unsigned short LOADING = 3;
+        const unsigned short DONE = 4;
+
+        readonly attribute unsigned short readyState;
+
+        // request
+        // void open(in DOMString method, in DOMString url);
+        // void open(in DOMString method, in DOMString url, in boolean async);
+        // void open(in DOMString method, in DOMString url, in boolean async, in DOMString user);
+        [Custom] void open(in DOMString method, in DOMString url, in boolean async, in DOMString user, in DOMString password)
+            raises(DOMException);
+
+        [Custom] void setRequestHeader(in DOMString header, in DOMString value)
+            raises(DOMException);
+
+        // void send();
+        // void send(in DOMString data);
+        [Custom] void send(in Document data)
+            raises(DOMException);
+
+        void abort();
+
+        readonly attribute XMLHttpRequestUpload upload;
+
+        // response
+        [ConvertNullStringTo=Undefined] DOMString getAllResponseHeaders()
+            raises(DOMException);
+        [Custom, ConvertNullStringTo=Null] DOMString getResponseHeader(in DOMString header)
+            raises(DOMException);
+        readonly attribute [ConvertNullStringTo=Null] DOMString responseText;
+        readonly attribute Document responseXML;
+        readonly attribute unsigned short status
+            getter raises(DOMException);
+        readonly attribute DOMString statusText
+            getter raises(DOMException);
+
+        // Extension
+        [Custom] void overrideMimeType(in DOMString override);
+
+        // EventTarget interface
+        [Custom] void addEventListener(in DOMString type, 
+                                      in EventListener listener, 
+                                      in boolean useCapture);
+        [Custom] void removeEventListener(in DOMString type, 
+                                          in EventListener listener, 
+                                          in boolean useCapture);
+        boolean dispatchEvent(in Event evt)
+            raises(EventException);
+    };
+
+}
diff --git a/WebCore/xml/XMLHttpRequestException.h b/WebCore/xml/XMLHttpRequestException.h
new file mode 100644
index 0000000..737cab0
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestException.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007, 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 XMLHttpRequestException_h
+#define XMLHttpRequestException_h
+
+#include "ExceptionBase.h"
+
+namespace WebCore {
+
+    class XMLHttpRequestException : public ExceptionBase {
+    public:
+        static PassRefPtr<XMLHttpRequestException> create(const ExceptionCodeDescription& description)
+        {
+            return adoptRef(new XMLHttpRequestException(description));
+        }
+
+        static const int XMLHttpRequestExceptionOffset = 500;
+        static const int XMLHttpRequestExceptionMax = 699;
+
+        enum XMLHttpRequestExceptionCode {
+            NETWORK_ERR = XMLHttpRequestExceptionOffset + 101,
+            ABORT_ERR
+        };
+
+    private:
+        XMLHttpRequestException(const ExceptionCodeDescription& description)
+            : ExceptionBase(description)
+        {
+        }
+    };
+
+} // namespace WebCore
+
+#endif // XMLHttpRequestException_h
diff --git a/WebCore/xml/XMLHttpRequestException.idl b/WebCore/xml/XMLHttpRequestException.idl
new file mode 100644
index 0000000..2feb574
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestException.idl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+module xml {
+
+    interface [
+        GenerateConstructor
+    ] XMLHttpRequestException {
+
+        readonly attribute unsigned short   code;
+        readonly attribute DOMString        name;
+        readonly attribute DOMString        message;
+
+#if defined(LANGUAGE_JAVASCRIPT)
+        // Override in a Mozilla compatible format
+        [DontEnum] DOMString toString();
+#endif
+
+        // XMLHttpRequestExceptionCode
+        const unsigned short NETWORK_ERR = 101;
+        const unsigned short ABORT_ERR = 102;
+    };
+
+}
diff --git a/WebCore/xml/XMLHttpRequestProgressEvent.h b/WebCore/xml/XMLHttpRequestProgressEvent.h
new file mode 100644
index 0000000..02bfdea
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestProgressEvent.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Julien Chaffraix <[email protected]>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 XMLHttpRequestProgressEvent_h
+#define XMLHttpRequestProgressEvent_h
+
+#include "ProgressEvent.h"
+
+namespace WebCore {
+
+    class XMLHttpRequestProgressEvent : public ProgressEvent {
+    public:
+        static PassRefPtr<XMLHttpRequestProgressEvent> create()
+        {
+            return adoptRef(new XMLHttpRequestProgressEvent);
+        }
+        static PassRefPtr<XMLHttpRequestProgressEvent> create(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+        {
+            return adoptRef(new XMLHttpRequestProgressEvent(type, lengthComputable, loaded, total));
+        }
+
+        virtual bool isXMLHttpRequestProgressEvent() const { return true; }
+
+        // Those 2 methods are to be compatible with Firefox and are only a wrapper on top of the real implementation.
+        unsigned position() const { return loaded(); }
+        unsigned totalSize() const { return total(); }
+
+    private:
+        XMLHttpRequestProgressEvent() { }
+        XMLHttpRequestProgressEvent(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+            : ProgressEvent(type, lengthComputable, loaded, total)
+        {
+        }
+    };
+
+} // namespace WebCore
+
+#endif // XMLHttpRequestProgressEvent_h
diff --git a/WebCore/xml/XMLHttpRequestProgressEvent.idl b/WebCore/xml/XMLHttpRequestProgressEvent.idl
new file mode 100644
index 0000000..6de9690
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestProgressEvent.idl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+module events {
+
+    interface [
+        GenerateConstructor
+    // We should also inherit from LSProgressEvent when the idl is added.
+    ] XMLHttpRequestProgressEvent : ProgressEvent {
+         readonly attribute unsigned long   position;
+         readonly attribute unsigned long   totalSize;
+    };
+
+}
diff --git a/WebCore/xml/XMLHttpRequestUpload.cpp b/WebCore/xml/XMLHttpRequestUpload.cpp
new file mode 100644
index 0000000..cef1798
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestUpload.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2008 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "XMLHttpRequestUpload.h"
+
+#include "AtomicString.h"
+#include "Event.h"
+#include "EventException.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+XMLHttpRequestUpload::XMLHttpRequestUpload(XMLHttpRequest* xmlHttpRequest)
+    : m_xmlHttpRequest(xmlHttpRequest)
+{
+}
+
+ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
+{
+    XMLHttpRequest* xmlHttpRequest = associatedXMLHttpRequest();
+    if (!xmlHttpRequest)
+        return 0;
+    return xmlHttpRequest->scriptExecutionContext();
+}
+
+void XMLHttpRequestUpload::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
+{
+    EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+    if (iter == m_eventListeners.end()) {
+        ListenerVector listeners;
+        listeners.append(eventListener);
+        m_eventListeners.add(eventType, listeners);
+    } else {
+        ListenerVector& listeners = iter->second;
+        for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+            if (*listenerIter == eventListener)
+                return;
+        }
+        
+        listeners.append(eventListener);
+        m_eventListeners.add(eventType, listeners);
+    }
+}
+
+void XMLHttpRequestUpload::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
+{
+    EventListenersMap::iterator iter = m_eventListeners.find(eventType);
+    if (iter == m_eventListeners.end())
+        return;
+
+    ListenerVector& listeners = iter->second;
+    for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
+        if (*listenerIter == eventListener) {
+            listeners.remove(listenerIter - listeners.begin());
+            return;
+        }
+    }
+}
+
+bool XMLHttpRequestUpload::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec)
+{
+    // FIXME: check for other error conditions enumerated in the spec.
+    if (evt->type().isEmpty()) {
+        ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
+        return true;
+    }
+
+    ListenerVector listenersCopy = m_eventListeners.get(evt->type());
+    for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
+        evt->setTarget(this);
+        evt->setCurrentTarget(this);
+        listenerIter->get()->handleEvent(evt.get(), false);
+    }
+
+    return !evt->defaultPrevented();
+}
+
+void XMLHttpRequestUpload::dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+{
+    RefPtr<XMLHttpRequestProgressEvent> evt = XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total);
+    if (listener) {
+        evt->setTarget(this);
+        evt->setCurrentTarget(this);
+        listener->handleEvent(evt.get(), false);
+    }
+
+    ExceptionCode ec = 0;
+    dispatchEvent(evt.release(), ec);
+    ASSERT(!ec);
+}
+
+void XMLHttpRequestUpload::dispatchAbortEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onAbortListener.get(), eventNames().abortEvent, false, 0, 0);
+}
+
+void XMLHttpRequestUpload::dispatchErrorEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onErrorListener.get(), eventNames().errorEvent, false, 0, 0);
+}
+
+void XMLHttpRequestUpload::dispatchLoadEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onLoadListener.get(), eventNames().loadEvent, false, 0, 0);
+}
+
+void XMLHttpRequestUpload::dispatchLoadStartEvent()
+{
+    dispatchXMLHttpRequestProgressEvent(m_onLoadStartListener.get(), eventNames().loadstartEvent, false, 0, 0);
+}
+
+void XMLHttpRequestUpload::dispatchProgressEvent(long long bytesSent, long long totalBytesToBeSent)
+{
+    dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, true, static_cast<unsigned>(bytesSent), static_cast<unsigned>(totalBytesToBeSent));
+}
+
+} // namespace WebCore
diff --git a/WebCore/xml/XMLHttpRequestUpload.h b/WebCore/xml/XMLHttpRequestUpload.h
new file mode 100644
index 0000000..93fa7f9
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestUpload.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 XMLHttpRequestUpload_h
+#define XMLHttpRequestUpload_h
+
+#include "AtomicStringHash.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class AtomicStringImpl;
+    class ScriptExecutionContext;
+    class XMLHttpRequest;
+
+    class XMLHttpRequestUpload : public RefCounted<XMLHttpRequestUpload>, public EventTarget {
+    public:
+        static PassRefPtr<XMLHttpRequestUpload> create(XMLHttpRequest* xmlHttpRequest)
+        {
+            return adoptRef(new XMLHttpRequestUpload(xmlHttpRequest));
+        }
+
+        virtual XMLHttpRequestUpload* toXMLHttpRequestUpload() { return this; }
+
+        XMLHttpRequest* associatedXMLHttpRequest() const { return m_xmlHttpRequest; }
+        void disconnectXMLHttpRequest() { m_xmlHttpRequest = 0; }
+
+        ScriptExecutionContext* scriptExecutionContext() const;
+
+        void dispatchAbortEvent();
+        void dispatchErrorEvent();
+        void dispatchLoadEvent();
+        void dispatchLoadStartEvent();
+        void dispatchProgressEvent(long long bytesSent, long long totalBytesToBeSent);
+
+        void setOnabort(PassRefPtr<EventListener> eventListener) { m_onAbortListener = eventListener; }
+        EventListener* onabort() const { return m_onAbortListener.get(); }
+
+        void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
+        EventListener* onerror() const { return m_onErrorListener.get(); }
+
+        void setOnload(PassRefPtr<EventListener> eventListener) { m_onLoadListener = eventListener; }
+        EventListener* onload() const { return m_onLoadListener.get(); }
+
+        void setOnloadstart(PassRefPtr<EventListener> eventListener) { m_onLoadStartListener = eventListener; }
+        EventListener* onloadstart() const { return m_onLoadStartListener.get(); }
+
+        void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; }
+        EventListener* onprogress() const { return m_onProgressListener.get(); }
+
+        typedef Vector<RefPtr<EventListener> > ListenerVector;
+        typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
+
+        virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
+        virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
+        virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
+        EventListenersMap& eventListeners() { return m_eventListeners; }
+
+        using RefCounted<XMLHttpRequestUpload>::ref;
+        using RefCounted<XMLHttpRequestUpload>::deref;
+
+    private:
+        XMLHttpRequestUpload(XMLHttpRequest*);
+
+        void dispatchXMLHttpRequestProgressEvent(EventListener*, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total);
+
+        virtual void refEventTarget() { ref(); }
+        virtual void derefEventTarget() { deref(); }
+
+        RefPtr<EventListener> m_onAbortListener;
+        RefPtr<EventListener> m_onErrorListener;
+        RefPtr<EventListener> m_onLoadListener;
+        RefPtr<EventListener> m_onLoadStartListener;
+        RefPtr<EventListener> m_onProgressListener;
+        EventListenersMap m_eventListeners;
+
+        XMLHttpRequest* m_xmlHttpRequest;
+    };
+    
+} // namespace WebCore
+
+#endif // XMLHttpRequestUpload_h
diff --git a/WebCore/xml/XMLHttpRequestUpload.idl b/WebCore/xml/XMLHttpRequestUpload.idl
new file mode 100644
index 0000000..c066710
--- /dev/null
+++ b/WebCore/xml/XMLHttpRequestUpload.idl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+module xml {
+
+    interface [
+        GenerateConstructor,
+        CustomMarkFunction
+    ] XMLHttpRequestUpload {
+        // From XMLHttpRequestEventTarget
+        // event handler attributes
+        attribute EventListener onabort;
+        attribute EventListener onerror;
+        attribute EventListener onload;
+        attribute EventListener onloadstart;
+        attribute EventListener onprogress;
+
+        // EventTarget interface
+        [Custom] void addEventListener(in DOMString type, 
+                                      in EventListener listener, 
+                                      in boolean useCapture);
+        [Custom] void removeEventListener(in DOMString type, 
+                                          in EventListener listener, 
+                                          in boolean useCapture);
+        boolean dispatchEvent(in Event evt)
+            raises(EventException);
+    };
+
+}
diff --git a/WebCore/xml/XMLSerializer.cpp b/WebCore/xml/XMLSerializer.cpp
new file mode 100644
index 0000000..ac7dc19
--- /dev/null
+++ b/WebCore/xml/XMLSerializer.cpp
@@ -0,0 +1,48 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006 Samuel Weinig ([email protected])
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "XMLSerializer.h"
+
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "markup.h"
+
+namespace WebCore {
+
+String XMLSerializer::serializeToString(Node* node, ExceptionCode& ec)
+{
+    if (!node)
+        return String();
+
+    if (!node->document()) {
+        // Due to the fact that DocumentType nodes are created by the DOMImplementation
+        // and not the Document, it is possible for it to not have a Document associated
+        // with it.  It should be the only type of node where this is possible.
+        ASSERT(node->nodeType() == Node::DOCUMENT_TYPE_NODE);
+
+        ec = INVALID_ACCESS_ERR;
+        return String();
+    }
+
+    return createMarkup(node);
+}
+
+} // namespace WebCore
diff --git a/WebCore/xml/XMLSerializer.h b/WebCore/xml/XMLSerializer.h
new file mode 100644
index 0000000..33e94b7
--- /dev/null
+++ b/WebCore/xml/XMLSerializer.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006 Samuel Weinig ([email protected])
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XMLSerializer_h
+#define XMLSerializer_h
+
+#include <wtf/RefCounted.h>
+#include "PlatformString.h"
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class Node;
+
+    class XMLSerializer : public RefCounted<XMLSerializer> {
+    public:
+        static PassRefPtr<XMLSerializer> create() { return adoptRef(new XMLSerializer); }
+        
+        String serializeToString(Node*, ExceptionCode&);
+        
+    private:
+        XMLSerializer()  { }        
+    };
+
+} // namespace WebCore
+
+#endif // XMLSerializer_h
diff --git a/WebCore/xml/XMLSerializer.idl b/WebCore/xml/XMLSerializer.idl
new file mode 100644
index 0000000..6dcc3a4
--- /dev/null
+++ b/WebCore/xml/XMLSerializer.idl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig ([email protected])
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+
+    interface [GenerateConstructor, CanBeConstructed] XMLSerializer {
+        DOMString serializeToString(in Node node)
+            raises(DOMException);
+    };
+
+}
diff --git a/WebCore/xml/XPathEvaluator.cpp b/WebCore/xml/XPathEvaluator.cpp
new file mode 100644
index 0000000..8fb203f
--- /dev/null
+++ b/WebCore/xml/XPathEvaluator.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathEvaluator.h"
+
+#if ENABLE(XPATH)
+
+#include "ExceptionCode.h"
+#include "NativeXPathNSResolver.h"
+#include "Node.h"
+#include "XPathExpression.h"
+#include "XPathResult.h"
+#include "XPathUtil.h"
+
+namespace WebCore {
+
+using namespace XPath;
+    
+PassRefPtr<XPathExpression> XPathEvaluator::createExpression(const String& expression,
+                                                             XPathNSResolver* resolver,
+                                                             ExceptionCode& ec)
+{
+    return XPathExpression::createExpression(expression, resolver, ec);
+}
+
+PassRefPtr<XPathNSResolver> XPathEvaluator::createNSResolver(Node* nodeResolver)
+{
+    return NativeXPathNSResolver::create(nodeResolver);
+}
+
+PassRefPtr<XPathResult> XPathEvaluator::evaluate(const String& expression,
+                                                 Node* contextNode,
+                                                 XPathNSResolver* resolver,
+                                                 unsigned short type,
+                                                 XPathResult* result,
+                                                 ExceptionCode& ec)
+{
+    if (!isValidContextNode(contextNode)) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    ec = 0;
+    RefPtr<XPathExpression> expr = createExpression(expression, resolver, ec);
+    if (ec)
+        return 0;
+    
+    return expr->evaluate(contextNode, type, result, ec);
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathEvaluator.h b/WebCore/xml/XPathEvaluator.h
new file mode 100644
index 0000000..c8e456e
--- /dev/null
+++ b/WebCore/xml/XPathEvaluator.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathEvaluator_h
+#define XPathEvaluator_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class Node;
+    class String;
+    class XPathExpression;
+    class XPathNSResolver;
+    class XPathResult;
+
+    class XPathEvaluator : public RefCounted<XPathEvaluator> {
+    public:
+        static PassRefPtr<XPathEvaluator> create() { return adoptRef(new XPathEvaluator); }
+        
+        PassRefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&);
+        PassRefPtr<XPathNSResolver> createNSResolver(Node* nodeResolver);
+        PassRefPtr<XPathResult> evaluate(const String& expression, Node* contextNode,
+            XPathNSResolver*, unsigned short type, XPathResult*, ExceptionCode&);
+
+    private:
+        XPathEvaluator() { }
+    };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathEvaluator_h
diff --git a/WebCore/xml/XPathEvaluator.idl b/WebCore/xml/XPathEvaluator.idl
new file mode 100644
index 0000000..da6155b
--- /dev/null
+++ b/WebCore/xml/XPathEvaluator.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+    interface [GenerateConstructor, CanBeConstructed, Conditional=XPATH] XPathEvaluator {
+        XPathExpression createExpression(in DOMString expression,
+                                         in XPathNSResolver resolver)
+            raises(core::DOMException);
+
+        XPathNSResolver createNSResolver(in Node nodeResolver);
+
+        XPathResult evaluate(in DOMString expression,
+                             in Node contextNode, 
+                             in XPathNSResolver resolver,
+                             in unsigned short type,
+                             in XPathResult inResult)
+            raises(DOMException);
+    };
+}
diff --git a/WebCore/xml/XPathException.h b/WebCore/xml/XPathException.h
new file mode 100644
index 0000000..45ad628
--- /dev/null
+++ b/WebCore/xml/XPathException.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007, 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 XPathException_h
+#define XPathException_h
+
+#include "ExceptionBase.h"
+
+#if ENABLE(XPATH)
+
+namespace WebCore {
+
+    class XPathException : public ExceptionBase {
+    public:
+        static PassRefPtr<XPathException> create(const ExceptionCodeDescription& description)
+        {
+            return adoptRef(new XPathException(description));
+        }
+
+        static const int XPathExceptionOffset = 400;
+        static const int XPathExceptionMax = 499;
+
+        enum XPathExceptionCode {
+            INVALID_EXPRESSION_ERR = XPathExceptionOffset + 51,
+            TYPE_ERR
+        };
+
+    private:
+        XPathException(const ExceptionCodeDescription& description)
+            : ExceptionBase(description)
+        {
+        }
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathException_h
diff --git a/WebCore/xml/XPathException.idl b/WebCore/xml/XPathException.idl
new file mode 100644
index 0000000..6e25514
--- /dev/null
+++ b/WebCore/xml/XPathException.idl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+module xpath {
+
+    interface [
+        GenerateConstructor,
+        Conditional=XPATH
+    ] XPathException {
+
+        readonly attribute unsigned short   code;
+        readonly attribute DOMString        name;
+        readonly attribute DOMString        message;
+
+#if defined(LANGUAGE_JAVASCRIPT)
+        // Override in a Mozilla compatible format
+        [DontEnum] DOMString toString();
+#endif
+
+        // XPathExceptionCode
+        const unsigned short INVALID_EXPRESSION_ERR = 51;
+        const unsigned short TYPE_ERR = 52;
+    };
+
+}
diff --git a/WebCore/xml/XPathExpression.cpp b/WebCore/xml/XPathExpression.cpp
new file mode 100644
index 0000000..446a7ad
--- /dev/null
+++ b/WebCore/xml/XPathExpression.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathExpression.h"
+
+#if ENABLE(XPATH)
+
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "Node.h"
+#include "PlatformString.h"
+#include "XPathExpressionNode.h"
+#include "XPathNSResolver.h"
+#include "XPathParser.h"
+#include "XPathResult.h"
+#include "XPathUtil.h"
+
+namespace WebCore {
+
+using namespace XPath;
+    
+PassRefPtr<XPathExpression> XPathExpression::createExpression(const String& expression, XPathNSResolver* resolver, ExceptionCode& ec)
+{
+    RefPtr<XPathExpression> expr = XPathExpression::create();
+    Parser parser;
+
+    expr->m_topExpression = parser.parseStatement(expression, resolver, ec);
+    if (!expr->m_topExpression)
+        return 0;
+
+    return expr.release();
+}
+
+XPathExpression::~XPathExpression()
+{
+    delete m_topExpression;
+}
+
+PassRefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode& ec)
+{
+    if (!isValidContextNode(contextNode)) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    EventTargetNode* eventTarget = contextNode->ownerDocument()
+        ? contextNode->ownerDocument()
+        : static_cast<EventTargetNode*>(contextNode);
+
+    EvaluationContext& evaluationContext = Expression::evaluationContext();
+    evaluationContext.node = contextNode;
+    evaluationContext.size = 1;
+    evaluationContext.position = 1;
+    RefPtr<XPathResult> result = XPathResult::create(eventTarget, m_topExpression->evaluate());
+    evaluationContext.node = 0; // Do not hold a reference to the context node, as this may prevent the whole document from being destroyed in time.
+
+    if (type != XPathResult::ANY_TYPE) {
+        ec = 0;
+        result->convertTo(type, ec);
+        if (ec)
+            return 0;
+    }
+
+    return result;
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathExpression.h b/WebCore/xml/XPathExpression.h
new file mode 100644
index 0000000..a2b75d7
--- /dev/null
+++ b/WebCore/xml/XPathExpression.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathExpression_h
+#define XPathExpression_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class Node;
+    class String;
+    class XPathNSResolver;
+    class XPathResult;
+
+    namespace XPath {
+        class Expression;
+    }
+
+    class XPathExpression : public RefCounted<XPathExpression> {
+    public:
+        static PassRefPtr<XPathExpression> create() { return adoptRef(new XPathExpression); }
+        ~XPathExpression();
+        
+        static PassRefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&);
+        PassRefPtr<XPathResult> evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode&);
+            
+    private:
+        XPathExpression() { }
+
+        XPath::Expression* m_topExpression;
+    };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathExpression_h
diff --git a/WebCore/xml/XPathExpression.idl b/WebCore/xml/XPathExpression.idl
new file mode 100644
index 0000000..c1fc15e
--- /dev/null
+++ b/WebCore/xml/XPathExpression.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+
+
+    interface [
+        Conditional=XPATH,
+        GenerateConstructor
+    ] XPathExpression {
+        [OldStyleObjC] XPathResult evaluate(in Node contextNode, 
+                                            in unsigned short type, 
+                                            in XPathResult inResult)
+            raises(DOMException);
+    };
+
+}
diff --git a/WebCore/xml/XPathExpressionNode.cpp b/WebCore/xml/XPathExpressionNode.cpp
new file mode 100644
index 0000000..88e349e
--- /dev/null
+++ b/WebCore/xml/XPathExpressionNode.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathExpressionNode.h"
+
+#if ENABLE(XPATH)
+
+#include "Node.h"
+#include "XPathValue.h"
+
+namespace WebCore {
+namespace XPath {
+    
+EvaluationContext& Expression::evaluationContext()
+{
+    static EvaluationContext evaluationContext;
+    return evaluationContext;
+}
+
+Expression::Expression()
+{
+}
+
+Expression::~Expression()
+{
+    deleteAllValues(m_subExpressions);
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathExpressionNode.h b/WebCore/xml/XPathExpressionNode.h
new file mode 100644
index 0000000..9c5f79b
--- /dev/null
+++ b/WebCore/xml/XPathExpressionNode.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathExpressionNode_h
+#define XPathExpressionNode_h
+
+#if ENABLE(XPATH)
+
+#include "StringHash.h"
+#include "Node.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    namespace XPath {
+
+        class Value;
+        
+        struct EvaluationContext {
+            EvaluationContext() : node(0), size(0), position(0) { }
+
+            RefPtr<Node> node;
+            unsigned long size;
+            unsigned long position;
+            HashMap<String, String> variableBindings;
+
+        };
+
+        class ParseNode {
+        public:
+            virtual ~ParseNode() { }
+        };
+
+        class Expression : public ParseNode, Noncopyable {
+        public:
+            static EvaluationContext& evaluationContext();
+
+            Expression();
+            virtual ~Expression();
+
+            virtual Value evaluate() const = 0;
+
+            void addSubExpression(Expression* expr) { m_subExpressions.append(expr); }
+
+        protected:
+            unsigned subExprCount() const { return m_subExpressions.size(); }
+            Expression* subExpr(unsigned i) { return m_subExpressions[i]; }
+            const Expression* subExpr(unsigned i) const { return m_subExpressions[i]; }
+
+        private:
+            Vector<Expression*> m_subExpressions;
+        };
+
+    }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // EXPRESSION_H
+
diff --git a/WebCore/xml/XPathFunctions.cpp b/WebCore/xml/XPathFunctions.cpp
new file mode 100644
index 0000000..841b436
--- /dev/null
+++ b/WebCore/xml/XPathFunctions.cpp
@@ -0,0 +1,683 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathFunctions.h"
+
+#if ENABLE(XPATH)
+
+#include "Document.h"
+#include "Element.h"
+#include "NamedAttrMap.h"
+#include "XMLNames.h"
+#include "XPathUtil.h"
+#include "XPathValue.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+namespace XPath {
+
+static inline bool isWhitespace(UChar c)
+{
+    return c == ' ' || c == '\n' || c == '\r' || c == '\t';
+}
+
+
+#define DEFINE_FUNCTION_CREATOR(Class) static Function* create##Class() { return new Class; }
+
+class Interval {
+public:
+    static const int Inf = -1;
+
+    Interval();
+    Interval(int value);
+    Interval(int min, int max);
+
+    bool contains(int value) const;
+
+private:
+    int m_min;
+    int m_max;
+};
+
+struct FunctionRec {
+    typedef Function *(*FactoryFn)();
+    FactoryFn factoryFn;
+    Interval args;
+};
+
+static HashMap<String, FunctionRec>* functionMap;
+
+class FunLast : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunPosition : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunCount : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunId : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunLocalName : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunNamespaceURI : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunName : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunString : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunConcat : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunStartsWith : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunContains : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunSubstringBefore : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunSubstringAfter : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunSubstring : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunStringLength : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunNormalizeSpace : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunTranslate : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunBoolean : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunNot : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunTrue : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunFalse : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunLang : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunNumber : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunSum : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunFloor : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunCeiling : public Function {
+    virtual Value evaluate() const;
+};
+
+class FunRound : public Function {
+    virtual Value evaluate() const;
+public:
+    static double round(double);
+};
+
+DEFINE_FUNCTION_CREATOR(FunLast)
+DEFINE_FUNCTION_CREATOR(FunPosition)
+DEFINE_FUNCTION_CREATOR(FunCount)
+DEFINE_FUNCTION_CREATOR(FunId)
+DEFINE_FUNCTION_CREATOR(FunLocalName)
+DEFINE_FUNCTION_CREATOR(FunNamespaceURI)
+DEFINE_FUNCTION_CREATOR(FunName)
+
+DEFINE_FUNCTION_CREATOR(FunString)
+DEFINE_FUNCTION_CREATOR(FunConcat)
+DEFINE_FUNCTION_CREATOR(FunStartsWith)
+DEFINE_FUNCTION_CREATOR(FunContains)
+DEFINE_FUNCTION_CREATOR(FunSubstringBefore)
+DEFINE_FUNCTION_CREATOR(FunSubstringAfter)
+DEFINE_FUNCTION_CREATOR(FunSubstring)
+DEFINE_FUNCTION_CREATOR(FunStringLength)
+DEFINE_FUNCTION_CREATOR(FunNormalizeSpace)
+DEFINE_FUNCTION_CREATOR(FunTranslate)
+
+DEFINE_FUNCTION_CREATOR(FunBoolean)
+DEFINE_FUNCTION_CREATOR(FunNot)
+DEFINE_FUNCTION_CREATOR(FunTrue)
+DEFINE_FUNCTION_CREATOR(FunFalse)
+DEFINE_FUNCTION_CREATOR(FunLang)
+
+DEFINE_FUNCTION_CREATOR(FunNumber)
+DEFINE_FUNCTION_CREATOR(FunSum)
+DEFINE_FUNCTION_CREATOR(FunFloor)
+DEFINE_FUNCTION_CREATOR(FunCeiling)
+DEFINE_FUNCTION_CREATOR(FunRound)
+
+#undef DEFINE_FUNCTION_CREATOR
+
+inline Interval::Interval()
+    : m_min(Inf), m_max(Inf)
+{
+}
+
+inline Interval::Interval(int value)
+    : m_min(value), m_max(value)
+{
+}
+
+inline Interval::Interval(int min, int max)
+    : m_min(min), m_max(max)
+{
+}
+
+inline bool Interval::contains(int value) const
+{
+    if (m_min == Inf && m_max == Inf)
+        return true;
+
+    if (m_min == Inf)
+        return value <= m_max;
+
+    if (m_max == Inf)
+        return value >= m_min;
+
+    return value >= m_min && value <= m_max;
+}
+
+void Function::setArguments(const Vector<Expression*>& args)
+{
+    Vector<Expression*>::const_iterator end = args.end();
+
+    for (Vector<Expression*>::const_iterator it = args.begin(); it != end; it++)
+        addSubExpression(*it);
+}
+
+Value FunLast::evaluate() const
+{
+    return Expression::evaluationContext().size;
+}
+
+Value FunPosition::evaluate() const
+{
+    return Expression::evaluationContext().position;
+}
+
+Value FunId::evaluate() const
+{
+    Value a = arg(0)->evaluate();
+    Vector<UChar> idList; // A whitespace-separated list of IDs
+
+    if (a.isNodeSet()) {
+        const NodeSet& nodes = a.toNodeSet();
+        for (size_t i = 0; i < nodes.size(); ++i) {
+            String str = stringValue(nodes[i]);
+            idList.append(str.characters(), str.length());
+            idList.append(' ');
+        }
+    } else {
+        String str = a.toString();
+        idList.append(str.characters(), str.length());
+    }
+    
+    Document* contextDocument = evaluationContext().node->document();
+    NodeSet result;
+    HashSet<Node*> resultSet;
+
+    size_t startPos = 0;
+    size_t length = idList.size();
+    while (true) {
+        while (startPos < length && isWhitespace(idList[startPos]))
+            ++startPos;
+        
+        if (startPos == length)
+            break;
+
+        size_t endPos = startPos;
+        while (endPos < length && !isWhitespace(idList[endPos]))
+            ++endPos;
+
+        // If there are several nodes with the same id, id() should return the first one.
+        // In WebKit, getElementById behaves so, too, although its behavior in this case is formally undefined.
+        Node* node = contextDocument->getElementById(String(&idList[startPos], endPos - startPos));
+        if (node && resultSet.add(node).second)
+            result.append(node);
+        
+        startPos = endPos;
+    }
+    
+    result.markSorted(false);
+    
+    return Value(result, Value::adopt);
+}
+
+Value FunLocalName::evaluate() const
+{
+    Node* node = 0;
+    if (argCount() > 0) {
+        Value a = arg(0)->evaluate();
+        if (!a.isNodeSet())
+            return "";
+
+        node = a.toNodeSet().firstNode();
+        if (!node)
+            return "";
+    }
+
+    if (!node)
+        node = evaluationContext().node.get();
+
+    return node->localName().string();
+}
+
+Value FunNamespaceURI::evaluate() const
+{
+    Node* node = 0;
+    if (argCount() > 0) {
+        Value a = arg(0)->evaluate();
+        if (!a.isNodeSet())
+            return "";
+
+        node = a.toNodeSet().firstNode();
+        if (!node)
+            return "";
+    }
+
+    if (!node)
+        node = evaluationContext().node.get();
+
+    return node->namespaceURI().string();
+}
+
+Value FunName::evaluate() const
+{
+    Node* node = 0;
+    if (argCount() > 0) {
+        Value a = arg(0)->evaluate();
+        if (!a.isNodeSet())
+            return "";
+
+        node = a.toNodeSet().firstNode();
+        if (!node)
+            return "";
+    }
+
+    if (!node)
+        node = evaluationContext().node.get();
+
+    const AtomicString& prefix = node->prefix();
+    return prefix.isEmpty() ? node->localName().string() : prefix + ":" + node->localName();
+}
+
+Value FunCount::evaluate() const
+{
+    Value a = arg(0)->evaluate();
+    
+    if (!a.isNodeSet())
+        return 0.0;
+    
+    return double(a.toNodeSet().size());
+}
+
+Value FunString::evaluate() const
+{
+    if (!argCount())
+        return Value(Expression::evaluationContext().node.get()).toString();
+    return arg(0)->evaluate().toString();
+}
+
+Value FunConcat::evaluate() const
+{
+    Vector<UChar, 1024> result;
+
+    unsigned count = argCount();
+    for (unsigned i = 0; i < count; ++i) {
+        String str(arg(i)->evaluate().toString());
+        result.append(str.characters(), str.length());
+    }
+
+    return String(result.data(), result.size());
+}
+
+Value FunStartsWith::evaluate() const
+{
+    String s1 = arg(0)->evaluate().toString();
+    String s2 = arg(1)->evaluate().toString();
+
+    if (s2.isEmpty())
+        return true;
+
+    return s1.startsWith(s2);
+}
+
+Value FunContains::evaluate() const
+{
+    String s1 = arg(0)->evaluate().toString();
+    String s2 = arg(1)->evaluate().toString();
+
+    if (s2.isEmpty()) 
+        return true;
+
+    return s1.contains(s2) != 0;
+}
+
+Value FunSubstringBefore::evaluate() const
+{
+    String s1 = arg(0)->evaluate().toString();
+    String s2 = arg(1)->evaluate().toString();
+
+    if (s2.isEmpty())
+        return "";
+
+    int i = s1.find(s2);
+
+    if (i == -1)
+        return "";
+
+    return s1.left(i);
+}
+
+Value FunSubstringAfter::evaluate() const
+{
+    String s1 = arg(0)->evaluate().toString();
+    String s2 = arg(1)->evaluate().toString();
+
+    int i = s1.find(s2);
+    if (i == -1)
+        return "";
+
+    return s1.substring(i + s2.length());
+}
+
+Value FunSubstring::evaluate() const
+{
+    String s = arg(0)->evaluate().toString();
+    long pos = static_cast<long>(FunRound::round(arg(1)->evaluate().toNumber()));
+    bool haveLength = argCount() == 3;
+    long len = -1;
+    if (haveLength) {
+        double doubleLen = arg(2)->evaluate().toNumber();
+        if (isnan(doubleLen))
+            return "";
+        len = static_cast<long>(FunRound::round(doubleLen));
+    }
+
+    if (pos > long(s.length())) 
+        return "";
+
+    if (haveLength && pos < 1) {
+        len -= 1 - pos;
+        pos = 1;
+        if (len < 1)
+            return "";
+    }
+
+    return s.substring(pos - 1, len);
+}
+
+Value FunStringLength::evaluate() const
+{
+    if (!argCount())
+        return Value(Expression::evaluationContext().node.get()).toString().length();
+    return arg(0)->evaluate().toString().length();
+}
+
+Value FunNormalizeSpace::evaluate() const
+{
+    if (!argCount()) {
+        String s = Value(Expression::evaluationContext().node.get()).toString();
+        return s.simplifyWhiteSpace();
+    }
+
+    String s = arg(0)->evaluate().toString();
+    return s.simplifyWhiteSpace();
+}
+
+Value FunTranslate::evaluate() const
+{
+    String s1 = arg(0)->evaluate().toString();
+    String s2 = arg(1)->evaluate().toString();
+    String s3 = arg(2)->evaluate().toString();
+    String newString;
+
+    // FIXME: Building a String a character at a time is quite slow.
+    for (unsigned i1 = 0; i1 < s1.length(); ++i1) {
+        UChar ch = s1[i1];
+        int i2 = s2.find(ch);
+        
+        if (i2 == -1)
+            newString += String(&ch, 1);
+        else if ((unsigned)i2 < s3.length()) {
+            UChar c2 = s3[i2];
+            newString += String(&c2, 1);
+        }
+    }
+
+    return newString;
+}
+
+Value FunBoolean::evaluate() const
+{
+    return arg(0)->evaluate().toBoolean();
+}
+
+Value FunNot::evaluate() const
+{
+    return !arg(0)->evaluate().toBoolean();
+}
+
+Value FunTrue::evaluate() const
+{
+    return true;
+}
+
+Value FunLang::evaluate() const
+{
+    String lang = arg(0)->evaluate().toString();
+
+    RefPtr<Node> langNode = 0;
+    Node* node = evaluationContext().node.get();
+    while (node) {
+        NamedAttrMap* attrs = node->attributes();
+        if (attrs)
+            langNode = attrs->getNamedItemNS(XMLNames::xmlNamespaceURI, "lang");
+        if (langNode)
+            break;
+        node = node->parentNode();
+    }
+
+    if (!langNode)
+        return false;
+
+    String langNodeValue = langNode->nodeValue();
+    while (true) {
+        if (equalIgnoringCase(langNodeValue, lang))
+            return true;
+
+        // Remove suffixes one by one.
+        int index = langNodeValue.reverseFind('-');
+        if (index == -1)
+            break;
+        langNodeValue = langNodeValue.left(index);
+    }
+
+    return false;
+}
+
+Value FunFalse::evaluate() const
+{
+    return false;
+}
+
+Value FunNumber::evaluate() const
+{
+    if (!argCount())
+        return Value(Expression::evaluationContext().node.get()).toNumber();
+    return arg(0)->evaluate().toNumber();
+}
+
+Value FunSum::evaluate() const
+{
+    Value a = arg(0)->evaluate();
+    if (!a.isNodeSet())
+        return 0.0;
+
+    double sum = 0.0;
+    const NodeSet& nodes = a.toNodeSet();
+    // To be really compliant, we should sort the node-set, as floating point addition is not associative.
+    // However, this is unlikely to ever become a practical issue, and sorting is slow.
+
+    for (unsigned i = 0; i < nodes.size(); i++)
+        sum += Value(stringValue(nodes[i])).toNumber();
+    
+    return sum;
+}
+
+Value FunFloor::evaluate() const
+{
+    return floor(arg(0)->evaluate().toNumber());
+}
+
+Value FunCeiling::evaluate() const
+{
+    return ceil(arg(0)->evaluate().toNumber());
+}
+
+double FunRound::round(double val)
+{
+    if (!isnan(val) && !isinf(val)) {
+        if (signbit(val) && val >= -0.5)
+            val *= 0; // negative zero
+        else
+            val = floor(val + 0.5);
+    }
+    return val;
+}
+
+Value FunRound::evaluate() const
+{
+    return round(arg(0)->evaluate().toNumber());
+}
+
+static void createFunctionMap()
+{
+    struct FunctionMapping {
+        const char *name;
+        FunctionRec function;
+    };
+    static const FunctionMapping functions[] = {
+        { "boolean", { &createFunBoolean, 1 } },
+        { "ceiling", { &createFunCeiling, 1 } },
+        { "concat", { &createFunConcat, Interval(2, Interval::Inf) } },
+        { "contains", { &createFunContains, 2 } },
+        { "count", { &createFunCount, 1 } },
+        { "false", { &createFunFalse, 0 } },
+        { "floor", { &createFunFloor, 1 } },
+        { "id", { &createFunId, 1 } },
+        { "lang", { &createFunLang, 1 } },
+        { "last", { &createFunLast, 0 } },
+        { "local-name", { &createFunLocalName, Interval(0, 1) } },
+        { "name", { &createFunName, Interval(0, 1) } },
+        { "namespace-uri", { &createFunNamespaceURI, Interval(0, 1) } },
+        { "normalize-space", { &createFunNormalizeSpace, Interval(0, 1) } },
+        { "not", { &createFunNot, 1 } },
+        { "number", { &createFunNumber, Interval(0, 1) } },
+        { "position", { &createFunPosition, 0 } },
+        { "round", { &createFunRound, 1 } },
+        { "starts-with", { &createFunStartsWith, 2 } },
+        { "string", { &createFunString, Interval(0, 1) } },
+        { "string-length", { &createFunStringLength, Interval(0, 1) } },
+        { "substring", { &createFunSubstring, Interval(2, 3) } },
+        { "substring-after", { &createFunSubstringAfter, 2 } },
+        { "substring-before", { &createFunSubstringBefore, 2 } },
+        { "sum", { &createFunSum, 1 } },
+        { "translate", { &createFunTranslate, 3 } },
+        { "true", { &createFunTrue, 0 } },
+    };
+    const unsigned int numFunctions = sizeof(functions) / sizeof(functions[0]);
+
+    functionMap = new HashMap<String, FunctionRec>;
+    for (unsigned i = 0; i < numFunctions; ++i)
+        functionMap->set(functions[i].name, functions[i].function);
+}
+
+Function* createFunction(const String& name, const Vector<Expression*>& args)
+{
+    if (!functionMap)
+        createFunctionMap();
+
+    HashMap<String, FunctionRec>::iterator functionMapIter = functionMap->find(name);
+    FunctionRec* functionRec = 0;
+
+    if (functionMapIter == functionMap->end() || !(functionRec = &functionMapIter->second)->args.contains(args.size()))
+        return 0;
+
+    Function* function = functionRec->factoryFn();
+    function->setArguments(args);
+    function->setName(name);
+    return function;
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathFunctions.h b/WebCore/xml/XPathFunctions.h
new file mode 100644
index 0000000..f22d3ef
--- /dev/null
+++ b/WebCore/xml/XPathFunctions.h
@@ -0,0 +1,62 @@
+/*
+ * functions.h - Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathFunctions_h
+#define XPathFunctions_h
+
+#if ENABLE(XPATH)
+
+#include "XPathExpressionNode.h"
+
+namespace WebCore {
+
+    namespace XPath {
+
+        class Function : public Expression {
+        public:
+            void setArguments(const Vector<Expression*>&);
+            void setName(const String& name) { m_name = name; }
+
+        protected:
+            Expression* arg(int pos) { return subExpr(pos); }
+            const Expression* arg(int pos) const { return subExpr(pos); }
+            unsigned int argCount() const { return subExprCount(); }
+            String name() const { return m_name; }
+
+        private:
+            String m_name;
+        };
+
+        Function* createFunction(const String& name, const Vector<Expression*>& args = Vector<Expression*>());
+
+    }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Functions_H
+
diff --git a/WebCore/xml/XPathGrammar.y b/WebCore/xml/XPathGrammar.y
new file mode 100644
index 0000000..50a69c2
--- /dev/null
+++ b/WebCore/xml/XPathGrammar.y
@@ -0,0 +1,554 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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"
+
+#if ENABLE(XPATH)
+
+#include "XPathFunctions.h"
+#include "XPathNSResolver.h"
+#include "XPathParser.h"
+#include "XPathPath.h"
+#include "XPathPredicate.h"
+#include "XPathVariableReference.h"
+
+#define YYENABLE_NLS 0
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYDEBUG 0
+#define YYMAXDEPTH 10000
+#define YYPARSE_PARAM parserParameter
+#define PARSER static_cast<Parser*>(parserParameter)
+
+using namespace WebCore;
+using namespace XPath;
+
+%}
+
+%pure_parser
+
+%union
+{
+    Step::Axis axis;
+    Step::NodeTest* nodeTest;
+    NumericOp::Opcode numop;
+    EqTestOp::Opcode eqop;
+    String* str;
+    Expression* expr;
+    Vector<Predicate*>* predList;
+    Vector<Expression*>* argList;
+    Step* step;
+    LocationPath* locationPath;
+}
+
+%{
+
+int xpathyylex(YYSTYPE* yylval) { return Parser::current()->lex(yylval); }
+void xpathyyerror(const char* str) { }
+    
+%}
+
+%left <numop> MULOP
+%left <eqop> EQOP RELOP
+%left PLUS MINUS
+%left OR AND
+%token <axis> AXISNAME
+%token <str> NODETYPE PI FUNCTIONNAME LITERAL
+%token <str> VARIABLEREFERENCE NUMBER
+%token DOTDOT SLASHSLASH
+%token <str> NAMETEST
+%token XPATH_ERROR
+
+%type <locationPath> LocationPath
+%type <locationPath> AbsoluteLocationPath
+%type <locationPath> RelativeLocationPath
+%type <step> Step
+%type <axis> AxisSpecifier
+%type <step> DescendantOrSelf
+%type <nodeTest> NodeTest
+%type <expr> Predicate
+%type <predList> OptionalPredicateList
+%type <predList> PredicateList
+%type <step> AbbreviatedStep
+%type <expr> Expr
+%type <expr> PrimaryExpr
+%type <expr> FunctionCall
+%type <argList> ArgumentList
+%type <expr> Argument
+%type <expr> UnionExpr
+%type <expr> PathExpr
+%type <expr> FilterExpr
+%type <expr> OrExpr
+%type <expr> AndExpr
+%type <expr> EqualityExpr
+%type <expr> RelationalExpr
+%type <expr> AdditiveExpr
+%type <expr> MultiplicativeExpr
+%type <expr> UnaryExpr
+
+%%
+
+Expr:
+    OrExpr
+    {
+        PARSER->m_topExpr = $1;
+    }
+    ;
+
+LocationPath:
+    RelativeLocationPath
+    {
+        $$->setAbsolute(false);
+    }
+    |
+    AbsoluteLocationPath
+    {
+        $$->setAbsolute(true);
+    }
+    ;
+
+AbsoluteLocationPath:
+    '/'
+    {
+        $$ = new LocationPath;
+        PARSER->registerParseNode($$);
+    }
+    |
+    '/' RelativeLocationPath
+    {
+        $$ = $2;
+    }
+    |
+    DescendantOrSelf RelativeLocationPath
+    {
+        $$ = $2;
+        $$->insertFirstStep($1);
+        PARSER->unregisterParseNode($1);
+    }
+    ;
+
+RelativeLocationPath:
+    Step
+    {
+        $$ = new LocationPath;
+        $$->appendStep($1);
+        PARSER->unregisterParseNode($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    RelativeLocationPath '/' Step
+    {
+        $$->appendStep($3);
+        PARSER->unregisterParseNode($3);
+    }
+    |
+    RelativeLocationPath DescendantOrSelf Step
+    {
+        $$->appendStep($2);
+        $$->appendStep($3);
+        PARSER->unregisterParseNode($2);
+        PARSER->unregisterParseNode($3);
+    }
+    ;
+
+Step:
+    NodeTest OptionalPredicateList
+    {
+        if ($2) {
+            $$ = new Step(Step::ChildAxis, *$1, *$2);
+            PARSER->deletePredicateVector($2);
+        } else
+            $$ = new Step(Step::ChildAxis, *$1);
+        PARSER->deleteNodeTest($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    NAMETEST OptionalPredicateList
+    {
+        String localName;
+        String namespaceURI;
+        if (!PARSER->expandQName(*$1, localName, namespaceURI)) {
+            PARSER->m_gotNamespaceError = true;
+            YYABORT;
+        }
+        
+        if ($2) {
+            $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$2);
+            PARSER->deletePredicateVector($2);
+        } else
+            $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
+        PARSER->deleteString($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    AxisSpecifier NodeTest OptionalPredicateList
+    {
+        if ($3) {
+            $$ = new Step($1, *$2, *$3);
+            PARSER->deletePredicateVector($3);
+        } else
+            $$ = new Step($1, *$2);
+        PARSER->deleteNodeTest($2);
+        PARSER->registerParseNode($$);
+    }
+    |
+    AxisSpecifier NAMETEST OptionalPredicateList
+    {
+        String localName;
+        String namespaceURI;
+        if (!PARSER->expandQName(*$2, localName, namespaceURI)) {
+            PARSER->m_gotNamespaceError = true;
+            YYABORT;
+        }
+
+        if ($3) {
+            $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$3);
+            PARSER->deletePredicateVector($3);
+        } else
+            $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
+        PARSER->deleteString($2);
+        PARSER->registerParseNode($$);
+    }
+    |
+    AbbreviatedStep
+    ;
+
+AxisSpecifier:
+    AXISNAME
+    |
+    '@'
+    {
+        $$ = Step::AttributeAxis;
+    }
+    ;
+
+NodeTest:
+    NODETYPE '(' ')'
+    {
+        if (*$1 == "node")
+            $$ = new Step::NodeTest(Step::NodeTest::AnyNodeTest);
+        else if (*$1 == "text")
+            $$ = new Step::NodeTest(Step::NodeTest::TextNodeTest);
+        else if (*$1 == "comment")
+            $$ = new Step::NodeTest(Step::NodeTest::CommentNodeTest);
+
+        PARSER->deleteString($1);
+        PARSER->registerNodeTest($$);
+    }
+    |
+    PI '(' ')'
+    {
+        $$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest);
+        PARSER->deleteString($1);        
+        PARSER->registerNodeTest($$);
+    }
+    |
+    PI '(' LITERAL ')'
+    {
+        $$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest, $3->stripWhiteSpace());
+        PARSER->deleteString($1);        
+        PARSER->deleteString($3);
+        PARSER->registerNodeTest($$);
+    }
+    ;
+
+OptionalPredicateList:
+    /* empty */
+    {
+        $$ = 0;
+    }
+    |
+    PredicateList
+    ;
+
+PredicateList:
+    Predicate
+    {
+        $$ = new Vector<Predicate*>;
+        $$->append(new Predicate($1));
+        PARSER->unregisterParseNode($1);
+        PARSER->registerPredicateVector($$);
+    }
+    |
+    PredicateList Predicate
+    {
+        $$->append(new Predicate($2));
+        PARSER->unregisterParseNode($2);
+    }
+    ;
+
+Predicate:
+    '[' Expr ']'
+    {
+        $$ = $2;
+    }
+    ;
+
+DescendantOrSelf:
+    SLASHSLASH
+    {
+        $$ = new Step(Step::DescendantOrSelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+AbbreviatedStep:
+    '.'
+    {
+        $$ = new Step(Step::SelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
+        PARSER->registerParseNode($$);
+    }
+    |
+    DOTDOT
+    {
+        $$ = new Step(Step::ParentAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+PrimaryExpr:
+    VARIABLEREFERENCE
+    {
+        $$ = new VariableReference(*$1);
+        PARSER->deleteString($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    '(' Expr ')'
+    {
+        $$ = $2;
+    }
+    |
+    LITERAL
+    {
+        $$ = new StringExpression(*$1);
+        PARSER->deleteString($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    NUMBER
+    {
+        $$ = new Number($1->toDouble());
+        PARSER->deleteString($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    FunctionCall
+    ;
+
+FunctionCall:
+    FUNCTIONNAME '(' ')'
+    {
+        $$ = createFunction(*$1);
+        if (!$$)
+            YYABORT;
+        PARSER->deleteString($1);
+        PARSER->registerParseNode($$);
+    }
+    |
+    FUNCTIONNAME '(' ArgumentList ')'
+    {
+        $$ = createFunction(*$1, *$3);
+        if (!$$)
+            YYABORT;
+        PARSER->deleteString($1);
+        PARSER->deleteExpressionVector($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+ArgumentList:
+    Argument
+    {
+        $$ = new Vector<Expression*>;
+        $$->append($1);
+        PARSER->unregisterParseNode($1);
+        PARSER->registerExpressionVector($$);
+    }
+    |
+    ArgumentList ',' Argument
+    {
+        $$->append($3);
+        PARSER->unregisterParseNode($3);
+    }
+    ;
+
+Argument:
+    Expr
+    ;
+
+UnionExpr:
+    PathExpr
+    |
+    UnionExpr '|' PathExpr
+    {
+        $$ = new Union;
+        $$->addSubExpression($1);
+        $$->addSubExpression($3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+PathExpr:
+    LocationPath
+    {
+        $$ = $1;
+    }
+    |
+    FilterExpr
+    |
+    FilterExpr '/' RelativeLocationPath
+    {
+        $3->setAbsolute(true);
+        $$ = new Path(static_cast<Filter*>($1), $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    |
+    FilterExpr DescendantOrSelf RelativeLocationPath
+    {
+        $3->insertFirstStep($2);
+        $3->setAbsolute(true);
+        $$ = new Path(static_cast<Filter*>($1), $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($2);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+FilterExpr:
+    PrimaryExpr
+    |
+    PrimaryExpr PredicateList
+    {
+        $$ = new Filter($1, *$2);
+        PARSER->unregisterParseNode($1);
+        PARSER->deletePredicateVector($2);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+OrExpr:
+    AndExpr
+    |
+    OrExpr OR AndExpr
+    {
+        $$ = new LogicalOp(LogicalOp::OP_Or, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+AndExpr:
+    EqualityExpr
+    |
+    AndExpr AND EqualityExpr
+    {
+        $$ = new LogicalOp(LogicalOp::OP_And, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+EqualityExpr:
+    RelationalExpr
+    |
+    EqualityExpr EQOP RelationalExpr
+    {
+        $$ = new EqTestOp($2, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+RelationalExpr:
+    AdditiveExpr
+    |
+    RelationalExpr RELOP AdditiveExpr
+    {
+        $$ = new EqTestOp($2, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+AdditiveExpr:
+    MultiplicativeExpr
+    |
+    AdditiveExpr PLUS MultiplicativeExpr
+    {
+        $$ = new NumericOp(NumericOp::OP_Add, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    |
+    AdditiveExpr MINUS MultiplicativeExpr
+    {
+        $$ = new NumericOp(NumericOp::OP_Sub, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+MultiplicativeExpr:
+    UnaryExpr
+    |
+    MultiplicativeExpr MULOP UnaryExpr
+    {
+        $$ = new NumericOp($2, $1, $3);
+        PARSER->unregisterParseNode($1);
+        PARSER->unregisterParseNode($3);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+UnaryExpr:
+    UnionExpr
+    |
+    MINUS UnaryExpr
+    {
+        $$ = new Negative;
+        $$->addSubExpression($2);
+        PARSER->unregisterParseNode($2);
+        PARSER->registerParseNode($$);
+    }
+    ;
+
+%%
+
+#endif
diff --git a/WebCore/xml/XPathNSResolver.cpp b/WebCore/xml/XPathNSResolver.cpp
new file mode 100644
index 0000000..3dde1f2
--- /dev/null
+++ b/WebCore/xml/XPathNSResolver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathNSResolver.h"
+
+#if ENABLE(XPATH)
+
+namespace WebCore {
+
+XPathNSResolver::~XPathNSResolver()
+{
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathNSResolver.h b/WebCore/xml/XPathNSResolver.h
new file mode 100644
index 0000000..04b5f80
--- /dev/null
+++ b/WebCore/xml/XPathNSResolver.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathNSResolver_h
+#define XPathNSResolver_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class String;
+
+    class XPathNSResolver : public RefCounted<XPathNSResolver> {
+    public:
+        virtual ~XPathNSResolver();
+        virtual String lookupNamespaceURI(const String& prefix) = 0;
+        
+    protected:
+        XPathNSResolver() { }
+    };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathNSResolver_h
diff --git a/WebCore/xml/XPathNSResolver.idl b/WebCore/xml/XPathNSResolver.idl
new file mode 100644
index 0000000..48c0113
--- /dev/null
+++ b/WebCore/xml/XPathNSResolver.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+
+    interface [ObjCProtocol, Conditional=XPATH] XPathNSResolver {
+        [ConvertNullStringTo=Null] DOMString lookupNamespaceURI(in DOMString prefix);
+    };
+
+}
diff --git a/WebCore/xml/XPathNamespace.cpp b/WebCore/xml/XPathNamespace.cpp
new file mode 100644
index 0000000..3c8c42c
--- /dev/null
+++ b/WebCore/xml/XPathNamespace.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathNamespace.h"
+
+#if ENABLE(XPATH)
+
+#include "Element.h"
+
+namespace WebCore {
+
+XPathNamespace::XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri)
+    : Node(ownerElement->document())
+    , m_ownerElement(ownerElement)
+    , m_prefix(prefix)
+    , m_uri(uri)
+{
+}
+
+XPathNamespace::~XPathNamespace()
+{
+}
+
+Document* XPathNamespace::ownerDocument() const
+{
+    return m_ownerElement->ownerDocument();
+}
+
+Element* XPathNamespace::ownerElement() const
+{
+    return m_ownerElement.get();
+}
+
+const AtomicString& XPathNamespace::prefix() const
+{
+    return m_prefix;
+}
+
+String XPathNamespace::nodeName() const
+{
+    return "#namespace";
+}
+
+String XPathNamespace::nodeValue() const
+{
+    return m_uri;
+}
+
+const AtomicString& XPathNamespace::namespaceURI() const
+{
+    return m_uri;
+}
+
+Node::NodeType XPathNamespace::nodeType() const
+{
+    return Node::XPATH_NAMESPACE_NODE;
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathNamespace.h b/WebCore/xml/XPathNamespace.h
new file mode 100644
index 0000000..c0e4280
--- /dev/null
+++ b/WebCore/xml/XPathNamespace.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathNamespace_h
+#define XPathNamespace_h
+
+#if ENABLE(XPATH)
+
+#include "AtomicString.h"
+#include "Node.h"
+
+namespace WebCore {
+
+    class Document;
+    class Element;
+
+    class XPathNamespace : public Node {
+    public:
+        XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri);
+        virtual ~XPathNamespace();
+
+        virtual Document* ownerDocument() const;
+        virtual Element* ownerElement() const;
+
+        virtual const AtomicString& prefix() const;
+        virtual String nodeName() const;
+        virtual String nodeValue() const;
+        virtual const AtomicString& namespaceURI() const;
+
+        virtual Node::NodeType nodeType() const;
+
+    private:
+        RefPtr<Element> m_ownerElement;
+        AtomicString m_prefix;
+        AtomicString m_uri;
+    };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathNamespace_h
+
diff --git a/WebCore/xml/XPathNodeSet.cpp b/WebCore/xml/XPathNodeSet.cpp
new file mode 100644
index 0000000..e29c096
--- /dev/null
+++ b/WebCore/xml/XPathNodeSet.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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"
+
+#if ENABLE(XPATH)
+#include "XPathNodeSet.h"
+
+#include "Attr.h"
+#include "Element.h"
+#include "Node.h"
+
+namespace WebCore {
+namespace XPath {
+
+static inline Node* parentWithDepth(unsigned depth, const Vector<Node*>& parents)
+{
+    ASSERT(parents.size() >= depth + 1);
+    return parents[parents.size() - 1 - depth];
+}
+
+static void sortBlock(unsigned from, unsigned to, Vector<Vector<Node*> >& parentMatrix, bool mayContainAttributeNodes)
+{
+    ASSERT(from + 1 < to); // Should not call this function with less that two nodes to sort.
+    unsigned minDepth = UINT_MAX;
+    for (unsigned i = from; i < to; ++i) {
+        unsigned depth = parentMatrix[i].size() - 1;
+        if (minDepth > depth)
+            minDepth = depth;
+    }
+    
+    // Find the common ancestor.
+    unsigned commonAncestorDepth = minDepth;
+    Node* commonAncestor;
+    while (true) {
+        commonAncestor = parentWithDepth(commonAncestorDepth, parentMatrix[from]);
+        if (commonAncestorDepth == 0)
+            break;
+
+        bool allEqual = true;
+        for (unsigned i = from + 1; i < to; ++i) {
+            if (commonAncestor != parentWithDepth(commonAncestorDepth, parentMatrix[i])) {
+                allEqual = false;
+                break;
+            }
+        }
+        if (allEqual)
+            break;
+        
+        --commonAncestorDepth;
+    }
+
+    if (commonAncestorDepth == minDepth) {
+        // One of the nodes is the common ancestor => it is the first in document order.
+        // Find it and move it to the beginning.
+        for (unsigned i = from; i < to; ++i)
+            if (commonAncestor == parentMatrix[i][0]) {
+                parentMatrix[i].swap(parentMatrix[from]);
+                if (from + 2 < to)
+                    sortBlock(from + 1, to, parentMatrix, mayContainAttributeNodes);
+                return;
+            }
+    }
+    
+    if (mayContainAttributeNodes && commonAncestor->isElementNode()) {
+        // The attribute nodes and namespace nodes of an element occur before the children of the element.
+        // The namespace nodes are defined to occur before the attribute nodes.
+        // The relative order of namespace nodes is implementation-dependent.
+        // The relative order of attribute nodes is implementation-dependent.
+        unsigned sortedEnd = from;
+        // FIXME: namespace nodes are not implemented.
+        for (unsigned i = sortedEnd; i < to; ++i) {
+            Node* n = parentMatrix[i][0];
+            if (n->isAttributeNode() && static_cast<Attr*>(n)->ownerElement() == commonAncestor)
+                parentMatrix[i].swap(parentMatrix[sortedEnd++]);
+        }
+        if (sortedEnd != from) {
+            if (to - sortedEnd > 1)
+                sortBlock(sortedEnd, to, parentMatrix, mayContainAttributeNodes);
+            return;
+        }
+    }
+
+    // Children nodes of the common ancestor induce a subdivision of our node-set.
+    // Sort it according to this subdivision, and recursively sort each group.
+    HashSet<Node*> parentNodes;
+    for (unsigned i = from; i < to; ++i)
+        parentNodes.add(parentWithDepth(commonAncestorDepth + 1, parentMatrix[i]));
+
+    unsigned previousGroupEnd = from;
+    unsigned groupEnd = from;
+    for (Node* n = commonAncestor->firstChild(); n; n = n->nextSibling()) {
+        // If parentNodes contains the node, perform a linear search to move its children in the node-set to the beginning.
+        if (parentNodes.contains(n)) {
+            for (unsigned i = groupEnd; i < to; ++i)
+                if (parentWithDepth(commonAncestorDepth + 1, parentMatrix[i]) == n)
+                    parentMatrix[i].swap(parentMatrix[groupEnd++]);
+
+            if (groupEnd - previousGroupEnd > 1)
+                sortBlock(previousGroupEnd, groupEnd, parentMatrix, mayContainAttributeNodes);
+
+            ASSERT(previousGroupEnd != groupEnd);
+            previousGroupEnd = groupEnd;
+#ifndef NDEBUG
+            parentNodes.remove(n);
+#endif
+        }
+    }
+
+    ASSERT(parentNodes.isEmpty());
+}
+
+void NodeSet::sort() const
+{
+    if (m_isSorted)
+        return;
+
+    unsigned nodeCount = m_nodes.size();
+    if (nodeCount < 2) {
+        const_cast<bool&>(m_isSorted) = true;
+        return;
+    }
+    
+    bool containsAttributeNodes = false;
+    
+    Vector<Vector<Node*> > parentMatrix(nodeCount);
+    for (unsigned i = 0; i < nodeCount; ++i) {
+        Vector<Node*>& parentsVector = parentMatrix[i];
+        Node* n = m_nodes[i].get();
+        parentsVector.append(n);
+        if (n->isAttributeNode()) {
+            n = static_cast<Attr*>(n)->ownerElement();
+            parentsVector.append(n);
+            containsAttributeNodes = true;
+        }
+        while ((n = n->parent()))
+            parentsVector.append(n);
+    }
+    sortBlock(0, nodeCount, parentMatrix, containsAttributeNodes);
+    
+    // It is not possible to just assign the result to m_nodes, because some nodes may get dereferenced and destroyed.
+    Vector<RefPtr<Node> > sortedNodes;
+    sortedNodes.reserveCapacity(nodeCount);
+    for (unsigned i = 0; i < nodeCount; ++i)
+        sortedNodes.append(parentMatrix[i][0]);
+    
+    const_cast<Vector<RefPtr<Node> >& >(m_nodes).swap(sortedNodes);
+}
+
+void NodeSet::reverse()
+{
+    if (m_nodes.isEmpty())
+        return;
+
+    unsigned from = 0;
+    unsigned to = m_nodes.size() - 1;
+    while (from < to) {
+        m_nodes[from].swap(m_nodes[to]);
+        ++from;
+        --to;
+    }
+}
+
+Node* NodeSet::firstNode() const
+{
+    if (isEmpty())
+        return 0;
+
+    sort(); // FIXME: fully sorting the node-set just to find its first node is wasteful.
+    return m_nodes.at(0).get();
+}
+
+Node* NodeSet::anyNode() const
+{
+    if (isEmpty())
+        return 0;
+
+    return m_nodes.at(0).get();
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathNodeSet.h b/WebCore/xml/XPathNodeSet.h
new file mode 100644
index 0000000..2ab6f1f
--- /dev/null
+++ b/WebCore/xml/XPathNodeSet.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 XPathNodeSet_h
+#define XPathNodeSet_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/Vector.h>
+#include <wtf/Forward.h>
+
+#include "Node.h"
+
+namespace WebCore {
+
+    namespace XPath {
+
+        class NodeSet {
+        public:
+        
+            NodeSet() : m_isSorted(true) {}
+            NodeSet(const NodeSet& other) : m_isSorted(other.m_isSorted), m_nodes(other.m_nodes) {}
+            NodeSet& operator=(const NodeSet& other) { m_isSorted = other.m_isSorted; m_nodes = other.m_nodes; return *this; }
+            
+            size_t size() const { return m_nodes.size(); }
+            bool isEmpty() const { return !m_nodes.size(); }
+            Node* operator[](unsigned i) const { return m_nodes.at(i).get(); }
+            void reserveCapacity(size_t newCapacity) { m_nodes.reserveCapacity(newCapacity); }
+            void clear() { m_nodes.clear(); }
+            void swap(NodeSet& other) { std::swap(m_isSorted, other.m_isSorted); m_nodes.swap(other.m_nodes); }
+
+            // NodeSet itself does not verify that nodes in it are unique.
+            void append(Node* node) { m_nodes.append(node); }
+            void append(PassRefPtr<Node> node) { m_nodes.append(node); }
+            void append(const NodeSet& nodeSet) { m_nodes.append(nodeSet.m_nodes); }
+
+            // Returns the set's first node in document order, or 0 if the set is empty.
+            Node* firstNode() const;
+
+            // Returns 0 if the set is empty.
+            Node* anyNode() const;
+
+            // NodeSet itself doesn't check if it is contains sorted data - the caller should tell it if it does not.
+            void markSorted(bool isSorted) { m_isSorted = isSorted; }
+            bool isSorted() const { return m_isSorted; }
+
+            void sort() const;
+
+            void reverse();
+        
+        private:
+            bool m_isSorted;
+            Vector<RefPtr<Node> > m_nodes;
+        };
+
+    }
+}
+
+#endif // ENABLE(XPATH)
+#endif // XPathNodeSet_h
diff --git a/WebCore/xml/XPathParser.cpp b/WebCore/xml/XPathParser.cpp
new file mode 100644
index 0000000..77c3011
--- /dev/null
+++ b/WebCore/xml/XPathParser.cpp
@@ -0,0 +1,633 @@
+/*
+ * Copyright 2005 Maksim Orlovich <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathParser.h"
+
+#if ENABLE(XPATH)
+
+#include "ExceptionCode.h"
+#include "StringHash.h"
+#include "XPathEvaluator.h"
+#include "XPathException.h"
+#include "XPathNSResolver.h"
+#include "XPathStep.h"
+
+int xpathyyparse(void*);
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+namespace XPath {
+
+class LocationPath;
+
+#include "XPathGrammar.h"    
+
+Parser* Parser::currentParser = 0;
+    
+enum XMLCat { NameStart, NameCont, NotPartOfName };
+
+static XMLCat charCat(UChar aChar)
+{
+    //### might need to add some special cases from the XML spec.
+
+    if (aChar == '_')
+        return NameStart;
+
+    if (aChar == '.' || aChar == '-')
+        return NameCont;
+    CharCategory category = Unicode::category(aChar);
+    if (category & (Letter_Uppercase | Letter_Lowercase | Letter_Other | Letter_Titlecase | Number_Letter))
+        return NameStart;
+    if (category & (Mark_NonSpacing | Mark_SpacingCombining | Mark_Enclosing | Letter_Modifier | Number_DecimalDigit))
+        return NameCont;
+    return NotPartOfName;
+}
+
+static void setUpAxisNamesMap(HashMap<String, Step::Axis>& axisNames)
+{
+    struct AxisName {
+        const char* name;
+        Step::Axis axis;
+    };
+    const AxisName axisNameList[] = {
+        { "ancestor", Step::AncestorAxis },
+        { "ancestor-or-self", Step::AncestorOrSelfAxis },
+        { "attribute", Step::AttributeAxis },
+        { "child", Step::ChildAxis },
+        { "descendant", Step::DescendantAxis },
+        { "descendant-or-self", Step::DescendantOrSelfAxis },
+        { "following", Step::FollowingAxis },
+        { "following-sibling", Step::FollowingSiblingAxis },
+        { "namespace", Step::NamespaceAxis },
+        { "parent", Step::ParentAxis },
+        { "preceding", Step::PrecedingAxis },
+        { "preceding-sibling", Step::PrecedingSiblingAxis },
+        { "self", Step::SelfAxis }
+    };
+    for (unsigned i = 0; i < sizeof(axisNameList) / sizeof(axisNameList[0]); ++i)
+        axisNames.set(axisNameList[i].name, axisNameList[i].axis);
+}
+
+static bool isAxisName(const String& name, Step::Axis& type)
+{
+    static HashMap<String, Step::Axis> axisNames;
+
+    if (axisNames.isEmpty())
+        setUpAxisNamesMap(axisNames);
+
+    HashMap<String, Step::Axis>::iterator it = axisNames.find(name);
+    if (it == axisNames.end())
+        return false;
+    type = it->second;
+    return true;
+}
+
+static bool isNodeTypeName(const String& name)
+{
+    static HashSet<String> nodeTypeNames;
+    if (nodeTypeNames.isEmpty()) {
+        nodeTypeNames.add("comment");
+        nodeTypeNames.add("text");
+        nodeTypeNames.add("processing-instruction");
+        nodeTypeNames.add("node");
+    }
+    return nodeTypeNames.contains(name);
+}
+
+/* Returns whether the last parsed token matches the [32] Operator rule
+ * (check http://www.w3.org/TR/xpath#exprlex). Necessary to disambiguate
+ * the tokens.
+ */
+bool Parser::isOperatorContext() const
+{
+    if (m_nextPos == 0)
+        return false;
+
+    switch (m_lastTokenType) {
+        case AND: case OR: case MULOP:
+        case '/': case SLASHSLASH: case '|': case PLUS: case MINUS:
+        case EQOP: case RELOP:
+        case '@': case AXISNAME:   case '(': case '[':
+            return false;
+        default:
+            return true;
+    }
+}
+
+void Parser::skipWS()
+{
+    while (m_nextPos < m_data.length() && isSpaceOrNewline(m_data[m_nextPos]))
+        ++m_nextPos;
+}
+
+Token Parser::makeTokenAndAdvance(int code, int advance)
+{
+    m_nextPos += advance;
+    return Token(code);
+}
+
+Token Parser::makeTokenAndAdvance(int code, NumericOp::Opcode val, int advance)
+{
+    m_nextPos += advance;
+    return Token(code, val);
+}
+
+Token Parser::makeTokenAndAdvance(int code, EqTestOp::Opcode val, int advance)
+{
+    m_nextPos += advance;
+    return Token(code, val);
+}
+
+// Returns next char if it's there and interesting, 0 otherwise
+char Parser::peekAheadHelper()
+{
+    if (m_nextPos + 1 >= m_data.length())
+        return 0;
+    UChar next = m_data[m_nextPos + 1];
+    if (next >= 0xff)
+        return 0;
+    return next;
+}
+
+char Parser::peekCurHelper()
+{
+    if (m_nextPos >= m_data.length())
+        return 0;
+    UChar next = m_data[m_nextPos];
+    if (next >= 0xff)
+        return 0;
+    return next;
+}
+
+Token Parser::lexString()
+{
+    UChar delimiter = m_data[m_nextPos];
+    int startPos = m_nextPos + 1;
+
+    for (m_nextPos = startPos; m_nextPos < m_data.length(); ++m_nextPos) {
+        if (m_data[m_nextPos] == delimiter) {
+            String value = m_data.substring(startPos, m_nextPos - startPos);
+            if (value.isNull())
+                value = "";
+            ++m_nextPos; // Consume the char.
+            return Token(LITERAL, value);
+        }
+    }
+
+    // Ouch, went off the end -- report error.
+    return Token(XPATH_ERROR);
+}
+
+Token Parser::lexNumber()
+{
+    int startPos = m_nextPos;
+    bool seenDot = false;
+
+    // Go until end or a non-digits character.
+    for (; m_nextPos < m_data.length(); ++m_nextPos) {
+        UChar aChar = m_data[m_nextPos];
+        if (aChar >= 0xff) break;
+
+        if (aChar < '0' || aChar > '9') {
+            if (aChar == '.' && !seenDot)
+                seenDot = true;
+            else
+                break;
+        }
+    }
+
+    return Token(NUMBER, m_data.substring(startPos, m_nextPos - startPos));
+}
+
+bool Parser::lexNCName(String& name)
+{
+    int startPos = m_nextPos;
+    if (m_nextPos >= m_data.length())
+        return false;
+
+    if (charCat(m_data[m_nextPos]) != NameStart)
+        return false;
+
+    // Keep going until we get a character that's not good for names.
+    for (; m_nextPos < m_data.length(); ++m_nextPos)
+        if (charCat(m_data[m_nextPos]) == NotPartOfName)
+            break;
+
+    name = m_data.substring(startPos, m_nextPos - startPos);
+    return true;
+}
+
+bool Parser::lexQName(String& name)
+{
+    String n1;
+    if (!lexNCName(n1))
+        return false;
+
+    skipWS();
+
+    // If the next character is :, what we just got it the prefix, if not,
+    // it's the whole thing.
+    if (peekAheadHelper() != ':') {
+        name = n1;
+        return true;
+    }
+
+    String n2;
+    if (!lexNCName(n2))
+        return false;
+
+    name = n1 + ":" + n2;
+    return true;
+}
+
+Token Parser::nextTokenInternal()
+{
+    skipWS();
+
+    if (m_nextPos >= m_data.length())
+        return Token(0);
+
+    char code = peekCurHelper();
+    switch (code) {
+        case '(': case ')': case '[': case ']':
+        case '@': case ',': case '|':
+            return makeTokenAndAdvance(code);
+        case '\'':
+        case '\"':
+            return lexString();
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            return lexNumber();
+        case '.': {
+            char next = peekAheadHelper();
+            if (next == '.')
+                return makeTokenAndAdvance(DOTDOT, 2);
+            if (next >= '0' && next <= '9')
+                return lexNumber();
+            return makeTokenAndAdvance('.');
+        }
+        case '/':
+            if (peekAheadHelper() == '/')
+                return makeTokenAndAdvance(SLASHSLASH, 2);
+            return makeTokenAndAdvance('/');
+        case '+':
+            return makeTokenAndAdvance(PLUS);
+        case '-':
+            return makeTokenAndAdvance(MINUS);
+        case '=':
+            return makeTokenAndAdvance(EQOP, EqTestOp::OP_EQ);
+        case '!':
+            if (peekAheadHelper() == '=')
+                return makeTokenAndAdvance(EQOP, EqTestOp::OP_NE, 2);
+            return Token(XPATH_ERROR);
+        case '<':
+            if (peekAheadHelper() == '=')
+                return makeTokenAndAdvance(RELOP, EqTestOp::OP_LE, 2);
+            return makeTokenAndAdvance(RELOP, EqTestOp::OP_LT);
+        case '>':
+            if (peekAheadHelper() == '=')
+                return makeTokenAndAdvance(RELOP, EqTestOp::OP_GE, 2);
+            return makeTokenAndAdvance(RELOP, EqTestOp::OP_GT);
+        case '*':
+            if (isOperatorContext())
+                return makeTokenAndAdvance(MULOP, NumericOp::OP_Mul);
+            ++m_nextPos;
+            return Token(NAMETEST, "*");
+        case '$': { // $ QName
+            m_nextPos++;
+            String name;
+            if (!lexQName(name))
+                return Token(XPATH_ERROR);
+            return Token(VARIABLEREFERENCE, name);
+        }
+    }
+
+    String name;
+    if (!lexNCName(name))
+        return Token(XPATH_ERROR);
+
+    skipWS();
+    // If we're in an operator context, check for any operator names
+    if (isOperatorContext()) {
+        if (name == "and") //### hash?
+            return Token(AND);
+        if (name == "or")
+            return Token(OR);
+        if (name == "mod")
+            return Token(MULOP, NumericOp::OP_Mod);
+        if (name == "div")
+            return Token(MULOP, NumericOp::OP_Div);
+    }
+
+    // See whether we are at a :
+    if (peekCurHelper() == ':') {
+        m_nextPos++;
+        // Any chance it's an axis name?
+        if (peekCurHelper() == ':') {
+            m_nextPos++;
+            
+            //It might be an axis name.
+            Step::Axis axis;
+            if (isAxisName(name, axis))
+                return Token(AXISNAME, axis);
+            // Ugh, :: is only valid in axis names -> error
+            return Token(XPATH_ERROR);
+        }
+
+        // Seems like this is a fully qualified qname, or perhaps the * modified one from NameTest
+        skipWS();
+        if (peekCurHelper() == '*') {
+            m_nextPos++;
+            return Token(NAMETEST, name + ":*");
+        }
+        
+        // Make a full qname.
+        String n2;
+        if (!lexNCName(n2))
+            return Token(XPATH_ERROR);
+        
+        name = name + ":" + n2;
+    }
+
+    skipWS();
+    if (peekCurHelper() == '(') {
+        //note: we don't swallow the (here!
+        
+        //either node type of function name
+        if (isNodeTypeName(name)) {
+            if (name == "processing-instruction")
+                return Token(PI, name);
+
+            return Token(NODETYPE, name);
+        }
+        //must be a function name.
+        return Token(FUNCTIONNAME, name);
+    }
+
+    // At this point, it must be NAMETEST.
+    return Token(NAMETEST, name);
+}
+
+Token Parser::nextToken()
+{
+    Token toRet = nextTokenInternal();
+    m_lastTokenType = toRet.type;
+    return toRet;
+}
+
+Parser::Parser()
+{
+    reset(String());
+}
+
+void Parser::reset(const String& data)
+{
+    m_nextPos = 0;
+    m_data = data;
+    m_lastTokenType = 0;
+    
+    m_topExpr = 0;
+    m_gotNamespaceError = false;
+}
+
+int Parser::lex(void* data)
+{
+    YYSTYPE* yylval = static_cast<YYSTYPE*>(data);
+    Token tok = nextToken();
+
+    switch (tok.type) {
+        case AXISNAME:
+            yylval->axis = tok.axis;
+            break;
+        case MULOP:
+            yylval->numop = tok.numop;
+            break;
+        case RELOP:
+        case EQOP:
+            yylval->eqop = tok.eqop;
+            break;
+        case NODETYPE:
+        case PI:
+        case FUNCTIONNAME:
+        case LITERAL:
+        case VARIABLEREFERENCE:
+        case NUMBER:
+        case NAMETEST:
+            yylval->str = new String(tok.str);
+            registerString(yylval->str);
+            break;
+    }
+
+    return tok.type;
+}
+
+bool Parser::expandQName(const String& qName, String& localName, String& namespaceURI)
+{
+    int colon = qName.find(':');
+    if (colon >= 0) {
+        if (!m_resolver)
+            return false;
+        namespaceURI = m_resolver->lookupNamespaceURI(qName.left(colon));
+        if (namespaceURI.isNull())
+            return false;
+        localName = qName.substring(colon + 1);
+    } else
+        localName = qName;
+    
+    return true;
+}
+
+Expression* Parser::parseStatement(const String& statement, PassRefPtr<XPathNSResolver> resolver, ExceptionCode& ec)
+{
+    reset(statement);
+
+    m_resolver = resolver;
+    
+    Parser* oldParser = currentParser;
+    currentParser = this;
+    int parseError = xpathyyparse(this);
+    currentParser = oldParser;
+
+    if (parseError) {
+        deleteAllValues(m_parseNodes);
+        m_parseNodes.clear();
+
+        HashSet<Vector<Predicate*>*>::iterator pend = m_predicateVectors.end();
+        for (HashSet<Vector<Predicate*>*>::iterator it = m_predicateVectors.begin(); it != pend; ++it) {
+            deleteAllValues(**it);
+            delete *it;
+        }
+        m_predicateVectors.clear();
+
+        HashSet<Vector<Expression*>*>::iterator eend = m_expressionVectors.end();
+        for (HashSet<Vector<Expression*>*>::iterator it = m_expressionVectors.begin(); it != eend; ++it) {
+            deleteAllValues(**it);
+            delete *it;
+        }
+        m_expressionVectors.clear();
+
+        deleteAllValues(m_strings);
+        m_strings.clear();
+
+        deleteAllValues(m_nodeTests);
+        m_nodeTests.clear();
+
+        m_topExpr = 0;
+
+        if (m_gotNamespaceError)
+            ec = NAMESPACE_ERR;
+        else
+            ec = XPathException::INVALID_EXPRESSION_ERR;
+        return 0;
+    }
+
+    ASSERT(m_parseNodes.size() == 1);
+    ASSERT(*m_parseNodes.begin() == m_topExpr);
+    ASSERT(m_expressionVectors.size() == 0);
+    ASSERT(m_predicateVectors.size() == 0);
+    ASSERT(m_strings.size() == 0);
+    ASSERT(m_nodeTests.size() == 0);
+
+    m_parseNodes.clear();
+    Expression* result = m_topExpr;
+    m_topExpr = 0;
+
+    return result;
+}
+
+void Parser::registerParseNode(ParseNode* node)
+{
+    if (node == 0)
+        return;
+    
+    ASSERT(!m_parseNodes.contains(node));
+    
+    m_parseNodes.add(node);
+}
+
+void Parser::unregisterParseNode(ParseNode* node)
+{
+    if (node == 0)
+        return;
+    
+    ASSERT(m_parseNodes.contains(node));
+
+    m_parseNodes.remove(node);
+}
+
+void Parser::registerPredicateVector(Vector<Predicate*>* vector)
+{
+    if (vector == 0)
+        return;
+
+    ASSERT(!m_predicateVectors.contains(vector));
+    
+    m_predicateVectors.add(vector);
+}
+
+void Parser::deletePredicateVector(Vector<Predicate*>* vector)
+{
+    if (vector == 0)
+        return;
+
+    ASSERT(m_predicateVectors.contains(vector));
+    
+    m_predicateVectors.remove(vector);
+    delete vector;
+}
+
+
+void Parser::registerExpressionVector(Vector<Expression*>* vector)
+{
+    if (vector == 0)
+        return;
+
+    ASSERT(!m_expressionVectors.contains(vector));
+    
+    m_expressionVectors.add(vector);    
+}
+
+void Parser::deleteExpressionVector(Vector<Expression*>* vector)
+{
+    if (vector == 0)
+        return;
+
+    ASSERT(m_expressionVectors.contains(vector));
+    
+    m_expressionVectors.remove(vector);
+    delete vector;
+}
+
+void Parser::registerString(String* s)
+{
+    if (s == 0)
+        return;
+    
+    ASSERT(!m_strings.contains(s));
+    
+    m_strings.add(s);        
+}
+
+void Parser::deleteString(String* s)
+{
+    if (s == 0)
+        return;
+    
+    ASSERT(m_strings.contains(s));
+    
+    m_strings.remove(s);
+    delete s;
+}
+
+void Parser::registerNodeTest(Step::NodeTest* t)
+{
+    if (t == 0)
+        return;
+    
+    ASSERT(!m_nodeTests.contains(t));
+    
+    m_nodeTests.add(t);        
+}
+
+void Parser::deleteNodeTest(Step::NodeTest* t)
+{
+    if (t == 0)
+        return;
+    
+    ASSERT(m_nodeTests.contains(t));
+    
+    m_nodeTests.remove(t);
+    delete t;
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathParser.h b/WebCore/xml/XPathParser.h
new file mode 100644
index 0000000..8d6da3f
--- /dev/null
+++ b/WebCore/xml/XPathParser.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2005 Maksim Orlovich <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathParser_h
+#define XPathParser_h
+
+#if ENABLE(XPATH)
+
+#include "XPathStep.h"
+#include "XPathPredicate.h"
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class XPathNSResolver;
+
+    namespace XPath {
+
+        class Expression;
+        class ParseNode;
+        class Predicate;
+
+        struct Token {
+            int type;
+            String str;
+            Step::Axis axis;
+            NumericOp::Opcode numop;
+            EqTestOp::Opcode eqop;
+            
+            Token(int t) : type(t) {}
+            Token(int t, const String& v): type(t), str(v) {}
+            Token(int t, Step::Axis v): type(t), axis(v) {}
+            Token(int t, NumericOp::Opcode v): type(t), numop(v) {}
+            Token(int t, EqTestOp::Opcode v): type(t), eqop(v) {}
+        };
+
+        class Parser : Noncopyable {
+        public:
+            Parser();
+
+            XPathNSResolver* resolver() const { return m_resolver.get(); }
+            bool expandQName(const String& qName, String& localName, String& namespaceURI);
+
+            Expression* parseStatement(const String& statement, PassRefPtr<XPathNSResolver>, ExceptionCode&);
+
+            static Parser* current() { return currentParser; }
+
+            int lex(void* yylval);
+
+            Expression* m_topExpr;
+            bool m_gotNamespaceError;
+
+            void registerParseNode(ParseNode*);
+            void unregisterParseNode(ParseNode*);
+
+            void registerPredicateVector(Vector<Predicate*>*);
+            void deletePredicateVector(Vector<Predicate*>*);
+
+            void registerExpressionVector(Vector<Expression*>*);
+            void deleteExpressionVector(Vector<Expression*>*);
+
+            void registerString(String*);
+            void deleteString(String*);
+
+            void registerNodeTest(Step::NodeTest*);
+            void deleteNodeTest(Step::NodeTest*);
+
+        private:
+            bool isOperatorContext() const;
+
+            void skipWS();
+            Token makeTokenAndAdvance(int type, int advance = 1);
+            Token makeTokenAndAdvance(int type, NumericOp::Opcode, int advance = 1);
+            Token makeTokenAndAdvance(int type, EqTestOp::Opcode, int advance = 1);
+            char peekAheadHelper();
+            char peekCurHelper();
+
+            Token lexString();
+            Token lexNumber();
+            bool lexNCName(String&);
+            bool lexQName(String&);
+
+            Token nextToken();
+            Token nextTokenInternal();
+
+            void reset(const String& data);
+
+            static Parser* currentParser;
+
+            unsigned m_nextPos;
+            String m_data;
+            int m_lastTokenType;
+            RefPtr<XPathNSResolver> m_resolver;
+
+            HashSet<ParseNode*> m_parseNodes;
+            HashSet<Vector<Predicate*>*> m_predicateVectors;
+            HashSet<Vector<Expression*>*> m_expressionVectors;
+            HashSet<String*> m_strings;
+            HashSet<Step::NodeTest*> m_nodeTests;
+        };
+
+    }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif
diff --git a/WebCore/xml/XPathPath.cpp b/WebCore/xml/XPathPath.cpp
new file mode 100644
index 0000000..bc7b153
--- /dev/null
+++ b/WebCore/xml/XPathPath.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathPath.h"
+
+#if ENABLE(XPATH)
+
+#include "Document.h"
+#include "XPathPredicate.h"
+#include "XPathStep.h"
+#include "XPathValue.h"
+
+namespace WebCore {
+namespace XPath {
+        
+Filter::Filter(Expression* expr, const Vector<Predicate*>& predicates)
+    : m_expr(expr), m_predicates(predicates)
+{
+}
+
+Filter::~Filter()
+{
+    delete m_expr;
+    deleteAllValues(m_predicates);
+}
+
+Value Filter::evaluate() const
+{
+    Value v = m_expr->evaluate();
+    
+    if (!v.isNodeSet()) 
+        return v;
+
+    NodeSet& nodes = v.modifiableNodeSet();
+    nodes.sort();
+
+    EvaluationContext& evaluationContext = Expression::evaluationContext();
+    for (unsigned i = 0; i < m_predicates.size(); i++) {
+        NodeSet newNodes;
+        evaluationContext.size = nodes.size();
+        evaluationContext.position = 0;
+        
+        for (unsigned j = 0; j < nodes.size(); j++) {
+            Node* node = nodes[j];
+            
+            evaluationContext.node = node;
+            ++evaluationContext.position;
+            
+            if (m_predicates[i]->evaluate())
+                newNodes.append(node);
+        }
+        nodes.swap(newNodes);
+    }
+
+    return v;
+}
+
+LocationPath::LocationPath()
+    : m_absolute(false)
+{
+}
+
+LocationPath::~LocationPath()
+{
+    deleteAllValues(m_steps);
+}
+
+Value LocationPath::evaluate() const
+{
+    EvaluationContext& evaluationContext = Expression::evaluationContext();
+    EvaluationContext backupContext = evaluationContext;
+    /* For absolute location paths, the context node is ignored - the
+     * document's root node is used instead.
+     */
+    Node* context = evaluationContext.node.get();
+    if (m_absolute && context->nodeType() != Node::DOCUMENT_NODE) 
+        context = context->ownerDocument();
+
+    NodeSet nodes;
+    nodes.append(context);
+    evaluate(nodes);
+    
+    evaluationContext = backupContext;
+    return Value(nodes, Value::adopt);
+}
+
+void LocationPath::evaluate(NodeSet& nodes) const
+{
+    for (unsigned i = 0; i < m_steps.size(); i++) {
+        Step* step = m_steps[i];
+        NodeSet newNodes;
+        HashSet<Node*> newNodesSet;
+
+        for (unsigned j = 0; j < nodes.size(); j++) {
+            NodeSet matches;
+            step->evaluate(nodes[j], matches);
+            
+            for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) {
+                Node* node = matches[nodeIndex];
+                if (newNodesSet.add(node).second)
+                    newNodes.append(node);
+            }
+        }
+        
+        nodes.swap(newNodes);
+    }
+
+    nodes.markSorted(false);
+}
+
+void LocationPath::optimizeStepPair(unsigned index)
+{
+    Step* first = m_steps[index];
+    
+    if (first->axis() == Step::DescendantOrSelfAxis
+        && first->nodeTest().kind() == Step::NodeTest::AnyNodeTest
+        && first->predicates().size() == 0) {
+
+        Step* second = m_steps[index + 1];
+        if (second->axis() == Step::ChildAxis
+            && second->nodeTest().namespaceURI().isEmpty()
+            && second->nodeTest().kind() == Step::NodeTest::NameTest
+            && second->nodeTest().data() == "*") {
+
+            // Optimize the common case of "//*" AKA descendant-or-self::node()/child::*.
+            first->setAxis(Step::DescendantAxis);
+            second->setAxis(Step::SelfAxis);
+            second->setNodeTest(Step::NodeTest::ElementNodeTest);
+            ASSERT(second->nodeTest().data().isEmpty());
+        }
+    }
+}
+
+void LocationPath::appendStep(Step* step)
+{
+    m_steps.append(step);
+    
+    unsigned stepCount = m_steps.size();
+    if (stepCount > 1)
+        optimizeStepPair(stepCount - 2);
+}
+
+void LocationPath::insertFirstStep(Step* step)
+{
+    m_steps.insert(0, step);
+
+    if (m_steps.size() > 1)
+        optimizeStepPair(0);
+}
+
+Path::Path(Filter* filter, LocationPath* path)
+    : m_filter(filter),
+    m_path(path)
+{
+}
+
+Path::~Path()
+{
+    delete m_filter;
+    delete m_path;
+}
+
+Value Path::evaluate() const
+{
+    Value v = m_filter->evaluate();
+
+    NodeSet& nodes = v.modifiableNodeSet();
+    m_path->evaluate(nodes);
+    
+    return v;
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathPath.h b/WebCore/xml/XPathPath.h
new file mode 100644
index 0000000..97692b2
--- /dev/null
+++ b/WebCore/xml/XPathPath.h
@@ -0,0 +1,93 @@
+/*
+ * path.h - Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathPath_h
+#define XPathPath_h
+
+#if ENABLE(XPATH)
+
+#include "XPathExpressionNode.h"
+#include "XPathNodeSet.h"
+
+int xpathyyparse(void*);
+
+namespace WebCore {
+
+    namespace XPath {
+
+        class Predicate;
+        class Step;
+
+        class Filter : public Expression {
+        public:
+            Filter(Expression*, const Vector<Predicate*>& = Vector<Predicate*>());
+            virtual ~Filter();
+
+            virtual Value evaluate() const;
+
+        private:
+            Expression* m_expr;
+            Vector<Predicate*> m_predicates;
+        };
+
+        class LocationPath : public Expression {
+        public:
+            LocationPath();
+            virtual ~LocationPath();
+            void setAbsolute(bool value) { m_absolute = value; }
+
+            virtual Value evaluate() const;
+            void evaluate(NodeSet& nodes) const; // nodes is an input/output parameter
+
+            void appendStep(Step* step);
+            void insertFirstStep(Step* step);
+
+        private:
+            void optimizeStepPair(unsigned index);
+
+            Vector<Step*> m_steps;
+            bool m_absolute;
+        };
+
+        class Path : public Expression
+        {
+        public:
+            Path(Filter*, LocationPath*);
+            virtual ~Path();
+
+            virtual Value evaluate() const;
+
+        private:
+            Filter* m_filter;
+            LocationPath* m_path;
+        };
+
+    }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Path_H
diff --git a/WebCore/xml/XPathPredicate.cpp b/WebCore/xml/XPathPredicate.cpp
new file mode 100644
index 0000000..7b3e4d8
--- /dev/null
+++ b/WebCore/xml/XPathPredicate.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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"
+
+#if ENABLE(XPATH)
+
+#include "XPathPredicate.h"
+
+#include "Node.h"
+#include "XPathFunctions.h"
+#include "XPathUtil.h"
+#include "XPathValue.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+namespace XPath {
+        
+Number::Number(double value)
+    : m_value(value)
+{
+}
+
+Value Number::evaluate() const
+{
+    return m_value;
+}
+
+StringExpression::StringExpression(const String& value)
+    : m_value(value)
+{
+}
+
+Value StringExpression::evaluate() const
+{
+    return m_value;
+}
+
+Value Negative::evaluate() const
+{
+    Value p(subExpr(0)->evaluate());
+    return -p.toNumber();
+}
+
+NumericOp::NumericOp(Opcode opcode, Expression* lhs, Expression* rhs)
+    : m_opcode(opcode)
+{
+    addSubExpression(lhs);
+    addSubExpression(rhs);
+}
+
+Value NumericOp::evaluate() const
+{
+    Value lhs(subExpr(0)->evaluate());
+    Value rhs(subExpr(1)->evaluate());
+    
+    double leftVal = lhs.toNumber();
+    double rightVal = rhs.toNumber();
+
+    switch (m_opcode) {
+        case OP_Add:
+            return leftVal + rightVal;
+        case OP_Sub:
+            return leftVal - rightVal;
+        case OP_Mul:
+            return leftVal * rightVal;
+        case OP_Div:
+            return leftVal / rightVal;
+        case OP_Mod:
+            return fmod(leftVal, rightVal);
+    }
+    ASSERT_NOT_REACHED();
+    return 0.0;
+}
+
+EqTestOp::EqTestOp(Opcode opcode, Expression* lhs, Expression* rhs)
+    : m_opcode(opcode)
+{
+    addSubExpression(lhs);
+    addSubExpression(rhs);
+}
+
+bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
+{
+    if (lhs.isNodeSet()) {
+        const NodeSet& lhsSet = lhs.toNodeSet();
+        if (rhs.isNodeSet()) {
+            // If both objects to be compared are node-sets, then the comparison will be true if and only if
+            // there is a node in the first node-set and a node in the second node-set such that the result of
+            // performing the comparison on the string-values of the two nodes is true.
+            const NodeSet& rhsSet = rhs.toNodeSet();
+            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)
+                for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)
+                    if (compare(stringValue(lhsSet[lindex]), stringValue(rhsSet[rindex])))
+                        return true;
+            return false;
+        }
+        if (rhs.isNumber()) {
+            // If one object to be compared is a node-set and the other is a number, then the comparison will be true
+            // if and only if there is a node in the node-set such that the result of performing the comparison on the number
+            // to be compared and on the result of converting the string-value of that node to a number using the number function is true.
+            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)
+                if (compare(Value(stringValue(lhsSet[lindex])).toNumber(), rhs))
+                    return true;
+            return false;
+        }
+        if (rhs.isString()) {
+            // If one object to be compared is a node-set and the other is a string, then the comparison will be true
+            // if and only if there is a node in the node-set such that the result of performing the comparison on
+            // the string-value of the node and the other string is true.
+            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)
+                if (compare(stringValue(lhsSet[lindex]), rhs))
+                    return true;
+            return false;
+        }
+        if (rhs.isBoolean()) {
+            // If one object to be compared is a node-set and the other is a boolean, then the comparison will be true
+            // if and only if the result of performing the comparison on the boolean and on the result of converting
+            // the node-set to a boolean using the boolean function is true.
+            return compare(lhs.toBoolean(), rhs);
+        }
+        ASSERT(0);
+    }
+    if (rhs.isNodeSet()) {
+        const NodeSet& rhsSet = rhs.toNodeSet();
+        if (lhs.isNumber()) {
+            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)
+                if (compare(lhs, Value(stringValue(rhsSet[rindex])).toNumber()))
+                    return true;
+            return false;
+        }
+        if (lhs.isString()) {
+            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)
+                if (compare(lhs, stringValue(rhsSet[rindex])))
+                    return true;
+            return false;
+        }
+        if (lhs.isBoolean())
+            return compare(lhs, rhs.toBoolean());
+        ASSERT(0);
+    }
+    
+    // Neither side is a NodeSet.
+    switch (m_opcode) {
+        case OP_EQ:
+        case OP_NE:
+            bool equal;
+            if (lhs.isBoolean() || rhs.isBoolean())
+                equal = lhs.toBoolean() == rhs.toBoolean();
+            else if (lhs.isNumber() || rhs.isNumber())
+                equal = lhs.toNumber() == rhs.toNumber();
+            else
+                equal = lhs.toString() == rhs.toString();
+
+            if (m_opcode == OP_EQ)
+                return equal;
+            return !equal;
+        case OP_GT:
+            return lhs.toNumber() > rhs.toNumber();
+        case OP_GE:
+            return lhs.toNumber() >= rhs.toNumber();
+        case OP_LT:
+            return lhs.toNumber() < rhs.toNumber();
+        case OP_LE:
+            return lhs.toNumber() <= rhs.toNumber();
+    }
+    ASSERT(0);
+    return false;
+}
+
+Value EqTestOp::evaluate() const
+{
+    Value lhs(subExpr(0)->evaluate());
+    Value rhs(subExpr(1)->evaluate());
+
+    return compare(lhs, rhs);
+}
+
+LogicalOp::LogicalOp(Opcode opcode, Expression* lhs, Expression* rhs)
+    : m_opcode(opcode)
+{
+    addSubExpression(lhs);
+    addSubExpression(rhs);
+}
+
+bool LogicalOp::shortCircuitOn() const
+{
+    if (m_opcode == OP_And)
+        return false; //false and foo
+
+    return true;  //true or bar
+}
+
+Value LogicalOp::evaluate() const
+{
+    Value lhs(subExpr(0)->evaluate());
+
+    // This is not only an optimization, http://www.w3.org/TR/xpath
+    // dictates that we must do short-circuit evaluation
+    bool lhsBool = lhs.toBoolean();
+    if (lhsBool == shortCircuitOn())
+        return lhsBool;
+
+    return subExpr(1)->evaluate().toBoolean();
+}
+
+Value Union::evaluate() const
+{
+    Value lhsResult = subExpr(0)->evaluate();
+    Value rhs = subExpr(1)->evaluate();
+    if (!lhsResult.isNodeSet() || !rhs.isNodeSet())
+        return NodeSet();
+    
+    NodeSet& resultSet = lhsResult.modifiableNodeSet();
+    const NodeSet& rhsNodes = rhs.toNodeSet();
+    
+    HashSet<Node*> nodes;
+    for (size_t i = 0; i < resultSet.size(); ++i)
+        nodes.add(resultSet[i]);
+    
+    for (size_t i = 0; i < rhsNodes.size(); ++i) {
+        Node* node = rhsNodes[i];
+        if (nodes.add(node).second)
+            resultSet.append(node);
+    }
+
+    // It is also possible to use merge sort to avoid making the result unsorted;
+    // but this would waste the time in cases when order is not important.
+    resultSet.markSorted(false);
+    return lhsResult;
+}
+
+Predicate::Predicate(Expression* expr)
+    : m_expr(expr)
+{
+}
+
+Predicate::~Predicate()
+{
+    delete m_expr;
+}
+
+bool Predicate::evaluate() const
+{
+    ASSERT(m_expr != 0);
+
+    Value result(m_expr->evaluate());
+
+    // foo[3] means foo[position()=3]
+    if (result.isNumber())
+        return EqTestOp(EqTestOp::OP_EQ, createFunction("position"), new Number(result.toNumber())).evaluate().toBoolean();
+
+    return result.toBoolean();
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathPredicate.h b/WebCore/xml/XPathPredicate.h
new file mode 100644
index 0000000..8d1b0d8
--- /dev/null
+++ b/WebCore/xml/XPathPredicate.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathPredicate_h
+#define XPathPredicate_h
+
+#if ENABLE(XPATH)
+
+#include "XPathExpressionNode.h"
+#include "XPathValue.h"
+
+namespace WebCore {
+
+    namespace XPath {
+        
+        class Number : public Expression {
+        public:
+            Number(double);
+        private:
+            virtual Value evaluate() const;
+            Value m_value;
+        };
+
+        class StringExpression : public Expression {
+        public:
+            StringExpression(const String&);
+        private:
+            virtual Value evaluate() const;
+            Value m_value;
+        };
+
+        class Negative : public Expression {
+        private:
+            virtual Value evaluate() const;
+        };
+
+        class NumericOp : public Expression {
+        public:
+            enum Opcode {
+                OP_Add, OP_Sub, OP_Mul, OP_Div, OP_Mod
+            };
+            NumericOp(Opcode, Expression* lhs, Expression* rhs);
+        private:
+            virtual Value evaluate() const;
+            Opcode m_opcode;
+        };
+
+        class EqTestOp : public Expression {
+        public:
+            enum Opcode { OP_EQ, OP_NE, OP_GT, OP_LT, OP_GE, OP_LE };
+            EqTestOp(Opcode, Expression* lhs, Expression* rhs);
+            virtual Value evaluate() const;
+        private:
+            bool compare(const Value&, const Value&) const;
+            Opcode m_opcode;
+        };
+
+        class LogicalOp : public Expression {
+        public:
+            enum Opcode { OP_And, OP_Or };
+            LogicalOp(Opcode, Expression* lhs, Expression* rhs);
+        private:
+            bool shortCircuitOn() const;
+            virtual Value evaluate() const;
+            Opcode m_opcode;
+        };
+
+        class Union : public Expression {
+        private:
+            virtual Value evaluate() const;
+        };
+
+        class Predicate : Noncopyable {
+        public:
+            Predicate(Expression*);
+            ~Predicate();
+            bool evaluate() const;
+        private:
+            Expression* m_expr;
+        };
+
+    }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathPredicate_h
diff --git a/WebCore/xml/XPathResult.cpp b/WebCore/xml/XPathResult.cpp
new file mode 100644
index 0000000..285350e
--- /dev/null
+++ b/WebCore/xml/XPathResult.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathResult.h"
+
+#if ENABLE(XPATH)
+
+#include "EventListener.h"
+#include "EventNames.h"
+#include "EventTargetNode.h"
+#include "ExceptionCode.h"
+#include "XPathEvaluator.h"
+#include "XPathException.h"
+
+namespace WebCore {
+
+using namespace XPath;
+
+class InvalidatingEventListener : public EventListener {
+public:
+    static PassRefPtr<InvalidatingEventListener> create(XPathResult* result) { return adoptRef(new InvalidatingEventListener(result)); }
+    virtual void handleEvent(Event*, bool) { m_result->invalidateIteratorState(); }
+
+private:
+    InvalidatingEventListener(XPathResult* result) : m_result(result) { }
+    XPathResult* m_result;
+};
+
+XPathResult::XPathResult(EventTargetNode* eventTarget, const Value& value)
+    : m_value(value)
+    , m_eventTarget(eventTarget)
+{
+    m_eventListener = InvalidatingEventListener::create(this);
+    m_eventTarget->addEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener, false);
+    switch (m_value.type()) {
+        case Value::BooleanValue:
+            m_resultType = BOOLEAN_TYPE;
+            return;
+        case Value::NumberValue:
+            m_resultType = NUMBER_TYPE;
+            return;
+        case Value::StringValue:
+            m_resultType = STRING_TYPE;
+            return;
+        case Value::NodeSetValue:
+            m_resultType = UNORDERED_NODE_ITERATOR_TYPE;
+            m_nodeSetPosition = 0;
+            m_nodeSet = m_value.toNodeSet();
+            m_invalidIteratorState = false;
+            return;
+    }
+    ASSERT_NOT_REACHED();
+}
+
+XPathResult::~XPathResult()
+{
+    if (m_eventTarget)
+        m_eventTarget->removeEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
+}
+
+void XPathResult::convertTo(unsigned short type, ExceptionCode& ec)
+{
+    switch (type) {
+        case ANY_TYPE:
+            break;
+        case NUMBER_TYPE:
+            m_resultType = type;
+            m_value = m_value.toNumber();
+            break;
+        case STRING_TYPE:
+            m_resultType = type;
+            m_value = m_value.toString();
+            break;
+        case BOOLEAN_TYPE:
+            m_resultType = type;
+            m_value = m_value.toBoolean();
+            break;
+        case UNORDERED_NODE_ITERATOR_TYPE:
+        case UNORDERED_NODE_SNAPSHOT_TYPE:
+        case ANY_UNORDERED_NODE_TYPE:
+        case FIRST_ORDERED_NODE_TYPE: // This is correct - singleNodeValue() will take care of ordering.
+            if (!m_value.isNodeSet()) {
+                ec = XPathException::TYPE_ERR;
+                return;
+            }
+            m_resultType = type;
+            break;
+        case ORDERED_NODE_ITERATOR_TYPE:
+            if (!m_value.isNodeSet()) {
+                ec = XPathException::TYPE_ERR;
+                return;
+            }
+            m_nodeSet.sort();
+            m_resultType = type;
+            break;
+        case ORDERED_NODE_SNAPSHOT_TYPE:
+            if (!m_value.isNodeSet()) {
+                ec = XPathException::TYPE_ERR;
+                return;
+            }
+            m_value.toNodeSet().sort();
+            m_resultType = type;
+            break;
+    }
+}
+
+unsigned short XPathResult::resultType() const
+{
+    return m_resultType;
+}
+
+double XPathResult::numberValue(ExceptionCode& ec) const
+{
+    if (resultType() != NUMBER_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return 0.0;
+    }
+    return m_value.toNumber();
+}
+
+String XPathResult::stringValue(ExceptionCode& ec) const
+{
+    if (resultType() != STRING_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return String();
+    }
+    return m_value.toString();
+}
+
+bool XPathResult::booleanValue(ExceptionCode& ec) const
+{
+    if (resultType() != BOOLEAN_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return false;
+    }
+    return m_value.toBoolean();
+}
+
+Node* XPathResult::singleNodeValue(ExceptionCode& ec) const
+{
+    if (resultType() != ANY_UNORDERED_NODE_TYPE && resultType() != FIRST_ORDERED_NODE_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return 0;
+    }
+  
+    const NodeSet& nodes = m_value.toNodeSet();
+    if (resultType() == FIRST_ORDERED_NODE_TYPE)
+        return nodes.firstNode();
+    else
+        return nodes.anyNode();
+}
+
+void XPathResult::invalidateIteratorState()
+{ 
+    m_invalidIteratorState = true;
+    
+    ASSERT(m_eventTarget);
+    ASSERT(m_eventListener);
+    
+    m_eventTarget->removeEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
+    
+    m_eventTarget = 0;
+}
+
+bool XPathResult::invalidIteratorState() const
+{
+    if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE)
+        return false;
+    
+    return m_invalidIteratorState;
+}
+
+unsigned long XPathResult::snapshotLength(ExceptionCode& ec) const
+{
+    if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return 0;
+    }
+
+    return m_value.toNodeSet().size();
+}
+
+Node* XPathResult::iterateNext(ExceptionCode& ec)
+{
+    if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return 0;
+    }
+    
+    if (m_invalidIteratorState) {
+        ec = INVALID_STATE_ERR;
+        return 0;
+    }
+    
+    if (m_nodeSetPosition + 1 > m_nodeSet.size())
+        return 0;
+
+    Node* node = m_nodeSet[m_nodeSetPosition];
+    
+    m_nodeSetPosition++;
+
+    return node;
+}
+
+Node* XPathResult::snapshotItem(unsigned long index, ExceptionCode& ec)
+{
+    if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) {
+        ec = XPathException::TYPE_ERR;
+        return 0;
+    }
+    
+    const NodeSet& nodes = m_value.toNodeSet();
+    if (index >= nodes.size())
+        return 0;
+    
+    return nodes[index];
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathResult.h b/WebCore/xml/XPathResult.h
new file mode 100644
index 0000000..ecd5cac
--- /dev/null
+++ b/WebCore/xml/XPathResult.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathResult_h
+#define XPathResult_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/RefCounted.h>
+#include "XPathValue.h"
+
+namespace WebCore {
+
+    typedef int ExceptionCode;
+
+    class EventListener;
+    class EventTargetNode;
+    class Node;
+    class String;
+
+    class XPathResult : public RefCounted<XPathResult> {
+    public:
+        enum XPathResultType {
+            ANY_TYPE = 0,
+            NUMBER_TYPE = 1,
+            STRING_TYPE = 2,
+            BOOLEAN_TYPE = 3,
+            UNORDERED_NODE_ITERATOR_TYPE = 4,
+            ORDERED_NODE_ITERATOR_TYPE = 5,
+            UNORDERED_NODE_SNAPSHOT_TYPE = 6,
+            ORDERED_NODE_SNAPSHOT_TYPE = 7,
+            ANY_UNORDERED_NODE_TYPE = 8,
+            FIRST_ORDERED_NODE_TYPE = 9
+        };
+        
+        static PassRefPtr<XPathResult> create(EventTargetNode* eventTarget, const XPath::Value& value) { return adoptRef(new XPathResult(eventTarget, value)); }
+        ~XPathResult();
+        
+        void convertTo(unsigned short type, ExceptionCode&);
+
+        unsigned short resultType() const;
+
+        double numberValue(ExceptionCode&) const;
+        String stringValue(ExceptionCode&) const;
+        bool booleanValue(ExceptionCode&) const;
+        Node* singleNodeValue(ExceptionCode&) const;
+
+        bool invalidIteratorState() const;
+        unsigned long snapshotLength(ExceptionCode&) const;
+        Node* iterateNext(ExceptionCode&);
+        Node* snapshotItem(unsigned long index, ExceptionCode&);
+
+        void invalidateIteratorState();
+
+    private:
+        XPathResult(EventTargetNode*, const XPath::Value&);
+        
+        XPath::Value m_value;
+        unsigned m_nodeSetPosition;
+        XPath::NodeSet m_nodeSet; // FIXME: why duplicate the node set stored in m_value?
+        unsigned short m_resultType;
+        bool m_invalidIteratorState;
+        RefPtr<EventTargetNode> m_eventTarget;
+        RefPtr<EventListener> m_eventListener;
+    };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathResult_h
diff --git a/WebCore/xml/XPathResult.idl b/WebCore/xml/XPathResult.idl
new file mode 100644
index 0000000..bc36c3e
--- /dev/null
+++ b/WebCore/xml/XPathResult.idl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module xpath {
+
+    interface [GenerateConstructor, Conditional=XPATH] XPathResult {
+        const unsigned short ANY_TYPE                       = 0;
+        const unsigned short NUMBER_TYPE                    = 1;
+        const unsigned short STRING_TYPE                    = 2;
+        const unsigned short BOOLEAN_TYPE                   = 3;
+        const unsigned short UNORDERED_NODE_ITERATOR_TYPE   = 4;
+        const unsigned short ORDERED_NODE_ITERATOR_TYPE     = 5;
+        const unsigned short UNORDERED_NODE_SNAPSHOT_TYPE   = 6;
+        const unsigned short ORDERED_NODE_SNAPSHOT_TYPE     = 7;
+        const unsigned short ANY_UNORDERED_NODE_TYPE        = 8;
+        const unsigned short FIRST_ORDERED_NODE_TYPE        = 9;
+
+        readonly attribute unsigned short  resultType;
+        readonly attribute double          numberValue
+            getter raises (DOMException);
+            
+        readonly attribute DOMString       stringValue
+            getter raises (DOMException);
+
+        readonly attribute boolean         booleanValue
+            getter raises (DOMException);
+
+        readonly attribute Node            singleNodeValue
+            getter raises (DOMException);
+
+        readonly attribute boolean         invalidIteratorState;
+        readonly attribute unsigned long   snapshotLength
+            getter raises (DOMException);
+            
+        Node iterateNext()
+            raises (DOMException);
+        Node snapshotItem(in unsigned long index)
+            raises (DOMException);
+    };
+
+}
diff --git a/WebCore/xml/XPathStep.cpp b/WebCore/xml/XPathStep.cpp
new file mode 100644
index 0000000..abdcba5
--- /dev/null
+++ b/WebCore/xml/XPathStep.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathStep.h"
+
+#if ENABLE(XPATH)
+
+#include "Document.h"
+#include "Element.h"
+#include "NamedAttrMap.h"
+#include "XPathNSResolver.h"
+#include "XPathParser.h"
+#include "XPathUtil.h"
+
+namespace WebCore {
+namespace XPath {
+
+Step::Step(Axis axis, const NodeTest& nodeTest, const Vector<Predicate*>& predicates)
+    : m_axis(axis)
+    , m_nodeTest(nodeTest)
+    , m_predicates(predicates)
+{
+}
+
+Step::~Step()
+{
+    deleteAllValues(m_predicates);
+}
+
+void Step::evaluate(Node* context, NodeSet& nodes) const
+{
+    nodesInAxis(context, nodes);
+    
+    EvaluationContext& evaluationContext = Expression::evaluationContext();
+    
+    for (unsigned i = 0; i < m_predicates.size(); i++) {
+        Predicate* predicate = m_predicates[i];
+
+        NodeSet newNodes;
+        if (!nodes.isSorted())
+            newNodes.markSorted(false);
+
+        for (unsigned j = 0; j < nodes.size(); j++) {
+            Node* node = nodes[j];
+
+            Expression::evaluationContext().node = node;
+            evaluationContext.size = nodes.size();
+            evaluationContext.position = j + 1;
+            if (predicate->evaluate())
+                newNodes.append(node);
+        }
+
+        nodes.swap(newNodes);
+    }
+}
+
+void Step::nodesInAxis(Node* context, NodeSet& nodes) const
+{
+    ASSERT(nodes.isEmpty());
+    switch (m_axis) {
+        case ChildAxis:
+            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
+                return;
+
+            for (Node* n = context->firstChild(); n; n = n->nextSibling())
+                if (nodeMatches(n))
+                    nodes.append(n);
+            return;
+        case DescendantAxis:
+            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
+                return;
+
+            for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
+                if (nodeMatches(n))
+                    nodes.append(n);
+            return;
+        case ParentAxis:
+            if (context->isAttributeNode()) {
+                Node* n = static_cast<Attr*>(context)->ownerElement();
+                if (nodeMatches(n))
+                    nodes.append(n);
+            } else {
+                Node* n = context->parentNode();
+                if (n && nodeMatches(n))
+                    nodes.append(n);
+            }
+            return;
+        case AncestorAxis: {
+            Node* n = context;
+            if (context->isAttributeNode()) {
+                n = static_cast<Attr*>(context)->ownerElement();
+                if (nodeMatches(n))
+                    nodes.append(n);
+            }
+            for (n = n->parentNode(); n; n = n->parentNode())
+                if (nodeMatches(n))
+                    nodes.append(n);
+            nodes.markSorted(false);
+            return;
+        }
+        case FollowingSiblingAxis:
+            if (context->nodeType() == Node::ATTRIBUTE_NODE ||
+                 context->nodeType() == Node::XPATH_NAMESPACE_NODE) 
+                return;
+            
+            for (Node* n = context->nextSibling(); n; n = n->nextSibling())
+                if (nodeMatches(n))
+                    nodes.append(n);
+            return;
+        case PrecedingSiblingAxis:
+            if (context->nodeType() == Node::ATTRIBUTE_NODE ||
+                 context->nodeType() == Node::XPATH_NAMESPACE_NODE)
+                return;
+            
+            for (Node* n = context->previousSibling(); n; n = n->previousSibling())
+                if (nodeMatches(n))
+                    nodes.append(n);
+
+            nodes.markSorted(false);
+            return;
+        case FollowingAxis:
+            if (context->isAttributeNode()) {
+                Node* p = static_cast<Attr*>(context)->ownerElement();
+                while ((p = p->traverseNextNode()))
+                    if (nodeMatches(p))
+                        nodes.append(p);
+            } else {
+                for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) {
+                    for (Node* n = p->nextSibling(); n; n = n->nextSibling()) {
+                        if (nodeMatches(n))
+                            nodes.append(n);
+                        for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n))
+                            if (nodeMatches(c))
+                                nodes.append(c);
+                    }
+                }
+            }
+            return;
+        case PrecedingAxis: {
+            if (context->isAttributeNode())
+                context = static_cast<Attr*>(context)->ownerElement();
+
+            Node* n = context;
+            while (Node* parent = n->parent()) {
+                for (n = n->traversePreviousNode(); n != parent; n = n->traversePreviousNode())
+                    if (nodeMatches(n))
+                        nodes.append(n);
+                n = parent;
+            }
+            nodes.markSorted(false);
+            return;
+        }
+        case AttributeAxis: {
+            if (context->nodeType() != Node::ELEMENT_NODE)
+                return;
+
+            // Avoid lazily creating attribute nodes for attributes that we do not need anyway.
+            if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != "*") {
+                RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data());
+                if (n && n->namespaceURI() != "http://www.w3.org/2000/xmlns/") // In XPath land, namespace nodes are not accessible on the attribute axis.
+                    nodes.append(n.release());
+                return;
+            }
+            
+            NamedAttrMap* attrs = context->attributes();
+            if (!attrs)
+                return;
+
+            for (unsigned long i = 0; i < attrs->length(); ++i) {
+                RefPtr<Node> n = attrs->item(i);
+                if (nodeMatches(n.get()))
+                    nodes.append(n.release());
+            }
+            return;
+        }
+        case NamespaceAxis:
+            // XPath namespace nodes are not implemented yet.
+            return;
+        case SelfAxis:
+            if (nodeMatches(context))
+                nodes.append(context);
+            return;
+        case DescendantOrSelfAxis:
+            if (nodeMatches(context))
+                nodes.append(context);
+            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
+                return;
+
+            for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
+            if (nodeMatches(n))
+                nodes.append(n);
+            return;
+        case AncestorOrSelfAxis: {
+            if (nodeMatches(context))
+                nodes.append(context);
+            Node* n = context;
+            if (context->isAttributeNode()) {
+                n = static_cast<Attr*>(context)->ownerElement();
+                if (nodeMatches(n))
+                    nodes.append(n);
+            }
+            for (n = n->parentNode(); n; n = n->parentNode())
+                if (nodeMatches(n))
+                    nodes.append(n);
+
+            nodes.markSorted(false);
+            return;
+        }
+    }
+    ASSERT_NOT_REACHED();
+}
+
+
+bool Step::nodeMatches(Node* node) const
+{
+    switch (m_nodeTest.kind()) {
+        case NodeTest::TextNodeTest:
+            return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE;
+        case NodeTest::CommentNodeTest:
+            return node->nodeType() == Node::COMMENT_NODE;
+        case NodeTest::ProcessingInstructionNodeTest: {
+            const String& name = m_nodeTest.data();
+            return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name);
+        }
+        case NodeTest::ElementNodeTest:
+            return node->isElementNode();
+        case NodeTest::AnyNodeTest:
+            return true;
+        case NodeTest::NameTest: {
+            const String& name = m_nodeTest.data();
+            const String& namespaceURI = m_nodeTest.namespaceURI();
+
+            if (m_axis == AttributeAxis) {
+                ASSERT(node->isAttributeNode());
+
+                // In XPath land, namespace nodes are not accessible on the attribute axis.
+                if (node->namespaceURI() == "http://www.w3.org/2000/xmlns/")
+                    return false;
+
+                if (name == "*")
+                    return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI;
+
+                return node->localName() == name && node->namespaceURI() == namespaceURI;
+            }
+
+            if (m_axis == NamespaceAxis) {
+                // Node test on the namespace axis is not implemented yet
+                return false;
+            }
+            
+            if (name == "*")
+                return node->nodeType() == primaryNodeType(m_axis) && (namespaceURI.isEmpty() || namespaceURI == node->namespaceURI());
+
+            // We use tagQName here because we don't want the element name in uppercase 
+            // like we get with HTML elements.
+            // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace.
+            return node->nodeType() == Node::ELEMENT_NODE
+                    && static_cast<Element*>(node)->tagQName().localName() == name
+                    && ((node->isHTMLElement() && node->document()->isHTMLDocument() && namespaceURI.isNull()) || namespaceURI == node->namespaceURI());
+        }
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+Node::NodeType Step::primaryNodeType(Axis axis) const
+{
+    switch (axis) {
+        case AttributeAxis:
+            return Node::ATTRIBUTE_NODE;
+        case NamespaceAxis:
+            return Node::XPATH_NAMESPACE_NODE;
+        default:
+            return Node::ELEMENT_NODE;
+    }
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathStep.h b/WebCore/xml/XPathStep.h
new file mode 100644
index 0000000..f1420d0
--- /dev/null
+++ b/WebCore/xml/XPathStep.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathStep_h
+#define XPathStep_h
+
+#if ENABLE(XPATH)
+
+#include "Node.h"
+#include "XPathExpressionNode.h"
+#include "XPathNodeSet.h"
+
+namespace WebCore {
+
+    namespace XPath {
+
+        class Predicate;
+        
+        class Step : public ParseNode, Noncopyable {
+        public:
+            enum Axis {
+                AncestorAxis, AncestorOrSelfAxis, AttributeAxis,
+                ChildAxis, DescendantAxis, DescendantOrSelfAxis,
+                FollowingAxis, FollowingSiblingAxis, NamespaceAxis,
+                ParentAxis, PrecedingAxis, PrecedingSiblingAxis,
+                SelfAxis
+            };
+            
+            class NodeTest {
+            public:
+                enum Kind {
+                    TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest,
+                    ElementNodeTest // XPath 2.0
+                };
+                
+                NodeTest(Kind kind) : m_kind(kind) {}
+                NodeTest(Kind kind, const String& data) : m_kind(kind), m_data(data) {}
+                NodeTest(Kind kind, const String& data, const String& namespaceURI) : m_kind(kind), m_data(data), m_namespaceURI(namespaceURI) {}
+                
+                Kind kind() const { return m_kind; }
+                const String data() const { return m_data; }
+                const String namespaceURI() const { return m_namespaceURI; }
+                
+            private:
+                Kind m_kind;
+                String m_data;
+                String m_namespaceURI;
+            };
+
+            Step(Axis, const NodeTest& nodeTest, const Vector<Predicate*>& predicates = Vector<Predicate*>());
+            ~Step();
+
+            void evaluate(Node* context, NodeSet&) const;
+            
+            Axis axis() const { return m_axis; }
+            NodeTest nodeTest() const { return m_nodeTest; }
+            const Vector<Predicate*>& predicates() const { return m_predicates; }
+            
+            void setAxis(Axis axis) { m_axis = axis; }
+            void setNodeTest(NodeTest nodeTest) { m_nodeTest = nodeTest; }
+            void setPredicates(const Vector<Predicate*>& predicates) { m_predicates = predicates; }
+            
+        private:
+            void parseNodeTest(const String&);
+            void nodesInAxis(Node* context, NodeSet&) const;
+            bool nodeMatches(Node*) const;
+            String namespaceFromNodetest(const String& nodeTest) const;
+            Node::NodeType primaryNodeType(Axis) const;
+
+            Axis m_axis;
+            NodeTest m_nodeTest;
+            Vector<Predicate*> m_predicates;
+        };
+
+    }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Step_H
diff --git a/WebCore/xml/XPathUtil.cpp b/WebCore/xml/XPathUtil.cpp
new file mode 100644
index 0000000..ab4b1d4
--- /dev/null
+++ b/WebCore/xml/XPathUtil.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathUtil.h"
+
+#if ENABLE(XPATH)
+
+#include "ContainerNode.h"
+
+namespace WebCore {
+namespace XPath {
+        
+bool isRootDomNode(Node* node)
+{
+    return node && !node->parentNode();
+}
+
+String stringValue(Node* node)
+{
+    switch (node->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::TEXT_NODE:
+        case Node::CDATA_SECTION_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            return node->nodeValue();
+        default:
+            if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) {
+                String str;
+                
+                for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node))
+                    if (n->isTextNode())
+                        str += n->nodeValue();
+
+                return str;
+            }
+    }
+    
+    return String();
+}
+
+bool isValidContextNode(Node* node)
+{
+    if (!node)
+        return false;
+    switch (node->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+        case Node::CDATA_SECTION_NODE:
+        case Node::COMMENT_NODE:
+        case Node::DOCUMENT_NODE:
+        case Node::ELEMENT_NODE:
+        case Node::PROCESSING_INSTRUCTION_NODE:
+        case Node::XPATH_NAMESPACE_NODE:
+            return true;
+        case Node::DOCUMENT_FRAGMENT_NODE:
+        case Node::DOCUMENT_TYPE_NODE:
+        case Node::ENTITY_NODE:
+        case Node::ENTITY_REFERENCE_NODE:
+        case Node::NOTATION_NODE:
+            return false;
+        case Node::TEXT_NODE:
+            return !(node->parentNode() && node->parentNode()->isAttributeNode());
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathUtil.h b/WebCore/xml/XPathUtil.h
new file mode 100644
index 0000000..30f21ae
--- /dev/null
+++ b/WebCore/xml/XPathUtil.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathUtil_h
+#define XPathUtil_h
+
+#if ENABLE(XPATH)
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class Node;
+    class String;
+
+    namespace XPath {
+
+        /* @return whether the given node is the root node */
+        bool isRootDomNode(Node*);
+
+        /* @return the 'string-value' of the given node as specified by http://www.w3.org/TR/xpath */
+        String stringValue(Node*);
+
+        /* @return whether the given node is a valid context node */
+        bool isValidContextNode(Node*);
+
+    }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Util_H
diff --git a/WebCore/xml/XPathValue.cpp b/WebCore/xml/XPathValue.cpp
new file mode 100644
index 0000000..b3cad38
--- /dev/null
+++ b/WebCore/xml/XPathValue.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathValue.h"
+
+#if ENABLE(XPATH)
+
+#include "Node.h"
+#include "XPathUtil.h"
+
+#include <wtf/MathExtras.h>
+#include <limits>
+
+using std::numeric_limits;
+
+namespace WebCore {
+namespace XPath {
+
+const Value::AdoptTag Value::adopt = {};
+
+const NodeSet& Value::toNodeSet() const
+{
+    if (!m_data) {
+        static NodeSet emptyNodeSet;
+        return emptyNodeSet;
+    }
+
+    return m_data->m_nodeSet;
+}    
+
+NodeSet& Value::modifiableNodeSet()
+{
+    if (!m_data)
+        m_data = ValueData::create();
+    
+    m_type = NodeSetValue;
+    return m_data->m_nodeSet;
+}
+
+bool Value::toBoolean() const
+{
+    switch (m_type) {
+        case NodeSetValue:
+            return !m_data->m_nodeSet.isEmpty();
+        case BooleanValue:
+            return m_bool;
+        case NumberValue:
+            return m_number != 0 && !isnan(m_number);
+        case StringValue:
+            return !m_data->m_string.isEmpty();
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+double Value::toNumber() const
+{
+    switch (m_type) {
+        case NodeSetValue:
+            return Value(toString()).toNumber();
+        case NumberValue:
+            return m_number;
+        case StringValue: {
+            bool canConvert;
+            double value = m_data->m_string.simplifyWhiteSpace().toDouble(&canConvert);
+            if (canConvert)
+                return value;
+            return numeric_limits<double>::quiet_NaN();
+        }
+        case BooleanValue:
+            return m_bool;
+    }
+    ASSERT_NOT_REACHED();
+    return 0.0;
+}
+
+String Value::toString() const
+{
+    switch (m_type) {
+        case NodeSetValue:
+            if (m_data->m_nodeSet.isEmpty()) 
+                return "";
+            return stringValue(m_data->m_nodeSet.firstNode());
+        case StringValue:
+            return m_data->m_string;
+        case NumberValue:
+            if (isnan(m_number))
+                return "NaN";
+            if (m_number == 0)
+                return "0";
+            if (isinf(m_number))
+                return signbit(m_number) ? "-Infinity" : "Infinity";
+            return String::number(m_number);
+        case BooleanValue:
+            return m_bool ? "true" : "false";
+    }
+    ASSERT_NOT_REACHED();
+    return String();
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathValue.h b/WebCore/xml/XPathValue.h
new file mode 100644
index 0000000..a0cd24d
--- /dev/null
+++ b/WebCore/xml/XPathValue.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathValue_h
+#define XPathValue_h
+
+#if ENABLE(XPATH)
+
+#include "PlatformString.h"
+#include "XPathNodeSet.h"
+
+namespace WebCore {
+
+    namespace XPath {
+    
+        class ValueData : public RefCounted<ValueData> {
+        public:            
+            static PassRefPtr<ValueData> create() { return adoptRef(new ValueData); }
+            static PassRefPtr<ValueData> create(const NodeSet& nodeSet) { return adoptRef(new ValueData(nodeSet)); }
+            static PassRefPtr<ValueData> create(const String& string) { return adoptRef(new ValueData(string)); }
+
+            NodeSet m_nodeSet;
+            String m_string;
+            
+        private:
+            ValueData() { }
+            ValueData(const NodeSet& nodeSet) : m_nodeSet(nodeSet) { }
+            ValueData(const String& string) : m_string(string) { }            
+        };
+
+        // Copying Value objects makes their data partially shared, so care has to be taken when dealing with copies.
+        class Value {
+        public:
+            enum Type { NodeSetValue, BooleanValue, NumberValue, StringValue };
+            
+            Value(unsigned value) : m_type(NumberValue), m_bool(false), m_number(value) {}
+            Value(unsigned long value) : m_type(NumberValue), m_bool(false), m_number(value) {}
+            Value(double value) : m_type(NumberValue), m_bool(false), m_number(value) {}
+
+            Value(const char* value) : m_type(StringValue), m_bool(false), m_number(0), m_data(ValueData::create(value)) {}
+            Value(const String& value) : m_type(StringValue), m_bool(false), m_number(0), m_data(ValueData::create(value)) {}
+            Value(const NodeSet& value) : m_type(NodeSetValue), m_bool(false), m_number(0), m_data(ValueData::create(value)) {}
+            Value(Node* value) : m_type(NodeSetValue), m_bool(false), m_number(0), m_data(ValueData::create()) { m_data->m_nodeSet.append(value); }
+
+            // This is needed to safely implement constructing from bool - with normal function overloading, any pointer type would match.
+            template<typename T> Value(T);
+
+            static const struct AdoptTag {} adopt;
+            Value(NodeSet& value, const AdoptTag&) : m_type(NodeSetValue), m_bool(false), m_number(0),  m_data(ValueData::create()) { value.swap(m_data->m_nodeSet); }
+
+            Type type() const { return m_type; }
+
+            bool isNodeSet() const { return m_type == NodeSetValue; }
+            bool isBoolean() const { return m_type == BooleanValue; }
+            bool isNumber() const { return m_type == NumberValue; }
+            bool isString() const { return m_type == StringValue; }
+
+            const NodeSet& toNodeSet() const;
+            NodeSet& modifiableNodeSet();
+            bool toBoolean() const;
+            double toNumber() const;
+            String toString() const;
+
+        private:
+            Type m_type;
+            bool m_bool;
+            double m_number;
+            RefPtr<ValueData> m_data;
+        };
+
+        template<>
+        inline Value::Value(bool value)
+            : m_type(BooleanValue)
+            , m_bool(value)
+            , m_number(0)
+        {
+        }
+    }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Value_H
diff --git a/WebCore/xml/XPathVariableReference.cpp b/WebCore/xml/XPathVariableReference.cpp
new file mode 100644
index 0000000..efe9cf9
--- /dev/null
+++ b/WebCore/xml/XPathVariableReference.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "XPathVariableReference.h"
+
+#if ENABLE(XPATH)
+
+#include "Node.h"
+#include "XPathValue.h"
+
+namespace WebCore {
+namespace XPath {
+    
+VariableReference::VariableReference(const String& name)
+    : m_name(name)
+{
+}
+
+Value VariableReference::evaluate() const
+{
+    HashMap<String, String>& bindings = evaluationContext().variableBindings;
+    if (!bindings.contains(m_name))
+        // FIXME: Is this the right thing to do if an unknown variable is referenced?
+        return "";
+    return bindings.get(m_name);
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathVariableReference.h b/WebCore/xml/XPathVariableReference.h
new file mode 100644
index 0000000..811176d
--- /dev/null
+++ b/WebCore/xml/XPathVariableReference.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005 Frerich Raabe <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XPathVariableReference_h
+#define XPathVariableReference_h
+
+#if ENABLE(XPATH)
+
+#include "XPathExpressionNode.h"
+
+namespace WebCore {
+
+    namespace XPath {
+    
+        class VariableReference : public Expression {
+        public:
+            VariableReference(const String& name);
+        private:
+            virtual Value evaluate() const;
+            String m_name;
+        };
+
+    }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_VariableReference_H
diff --git a/WebCore/xml/XSLImportRule.cpp b/WebCore/xml/XSLImportRule.cpp
new file mode 100644
index 0000000..2efafa3
--- /dev/null
+++ b/WebCore/xml/XSLImportRule.cpp
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "XSLImportRule.h"
+
+#if ENABLE(XSLT)
+
+#include "CachedXSLStyleSheet.h"
+#include "DocLoader.h"
+#include "XSLStyleSheet.h"
+
+namespace WebCore {
+
+XSLImportRule::XSLImportRule(XSLStyleSheet* parent, const String& href)
+    : StyleBase(parent)
+    , m_strHref(href)
+    , m_cachedSheet(0)
+    , m_loading(false)
+{
+}
+
+XSLImportRule::~XSLImportRule()
+{
+    if (m_styleSheet)
+        m_styleSheet->setParent(0);
+    
+    if (m_cachedSheet)
+        m_cachedSheet->removeClient(this);
+}
+
+XSLStyleSheet* XSLImportRule::parentStyleSheet() const
+{
+    return (parent() && parent()->isXSLStyleSheet()) ? static_cast<XSLStyleSheet*>(parent()) : 0;
+}
+
+void XSLImportRule::setXSLStyleSheet(const String& url, const String& sheet)
+{
+    if (m_styleSheet)
+        m_styleSheet->setParent(0);
+    
+    m_styleSheet = XSLStyleSheet::create(this, url);
+    
+    XSLStyleSheet* parent = parentStyleSheet();
+    if (parent)
+        m_styleSheet->setOwnerDocument(parent->ownerDocument());
+
+    m_styleSheet->parseString(sheet);
+    m_loading = false;
+    
+    if (parent)
+        parent->checkLoaded();
+}
+
+bool XSLImportRule::isLoading()
+{
+    return (m_loading || (m_styleSheet && m_styleSheet->isLoading()));
+}
+
+void XSLImportRule::loadSheet()
+{
+    DocLoader* docLoader = 0;
+    StyleBase* root = this;
+    StyleBase* parent;
+    while ((parent = root->parent()))
+        root = parent;
+    if (root->isXSLStyleSheet())
+        docLoader = static_cast<XSLStyleSheet*>(root)->docLoader();
+    
+    String absHref = m_strHref;
+    XSLStyleSheet* parentSheet = parentStyleSheet();
+    if (!parentSheet->href().isNull())
+        // use parent styleheet's URL as the base URL
+        absHref = KURL(KURL(parentSheet->href()), m_strHref).string();
+    
+    // Check for a cycle in our import chain.  If we encounter a stylesheet
+    // in our parent chain with the same URL, then just bail.
+    for (parent = this->parent(); parent; parent = parent->parent()) {
+        if (parent->isXSLStyleSheet() && absHref == static_cast<XSLStyleSheet*>(parent)->href())
+            return;
+    }
+    
+    m_cachedSheet = docLoader->requestXSLStyleSheet(absHref);
+    
+    if (m_cachedSheet) {
+        m_cachedSheet->addClient(this);
+        
+        // If the imported sheet is in the cache, then setXSLStyleSheet gets called,
+        // and the sheet even gets parsed (via parseString).  In this case we have
+        // loaded (even if our subresources haven't), so if we have a stylesheet after
+        // checking the cache, then we've clearly loaded.
+        if (!m_styleSheet)
+            m_loading = true;
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLImportRule.h b/WebCore/xml/XSLImportRule.h
new file mode 100644
index 0000000..fc7a7f8
--- /dev/null
+++ b/WebCore/xml/XSLImportRule.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef XSLImportRule_h
+#define XSLImportRule_h
+
+#if ENABLE(XSLT)
+
+#include "CachedResourceClient.h"
+#include "CachedResourceHandle.h"
+#include "StyleBase.h"
+#include "XSLStyleSheet.h"
+
+namespace WebCore {
+
+class CachedXSLStyleSheet;
+
+class XSLImportRule : public StyleBase, private CachedResourceClient {
+public:
+    static PassRefPtr<XSLImportRule> create(XSLStyleSheet* parentSheet, const String& href)
+    {
+        return adoptRef(new XSLImportRule(parentSheet, href));
+    }
+
+    virtual ~XSLImportRule();
+    
+    const String& href() const { return m_strHref; }
+    XSLStyleSheet* styleSheet() const { return m_styleSheet.get(); }
+
+    XSLStyleSheet* parentStyleSheet() const;
+
+    bool isLoading();
+    void loadSheet();
+    
+private:
+    XSLImportRule(XSLStyleSheet* parentSheet, const String& href);
+
+    virtual bool isImportRule() { return true; }
+
+    // from CachedResourceClient
+    virtual void setXSLStyleSheet(const String& url, const String& sheet);
+    
+    String m_strHref;
+    RefPtr<XSLStyleSheet> m_styleSheet;
+    CachedResourceHandle<CachedXSLStyleSheet> m_cachedSheet;
+    bool m_loading;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
+
+#endif // XSLImportRule_h
diff --git a/WebCore/xml/XSLStyleSheet.cpp b/WebCore/xml/XSLStyleSheet.cpp
new file mode 100644
index 0000000..9443652
--- /dev/null
+++ b/WebCore/xml/XSLStyleSheet.cpp
@@ -0,0 +1,288 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "XSLStyleSheet.h"
+
+#if ENABLE(XSLT)
+
+#include "CString.h"
+#include "Console.h"
+#include "DOMWindow.h"
+#include "DocLoader.h"
+#include "Document.h"
+#include "Frame.h"
+#include "loader.h"
+#include "Node.h"
+#include "XMLTokenizer.h"
+#include "XSLImportRule.h"
+#include "XSLTProcessor.h"
+
+#include <libxml/uri.h>
+#include <libxslt/xsltutils.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+#endif
+
+#if PLATFORM(MAC)
+SOFT_LINK_LIBRARY(libxslt)
+SOFT_LINK(libxslt, xsltIsBlank, int, (xmlChar *str), (str))
+SOFT_LINK(libxslt, xsltGetNsProp, xmlChar *, (xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace), (node, name, nameSpace))
+SOFT_LINK(libxslt, xsltParseStylesheetDoc, xsltStylesheetPtr, (xmlDocPtr doc), (doc))
+SOFT_LINK(libxslt, xsltLoadStylesheetPI, xsltStylesheetPtr, (xmlDocPtr doc), (doc))
+#endif
+
+namespace WebCore {
+
+XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& href)
+    : StyleSheet(parentRule, href)
+    , m_ownerDocument(0)
+    , m_stylesheetDoc(0)
+    , m_embedded(false)
+    , m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them.
+    , m_stylesheetDocTaken(false)
+{
+}
+
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& href,  bool embedded)
+    : StyleSheet(parentNode, href)
+    , m_ownerDocument(parentNode->document())
+    , m_stylesheetDoc(0)
+    , m_embedded(embedded)
+    , m_processed(true) // The root sheet starts off processed.
+    , m_stylesheetDocTaken(false)
+{
+}
+
+XSLStyleSheet::~XSLStyleSheet()
+{
+    if (!m_stylesheetDocTaken)
+        xmlFreeDoc(m_stylesheetDoc);
+}
+
+bool XSLStyleSheet::isLoading()
+{
+    unsigned len = length();
+    for (unsigned i = 0; i < len; ++i) {
+        StyleBase* rule = item(i);
+        if (rule->isImportRule()) {
+            XSLImportRule* import = static_cast<XSLImportRule*>(rule);
+            if (import->isLoading())
+                return true;
+        }
+    }
+    return false;
+}
+
+void XSLStyleSheet::checkLoaded()
+{
+    if (isLoading()) 
+        return;
+    if (parent())
+        parent()->checkLoaded();
+    if (ownerNode())
+        ownerNode()->sheetLoaded();
+}
+
+xmlDocPtr XSLStyleSheet::document()
+{
+    if (m_embedded && ownerDocument())
+        return (xmlDocPtr)ownerDocument()->transformSource();
+    return m_stylesheetDoc;
+}
+
+void XSLStyleSheet::clearDocuments()
+{
+    m_stylesheetDoc = 0;
+    unsigned len = length();
+    for (unsigned i = 0; i < len; ++i) {
+        StyleBase* rule = item(i);
+        if (rule->isImportRule()) {
+            XSLImportRule* import = static_cast<XSLImportRule*>(rule);
+            if (import->styleSheet())
+                import->styleSheet()->clearDocuments();
+        }
+    }
+}
+
+DocLoader* XSLStyleSheet::docLoader()
+{
+    if (!m_ownerDocument)
+        return 0;
+    return m_ownerDocument->docLoader();
+}
+
+bool XSLStyleSheet::parseString(const String& string, bool strict)
+{
+    // Parse in a single chunk into an xmlDocPtr
+    const UChar BOM = 0xFEFF;
+    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
+    setLoaderForLibXMLCallbacks(docLoader());
+    if (!m_stylesheetDocTaken)
+        xmlFreeDoc(m_stylesheetDoc);
+    m_stylesheetDocTaken = false;
+
+    Console* console = 0;
+    if (Frame* frame = ownerDocument()->frame())
+        console = frame->domWindow()->console();
+    xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
+    xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
+
+    m_stylesheetDoc = xmlReadMemory(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar),
+        href().utf8().data(),
+        BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE", 
+        XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
+    loadChildSheets();
+
+    xmlSetStructuredErrorFunc(0, 0);
+    xmlSetGenericErrorFunc(0, 0);
+
+    setLoaderForLibXMLCallbacks(0);
+    return m_stylesheetDoc;
+}
+
+void XSLStyleSheet::loadChildSheets()
+{
+    if (!document())
+        return;
+    
+    xmlNodePtr stylesheetRoot = document()->children;
+    
+    // Top level children may include other things such as DTD nodes, we ignore those.
+    while (stylesheetRoot && stylesheetRoot->type != XML_ELEMENT_NODE)
+        stylesheetRoot = stylesheetRoot->next;
+    
+    if (m_embedded) {
+        // We have to locate (by ID) the appropriate embedded stylesheet element, so that we can walk the 
+        // import/include list.
+        xmlAttrPtr idNode = xmlGetID(document(), (const xmlChar*)(href().utf8().data()));
+        if (!idNode)
+            return;
+        stylesheetRoot = idNode->parent;
+    } else {
+        // FIXME: Need to handle an external URI with a # in it.  This is a pretty minor edge case, so we'll deal
+        // with it later.
+    }
+    
+    if (stylesheetRoot) {
+        // Walk the children of the root element and look for import/include elements.
+        // Imports must occur first.
+        xmlNodePtr curr = stylesheetRoot->children;
+        while (curr) {
+            if (curr->type != XML_ELEMENT_NODE) {
+                curr = curr->next;
+                continue;
+            }
+            if (IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "import")) {
+                xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);                
+                loadChildSheet(String::fromUTF8((const char*)uriRef));
+                xmlFree(uriRef);
+            } else
+                break;
+            curr = curr->next;
+        }
+
+        // Now handle includes.
+        while (curr) {
+            if (curr->type == XML_ELEMENT_NODE && IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "include")) {
+                xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);
+                loadChildSheet(String::fromUTF8((const char*)uriRef));
+                xmlFree(uriRef);
+            }
+            curr = curr->next;
+        }
+    }
+}
+
+void XSLStyleSheet::loadChildSheet(const String& href)
+{
+    RefPtr<XSLImportRule> childRule = XSLImportRule::create(this, href);
+    append(childRule);
+    childRule->loadSheet();
+}
+
+xsltStylesheetPtr XSLStyleSheet::compileStyleSheet()
+{
+    // FIXME: Hook up error reporting for the stylesheet compilation process.
+    if (m_embedded)
+        return xsltLoadStylesheetPI(document());
+    
+    // xsltParseStylesheetDoc makes the document part of the stylesheet
+    // so we have to release our pointer to it.
+    ASSERT(!m_stylesheetDocTaken);
+    xsltStylesheetPtr result = xsltParseStylesheetDoc(m_stylesheetDoc);
+    if (result)
+        m_stylesheetDocTaken = true;
+    return result;
+}
+
+xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri)
+{
+    bool matchedParent = (parentDoc == document());
+    unsigned len = length();
+    for (unsigned i = 0; i < len; ++i) {
+        StyleBase* rule = item(i);
+        if (rule->isImportRule()) {
+            XSLImportRule* import = static_cast<XSLImportRule*>(rule);
+            XSLStyleSheet* child = import->styleSheet();
+            if (!child)
+                continue;
+            if (matchedParent) {
+                if (child->processed())
+                    continue; // libxslt has been given this sheet already.
+                
+                // Check the URI of the child stylesheet against the doc URI.
+                // In order to ensure that libxml canonicalized both URLs, we get the original href
+                // string from the import rule and canonicalize it using libxml before comparing it
+                // with the URI argument.
+                CString importHref = import->href().utf8();
+                xmlChar* base = xmlNodeGetBase(parentDoc, (xmlNodePtr)parentDoc);
+                xmlChar* childURI = xmlBuildURI((const xmlChar*)importHref.data(), base);
+                bool equalURIs = xmlStrEqual(uri, childURI);
+                xmlFree(base);
+                xmlFree(childURI);
+                if (equalURIs) {
+                    child->markAsProcessed();
+                    return child->document();
+                }
+            } else {
+                xmlDocPtr result = import->styleSheet()->locateStylesheetSubResource(parentDoc, uri);
+                if (result)
+                    return result;
+            }
+        }
+    }
+    
+    return 0;
+}
+
+void XSLStyleSheet::markAsProcessed()
+{
+    ASSERT(!m_processed);
+    ASSERT(!m_stylesheetDocTaken);
+    m_processed = true;
+    m_stylesheetDocTaken = true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLStyleSheet.h b/WebCore/xml/XSLStyleSheet.h
new file mode 100644
index 0000000..8946529
--- /dev/null
+++ b/WebCore/xml/XSLStyleSheet.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef XSLStyleSheet_h
+#define XSLStyleSheet_h
+
+#if ENABLE(XSLT)
+
+#include "StyleSheet.h"
+#include <libxml/parser.h>
+#include <libxslt/transform.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class DocLoader;
+class Document;
+class XSLImportRule;
+    
+class XSLStyleSheet : public StyleSheet {
+public:
+    static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& href)
+    {
+        return adoptRef(new XSLStyleSheet(parentImport, href));
+    }
+    static PassRefPtr<XSLStyleSheet> create(Node* parentNode, const String& href)
+    {
+        return adoptRef(new XSLStyleSheet(parentNode, href, false));
+    }
+    static PassRefPtr<XSLStyleSheet> createEmbedded(Node* parentNode, const String& href)
+    {
+        return adoptRef(new XSLStyleSheet(parentNode, href, true));
+    }
+
+    virtual ~XSLStyleSheet();
+    
+    virtual bool isXSLStyleSheet() const { return true; }
+
+    virtual String type() const { return "text/xml"; }
+
+    virtual bool parseString(const String &string, bool strict = true);
+    
+    virtual bool isLoading();
+    virtual void checkLoaded();
+
+    void loadChildSheets();
+    void loadChildSheet(const String& href);
+
+    xsltStylesheetPtr compileStyleSheet();
+
+    DocLoader* docLoader();
+
+    Document* ownerDocument() { return m_ownerDocument; }
+    void setOwnerDocument(Document* doc) { m_ownerDocument = doc; }
+
+    xmlDocPtr document();
+
+    void clearDocuments();
+
+    xmlDocPtr locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri);
+    
+    void markAsProcessed();
+    bool processed() const { return m_processed; }
+
+private:
+    XSLStyleSheet(Node* parentNode, const String& href, bool embedded);
+    XSLStyleSheet(XSLImportRule* parentImport, const String& href);
+
+    Document* m_ownerDocument;
+    xmlDocPtr m_stylesheetDoc;
+    bool m_embedded;
+    bool m_processed;
+    bool m_stylesheetDocTaken;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
+
+#endif // XSLStyleSheet_h
diff --git a/WebCore/xml/XSLTExtensions.cpp b/WebCore/xml/XSLTExtensions.cpp
new file mode 100644
index 0000000..d89f08b
--- /dev/null
+++ b/WebCore/xml/XSLTExtensions.cpp
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2001-2002 Thomas Broyer, Charlie Bozeman and Daniel Veillard.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is fur-
+ * nished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+ * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+ * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ * Except as contained in this notice, the name of the authors shall not
+ * be used in advertising or otherwise to promote the sale, use or other deal-
+ * ings in this Software without prior written authorization from him.
+ */
+
+#include "config.h"
+
+#if ENABLE(XSLT)
+
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltutils.h>
+#include <libxslt/extensions.h>
+#include <libxslt/extra.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+#endif
+
+#if PLATFORM(MAC)
+SOFT_LINK_LIBRARY(libxslt)
+SOFT_LINK(libxslt, xsltRegisterExtFunction, int, (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI, xmlXPathFunction function), (ctxt, name, URI, function))
+SOFT_LINK(libxslt, xsltFunctionNodeSet, void, (xmlXPathParserContextPtr ctxt, int nargs), (ctxt, nargs))
+#endif
+
+namespace WebCore {
+
+// FIXME: This code is taken from libexslt 1.1.11; should sync with newer versions.
+static void exsltNodeSetFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+    xmlChar *strval;
+    xmlNodePtr retNode;
+    xmlXPathObjectPtr ret;
+
+    if (nargs != 1) {
+        xmlXPathSetArityError(ctxt);
+        return;
+    }
+
+    if (xmlXPathStackIsNodeSet(ctxt)) {
+        xsltFunctionNodeSet(ctxt, nargs);
+        return;
+    }
+
+    strval = xmlXPathPopString(ctxt);
+    retNode = xmlNewDocText(NULL, strval);
+    ret = xmlXPathNewValueTree(retNode);
+    
+    // FIXME: It might be helpful to push any errors from xmlXPathNewValueTree
+    // up to the Javascript Console.
+    if (ret != NULL) 
+        ret->type = XPATH_NODESET;
+
+    if (strval != NULL)
+        xmlFree(strval);
+
+    valuePush(ctxt, ret);
+}
+
+void registerXSLTExtensions(xsltTransformContextPtr ctxt)
+{
+    xsltRegisterExtFunction(ctxt, (const xmlChar*)"node-set", (const xmlChar*)"http://exslt.org/common", exsltNodeSetFunction);
+}
+
+}
+
+#endif
diff --git a/WebCore/xml/XSLTExtensions.h b/WebCore/xml/XSLTExtensions.h
new file mode 100644
index 0000000..4e4224f
--- /dev/null
+++ b/WebCore/xml/XSLTExtensions.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 XSLTExtensions_h
+#define XSLTExtensions_h
+
+#if ENABLE(XSLT)
+
+#include <libxslt/xsltInternals.h>
+
+namespace WebCore {
+
+void registerXSLTExtensions(xsltTransformContextPtr ctxt);
+
+}
+
+#endif
+#endif
diff --git a/WebCore/xml/XSLTProcessor.cpp b/WebCore/xml/XSLTProcessor.cpp
new file mode 100644
index 0000000..ab554c4
--- /dev/null
+++ b/WebCore/xml/XSLTProcessor.cpp
@@ -0,0 +1,461 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple, Inc. All rights reserved.
+ * Copyright (C) 2005, 2006 Alexey Proskuryakov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(XSLT)
+
+#include "XSLTProcessor.h"
+
+#include "CString.h"
+#include "Console.h"
+#include "DOMImplementation.h"
+#include "DOMWindow.h"
+#include "DocLoader.h"
+#include "DocumentFragment.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameView.h"
+#include "HTMLDocument.h"
+#include "HTMLTokenizer.h"
+#include "Page.h"
+#include "ResourceError.h"
+#include "ResourceHandle.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "Text.h"
+#include "TextResourceDecoder.h"
+#include "XMLTokenizer.h"
+#include "XSLTExtensions.h"
+#include "XSLTUnicodeSort.h"
+#include "loader.h"
+#include "markup.h"
+#include <libxslt/imports.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltutils.h>
+#include <wtf/Assertions.h>
+#include <wtf/Platform.h>
+#include <wtf/Vector.h>
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+#endif
+
+#if PLATFORM(MAC)
+SOFT_LINK_LIBRARY(libxslt);
+SOFT_LINK(libxslt, xsltFreeStylesheet, void, (xsltStylesheetPtr sheet), (sheet))
+SOFT_LINK(libxslt, xsltFreeTransformContext, void, (xsltTransformContextPtr ctxt), (ctxt))
+SOFT_LINK(libxslt, xsltNewTransformContext, xsltTransformContextPtr, (xsltStylesheetPtr style, xmlDocPtr doc), (style, doc))
+SOFT_LINK(libxslt, xsltApplyStylesheetUser, xmlDocPtr, (xsltStylesheetPtr style, xmlDocPtr doc, const char** params, const char* output, FILE* profile, xsltTransformContextPtr userCtxt), (style, doc, params, output, profile, userCtxt))
+SOFT_LINK(libxslt, xsltQuoteUserParams, int, (xsltTransformContextPtr ctxt, const char** params), (ctxt, params))
+SOFT_LINK(libxslt, xsltSetCtxtSortFunc, void, (xsltTransformContextPtr ctxt, xsltSortFunc handler), (ctxt, handler))
+SOFT_LINK(libxslt, xsltSetLoaderFunc, void, (xsltDocLoaderFunc f), (f))
+SOFT_LINK(libxslt, xsltSaveResultTo, int, (xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style), (buf, result, style))
+SOFT_LINK(libxslt, xsltNextImport, xsltStylesheetPtr, (xsltStylesheetPtr style), (style))
+#endif
+
+namespace WebCore {
+
+void XSLTProcessor::genericErrorFunc(void* userData, const char* msg, ...)
+{
+    // It would be nice to do something with this error message.
+}
+    
+void XSLTProcessor::parseErrorFunc(void* userData, xmlError* error)
+{
+    Console* console = static_cast<Console*>(userData);
+    if (!console)
+        return;
+
+    MessageLevel level;
+    switch (error->level) {
+        case XML_ERR_NONE:
+            level = TipMessageLevel;
+            break;
+        case XML_ERR_WARNING:
+            level = WarningMessageLevel;
+            break;
+        case XML_ERR_ERROR:
+        case XML_ERR_FATAL:
+        default:
+            level = ErrorMessageLevel;
+            break;
+    }
+
+    console->addMessage(XMLMessageSource, level, error->message, error->line, error->file);
+}
+
+// FIXME: There seems to be no way to control the ctxt pointer for loading here, thus we have globals.
+static XSLTProcessor* globalProcessor = 0;
+static DocLoader* globalDocLoader = 0;
+static xmlDocPtr docLoaderFunc(const xmlChar* uri,
+                                    xmlDictPtr dict,
+                                    int options,
+                                    void* ctxt,
+                                    xsltLoadType type)
+{
+    if (!globalProcessor)
+        return 0;
+    
+    switch (type) {
+        case XSLT_LOAD_DOCUMENT: {
+            xsltTransformContextPtr context = (xsltTransformContextPtr)ctxt;
+            xmlChar* base = xmlNodeGetBase(context->document->doc, context->node);
+            KURL url(KURL(reinterpret_cast<const char*>(base)), reinterpret_cast<const char*>(uri));
+            xmlFree(base);
+            ResourceError error;
+            ResourceResponse response;
+
+            Vector<char> data;
+
+            bool requestAllowed = globalDocLoader->frame() && globalDocLoader->doc()->securityOrigin()->canRequest(url);
+            if (requestAllowed) {
+                globalDocLoader->frame()->loader()->loadResourceSynchronously(url, error, response, data);
+                requestAllowed = globalDocLoader->doc()->securityOrigin()->canRequest(response.url());
+            }
+            if (!requestAllowed) {
+                data.clear();
+                globalDocLoader->printAccessDeniedMessage(url);
+            }
+
+            Console* console = 0;
+            if (Frame* frame = globalProcessor->xslStylesheet()->ownerDocument()->frame())
+                console = frame->domWindow()->console();
+            xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
+            xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
+            
+            // We don't specify an encoding here. Neither Gecko nor WinIE respects
+            // the encoding specified in the HTTP headers.
+            xmlDocPtr doc = xmlReadMemory(data.data(), data.size(), (const char*)uri, 0, options);
+
+            xmlSetStructuredErrorFunc(0, 0);
+            xmlSetGenericErrorFunc(0, 0);
+
+            return doc;
+        }
+        case XSLT_LOAD_STYLESHEET:
+            return globalProcessor->xslStylesheet()->locateStylesheetSubResource(((xsltStylesheetPtr)ctxt)->doc, uri);
+        default:
+            break;
+    }
+    
+    return 0;
+}
+
+static inline void setXSLTLoadCallBack(xsltDocLoaderFunc func, XSLTProcessor* processor, DocLoader* loader)
+{
+    xsltSetLoaderFunc(func);
+    globalProcessor = processor;
+    globalDocLoader = loader;
+}
+
+static int writeToVector(void* context, const char* buffer, int len)
+{
+    Vector<UChar>& resultOutput = *static_cast<Vector<UChar>*>(context);
+    String decodedChunk = String::fromUTF8(buffer, len);
+    resultOutput.append(decodedChunk.characters(), decodedChunk.length());
+    return len;
+}
+
+static bool saveResultToString(xmlDocPtr resultDoc, xsltStylesheetPtr sheet, String& resultString)
+{
+    xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(0);
+    if (!outputBuf)
+        return false;
+
+    Vector<UChar> resultVector;
+    outputBuf->context = &resultVector;
+    outputBuf->writecallback = writeToVector;
+    
+    int retval = xsltSaveResultTo(outputBuf, resultDoc, sheet);
+    xmlOutputBufferClose(outputBuf);
+    if (retval < 0)
+        return false;
+
+    // Workaround for <http://bugzilla.gnome.org/show_bug.cgi?id=495668>: libxslt appends an extra line feed to the result.
+    if (resultVector.size() > 0 && resultVector[resultVector.size() - 1] == '\n')
+        resultVector.removeLast();
+
+    resultString = String::adopt(resultVector);
+
+    return true;
+}
+
+static inline void transformTextStringToXHTMLDocumentString(String& text)
+{
+    // Modify the output so that it is a well-formed XHTML document with a <pre> tag enclosing the text.
+    text.replace('&', "&amp;");
+    text.replace('<', "&lt;");
+    text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+        "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+        "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+        "<head><title/></head>\n"
+        "<body>\n"
+        "<pre>" + text + "</pre>\n"
+        "</body>\n"
+        "</html>\n";
+}
+
+static const char** xsltParamArrayFromParameterMap(XSLTProcessor::ParameterMap& parameters)
+{
+    if (parameters.isEmpty())
+        return 0;
+
+    const char** parameterArray = (const char**)fastMalloc(((parameters.size() * 2) + 1) * sizeof(char*));
+
+    XSLTProcessor::ParameterMap::iterator end = parameters.end();
+    unsigned index = 0;
+    for (XSLTProcessor::ParameterMap::iterator it = parameters.begin(); it != end; ++it) {
+        parameterArray[index++] = strdup(it->first.utf8().data());
+        parameterArray[index++] = strdup(it->second.utf8().data());
+    }
+    parameterArray[index] = 0;
+
+    return parameterArray;
+}
+
+static void freeXsltParamArray(const char** params)
+{
+    const char** temp = params;
+    if (!params)
+        return;
+    
+    while (*temp) {
+        free((void*)*(temp++)); // strdup returns malloc'd blocks, so we have to use free() here
+        free((void*)*(temp++));
+    }
+    fastFree(params);
+}
+
+
+PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString,
+    const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame)
+{
+    RefPtr<Document> ownerDocument = sourceNode->document();
+    bool sourceIsDocument = (sourceNode == ownerDocument.get());
+    String documentSource = sourceString;
+
+    RefPtr<Document> result;
+    if (sourceMIMEType == "text/plain") {
+        result = ownerDocument->implementation()->createDocument(frame);
+        transformTextStringToXHTMLDocumentString(documentSource);
+    } else
+        result = ownerDocument->implementation()->createDocument(sourceMIMEType, frame, false);
+    
+    // Before parsing, we need to save & detach the old document and get the new document
+    // in place. We have to do this only if we're rendering the result document.
+    if (frame) {
+        if (FrameView* view = frame->view())
+            view->clear();
+        result->setTransformSourceDocument(frame->document());
+        frame->setDocument(result);
+    }
+    
+    if (sourceIsDocument)
+        result->setURL(ownerDocument->url());
+    result->open();
+    
+    RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(sourceMIMEType);
+    decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader);
+    result->setDecoder(decoder.release());
+    
+    result->write(documentSource);
+    result->finishParsing();
+    result->close();
+
+    return result.release();
+}
+
+static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& sourceString, const String& sourceMIMEType, Node* sourceNode, Document* outputDoc)
+{
+    RefPtr<DocumentFragment> fragment = new DocumentFragment(outputDoc);
+    
+    if (sourceMIMEType == "text/html")
+        parseHTMLDocumentFragment(sourceString, fragment.get());
+    else if (sourceMIMEType == "text/plain")
+        fragment->addChild(new Text(outputDoc, sourceString));
+    else {
+        bool successfulParse = parseXMLDocumentFragment(sourceString, fragment.get(), outputDoc->documentElement());
+        if (!successfulParse)
+            return 0;
+    }
+    
+    // FIXME: Do we need to mess with URLs here?
+        
+    return fragment;
+}
+
+static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStylesheet, Node* stylesheetRootNode)
+{
+    if (!cachedStylesheet && stylesheetRootNode) {
+        cachedStylesheet = XSLStyleSheet::create(stylesheetRootNode->parent() ? stylesheetRootNode->parent() : stylesheetRootNode,
+            stylesheetRootNode->document()->url().string());
+        cachedStylesheet->parseString(createMarkup(stylesheetRootNode));
+    }
+    
+    if (!cachedStylesheet || !cachedStylesheet->document())
+        return 0;
+    
+    return cachedStylesheet->compileStyleSheet();
+}
+
+static inline xmlDocPtr xmlDocPtrFromNode(Node* sourceNode, bool& shouldDelete)
+{
+    RefPtr<Document> ownerDocument = sourceNode->document();
+    bool sourceIsDocument = (sourceNode == ownerDocument.get());
+    
+    xmlDocPtr sourceDoc = 0;
+    if (sourceIsDocument)
+        sourceDoc = (xmlDocPtr)ownerDocument->transformSource();
+    if (!sourceDoc) {
+        sourceDoc = (xmlDocPtr)xmlDocPtrForString(ownerDocument->docLoader(), createMarkup(sourceNode),
+            sourceIsDocument ? ownerDocument->url().string() : String());
+        shouldDelete = (sourceDoc != 0);
+    }
+    return sourceDoc;
+}
+
+static inline String resultMIMEType(xmlDocPtr resultDoc, xsltStylesheetPtr sheet)
+{
+    // There are three types of output we need to be able to deal with:
+    // HTML (create an HTML document), XML (create an XML document),
+    // and text (wrap in a <pre> and create an XML document).
+
+    const xmlChar* resultType = 0;
+    XSLT_GET_IMPORT_PTR(resultType, sheet, method);
+    if (resultType == 0 && resultDoc->type == XML_HTML_DOCUMENT_NODE)
+        resultType = (const xmlChar*)"html";
+    
+    if (xmlStrEqual(resultType, (const xmlChar*)"html"))
+        return "text/html";
+    else if (xmlStrEqual(resultType, (const xmlChar*)"text"))
+        return "text/plain";
+        
+    return "application/xml";
+}
+
+bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String& resultString, String& resultEncoding)
+{
+    RefPtr<Document> ownerDocument = sourceNode->document();
+    
+    setXSLTLoadCallBack(docLoaderFunc, this, ownerDocument->docLoader());
+    xsltStylesheetPtr sheet = xsltStylesheetPointer(m_stylesheet, m_stylesheetRootNode.get());
+    if (!sheet) {
+        setXSLTLoadCallBack(0, 0, 0);
+        return false;
+    }
+    m_stylesheet->clearDocuments();
+
+    xmlChar* origMethod = sheet->method;
+    if (!origMethod && mimeType == "text/html")
+        sheet->method = (xmlChar*)"html";
+
+    bool success = false;
+    bool shouldFreeSourceDoc = false;
+    if (xmlDocPtr sourceDoc = xmlDocPtrFromNode(sourceNode, shouldFreeSourceDoc)) {
+        // The XML declaration would prevent parsing the result as a fragment, and it's not needed even for documents, 
+        // as the result of this function is always immediately parsed.
+        sheet->omitXmlDeclaration = true;
+
+        xsltTransformContextPtr transformContext = xsltNewTransformContext(sheet, sourceDoc);
+        registerXSLTExtensions(transformContext);
+
+        // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor <xsl:sort> algorithm only compares by code point
+        xsltSetCtxtSortFunc(transformContext, xsltUnicodeSortFunction);
+
+        // This is a workaround for a bug in libxslt. 
+        // The bug has been fixed in version 1.1.13, so once we ship that this can be removed.
+        if (transformContext->globalVars == NULL)
+           transformContext->globalVars = xmlHashCreate(20);
+
+        const char** params = xsltParamArrayFromParameterMap(m_parameters);
+        xsltQuoteUserParams(transformContext, params);
+        xmlDocPtr resultDoc = xsltApplyStylesheetUser(sheet, sourceDoc, 0, 0, 0, transformContext);
+        
+        xsltFreeTransformContext(transformContext);        
+        freeXsltParamArray(params);
+        
+        if (shouldFreeSourceDoc)
+            xmlFreeDoc(sourceDoc);
+        
+        if (success = saveResultToString(resultDoc, sheet, resultString)) {
+            mimeType = resultMIMEType(resultDoc, sheet);
+            resultEncoding = (char*)resultDoc->encoding;
+        }
+        xmlFreeDoc(resultDoc);
+    }
+    
+    sheet->method = origMethod;
+    setXSLTLoadCallBack(0, 0, 0);
+    xsltFreeStylesheet(sheet);
+    m_stylesheet = 0;
+
+    return success;
+}
+
+PassRefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode)
+{
+    String resultMIMEType;
+    String resultString;
+    String resultEncoding;
+    if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding))
+        return 0;
+    return createDocumentFromSource(resultString, resultEncoding, resultMIMEType, sourceNode, 0);
+}
+
+PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode, Document* outputDoc)
+{
+    String resultMIMEType;
+    String resultString;
+    String resultEncoding;
+
+    // If the output document is HTML, default to HTML method.
+    if (outputDoc->isHTMLDocument())
+        resultMIMEType = "text/html";
+    
+    if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding))
+        return 0;
+    return createFragmentFromSource(resultString, resultMIMEType, sourceNode, outputDoc);
+}
+
+void XSLTProcessor::setParameter(const String& namespaceURI, const String& localName, const String& value)
+{
+    // FIXME: namespace support?
+    // should make a QualifiedName here but we'd have to expose the impl
+    m_parameters.set(localName, value);
+}
+
+String XSLTProcessor::getParameter(const String& namespaceURI, const String& localName) const
+{
+    // FIXME: namespace support?
+    // should make a QualifiedName here but we'd have to expose the impl
+    return m_parameters.get(localName);
+}
+
+void XSLTProcessor::removeParameter(const String& namespaceURI, const String& localName)
+{
+    // FIXME: namespace support?
+    m_parameters.remove(localName);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLTProcessor.h b/WebCore/xml/XSLTProcessor.h
new file mode 100644
index 0000000..9ee2aad
--- /dev/null
+++ b/WebCore/xml/XSLTProcessor.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2007, 2008 Apple, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef XSLTProcessor_h
+#define XSLTProcessor_h
+
+#if ENABLE(XSLT)
+
+#include "Node.h"
+#include "StringHash.h"
+#include "XSLStyleSheet.h"
+#include <libxml/parserInternals.h>
+#include <libxslt/documents.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class Frame;
+class Document;
+class DocumentFragment;
+
+class XSLTProcessor : public RefCounted<XSLTProcessor> {
+public:
+    static PassRefPtr<XSLTProcessor> create() { return adoptRef(new XSLTProcessor); }
+
+    void setXSLStyleSheet(PassRefPtr<XSLStyleSheet> styleSheet) { m_stylesheet = styleSheet; }
+    bool transformToString(Node* source, String& resultMIMEType, String& resultString, String& resultEncoding);
+    PassRefPtr<Document> createDocumentFromSource(const String& source, const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame);
+    
+    // DOM methods
+    void importStylesheet(PassRefPtr<Node> style) { m_stylesheetRootNode = style; }
+    PassRefPtr<DocumentFragment> transformToFragment(Node* source, Document* ouputDoc);
+    PassRefPtr<Document> transformToDocument(Node* source);
+    
+    void setParameter(const String& namespaceURI, const String& localName, const String& value);
+    String getParameter(const String& namespaceURI, const String& localName) const;
+    void removeParameter(const String& namespaceURI, const String& localName);
+    void clearParameters() { m_parameters.clear(); }
+
+    void reset() { m_stylesheet.clear(); m_stylesheetRootNode.clear();  m_parameters.clear(); }
+
+    static void parseErrorFunc(void* userData, xmlError*);
+    static void genericErrorFunc(void* userData, const char* msg, ...);
+    
+public:
+    // Only for libXSLT callbacks
+    XSLStyleSheet* xslStylesheet() const { return m_stylesheet.get(); }
+
+    typedef HashMap<String, String> ParameterMap;
+
+private:
+    XSLTProcessor() { }
+
+    RefPtr<XSLStyleSheet> m_stylesheet;
+    RefPtr<Node> m_stylesheetRootNode;
+    ParameterMap m_parameters;
+};
+
+}
+
+#endif
+#endif
diff --git a/WebCore/xml/XSLTProcessor.idl b/WebCore/xml/XSLTProcessor.idl
new file mode 100644
index 0000000..0a6ff93
--- /dev/null
+++ b/WebCore/xml/XSLTProcessor.idl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+module xml {
+
+    // Eventually we should implement XSLTException:
+    // http://lxr.mozilla.org/seamonkey/source/content/xsl/public/nsIXSLTException.idl
+    // http://bugs.webkit.org/show_bug.cgi?id=5446
+
+    interface [
+        Conditional=XSLT
+    ] XSLTProcessor {
+        
+        [Custom] void importStylesheet(in Node stylesheet);
+        [Custom] DocumentFragment transformToFragment(in Node source, in Document docVal);
+        [Custom] Document transformToDocument(in Node source);
+
+        [Custom] void setParameter(in DOMString namespaceURI, in DOMString localName, in DOMString value);
+        [Custom, ConvertNullStringTo=Undefined] DOMString getParameter(in DOMString namespaceURI, in DOMString localName);
+        [Custom] void removeParameter(in DOMString namespaceURI, in DOMString localName);
+        void clearParameters();
+
+        void reset();
+
+    };
+
+}
diff --git a/WebCore/xml/XSLTUnicodeSort.cpp b/WebCore/xml/XSLTUnicodeSort.cpp
new file mode 100644
index 0000000..ed66112
--- /dev/null
+++ b/WebCore/xml/XSLTUnicodeSort.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2007, 2008 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "XSLTUnicodeSort.h"
+
+#if ENABLE(XSLT)
+
+#include "PlatformString.h"
+
+#include <libxslt/templates.h>
+#include <libxslt/xsltutils.h>
+
+#include <wtf/unicode/Collator.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+#endif
+
+#if PLATFORM(MAC)
+SOFT_LINK_LIBRARY(libxslt)
+SOFT_LINK(libxslt, xsltComputeSortResult, xmlXPathObjectPtr*, (xsltTransformContextPtr ctxt, xmlNodePtr sort), (ctxt, sort))
+SOFT_LINK(libxslt, xsltEvalAttrValueTemplate, xmlChar*, (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *name, const xmlChar *ns), (ctxt, node, name, ns))
+
+static void init_xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+static void (*softLink_xsltTransformError)(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...) WTF_ATTRIBUTE_PRINTF(4, 5) = init_xsltTransformError;
+
+static void init_xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...)
+{
+    softLink_xsltTransformError = (void (*) (xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *, ...))dlsym(libxsltLibrary(), "xsltTransformError");
+    ASSERT(softLink_xsltTransformError);
+
+    va_list args;
+    va_start(args, msg);
+#if PLATFORM(WIN_OS)
+    char str[1024];
+    vsnprintf(str, sizeof(str) - 1, msg, args);
+#else
+    char* str;
+    vasprintf(&str, msg, args);
+#endif
+    va_end(args);
+
+    softLink_xsltTransformError(ctxt, style, node, "%s", str);
+
+#if !PLATFORM(WIN_OS)
+    free(str);
+#endif
+}
+
+inline void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+
+inline void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char* msg, ...)
+{
+    va_list args;
+    va_start(args, msg);
+#if PLATFORM(WIN_OS)
+    char str[1024];
+    vsnprintf(str, sizeof(str) - 1, msg, args);
+#else
+    char* str;
+    vasprintf(&str, msg, args);
+#endif
+    va_end(args);
+
+    softLink_xsltTransformError(ctxt, style, node, "%s", str);
+
+#if !PLATFORM(WIN_OS)
+    free(str);
+#endif
+}
+
+#endif
+
+namespace WebCore {
+
+// Based on default implementation from libxslt 1.1.22 and xsltICUSort.c example.
+void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemSortPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
+    xmlXPathObjectPtr *results = NULL, *res;
+    xmlNodeSetPtr list = NULL;
+    int descending, number, desc, numb;
+    int len = 0;
+    int i, j, incr;
+    int tst;
+    int depth;
+    xmlNodePtr node;
+    xmlXPathObjectPtr tmp;    
+    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
+
+    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
+        (nbsorts >= XSLT_MAX_SORT))
+        return;
+    if (sorts[0] == NULL)
+        return;
+    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
+    if (comp == NULL)
+        return;
+
+    list = ctxt->nodeList;
+    if ((list == NULL) || (list->nodeNr <= 1))
+        return; /* nothing to do */
+
+    for (j = 0; j < nbsorts; j++) {
+        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
+        tempstype[j] = 0;
+        if ((comp->stype == NULL) && (comp->has_stype != 0)) {
+            comp->stype =
+                xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                          (const xmlChar *) "data-type",
+                                          XSLT_NAMESPACE);
+            if (comp->stype != NULL) {
+                tempstype[j] = 1;
+                if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
+                    comp->number = 0;
+                else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
+                    comp->number = 1;
+                else {
+                    xsltTransformError(ctxt, NULL, sorts[j],
+                          "xsltDoSortFunction: no support for data-type = %s\n",
+                                     comp->stype);
+                    comp->number = 0; /* use default */
+                }
+            }
+        }
+        temporder[j] = 0;
+        if ((comp->order == NULL) && (comp->has_order != 0)) {
+            comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                                    (const xmlChar *) "order",
+                                                    XSLT_NAMESPACE);
+            if (comp->order != NULL) {
+                temporder[j] = 1;
+                if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
+                    comp->descending = 0;
+                else if (xmlStrEqual(comp->order,
+                                     (const xmlChar *) "descending"))
+                    comp->descending = 1;
+                else {
+                    xsltTransformError(ctxt, NULL, sorts[j],
+                             "xsltDoSortFunction: invalid value %s for order\n",
+                                     comp->order);
+                    comp->descending = 0; /* use default */
+                }
+            }
+        }
+    }
+
+    len = list->nodeNr;
+
+    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
+    for (i = 1;i < XSLT_MAX_SORT;i++)
+        resultsTab[i] = NULL;
+
+    results = resultsTab[0];
+
+    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
+    descending = comp->descending;
+    number = comp->number;
+    if (results == NULL)
+        return;
+
+    // We are passing a language identifier to a function that expects a locale identifier.
+    // The implementation of Collator should be lenient, and accept both "en-US" and "en_US", for example.
+    // This lets an author to really specify sorting rules, e.g. "de_DE@collation=phonebook", which isn't
+    // possible with language alone.
+    Collator collator(comp->has_lang ? (const char*)comp->lang : "en");
+    collator.setOrderLowerFirst(comp->lower_first);
+
+    /* Shell's sort of node-set */
+    for (incr = len / 2; incr > 0; incr /= 2) {
+        for (i = incr; i < len; i++) {
+            j = i - incr;
+            if (results[i] == NULL)
+                continue;
+            
+            while (j >= 0) {
+                if (results[j] == NULL)
+                    tst = 1;
+                else {
+                    if (number) {
+                        /* We make NaN smaller than number in accordance
+                           with XSLT spec */
+                        if (xmlXPathIsNaN(results[j]->floatval)) {
+                            if (xmlXPathIsNaN(results[j + incr]->floatval))
+                                tst = 0;
+                            else
+                                tst = -1;
+                        } else if (xmlXPathIsNaN(results[j + incr]->floatval))
+                            tst = 1;
+                        else if (results[j]->floatval ==
+                                results[j + incr]->floatval)
+                            tst = 0;
+                        else if (results[j]->floatval > 
+                                results[j + incr]->floatval)
+                            tst = 1;
+                        else tst = -1;
+                    } else {
+                        String str1 = String::fromUTF8((const char*)results[j]->stringval);
+                        String str2 = String::fromUTF8((const char*)results[j + incr]->stringval);
+                        tst = collator.collate(str1.characters(), str1.length(), str2.characters(), str2.length());
+                    }
+                    if (descending)
+                        tst = -tst;
+                }
+                if (tst == 0) {
+                    /*
+                     * Okay we need to use multi level sorts
+                     */
+                    depth = 1;
+                    while (depth < nbsorts) {
+                        if (sorts[depth] == NULL)
+                            break;
+                        comp = static_cast<xsltStylePreComp*>(sorts[depth]->psvi);
+                        if (comp == NULL)
+                            break;
+                        desc = comp->descending;
+                        numb = comp->number;
+
+                        /*
+                         * Compute the result of the next level for the
+                         * full set, this might be optimized ... or not
+                         */
+                        if (resultsTab[depth] == NULL) 
+                            resultsTab[depth] = xsltComputeSortResult(ctxt,
+                                                        sorts[depth]);
+                        res = resultsTab[depth];
+                        if (res == NULL) 
+                            break;
+                        if (res[j] == NULL) {
+                            if (res[j+incr] != NULL)
+                                tst = 1;
+                        } else {
+                            if (numb) {
+                                /* We make NaN smaller than number in
+                                   accordance with XSLT spec */
+                                if (xmlXPathIsNaN(res[j]->floatval)) {
+                                    if (xmlXPathIsNaN(res[j +
+                                                    incr]->floatval))
+                                        tst = 0;
+                                    else
+                                        tst = -1;
+                                } else if (xmlXPathIsNaN(res[j + incr]->
+                                                floatval))
+                                    tst = 1;
+                                else if (res[j]->floatval == res[j + incr]->
+                                                floatval)
+                                    tst = 0;
+                                else if (res[j]->floatval > 
+                                        res[j + incr]->floatval)
+                                    tst = 1;
+                                else tst = -1;
+                            } else {
+                                String str1 = String::fromUTF8((const char*)res[j]->stringval);
+                                String str2 = String::fromUTF8((const char*)res[j + incr]->stringval);
+                                tst = collator.collate(str1.characters(), str1.length(), str2.characters(), str2.length());
+                            }
+                            if (desc)
+                                tst = -tst;
+                        }
+
+                        /*
+                         * if we still can't differenciate at this level
+                         * try one level deeper.
+                         */
+                        if (tst != 0)
+                            break;
+                        depth++;
+                    }
+                }
+                if (tst == 0) {
+                    tst = results[j]->index > results[j + incr]->index;
+                }
+                if (tst > 0) {
+                    tmp = results[j];
+                    results[j] = results[j + incr];
+                    results[j + incr] = tmp;
+                    node = list->nodeTab[j];
+                    list->nodeTab[j] = list->nodeTab[j + incr];
+                    list->nodeTab[j + incr] = node;
+                    depth = 1;
+                    while (depth < nbsorts) {
+                        if (sorts[depth] == NULL)
+                            break;
+                        if (resultsTab[depth] == NULL)
+                            break;
+                        res = resultsTab[depth];
+                        tmp = res[j];
+                        res[j] = res[j + incr];
+                        res[j + incr] = tmp;
+                        depth++;
+                    }
+                    j -= incr;
+                } else
+                    break;
+            }
+        }
+    }
+
+    for (j = 0; j < nbsorts; j++) {
+        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
+        if (tempstype[j] == 1) {
+            /* The data-type needs to be recomputed each time */
+            xmlFree((void *)(comp->stype));
+            comp->stype = NULL;
+        }
+        if (temporder[j] == 1) {
+            /* The order needs to be recomputed each time */
+            xmlFree((void *)(comp->order));
+            comp->order = NULL;
+        }
+        if (resultsTab[j] != NULL) {
+            for (i = 0;i < len;i++)
+                xmlXPathFreeObject(resultsTab[j][i]);
+            xmlFree(resultsTab[j]);
+        }
+    }
+}
+
+}
+
+#endif
diff --git a/WebCore/xml/XSLTUnicodeSort.h b/WebCore/xml/XSLTUnicodeSort.h
new file mode 100644
index 0000000..c8d395b
--- /dev/null
+++ b/WebCore/xml/XSLTUnicodeSort.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 XSLTUnicodeSort_h
+#define XSLTUnicodeSort_h
+
+#if ENABLE(XSLT)
+
+#include <libxslt/xsltInternals.h>
+
+namespace WebCore {
+
+    void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr* sorts, int nbsorts);
+
+}
+
+#endif
+#endif
diff --git a/WebCore/xml/xmlattrs.in b/WebCore/xml/xmlattrs.in
new file mode 100644
index 0000000..6cc47be
--- /dev/null
+++ b/WebCore/xml/xmlattrs.in
@@ -0,0 +1,6 @@
+namespace="XML"
+namespaceURI="http://www.w3.org/XML/1998/namespace"
+
+base
+lang
+space