summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/xml
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/xml
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/xml')
-rw-r--r--Source/WebCore/xml/DOMParser.cpp43
-rw-r--r--Source/WebCore/xml/DOMParser.h42
-rw-r--r--Source/WebCore/xml/DOMParser.idl24
-rw-r--r--Source/WebCore/xml/NativeXPathNSResolver.cpp58
-rw-r--r--Source/WebCore/xml/NativeXPathNSResolver.h53
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.cpp1147
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.h237
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.idl123
-rw-r--r--Source/WebCore/xml/XMLHttpRequestException.h60
-rw-r--r--Source/WebCore/xml/XMLHttpRequestException.idl50
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEvent.h61
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEvent.idl36
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp154
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h81
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.cpp62
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.h82
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.idl55
-rw-r--r--Source/WebCore/xml/XMLSerializer.cpp47
-rw-r--r--Source/WebCore/xml/XMLSerializer.h44
-rw-r--r--Source/WebCore/xml/XMLSerializer.idl28
-rw-r--r--Source/WebCore/xml/XPathEvaluator.cpp77
-rw-r--r--Source/WebCore/xml/XPathEvaluator.h62
-rw-r--r--Source/WebCore/xml/XPathEvaluator.idl35
-rw-r--r--Source/WebCore/xml/XPathException.h64
-rw-r--r--Source/WebCore/xml/XPathException.idl50
-rw-r--r--Source/WebCore/xml/XPathExpression.cpp96
-rw-r--r--Source/WebCore/xml/XPathExpression.h66
-rw-r--r--Source/WebCore/xml/XPathExpression.idl33
-rw-r--r--Source/WebCore/xml/XPathExpressionNode.cpp59
-rw-r--r--Source/WebCore/xml/XPathExpressionNode.h103
-rw-r--r--Source/WebCore/xml/XPathFunctions.cpp737
-rw-r--r--Source/WebCore/xml/XPathFunctions.h60
-rw-r--r--Source/WebCore/xml/XPathGrammar.y558
-rw-r--r--Source/WebCore/xml/XPathNSResolver.cpp40
-rw-r--r--Source/WebCore/xml/XPathNSResolver.h50
-rw-r--r--Source/WebCore/xml/XPathNSResolver.idl27
-rw-r--r--Source/WebCore/xml/XPathNamespace.cpp81
-rw-r--r--Source/WebCore/xml/XPathNamespace.h63
-rw-r--r--Source/WebCore/xml/XPathNodeSet.cpp206
-rw-r--r--Source/WebCore/xml/XPathNodeSet.h84
-rw-r--r--Source/WebCore/xml/XPathParser.cpp638
-rw-r--r--Source/WebCore/xml/XPathParser.h132
-rw-r--r--Source/WebCore/xml/XPathPath.cpp209
-rw-r--r--Source/WebCore/xml/XPathPath.h94
-rw-r--r--Source/WebCore/xml/XPathPredicate.cpp282
-rw-r--r--Source/WebCore/xml/XPathPredicate.h127
-rw-r--r--Source/WebCore/xml/XPathResult.cpp219
-rw-r--r--Source/WebCore/xml/XPathResult.h90
-rw-r--r--Source/WebCore/xml/XPathResult.idl57
-rw-r--r--Source/WebCore/xml/XPathStep.cpp398
-rw-r--r--Source/WebCore/xml/XPathStep.h107
-rw-r--r--Source/WebCore/xml/XPathUtil.cpp100
-rw-r--r--Source/WebCore/xml/XPathUtil.h56
-rw-r--r--Source/WebCore/xml/XPathValue.cpp145
-rw-r--r--Source/WebCore/xml/XPathValue.h106
-rw-r--r--Source/WebCore/xml/XPathVariableReference.cpp55
-rw-r--r--Source/WebCore/xml/XPathVariableReference.h52
-rw-r--r--Source/WebCore/xml/XSLImportRule.cpp117
-rw-r--r--Source/WebCore/xml/XSLImportRule.h88
-rw-r--r--Source/WebCore/xml/XSLStyleSheet.h122
-rw-r--r--Source/WebCore/xml/XSLStyleSheetLibxslt.cpp314
-rw-r--r--Source/WebCore/xml/XSLStyleSheetQt.cpp102
-rw-r--r--Source/WebCore/xml/XSLTExtensions.cpp89
-rw-r--r--Source/WebCore/xml/XSLTExtensions.h40
-rw-r--r--Source/WebCore/xml/XSLTProcessor.cpp183
-rw-r--r--Source/WebCore/xml/XSLTProcessor.h86
-rw-r--r--Source/WebCore/xml/XSLTProcessor.idl55
-rw-r--r--Source/WebCore/xml/XSLTProcessorLibxslt.cpp354
-rw-r--r--Source/WebCore/xml/XSLTProcessorQt.cpp182
-rw-r--r--Source/WebCore/xml/XSLTUnicodeSort.cpp322
-rw-r--r--Source/WebCore/xml/XSLTUnicodeSort.h42
-rw-r--r--Source/WebCore/xml/xmlattrs.in6
-rw-r--r--Source/WebCore/xml/xmlnsattrs.in4
73 files changed, 10011 insertions, 0 deletions
diff --git a/Source/WebCore/xml/DOMParser.cpp b/Source/WebCore/xml/DOMParser.cpp
new file mode 100644
index 0000000..e6aa3b0
--- /dev/null
+++ b/Source/WebCore/xml/DOMParser.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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 "Document.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, KURL(), false);
+
+ doc->open();
+ doc->write(str);
+ doc->finishParsing();
+ doc->close();
+
+ return doc.release();
+}
+
+}
diff --git a/Source/WebCore/xml/DOMParser.h b/Source/WebCore/xml/DOMParser.h
new file mode 100644
index 0000000..41329ba
--- /dev/null
+++ b/Source/WebCore/xml/DOMParser.h
@@ -0,0 +1,42 @@
+/*
+ * 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/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Document;
+
+class DOMParser : public RefCounted<DOMParser> {
+public:
+ static PassRefPtr<DOMParser> create() { return adoptRef(new DOMParser); }
+
+ PassRefPtr<Document> parseFromString(const String&, const String& contentType);
+
+private:
+ DOMParser() { }
+};
+
+}
+
+#endif // XMLSerializer.h
diff --git a/Source/WebCore/xml/DOMParser.idl b/Source/WebCore/xml/DOMParser.idl
new file mode 100644
index 0000000..90a8b52
--- /dev/null
+++ b/Source/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 [CanBeConstructed] DOMParser {
+ Document parseFromString(in DOMString str, in DOMString contentType);
+ };
+}
diff --git a/Source/WebCore/xml/NativeXPathNSResolver.cpp b/Source/WebCore/xml/NativeXPathNSResolver.cpp
new file mode 100644
index 0000000..11faea6
--- /dev/null
+++ b/Source/WebCore/xml/NativeXPathNSResolver.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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/Source/WebCore/xml/NativeXPathNSResolver.h b/Source/WebCore/xml/NativeXPathNSResolver.h
new file mode 100644
index 0000000..212b929
--- /dev/null
+++ b/Source/WebCore/xml/NativeXPathNSResolver.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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/Source/WebCore/xml/XMLHttpRequest.cpp b/Source/WebCore/xml/XMLHttpRequest.cpp
new file mode 100644
index 0000000..fc7eb9e
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequest.cpp
@@ -0,0 +1,1147 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org>
+ * Copyright (C) 2008 David Levin <levin@chromium.org>
+ *
+ * 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 "ArrayBuffer.h"
+#include "Blob.h"
+#include "MemoryCache.h"
+#include "CrossOriginAccessControl.h"
+#include "DOMFormData.h"
+#include "DOMImplementation.h"
+#include "Document.h"
+#include "Event.h"
+#include "EventException.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "File.h"
+#include "HTTPParsers.h"
+#include "InspectorController.h"
+#include "InspectorInstrumentation.h"
+#include "ResourceError.h"
+#include "ResourceRequest.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "SharedBuffer.h"
+#include "TextResourceDecoder.h"
+#include "ThreadableLoader.h"
+#include "XMLHttpRequestException.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include "XMLHttpRequestUpload.h"
+#include "markup.h"
+#include <wtf/text/CString.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/UnusedParam.h>
+
+#if USE(JSC)
+#include "JSDOMBinding.h"
+#include "JSDOMWindow.h"
+#include <runtime/Protect.h>
+#endif
+
+namespace WebCore {
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter xmlHttpRequestCounter("XMLHttpRequest");
+#endif
+
+struct XMLHttpRequestStaticData : Noncopyable {
+ XMLHttpRequestStaticData();
+ String m_proxyHeaderPrefix;
+ String m_secHeaderPrefix;
+ HashSet<String, CaseFoldingHash> m_forbiddenRequestHeaders;
+};
+
+XMLHttpRequestStaticData::XMLHttpRequestStaticData()
+ : m_proxyHeaderPrefix("proxy-")
+ , m_secHeaderPrefix("sec-")
+{
+ m_forbiddenRequestHeaders.add("accept-charset");
+ m_forbiddenRequestHeaders.add("accept-encoding");
+ m_forbiddenRequestHeaders.add("access-control-request-headers");
+ m_forbiddenRequestHeaders.add("access-control-request-method");
+ m_forbiddenRequestHeaders.add("connection");
+ m_forbiddenRequestHeaders.add("content-length");
+ m_forbiddenRequestHeaders.add("content-transfer-encoding");
+ m_forbiddenRequestHeaders.add("cookie");
+ m_forbiddenRequestHeaders.add("cookie2");
+ m_forbiddenRequestHeaders.add("date");
+ m_forbiddenRequestHeaders.add("expect");
+ m_forbiddenRequestHeaders.add("host");
+ m_forbiddenRequestHeaders.add("keep-alive");
+ m_forbiddenRequestHeaders.add("origin");
+ m_forbiddenRequestHeaders.add("referer");
+ m_forbiddenRequestHeaders.add("te");
+ m_forbiddenRequestHeaders.add("trailer");
+ m_forbiddenRequestHeaders.add("transfer-encoding");
+ m_forbiddenRequestHeaders.add("upgrade");
+ m_forbiddenRequestHeaders.add("user-agent");
+ m_forbiddenRequestHeaders.add("via");
+}
+
+// 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 length > 0;
+}
+
+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');
+}
+
+static bool isSetCookieHeader(const AtomicString& name)
+{
+ return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
+}
+
+static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
+{
+ unsigned int pos = 0, len = 0;
+
+ findCharsetInMediaType(mediaType, pos, len);
+
+ if (!len) {
+ // When no charset found, do nothing.
+ return;
+ }
+
+ // Found at least one existing charset, replace all occurrences with new charset.
+ while (len) {
+ mediaType.replace(pos, len, charsetValue);
+ unsigned int start = pos + charsetValue.length();
+ findCharsetInMediaType(mediaType, pos, len, start);
+ }
+}
+
+static const XMLHttpRequestStaticData* staticData = 0;
+
+static const XMLHttpRequestStaticData* createXMLHttpRequestStaticData()
+{
+ staticData = new XMLHttpRequestStaticData;
+ return staticData;
+}
+
+static const XMLHttpRequestStaticData* initializeXMLHttpRequestStaticData()
+{
+ // Uses dummy to avoid warnings about an unused variable.
+ AtomicallyInitializedStatic(const XMLHttpRequestStaticData*, dummy = createXMLHttpRequestStaticData());
+ return dummy;
+}
+
+XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
+ : ActiveDOMObject(context, this)
+ , m_async(true)
+ , m_includeCredentials(false)
+ , m_state(UNSENT)
+ , m_createdDocument(false)
+ , m_error(false)
+ , m_uploadEventsAllowed(true)
+ , m_uploadComplete(false)
+ , m_sameOriginRequest(true)
+ , m_receivedLength(0)
+ , m_lastSendLineNumber(0)
+ , m_exceptionCode(0)
+ , m_progressEventThrottle(this)
+ , m_responseTypeCode(ResponseTypeDefault)
+{
+ initializeXMLHttpRequestStaticData();
+#ifndef NDEBUG
+ xmlHttpRequestCounter.increment();
+#endif
+}
+
+XMLHttpRequest::~XMLHttpRequest()
+{
+ if (m_upload)
+ m_upload->disconnectXMLHttpRequest();
+
+#ifndef NDEBUG
+ xmlHttpRequestCounter.decrement();
+#endif
+}
+
+Document* XMLHttpRequest::document() const
+{
+ ASSERT(scriptExecutionContext()->isDocument());
+ return static_cast<Document*>(scriptExecutionContext());
+}
+
+#if ENABLE(DASHBOARD_SUPPORT)
+bool XMLHttpRequest::usesDashboardBackwardCompatibilityMode() const
+{
+ if (scriptExecutionContext()->isWorkerContext())
+ return false;
+ Settings* settings = document()->settings();
+ return settings && settings->usesDashboardBackwardCompatibilityMode();
+}
+#endif
+
+XMLHttpRequest::State XMLHttpRequest::readyState() const
+{
+ return m_state;
+}
+
+String XMLHttpRequest::responseText(ExceptionCode& ec)
+{
+ if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText) {
+ ec = INVALID_STATE_ERR;
+ return "";
+ }
+ return m_responseBuilder.toStringPreserveCapacity();
+}
+
+Document* XMLHttpRequest::responseXML(ExceptionCode& ec)
+{
+ if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText && responseTypeCode() != ResponseTypeDocument) {
+ ec = INVALID_STATE_ERR;
+ return 0;
+ }
+
+ if (m_state != DONE)
+ return 0;
+
+ if (!m_createdDocument) {
+ if ((m_response.isHTTP() && !responseIsXML()) || scriptExecutionContext()->isWorkerContext()) {
+ // The W3C spec requires this.
+ m_responseXML = 0;
+ } else {
+ m_responseXML = Document::create(0, m_url);
+ m_responseXML->open();
+ // FIXME: Set Last-Modified.
+ m_responseXML->write(m_responseBuilder.toStringPreserveCapacity());
+ m_responseXML->finishParsing();
+ m_responseXML->close();
+
+ if (!m_responseXML->wellFormed())
+ m_responseXML = 0;
+ }
+ m_createdDocument = true;
+ }
+
+ return m_responseXML.get();
+}
+
+#if ENABLE(XHR_RESPONSE_BLOB)
+Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec) const
+{
+ if (responseTypeCode() != ResponseTypeBlob) {
+ ec = INVALID_STATE_ERR;
+ return 0;
+ }
+ return m_responseBlob.get();
+}
+#endif
+
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ArrayBuffer* XMLHttpRequest::responseArrayBuffer(ExceptionCode& ec)
+{
+ if (m_responseTypeCode != ResponseTypeArrayBuffer) {
+ ec = INVALID_STATE_ERR;
+ return 0;
+ }
+
+ if (m_state != DONE)
+ return 0;
+
+ if (!m_responseArrayBuffer.get() && m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size() > 0) {
+ m_responseArrayBuffer = ArrayBuffer::create(const_cast<char*>(m_binaryResponseBuilder->data()), static_cast<unsigned>(m_binaryResponseBuilder->size()));
+ m_binaryResponseBuilder.clear();
+ }
+
+ if (m_responseArrayBuffer.get())
+ return m_responseArrayBuffer.get();
+
+ return 0;
+}
+#endif
+
+void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode& ec)
+{
+ if (m_state != OPENED || m_loader) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ if (responseType == "")
+ m_responseTypeCode = ResponseTypeDefault;
+ else if (responseType == "text")
+ m_responseTypeCode = ResponseTypeText;
+ else if (responseType == "document")
+ m_responseTypeCode = ResponseTypeDocument;
+ else if (responseType == "blob") {
+#if ENABLE(XHR_RESPONSE_BLOB)
+ m_responseTypeCode = ResponseTypeBlob;
+#endif
+ } else if (responseType == "arraybuffer") {
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ m_responseTypeCode = ResponseTypeArrayBuffer;
+#endif
+ } else
+ ec = SYNTAX_ERR;
+}
+
+String XMLHttpRequest::responseType()
+{
+ switch (m_responseTypeCode) {
+ case ResponseTypeDefault:
+ return "";
+ case ResponseTypeText:
+ return "text";
+ case ResponseTypeDocument:
+ return "document";
+ case ResponseTypeBlob:
+ return "blob";
+ case ResponseTypeArrayBuffer:
+ return "arraybuffer";
+ }
+ return "";
+}
+
+XMLHttpRequestUpload* XMLHttpRequest::upload()
+{
+ if (!m_upload)
+ m_upload = XMLHttpRequestUpload::create(this);
+ return m_upload.get();
+}
+
+void XMLHttpRequest::changeState(State newState)
+{
+ if (m_state != newState) {
+ m_state = newState;
+ callReadyStateChangeListener();
+ }
+}
+
+void XMLHttpRequest::callReadyStateChangeListener()
+{
+ if (!scriptExecutionContext())
+ return;
+
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willChangeXHRReadyState(scriptExecutionContext(), this);
+
+ if (m_async || (m_state <= OPENED || m_state == DONE))
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().readystatechangeEvent), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
+
+ InspectorInstrumentation::didChangeXHRReadyState(cookie);
+
+ if (m_state == DONE && !m_error) {
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this);
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
+ InspectorInstrumentation::didLoadXHR(cookie);
+ }
+}
+
+void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
+{
+ if (m_state != OPENED || m_loader) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ m_includeCredentials = value;
+}
+
+#if ENABLE(XHR_RESPONSE_BLOB)
+void XMLHttpRequest::setAsBlob(bool value, ExceptionCode& ec)
+{
+ if (m_state != OPENED || m_loader) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ m_responseTypeCode = value ? ResponseTypeBlob : ResponseTypeDefault;
+}
+#endif
+
+void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionCode& ec)
+{
+ open(method, url, true, ec);
+}
+
+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_responseTypeCode = ResponseTypeDefault;
+ 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 (!scriptExecutionContext())
+ 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.protocolInHTTPFamily()) {
+ String contentType = getRequestHeader("Content-Type");
+ if (contentType.isEmpty()) {
+#if ENABLE(DASHBOARD_SUPPORT)
+ if (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.protocolInHTTPFamily()) {
+ String contentType = getRequestHeader("Content-Type");
+ if (contentType.isEmpty()) {
+#if ENABLE(DASHBOARD_SUPPORT)
+ if (usesDashboardBackwardCompatibilityMode())
+ setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
+ else
+#endif
+ setRequestHeaderInternal("Content-Type", "application/xml");
+ } else {
+ replaceCharsetInMediaType(contentType, "UTF-8");
+ m_requestHeaders.set("Content-Type", contentType);
+ }
+
+ m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));
+ if (m_upload)
+ m_requestEntityBody->setAlwaysStream(true);
+ }
+
+ createRequest(ec);
+}
+
+void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
+{
+ if (!initSend(ec))
+ return;
+
+ if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
+ // FIXME: Should we set a Content-Type if one is not set.
+ // FIXME: add support for uploading bundles.
+ m_requestEntityBody = FormData::create();
+ if (body->isFile())
+ m_requestEntityBody->appendFile(static_cast<File*>(body)->path());
+#if ENABLE(BLOB)
+ else
+ m_requestEntityBody->appendBlob(body->url());
+#endif
+ }
+
+ createRequest(ec);
+}
+
+void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec)
+{
+ if (!initSend(ec))
+ return;
+
+ if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
+ m_requestEntityBody = FormData::createMultiPart(*(static_cast<FormDataList*>(body)), body->encoding(), document());
+
+ // We need to ask the client to provide the generated file names if needed. When FormData fills the element
+ // for the file, it could set a flag to use the generated file name, i.e. a package file on Mac.
+ m_requestEntityBody->generateFiles(document());
+
+ String contentType = getRequestHeader("Content-Type");
+ if (contentType.isEmpty()) {
+ contentType = "multipart/form-data; boundary=";
+ contentType += m_requestEntityBody->boundary().data();
+ setRequestHeaderInternal("Content-Type", contentType);
+ }
+ }
+
+ createRequest(ec);
+}
+
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+void XMLHttpRequest::send(ArrayBuffer* body, ExceptionCode& ec)
+{
+ if (!initSend(ec))
+ return;
+
+ if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
+ m_requestEntityBody = FormData::create(body->data(), body->byteLength());
+ if (m_upload)
+ m_requestEntityBody->setAlwaysStream(true);
+ }
+
+ createRequest(ec);
+}
+#endif
+
+void XMLHttpRequest::createRequest(ExceptionCode& ec)
+{
+#if ENABLE(BLOB)
+ // Only GET request is supported for blob URL.
+ if (m_url.protocolIs("blob") && m_method != "GET") {
+ ec = XMLHttpRequestException::NETWORK_ERR;
+ return;
+ }
+#endif
+
+ // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
+ // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
+ // Also, only async requests support upload progress events.
+ bool uploadEvents = false;
+ if (m_async) {
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
+ if (m_requestEntityBody && m_upload) {
+ uploadEvents = m_upload->hasEventListeners();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
+ }
+ }
+
+ m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url);
+
+ // We also remember whether upload events should be allowed for this request in case the upload listeners are
+ // added after the request is started.
+ m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
+
+ ResourceRequest request(m_url);
+ request.setHTTPMethod(m_method);
+
+ if (m_requestEntityBody) {
+ ASSERT(m_method != "GET");
+ ASSERT(m_method != "HEAD");
+ request.setHTTPBody(m_requestEntityBody.release());
+ }
+
+ if (m_requestHeaders.size() > 0)
+ request.addHTTPHeaderFields(m_requestHeaders);
+
+ ThreadableLoaderOptions options;
+ options.sendLoadCallbacks = true;
+ options.sniffContent = false;
+ options.forcePreflight = uploadEvents;
+ options.allowCredentials = m_sameOriginRequest || m_includeCredentials;
+ options.crossOriginRequestPolicy = UseAccessControl;
+
+ m_exceptionCode = 0;
+ m_error = false;
+
+ if (m_async) {
+ if (m_upload)
+ request.setReportUploadProgress(true);
+
+ // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
+ // This is true while running onunload handlers.
+ // FIXME: Maybe 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?
+ m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
+ 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);
+ }
+ } else
+ ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options);
+
+ if (!m_exceptionCode && m_error)
+ m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
+ ec = m_exceptionCode;
+}
+
+void XMLHttpRequest::abort()
+{
+ // internalAbort() calls dropProtection(), which may release the last reference.
+ RefPtr<XMLHttpRequest> protect(this);
+
+ bool sendFlag = m_loader;
+
+ internalAbort();
+
+ m_responseBuilder.clear();
+ m_createdDocument = false;
+ m_responseXML = 0;
+#if ENABLE(XHR_RESPONSE_BLOB)
+ m_responseBlob = 0;
+#endif
+
+ // 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;
+ }
+
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
+ if (!m_uploadComplete) {
+ m_uploadComplete = true;
+ if (m_upload && m_uploadEventsAllowed)
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
+ }
+}
+
+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();
+ m_responseBuilder.clear();
+ m_createdDocument = false;
+ m_responseXML = 0;
+#if ENABLE(XHR_RESPONSE_BLOB)
+ m_responseBlob = 0;
+#endif
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ m_binaryResponseBuilder.clear();
+ m_responseArrayBuffer.clear();
+#endif
+}
+
+void XMLHttpRequest::clearRequest()
+{
+ m_requestHeaders.clear();
+ m_requestEntityBody = 0;
+}
+
+void XMLHttpRequest::genericError()
+{
+ clearResponse();
+ clearRequest();
+ m_error = true;
+
+ changeState(DONE);
+}
+
+void XMLHttpRequest::networkError()
+{
+ genericError();
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
+ if (!m_uploadComplete) {
+ m_uploadComplete = true;
+ if (m_upload && m_uploadEventsAllowed)
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
+ }
+ internalAbort();
+}
+
+void XMLHttpRequest::abortError()
+{
+ genericError();
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
+ if (!m_uploadComplete) {
+ m_uploadComplete = true;
+ if (m_upload && m_uploadEventsAllowed)
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
+ }
+}
+
+void XMLHttpRequest::dropProtection()
+{
+#if USE(JSC)
+ // 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.
+ JSC::JSGlobalData* globalData = scriptExecutionContext()->globalData();
+ if (hasCachedDOMObjectWrapper(globalData, this))
+ globalData->heap.reportExtraMemoryCost(m_responseBuilder.length() * 2);
+#endif
+
+ unsetPendingActivity(this);
+}
+
+void XMLHttpRequest::overrideMimeType(const String& override)
+{
+ m_mimeTypeOverride = override;
+}
+
+static void reportUnsafeUsage(ScriptExecutionContext* context, const String& message)
+{
+ if (!context)
+ return;
+ // FIXME: It's not good to report the bad usage without indicating what source line it came from.
+ // We should pass additional parameters so we can tell the console where the mistake occurred.
+ context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
+}
+
+void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& value, ExceptionCode& ec)
+{
+ if (m_state != OPENED || m_loader) {
+#if ENABLE(DASHBOARD_SUPPORT)
+ if (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 (!scriptExecutionContext()->securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
+ reportUnsafeUsage(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
+ return;
+ }
+
+ setRequestHeaderInternal(name, value);
+}
+
+void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value)
+{
+ pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value);
+ if (!result.second)
+ result.first->second += ", " + value;
+}
+
+bool XMLHttpRequest::isSafeRequestHeader(const String& name) const
+{
+ return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
+ && !name.startsWith(staticData->m_secHeaderPrefix, false);
+}
+
+String XMLHttpRequest::getRequestHeader(const AtomicString& name) const
+{
+ return m_requestHeaders.get(name);
+}
+
+String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
+{
+ if (m_state < HEADERS_RECEIVED) {
+ ec = INVALID_STATE_ERR;
+ return "";
+ }
+
+ Vector<UChar> stringBuilder;
+
+ HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
+ for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
+ // Hide Set-Cookie header fields from the XMLHttpRequest client for these reasons:
+ // 1) If the client did have access to the fields, then it could read HTTP-only
+ // cookies; those cookies are supposed to be hidden from scripts.
+ // 2) There's no known harm in hiding Set-Cookie header fields entirely; we don't
+ // know any widely used technique that requires access to them.
+ // 3) Firefox has implemented this policy.
+ if (isSetCookieHeader(it->first) && !scriptExecutionContext()->securityOrigin()->canLoadLocalResources())
+ continue;
+
+ if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->first))
+ continue;
+
+ stringBuilder.append(it->first.characters(), it->first.length());
+ stringBuilder.append(':');
+ stringBuilder.append(' ');
+ stringBuilder.append(it->second.characters(), it->second.length());
+ stringBuilder.append('\r');
+ stringBuilder.append('\n');
+ }
+
+ return String::adopt(stringBuilder);
+}
+
+String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode& ec) const
+{
+ if (m_state < HEADERS_RECEIVED) {
+ ec = INVALID_STATE_ERR;
+ return String();
+ }
+
+ // See comment in getAllResponseHeaders above.
+ if (isSetCookieHeader(name) && !scriptExecutionContext()->securityOrigin()->canLoadLocalResources()) {
+ reportUnsafeUsage(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
+ return String();
+ }
+
+ if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name)) {
+ reportUnsafeUsage(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
+ return String();
+ }
+ 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
+{
+ if (!m_response.httpStatusText().isNull())
+ return m_response.httpStatusText();
+
+ if (m_state == OPENED) {
+ // See comments in status() above.
+ ec = INVALID_STATE_ERR;
+ }
+
+ return String();
+}
+
+void XMLHttpRequest::didFail(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()) {
+ m_exceptionCode = XMLHttpRequestException::ABORT_ERR;
+ abortError();
+ return;
+ }
+
+ // Network failures are already reported to Web Inspector by ResourceLoader.
+ if (error.domain() == errorDomainWebKitInternal)
+ reportUnsafeUsage(scriptExecutionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());
+
+ m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
+ networkError();
+}
+
+void XMLHttpRequest::didFailRedirectCheck()
+{
+ networkError();
+}
+
+void XMLHttpRequest::didFinishLoading(unsigned long identifier)
+{
+ if (m_error)
+ return;
+
+ if (m_state < HEADERS_RECEIVED)
+ changeState(HEADERS_RECEIVED);
+
+ if (m_decoder)
+ m_responseBuilder.append(m_decoder->flush());
+
+ m_responseBuilder.shrinkToFit();
+
+#if ENABLE(XHR_RESPONSE_BLOB)
+ // FIXME: Set m_responseBlob to something here in the ResponseTypeBlob case.
+#endif
+
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspector = scriptExecutionContext()->inspectorController())
+ inspector->resourceRetrievedByXMLHttpRequest(identifier, m_responseBuilder.toStringPreserveCapacity(), m_url, m_lastSendURL, m_lastSendLineNumber);
+#endif
+
+ bool hadLoader = m_loader;
+ m_loader = 0;
+
+ changeState(DONE);
+ m_decoder = 0;
+
+ if (hadLoader)
+ dropProtection();
+}
+
+void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+ if (!m_upload)
+ return;
+
+ if (m_uploadEventsAllowed)
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, true, bytesSent, totalBytesToBeSent));
+
+ if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
+ m_uploadComplete = true;
+ if (m_uploadEventsAllowed)
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
+ }
+}
+
+void XMLHttpRequest::didReceiveResponse(const ResourceResponse& response)
+{
+ m_response = response;
+ m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
+ if (m_responseEncoding.isEmpty())
+ m_responseEncoding = response.textEncodingName();
+}
+
+void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse& failureResponse)
+{
+ m_response = failureResponse;
+}
+
+void XMLHttpRequest::didReceiveData(const char* data, int len)
+{
+ if (m_error)
+ return;
+
+ if (m_state < HEADERS_RECEIVED)
+ changeState(HEADERS_RECEIVED);
+
+ bool useDecoder = responseTypeCode() == ResponseTypeDefault || responseTypeCode() == ResponseTypeText || responseTypeCode() == ResponseTypeDocument;
+
+ if (useDecoder && !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");
+ // Don't stop on encoding errors, unlike it is done for other kinds of XML resources. This matches the behavior of previous WebKit versions, Firefox and Opera.
+ m_decoder->useLenientXMLDecoding();
+ } else if (responseMIMEType() == "text/html")
+ m_decoder = TextResourceDecoder::create("text/html", "UTF-8");
+ else
+ m_decoder = TextResourceDecoder::create("text/plain", "UTF-8");
+ }
+
+ if (!len)
+ return;
+
+ if (len == -1)
+ len = strlen(data);
+
+ if (useDecoder)
+ m_responseBuilder.append(m_decoder->decode(data, len));
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ else if (responseTypeCode() == ResponseTypeArrayBuffer) {
+ // Buffer binary data.
+ if (!m_binaryResponseBuilder)
+ m_binaryResponseBuilder = SharedBuffer::create();
+ m_binaryResponseBuilder->append(data, len);
+ }
+#endif
+
+ if (!m_error) {
+ long long expectedLength = m_response.expectedContentLength();
+ m_receivedLength += len;
+
+ if (m_async) {
+ bool lengthComputable = expectedLength && m_receivedLength <= expectedLength;
+ m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, expectedLength);
+ }
+
+ if (m_state != LOADING)
+ changeState(LOADING);
+ else
+ // Firefox calls readyStateChanged every time it receives data, 4449442
+ callReadyStateChangeListener();
+ }
+}
+
+bool XMLHttpRequest::canSuspend() const
+{
+ return !m_loader;
+}
+
+void XMLHttpRequest::suspend(ReasonForSuspension)
+{
+ m_progressEventThrottle.suspend();
+}
+
+void XMLHttpRequest::resume()
+{
+ m_progressEventThrottle.resume();
+}
+
+void XMLHttpRequest::stop()
+{
+ internalAbort();
+}
+
+void XMLHttpRequest::contextDestroyed()
+{
+ ASSERT(!m_loader);
+ ActiveDOMObject::contextDestroyed();
+}
+
+ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
+{
+ return ActiveDOMObject::scriptExecutionContext();
+}
+
+EventTargetData* XMLHttpRequest::eventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+EventTargetData* XMLHttpRequest::ensureEventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequest.h b/Source/WebCore/xml/XMLHttpRequest.h
new file mode 100644
index 0000000..bc6815d
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequest.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@nypop.com>
+ *
+ * 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 "EventListener.h"
+#include "EventNames.h"
+#include "EventTarget.h"
+#include "FormData.h"
+#include "ResourceResponse.h"
+#include "ThreadableLoaderClient.h"
+#include "XMLHttpRequestProgressEventThrottle.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/text/AtomicStringHash.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+class ArrayBuffer;
+class Blob;
+class Document;
+class DOMFormData;
+class ResourceRequest;
+class SharedBuffer;
+class TextResourceDecoder;
+class ThreadableLoader;
+
+class XMLHttpRequest : public RefCounted<XMLHttpRequest>, public EventTarget, private ThreadableLoaderClient, public ActiveDOMObject {
+public:
+ static PassRefPtr<XMLHttpRequest> create(ScriptExecutionContext* context) { return adoptRef(new XMLHttpRequest(context)); }
+ ~XMLHttpRequest();
+
+ // These exact numeric values are important because JS expects them.
+ enum State {
+ UNSENT = 0,
+ OPENED = 1,
+ HEADERS_RECEIVED = 2,
+ LOADING = 3,
+ DONE = 4
+ };
+
+ enum ResponseTypeCode {
+ ResponseTypeDefault,
+ ResponseTypeText,
+ ResponseTypeDocument,
+ ResponseTypeBlob,
+ ResponseTypeArrayBuffer
+ };
+
+ virtual XMLHttpRequest* toXMLHttpRequest() { return this; }
+
+ virtual void contextDestroyed();
+ virtual bool canSuspend() const;
+ virtual void suspend(ReasonForSuspension);
+ virtual void resume();
+ virtual void stop();
+
+ virtual ScriptExecutionContext* scriptExecutionContext() const;
+
+ const KURL& url() const { return m_url; }
+ String statusText(ExceptionCode&) const;
+ int status(ExceptionCode&) const;
+ State readyState() const;
+ bool withCredentials() const { return m_includeCredentials; }
+ void setWithCredentials(bool, ExceptionCode&);
+#if ENABLE(XHR_RESPONSE_BLOB)
+ bool asBlob() const { return responseTypeCode() == ResponseTypeBlob; }
+ void setAsBlob(bool, ExceptionCode&);
+#endif
+ void open(const String& method, const KURL&, ExceptionCode&);
+ 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(Blob*, ExceptionCode&);
+ void send(DOMFormData*, ExceptionCode&);
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ void send(ArrayBuffer*, ExceptionCode&);
+#endif
+ void abort();
+ void setRequestHeader(const AtomicString& name, const String& value, ExceptionCode&);
+ void overrideMimeType(const String& override);
+ String getAllResponseHeaders(ExceptionCode&) const;
+ String getResponseHeader(const AtomicString& name, ExceptionCode&) const;
+ String responseText(ExceptionCode&);
+ Document* responseXML(ExceptionCode&);
+ Document* optionalResponseXML() const { return m_responseXML.get(); }
+#if ENABLE(XHR_RESPONSE_BLOB)
+ Blob* responseBlob(ExceptionCode&) const;
+ Blob* optionalResponseBlob() const { return m_responseBlob.get(); }
+#endif
+
+ void setResponseType(const String&, ExceptionCode&);
+ String responseType();
+ ResponseTypeCode responseTypeCode() const { return m_responseTypeCode; }
+
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ // response attribute has custom getter.
+ ArrayBuffer* responseArrayBuffer(ExceptionCode&);
+ ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); }
+#endif
+
+ void setLastSendLineNumber(unsigned lineNumber) { m_lastSendLineNumber = lineNumber; }
+ void setLastSendURL(const String& url) { m_lastSendURL = url; }
+
+ XMLHttpRequestUpload* upload();
+ XMLHttpRequestUpload* optionalUpload() const { return m_upload.get(); }
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
+
+ using RefCounted<XMLHttpRequest>::ref;
+ using RefCounted<XMLHttpRequest>::deref;
+
+private:
+ XMLHttpRequest(ScriptExecutionContext*);
+
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
+
+ Document* document() const;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+ bool usesDashboardBackwardCompatibilityMode() const;
+#endif
+
+ virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+ virtual void didReceiveResponse(const ResourceResponse&);
+ virtual void didReceiveData(const char* data, int lengthReceived);
+ virtual void didFinishLoading(unsigned long identifier);
+ virtual void didFail(const ResourceError&);
+ virtual void didFailRedirectCheck();
+ virtual void didReceiveAuthenticationCancellation(const ResourceResponse&);
+
+ String responseMIMEType() const;
+ bool responseIsXML() const;
+
+ bool initSend(ExceptionCode&);
+
+ String getRequestHeader(const AtomicString& name) const;
+ void setRequestHeaderInternal(const AtomicString& name, const String& value);
+ bool isSafeRequestHeader(const String&) const;
+
+ void changeState(State newState);
+ void callReadyStateChangeListener();
+ void dropProtection();
+ void internalAbort();
+ void clearResponse();
+ void clearRequest();
+
+ void createRequest(ExceptionCode&);
+
+ void genericError();
+ void networkError();
+ void abortError();
+
+ 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;
+#if ENABLE(XHR_RESPONSE_BLOB)
+ RefPtr<Blob> m_responseBlob;
+#endif
+
+ RefPtr<ThreadableLoader> m_loader;
+ State m_state;
+
+ ResourceResponse m_response;
+ String m_responseEncoding;
+
+ RefPtr<TextResourceDecoder> m_decoder;
+
+ StringBuilder m_responseBuilder;
+ mutable bool m_createdDocument;
+ mutable RefPtr<Document> m_responseXML;
+
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
+ RefPtr<SharedBuffer> m_binaryResponseBuilder;
+ mutable RefPtr<ArrayBuffer> m_responseArrayBuffer;
+#endif
+
+ bool m_error;
+
+ bool m_uploadEventsAllowed;
+ bool m_uploadComplete;
+
+ bool m_sameOriginRequest;
+
+ // Used for onprogress tracking
+ long long m_receivedLength;
+
+ unsigned m_lastSendLineNumber;
+ String m_lastSendURL;
+ ExceptionCode m_exceptionCode;
+
+ EventTargetData m_eventTargetData;
+
+ XMLHttpRequestProgressEventThrottle m_progressEventThrottle;
+
+ // An enum corresponding to the allowed string values for the responseType attribute.
+ ResponseTypeCode m_responseTypeCode;
+};
+
+} // namespace WebCore
+
+#endif // XMLHttpRequest_h
diff --git a/Source/WebCore/xml/XMLHttpRequest.idl b/Source/WebCore/xml/XMLHttpRequest.idl
new file mode 100644
index 0000000..2b0b177
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequest.idl
@@ -0,0 +1,123 @@
+/*
+ * 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 [
+ CanBeConstructed,
+ CustomConstructFunction,
+ V8CustomConstructor,
+ CustomMarkFunction,
+ EventTarget,
+ NoStaticTables
+ ] 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
+#if defined(ENABLE_XHR_RESPONSE_BLOB) && ENABLE_XHR_RESPONSE_BLOB
+ attribute [EnabledAtRuntime] boolean asBlob
+ setter raises(DOMException);
+#endif
+
+ attribute boolean withCredentials
+ setter raises(DOMException);
+ // 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);
+
+ [RequiresAllArguments=Raise] 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);
+ [RequiresAllArguments=Raise, ConvertNullStringTo=Null] DOMString getResponseHeader(in DOMString header)
+ raises(DOMException);
+ readonly attribute [CustomGetter] DOMString responseText // The custom getter implements ConvertNullStringTo=Null
+ getter raises(DOMException);
+ readonly attribute Document responseXML
+ getter raises(DOMException);
+#if defined(ENABLE_XHR_RESPONSE_BLOB) && ENABLE_XHR_RESPONSE_BLOB
+ readonly attribute [EnabledAtRuntime] Blob responseBlob
+ getter raises(DOMException);
+#endif
+
+ attribute DOMString responseType
+ setter raises(DOMException);
+ readonly attribute [CustomGetter] Object response
+ getter raises(DOMException);
+
+ readonly attribute unsigned short status
+ getter raises(DOMException);
+ readonly attribute DOMString statusText
+ getter raises(DOMException);
+
+ // Extension
+ [RequiresAllArguments=Raise] void overrideMimeType(in DOMString override);
+
+ // EventTarget interface
+ void addEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ boolean dispatchEvent(in Event evt)
+ raises(EventException);
+ };
+
+}
diff --git a/Source/WebCore/xml/XMLHttpRequestException.h b/Source/WebCore/xml/XMLHttpRequestException.h
new file mode 100644
index 0000000..737cab0
--- /dev/null
+++ b/Source/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/Source/WebCore/xml/XMLHttpRequestException.idl b/Source/WebCore/xml/XMLHttpRequestException.idl
new file mode 100644
index 0000000..ffea732
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestException.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 xml {
+
+ interface [
+ NoStaticTables,
+ DontCheckEnums
+ ] XMLHttpRequestException {
+
+ readonly attribute unsigned short code;
+ readonly attribute DOMString name;
+ readonly attribute DOMString message;
+
+#if defined(LANGUAGE_JAVASCRIPT) && 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/Source/WebCore/xml/XMLHttpRequestProgressEvent.h b/Source/WebCore/xml/XMLHttpRequestProgressEvent.h
new file mode 100644
index 0000000..009f1c0
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEvent.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Julien Chaffraix <jchaffraix@webkit.org>. 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 = false, unsigned long long loaded = 0, unsigned long long total = 0)
+ {
+ return adoptRef(new XMLHttpRequestProgressEvent(type, lengthComputable, loaded, total));
+ }
+
+ // Those 2 synonyms are included for compatibility with Firefox.
+ unsigned long long position() const { return loaded(); }
+ unsigned long long totalSize() const { return total(); }
+
+private:
+ virtual bool isXMLHttpRequestProgressEvent() const { return true; }
+
+ XMLHttpRequestProgressEvent() { }
+ XMLHttpRequestProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
+ : ProgressEvent(type, lengthComputable, loaded, total)
+ {
+ }
+};
+
+} // namespace WebCore
+
+#endif // XMLHttpRequestProgressEvent_h
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl b/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl
new file mode 100644
index 0000000..05c984e
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 [
+ NoStaticTables
+ // We should also inherit from LSProgressEvent when the idl is added.
+ ] XMLHttpRequestProgressEvent : ProgressEvent {
+ readonly attribute unsigned long long position;
+ readonly attribute unsigned long long totalSize;
+ };
+
+}
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
new file mode 100644
index 0000000..5d4afa3
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Julien Chaffraix <jchaffraix@webkit.org>
+ * All right 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "XMLHttpRequestProgressEventThrottle.h"
+
+#include "EventTarget.h"
+#include "XMLHttpRequestProgressEvent.h"
+
+namespace WebCore {
+
+const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingIntervalInSeconds = .05; // 50 ms per specification.
+
+XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
+ : m_target(target)
+ , m_loaded(0)
+ , m_total(0)
+ , m_suspended(false)
+{
+ ASSERT(target);
+}
+
+XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle()
+{
+}
+
+void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
+{
+ ASSERT(!suspended());
+ if (!isActive()) {
+ // The timer is not active so the least frequent event for now is every byte.
+ // Just go ahead and dispatch the event.
+
+ // We should not have any pending loaded & total information from a previous run.
+ ASSERT(!m_loaded);
+ ASSERT(!m_total);
+
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
+ startRepeating(minimumProgressEventDispatchingIntervalInSeconds);
+ return;
+ }
+
+ // The timer is already active so minimumProgressEventDispatchingIntervalInSeconds is the least frequent event.
+ m_lengthComputable = lengthComputable;
+ m_loaded = loaded;
+ m_total = total;
+}
+
+void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event, ProgressEventAction progressEventAction)
+{
+ ASSERT(!suspended());
+ // We should not have any pending events from a previous resume.
+ ASSERT(!m_pausedEvent);
+
+ if (progressEventAction == FlushProgressEvent)
+ flushProgressEvent();
+
+ m_target->dispatchEvent(event);
+}
+
+void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
+{
+ if (!hasEventToDispatch())
+ return;
+
+ PassRefPtr<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
+ m_loaded = 0;
+ m_total = 0;
+
+ // We stop the timer as this is called when no more events are supposed to occur.
+ stop();
+
+ m_target->dispatchEvent(event);
+}
+
+void XMLHttpRequestProgressEventThrottle::dispatchPausedEvent()
+{
+ ASSERT(!suspended());
+ if (!m_pausedEvent)
+ return;
+
+ m_target->dispatchEvent(m_pausedEvent);
+ m_pausedEvent = 0;
+}
+
+void XMLHttpRequestProgressEventThrottle::fired()
+{
+ ASSERT(isActive());
+ ASSERT(!suspended());
+ ASSERT(!m_pausedEvent);
+ if (!hasEventToDispatch()) {
+ // No progress event was queued since the previous dispatch, we can safely stop the timer.
+ stop();
+ return;
+ }
+
+ m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
+ m_total = 0;
+ m_loaded = 0;
+}
+
+bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const
+{
+ return (m_total || m_loaded) && isActive();
+}
+
+void XMLHttpRequestProgressEventThrottle::suspend()
+{
+ ASSERT(!m_pausedEvent);
+
+ m_suspended = true;
+ // If we have a progress event waiting to be dispatched,
+ // just queue it.
+ if (hasEventToDispatch()) {
+ m_pausedEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
+ m_total = 0;
+ m_loaded = 0;
+ }
+ stop();
+}
+
+void XMLHttpRequestProgressEventThrottle::resume()
+{
+ ASSERT(!m_loaded);
+ ASSERT(!m_total);
+
+ m_suspended = false;
+ dispatchPausedEvent();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h
new file mode 100644
index 0000000..036905e
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 Julien Chaffraix <jchaffraix@webkit.org>
+ * All right 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef XMLHttpRequestProgressEventThrottle_h
+#define XMLHttpRequestProgressEventThrottle_h
+
+#include "Timer.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+class Event;
+class EventTarget;
+
+enum ProgressEventAction {
+ DoNotFlushProgressEvent,
+ FlushProgressEvent
+};
+
+// This implements the XHR2 progress event dispatching: "dispatch a progress event called progress
+// about every 50ms or for every byte received, whichever is least frequent".
+class XMLHttpRequestProgressEventThrottle : public TimerBase {
+public:
+ XMLHttpRequestProgressEventThrottle(EventTarget*);
+ virtual ~XMLHttpRequestProgressEventThrottle();
+
+ void dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
+ void dispatchEvent(PassRefPtr<Event>, ProgressEventAction = DoNotFlushProgressEvent);
+
+ void suspend();
+ void resume();
+
+ bool suspended() const { return m_suspended; }
+
+private:
+ static const double minimumProgressEventDispatchingIntervalInSeconds;
+
+ virtual void fired();
+ void dispatchPausedEvent();
+ void flushProgressEvent();
+
+ bool hasEventToDispatch() const;
+
+ // Weak pointer to our XMLHttpRequest object as it is the one holding us.
+ EventTarget* m_target;
+
+ bool m_lengthComputable;
+ unsigned long long m_loaded;
+ unsigned long long m_total;
+
+ bool m_suspended;
+ RefPtr<Event> m_pausedEvent;
+};
+
+} // namespace WebCore
+
+#endif // XMLHttpRequestProgressEventThrottle_h
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.cpp b/Source/WebCore/xml/XMLHttpRequestUpload.cpp
new file mode 100644
index 0000000..739082d
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "Event.h"
+#include "EventException.h"
+#include "EventNames.h"
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include <wtf/Assertions.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+XMLHttpRequestUpload::XMLHttpRequestUpload(XMLHttpRequest* xmlHttpRequest)
+ : m_xmlHttpRequest(xmlHttpRequest)
+{
+}
+
+ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
+{
+ XMLHttpRequest* xmlHttpRequest = associatedXMLHttpRequest();
+ if (!xmlHttpRequest)
+ return 0;
+ return xmlHttpRequest->scriptExecutionContext();
+}
+
+EventTargetData* XMLHttpRequestUpload::eventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+EventTargetData* XMLHttpRequestUpload::ensureEventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.h b/Source/WebCore/xml/XMLHttpRequestUpload.h
new file mode 100644
index 0000000..984d86a
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.h
@@ -0,0 +1,82 @@
+/*
+ * 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 "EventListener.h"
+#include "EventNames.h"
+#include "EventTarget.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+ 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;
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
+
+ using RefCounted<XMLHttpRequestUpload>::ref;
+ using RefCounted<XMLHttpRequestUpload>::deref;
+
+ private:
+ XMLHttpRequestUpload(XMLHttpRequest*);
+
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
+
+ XMLHttpRequest* m_xmlHttpRequest;
+ EventTargetData m_eventTargetData;
+ };
+
+} // namespace WebCore
+
+#endif // XMLHttpRequestUpload_h
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.idl b/Source/WebCore/xml/XMLHttpRequestUpload.idl
new file mode 100644
index 0000000..5a18567
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.idl
@@ -0,0 +1,55 @@
+/*
+ * 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,
+ EventTarget,
+ NoStaticTables
+ ] XMLHttpRequestUpload {
+ // From XMLHttpRequestEventTarget
+ // event handler attributes
+ attribute EventListener onabort;
+ attribute EventListener onerror;
+ attribute EventListener onload;
+ attribute EventListener onloadstart;
+ attribute EventListener onprogress;
+
+ // EventTarget interface
+ void addEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
+ boolean dispatchEvent(in Event evt)
+ raises(EventException);
+ };
+
+}
diff --git a/Source/WebCore/xml/XMLSerializer.cpp b/Source/WebCore/xml/XMLSerializer.cpp
new file mode 100644
index 0000000..7b49897
--- /dev/null
+++ b/Source/WebCore/xml/XMLSerializer.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ *
+ * 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/Source/WebCore/xml/XMLSerializer.h b/Source/WebCore/xml/XMLSerializer.h
new file mode 100644
index 0000000..33e94b7
--- /dev/null
+++ b/Source/WebCore/xml/XMLSerializer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ *
+ * 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/Source/WebCore/xml/XMLSerializer.idl b/Source/WebCore/xml/XMLSerializer.idl
new file mode 100644
index 0000000..8c59446
--- /dev/null
+++ b/Source/WebCore/xml/XMLSerializer.idl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ *
+ * 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 [CanBeConstructed] XMLSerializer {
+ DOMString serializeToString(in Node node)
+ raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/xml/XPathEvaluator.cpp b/Source/WebCore/xml/XPathEvaluator.cpp
new file mode 100644
index 0000000..8fb203f
--- /dev/null
+++ b/Source/WebCore/xml/XPathEvaluator.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Source/WebCore/xml/XPathEvaluator.h b/Source/WebCore/xml/XPathEvaluator.h
new file mode 100644
index 0000000..70322a4
--- /dev/null
+++ b/Source/WebCore/xml/XPathEvaluator.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+ typedef int ExceptionCode;
+
+ class Node;
+ 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/Source/WebCore/xml/XPathEvaluator.idl b/Source/WebCore/xml/XPathEvaluator.idl
new file mode 100644
index 0000000..30df23a
--- /dev/null
+++ b/Source/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 [CanBeConstructed, Conditional=XPATH] XPathEvaluator {
+ XPathExpression createExpression(in DOMString expression,
+ in XPathNSResolver resolver)
+ raises(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/Source/WebCore/xml/XPathException.h b/Source/WebCore/xml/XPathException.h
new file mode 100644
index 0000000..45ad628
--- /dev/null
+++ b/Source/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/Source/WebCore/xml/XPathException.idl b/Source/WebCore/xml/XPathException.idl
new file mode 100644
index 0000000..b57df57
--- /dev/null
+++ b/Source/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 [
+ Conditional=XPATH,
+ DontCheckEnums
+ ] XPathException {
+
+ readonly attribute unsigned short code;
+ readonly attribute DOMString name;
+ readonly attribute DOMString message;
+
+#if defined(LANGUAGE_JAVASCRIPT) && 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/Source/WebCore/xml/XPathExpression.cpp b/Source/WebCore/xml/XPathExpression.cpp
new file mode 100644
index 0000000..6188426
--- /dev/null
+++ b/Source/WebCore/xml/XPathExpression.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 "PlatformString.h"
+#include "XPathException.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;
+ }
+
+ EvaluationContext& evaluationContext = Expression::evaluationContext();
+ evaluationContext.node = contextNode;
+ evaluationContext.size = 1;
+ evaluationContext.position = 1;
+ evaluationContext.hadTypeConversionError = false;
+ RefPtr<XPathResult> result = XPathResult::create(contextNode->document(), 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 (evaluationContext.hadTypeConversionError) {
+ // It is not specified what to do if type conversion fails while evaluating an expression, and INVALID_EXPRESSION_ERR is not exactly right
+ // when the failure happens in an otherwise valid expression because of a variable. But XPathEvaluator does not support variables, so it's close enough.
+ ec = XPathException::INVALID_EXPRESSION_ERR;
+ return 0;
+ }
+
+ if (type != XPathResult::ANY_TYPE) {
+ ec = 0;
+ result->convertTo(type, ec);
+ if (ec)
+ return 0;
+ }
+
+ return result;
+}
+
+}
+
+#endif // ENABLE(XPATH)
diff --git a/Source/WebCore/xml/XPathExpression.h b/Source/WebCore/xml/XPathExpression.h
new file mode 100644
index 0000000..633ec80
--- /dev/null
+++ b/Source/WebCore/xml/XPathExpression.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+ typedef int ExceptionCode;
+
+ class Node;
+ 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/Source/WebCore/xml/XPathExpression.idl b/Source/WebCore/xml/XPathExpression.idl
new file mode 100644
index 0000000..6b6ceeb
--- /dev/null
+++ b/Source/WebCore/xml/XPathExpression.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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
+ ] XPathExpression {
+ [OldStyleObjC] XPathResult evaluate(in Node contextNode,
+ in unsigned short type,
+ in XPathResult inResult)
+ raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/xml/XPathExpressionNode.cpp b/Source/WebCore/xml/XPathExpressionNode.cpp
new file mode 100644
index 0000000..4656f8d
--- /dev/null
+++ b/Source/WebCore/xml/XPathExpressionNode.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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 <wtf/StdLibExtras.h>
+
+namespace WebCore {
+namespace XPath {
+
+EvaluationContext& Expression::evaluationContext()
+{
+ DEFINE_STATIC_LOCAL(EvaluationContext, evaluationContext, ());
+ return evaluationContext;
+}
+
+Expression::Expression()
+ : m_isContextNodeSensitive(false)
+ , m_isContextPositionSensitive(false)
+ , m_isContextSizeSensitive(false)
+{
+}
+
+Expression::~Expression()
+{
+ deleteAllValues(m_subExpressions);
+}
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/Source/WebCore/xml/XPathExpressionNode.h b/Source/WebCore/xml/XPathExpressionNode.h
new file mode 100644
index 0000000..c04d45b
--- /dev/null
+++ b/Source/WebCore/xml/XPathExpressionNode.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple 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 "Node.h"
+#include "XPathValue.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+ namespace XPath {
+
+ struct EvaluationContext : FastAllocBase {
+ RefPtr<Node> node;
+ unsigned long size;
+ unsigned long position;
+ HashMap<String, String> variableBindings;
+
+ bool hadTypeConversionError;
+ };
+
+ class ParseNode {
+ public:
+ virtual ~ParseNode() { }
+ };
+
+ class Expression : public ParseNode, public Noncopyable {
+ public:
+ static EvaluationContext& evaluationContext();
+
+ Expression();
+ virtual ~Expression();
+
+ virtual Value evaluate() const = 0;
+
+ void addSubExpression(Expression* expr)
+ {
+ m_subExpressions.append(expr);
+ m_isContextNodeSensitive |= expr->m_isContextNodeSensitive;
+ m_isContextPositionSensitive |= expr->m_isContextPositionSensitive;
+ m_isContextSizeSensitive |= expr->m_isContextSizeSensitive;
+ }
+
+ bool isContextNodeSensitive() const { return m_isContextNodeSensitive; }
+ bool isContextPositionSensitive() const { return m_isContextPositionSensitive; }
+ bool isContextSizeSensitive() const { return m_isContextSizeSensitive; }
+ void setIsContextNodeSensitive(bool value) { m_isContextNodeSensitive = value; }
+ void setIsContextPositionSensitive(bool value) { m_isContextPositionSensitive = value; }
+ void setIsContextSizeSensitive(bool value) { m_isContextSizeSensitive = value; }
+
+ virtual Value::Type resultType() const = 0;
+
+ 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;
+
+ // Evaluation details that can be used for optimization.
+ bool m_isContextNodeSensitive;
+ bool m_isContextPositionSensitive;
+ bool m_isContextSizeSensitive;
+ };
+
+ }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // EXPRESSION_H
+
diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp
new file mode 100644
index 0000000..2091aca
--- /dev/null
+++ b/Source/WebCore/xml/XPathFunctions.cpp
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 "NamedNodeMap.h"
+#include "ProcessingInstruction.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;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunLast() { setIsContextSizeSensitive(true); }
+};
+
+class FunPosition : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunPosition() { setIsContextPositionSensitive(true); }
+};
+
+class FunCount : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+};
+
+class FunId : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+};
+
+class FunLocalName : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunLocalName() { setIsContextNodeSensitive(true); } // local-name() with no arguments uses context node.
+};
+
+class FunNamespaceURI : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunNamespaceURI() { setIsContextNodeSensitive(true); } // namespace-uri() with no arguments uses context node.
+};
+
+class FunName : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunName() { setIsContextNodeSensitive(true); } // name() with no arguments uses context node.
+};
+
+class FunString : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunString() { setIsContextNodeSensitive(true); } // string() with no arguments uses context node.
+};
+
+class FunConcat : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+};
+
+class FunStartsWith : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunContains : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunSubstringBefore : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+};
+
+class FunSubstringAfter : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+};
+
+class FunSubstring : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+};
+
+class FunStringLength : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunStringLength() { setIsContextNodeSensitive(true); } // string-length() with no arguments uses context node.
+};
+
+class FunNormalizeSpace : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunNormalizeSpace() { setIsContextNodeSensitive(true); } // normalize-space() with no arguments uses context node.
+};
+
+class FunTranslate : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+};
+
+class FunBoolean : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunNot : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunTrue : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunFalse : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+};
+
+class FunLang : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+public:
+ FunLang() { setIsContextNodeSensitive(true); } // lang() always works on context node.
+};
+
+class FunNumber : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunNumber() { setIsContextNodeSensitive(true); } // number() with no arguments uses context node.
+};
+
+class FunSum : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+};
+
+class FunFloor : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+};
+
+class FunCeiling : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+};
+
+class FunRound : public Function {
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+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)
+{
+ ASSERT(!subExprCount());
+
+ // Some functions use context node as implicit argument, so when explicit arguments are added, they may no longer be context node sensitive.
+ if (m_name != "lang" && !args.isEmpty())
+ setIsContextNodeSensitive(false);
+
+ 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);
+}
+
+static inline String expandedNameLocalPart(Node* node)
+{
+ // The local part of an XPath expanded-name matches DOM local name for most node types, except for namespace nodes and processing instruction nodes.
+ ASSERT(node->nodeType() != Node::XPATH_NAMESPACE_NODE); // Not supported yet.
+ if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
+ return static_cast<ProcessingInstruction*>(node)->target();
+ return node->localName().string();
+}
+
+static inline String expandedName(Node* node)
+{
+ const AtomicString& prefix = node->prefix();
+ return prefix.isEmpty() ? expandedNameLocalPart(node) : prefix + ":" + expandedNameLocalPart(node);
+}
+
+Value FunLocalName::evaluate() const
+{
+ if (argCount() > 0) {
+ Value a = arg(0)->evaluate();
+ if (!a.isNodeSet())
+ return "";
+
+ Node* node = a.toNodeSet().firstNode();
+ return node ? expandedNameLocalPart(node) : "";
+ }
+
+ return expandedNameLocalPart(evaluationContext().node.get());
+}
+
+Value FunNamespaceURI::evaluate() const
+{
+ if (argCount() > 0) {
+ Value a = arg(0)->evaluate();
+ if (!a.isNodeSet())
+ return "";
+
+ Node* node = a.toNodeSet().firstNode();
+ return node ? node->namespaceURI().string() : "";
+ }
+
+ return evaluationContext().node->namespaceURI().string();
+}
+
+Value FunName::evaluate() const
+{
+ if (argCount() > 0) {
+ Value a = arg(0)->evaluate();
+ if (!a.isNodeSet())
+ return "";
+
+ Node* node = a.toNodeSet().firstNode();
+ return node ? expandedName(node) : "";
+ }
+
+ return expandedName(evaluationContext().node.get());
+}
+
+Value FunCount::evaluate() const
+{
+ Value a = arg(0)->evaluate();
+
+ 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 "";
+
+ size_t i = s1.find(s2);
+
+ if (i == notFound)
+ return "";
+
+ return s1.left(i);
+}
+
+Value FunSubstringAfter::evaluate() const
+{
+ String s1 = arg(0)->evaluate().toString();
+ String s2 = arg(1)->evaluate().toString();
+
+ size_t i = s1.find(s2);
+ if (i == notFound)
+ return "";
+
+ return s1.substring(i + s2.length());
+}
+
+Value FunSubstring::evaluate() const
+{
+ String s = arg(0)->evaluate().toString();
+ double doublePos = arg(1)->evaluate().toNumber();
+ if (isnan(doublePos))
+ return "";
+ long pos = static_cast<long>(FunRound::round(doublePos));
+ 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 (pos < 1) {
+ if (haveLength) {
+ len -= 1 - pos;
+ if (len < 1)
+ return "";
+ }
+ pos = 1;
+ }
+
+ 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];
+ size_t i2 = s2.find(ch);
+
+ if (i2 == notFound)
+ newString += String(&ch, 1);
+ else if (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();
+
+ Attribute* languageAttribute = 0;
+ Node* node = evaluationContext().node.get();
+ while (node) {
+ NamedNodeMap* attrs = node->attributes();
+ if (attrs)
+ languageAttribute = attrs->getAttributeItem(XMLNames::langAttr);
+ if (languageAttribute)
+ break;
+ node = node->parentNode();
+ }
+
+ if (!languageAttribute)
+ return false;
+
+ String langValue = languageAttribute->value();
+ while (true) {
+ if (equalIgnoringCase(langValue, lang))
+ return true;
+
+ // Remove suffixes one by one.
+ size_t index = langValue.reverseFind('-');
+ if (index == notFound)
+ break;
+ langValue = langValue.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());
+}
+
+struct FunctionMapping {
+ const char* name;
+ FunctionRec function;
+};
+
+static void createFunctionMap()
+{
+ 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 } },
+ };
+
+ functionMap = new HashMap<String, FunctionRec>;
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(functions); ++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/Source/WebCore/xml/XPathFunctions.h b/Source/WebCore/xml/XPathFunctions.h
new file mode 100644
index 0000000..62d687f
--- /dev/null
+++ b/Source/WebCore/xml/XPathFunctions.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple 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*>());
+
+ } // namespace XPath
+
+} // namespace WebCore
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathFunctions_h
diff --git a/Source/WebCore/xml/XPathGrammar.y b/Source/WebCore/xml/XPathGrammar.y
new file mode 100644
index 0000000..14e9fa3
--- /dev/null
+++ b/Source/WebCore/xml/XPathGrammar.y
@@ -0,0 +1,558 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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"
+#include <wtf/FastMalloc.h>
+
+#define YYMALLOC fastMalloc
+#define YYFREE fastFree
+
+#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;
+}
+
+%{
+
+static int xpathyylex(YYSTYPE* yylval) { return Parser::current()->lex(yylval); }
+static void xpathyyerror(const char*) { }
+
+%}
+
+%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/Source/WebCore/xml/XPathNSResolver.cpp b/Source/WebCore/xml/XPathNSResolver.cpp
new file mode 100644
index 0000000..3dde1f2
--- /dev/null
+++ b/Source/WebCore/xml/XPathNSResolver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Source/WebCore/xml/XPathNSResolver.h b/Source/WebCore/xml/XPathNSResolver.h
new file mode 100644
index 0000000..7b7fd2e
--- /dev/null
+++ b/Source/WebCore/xml/XPathNSResolver.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+ 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/Source/WebCore/xml/XPathNSResolver.idl b/Source/WebCore/xml/XPathNSResolver.idl
new file mode 100644
index 0000000..4e996c2
--- /dev/null
+++ b/Source/WebCore/xml/XPathNSResolver.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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, OmitConstructor] XPathNSResolver {
+ [ConvertNullStringTo=Null] DOMString lookupNamespaceURI(in DOMString prefix);
+ };
+
+}
diff --git a/Source/WebCore/xml/XPathNamespace.cpp b/Source/WebCore/xml/XPathNamespace.cpp
new file mode 100644
index 0000000..9646402
--- /dev/null
+++ b/Source/WebCore/xml/XPathNamespace.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 AtomicString& prefix, const AtomicString& uri)
+ : Node(ownerElement->document(), CreateOther)
+ , m_ownerElement(ownerElement)
+ , m_prefix(prefix)
+ , m_uri(uri)
+{
+}
+
+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/Source/WebCore/xml/XPathNamespace.h b/Source/WebCore/xml/XPathNamespace.h
new file mode 100644
index 0000000..c34eeef
--- /dev/null
+++ b/Source/WebCore/xml/XPathNamespace.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 "Node.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+ // FIXME: This class is never instantiated. Maybe it should be removed.
+
+ class XPathNamespace : public Node {
+ private:
+ XPathNamespace(PassRefPtr<Element> ownerElement, const AtomicString& prefix, const AtomicString& uri);
+
+ 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 NodeType nodeType() const;
+
+ RefPtr<Element> m_ownerElement;
+ AtomicString m_prefix;
+ AtomicString m_uri;
+ };
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathNamespace_h
+
diff --git a/Source/WebCore/xml/XPathNodeSet.cpp b/Source/WebCore/xml/XPathNodeSet.cpp
new file mode 100644
index 0000000..a8e4428
--- /dev/null
+++ b/Source/WebCore/xml/XPathNodeSet.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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->parentNode()))
+ 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.reserveInitialCapacity(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/Source/WebCore/xml/XPathNodeSet.h b/Source/WebCore/xml/XPathNodeSet.h
new file mode 100644
index 0000000..d5c47be
--- /dev/null
+++ b/Source/WebCore/xml/XPathNodeSet.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 FastAllocBase {
+ public:
+ NodeSet() : m_isSorted(true), m_subtreesAreDisjoint(false) { }
+
+ 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); std::swap(m_subtreesAreDisjoint, other.m_subtreesAreDisjoint); 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 contains nodes in document order - the caller should tell it if it does not.
+ void markSorted(bool isSorted) { m_isSorted = isSorted; }
+ bool isSorted() const { return m_isSorted || m_nodes.size() < 2; }
+
+ void sort() const;
+
+ // No node in the set is ancestor of another. Unlike m_isSorted, this is assumed to be false, unless the caller sets it to true.
+ void markSubtreesDisjoint(bool disjoint) { m_subtreesAreDisjoint = disjoint; }
+ bool subtreesAreDisjoint() const { return m_subtreesAreDisjoint || m_nodes.size() < 2; }
+
+ void reverse();
+
+ private:
+ bool m_isSorted;
+ bool m_subtreesAreDisjoint;
+ Vector<RefPtr<Node> > m_nodes;
+ };
+
+ }
+}
+
+#endif // ENABLE(XPATH)
+#endif // XPathNodeSet_h
diff --git a/Source/WebCore/xml/XPathParser.cpp b/Source/WebCore/xml/XPathParser.cpp
new file mode 100644
index 0000000..ba6da7e
--- /dev/null
+++ b/Source/WebCore/xml/XPathParser.cpp
@@ -0,0 +1,638 @@
+/*
+ * Copyright 2005 Maksim Orlovich <maksim@kde.org>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 "XPathEvaluator.h"
+#include "XPathException.h"
+#include "XPathNSResolver.h"
+#include "XPathStep.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringHash.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 };
+
+typedef HashMap<String, Step::Axis> AxisNamesMap;
+
+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(AxisNamesMap& 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)
+{
+ DEFINE_STATIC_LOCAL(AxisNamesMap, axisNames, ());
+
+ if (axisNames.isEmpty())
+ setUpAxisNamesMap(axisNames);
+
+ AxisNamesMap::iterator it = axisNames.find(name);
+ if (it == axisNames.end())
+ return false;
+ type = it->second;
+ return true;
+}
+
+static bool isNodeTypeName(const String& name)
+{
+ DEFINE_STATIC_LOCAL(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 current token can possibly be a binary operator, given
+// the previous token. Necessary to disambiguate some of the operators
+// (* (multiply), div, and, or, mod) in the [32] Operator rule
+// (check http://www.w3.org/TR/xpath#exprlex).
+bool Parser::isBinaryOperatorContext() const
+{
+ switch (m_lastTokenType) {
+ case 0:
+ case '@': case AXISNAME: case '(': case '[': case ',':
+ case AND: case OR: case MULOP:
+ case '/': case SLASHSLASH: case '|': case PLUS: case MINUS:
+ case EQOP: case RELOP:
+ 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 (isBinaryOperatorContext())
+ 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 (isBinaryOperatorContext()) {
+ 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());
+}
+
+Parser::~Parser()
+{
+}
+
+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)
+{
+ size_t colon = qName.find(':');
+ if (colon != notFound) {
+ 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/Source/WebCore/xml/XPathParser.h b/Source/WebCore/xml/XPathParser.h
new file mode 100644
index 0000000..0ee447a
--- /dev/null
+++ b/Source/WebCore/xml/XPathParser.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005 Maksim Orlovich <maksim@kde.org>
+ * 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 : public Noncopyable {
+ public:
+ Parser();
+ ~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 isBinaryOperatorContext() 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/Source/WebCore/xml/XPathPath.cpp b/Source/WebCore/xml/XPathPath.cpp
new file mode 100644
index 0000000..1a7ed3f
--- /dev/null
+++ b/Source/WebCore/xml/XPathPath.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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)
+{
+ setIsContextNodeSensitive(m_expr->isContextNodeSensitive());
+ setIsContextPositionSensitive(m_expr->isContextPositionSensitive());
+ setIsContextSizeSensitive(m_expr->isContextSizeSensitive());
+}
+
+Filter::~Filter()
+{
+ delete m_expr;
+ deleteAllValues(m_predicates);
+}
+
+Value Filter::evaluate() const
+{
+ Value v = m_expr->evaluate();
+
+ 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)
+{
+ setIsContextNodeSensitive(true);
+}
+
+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
+{
+ bool resultIsSorted = nodes.isSorted();
+
+ for (unsigned i = 0; i < m_steps.size(); i++) {
+ Step* step = m_steps[i];
+ NodeSet newNodes;
+ HashSet<Node*> newNodesSet;
+
+ bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis
+ && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis);
+
+ if (needToCheckForDuplicateNodes)
+ resultIsSorted = false;
+
+ // This is a simplified check that can be improved to handle more cases.
+ if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis))
+ newNodes.markSubtreesDisjoint(true);
+
+ for (unsigned j = 0; j < nodes.size(); j++) {
+ NodeSet matches;
+ step->evaluate(nodes[j], matches);
+
+ if (!matches.isSorted())
+ resultIsSorted = false;
+
+ for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) {
+ Node* node = matches[nodeIndex];
+ if (!needToCheckForDuplicateNodes || newNodesSet.add(node).second)
+ newNodes.append(node);
+ }
+ }
+
+ nodes.swap(newNodes);
+ }
+
+ nodes.markSorted(resultIsSorted);
+}
+
+void LocationPath::appendStep(Step* step)
+{
+ unsigned stepCount = m_steps.size();
+ if (stepCount) {
+ bool dropSecondStep;
+ optimizeStepPair(m_steps[stepCount - 1], step, dropSecondStep);
+ if (dropSecondStep) {
+ delete step;
+ return;
+ }
+ }
+ step->optimize();
+ m_steps.append(step);
+}
+
+void LocationPath::insertFirstStep(Step* step)
+{
+ if (m_steps.size()) {
+ bool dropSecondStep;
+ optimizeStepPair(step, m_steps[0], dropSecondStep);
+ if (dropSecondStep) {
+ delete m_steps[0];
+ m_steps[0] = step;
+ return;
+ }
+ }
+ step->optimize();
+ m_steps.insert(0, step);
+}
+
+Path::Path(Filter* filter, LocationPath* path)
+ : m_filter(filter)
+ , m_path(path)
+{
+ setIsContextNodeSensitive(filter->isContextNodeSensitive());
+ setIsContextPositionSensitive(filter->isContextPositionSensitive());
+ setIsContextSizeSensitive(filter->isContextSizeSensitive());
+}
+
+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/Source/WebCore/xml/XPathPath.h b/Source/WebCore/xml/XPathPath.h
new file mode 100644
index 0000000..7dd17d9
--- /dev/null
+++ b/Source/WebCore/xml/XPathPath.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple 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"
+
+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:
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+
+ Expression* m_expr;
+ Vector<Predicate*> m_predicates;
+ };
+
+ class LocationPath : public Expression {
+ public:
+ LocationPath();
+ virtual ~LocationPath();
+ void setAbsolute(bool value) { m_absolute = value; setIsContextNodeSensitive(!m_absolute); }
+
+ virtual Value evaluate() const;
+ void evaluate(NodeSet& nodes) const; // nodes is an input/output parameter
+
+ void appendStep(Step* step);
+ void insertFirstStep(Step* step);
+
+ private:
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+
+ Vector<Step*> m_steps;
+ bool m_absolute;
+ };
+
+ class Path : public Expression {
+ public:
+ Path(Filter*, LocationPath*);
+ virtual ~Path();
+
+ virtual Value evaluate() const;
+
+ private:
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+
+ Filter* m_filter;
+ LocationPath* m_path;
+ };
+
+ }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_Path_H
diff --git a/Source/WebCore/xml/XPathPredicate.cpp b/Source/WebCore/xml/XPathPredicate.cpp
new file mode 100644
index 0000000..2a6482f
--- /dev/null
+++ b/Source/WebCore/xml/XPathPredicate.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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();
+
+ 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/Source/WebCore/xml/XPathPredicate.h b/Source/WebCore/xml/XPathPredicate.h
new file mode 100644
index 0000000..5f2482a
--- /dev/null
+++ b/Source/WebCore/xml/XPathPredicate.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+
+ Value m_value;
+ };
+
+ class StringExpression : public Expression {
+ public:
+ StringExpression(const String&);
+ private:
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+
+ Value m_value;
+ };
+
+ class Negative : public Expression {
+ private:
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+ };
+
+ 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;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+
+ 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:
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+ 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:
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+ bool shortCircuitOn() const;
+ virtual Value evaluate() const;
+
+ Opcode m_opcode;
+ };
+
+ class Union : public Expression {
+ private:
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+ };
+
+ class Predicate : public Noncopyable {
+ public:
+ Predicate(Expression*);
+ ~Predicate();
+ bool evaluate() const;
+
+ bool isContextPositionSensitive() const { return m_expr->isContextPositionSensitive() || m_expr->resultType() == Value::NumberValue; }
+ bool isContextSizeSensitive() const { return m_expr->isContextSizeSensitive(); }
+
+ private:
+ Expression* m_expr;
+ };
+
+ }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathPredicate_h
diff --git a/Source/WebCore/xml/XPathResult.cpp b/Source/WebCore/xml/XPathResult.cpp
new file mode 100644
index 0000000..b608280
--- /dev/null
+++ b/Source/WebCore/xml/XPathResult.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 "Document.h"
+#include "Node.h"
+#include "ExceptionCode.h"
+#include "XPathEvaluator.h"
+#include "XPathException.h"
+
+namespace WebCore {
+
+using namespace XPath;
+
+XPathResult::XPathResult(Document* document, const Value& value)
+ : m_value(value)
+{
+ 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_document = document;
+ m_domTreeVersion = document->domTreeVersion();
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+XPathResult::~XPathResult()
+{
+}
+
+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();
+}
+
+bool XPathResult::invalidIteratorState() const
+{
+ if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE)
+ return false;
+
+ ASSERT(m_document);
+ return m_document->domTreeVersion() != m_domTreeVersion;
+}
+
+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 (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/Source/WebCore/xml/XPathResult.h b/Source/WebCore/xml/XPathResult.h
new file mode 100644
index 0000000..cbb51f5
--- /dev/null
+++ b/Source/WebCore/xml/XPathResult.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 "XPathValue.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+ typedef int ExceptionCode;
+
+ class Document;
+ class Node;
+
+ 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(Document* document, const XPath::Value& value) { return adoptRef(new XPathResult(document, 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&);
+
+ private:
+ XPathResult(Document*, 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;
+ RefPtr<Document> m_document;
+ unsigned m_domTreeVersion;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathResult_h
diff --git a/Source/WebCore/xml/XPathResult.idl b/Source/WebCore/xml/XPathResult.idl
new file mode 100644
index 0000000..ebbff42
--- /dev/null
+++ b/Source/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 [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/Source/WebCore/xml/XPathStep.cpp b/Source/WebCore/xml/XPathStep.cpp
new file mode 100644
index 0000000..d82cd50
--- /dev/null
+++ b/Source/WebCore/xml/XPathStep.cpp
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 "Attr.h"
+#include "Document.h"
+#include "Element.h"
+#include "NamedNodeMap.h"
+#include "XMLNSNames.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);
+ deleteAllValues(m_nodeTest.mergedPredicates());
+}
+
+void Step::optimize()
+{
+ // Evaluate predicates as part of node test if possible to avoid building unnecessary NodeSets.
+ // E.g., there is no need to build a set of all "foo" nodes to evaluate "foo[@bar]", we can check the predicate while enumerating.
+ // This optimization can be applied to predicates that are not context node list sensitive, or to first predicate that is only context position sensitive, e.g. foo[position() mod 2 = 0].
+ Vector<Predicate*> remainingPredicates;
+ for (size_t i = 0; i < m_predicates.size(); ++i) {
+ Predicate* predicate = m_predicates[i];
+ if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredicates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates.isEmpty()) {
+ m_nodeTest.mergedPredicates().append(predicate);
+ } else
+ remainingPredicates.append(predicate);
+ }
+ swap(remainingPredicates, m_predicates);
+}
+
+void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep)
+{
+ dropSecondStep = false;
+
+ if (first->m_axis == Step::DescendantOrSelfAxis
+ && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest
+ && !first->m_predicates.size()
+ && !first->m_nodeTest.mergedPredicates().size()) {
+
+ ASSERT(first->m_nodeTest.data().isEmpty());
+ ASSERT(first->m_nodeTest.namespaceURI().isEmpty());
+
+ // Optimize the common case of "//" AKA /descendant-or-self::node()/child::NodeTest to /descendant::NodeTest.
+ if (second->m_axis == Step::ChildAxis && second->predicatesAreContextListInsensitive()) {
+ first->m_axis = Step::DescendantAxis;
+ first->m_nodeTest = Step::NodeTest(second->m_nodeTest.kind(), second->m_nodeTest.data(), second->m_nodeTest.namespaceURI());
+ swap(second->m_nodeTest.mergedPredicates(), first->m_nodeTest.mergedPredicates());
+ swap(second->m_predicates, first->m_predicates);
+ first->optimize();
+ dropSecondStep = true;
+ }
+ }
+}
+
+bool Step::predicatesAreContextListInsensitive() const
+{
+ for (size_t i = 0; i < m_predicates.size(); ++i) {
+ Predicate* predicate = m_predicates[i];
+ if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive())
+ return false;
+ }
+
+ for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) {
+ Predicate* predicate = m_nodeTest.mergedPredicates()[i];
+ if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive())
+ return false;
+ }
+
+ return true;
+}
+
+void Step::evaluate(Node* context, NodeSet& nodes) const
+{
+ EvaluationContext& evaluationContext = Expression::evaluationContext();
+ evaluationContext.position = 0;
+
+ nodesInAxis(context, nodes);
+
+ // Check predicates that couldn't be merged into node test.
+ 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];
+
+ evaluationContext.node = node;
+ evaluationContext.size = nodes.size();
+ evaluationContext.position = j + 1;
+ if (predicate->evaluate())
+ newNodes.append(node);
+ }
+
+ nodes.swap(newNodes);
+ }
+}
+
+static inline Node::NodeType primaryNodeType(Step::Axis axis)
+{
+ switch (axis) {
+ case Step::AttributeAxis:
+ return Node::ATTRIBUTE_NODE;
+ case Step::NamespaceAxis:
+ return Node::XPATH_NAMESPACE_NODE;
+ default:
+ return Node::ELEMENT_NODE;
+ }
+}
+
+// Evaluate NodeTest without considering merged predicates.
+static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest)
+{
+ switch (nodeTest.kind()) {
+ case Step::NodeTest::TextNodeTest:
+ return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE;
+ case Step::NodeTest::CommentNodeTest:
+ return node->nodeType() == Node::COMMENT_NODE;
+ case Step::NodeTest::ProcessingInstructionNodeTest: {
+ const AtomicString& name = nodeTest.data();
+ return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name);
+ }
+ case Step::NodeTest::AnyNodeTest:
+ return true;
+ case Step::NodeTest::NameTest: {
+ const AtomicString& name = nodeTest.data();
+ const AtomicString& namespaceURI = nodeTest.namespaceURI();
+
+ if (axis == Step::AttributeAxis) {
+ ASSERT(node->isAttributeNode());
+
+ // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (node->namespaceURI() == XMLNSNames::xmlnsNamespaceURI)
+ return false;
+
+ if (name == starAtom)
+ return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI;
+
+ return node->localName() == name && node->namespaceURI() == namespaceURI;
+ }
+
+ // Node test on the namespace axis is not implemented yet, the caller has a check for it.
+ ASSERT(axis != Step::NamespaceAxis);
+
+ // For other axes, the principal node type is element.
+ ASSERT(primaryNodeType(axis) == Node::ELEMENT_NODE);
+ if (node->nodeType() != Node::ELEMENT_NODE)
+ return false;
+
+ if (name == starAtom)
+ return namespaceURI.isEmpty() || namespaceURI == node->namespaceURI();
+
+ if (node->document()->isHTMLDocument()) {
+ if (node->isHTMLElement()) {
+ // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively.
+ return equalIgnoringCase(static_cast<Element*>(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI());
+ }
+ // An expression without any prefix shouldn't match no-namespace nodes (because HTML5 says so).
+ return static_cast<Element*>(node)->hasLocalName(name) && namespaceURI == node->namespaceURI() && !namespaceURI.isNull();
+ }
+ return static_cast<Element*>(node)->hasLocalName(name) && namespaceURI == node->namespaceURI();
+ }
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest)
+{
+ if (!nodeMatchesBasicTest(node, axis, nodeTest))
+ return false;
+
+ EvaluationContext& evaluationContext = Expression::evaluationContext();
+
+ // Only the first merged predicate may depend on position.
+ ++evaluationContext.position;
+
+ const Vector<Predicate*>& mergedPredicates = nodeTest.mergedPredicates();
+ for (unsigned i = 0; i < mergedPredicates.size(); i++) {
+ Predicate* predicate = mergedPredicates[i];
+
+ evaluationContext.node = node;
+ // No need to set context size - we only get here when evaluating predicates that do not depend on it.
+ if (!predicate->evaluate())
+ return false;
+ }
+
+ return true;
+}
+
+// Result nodes are ordered in axis order. Node test (including merged predicates) is applied.
+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, ChildAxis, m_nodeTest))
+ 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, DescendantAxis, m_nodeTest))
+ nodes.append(n);
+ return;
+ case ParentAxis:
+ if (context->isAttributeNode()) {
+ Element* n = static_cast<Attr*>(context)->ownerElement();
+ if (nodeMatches(n, ParentAxis, m_nodeTest))
+ nodes.append(n);
+ } else {
+ ContainerNode* n = context->parentNode();
+ if (n && nodeMatches(n, ParentAxis, m_nodeTest))
+ nodes.append(n);
+ }
+ return;
+ case AncestorAxis: {
+ Node* n = context;
+ if (context->isAttributeNode()) {
+ n = static_cast<Attr*>(context)->ownerElement();
+ if (nodeMatches(n, AncestorAxis, m_nodeTest))
+ nodes.append(n);
+ }
+ for (n = n->parentNode(); n; n = n->parentNode())
+ if (nodeMatches(n, AncestorAxis, m_nodeTest))
+ 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, FollowingSiblingAxis, m_nodeTest))
+ 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, PrecedingSiblingAxis, m_nodeTest))
+ 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, FollowingAxis, m_nodeTest))
+ 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, FollowingAxis, m_nodeTest))
+ nodes.append(n);
+ for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n))
+ if (nodeMatches(c, FollowingAxis, m_nodeTest))
+ nodes.append(c);
+ }
+ }
+ }
+ return;
+ case PrecedingAxis: {
+ if (context->isAttributeNode())
+ context = static_cast<Attr*>(context)->ownerElement();
+
+ Node* n = context;
+ while (ContainerNode* parent = n->parentNode()) {
+ for (n = n->traversePreviousNode(); n != parent; n = n->traversePreviousNode())
+ if (nodeMatches(n, PrecedingAxis, m_nodeTest))
+ 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() != starAtom) {
+ RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data());
+ if (n && n->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (nodeMatches(n.get(), AttributeAxis, m_nodeTest)) // Still need to check merged predicates.
+ nodes.append(n.release());
+ }
+ return;
+ }
+
+ NamedNodeMap* attrs = context->attributes();
+ if (!attrs)
+ return;
+
+ for (unsigned i = 0; i < attrs->length(); ++i) {
+ RefPtr<Attr> attr = attrs->attributeItem(i)->createAttrIfNeeded(static_cast<Element*>(context));
+ if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest))
+ nodes.append(attr.release());
+ }
+ return;
+ }
+ case NamespaceAxis:
+ // XPath namespace nodes are not implemented yet.
+ return;
+ case SelfAxis:
+ if (nodeMatches(context, SelfAxis, m_nodeTest))
+ nodes.append(context);
+ return;
+ case DescendantOrSelfAxis:
+ if (nodeMatches(context, DescendantOrSelfAxis, m_nodeTest))
+ 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, DescendantOrSelfAxis, m_nodeTest))
+ nodes.append(n);
+ return;
+ case AncestorOrSelfAxis: {
+ if (nodeMatches(context, AncestorOrSelfAxis, m_nodeTest))
+ nodes.append(context);
+ Node* n = context;
+ if (context->isAttributeNode()) {
+ n = static_cast<Attr*>(context)->ownerElement();
+ if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
+ nodes.append(n);
+ }
+ for (n = n->parentNode(); n; n = n->parentNode())
+ if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
+ nodes.append(n);
+
+ nodes.markSorted(false);
+ return;
+ }
+ }
+ ASSERT_NOT_REACHED();
+}
+
+
+}
+}
+
+#endif // ENABLE(XPATH)
diff --git a/Source/WebCore/xml/XPathStep.h b/Source/WebCore/xml/XPathStep.h
new file mode 100644
index 0000000..ec022b3
--- /dev/null
+++ b/Source/WebCore/xml/XPathStep.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple 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, public Noncopyable {
+ public:
+ enum Axis {
+ AncestorAxis, AncestorOrSelfAxis, AttributeAxis,
+ ChildAxis, DescendantAxis, DescendantOrSelfAxis,
+ FollowingAxis, FollowingSiblingAxis, NamespaceAxis,
+ ParentAxis, PrecedingAxis, PrecedingSiblingAxis,
+ SelfAxis
+ };
+
+ class NodeTest : public FastAllocBase {
+ public:
+ enum Kind {
+ TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest
+ };
+
+ 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 AtomicString& data() const { return m_data; }
+ const AtomicString& namespaceURI() const { return m_namespaceURI; }
+ Vector<Predicate*>& mergedPredicates() { return m_mergedPredicates; }
+ const Vector<Predicate*>& mergedPredicates() const { return m_mergedPredicates; }
+
+ private:
+ Kind m_kind;
+ AtomicString m_data;
+ AtomicString m_namespaceURI;
+
+ // When possible, we merge some or all predicates with node test for better performance.
+ Vector<Predicate*> m_mergedPredicates;
+ };
+
+ Step(Axis, const NodeTest& nodeTest, const Vector<Predicate*>& predicates = Vector<Predicate*>());
+ ~Step();
+
+ void optimize();
+
+ void evaluate(Node* context, NodeSet&) const;
+
+ Axis axis() const { return m_axis; }
+ const NodeTest& nodeTest() const { return m_nodeTest; }
+
+ private:
+ friend void optimizeStepPair(Step*, Step*, bool&);
+ bool predicatesAreContextListInsensitive() const;
+
+ void parseNodeTest(const String&);
+ void nodesInAxis(Node* context, NodeSet&) const;
+ String namespaceFromNodetest(const String& nodeTest) const;
+
+ Axis m_axis;
+ NodeTest m_nodeTest;
+ Vector<Predicate*> m_predicates;
+ };
+
+ void optimizeStepPair(Step*, Step*, bool& dropSecondStep);
+ }
+
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPathStep_h
diff --git a/Source/WebCore/xml/XPathUtil.cpp b/Source/WebCore/xml/XPathUtil.cpp
new file mode 100644
index 0000000..0100bea
--- /dev/null
+++ b/Source/WebCore/xml/XPathUtil.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple 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) {
+ Vector<UChar> result;
+ result.reserveCapacity(1024);
+
+ for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node)) {
+ if (n->isTextNode()) {
+ const String& nodeValue = n->nodeValue();
+ result.append(nodeValue.characters(), nodeValue.length());
+ }
+ }
+
+ return String::adopt(result);
+ }
+ }
+
+ 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/Source/WebCore/xml/XPathUtil.h b/Source/WebCore/xml/XPathUtil.h
new file mode 100644
index 0000000..cfb34dc
--- /dev/null
+++ b/Source/WebCore/xml/XPathUtil.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ class Node;
+
+ 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/Source/WebCore/xml/XPathValue.cpp b/Source/WebCore/xml/XPathValue.cpp
new file mode 100644
index 0000000..29e211e
--- /dev/null
+++ b/Source/WebCore/xml/XPathValue.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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 "XPathExpressionNode.h"
+#include "XPathUtil.h"
+#include <limits>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
+
+using std::numeric_limits;
+
+namespace WebCore {
+namespace XPath {
+
+const Value::AdoptTag Value::adopt = {};
+
+const NodeSet& Value::toNodeSet() const
+{
+ if (!isNodeSet())
+ Expression::evaluationContext().hadTypeConversionError = true;
+
+ if (!m_data) {
+ DEFINE_STATIC_LOCAL(NodeSet, emptyNodeSet, ());
+ return emptyNodeSet;
+ }
+
+ return m_data->m_nodeSet;
+}
+
+NodeSet& Value::modifiableNodeSet()
+{
+ if (!isNodeSet())
+ Expression::evaluationContext().hadTypeConversionError = true;
+
+ 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: {
+ const String& str = m_data->m_string.simplifyWhiteSpace();
+
+ // String::toDouble() supports exponential notation, which is not allowed in XPath.
+ unsigned len = str.length();
+ for (unsigned i = 0; i < len; ++i) {
+ UChar c = str[i];
+ if (!isASCIIDigit(c) && c != '.' && c != '-')
+ return numeric_limits<double>::quiet_NaN();
+ }
+
+ bool canConvert;
+ double value = str.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/Source/WebCore/xml/XPathValue.h b/Source/WebCore/xml/XPathValue.h
new file mode 100644
index 0000000..a0cd24d
--- /dev/null
+++ b/Source/WebCore/xml/XPathValue.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Source/WebCore/xml/XPathVariableReference.cpp b/Source/WebCore/xml/XPathVariableReference.cpp
new file mode 100644
index 0000000..efe9cf9
--- /dev/null
+++ b/Source/WebCore/xml/XPathVariableReference.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ * 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/Source/WebCore/xml/XPathVariableReference.h b/Source/WebCore/xml/XPathVariableReference.h
new file mode 100644
index 0000000..5e5a59a
--- /dev/null
+++ b/Source/WebCore/xml/XPathVariableReference.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005 Frerich Raabe <raabe@kde.org>
+ *
+ * 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 {
+
+ // Variable references are not used with XPathEvaluator.
+ class VariableReference : public Expression {
+ public:
+ VariableReference(const String& name);
+ private:
+ virtual Value evaluate() const;
+ virtual Value::Type resultType() const { ASSERT_NOT_REACHED(); return Value::NumberValue; }
+ String m_name;
+ };
+
+ }
+}
+
+#endif // ENABLE(XPATH)
+
+#endif // XPath_VariableReference_H
diff --git a/Source/WebCore/xml/XSLImportRule.cpp b/Source/WebCore/xml/XSLImportRule.cpp
new file mode 100644
index 0000000..c32da4e
--- /dev/null
+++ b/Source/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 "CachedResourceLoader.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& href, const KURL& baseURL, const String& sheet)
+{
+ if (m_styleSheet)
+ m_styleSheet->setParent(0);
+
+ m_styleSheet = XSLStyleSheet::create(this, href, baseURL);
+
+ XSLStyleSheet* parent = parentStyleSheet();
+ if (parent)
+ m_styleSheet->setParentStyleSheet(parent);
+
+ 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()
+{
+ CachedResourceLoader* cachedResourceLoader = 0;
+ StyleBase* root = this;
+ StyleBase* parent;
+ while ((parent = root->parent()))
+ root = parent;
+ if (root->isXSLStyleSheet())
+ cachedResourceLoader = static_cast<XSLStyleSheet*>(root)->cachedResourceLoader();
+
+ String absHref = m_strHref;
+ XSLStyleSheet* parentSheet = parentStyleSheet();
+ if (!parentSheet->finalURL().isNull())
+ // use parent styleheet's URL as the base URL
+ absHref = KURL(parentSheet->finalURL(), 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)->finalURL().string())
+ return;
+ }
+
+ m_cachedSheet = cachedResourceLoader->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/Source/WebCore/xml/XSLImportRule.h b/Source/WebCore/xml/XSLImportRule.h
new file mode 100644
index 0000000..63c271e
--- /dev/null
+++ b/Source/WebCore/xml/XSLImportRule.h
@@ -0,0 +1,88 @@
+/*
+ * 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();
+
+#ifdef ANDROID_INSTRUMENT
+ void* operator new(size_t size) {
+ return StyleBase::operator new(size);
+ }
+ void* operator new[](size_t size) {
+ return StyleBase::operator new[](size);
+ }
+
+ void operator delete(void* p, size_t size) {
+ StyleBase::operator delete(p, size);
+ }
+ void operator delete[](void* p, size_t size) {
+ StyleBase::operator delete[](p, size);
+ }
+#endif
+
+private:
+ XSLImportRule(XSLStyleSheet* parentSheet, const String& href);
+
+ virtual bool isImportRule() { return true; }
+
+ // from CachedResourceClient
+ virtual void setXSLStyleSheet(const String& href, const KURL& baseURL, 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/Source/WebCore/xml/XSLStyleSheet.h b/Source/WebCore/xml/XSLStyleSheet.h
new file mode 100644
index 0000000..4312771
--- /dev/null
+++ b/Source/WebCore/xml/XSLStyleSheet.h
@@ -0,0 +1,122 @@
+/*
+ * 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 "ProcessingInstruction.h"
+#include "StyleSheet.h"
+
+#if !USE(QXMLQUERY)
+#include <libxml/parser.h>
+#include <libxslt/transform.h>
+#endif
+
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class XSLImportRule;
+
+class XSLStyleSheet : public StyleSheet {
+public:
+#if !USE(QXMLQUERY)
+ static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& originalURL, const KURL& finalURL)
+ {
+ return adoptRef(new XSLStyleSheet(parentImport, originalURL, finalURL));
+ }
+#endif
+ static PassRefPtr<XSLStyleSheet> create(ProcessingInstruction* parentNode, const String& originalURL, const KURL& finalURL)
+ {
+ return adoptRef(new XSLStyleSheet(parentNode, originalURL, finalURL, false));
+ }
+ static PassRefPtr<XSLStyleSheet> createEmbedded(ProcessingInstruction* parentNode, const KURL& finalURL)
+ {
+ return adoptRef(new XSLStyleSheet(parentNode, finalURL.string(), finalURL, true));
+ }
+
+ // Taking an arbitrary node is unsafe, because owner node pointer can become stale.
+ // XSLTProcessor ensures that the stylesheet doesn't outlive its parent, in part by not exposing it to JavaScript.
+ static PassRefPtr<XSLStyleSheet> createForXSLTProcessor(Node* parentNode, const String& originalURL, const KURL& finalURL)
+ {
+ return adoptRef(new XSLStyleSheet(parentNode, originalURL, finalURL, false));
+ }
+
+ 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);
+
+ CachedResourceLoader* cachedResourceLoader();
+
+ Document* ownerDocument() { return m_ownerDocument; }
+ void setParentStyleSheet(XSLStyleSheet* parent);
+
+#if USE(QXMLQUERY)
+ String sheetString() const { return m_sheetString; }
+#else
+ xmlDocPtr document();
+ xsltStylesheetPtr compileStyleSheet();
+ xmlDocPtr locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri);
+#endif
+
+ void clearDocuments();
+
+ void markAsProcessed();
+ bool processed() const { return m_processed; }
+
+private:
+ XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded);
+#if !USE(QXMLQUERY)
+ XSLStyleSheet(XSLImportRule* parentImport, const String& originalURL, const KURL& finalURL);
+#endif
+
+ Document* m_ownerDocument;
+ bool m_embedded;
+ bool m_processed;
+
+#if USE(QXMLQUERY)
+ String m_sheetString;
+#else
+ xmlDocPtr m_stylesheetDoc;
+ bool m_stylesheetDocTaken;
+#endif
+
+ XSLStyleSheet* m_parentStyleSheet;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
+
+#endif // XSLStyleSheet_h
diff --git a/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
new file mode 100644
index 0000000..eb735f4
--- /dev/null
+++ b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
@@ -0,0 +1,314 @@
+/*
+ * 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 "Console.h"
+#include "DOMWindow.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "Frame.h"
+#include "Node.h"
+#include "TransformSource.h"
+#include "XMLDocumentParser.h"
+#include "XMLDocumentParserScope.h"
+#include "XSLImportRule.h"
+#include "XSLTProcessor.h"
+#include <wtf/text/CString.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& originalURL, const KURL& finalURL)
+ : StyleSheet(parentRule, originalURL, finalURL)
+ , m_ownerDocument(0)
+ , m_embedded(false)
+ , m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them.
+ , m_stylesheetDoc(0)
+ , m_stylesheetDocTaken(false)
+ , m_parentStyleSheet(0)
+{
+}
+
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
+ : StyleSheet(parentNode, originalURL, finalURL)
+ , m_ownerDocument(parentNode->document())
+ , m_embedded(embedded)
+ , m_processed(true) // The root sheet starts off processed.
+ , m_stylesheetDoc(0)
+ , m_stylesheetDocTaken(false)
+ , m_parentStyleSheet(0)
+{
+}
+
+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() && ownerDocument()->transformSource())
+ return (xmlDocPtr)ownerDocument()->transformSource()->platformSource();
+ 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();
+ }
+ }
+}
+
+CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
+{
+ if (!m_ownerDocument)
+ return 0;
+ return m_ownerDocument->cachedResourceLoader();
+}
+
+bool XSLStyleSheet::parseString(const String& string, bool)
+{
+ // Parse in a single chunk into an xmlDocPtr
+ const UChar BOM = 0xFEFF;
+ const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
+ if (!m_stylesheetDocTaken)
+ xmlFreeDoc(m_stylesheetDoc);
+ m_stylesheetDocTaken = false;
+
+ Console* console = 0;
+ if (Frame* frame = ownerDocument()->frame())
+ console = frame->domWindow()->console();
+
+ XMLDocumentParserScope scope(cachedResourceLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);
+
+ const char* buffer = reinterpret_cast<const char*>(string.characters());
+ int size = string.length() * sizeof(UChar);
+
+ xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+ if (!ctxt)
+ return 0;
+
+ if (m_parentStyleSheet) {
+ // The XSL transform may leave the newly-transformed document
+ // with references to the symbol dictionaries of the style sheet
+ // and any of its children. XML document disposal can corrupt memory
+ // if a document uses more than one symbol dictionary, so we
+ // ensure that all child stylesheets use the same dictionaries as their
+ // parents.
+ xmlDictFree(ctxt->dict);
+ ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict;
+ xmlDictReference(ctxt->dict);
+ }
+
+ m_stylesheetDoc = xmlCtxtReadMemory(ctxt, buffer, size,
+ finalURL().string().utf8().data(),
+ BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
+ XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
+ xmlFreeParserCtxt(ctxt);
+
+ loadChildSheets();
+
+ 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*)(finalURL().string().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;
+}
+
+void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet* parent)
+{
+ m_parentStyleSheet = parent;
+ if (parent)
+ m_ownerDocument = parent->ownerDocument();
+}
+
+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/Source/WebCore/xml/XSLStyleSheetQt.cpp b/Source/WebCore/xml/XSLStyleSheetQt.cpp
new file mode 100644
index 0000000..855d6ba
--- /dev/null
+++ b/Source/WebCore/xml/XSLStyleSheetQt.cpp
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 "DOMWindow.h"
+#include "Document.h"
+#include "Node.h"
+#include "NotImplemented.h"
+#include "XSLTProcessor.h"
+
+namespace WebCore {
+
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
+ : StyleSheet(parentNode, originalURL, finalURL)
+ , m_ownerDocument(parentNode->document())
+ , m_embedded(embedded)
+{
+}
+
+XSLStyleSheet::~XSLStyleSheet()
+{
+}
+
+bool XSLStyleSheet::isLoading()
+{
+ notImplemented();
+ return false;
+}
+
+void XSLStyleSheet::checkLoaded()
+{
+ if (ownerNode())
+ ownerNode()->sheetLoaded();
+}
+
+void XSLStyleSheet::clearDocuments()
+{
+ notImplemented();
+}
+
+CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
+{
+ if (!m_ownerDocument)
+ return 0;
+ return m_ownerDocument->cachedResourceLoader();
+}
+
+bool XSLStyleSheet::parseString(const String& string, bool)
+{
+ // FIXME: Fix QXmlQuery so that it allows compiling the stylesheet before setting the document
+ // to be transformed. This way we could not only check if the stylesheet is correct before using it
+ // but also turn XSLStyleSheet::sheetString() into XSLStyleSheet::query() that returns a QXmlQuery.
+
+ m_sheetString = string;
+ return !m_sheetString.isEmpty();
+}
+
+void XSLStyleSheet::loadChildSheets()
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::loadChildSheet(const String&)
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet*)
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::markAsProcessed()
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/Source/WebCore/xml/XSLTExtensions.cpp b/Source/WebCore/xml/XSLTExtensions.cpp
new file mode 100644
index 0000000..069ddd8
--- /dev/null
+++ b/Source/WebCore/xml/XSLTExtensions.cpp
@@ -0,0 +1,89 @@
+/**
+ * Copyright (C) 2001-2002 Thomas Broyer, Charlie Bozeman and Daniel Veillard.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 "XSLTExtensions.h"
+
+#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/Source/WebCore/xml/XSLTExtensions.h b/Source/WebCore/xml/XSLTExtensions.h
new file mode 100644
index 0000000..4e4224f
--- /dev/null
+++ b/Source/WebCore/xml/XSLTExtensions.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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/Source/WebCore/xml/XSLTProcessor.cpp b/Source/WebCore/xml/XSLTProcessor.cpp
new file mode 100644
index 0000000..9b6a067
--- /dev/null
+++ b/Source/WebCore/xml/XSLTProcessor.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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 <ap@webkit.org>
+ *
+ * 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 "DOMImplementation.h"
+#include "CachedResourceLoader.h"
+#include "DocumentFragment.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameView.h"
+#include "HTMLBodyElement.h"
+#include "HTMLDocument.h"
+#include "Page.h"
+#include "Text.h"
+#include "TextResourceDecoder.h"
+#include "markup.h"
+
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+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";
+}
+
+XSLTProcessor::~XSLTProcessor()
+{
+ // Stylesheet shouldn't outlive its root node.
+ ASSERT(!m_stylesheetRootNode || !m_stylesheet || m_stylesheet->hasOneRef());
+}
+
+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 = Document::create(frame, sourceIsDocument ? ownerDocument->url() : KURL());
+ transformTextStringToXHTMLDocumentString(documentSource);
+ } else
+ result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : KURL(), 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);
+ }
+
+ 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->close();
+
+ return result.release();
+}
+
+static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& sourceString, const String& sourceMIMEType, Document* outputDoc)
+{
+ RefPtr<DocumentFragment> fragment = outputDoc->createDocumentFragment();
+
+ if (sourceMIMEType == "text/html") {
+ // As far as I can tell, there isn't a spec for how transformToFragment
+ // is supposed to work. Based on the documentation I can find, it looks
+ // like we want to start parsing the fragment in the InBody insertion
+ // mode. Unfortunately, that's an implementation detail of the parser.
+ // We achieve that effect here by passing in a fake body element as
+ // context for the fragment.
+ RefPtr<HTMLBodyElement> fakeBody = HTMLBodyElement::create(outputDoc);
+ fragment->parseHTML(sourceString, fakeBody.get());
+ } else if (sourceMIMEType == "text/plain")
+ fragment->parserAddChild(Text::create(outputDoc, sourceString));
+ else {
+ bool successfulParse = fragment->parseXML(sourceString, 0);
+ if (!successfulParse)
+ return 0;
+ }
+
+ // FIXME: Do we need to mess with URLs here?
+
+ return fragment;
+}
+
+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, 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);
+}
+
+void XSLTProcessor::reset()
+{
+ m_stylesheet.clear();
+ m_stylesheetRootNode.clear();
+ m_parameters.clear();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/Source/WebCore/xml/XSLTProcessor.h b/Source/WebCore/xml/XSLTProcessor.h
new file mode 100644
index 0000000..451e12c
--- /dev/null
+++ b/Source/WebCore/xml/XSLTProcessor.h
@@ -0,0 +1,86 @@
+/*
+ * 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 "XSLStyleSheet.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/StringHash.h>
+
+#if !USE(QXMLQUERY)
+#include <libxml/parserInternals.h>
+#include <libxslt/documents.h>
+#endif
+
+namespace WebCore {
+
+class Frame;
+class Document;
+class DocumentFragment;
+
+class XSLTProcessor : public RefCounted<XSLTProcessor> {
+public:
+ static PassRefPtr<XSLTProcessor> create() { return adoptRef(new XSLTProcessor); }
+ ~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();
+
+#if !USE(QXMLQUERY)
+ static void parseErrorFunc(void* userData, xmlError*);
+ static void genericErrorFunc(void* userData, const char* msg, ...);
+
+ // Only for libXSLT callbacks
+ XSLStyleSheet* xslStylesheet() const { return m_stylesheet.get(); }
+#endif
+
+ typedef HashMap<String, String> ParameterMap;
+
+private:
+ XSLTProcessor() { }
+
+ RefPtr<XSLStyleSheet> m_stylesheet;
+ RefPtr<Node> m_stylesheetRootNode;
+ ParameterMap m_parameters;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/xml/XSLTProcessor.idl b/Source/WebCore/xml/XSLTProcessor.idl
new file mode 100644
index 0000000..dac4b21
--- /dev/null
+++ b/Source/WebCore/xml/XSLTProcessor.idl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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,
+ CanBeConstructed,
+ CustomConstructFunction,
+ V8CustomConstructor
+ ] 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/Source/WebCore/xml/XSLTProcessorLibxslt.cpp b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
new file mode 100644
index 0000000..89e1a87
--- /dev/null
+++ b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
@@ -0,0 +1,354 @@
+/*
+ * 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 <ap@webkit.org>
+ *
+ * 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 "Console.h"
+#include "DOMWindow.h"
+#include "CachedResourceLoader.h"
+#include "Frame.h"
+#include "ResourceError.h"
+#include "ResourceHandle.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "TransformSource.h"
+#include "XMLDocumentParser.h"
+#include "XSLStyleSheet.h"
+#include "XSLTExtensions.h"
+#include "XSLTUnicodeSort.h"
+#include "markup.h"
+#include <libxslt/imports.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltutils.h>
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuffer.h>
+#include <wtf/unicode/UTF8.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+
+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*, const char*, ...)
+{
+ // 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, LogMessageType, 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 CachedResourceLoader* globalCachedResourceLoader = 0;
+static xmlDocPtr docLoaderFunc(const xmlChar* uri,
+ xmlDictPtr,
+ 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(ParsedURLString, reinterpret_cast<const char*>(base)), reinterpret_cast<const char*>(uri));
+ xmlFree(base);
+ ResourceError error;
+ ResourceResponse response;
+
+ Vector<char> data;
+
+ bool requestAllowed = globalCachedResourceLoader->frame() && globalCachedResourceLoader->document()->securityOrigin()->canRequest(url);
+ if (requestAllowed) {
+ globalCachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data);
+ requestAllowed = globalCachedResourceLoader->document()->securityOrigin()->canRequest(response.url());
+ }
+ if (!requestAllowed) {
+ data.clear();
+ globalCachedResourceLoader->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, CachedResourceLoader* cachedResourceLoader)
+{
+ xsltSetLoaderFunc(func);
+ globalProcessor = processor;
+ globalCachedResourceLoader = cachedResourceLoader;
+}
+
+static int writeToVector(void* context, const char* buffer, int len)
+{
+ Vector<UChar>& resultOutput = *static_cast<Vector<UChar>*>(context);
+
+ if (!len)
+ return 0;
+
+ StringBuffer stringBuffer(len);
+ UChar* bufferUChar = stringBuffer.characters();
+ UChar* bufferUCharEnd = bufferUChar + len;
+
+ const char* stringCurrent = buffer;
+ WTF::Unicode::ConversionResult result = WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, buffer + len, &bufferUChar, bufferUCharEnd);
+ if (result != WTF::Unicode::conversionOK && result != WTF::Unicode::sourceExhausted) {
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+
+ int utf16Length = bufferUChar - stringBuffer.characters();
+ resultOutput.append(stringBuffer.characters(), utf16Length);
+ return stringCurrent - buffer;
+}
+
+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 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++] = fastStrDup(it->first.utf8().data());
+ parameterArray[index++] = fastStrDup(it->second.utf8().data());
+ }
+ parameterArray[index] = 0;
+
+ return parameterArray;
+}
+
+static void freeXsltParamArray(const char** params)
+{
+ const char** temp = params;
+ if (!params)
+ return;
+
+ while (*temp) {
+ fastFree((void*)*(temp++));
+ fastFree((void*)*(temp++));
+ }
+ fastFree(params);
+}
+
+static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStylesheet, Node* stylesheetRootNode)
+{
+ if (!cachedStylesheet && stylesheetRootNode) {
+ cachedStylesheet = XSLStyleSheet::createForXSLTProcessor(stylesheetRootNode->parentNode() ? stylesheetRootNode->parentNode() : stylesheetRootNode,
+ stylesheetRootNode->document()->url().string(),
+ stylesheetRootNode->document()->url()); // FIXME: Should we use baseURL here?
+
+ // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element.
+ // But we just use text content regardless of node type.
+ 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 && ownerDocument->transformSource())
+ sourceDoc = (xmlDocPtr)ownerDocument->transformSource()->platformSource();
+ if (!sourceDoc) {
+ sourceDoc = (xmlDocPtr)xmlDocPtrForString(ownerDocument->cachedResourceLoader(), createMarkup(sourceNode),
+ sourceIsDocument ? ownerDocument->url().string() : String());
+ shouldDelete = sourceDoc;
+ }
+ 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 && resultDoc->type == XML_HTML_DOCUMENT_NODE)
+ resultType = (const xmlChar*)"html";
+
+ if (xmlStrEqual(resultType, (const xmlChar*)"html"))
+ return "text/html";
+ 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->cachedResourceLoader());
+ 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)
+ 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;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/Source/WebCore/xml/XSLTProcessorQt.cpp b/Source/WebCore/xml/XSLTProcessorQt.cpp
new file mode 100644
index 0000000..717ad8b
--- /dev/null
+++ b/Source/WebCore/xml/XSLTProcessorQt.cpp
@@ -0,0 +1,182 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 "Console.h"
+#include "DOMWindow.h"
+#include "Frame.h"
+#include "TransformSource.h"
+#include "markup.h"
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+#include <qabstractmessagehandler.h>
+#include <qabstracturiresolver.h>
+#include <qbuffer.h>
+#include <qsourcelocation.h>
+#include <qxmlquery.h>
+
+namespace WebCore {
+
+class XSLTMessageHandler : public QAbstractMessageHandler {
+
+public:
+ XSLTMessageHandler(Document* document = 0);
+ virtual void handleMessage(QtMsgType type, const QString& description,
+ const QUrl& identifier, const QSourceLocation& sourceLocation);
+
+private:
+ Document* m_document;
+};
+
+XSLTMessageHandler::XSLTMessageHandler(Document* document)
+ : QAbstractMessageHandler()
+ , m_document(document)
+{
+}
+
+void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description,
+ const QUrl&, const QSourceLocation& sourceLocation)
+{
+ if (!m_document->frame())
+ return;
+
+ MessageLevel level;
+ switch (type) {
+ case QtDebugMsg:
+ level = TipMessageLevel;
+ break;
+ case QtWarningMsg:
+ level = WarningMessageLevel;
+ break;
+ case QtCriticalMsg:
+ case QtFatalMsg:
+ level = ErrorMessageLevel;
+ break;
+ default:
+ level = LogMessageLevel;
+ break;
+ }
+
+ Console* console = m_document->frame()->domWindow()->console();
+ console->addMessage(XMLMessageSource, LogMessageType, level, description,
+ sourceLocation.line(), sourceLocation.uri().toString());
+}
+
+class XSLTUriResolver : public QAbstractUriResolver {
+
+public:
+ XSLTUriResolver(Document* document);
+ virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const;
+
+private:
+ Document* m_document;
+};
+
+XSLTUriResolver::XSLTUriResolver(Document* document)
+ : QAbstractUriResolver()
+ , m_document(document)
+{
+}
+
+QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const
+{
+ QUrl url = baseURI.resolved(relative);
+
+ if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url))
+ return QUrl();
+ return url;
+}
+
+bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&)
+{
+ bool success = false;
+
+ RefPtr<XSLStyleSheet> stylesheet = m_stylesheet;
+ if (!stylesheet && m_stylesheetRootNode) {
+ Node* node = m_stylesheetRootNode.get();
+ stylesheet = XSLStyleSheet::createForXSLTProcessor(node->parentNode() ? node->parentNode() : node,
+ node->document()->url().string(),
+ node->document()->url()); // FIXME: Should we use baseURL here?
+
+ // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element.
+ // But we just use text content regardless of node type.
+ stylesheet->parseString(createMarkup(node));
+ }
+
+ if (!stylesheet || stylesheet->sheetString().isEmpty())
+ return success;
+
+ RefPtr<Document> ownerDocument = sourceNode->document();
+ bool sourceIsDocument = (sourceNode == ownerDocument.get());
+
+ QXmlQuery query(QXmlQuery::XSLT20);
+
+ XSLTMessageHandler messageHandler(ownerDocument.get());
+ XSLTUriResolver uriResolver(ownerDocument.get());
+ query.setMessageHandler(&messageHandler);
+
+ XSLTProcessor::ParameterMap::iterator end = m_parameters.end();
+ for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it)
+ query.bindVariable(QString(it->first), QXmlItem(QVariant(QString(it->second))));
+
+ QString source;
+ if (sourceIsDocument && ownerDocument->transformSource())
+ source = ownerDocument->transformSource()->platformSource();
+ if (!sourceIsDocument || source.isEmpty())
+ source = createMarkup(sourceNode);
+
+ QBuffer inputBuffer;
+ QBuffer styleSheetBuffer;
+ QBuffer outputBuffer;
+
+ inputBuffer.setData(source.toUtf8());
+ styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8());
+
+ inputBuffer.open(QIODevice::ReadOnly);
+ styleSheetBuffer.open(QIODevice::ReadOnly);
+ outputBuffer.open(QIODevice::ReadWrite);
+
+ query.setFocus(&inputBuffer);
+ query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href()));
+
+ query.setUriResolver(&uriResolver);
+
+ success = query.evaluateTo(&outputBuffer);
+ outputBuffer.reset();
+ resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed();
+
+ if (m_stylesheet) {
+ m_stylesheet->clearDocuments();
+ m_stylesheet = 0;
+ }
+
+ return success;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/Source/WebCore/xml/XSLTUnicodeSort.cpp b/Source/WebCore/xml/XSLTUnicodeSort.cpp
new file mode 100644
index 0000000..b0b9c72
--- /dev/null
+++ b/Source/WebCore/xml/XSLTUnicodeSort.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 xsltTransformErrorTrampoline(xsltTransformContextPtr, xsltStylesheetPtr, xmlNodePtr, const char* message, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+
+void xsltTransformErrorTrampoline(xsltTransformContextPtr context, xsltStylesheetPtr style, xmlNodePtr node, const char* message, ...)
+{
+ va_list args;
+ va_start(args, message);
+ char* messageWithArgs;
+ vasprintf(&messageWithArgs, message, args);
+ va_end(args);
+
+ static void (*xsltTransformErrorPointer)(xsltTransformContextPtr, xsltStylesheetPtr, xmlNodePtr, const char*, ...) WTF_ATTRIBUTE_PRINTF(4, 5)
+ = reinterpret_cast<void (*)(xsltTransformContextPtr, xsltStylesheetPtr, xmlNodePtr, const char*, ...)>(dlsym(libxsltLibrary(), "xsltTransformError"));
+ xsltTransformErrorPointer(context, style, node, "%s", messageWithArgs);
+
+ free(messageWithArgs);
+}
+
+#define xsltTransformError xsltTransformErrorTrampoline
+
+#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/Source/WebCore/xml/XSLTUnicodeSort.h b/Source/WebCore/xml/XSLTUnicodeSort.h
new file mode 100644
index 0000000..c8d395b
--- /dev/null
+++ b/Source/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/Source/WebCore/xml/xmlattrs.in b/Source/WebCore/xml/xmlattrs.in
new file mode 100644
index 0000000..6cc47be
--- /dev/null
+++ b/Source/WebCore/xml/xmlattrs.in
@@ -0,0 +1,6 @@
+namespace="XML"
+namespaceURI="http://www.w3.org/XML/1998/namespace"
+
+base
+lang
+space
diff --git a/Source/WebCore/xml/xmlnsattrs.in b/Source/WebCore/xml/xmlnsattrs.in
new file mode 100644
index 0000000..7ac415a
--- /dev/null
+++ b/Source/WebCore/xml/xmlnsattrs.in
@@ -0,0 +1,4 @@
+namespace="XMLNS"
+namespaceURI="http://www.w3.org/2000/xmlns/"
+
+xmlns