summaryrefslogtreecommitdiff
path: root/Source/WebCore/xml
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/xml
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/xml')
-rw-r--r--Source/WebCore/xml/DOMParser.cpp18
-rw-r--r--Source/WebCore/xml/DOMParser.h7
-rw-r--r--Source/WebCore/xml/DOMParser.idl6
-rw-r--r--Source/WebCore/xml/NativeXPathNSResolver.cpp8
-rw-r--r--Source/WebCore/xml/NativeXPathNSResolver.h8
-rw-r--r--Source/WebCore/xml/XMLErrors.cpp79
-rw-r--r--Source/WebCore/xml/XMLErrors.h2
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.cpp804
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.h167
-rw-r--r--Source/WebCore/xml/XMLHttpRequest.idl48
-rw-r--r--Source/WebCore/xml/XMLHttpRequestEventTarget.h38
-rw-r--r--Source/WebCore/xml/XMLHttpRequestEventTarget.idl (renamed from Source/WebCore/xml/XMLHttpRequestException.idl)32
-rw-r--r--Source/WebCore/xml/XMLHttpRequestException.cpp61
-rw-r--r--Source/WebCore/xml/XMLHttpRequestException.h63
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEvent.h17
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEvent.idl5
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp86
-rw-r--r--Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h17
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.cpp39
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.h39
-rw-r--r--Source/WebCore/xml/XMLHttpRequestUpload.idl24
-rw-r--r--Source/WebCore/xml/XMLSerializer.cpp15
-rw-r--r--Source/WebCore/xml/XMLSerializer.h6
-rw-r--r--Source/WebCore/xml/XMLSerializer.idl4
-rw-r--r--Source/WebCore/xml/XMLTreeViewer.cpp46
-rw-r--r--Source/WebCore/xml/XMLTreeViewer.h7
-rw-r--r--Source/WebCore/xml/XMLViewer.css23
-rw-r--r--Source/WebCore/xml/XMLViewer.js15
-rw-r--r--Source/WebCore/xml/XPathEvaluator.cpp13
-rw-r--r--Source/WebCore/xml/XPathEvaluator.h12
-rw-r--r--Source/WebCore/xml/XPathEvaluator.idl4
-rw-r--r--Source/WebCore/xml/XPathException.cpp4
-rw-r--r--Source/WebCore/xml/XPathException.h6
-rw-r--r--Source/WebCore/xml/XPathException.idl4
-rw-r--r--Source/WebCore/xml/XPathExpression.cpp30
-rw-r--r--Source/WebCore/xml/XPathExpression.h12
-rw-r--r--Source/WebCore/xml/XPathExpression.idl4
-rw-r--r--Source/WebCore/xml/XPathExpressionNode.cpp22
-rw-r--r--Source/WebCore/xml/XPathExpressionNode.h119
-rw-r--r--Source/WebCore/xml/XPathFunctions.cpp510
-rw-r--r--Source/WebCore/xml/XPathFunctions.h32
-rw-r--r--Source/WebCore/xml/XPathGrammar.y349
-rw-r--r--Source/WebCore/xml/XPathNSResolver.cpp2
-rw-r--r--Source/WebCore/xml/XPathNSResolver.h2
-rw-r--r--Source/WebCore/xml/XPathNSResolver.idl4
-rw-r--r--Source/WebCore/xml/XPathNodeSet.cpp81
-rw-r--r--Source/WebCore/xml/XPathNodeSet.h31
-rw-r--r--Source/WebCore/xml/XPathParser.cpp347
-rw-r--r--Source/WebCore/xml/XPathParser.h70
-rw-r--r--Source/WebCore/xml/XPathPath.cpp107
-rw-r--r--Source/WebCore/xml/XPathPath.h50
-rw-r--r--Source/WebCore/xml/XPathPredicate.cpp150
-rw-r--r--Source/WebCore/xml/XPathPredicate.h81
-rw-r--r--Source/WebCore/xml/XPathResult.cpp1
-rw-r--r--Source/WebCore/xml/XPathResult.h2
-rw-r--r--Source/WebCore/xml/XPathResult.idl14
-rw-r--r--Source/WebCore/xml/XPathStep.cpp331
-rw-r--r--Source/WebCore/xml/XPathStep.h80
-rw-r--r--Source/WebCore/xml/XPathUtil.cpp23
-rw-r--r--Source/WebCore/xml/XPathUtil.h2
-rw-r--r--Source/WebCore/xml/XPathValue.cpp46
-rw-r--r--Source/WebCore/xml/XPathValue.h83
-rw-r--r--Source/WebCore/xml/XPathVariableReference.cpp4
-rw-r--r--Source/WebCore/xml/XSLImportRule.cpp15
-rw-r--r--Source/WebCore/xml/XSLImportRule.h11
-rw-r--r--Source/WebCore/xml/XSLStyleSheet.h76
-rw-r--r--Source/WebCore/xml/XSLStyleSheetLibxslt.cpp65
-rw-r--r--Source/WebCore/xml/XSLStyleSheetQt.cpp116
-rw-r--r--Source/WebCore/xml/XSLTExtensions.cpp4
-rw-r--r--Source/WebCore/xml/XSLTProcessor.cpp40
-rw-r--r--Source/WebCore/xml/XSLTProcessor.h20
-rw-r--r--Source/WebCore/xml/XSLTProcessor.idl4
-rw-r--r--Source/WebCore/xml/XSLTProcessorLibxslt.cpp80
-rw-r--r--Source/WebCore/xml/XSLTProcessorQt.cpp183
-rw-r--r--Source/WebCore/xml/XSLTUnicodeSort.cpp26
-rw-r--r--Source/WebCore/xml/XSLTUnicodeSort.h2
-rw-r--r--Source/WebCore/xml/parser/CharacterReferenceParserInlines.h155
-rw-r--r--Source/WebCore/xml/parser/MarkupTokenizerInlines.h91
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParser.cpp90
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParser.h86
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp308
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParserQt.cpp657
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParserScope.cpp2
-rw-r--r--Source/WebCore/xml/parser/XMLDocumentParserScope.h4
84 files changed, 2428 insertions, 3923 deletions
diff --git a/Source/WebCore/xml/DOMParser.cpp b/Source/WebCore/xml/DOMParser.cpp
index 49677ea79..997faca0f 100644
--- a/Source/WebCore/xml/DOMParser.cpp
+++ b/Source/WebCore/xml/DOMParser.cpp
@@ -20,19 +20,25 @@
#include "DOMParser.h"
#include "DOMImplementation.h"
-#include "Document.h"
+#include "ExceptionCode.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
-PassRefPtr<Document> DOMParser::parseFromString(const String& str, const String& contentType)
+RefPtr<Document> DOMParser::parseFromString(const String& str, const String& contentType, ExceptionCode& ec)
{
- if (!DOMImplementation::isXMLMIMEType(contentType))
- return 0;
+ if (contentType != "text/html"
+ && contentType != "text/xml"
+ && contentType != "application/xml"
+ && contentType != "application/xhtml+xml"
+ && contentType != "image/svg+xml") {
+ ec = TypeError;
+ return nullptr;
+ }
- RefPtr<Document> doc = DOMImplementation::createDocument(contentType, 0, KURL(), false);
+ Ref<Document> doc = DOMImplementation::createDocument(contentType, nullptr, URL());
doc->setContent(str);
- return doc.release();
+ return WTFMove(doc);
}
} // namespace WebCore
diff --git a/Source/WebCore/xml/DOMParser.h b/Source/WebCore/xml/DOMParser.h
index 41329bac2..132ca5bc8 100644
--- a/Source/WebCore/xml/DOMParser.h
+++ b/Source/WebCore/xml/DOMParser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,14 +24,15 @@
#include <wtf/RefPtr.h>
namespace WebCore {
+typedef int ExceptionCode;
class Document;
class DOMParser : public RefCounted<DOMParser> {
public:
- static PassRefPtr<DOMParser> create() { return adoptRef(new DOMParser); }
+ static Ref<DOMParser> create() { return adoptRef(*new DOMParser); }
- PassRefPtr<Document> parseFromString(const String&, const String& contentType);
+ RefPtr<Document> parseFromString(const String&, const String& contentType, ExceptionCode&);
private:
DOMParser() { }
diff --git a/Source/WebCore/xml/DOMParser.idl b/Source/WebCore/xml/DOMParser.idl
index c602a59fd..940496b9b 100644
--- a/Source/WebCore/xml/DOMParser.idl
+++ b/Source/WebCore/xml/DOMParser.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,8 +19,8 @@
[
Constructor,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface DOMParser {
- Document parseFromString([Default=Undefined] optional DOMString str,
+ [RaisesException] Document parseFromString([Default=Undefined] optional DOMString str,
[Default=Undefined] optional DOMString contentType);
};
diff --git a/Source/WebCore/xml/NativeXPathNSResolver.cpp b/Source/WebCore/xml/NativeXPathNSResolver.cpp
index 54b0d4c46..fb11473d6 100644
--- a/Source/WebCore/xml/NativeXPathNSResolver.cpp
+++ b/Source/WebCore/xml/NativeXPathNSResolver.cpp
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -32,8 +32,8 @@
namespace WebCore {
-NativeXPathNSResolver::NativeXPathNSResolver(PassRefPtr<Node> node)
- : m_node(node)
+NativeXPathNSResolver::NativeXPathNSResolver(RefPtr<Node>&& node)
+ : m_node(WTFMove(node))
{
}
diff --git a/Source/WebCore/xml/NativeXPathNSResolver.h b/Source/WebCore/xml/NativeXPathNSResolver.h
index f71ad9364..64102072e 100644
--- a/Source/WebCore/xml/NativeXPathNSResolver.h
+++ b/Source/WebCore/xml/NativeXPathNSResolver.h
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -35,13 +35,13 @@ class Node;
class NativeXPathNSResolver : public XPathNSResolver {
public:
- static PassRefPtr<NativeXPathNSResolver> create(PassRefPtr<Node> node) { return adoptRef(new NativeXPathNSResolver(node)); }
+ static Ref<NativeXPathNSResolver> create(RefPtr<Node>&& node) { return adoptRef(*new NativeXPathNSResolver(WTFMove(node))); }
virtual ~NativeXPathNSResolver();
virtual String lookupNamespaceURI(const String& prefix);
private:
- explicit NativeXPathNSResolver(PassRefPtr<Node>);
+ explicit NativeXPathNSResolver(RefPtr<Node>&&);
RefPtr<Node> m_node;
};
diff --git a/Source/WebCore/xml/XMLErrors.cpp b/Source/WebCore/xml/XMLErrors.cpp
index 61b5c0ab9..e8f710c11 100644
--- a/Source/WebCore/xml/XMLErrors.cpp
+++ b/Source/WebCore/xml/XMLErrors.cpp
@@ -33,13 +33,10 @@
#include "Element.h"
#include "Frame.h"
#include "HTMLNames.h"
+#include "SVGNames.h"
#include "Text.h"
#include <wtf/text/WTFString.h>
-#if ENABLE(SVG)
-#include "SVGNames.h"
-#endif
-
namespace WebCore {
using namespace HTMLNames;
@@ -87,23 +84,23 @@ void XMLErrors::appendErrorMessage(const String& typeString, TextPosition positi
m_errorMessages.append(message);
}
-static inline PassRefPtr<Element> createXHTMLParserErrorHeader(Document* doc, const String& errorMessages)
+static inline Ref<Element> createXHTMLParserErrorHeader(Document* doc, const String& errorMessages)
{
- RefPtr<Element> reportElement = doc->createElement(QualifiedName(nullAtom, "parsererror", xhtmlNamespaceURI), true);
+ Ref<Element> reportElement = doc->createElement(QualifiedName(nullAtom, "parsererror", xhtmlNamespaceURI), true);
Vector<Attribute> reportAttributes;
reportAttributes.append(Attribute(styleAttr, "display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black"));
reportElement->parserSetAttributes(reportAttributes);
- RefPtr<Element> h3 = doc->createElement(h3Tag, true);
- reportElement->parserAppendChild(h3.get());
+ auto h3 = doc->createElement(h3Tag, true);
+ reportElement->parserAppendChild(h3.copyRef());
h3->parserAppendChild(doc->createTextNode("This page contains the following errors:"));
- RefPtr<Element> fixed = doc->createElement(divTag, true);
+ auto fixed = doc->createElement(divTag, true);
Vector<Attribute> fixedAttributes;
fixedAttributes.append(Attribute(styleAttr, "font-family:monospace;font-size:12px"));
fixed->parserSetAttributes(fixedAttributes);
- reportElement->parserAppendChild(fixed.get());
+ reportElement->parserAppendChild(fixed.copyRef());
fixed->parserAppendChild(doc->createTextNode(errorMessages));
@@ -111,7 +108,7 @@ static inline PassRefPtr<Element> createXHTMLParserErrorHeader(Document* doc, co
reportElement->parserAppendChild(h3.get());
h3->parserAppendChild(doc->createTextNode("Below is a rendering of the page up to the first error."));
- return reportElement.release();
+ return reportElement;
}
void XMLErrors::insertErrorMessageBlock()
@@ -123,58 +120,50 @@ void XMLErrors::insertErrorMessageBlock()
// Create elements for display
RefPtr<Element> documentElement = m_document->documentElement();
if (!documentElement) {
- RefPtr<Element> rootElement = m_document->createElement(htmlTag, true);
- RefPtr<Element> body = m_document->createElement(bodyTag, true);
- rootElement->parserAppendChild(body);
- m_document->parserAppendChild(rootElement);
- if (m_document->attached() && !rootElement->attached())
- rootElement->attach();
- documentElement = body.get();
+ auto rootElement = m_document->createElement(htmlTag, true);
+ auto body = m_document->createElement(bodyTag, true);
+ rootElement->parserAppendChild(body.copyRef());
+ m_document->parserAppendChild(rootElement.copyRef());
+ documentElement = WTFMove(body);
}
-#if ENABLE(SVG)
else if (documentElement->namespaceURI() == SVGNames::svgNamespaceURI) {
- RefPtr<Element> rootElement = m_document->createElement(htmlTag, true);
- RefPtr<Element> body = m_document->createElement(bodyTag, true);
- rootElement->parserAppendChild(body);
-
- documentElement->parentNode()->parserRemoveChild(documentElement.get());
- if (documentElement->attached())
- documentElement->detach();
-
- body->parserAppendChild(documentElement);
- m_document->parserAppendChild(rootElement.get());
-
- if (m_document->attached())
- // In general, rootElement shouldn't be attached right now, but it will be if there is a style element
- // in the SVG content.
- rootElement->reattach();
-
- documentElement = body.get();
+ auto rootElement = m_document->createElement(htmlTag, true);
+ auto head = m_document->createElement(headTag, true);
+ auto style = m_document->createElement(styleTag, true);
+ head->parserAppendChild(style.copyRef());
+ style->parserAppendChild(m_document->createTextNode("html, body { height: 100% } parsererror + svg { width: 100%; height: 100% }"));
+ style->finishParsingChildren();
+ rootElement->parserAppendChild(head.copyRef());
+ auto body = m_document->createElement(bodyTag, true);
+ rootElement->parserAppendChild(body.copyRef());
+
+ m_document->parserRemoveChild(*documentElement);
+
+ body->parserAppendChild(*documentElement);
+ m_document->parserAppendChild(WTFMove(rootElement));
+
+ documentElement = WTFMove(body);
}
-#endif
String errorMessages = m_errorMessages.toString();
- RefPtr<Element> reportElement = createXHTMLParserErrorHeader(m_document, errorMessages);
+ auto reportElement = createXHTMLParserErrorHeader(m_document, errorMessages);
#if ENABLE(XSLT)
if (m_document->transformSourceDocument()) {
Vector<Attribute> attributes;
attributes.append(Attribute(styleAttr, "white-space: normal"));
- RefPtr<Element> paragraph = m_document->createElement(pTag, true);
+ auto paragraph = m_document->createElement(pTag, true);
paragraph->parserSetAttributes(attributes);
paragraph->parserAppendChild(m_document->createTextNode("This document was created as the result of an XSL transformation. The line and column numbers given are from the transformed result."));
- reportElement->parserAppendChild(paragraph.release());
+ reportElement->parserAppendChild(WTFMove(paragraph));
}
#endif
Node* firstChild = documentElement->firstChild();
if (firstChild)
- documentElement->parserInsertBefore(reportElement, documentElement->firstChild());
+ documentElement->parserInsertBefore(WTFMove(reportElement), *firstChild);
else
- documentElement->parserAppendChild(reportElement);
-
- if (documentElement->attached() && !reportElement->attached())
- reportElement->attach();
+ documentElement->parserAppendChild(WTFMove(reportElement));
m_document->updateStyleIfNeeded();
}
diff --git a/Source/WebCore/xml/XMLErrors.h b/Source/WebCore/xml/XMLErrors.h
index d4e48b3e4..0032e8426 100644
--- a/Source/WebCore/xml/XMLErrors.h
+++ b/Source/WebCore/xml/XMLErrors.h
@@ -32,9 +32,7 @@
#include <wtf/text/StringBuilder.h>
#include <wtf/text/TextPosition.h>
-#if !USE(QXMLSTREAM)
#include <libxml/parser.h>
-#endif
namespace WebCore {
diff --git a/Source/WebCore/xml/XMLHttpRequest.cpp b/Source/WebCore/xml/XMLHttpRequest.cpp
index e854019bc..2c93b5aaa 100644
--- a/Source/WebCore/xml/XMLHttpRequest.cpp
+++ b/Source/WebCore/xml/XMLHttpRequest.cpp
@@ -24,21 +24,17 @@
#include "XMLHttpRequest.h"
#include "Blob.h"
-#include "BlobData.h"
+#include "CachedResourceRequestInitiators.h"
#include "ContentSecurityPolicy.h"
-#include "ContextFeatures.h"
#include "CrossOriginAccessControl.h"
#include "DOMFormData.h"
#include "DOMImplementation.h"
#include "Event.h"
-#include "EventException.h"
-#include "EventListener.h"
-#include "EventNames.h"
#include "ExceptionCode.h"
#include "File.h"
#include "HTMLDocument.h"
+#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
-#include "HistogramSupport.h"
#include "InspectorInstrumentation.h"
#include "JSDOMBinding.h"
#include "JSDOMWindow.h"
@@ -46,30 +42,27 @@
#include "ParsedContentType.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
-#include "ScriptCallStack.h"
#include "ScriptController.h"
-#include "ScriptProfile.h"
+#include "SecurityOriginPolicy.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 <heap/Strong.h>
+#include <mutex>
+#include <runtime/ArrayBuffer.h>
+#include <runtime/ArrayBufferView.h>
+#include <runtime/JSCInlines.h>
#include <runtime/JSLock.h>
-#include <runtime/Operations.h>
-#include <wtf/ArrayBuffer.h>
-#include <wtf/ArrayBufferView.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Ref.h>
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/CString.h>
-#if ENABLE(RESOURCE_TIMING)
-#include "CachedResourceRequestInitiators.h"
-#endif
-
namespace WebCore {
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
@@ -81,46 +74,9 @@ enum XMLHttpRequestSendArrayBufferOrView {
XMLHttpRequestSendArrayBufferOrViewMax,
};
-struct XMLHttpRequestStaticData {
- WTF_MAKE_NONCOPYABLE(XMLHttpRequestStaticData); WTF_MAKE_FAST_ALLOCATED;
-public:
- 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("dnt");
- 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");
-}
-
-static bool isSetCookieHeader(const AtomicString& name)
-{
- return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
+static bool isSetCookieHeader(const String& name)
+{
+ return equalLettersIgnoringASCIICase(name, "set-cookie") || equalLettersIgnoringASCIICase(name, "set-cookie2");
}
static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
@@ -142,45 +98,26 @@ static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa
}
}
-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;
-}
-
static void logConsoleError(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->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message);
+ context->addConsoleMessage(MessageSource::JS, MessageLevel::Error, message);
}
-PassRefPtr<XMLHttpRequest> XMLHttpRequest::create(ScriptExecutionContext* context)
+Ref<XMLHttpRequest> XMLHttpRequest::create(ScriptExecutionContext& context)
{
- RefPtr<XMLHttpRequest> xmlHttpRequest(adoptRef(new XMLHttpRequest(context)));
+ Ref<XMLHttpRequest> xmlHttpRequest = adoptRef(*new XMLHttpRequest(context));
xmlHttpRequest->suspendIfNeeded();
-
- return xmlHttpRequest.release();
+ return xmlHttpRequest;
}
-XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
- : ActiveDOMObject(context)
+XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext& context)
+ : ActiveDOMObject(&context)
, m_async(true)
, m_includeCredentials(false)
-#if ENABLE(XHR_TIMEOUT)
- , m_timeoutMilliseconds(0)
-#endif
, m_state(UNSENT)
, m_createdDocument(false)
, m_error(false)
@@ -189,11 +126,16 @@ XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
, m_sameOriginRequest(true)
, m_receivedLength(0)
, m_lastSendLineNumber(0)
+ , m_lastSendColumnNumber(0)
, m_exceptionCode(0)
, m_progressEventThrottle(this)
, m_responseTypeCode(ResponseTypeDefault)
+ , m_responseCacheIsValid(false)
+ , m_resumeTimer(*this, &XMLHttpRequest::resumeTimerFired)
+ , m_dispatchErrorOnResuming(false)
+ , m_networkErrorTimer(*this, &XMLHttpRequest::networkErrorTimerFired)
+ , m_timeoutTimer(*this, &XMLHttpRequest::didReachTimeout)
{
- initializeXMLHttpRequestStaticData();
#ifndef NDEBUG
xmlHttpRequestCounter.increment();
#endif
@@ -208,8 +150,8 @@ XMLHttpRequest::~XMLHttpRequest()
Document* XMLHttpRequest::document() const
{
- ASSERT(scriptExecutionContext()->isDocument());
- return static_cast<Document*>(scriptExecutionContext());
+ ASSERT(scriptExecutionContext());
+ return downcast<Document>(scriptExecutionContext());
}
SecurityOrigin* XMLHttpRequest::securityOrigin() const
@@ -238,39 +180,49 @@ String XMLHttpRequest::responseText(ExceptionCode& ec)
ec = INVALID_STATE_ERR;
return "";
}
- return m_responseBuilder.toStringPreserveCapacity();
+ return responseTextIgnoringResponseType();
+}
+
+void XMLHttpRequest::didCacheResponseJSON()
+{
+ ASSERT(m_responseTypeCode == ResponseTypeJSON);
+ ASSERT(doneWithoutErrors());
+ m_responseCacheIsValid = true;
+ m_responseBuilder.clear();
}
Document* XMLHttpRequest::responseXML(ExceptionCode& ec)
{
if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
ec = INVALID_STATE_ERR;
- return 0;
+ return nullptr;
}
- if (m_error || m_state != DONE)
- return 0;
+ if (!doneWithoutErrors())
+ return nullptr;
if (!m_createdDocument) {
- bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html");
+ String mimeType = responseMIMEType();
+ bool isHTML = equalLettersIgnoringASCIICase(mimeType, "text/html");
// The W3C spec requires the final MIME type to be some valid XML type, or text/html.
// If it is text/html, then the responseType of "document" must have been supplied explicitly.
if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
|| (isHTML && m_responseTypeCode == ResponseTypeDefault)
|| scriptExecutionContext()->isWorkerGlobalScope()) {
- m_responseDocument = 0;
+ m_responseDocument = nullptr;
} else {
if (isHTML)
m_responseDocument = HTMLDocument::create(0, m_url);
else
- m_responseDocument = Document::create(0, m_url);
+ m_responseDocument = XMLDocument::create(0, m_url);
// FIXME: Set Last-Modified.
m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity());
- m_responseDocument->setSecurityOrigin(securityOrigin());
- m_responseDocument->setContextFeatures(document()->contextFeatures());
+ m_responseDocument->setSecurityOriginPolicy(scriptExecutionContext()->securityOriginPolicy());
+ m_responseDocument->overrideMIMEType(mimeType);
+
if (!m_responseDocument->wellFormed())
- m_responseDocument = 0;
+ m_responseDocument = nullptr;
}
m_createdDocument = true;
}
@@ -278,73 +230,61 @@ Document* XMLHttpRequest::responseXML(ExceptionCode& ec)
return m_responseDocument.get();
}
-Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec)
+Blob* XMLHttpRequest::responseBlob()
{
- if (m_responseTypeCode != ResponseTypeBlob) {
- ec = INVALID_STATE_ERR;
- return 0;
- }
- // We always return null before DONE.
- if (m_state != DONE)
- return 0;
+ ASSERT(m_responseTypeCode == ResponseTypeBlob);
+ ASSERT(doneWithoutErrors());
if (!m_responseBlob) {
- // FIXME: This causes two (or more) unnecessary copies of the data.
- // Chromium stores blob data in the browser process, so we're pulling the data
- // from the network only to copy it into the renderer to copy it back to the browser.
- // Ideally we'd get the blob/file-handle from the ResourceResponse directly
- // instead of copying the bytes. Embedders who store blob data in the
- // same process as WebCore would at least to teach BlobData to take
- // a SharedBuffer, even if they don't get the Blob from the network layer directly.
- OwnPtr<BlobData> blobData = BlobData::create();
- // If we errored out or got no data, we still return a blob, just an empty one.
- size_t size = 0;
if (m_binaryResponseBuilder) {
- RefPtr<RawData> rawData = RawData::create();
- size = m_binaryResponseBuilder->size();
- rawData->mutableData()->append(m_binaryResponseBuilder->data(), size);
- blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile);
- String normalizedContentType = Blob::normalizedContentType(responseMIMEType());
- blobData->setContentType(normalizedContentType); // responseMIMEType defaults to text/xml which may be incorrect.
- m_binaryResponseBuilder.clear();
+ // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient.
+ Vector<uint8_t> data;
+ data.append(m_binaryResponseBuilder->data(), m_binaryResponseBuilder->size());
+ String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect.
+ m_responseBlob = Blob::create(WTFMove(data), normalizedContentType);
+ m_binaryResponseBuilder = nullptr;
+ } else {
+ // If we errored out or got no data, we still return a blob, just an empty one.
+ m_responseBlob = Blob::create();
}
- m_responseBlob = Blob::create(blobData.release(), size);
}
return m_responseBlob.get();
}
-ArrayBuffer* XMLHttpRequest::responseArrayBuffer(ExceptionCode& ec)
+ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
{
- if (m_responseTypeCode != ResponseTypeArrayBuffer) {
- ec = INVALID_STATE_ERR;
- return 0;
- }
-
- if (m_state != DONE)
- return 0;
+ ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer);
+ ASSERT(doneWithoutErrors());
- 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) {
+ if (m_binaryResponseBuilder)
+ m_responseArrayBuffer = m_binaryResponseBuilder->createArrayBuffer();
+ else
+ m_responseArrayBuffer = ArrayBuffer::create(nullptr, 0);
+ m_binaryResponseBuilder = nullptr;
}
return m_responseArrayBuffer.get();
}
-#if ENABLE(XHR_TIMEOUT)
-void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionCode& ec)
+void XMLHttpRequest::setTimeout(unsigned timeout, ExceptionCode& ec)
{
- // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
- // XHR2 spec, 4.7.3. "This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative to the start of fetching."
if (scriptExecutionContext()->isDocument() && !m_async) {
logConsoleError(scriptExecutionContext(), "XMLHttpRequest.timeout cannot be set for synchronous HTTP(S) requests made from the window context.");
ec = INVALID_ACCESS_ERR;
return;
}
m_timeoutMilliseconds = timeout;
+ if (!m_timeoutTimer.isActive())
+ return;
+ if (!m_timeoutMilliseconds) {
+ m_timeoutTimer.stop();
+ return;
+ }
+ std::chrono::duration<double> interval = std::chrono::milliseconds { m_timeoutMilliseconds } - (std::chrono::steady_clock::now() - m_sendingTime);
+ m_timeoutTimer.startOneShot(std::max(0.0, interval.count()));
}
-#endif
void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode& ec)
{
@@ -367,6 +307,8 @@ void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode&
m_responseTypeCode = ResponseTypeDefault;
else if (responseType == "text")
m_responseTypeCode = ResponseTypeText;
+ else if (responseType == "json")
+ m_responseTypeCode = ResponseTypeJSON;
else if (responseType == "document")
m_responseTypeCode = ResponseTypeDocument;
else if (responseType == "blob")
@@ -384,6 +326,8 @@ String XMLHttpRequest::responseType()
return "";
case ResponseTypeText:
return "text";
+ case ResponseTypeJSON:
+ return "json";
case ResponseTypeDocument:
return "document";
case ResponseTypeBlob:
@@ -394,10 +338,24 @@ String XMLHttpRequest::responseType()
return "";
}
+String XMLHttpRequest::responseURL() const
+{
+ URL responseURL(m_response.url());
+ responseURL.removeFragmentIdentifier();
+
+ return responseURL.string();
+}
+
+void XMLHttpRequest::setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber)
+{
+ m_lastSendLineNumber = lineNumber;
+ m_lastSendColumnNumber = columnNumber;
+}
+
XMLHttpRequestUpload* XMLHttpRequest::upload()
{
if (!m_upload)
- m_upload = XMLHttpRequestUpload::create(this);
+ m_upload = std::make_unique<XMLHttpRequestUpload>(this);
return m_upload.get();
}
@@ -414,23 +372,21 @@ void XMLHttpRequest::callReadyStateChangeListener()
if (!scriptExecutionContext())
return;
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(scriptExecutionContext(), this);
+ // Check whether sending load and loadend events before sending readystatechange event, as it may change m_error/m_state values.
+ bool shouldSendLoadEvent = (m_state == DONE && !m_error);
if (m_async || (m_state <= OPENED || m_state == DONE))
- m_progressEventThrottle.dispatchReadyStateChangeEvent(XMLHttpRequestProgressEvent::create(eventNames().readystatechangeEvent), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
-
- InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
- if (m_state == DONE && !m_error) {
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(scriptExecutionContext(), this);
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
- InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
+ m_progressEventThrottle.dispatchReadyStateChangeEvent(Event::create(eventNames().readystatechangeEvent, false, false), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
+
+ if (shouldSendLoadEvent) {
+ m_progressEventThrottle.dispatchProgressEvent(eventNames().loadEvent);
+ m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent);
}
}
void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
{
- if (m_state > OPENED || m_loader) {
+ if (m_state > OPENED || m_sendFlag) {
ec = INVALID_STATE_ERR;
return;
}
@@ -440,41 +396,89 @@ void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
{
- return !equalIgnoringCase(method, "TRACE")
- && !equalIgnoringCase(method, "TRACK")
- && !equalIgnoringCase(method, "CONNECT");
+ return !equalLettersIgnoringASCIICase(method, "trace")
+ && !equalLettersIgnoringASCIICase(method, "track")
+ && !equalLettersIgnoringASCIICase(method, "connect");
}
String XMLHttpRequest::uppercaseKnownHTTPMethod(const String& method)
{
- if (equalIgnoringCase(method, "COPY") || equalIgnoringCase(method, "DELETE") || equalIgnoringCase(method, "GET")
- || equalIgnoringCase(method, "HEAD") || equalIgnoringCase(method, "INDEX") || equalIgnoringCase(method, "LOCK")
- || equalIgnoringCase(method, "M-POST") || equalIgnoringCase(method, "MKCOL") || equalIgnoringCase(method, "MOVE")
- || equalIgnoringCase(method, "OPTIONS") || equalIgnoringCase(method, "POST") || equalIgnoringCase(method, "PROPFIND")
- || equalIgnoringCase(method, "PROPPATCH") || equalIgnoringCase(method, "PUT") || equalIgnoringCase(method, "UNLOCK")) {
- return method.upper();
+ const char* const methods[] = { "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT" };
+ for (auto* value : methods) {
+ if (equalIgnoringASCIICase(method, value)) {
+ // Don't bother allocating a new string if it's already all uppercase.
+ if (method == value)
+ break;
+ return ASCIILiteral(value);
+ }
}
return method;
}
+static bool isForbiddenRequestHeader(const String& name)
+{
+ HTTPHeaderName headerName;
+ if (!findHTTPHeaderName(name, headerName))
+ return false;
+
+ switch (headerName) {
+ case HTTPHeaderName::AcceptCharset:
+ case HTTPHeaderName::AcceptEncoding:
+ case HTTPHeaderName::AccessControlRequestHeaders:
+ case HTTPHeaderName::AccessControlRequestMethod:
+ case HTTPHeaderName::Connection:
+ case HTTPHeaderName::ContentLength:
+ case HTTPHeaderName::ContentTransferEncoding:
+ case HTTPHeaderName::Cookie:
+ case HTTPHeaderName::Cookie2:
+ case HTTPHeaderName::Date:
+ case HTTPHeaderName::DNT:
+ case HTTPHeaderName::Expect:
+ case HTTPHeaderName::Host:
+ case HTTPHeaderName::KeepAlive:
+ case HTTPHeaderName::Origin:
+ case HTTPHeaderName::Referer:
+ case HTTPHeaderName::TE:
+ case HTTPHeaderName::Trailer:
+ case HTTPHeaderName::TransferEncoding:
+ case HTTPHeaderName::Upgrade:
+ case HTTPHeaderName::UserAgent:
+ case HTTPHeaderName::Via:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
{
- initializeXMLHttpRequestStaticData();
- return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
- && !name.startsWith(staticData->m_secHeaderPrefix, false);
+ if (isForbiddenRequestHeader(name))
+ return false;
+
+ if (name.startsWith("proxy-", false))
+ return false;
+
+ if (name.startsWith("sec-", false))
+ return false;
+
+ return true;
}
-void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionCode& ec)
+void XMLHttpRequest::open(const String& method, const URL& url, ExceptionCode& ec)
{
open(method, url, true, ec);
}
-void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
+void XMLHttpRequest::open(const String& method, const URL& url, bool async, ExceptionCode& ec)
{
- internalAbort();
+ if (!internalAbort())
+ return;
+
State previousState = m_state;
m_state = UNSENT;
m_error = false;
+ m_sendFlag = false;
m_uploadComplete = false;
// clear stuff from possible previous load
@@ -494,13 +498,7 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc
}
// FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
- bool shouldBypassMainWorldContentSecurityPolicy = false;
- if (scriptExecutionContext()->isDocument()) {
- Document* document = static_cast<Document*>(scriptExecutionContext());
- if (document->frame())
- shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()->shouldBypassMainWorldContentSecurityPolicy();
- }
- if (!shouldBypassMainWorldContentSecurityPolicy && !scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
+ if (!scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url, scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy())) {
// FIXME: Should this be throwing an exception?
ec = SECURITY_ERR;
return;
@@ -523,14 +521,12 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc
return;
}
-#if ENABLE(XHR_TIMEOUT)
// Similarly, timeouts are disabled for synchronous requests as well.
if (m_timeoutMilliseconds > 0) {
logConsoleError(scriptExecutionContext(), "Synchronous XMLHttpRequests must not have a timeout value set.");
ec = INVALID_ACCESS_ERR;
return;
}
-#endif
}
m_method = uppercaseKnownHTTPMethod(method);
@@ -549,17 +545,17 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc
m_state = OPENED;
}
-void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec)
+void XMLHttpRequest::open(const String& method, const URL& url, bool async, const String& user, ExceptionCode& ec)
{
- KURL urlWithCredentials(url);
+ URL 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)
+void XMLHttpRequest::open(const String& method, const URL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
{
- KURL urlWithCredentials(url);
+ URL urlWithCredentials(url);
urlWithCredentials.setUser(user);
urlWithCredentials.setPass(password);
@@ -571,10 +567,11 @@ bool XMLHttpRequest::initSend(ExceptionCode& ec)
if (!scriptExecutionContext())
return false;
- if (m_state != OPENED || m_loader) {
+ if (m_state != OPENED || m_sendFlag) {
ec = INVALID_STATE_ERR;
return false;
}
+ ASSERT(!m_loader);
m_error = false;
return true;
@@ -593,24 +590,21 @@ void XMLHttpRequest::send(Document* document, ExceptionCode& ec)
return;
if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
- String contentType = getRequestHeader("Content-Type");
- if (contentType.isEmpty()) {
+ if (!m_requestHeaders.contains(HTTPHeaderName::ContentType)) {
#if ENABLE(DASHBOARD_SUPPORT)
if (usesDashboardBackwardCompatibilityMode())
- setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
+ m_requestHeaders.set(HTTPHeaderName::ContentType, ASCIILiteral("application/x-www-form-urlencoded"));
else
#endif
// FIXME: this should include the charset used for encoding.
- setRequestHeaderInternal("Content-Type", "application/xml");
+ m_requestHeaders.set(HTTPHeaderName::ContentType, document->isHTMLDocument() ? ASCIILiteral("text/html;charset=UTF-8") : ASCIILiteral("application/xml;charset=UTF-8"));
}
// 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);
+ 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));
+ m_requestEntityBody = FormData::create(UTF8Encoding().encode(body, EntitiesForUnencodables));
if (m_upload)
m_requestEntityBody->setAlwaysStream(true);
}
@@ -624,20 +618,20 @@ void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
return;
if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
- String contentType = getRequestHeader("Content-Type");
- if (contentType.isEmpty()) {
+ String contentType = m_requestHeaders.get(HTTPHeaderName::ContentType);
+ if (contentType.isNull()) {
#if ENABLE(DASHBOARD_SUPPORT)
if (usesDashboardBackwardCompatibilityMode())
- setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
+ m_requestHeaders.set(HTTPHeaderName::ContentType, ASCIILiteral("application/x-www-form-urlencoded"));
else
#endif
- setRequestHeaderInternal("Content-Type", "application/xml");
+ m_requestHeaders.set(HTTPHeaderName::ContentType, ASCIILiteral("text/plain;charset=UTF-8"));
} else {
replaceCharsetInMediaType(contentType, "UTF-8");
- m_requestHeaders.set("Content-Type", contentType);
+ m_requestHeaders.set(HTTPHeaderName::ContentType, contentType);
}
- m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));
+ m_requestEntityBody = FormData::create(UTF8Encoding().encode(body, EntitiesForUnencodables));
if (m_upload)
m_requestEntityBody->setAlwaysStream(true);
}
@@ -651,25 +645,18 @@ void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
return;
if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
- const String& contentType = getRequestHeader("Content-Type");
- if (contentType.isEmpty()) {
+ if (!m_requestHeaders.contains(HTTPHeaderName::ContentType)) {
const String& blobType = body->type();
if (!blobType.isEmpty() && isValidContentType(blobType))
- setRequestHeaderInternal("Content-Type", blobType);
+ m_requestHeaders.set(HTTPHeaderName::ContentType, blobType);
else {
// From FileAPI spec, whenever media type cannot be determined, empty string must be returned.
- setRequestHeaderInternal("Content-Type", "");
+ m_requestHeaders.set(HTTPHeaderName::ContentType, emptyString());
}
}
- // FIXME: add support for uploading bundles.
m_requestEntityBody = FormData::create();
- if (body->isFile())
- m_requestEntityBody->appendFile(toFile(body)->path());
-#if ENABLE(BLOB)
- else
- m_requestEntityBody->appendBlob(body->url());
-#endif
+ m_requestEntityBody->appendBlob(body->url());
}
createRequest(ec);
@@ -683,15 +670,10 @@ void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec)
if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
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 = makeString("multipart/form-data; boundary=", m_requestEntityBody->boundary().data());
- setRequestHeaderInternal("Content-Type", contentType);
- }
+ if (!m_requestHeaders.contains(HTTPHeaderName::ContentType))
+ m_requestHeaders.set(HTTPHeaderName::ContentType, makeString("multipart/form-data; boundary=", m_requestEntityBody->boundary().data()));
}
createRequest(ec);
@@ -700,17 +682,13 @@ void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec)
void XMLHttpRequest::send(ArrayBuffer* body, ExceptionCode& ec)
{
String consoleMessage("ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.");
- scriptExecutionContext()->addConsoleMessage(JSMessageSource, WarningMessageLevel, consoleMessage);
-
- HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBuffer, XMLHttpRequestSendArrayBufferOrViewMax);
+ scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, consoleMessage);
sendBytesData(body->data(), body->byteLength(), ec);
}
void XMLHttpRequest::send(ArrayBufferView* body, ExceptionCode& ec)
{
- HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBufferView, XMLHttpRequestSendArrayBufferOrViewMax);
-
sendBytesData(body->baseAddress(), body->byteLength(), ec);
}
@@ -728,32 +706,25 @@ void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionCod
createRequest(ec);
}
-void XMLHttpRequest::sendFromInspector(PassRefPtr<FormData> formData, ExceptionCode& ec)
-{
- m_requestEntityBody = formData ? formData->deepCopy() : 0;
- createRequest(ec);
- m_exceptionCode = ec;
-}
-
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;
+ if (m_url.protocolIsBlob() && m_method != "GET") {
+ ec = NETWORK_ERR;
return;
}
-#endif
+
+ m_sendFlag = true;
// 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));
+ m_progressEventThrottle.dispatchProgressEvent(eventNames().loadstartEvent);
if (m_requestEntityBody && m_upload) {
uploadEvents = m_upload->hasEventListeners();
- m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
+ m_upload->dispatchProgressEvent(eventNames().loadstartEvent);
}
}
@@ -764,37 +735,37 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec)
m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
ResourceRequest request(m_url);
+ request.setRequester(ResourceRequest::Requester::XHR);
request.setHTTPMethod(m_method);
-#if PLATFORM(BLACKBERRY)
- request.setTargetType(ResourceRequest::TargetIsXHR);
-#endif
-
- InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_method, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m_requestHeaders, m_includeCredentials);
if (m_requestEntityBody) {
ASSERT(m_method != "GET");
ASSERT(m_method != "HEAD");
- request.setHTTPBody(m_requestEntityBody.release());
+ request.setHTTPBody(WTFMove(m_requestEntityBody));
}
- if (m_requestHeaders.size() > 0)
- request.addHTTPHeaderFields(m_requestHeaders);
+ if (!m_requestHeaders.isEmpty())
+ request.setHTTPHeaderFields(m_requestHeaders);
ThreadableLoaderOptions options;
- options.sendLoadCallbacks = SendCallbacks;
- options.sniffContent = DoNotSniffContent;
+ options.setSendLoadCallbacks(SendCallbacks);
+ options.setSniffContent(DoNotSniffContent);
options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
- options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
- options.crossOriginRequestPolicy = securityOrigin()->allowsCrossOriginRequests() ? UseAccessControl : DenyCrossOriginRequests;
+ options.setAllowCredentials((m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials);
+ options.setCredentialRequest(m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials);
+ options.crossOriginRequestPolicy = UseAccessControl;
options.securityOrigin = securityOrigin();
-#if ENABLE(RESOURCE_TIMING)
+ options.contentSecurityPolicyEnforcement = scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy() ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceConnectSrcDirective;
options.initiator = cachedResourceRequestInitiators().xmlhttprequest;
-#endif
-#if ENABLE(XHR_TIMEOUT)
- if (m_timeoutMilliseconds)
- request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0);
-#endif
+ if (m_timeoutMilliseconds) {
+ if (!m_async)
+ request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0);
+ else {
+ m_sendingTime = std::chrono::steady_clock::now();
+ m_timeoutTimer.startOneShot(std::chrono::milliseconds { m_timeoutMilliseconds });
+ }
+ }
m_exceptionCode = 0;
m_error = false;
@@ -803,16 +774,19 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec)
if (m_upload)
request.setReportUploadProgress(true);
- // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
+ // ThreadableLoader::create can return null here, for example if we're no longer attached to a page or if a content blocker blocks the load.
// 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);
+
+ // 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);
+ if (!m_loader) {
+ m_sendFlag = false;
+ m_timeoutTimer.stop();
+ m_networkErrorTimer.startOneShot(0);
}
} else {
InspectorInstrumentation::willLoadXHRSynchronously(scriptExecutionContext());
@@ -821,60 +795,60 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec)
}
if (!m_exceptionCode && m_error)
- m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
+ m_exceptionCode = 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;
+ Ref<XMLHttpRequest> protect(*this);
- internalAbort();
+ if (!internalAbort())
+ return;
clearResponseBuffers();
// Clear headers as required by the spec
m_requestHeaders.clear();
-
- if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
- m_state = UNSENT;
- else {
+ if ((m_state == OPENED && m_sendFlag) || m_state == HEADERS_RECEIVED || m_state == LOADING) {
ASSERT(!m_loader);
+ m_sendFlag = false;
changeState(DONE);
- m_state = UNSENT;
- }
-
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
- if (!m_uploadComplete) {
- m_uploadComplete = true;
- if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
+ dispatchErrorEvents(eventNames().abortEvent);
}
+ m_state = UNSENT;
}
-void XMLHttpRequest::internalAbort()
+bool 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 = nullptr;
- m_decoder = 0;
+ m_timeoutTimer.stop();
- InspectorInstrumentation::didFailXHRLoading(scriptExecutionContext(), this);
+ if (!m_loader)
+ return true;
- if (hadLoader)
- dropProtection();
+ // Cancelling m_loader may trigger a window.onload callback which can call open() on the same xhr.
+ // This would create internalAbort reentrant call.
+ // m_loader is set to null before being cancelled to exit early in any reentrant internalAbort() call.
+ RefPtr<ThreadableLoader> loader = m_loader.release();
+ loader->cancel();
+
+ // If window.onload callback calls open() and send() on the same xhr, m_loader is now set to a new value.
+ // The function calling internalAbort() should abort to let the open() and send() calls continue properly.
+ // We ask the function calling internalAbort() to exit by returning false.
+ // Save this information to a local variable since we are going to drop protection.
+ bool newLoadStarted = m_loader;
+
+ dropProtection();
+
+ return !newLoadStarted;
}
void XMLHttpRequest::clearResponse()
@@ -888,22 +862,24 @@ void XMLHttpRequest::clearResponseBuffers()
m_responseBuilder.clear();
m_responseEncoding = String();
m_createdDocument = false;
- m_responseDocument = 0;
- m_responseBlob = 0;
- m_binaryResponseBuilder.clear();
- m_responseArrayBuffer.clear();
+ m_responseDocument = nullptr;
+ m_responseBlob = nullptr;
+ m_binaryResponseBuilder = nullptr;
+ m_responseArrayBuffer = nullptr;
+ m_responseCacheIsValid = false;
}
void XMLHttpRequest::clearRequest()
{
m_requestHeaders.clear();
- m_requestEntityBody = 0;
+ m_requestEntityBody = nullptr;
}
void XMLHttpRequest::genericError()
{
clearResponse();
clearRequest();
+ m_sendFlag = false;
m_error = true;
changeState(DONE);
@@ -912,24 +888,20 @@ void XMLHttpRequest::genericError()
void XMLHttpRequest::networkError()
{
genericError();
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
- if (!m_uploadComplete) {
- m_uploadComplete = true;
- if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
- }
+ dispatchErrorEvents(eventNames().errorEvent);
internalAbort();
}
+void XMLHttpRequest::networkErrorTimerFired()
+{
+ networkError();
+ dropProtection();
+}
+
void XMLHttpRequest::abortError()
{
genericError();
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
- if (!m_uploadComplete) {
- m_uploadComplete = true;
- if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
- }
+ dispatchErrorEvents(eventNames().abortEvent);
}
void XMLHttpRequest::dropProtection()
@@ -940,21 +912,28 @@ void XMLHttpRequest::dropProtection()
// 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::VM* vm = scriptExecutionContext()->vm();
+ JSC::VM& vm = scriptExecutionContext()->vm();
JSC::JSLockHolder lock(vm);
- vm->heap.reportExtraMemoryCost(m_responseBuilder.length() * 2);
+ // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
+ // https://bugs.webkit.org/show_bug.cgi?id=142595
+ vm.heap.deprecatedReportExtraMemory(m_responseBuilder.length() * 2);
unsetPendingActivity(this);
}
-void XMLHttpRequest::overrideMimeType(const String& override)
+void XMLHttpRequest::overrideMimeType(const String& override, ExceptionCode& ec)
{
+ if (m_state == LOADING || m_state == DONE) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
m_mimeTypeOverride = override;
}
-void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& value, ExceptionCode& ec)
+void XMLHttpRequest::setRequestHeader(const String& name, const String& value, ExceptionCode& ec)
{
- if (m_state != OPENED || m_loader) {
+ if (m_state != OPENED || m_sendFlag) {
#if ENABLE(DASHBOARD_SUPPORT)
if (usesDashboardBackwardCompatibilityMode())
return;
@@ -964,7 +943,8 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
return;
}
- if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(value)) {
+ String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value);
+ if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(normalizedValue)) {
ec = SYNTAX_ERR;
return;
}
@@ -975,50 +955,36 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
return;
}
- setRequestHeaderInternal(name, value);
+ m_requestHeaders.add(name, normalizedValue);
}
-void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value)
+String XMLHttpRequest::getAllResponseHeaders() const
{
- HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
- if (!result.isNewEntry)
- result.iterator->value.append(", " + value);
-}
-
-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;
+ if (m_state < HEADERS_RECEIVED || m_error)
return "";
- }
StringBuilder stringBuilder;
HTTPHeaderSet accessControlExposeHeaderSet;
- parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
- HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
- for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
+ parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders), accessControlExposeHeaderSet);
+
+ for (const auto& header : m_response.httpHeaderFields()) {
// 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->key) && !securityOrigin()->canLoadLocalResources())
+ if (isSetCookieHeader(header.key) && !securityOrigin()->canLoadLocalResources())
continue;
- if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key))
+ if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(header.key) && !accessControlExposeHeaderSet.contains(header.key))
continue;
- stringBuilder.append(it->key);
+ stringBuilder.append(header.key);
stringBuilder.append(':');
stringBuilder.append(' ');
- stringBuilder.append(it->value);
+ stringBuilder.append(header.value);
stringBuilder.append('\r');
stringBuilder.append('\n');
}
@@ -1026,12 +992,10 @@ String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
return stringBuilder.toString();
}
-String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode& ec) const
+String XMLHttpRequest::getResponseHeader(const String& name) const
{
- if (m_state < HEADERS_RECEIVED) {
- ec = INVALID_STATE_ERR;
+ if (m_state < HEADERS_RECEIVED || m_error)
return String();
- }
// See comment in getAllResponseHeaders above.
if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
@@ -1040,7 +1004,7 @@ String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode
}
HTTPHeaderSet accessControlExposeHeaderSet;
- parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
+ parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders), accessControlExposeHeaderSet);
if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) {
logConsoleError(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
@@ -1054,7 +1018,7 @@ String XMLHttpRequest::responseMIMEType() const
String mimeType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
if (mimeType.isEmpty()) {
if (m_response.isHTTP())
- mimeType = extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
+ mimeType = extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType));
else
mimeType = m_response.mimeType();
}
@@ -1066,35 +1030,28 @@ String XMLHttpRequest::responseMIMEType() const
bool XMLHttpRequest::responseIsXML() const
{
- // FIXME: Remove the lower() call when DOMImplementation.isXMLMIMEType() is modified
- // to do case insensitive MIME type matching.
- return DOMImplementation::isXMLMIMEType(responseMIMEType().lower());
+ return DOMImplementation::isXMLMIMEType(responseMIMEType());
}
-int XMLHttpRequest::status(ExceptionCode& ec) const
+int XMLHttpRequest::status() const
{
+ if (m_state == UNSENT || m_state == OPENED || m_error)
+ return 0;
+
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
+String XMLHttpRequest::statusText() const
{
+ if (m_state == UNSENT || m_state == OPENED || m_error)
+ return String();
+
if (!m_response.httpStatusText().isNull())
return m_response.httpStatusText();
- if (m_state == OPENED) {
- // See comments in status() above.
- ec = INVALID_STATE_ERR;
- }
-
return String();
}
@@ -1106,23 +1063,24 @@ void XMLHttpRequest::didFail(const ResourceError& error)
return;
if (error.isCancellation()) {
- m_exceptionCode = XMLHttpRequestException::ABORT_ERR;
+ m_exceptionCode = ABORT_ERR;
abortError();
return;
}
-#if ENABLE(XHR_TIMEOUT)
+ // In case of worker sync timeouts.
if (error.isTimeout()) {
- didTimeout();
+ didReachTimeout();
return;
}
-#endif
// Network failures are already reported to Web Inspector by ResourceLoader.
- if (error.domain() == errorDomainWebKitInternal)
- logConsoleError(scriptExecutionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());
+ if (error.domain() == errorDomainWebKitInternal) {
+ String message = makeString("XMLHttpRequest cannot load ", error.failingURL().string(), ". ", error.localizedDescription());
+ logConsoleError(scriptExecutionContext(), message);
+ }
- m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
+ m_exceptionCode = NETWORK_ERR;
networkError();
}
@@ -1144,14 +1102,17 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
m_responseBuilder.shrinkToFit();
- InspectorInstrumentation::didFinishXHRLoading(scriptExecutionContext(), this, identifier, m_responseBuilder.toStringPreserveCapacity(), m_url, m_lastSendURL, m_lastSendLineNumber);
+ InspectorInstrumentation::didFinishXHRLoading(scriptExecutionContext(), this, identifier, m_responseBuilder.toStringPreserveCapacity(), m_url, m_lastSendURL, m_lastSendLineNumber, m_lastSendColumnNumber);
bool hadLoader = m_loader;
- m_loader = 0;
+ m_loader = nullptr;
+ m_sendFlag = false;
changeState(DONE);
m_responseEncoding = String();
- m_decoder = 0;
+ m_decoder = nullptr;
+
+ m_timeoutTimer.stop();
if (hadLoader)
dropProtection();
@@ -1163,12 +1124,13 @@ void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon
return;
if (m_uploadEventsAllowed)
- m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, true, bytesSent, totalBytesToBeSent));
-
+ m_upload->dispatchThrottledProgressEvent(true, bytesSent, totalBytesToBeSent);
if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
m_uploadComplete = true;
- if (m_uploadEventsAllowed)
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
+ if (m_uploadEventsAllowed) {
+ m_upload->dispatchProgressEvent(eventNames().loadEvent);
+ m_upload->dispatchProgressEvent(eventNames().loadendEvent);
+ }
}
}
@@ -1177,13 +1139,8 @@ void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const Resource
InspectorInstrumentation::didReceiveXHRResponse(scriptExecutionContext(), identifier);
m_response = response;
- if (!m_mimeTypeOverride.isEmpty()) {
- m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride);
- m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
- }
-
- if (m_responseEncoding.isEmpty())
- m_responseEncoding = response.textEncodingName();
+ if (!m_mimeTypeOverride.isEmpty())
+ m_response.setHTTPHeaderField(HTTPHeaderName::ContentType, m_mimeTypeOverride);
}
void XMLHttpRequest::didReceiveData(const char* data, int len)
@@ -1194,7 +1151,13 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
if (m_state < HEADERS_RECEIVED)
changeState(HEADERS_RECEIVED);
- bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeDocument;
+ // FIXME: Should we update "Content-Type" header field with m_mimeTypeOverride value in case it has changed since didReceiveResponse?
+ if (!m_mimeTypeOverride.isEmpty())
+ m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
+ if (m_responseEncoding.isEmpty())
+ m_responseEncoding = m_response.textEncodingName();
+
+ bool useDecoder = shouldDecodeResponse();
if (useDecoder && !m_decoder) {
if (!m_responseEncoding.isEmpty())
@@ -1204,7 +1167,7 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
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 (equalIgnoringCase(responseMIMEType(), "text/html"))
+ } else if (equalLettersIgnoringASCIICase(responseMIMEType(), "text/html"))
m_decoder = TextResourceDecoder::create("text/html", "UTF-8");
else
m_decoder = TextResourceDecoder::create("text/plain", "UTF-8");
@@ -1226,13 +1189,13 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
}
if (!m_error) {
- long long expectedLength = m_response.expectedContentLength();
m_receivedLength += len;
if (m_async) {
+ long long expectedLength = m_response.expectedContentLength();
bool lengthComputable = expectedLength > 0 && m_receivedLength <= expectedLength;
unsigned long long total = lengthComputable ? expectedLength : 0;
- m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, total);
+ m_progressEventThrottle.dispatchThrottledProgressEvent(lengthComputable, m_receivedLength, total);
}
if (m_state != LOADING)
@@ -1243,18 +1206,34 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
}
}
-#if ENABLE(XHR_TIMEOUT)
-void XMLHttpRequest::didTimeout()
+void XMLHttpRequest::dispatchErrorEvents(const AtomicString& type)
+{
+ if (!m_uploadComplete) {
+ m_uploadComplete = true;
+ if (m_upload && m_uploadEventsAllowed) {
+ m_upload->dispatchProgressEvent(eventNames().progressEvent);
+ m_upload->dispatchProgressEvent(type);
+ m_upload->dispatchProgressEvent(eventNames().loadendEvent);
+ }
+ }
+ m_progressEventThrottle.dispatchProgressEvent(eventNames().progressEvent);
+ m_progressEventThrottle.dispatchProgressEvent(type);
+ m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent);
+}
+
+void XMLHttpRequest::didReachTimeout()
{
// internalAbort() calls dropProtection(), which may release the last reference.
- RefPtr<XMLHttpRequest> protect(this);
- internalAbort();
+ Ref<XMLHttpRequest> protect(*this);
+ if (!internalAbort())
+ return;
clearResponse();
clearRequest();
+ m_sendFlag = false;
m_error = true;
- m_exceptionCode = XMLHttpRequestException::TIMEOUT_ERR;
+ m_exceptionCode = TIMEOUT_ERR;
if (!m_async) {
m_state = DONE;
@@ -1264,59 +1243,68 @@ void XMLHttpRequest::didTimeout()
changeState(DONE);
- if (!m_uploadComplete) {
- m_uploadComplete = true;
- if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
- }
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
+ dispatchErrorEvents(eventNames().timeoutEvent);
}
-#endif
-bool XMLHttpRequest::canSuspend() const
+bool XMLHttpRequest::canSuspendForDocumentSuspension() const
{
- return !m_loader;
+ // If the load event has not fired yet, cancelling the load in suspend() may cause
+ // the load event to be fired and arbitrary JS execution, which would be unsafe.
+ // Therefore, we prevent suspending in this case.
+ return document()->loadEventFinished();
}
-void XMLHttpRequest::suspend(ReasonForSuspension)
+const char* XMLHttpRequest::activeDOMObjectName() const
{
- m_progressEventThrottle.suspend();
+ return "XMLHttpRequest";
}
-void XMLHttpRequest::resume()
+void XMLHttpRequest::suspend(ReasonForSuspension reason)
{
- m_progressEventThrottle.resume();
-}
+ m_progressEventThrottle.suspend();
-void XMLHttpRequest::stop()
-{
- internalAbort();
-}
+ if (m_resumeTimer.isActive()) {
+ m_resumeTimer.stop();
+ m_dispatchErrorOnResuming = true;
+ }
-void XMLHttpRequest::contextDestroyed()
-{
- ASSERT(!m_loader);
- ActiveDOMObject::contextDestroyed();
+ if (reason == ActiveDOMObject::PageCache && m_loader) {
+ // Going into PageCache, abort the request and dispatch a network error on resuming.
+ genericError();
+ m_dispatchErrorOnResuming = true;
+ bool aborted = internalAbort();
+ // It should not be possible to restart the load when aborting in suspend() because
+ // we are not allowed to execute in JS in suspend().
+ ASSERT_UNUSED(aborted, aborted);
+ }
}
-const AtomicString& XMLHttpRequest::interfaceName() const
+void XMLHttpRequest::resume()
{
- return eventNames().interfaceForXMLHttpRequest;
+ m_progressEventThrottle.resume();
+
+ // We are not allowed to execute arbitrary JS in resume() so dispatch
+ // the error event in a timer.
+ if (m_dispatchErrorOnResuming && !m_resumeTimer.isActive())
+ m_resumeTimer.startOneShot(0);
}
-ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
+void XMLHttpRequest::resumeTimerFired()
{
- return ActiveDOMObject::scriptExecutionContext();
+ ASSERT(m_dispatchErrorOnResuming);
+ m_dispatchErrorOnResuming = false;
+ dispatchErrorEvents(eventNames().errorEvent);
}
-EventTargetData* XMLHttpRequest::eventTargetData()
+void XMLHttpRequest::stop()
{
- return &m_eventTargetData;
+ internalAbort();
}
-EventTargetData* XMLHttpRequest::ensureEventTargetData()
+void XMLHttpRequest::contextDestroyed()
{
- return &m_eventTargetData;
+ ASSERT(!m_loader);
+ ActiveDOMObject::contextDestroyed();
}
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequest.h b/Source/WebCore/xml/XMLHttpRequest.h
index cb0791753..6e9df36ed 100644
--- a/Source/WebCore/xml/XMLHttpRequest.h
+++ b/Source/WebCore/xml/XMLHttpRequest.h
@@ -24,17 +24,20 @@
#include "ActiveDOMObject.h"
#include "EventListener.h"
-#include "EventNames.h"
-#include "EventTarget.h"
#include "FormData.h"
#include "ResourceResponse.h"
#include "ScriptWrappable.h"
#include "ThreadableLoaderClient.h"
+#include "XMLHttpRequestEventTarget.h"
#include "XMLHttpRequestProgressEventThrottle.h"
-#include <wtf/OwnPtr.h>
#include <wtf/text/AtomicStringHash.h>
#include <wtf/text/StringBuilder.h>
+namespace JSC {
+class ArrayBuffer;
+class ArrayBufferView;
+}
+
namespace WebCore {
class Blob;
@@ -46,11 +49,11 @@ class SharedBuffer;
class TextResourceDecoder;
class ThreadableLoader;
-class XMLHttpRequest : public ScriptWrappable, public RefCounted<XMLHttpRequest>, public EventTarget, private ThreadableLoaderClient, public ActiveDOMObject {
+class XMLHttpRequest final : public RefCounted<XMLHttpRequest>, public XMLHttpRequestEventTarget, private ThreadableLoaderClient, public ActiveDOMObject {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<XMLHttpRequest> create(ScriptExecutionContext*);
- ~XMLHttpRequest();
+ static Ref<XMLHttpRequest> create(ScriptExecutionContext&);
+ WEBCORE_EXPORT ~XMLHttpRequest();
// These exact numeric values are important because JS expects them.
enum State {
@@ -63,57 +66,56 @@ public:
enum ResponseTypeCode {
ResponseTypeDefault,
- ResponseTypeText,
+ ResponseTypeText,
+ ResponseTypeJSON,
ResponseTypeDocument,
+
+ // Binary format
ResponseTypeBlob,
ResponseTypeArrayBuffer
};
+ static const ResponseTypeCode FirstBinaryResponseType = ResponseTypeBlob;
- virtual void contextDestroyed();
-#if ENABLE(XHR_TIMEOUT)
- virtual void didTimeout();
-#endif
- virtual bool canSuspend() const;
- virtual void suspend(ReasonForSuspension);
- virtual void resume();
- virtual void stop();
+ virtual void didReachTimeout();
- virtual const AtomicString& interfaceName() const;
- virtual ScriptExecutionContext* scriptExecutionContext() const;
+ virtual EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestEventTargetInterfaceType; }
+ virtual ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); }
- const KURL& url() const { return m_url; }
- String statusText(ExceptionCode&) const;
- int status(ExceptionCode&) const;
+ const URL& url() const { return m_url; }
+ String statusText() const;
+ int status() const;
State readyState() const;
bool withCredentials() const { return m_includeCredentials; }
void setWithCredentials(bool, ExceptionCode&);
- 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 open(const String& method, const URL&, ExceptionCode&);
+ void open(const String& method, const URL&, bool async, ExceptionCode&);
+ void open(const String& method, const URL&, bool async, const String& user, ExceptionCode&);
+ void open(const String& method, const URL&, 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&);
- void send(ArrayBuffer*, ExceptionCode&);
- void send(ArrayBufferView*, ExceptionCode&);
+ void send(JSC::ArrayBuffer*, ExceptionCode&);
+ void send(JSC::ArrayBufferView*, ExceptionCode&);
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;
+ void setRequestHeader(const String& name, const String& value, ExceptionCode&);
+ void overrideMimeType(const String& override, ExceptionCode&);
+ bool doneWithoutErrors() const { return !m_error && m_state == DONE; }
+ String getAllResponseHeaders() const;
+ String getResponseHeader(const String& name) const;
String responseText(ExceptionCode&);
+ String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); }
+ String responseMIMEType() const;
Document* responseXML(ExceptionCode&);
Document* optionalResponseXML() const { return m_responseDocument.get(); }
- Blob* responseBlob(ExceptionCode&);
+ Blob* responseBlob();
Blob* optionalResponseBlob() const { return m_responseBlob.get(); }
-#if ENABLE(XHR_TIMEOUT)
- unsigned long timeout() const { return m_timeoutMilliseconds; }
- void setTimeout(unsigned long timeout, ExceptionCode&);
-#endif
+ unsigned timeout() const { return m_timeoutMilliseconds; }
+ void setTimeout(unsigned timeout, ExceptionCode&);
- void sendFromInspector(PassRefPtr<FormData>, ExceptionCode&);
+ bool responseCacheIsValid() const { return m_responseCacheIsValid; }
+ void didCacheResponseJSON();
// Expose HTTP validation methods for other untrusted requests.
static bool isAllowedHTTPMethod(const String&);
@@ -123,38 +125,37 @@ public:
void setResponseType(const String&, ExceptionCode&);
String responseType();
ResponseTypeCode responseTypeCode() const { return m_responseTypeCode; }
-
+
+ String responseURL() const;
+
// response attribute has custom getter.
- ArrayBuffer* responseArrayBuffer(ExceptionCode&);
- ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); }
+ JSC::ArrayBuffer* responseArrayBuffer();
+ JSC::ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); }
- void setLastSendLineNumber(unsigned lineNumber) { m_lastSendLineNumber = lineNumber; }
+ void setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber);
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(loadend);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
-#if ENABLE(XHR_TIMEOUT)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(timeout);
-#endif
+ const ResourceResponse& resourceResponse() const { return m_response; }
using RefCounted<XMLHttpRequest>::ref;
using RefCounted<XMLHttpRequest>::deref;
private:
- XMLHttpRequest(ScriptExecutionContext*);
+ explicit XMLHttpRequest(ScriptExecutionContext&);
- virtual void refEventTarget() { ref(); }
- virtual void derefEventTarget() { deref(); }
- virtual EventTargetData* eventTargetData();
- virtual EventTargetData* ensureEventTargetData();
+ // ActiveDOMObject
+ void contextDestroyed() override;
+ bool canSuspendForDocumentSuspension() const override;
+ void suspend(ReasonForSuspension) override;
+ void resume() override;
+ void stop() override;
+ const char* activeDOMObjectName() const override;
+
+ virtual void refEventTarget() override { ref(); }
+ virtual void derefEventTarget() override { deref(); }
Document* document() const;
SecurityOrigin* securityOrigin() const;
@@ -163,26 +164,26 @@ private:
bool usesDashboardBackwardCompatibilityMode() const;
#endif
- virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
- virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
- virtual void didReceiveData(const char* data, int dataLength);
- virtual void didFinishLoading(unsigned long identifier, double finishTime);
- virtual void didFail(const ResourceError&);
- virtual void didFailRedirectCheck();
+ virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
+ virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override;
+ virtual void didReceiveData(const char* data, int dataLength) override;
+ virtual void didFinishLoading(unsigned long identifier, double finishTime) override;
+ virtual void didFail(const ResourceError&) override;
+ virtual void didFailRedirectCheck() override;
- String responseMIMEType() const;
bool responseIsXML() const;
bool initSend(ExceptionCode&);
void sendBytesData(const void*, size_t, ExceptionCode&);
- String getRequestHeader(const AtomicString& name) const;
- void setRequestHeaderInternal(const AtomicString& name, const String& value);
-
void changeState(State newState);
void callReadyStateChangeListener();
void dropProtection();
- void internalAbort();
+
+ // Returns false when cancelling the loader within internalAbort() triggers an event whose callback creates a new loader.
+ // In that case, the function calling internalAbort should exit.
+ bool internalAbort();
+
void clearResponse();
void clearResponseBuffers();
void clearRequest();
@@ -193,22 +194,26 @@ private:
void networkError();
void abortError();
- OwnPtr<XMLHttpRequestUpload> m_upload;
+ bool shouldDecodeResponse() const { return m_responseTypeCode < FirstBinaryResponseType; }
+
+ void dispatchErrorEvents(const AtomicString&);
+
+ void resumeTimerFired();
+
+ std::unique_ptr<XMLHttpRequestUpload> m_upload;
- KURL m_url;
+ URL m_url;
String m_method;
HTTPHeaderMap m_requestHeaders;
RefPtr<FormData> m_requestEntityBody;
String m_mimeTypeOverride;
bool m_async;
bool m_includeCredentials;
-#if ENABLE(XHR_TIMEOUT)
- unsigned long m_timeoutMilliseconds;
-#endif
RefPtr<Blob> m_responseBlob;
RefPtr<ThreadableLoader> m_loader;
State m_state;
+ bool m_sendFlag { false };
ResourceResponse m_response;
String m_responseEncoding;
@@ -216,11 +221,11 @@ private:
RefPtr<TextResourceDecoder> m_decoder;
StringBuilder m_responseBuilder;
- mutable bool m_createdDocument;
- mutable RefPtr<Document> m_responseDocument;
+ bool m_createdDocument;
+ RefPtr<Document> m_responseDocument;
RefPtr<SharedBuffer> m_binaryResponseBuilder;
- mutable RefPtr<ArrayBuffer> m_responseArrayBuffer;
+ RefPtr<JSC::ArrayBuffer> m_responseArrayBuffer;
bool m_error;
@@ -233,15 +238,25 @@ private:
long long m_receivedLength;
unsigned m_lastSendLineNumber;
+ unsigned m_lastSendColumnNumber;
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;
+ bool m_responseCacheIsValid;
+
+ Timer m_resumeTimer;
+ bool m_dispatchErrorOnResuming;
+
+ Timer m_networkErrorTimer;
+ void networkErrorTimerFired();
+
+ unsigned m_timeoutMilliseconds { 0 };
+ std::chrono::steady_clock::time_point m_sendingTime;
+ Timer m_timeoutTimer;
};
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequest.idl b/Source/WebCore/xml/XMLHttpRequest.idl
index 5965121fc..9cde17835 100644
--- a/Source/WebCore/xml/XMLHttpRequest.idl
+++ b/Source/WebCore/xml/XMLHttpRequest.idl
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -31,8 +31,7 @@ enum XMLHttpRequestResponseType {
"arraybuffer",
"blob",
"document",
-// FIXME: enable once support for json responseText is completed. (bug #73648)
-// "json",
+ "json",
"text"
};
@@ -42,21 +41,10 @@ enum XMLHttpRequestResponseType {
Constructor,
ConstructorCallWith=ScriptExecutionContext,
JSCustomMarkFunction,
- EventTarget,
- JSNoStaticTables
-] interface XMLHttpRequest {
- // From XMLHttpRequestEventTarget
- // event handler attributes
- attribute EventListener onabort;
- attribute EventListener onerror;
- attribute EventListener onload;
- attribute EventListener onloadend;
- attribute EventListener onloadstart;
- attribute EventListener onprogress;
- [Conditional=XHR_TIMEOUT] attribute EventListener ontimeout;
-
- // event handler attributes
- attribute EventListener onreadystatechange;
+ JSGenerateToNativeObject,
+ JSGenerateToJSObject,
+] interface XMLHttpRequest : XMLHttpRequestEventTarget {
+ attribute EventHandler onreadystatechange;
// state
const unsigned short UNSENT = 0;
@@ -65,7 +53,7 @@ enum XMLHttpRequestResponseType {
const unsigned short LOADING = 3;
const unsigned short DONE = 4;
- [Conditional=XHR_TIMEOUT, SetterRaisesException] attribute unsigned long timeout;
+ [SetterRaisesException] attribute unsigned long timeout;
readonly attribute unsigned short readyState;
[SetterRaisesException] attribute boolean withCredentials;
@@ -81,26 +69,18 @@ enum XMLHttpRequestResponseType {
readonly attribute XMLHttpRequestUpload upload;
// response
- [TreatReturnedNullStringAs=Undefined, RaisesException] DOMString getAllResponseHeaders();
- [TreatReturnedNullStringAs=Null, RaisesException] DOMString getResponseHeader(DOMString header);
+ [TreatReturnedNullStringAs=Undefined] DOMString getAllResponseHeaders();
+ [TreatReturnedNullStringAs=Null] DOMString getResponseHeader(DOMString header);
[GetterRaisesException, CustomGetter] readonly attribute DOMString responseText; // The custom getter implements TreatReturnedNullStringAs=Null
[GetterRaisesException] readonly attribute Document responseXML;
[SetterRaisesException] attribute XMLHttpRequestResponseType responseType;
- [GetterRaisesException, CustomGetter] readonly attribute Object response;
+ [GetterRaisesException, CachedAttribute, CustomGetter] readonly attribute Object response;
- [GetterRaisesException] readonly attribute unsigned short status;
- [GetterRaisesException] readonly attribute DOMString statusText;
+ readonly attribute unsigned short status;
+ readonly attribute DOMString statusText;
+ readonly attribute DOMString responseURL;
// Extension
- void overrideMimeType(DOMString override);
-
- // EventTarget interface
- void addEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- void removeEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- [RaisesException] boolean dispatchEvent(Event evt);
+ [RaisesException] void overrideMimeType(DOMString override);
};
diff --git a/Source/WebCore/xml/XMLHttpRequestEventTarget.h b/Source/WebCore/xml/XMLHttpRequestEventTarget.h
new file mode 100644
index 000000000..bfe1675f7
--- /dev/null
+++ b/Source/WebCore/xml/XMLHttpRequestEventTarget.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 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. 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 INC. 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 XMLHttpRequestEventTarget_h
+#define XMLHttpRequestEventTarget_h
+
+#include "EventTarget.h"
+
+namespace WebCore {
+
+class XMLHttpRequestEventTarget : public EventTargetWithInlineData {
+};
+
+}
+
+#endif // XMLHttpRequestEventTarget_h
diff --git a/Source/WebCore/xml/XMLHttpRequestException.idl b/Source/WebCore/xml/XMLHttpRequestEventTarget.idl
index 540f2825b..19c6551da 100644
--- a/Source/WebCore/xml/XMLHttpRequestException.idl
+++ b/Source/WebCore/xml/XMLHttpRequestEventTarget.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -27,22 +27,14 @@
*/
[
- JSNoStaticTables,
- DoNotCheckConstants,
- ImplementationLacksVTable
-] exception 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
- [NotEnumerable] DOMString toString();
-#endif
-
- // XMLHttpRequestExceptionCode
- const unsigned short NETWORK_ERR = 101;
- const unsigned short ABORT_ERR = 102;
+ GlobalContext=DOMWindow&WorkerGlobalScope,
+ SuppressToJSObject,
+] interface XMLHttpRequestEventTarget : EventTarget {
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onload;
+ attribute EventHandler ontimeout;
+ attribute EventHandler onloadend;
};
-
diff --git a/Source/WebCore/xml/XMLHttpRequestException.cpp b/Source/WebCore/xml/XMLHttpRequestException.cpp
deleted file mode 100644
index b8cb2f399..000000000
--- a/Source/WebCore/xml/XMLHttpRequestException.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2011 Google 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 GOOGLE 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 "XMLHttpRequestException.h"
-
-namespace WebCore {
-
-static struct XMLHttpRequestExceptionNameDescription {
- const char* const name;
- const char* const description;
-} exceptions[] = {
- { "NETWORK_ERR", "A network error occurred in synchronous requests." },
- { "ABORT_ERR", "The user aborted a request in synchronous requests." },
- { "TIMEOUT_ERR", "A timeout error occured in synchronous requests." }
-};
-
-bool XMLHttpRequestException::initializeDescription(ExceptionCode ec, ExceptionCodeDescription* description)
-{
- if (ec < XMLHttpRequestExceptionOffset || ec > XMLHttpRequestExceptionMax)
- return false;
-
- description->typeName = "XMLHttpRequest";
- description->code = ec - XMLHttpRequestExceptionOffset;
- description->type = XMLHttpRequestExceptionType;
-
- size_t tableSize = WTF_ARRAY_LENGTH(exceptions);
- size_t tableIndex = ec - NETWORK_ERR;
-
- description->name = tableIndex < tableSize ? exceptions[tableIndex].name : 0;
- description->description = tableIndex < tableSize ? exceptions[tableIndex].description : 0;
-
- return true;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestException.h b/Source/WebCore/xml/XMLHttpRequestException.h
deleted file mode 100644
index 940e30107..000000000
--- a/Source/WebCore/xml/XMLHttpRequestException.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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,
- TIMEOUT_ERR
- };
-
- static bool initializeDescription(ExceptionCode, ExceptionCodeDescription*);
-
-private:
- explicit XMLHttpRequestException(const ExceptionCodeDescription& description)
- : ExceptionBase(description)
- {
- }
-};
-
-} // namespace WebCore
-
-#endif // XMLHttpRequestException_h
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEvent.h b/Source/WebCore/xml/XMLHttpRequestProgressEvent.h
index d887a2694..f0cb0f4af 100644
--- a/Source/WebCore/xml/XMLHttpRequestProgressEvent.h
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEvent.h
@@ -11,10 +11,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -27,30 +27,23 @@
#ifndef XMLHttpRequestProgressEvent_h
#define XMLHttpRequestProgressEvent_h
-#include "EventNames.h"
#include "ProgressEvent.h"
namespace WebCore {
class XMLHttpRequestProgressEvent : public ProgressEvent {
public:
- static PassRefPtr<XMLHttpRequestProgressEvent> create()
+ static Ref<XMLHttpRequestProgressEvent> create(const AtomicString& type, bool lengthComputable = false, unsigned long long loaded = 0, unsigned long long total = 0)
{
- return adoptRef(new XMLHttpRequestProgressEvent);
+ return adoptRef(*new XMLHttpRequestProgressEvent(type, lengthComputable, loaded, total));
}
- 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(); }
- virtual const AtomicString& interfaceName() const { return eventNames().interfaceForXMLHttpRequestProgressEvent; }
+ virtual EventInterface eventInterface() const { return XMLHttpRequestProgressEventInterfaceType; }
private:
- XMLHttpRequestProgressEvent() { }
XMLHttpRequestProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
: ProgressEvent(type, lengthComputable, loaded, total)
{
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl b/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl
index 5ed5c2127..2116271c9 100644
--- a/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEvent.idl
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -24,7 +24,6 @@
*/
[
- JSNoStaticTables
// We should also inherit from LSProgressEvent when the idl is added.
] interface XMLHttpRequestProgressEvent : ProgressEvent {
readonly attribute unsigned long long position;
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
index 836f481c6..360000783 100644
--- a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
@@ -36,10 +36,12 @@ const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchin
XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
: m_target(target)
+ , m_hasThrottledProgressEvent(false)
+ , m_lengthComputable(false)
, m_loaded(0)
, m_total(0)
, m_deferEvents(false)
- , m_dispatchDeferredEventsTimer(this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents)
+ , m_dispatchDeferredEventsTimer(*this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents)
{
ASSERT(target);
}
@@ -48,8 +50,15 @@ XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle()
{
}
-void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
+void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
{
+ m_lengthComputable = lengthComputable;
+ m_loaded = loaded;
+ m_total = total;
+
+ if (!m_target->hasEventListeners(eventNames().progressEvent))
+ return;
+
if (m_deferEvents) {
// Only store the latest progress event while suspended.
m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total);
@@ -57,25 +66,22 @@ void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthCompu
}
if (!isActive()) {
- // The timer is not active so the least frequent event for now is every byte.
- // Just go ahead and dispatch the event.
+ // The timer is not active so the least frequent event for now is every byte. Just dispatch the event.
- // We should not have any pending loaded & total information from a previous run.
- ASSERT(!m_loaded);
- ASSERT(!m_total);
+ // We should not have any throttled progress event.
+ ASSERT(!m_hasThrottledProgressEvent);
dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
startRepeating(minimumProgressEventDispatchingIntervalInSeconds);
+ m_hasThrottledProgressEvent = false;
return;
}
// The timer is already active so minimumProgressEventDispatchingIntervalInSeconds is the least frequent event.
- m_lengthComputable = lengthComputable;
- m_loaded = loaded;
- m_total = total;
+ m_hasThrottledProgressEvent = true;
}
-void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(PassRefPtr<Event> event, ProgressEventAction progressEventAction)
+void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(Event& event, ProgressEventAction progressEventAction)
{
if (progressEventAction == FlushProgressEvent)
flushProgressEvent();
@@ -83,11 +89,10 @@ void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(PassRefP
dispatchEvent(event);
}
-void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event)
+void XMLHttpRequestProgressEventThrottle::dispatchEvent(Event& event)
{
- ASSERT(event);
if (m_deferEvents) {
- if (m_deferredEvents.size() > 1 && event->type() == eventNames().readystatechangeEvent && event->type() == m_deferredEvents.last()->type()) {
+ if (m_deferredEvents.size() > 1 && event.type() == eventNames().readystatechangeEvent && event.type() == m_deferredEvents.last()->type()) {
// Readystatechange events are state-less so avoid repeating two identical events in a row on resume.
return;
}
@@ -96,58 +101,56 @@ void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event)
m_target->dispatchEvent(event);
}
-void XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadEnd(PassRefPtr<Event> event)
+void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString& type)
{
- ASSERT(event->type() == eventNames().loadEvent || event->type() == eventNames().abortEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().timeoutEvent);
+ ASSERT(type == eventNames().loadstartEvent || type == eventNames().progressEvent || type == eventNames().loadEvent || type == eventNames().loadendEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);
- dispatchEvent(event);
- dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
+ if (type == eventNames().loadstartEvent) {
+ m_lengthComputable = false;
+ m_loaded = 0;
+ m_total = 0;
+ }
+
+ if (m_target->hasEventListeners(type))
+ dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
}
void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
{
if (m_deferEvents && m_deferredProgressEvent) {
// Move the progress event to the queue, to get it in the right order on resume.
- m_deferredEvents.append(m_deferredProgressEvent);
- m_deferredProgressEvent = 0;
+ m_deferredEvents.append(m_deferredProgressEvent.releaseNonNull());
return;
}
if (!hasEventToDispatch())
return;
-
- PassRefPtr<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
- m_loaded = 0;
- m_total = 0;
+ Ref<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
+ m_hasThrottledProgressEvent = false;
// We stop the timer as this is called when no more events are supposed to occur.
stop();
- dispatchEvent(event);
+ dispatchEvent(WTFMove(event));
}
-void XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents(Timer<XMLHttpRequestProgressEventThrottle>* timer)
+void XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents()
{
- ASSERT_UNUSED(timer, timer == &m_dispatchDeferredEventsTimer);
ASSERT(m_deferEvents);
m_deferEvents = false;
// Take over the deferred events before dispatching them which can potentially add more.
- Vector<RefPtr<Event> > deferredEvents;
- m_deferredEvents.swap(deferredEvents);
+ auto deferredEvents = WTFMove(m_deferredEvents);
- RefPtr<Event> deferredProgressEvent = m_deferredProgressEvent;
- m_deferredProgressEvent = 0;
+ RefPtr<Event> deferredProgressEvent = WTFMove(m_deferredProgressEvent);
- Vector<RefPtr<Event> >::const_iterator it = deferredEvents.begin();
- const Vector<RefPtr<Event> >::const_iterator end = deferredEvents.end();
- for (; it != end; ++it)
- dispatchEvent(*it);
+ for (auto& deferredEvent : deferredEvents)
+ dispatchEvent(deferredEvent);
// The progress event will be in the m_deferredEvents vector if the load was finished while suspended.
// If not, just send the most up-to-date progress on resume.
if (deferredProgressEvent)
- dispatchEvent(deferredProgressEvent);
+ dispatchEvent(*deferredProgressEvent);
}
void XMLHttpRequestProgressEventThrottle::fired()
@@ -160,13 +163,12 @@ void XMLHttpRequestProgressEventThrottle::fired()
}
dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
- m_total = 0;
- m_loaded = 0;
+ m_hasThrottledProgressEvent = false;
}
bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const
{
- return (m_total || m_loaded) && isActive();
+ return m_hasThrottledProgressEvent && isActive();
}
void XMLHttpRequestProgressEventThrottle::suspend()
@@ -187,16 +189,14 @@ void XMLHttpRequestProgressEventThrottle::suspend()
// just defer it.
if (hasEventToDispatch()) {
m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
- m_total = 0;
- m_loaded = 0;
+ m_hasThrottledProgressEvent = false;
}
stop();
}
void XMLHttpRequestProgressEventThrottle::resume()
{
- ASSERT(!m_loaded);
- ASSERT(!m_total);
+ ASSERT(!m_hasThrottledProgressEvent);
if (m_deferredEvents.isEmpty() && !m_deferredProgressEvent) {
m_deferEvents = false;
diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h
index d967985a0..c1009e50d 100644
--- a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h
+++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h
@@ -28,8 +28,8 @@
#define XMLHttpRequestProgressEventThrottle_h
#include "Timer.h"
-#include "wtf/PassRefPtr.h"
#include "wtf/Vector.h"
+#include <wtf/Forward.h>
namespace WebCore {
@@ -48,10 +48,9 @@ public:
explicit XMLHttpRequestProgressEventThrottle(EventTarget*);
virtual ~XMLHttpRequestProgressEventThrottle();
- void dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
- void dispatchReadyStateChangeEvent(PassRefPtr<Event>, ProgressEventAction = DoNotFlushProgressEvent);
- void dispatchEvent(PassRefPtr<Event>);
- void dispatchEventAndLoadEnd(PassRefPtr<Event>);
+ void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
+ void dispatchReadyStateChangeEvent(Event&, ProgressEventAction = DoNotFlushProgressEvent);
+ void dispatchProgressEvent(const AtomicString&);
void suspend();
void resume();
@@ -60,22 +59,24 @@ private:
static const double minimumProgressEventDispatchingIntervalInSeconds;
virtual void fired();
- void dispatchDeferredEvents(Timer<XMLHttpRequestProgressEventThrottle>*);
+ void dispatchDeferredEvents();
void flushProgressEvent();
+ void dispatchEvent(Event&);
bool hasEventToDispatch() const;
// Weak pointer to our XMLHttpRequest object as it is the one holding us.
EventTarget* m_target;
+ bool m_hasThrottledProgressEvent;
bool m_lengthComputable;
unsigned long long m_loaded;
unsigned long long m_total;
bool m_deferEvents;
RefPtr<Event> m_deferredProgressEvent;
- Vector<RefPtr<Event> > m_deferredEvents;
- Timer<XMLHttpRequestProgressEventThrottle> m_dispatchDeferredEventsTimer;
+ Vector<Ref<Event>> m_deferredEvents;
+ Timer m_dispatchDeferredEventsTimer;
};
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.cpp b/Source/WebCore/xml/XMLHttpRequestUpload.cpp
index 60627a0e0..3ec54185e 100644
--- a/Source/WebCore/xml/XMLHttpRequestUpload.cpp
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.cpp
@@ -27,9 +27,6 @@
#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>
@@ -38,37 +35,33 @@ namespace WebCore {
XMLHttpRequestUpload::XMLHttpRequestUpload(XMLHttpRequest* xmlHttpRequest)
: m_xmlHttpRequest(xmlHttpRequest)
+ , m_lengthComputable(false)
+ , m_loaded(0)
+ , m_total(0)
{
}
-const AtomicString& XMLHttpRequestUpload::interfaceName() const
+void XMLHttpRequestUpload::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
{
- return eventNames().interfaceForXMLHttpRequestUpload;
-}
-
-ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
-{
- return m_xmlHttpRequest->scriptExecutionContext();
-}
+ m_lengthComputable = lengthComputable;
+ m_loaded = loaded;
+ m_total = total;
-EventTargetData* XMLHttpRequestUpload::eventTargetData()
-{
- return &m_eventTargetData;
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
}
-EventTargetData* XMLHttpRequestUpload::ensureEventTargetData()
+void XMLHttpRequestUpload::dispatchProgressEvent(const AtomicString &type)
{
- return &m_eventTargetData;
-}
+ ASSERT(type == eventNames().loadstartEvent || type == eventNames().progressEvent || type == eventNames().loadEvent || type == eventNames().loadendEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);
-void XMLHttpRequestUpload::dispatchEventAndLoadEnd(PassRefPtr<Event> event)
-{
- ASSERT(event->type() == eventNames().loadEvent || event->type() == eventNames().abortEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().timeoutEvent);
+ if (type == eventNames().loadstartEvent) {
+ m_lengthComputable = false;
+ m_loaded = 0;
+ m_total = 0;
+ }
- dispatchEvent(event);
- dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
+ dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
}
-
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.h b/Source/WebCore/xml/XMLHttpRequestUpload.h
index 386745f1b..5418b734c 100644
--- a/Source/WebCore/xml/XMLHttpRequestUpload.h
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.h
@@ -26,56 +26,39 @@
#ifndef XMLHttpRequestUpload_h
#define XMLHttpRequestUpload_h
-#include "EventListener.h"
-#include "EventNames.h"
-#include "EventTarget.h"
#include "XMLHttpRequest.h"
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/AtomicStringHash.h>
namespace WebCore {
class ScriptExecutionContext;
class XMLHttpRequest;
- class XMLHttpRequestUpload : public EventTarget {
+ class XMLHttpRequestUpload final : public XMLHttpRequestEventTarget {
public:
- static PassOwnPtr<XMLHttpRequestUpload> create(XMLHttpRequest* xmlHttpRequest)
- {
- return adoptPtr(new XMLHttpRequestUpload(xmlHttpRequest));
- }
+ explicit XMLHttpRequestUpload(XMLHttpRequest*);
void ref() { m_xmlHttpRequest->ref(); }
void deref() { m_xmlHttpRequest->deref(); }
XMLHttpRequest* xmlHttpRequest() const { return m_xmlHttpRequest; }
- virtual const AtomicString& interfaceName() const;
- ScriptExecutionContext* scriptExecutionContext() const;
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(loadend);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
+ virtual EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestUploadEventTargetInterfaceType; }
+ virtual ScriptExecutionContext* scriptExecutionContext() const override { return m_xmlHttpRequest->scriptExecutionContext(); }
- void dispatchEventAndLoadEnd(PassRefPtr<Event>);
+ void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
+ void dispatchProgressEvent(const AtomicString &type);
private:
- explicit XMLHttpRequestUpload(XMLHttpRequest*);
-
- virtual void refEventTarget() { ref(); }
- virtual void derefEventTarget() { deref(); }
- virtual EventTargetData* eventTargetData();
- virtual EventTargetData* ensureEventTargetData();
+ virtual void refEventTarget() override final { ref(); }
+ virtual void derefEventTarget() override final { deref(); }
XMLHttpRequest* m_xmlHttpRequest;
- EventTargetData m_eventTargetData;
+ bool m_lengthComputable;
+ unsigned long long m_loaded;
+ unsigned long long m_total;
};
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.idl b/Source/WebCore/xml/XMLHttpRequestUpload.idl
index 844992724..b91453622 100644
--- a/Source/WebCore/xml/XMLHttpRequestUpload.idl
+++ b/Source/WebCore/xml/XMLHttpRequestUpload.idl
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -28,25 +28,7 @@
[
GenerateIsReachable=Impl,
- EventTarget,
- JSNoStaticTables
-] interface XMLHttpRequestUpload {
- // From XMLHttpRequestEventTarget
- // event handler attributes
- attribute EventListener onabort;
- attribute EventListener onerror;
- attribute EventListener onload;
- attribute EventListener onloadend;
- attribute EventListener onloadstart;
- attribute EventListener onprogress;
-
- // EventTarget interface
- void addEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- void removeEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- [RaisesException] boolean dispatchEvent(Event evt);
+ JSGenerateToJSObject,
+] interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
};
diff --git a/Source/WebCore/xml/XMLSerializer.cpp b/Source/WebCore/xml/XMLSerializer.cpp
index dfc0f56c0..9a9f9a392 100644
--- a/Source/WebCore/xml/XMLSerializer.cpp
+++ b/Source/WebCore/xml/XMLSerializer.cpp
@@ -29,20 +29,11 @@ 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;
+ if (!node) {
+ ec = TypeError;
return String();
}
-
- return createMarkup(node, IncludeNode, 0, DoNotResolveURLs, 0, XMLFragmentSerialization);
+ return createMarkup(*node, IncludeNode, 0, DoNotResolveURLs, 0, XMLFragmentSerialization);
}
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLSerializer.h b/Source/WebCore/xml/XMLSerializer.h
index 4d255b0e5..90cd13b25 100644
--- a/Source/WebCore/xml/XMLSerializer.h
+++ b/Source/WebCore/xml/XMLSerializer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006 Apple Inc.
* Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
*
* This library is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
#define XMLSerializer_h
#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
namespace WebCore {
@@ -32,7 +32,7 @@ namespace WebCore {
class XMLSerializer : public RefCounted<XMLSerializer> {
public:
- static PassRefPtr<XMLSerializer> create() { return adoptRef(new XMLSerializer); }
+ static Ref<XMLSerializer> create() { return adoptRef(*new XMLSerializer); }
String serializeToString(Node*, ExceptionCode&);
diff --git a/Source/WebCore/xml/XMLSerializer.idl b/Source/WebCore/xml/XMLSerializer.idl
index 5e174e172..81732d445 100644
--- a/Source/WebCore/xml/XMLSerializer.idl
+++ b/Source/WebCore/xml/XMLSerializer.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
*
* This library is free software; you can redistribute it and/or
@@ -20,7 +20,7 @@
[
Constructor,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface XMLSerializer {
[RaisesException] DOMString serializeToString([Default=Undefined] optional Node node);
};
diff --git a/Source/WebCore/xml/XMLTreeViewer.cpp b/Source/WebCore/xml/XMLTreeViewer.cpp
index d52e8112e..5f137ad2f 100644
--- a/Source/WebCore/xml/XMLTreeViewer.cpp
+++ b/Source/WebCore/xml/XMLTreeViewer.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,53 +36,34 @@
#include "Element.h"
#include "ExceptionCodePlaceholder.h"
#include "Frame.h"
-#include "Page.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
-#include "ScriptValue.h"
-#include "Settings.h"
+#include "SecurityOrigin.h"
+#include "SecurityOriginPolicy.h"
#include "Text.h"
#include "XMLViewerCSS.h"
#include "XMLViewerJS.h"
-
-using namespace std;
+#include <bindings/ScriptValue.h>
namespace WebCore {
-XMLTreeViewer::XMLTreeViewer(Document* document)
+XMLTreeViewer::XMLTreeViewer(Document& document)
: m_document(document)
{
}
-bool XMLTreeViewer::hasNoStyleInformation() const
-{
- if (m_document->sawElementsInKnownNamespaces() || m_document->transformSourceDocument())
- return false;
-
- if (!m_document->frame() || !m_document->frame()->page())
- return false;
-
- if (!m_document->frame()->page()->settings()->developerExtrasEnabled())
- return false;
-
- if (m_document->frame()->tree()->parent())
- return false; // This document is not in a top frame
-
- return true;
-}
-
void XMLTreeViewer::transformDocumentToTreeView()
{
- m_document->setIsViewSource(true);
- String scriptString(reinterpret_cast<const char*>(XMLViewer_js), sizeof(XMLViewer_js));
- m_document->frame()->script()->evaluate(ScriptSourceCode(scriptString));
- String noStyleMessage("This XML file does not appear to have any style information associated with it. The document tree is shown below.");
- m_document->frame()->script()->evaluate(ScriptSourceCode("prepareWebKitXMLViewer('" + noStyleMessage + "');"));
+ m_document.setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique()));
+
+ String scriptString = StringImpl::createWithoutCopying(XMLViewer_js, sizeof(XMLViewer_js));
+ m_document.frame()->script().evaluate(ScriptSourceCode(scriptString));
+ m_document.frame()->script().evaluate(ScriptSourceCode(AtomicString("prepareWebKitXMLViewer('This XML file does not appear to have any style information associated with it. The document tree is shown below.');")));
- String cssString(reinterpret_cast<const char*>(XMLViewer_css), sizeof(XMLViewer_css));
- RefPtr<Text> text = m_document->createTextNode(cssString);
- m_document->getElementById("xml-viewer-style")->appendChild(text, IGNORE_EXCEPTION);
- m_document->styleResolverChanged(RecalcStyleImmediately);
+ String cssString = StringImpl::createWithoutCopying(XMLViewer_css, sizeof(XMLViewer_css));
+ Ref<Text> text = m_document.createTextNode(cssString);
+ m_document.getElementById(String(ASCIILiteral("xml-viewer-style")))->appendChild(WTFMove(text), IGNORE_EXCEPTION);
+ m_document.styleResolverChanged(RecalcStyleImmediately);
}
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLTreeViewer.h b/Source/WebCore/xml/XMLTreeViewer.h
index 93018e7e6..599bc194a 100644
--- a/Source/WebCore/xml/XMLTreeViewer.h
+++ b/Source/WebCore/xml/XMLTreeViewer.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -37,14 +38,12 @@ class Document;
class XMLTreeViewer {
public:
- explicit XMLTreeViewer(Document*);
- virtual ~XMLTreeViewer() {};
+ explicit XMLTreeViewer(Document&);
- bool hasNoStyleInformation() const;
void transformDocumentToTreeView();
private:
- Document* m_document;
+ Document& m_document;
};
} // namespace WebCore
diff --git a/Source/WebCore/xml/XMLViewer.css b/Source/WebCore/xml/XMLViewer.css
index 4032438f8..6b35890eb 100644
--- a/Source/WebCore/xml/XMLViewer.css
+++ b/Source/WebCore/xml/XMLViewer.css
@@ -26,6 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+body {
+ margin: 0
+}
+
div.header {
border-bottom: 2px solid black;
padding-bottom: 5px;
@@ -46,10 +50,29 @@ div.collapsible > div.hidden {
.collapsible-content {
margin-left: 1em;
}
+
.comment {
+ /* Keep this in sync with inspector.css (.webkit-html-comment) */
+ color: rgb(35, 110, 37);
+
white-space: pre;
}
+.tag {
+ /* Keep this in sync with inspector.css (.tag-name) */
+ color: rgb(136, 18, 128);
+}
+
+.attribute-name {
+ /* Keep this in sync with inspector.css (.webkit-html-attribute-name) */
+ color: rgb(153, 69, 0);
+}
+
+.attribute-value {
+ /* Keep this in sync with inspector.css (.webkit-html-attribute-value) */
+ color: rgb(26, 26, 166);
+}
+
.button {
-webkit-user-select: none;
cursor: pointer;
diff --git a/Source/WebCore/xml/XMLViewer.js b/Source/WebCore/xml/XMLViewer.js
index 1fda909a0..5fda4867b 100644
--- a/Source/WebCore/xml/XMLViewer.js
+++ b/Source/WebCore/xml/XMLViewer.js
@@ -284,7 +284,6 @@ function createComment(commentString)
{
var comment = createHTMLElement('span');
comment.classList.add('comment');
- comment.classList.add('webkit-html-comment');
comment.textContent = commentString;
return comment;
}
@@ -307,7 +306,7 @@ function createLine()
function createTag(node, isClosing, isEmpty)
{
var tag = createHTMLElement('span');
- tag.classList.add('webkit-html-tag');
+ tag.classList.add('tag');
var stringBeforeAttrs = '<';
if (isClosing)
@@ -334,17 +333,16 @@ function createTag(node, isClosing, isEmpty)
function createAttribute(attributeNode)
{
var attribute = createHTMLElement('span');
- attribute.classList.add('webkit-html-attribute');
var attributeName = createHTMLElement('span');
- attributeName.classList.add('webkit-html-attribute-name');
+ attributeName.classList.add('attribute-name');
attributeName.textContent = attributeNode.name;
var textBefore = document.createTextNode(' ');
var textBetween = document.createTextNode('="');
var attributeValue = createHTMLElement('span');
- attributeValue.classList.add('webkit-html-attribute-value');
+ attributeValue.classList.add('attribute-value');
attributeValue.textContent = attributeNode.value;
var textAfter = document.createTextNode('"');
@@ -386,8 +384,7 @@ function drawArrows()
function expandFunction(sectionId)
{
- return function()
- {
+ return function() {
document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
};
@@ -395,8 +392,7 @@ function expandFunction(sectionId)
function collapseFunction(sectionId)
{
- return function()
- {
+ return function() {
document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
};
@@ -419,7 +415,6 @@ function initButtons()
expandButton.onclick = expandFunction(sectionId);
expandButton.onmousedown = handleButtonMouseDown;
}
-
}
function handleButtonMouseDown(e)
diff --git a/Source/WebCore/xml/XPathEvaluator.cpp b/Source/WebCore/xml/XPathEvaluator.cpp
index 68f29fa41..de0aa0d17 100644
--- a/Source/WebCore/xml/XPathEvaluator.cpp
+++ b/Source/WebCore/xml/XPathEvaluator.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,7 +29,6 @@
#include "ExceptionCode.h"
#include "NativeXPathNSResolver.h"
-#include "Node.h"
#include "XPathExpression.h"
#include "XPathResult.h"
#include "XPathUtil.h"
@@ -38,19 +37,19 @@ namespace WebCore {
using namespace XPath;
-PassRefPtr<XPathExpression> XPathEvaluator::createExpression(const String& expression,
+RefPtr<XPathExpression> XPathEvaluator::createExpression(const String& expression,
XPathNSResolver* resolver,
ExceptionCode& ec)
{
return XPathExpression::createExpression(expression, resolver, ec);
}
-PassRefPtr<XPathNSResolver> XPathEvaluator::createNSResolver(Node* nodeResolver)
+Ref<XPathNSResolver> XPathEvaluator::createNSResolver(Node* nodeResolver)
{
return NativeXPathNSResolver::create(nodeResolver);
}
-PassRefPtr<XPathResult> XPathEvaluator::evaluate(const String& expression,
+RefPtr<XPathResult> XPathEvaluator::evaluate(const String& expression,
Node* contextNode,
XPathNSResolver* resolver,
unsigned short type,
@@ -59,13 +58,13 @@ PassRefPtr<XPathResult> XPathEvaluator::evaluate(const String& expression,
{
if (!isValidContextNode(contextNode)) {
ec = NOT_SUPPORTED_ERR;
- return 0;
+ return nullptr;
}
ec = 0;
RefPtr<XPathExpression> expr = createExpression(expression, resolver, ec);
if (ec)
- return 0;
+ return nullptr;
return expr->evaluate(contextNode, type, result, ec);
}
diff --git a/Source/WebCore/xml/XPathEvaluator.h b/Source/WebCore/xml/XPathEvaluator.h
index ca35f2101..b16c248a6 100644
--- a/Source/WebCore/xml/XPathEvaluator.h
+++ b/Source/WebCore/xml/XPathEvaluator.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,8 +28,8 @@
#define XPathEvaluator_h
#include <wtf/Forward.h>
+#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
-#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -42,11 +42,11 @@ namespace WebCore {
class XPathEvaluator : public RefCounted<XPathEvaluator> {
public:
- static PassRefPtr<XPathEvaluator> create() { return adoptRef(new XPathEvaluator); }
+ static Ref<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,
+ RefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&);
+ Ref<XPathNSResolver> createNSResolver(Node* nodeResolver);
+ RefPtr<XPathResult> evaluate(const String& expression, Node* contextNode,
XPathNSResolver*, unsigned short type, XPathResult*, ExceptionCode&);
private:
diff --git a/Source/WebCore/xml/XPathEvaluator.idl b/Source/WebCore/xml/XPathEvaluator.idl
index 457663f73..198e67aa0 100644
--- a/Source/WebCore/xml/XPathEvaluator.idl
+++ b/Source/WebCore/xml/XPathEvaluator.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,7 +19,7 @@
[
Constructor,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface XPathEvaluator {
[RaisesException] XPathExpression createExpression([Default=Undefined] optional DOMString expression,
[Default=Undefined] optional XPathNSResolver resolver);
diff --git a/Source/WebCore/xml/XPathException.cpp b/Source/WebCore/xml/XPathException.cpp
index bb03e5e77..283a31d2a 100644
--- a/Source/WebCore/xml/XPathException.cpp
+++ b/Source/WebCore/xml/XPathException.cpp
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -29,6 +29,8 @@
#include "config.h"
#include "XPathException.h"
+#include "ExceptionCodeDescription.h"
+
namespace WebCore {
static struct XPathExceptionNameDescription {
diff --git a/Source/WebCore/xml/XPathException.h b/Source/WebCore/xml/XPathException.h
index e0c42e9b1..1cb3e7428 100644
--- a/Source/WebCore/xml/XPathException.h
+++ b/Source/WebCore/xml/XPathException.h
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -35,9 +35,9 @@ namespace WebCore {
class XPathException : public ExceptionBase {
public:
- static PassRefPtr<XPathException> create(const ExceptionCodeDescription& description)
+ static Ref<XPathException> create(const ExceptionCodeDescription& description)
{
- return adoptRef(new XPathException(description));
+ return adoptRef(*new XPathException(description));
}
static const int XPathExceptionOffset = 400;
diff --git a/Source/WebCore/xml/XPathException.idl b/Source/WebCore/xml/XPathException.idl
index 55879f63e..1ffb25d08 100644
--- a/Source/WebCore/xml/XPathException.idl
+++ b/Source/WebCore/xml/XPathException.idl
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -28,7 +28,7 @@
[
DoNotCheckConstants,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] exception XPathException {
readonly attribute unsigned short code;
diff --git a/Source/WebCore/xml/XPathExpression.cpp b/Source/WebCore/xml/XPathExpression.cpp
index c5b3ff8f9..1449093af 100644
--- a/Source/WebCore/xml/XPathExpression.cpp
+++ b/Source/WebCore/xml/XPathExpression.cpp
@@ -30,7 +30,6 @@
#include "Document.h"
#include "ExceptionCode.h"
#include "XPathException.h"
-#include "XPathExpressionNode.h"
#include "XPathNSResolver.h"
#include "XPathParser.h"
#include "XPathResult.h"
@@ -41,28 +40,29 @@ namespace WebCore {
using namespace XPath;
-PassRefPtr<XPathExpression> XPathExpression::createExpression(const String& expression, XPathNSResolver* resolver, ExceptionCode& ec)
+inline XPathExpression::XPathExpression(std::unique_ptr<XPath::Expression> expression)
+ : m_topExpression(WTFMove(expression))
{
- RefPtr<XPathExpression> expr = XPathExpression::create();
- Parser parser;
+}
- expr->m_topExpression = parser.parseStatement(expression, resolver, ec);
- if (!expr->m_topExpression)
- return 0;
+RefPtr<XPathExpression> XPathExpression::createExpression(const String& expression, XPathNSResolver* resolver, ExceptionCode& ec)
+{
+ auto parsedExpression = Parser::parseStatement(expression, resolver, ec);
+ if (!parsedExpression)
+ return nullptr;
- return expr.release();
+ return adoptRef(*new XPathExpression(WTFMove(parsedExpression)));
}
XPathExpression::~XPathExpression()
{
- delete m_topExpression;
}
-PassRefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode& ec)
+RefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode& ec)
{
if (!isValidContextNode(contextNode)) {
ec = NOT_SUPPORTED_ERR;
- return 0;
+ return nullptr;
}
EvaluationContext& evaluationContext = Expression::evaluationContext();
@@ -70,21 +70,21 @@ PassRefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned sh
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.
+ RefPtr<XPathResult> result = XPathResult::create(&contextNode->document(), m_topExpression->evaluate());
+ evaluationContext.node = nullptr; // 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;
+ return nullptr;
}
if (type != XPathResult::ANY_TYPE) {
ec = 0;
result->convertTo(type, ec);
if (ec)
- return 0;
+ return nullptr;
}
return result;
diff --git a/Source/WebCore/xml/XPathExpression.h b/Source/WebCore/xml/XPathExpression.h
index 3124939c6..90da675c5 100644
--- a/Source/WebCore/xml/XPathExpression.h
+++ b/Source/WebCore/xml/XPathExpression.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,7 +29,6 @@
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
-#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -45,16 +44,15 @@ namespace WebCore {
class XPathExpression : public RefCounted<XPathExpression> {
public:
- static PassRefPtr<XPathExpression> create() { return adoptRef(new XPathExpression); }
+ static RefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&);
~XPathExpression();
- static PassRefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&);
- PassRefPtr<XPathResult> evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode&);
+ RefPtr<XPathResult> evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode&);
private:
- XPathExpression() { }
+ explicit XPathExpression(std::unique_ptr<XPath::Expression>);
- XPath::Expression* m_topExpression;
+ std::unique_ptr<XPath::Expression> m_topExpression;
};
}
diff --git a/Source/WebCore/xml/XPathExpression.idl b/Source/WebCore/xml/XPathExpression.idl
index 659b9fa4f..1f45e8f57 100644
--- a/Source/WebCore/xml/XPathExpression.idl
+++ b/Source/WebCore/xml/XPathExpression.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -18,7 +18,7 @@
* Boston, MA 02110-1301, USA.
*/
[
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface XPathExpression {
[ObjCLegacyUnnamedParameters, RaisesException] XPathResult evaluate([Default=Undefined] optional Node contextNode,
[Default=Undefined] optional unsigned short type,
diff --git a/Source/WebCore/xml/XPathExpressionNode.cpp b/Source/WebCore/xml/XPathExpressionNode.cpp
index 9db488870..7521bce34 100644
--- a/Source/WebCore/xml/XPathExpressionNode.cpp
+++ b/Source/WebCore/xml/XPathExpressionNode.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,7 +27,7 @@
#include "config.h"
#include "XPathExpressionNode.h"
-#include "Node.h"
+#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -35,8 +35,8 @@ namespace XPath {
EvaluationContext& Expression::evaluationContext()
{
- DEFINE_STATIC_LOCAL(EvaluationContext, evaluationContext, ());
- return evaluationContext;
+ static NeverDestroyed<EvaluationContext> context;
+ return context;
}
Expression::Expression()
@@ -46,10 +46,16 @@ Expression::Expression()
{
}
-Expression::~Expression()
+void Expression::setSubexpressions(Vector<std::unique_ptr<Expression>> subexpressions)
{
- deleteAllValues(m_subExpressions);
+ ASSERT(m_subexpressions.isEmpty());
+ m_subexpressions = WTFMove(subexpressions);
+ for (auto& subexpression : m_subexpressions) {
+ m_isContextNodeSensitive |= subexpression->m_isContextNodeSensitive;
+ m_isContextPositionSensitive |= subexpression->m_isContextPositionSensitive;
+ m_isContextSizeSensitive |= subexpression->m_isContextSizeSensitive;
+ }
}
-}
-}
+} // namespace XPath
+} // namespace WebCore
diff --git a/Source/WebCore/xml/XPathExpressionNode.h b/Source/WebCore/xml/XPathExpressionNode.h
index 8945cf35f..c6364109f 100644
--- a/Source/WebCore/xml/XPathExpressionNode.h
+++ b/Source/WebCore/xml/XPathExpressionNode.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,75 +27,64 @@
#ifndef XPathExpressionNode_h
#define XPathExpressionNode_h
-#include "Node.h"
#include "XPathValue.h"
-#include <wtf/HashMap.h>
-#include <wtf/Vector.h>
-#include <wtf/text/StringHash.h>
namespace WebCore {
+namespace XPath {
- namespace XPath {
-
- struct EvaluationContext {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- RefPtr<Node> node;
- unsigned long size;
- unsigned long position;
- HashMap<String, String> variableBindings;
-
- bool hadTypeConversionError;
- };
-
- class ParseNode {
- public:
- virtual ~ParseNode() { }
- };
-
- class Expression : public ParseNode {
- WTF_MAKE_NONCOPYABLE(Expression); WTF_MAKE_FAST_ALLOCATED;
- 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;
- };
+struct EvaluationContext {
+ RefPtr<Node> node;
+ unsigned size;
+ unsigned position;
+ HashMap<String, String> variableBindings;
+ bool hadTypeConversionError;
+};
+
+class Expression {
+ WTF_MAKE_NONCOPYABLE(Expression); WTF_MAKE_FAST_ALLOCATED;
+public:
+ static EvaluationContext& evaluationContext();
+
+ virtual ~Expression() { }
+
+ virtual Value evaluate() const = 0;
+ virtual Value::Type resultType() const = 0;
+
+ bool isContextNodeSensitive() const { return m_isContextNodeSensitive; }
+ bool isContextPositionSensitive() const { return m_isContextPositionSensitive; }
+ bool isContextSizeSensitive() const { return m_isContextSizeSensitive; }
+
+protected:
+ Expression();
+
+ unsigned subexpressionCount() const { return m_subexpressions.size(); }
+ const Expression& subexpression(unsigned i) const { return *m_subexpressions[i]; }
+
+ void addSubexpression(std::unique_ptr<Expression> expression)
+ {
+ m_isContextNodeSensitive |= expression->m_isContextNodeSensitive;
+ m_isContextPositionSensitive |= expression->m_isContextPositionSensitive;
+ m_isContextSizeSensitive |= expression->m_isContextSizeSensitive;
+ m_subexpressions.append(WTFMove(expression));
}
-}
+ void setSubexpressions(Vector<std::unique_ptr<Expression>>);
+
+ void setIsContextNodeSensitive(bool value) { m_isContextNodeSensitive = value; }
+ void setIsContextPositionSensitive(bool value) { m_isContextPositionSensitive = value; }
+ void setIsContextSizeSensitive(bool value) { m_isContextSizeSensitive = value; }
+
+private:
+ Vector<std::unique_ptr<Expression>> m_subexpressions;
+
+ // Evaluation details that can be used for optimization.
+ bool m_isContextNodeSensitive;
+ bool m_isContextPositionSensitive;
+ bool m_isContextSizeSensitive;
+};
+
+} // namespace XPath
+} // namespace WebCore
-#endif // EXPRESSION_H
+#endif // XPathExpressionNode_h
diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp
index 0b3ba0701..a66c47191 100644
--- a/Source/WebCore/xml/XPathFunctions.cpp
+++ b/Source/WebCore/xml/XPathFunctions.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
#include "TreeScope.h"
#include "XMLNames.h"
#include "XPathUtil.h"
-#include "XPathValue.h"
#include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -45,8 +45,7 @@ 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; }
+#define DEFINE_FUNCTION_CREATOR(Suffix) static std::unique_ptr<Function> createFunction##Suffix() { return std::make_unique<Fun##Suffix>(); }
class Interval {
public:
@@ -63,201 +62,193 @@ private:
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; }
+class FunLast final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
public:
FunLast() { setIsContextSizeSensitive(true); }
};
-class FunPosition : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunPosition final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
public:
FunPosition() { setIsContextPositionSensitive(true); }
};
-class FunCount : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunCount final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
};
-class FunId : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NodeSetValue; }
+class FunId final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NodeSetValue; }
};
-class FunLocalName : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::StringValue; }
+class FunLocalName final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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; }
+class FunNamespaceURI final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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; }
+class FunName final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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; }
+class FunString final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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 FunConcat final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
};
-class FunStartsWith : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunStartsWith final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
-class FunContains : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunContains final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
-class FunSubstringBefore : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstringBefore final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
};
-class FunSubstringAfter : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstringAfter final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
};
-class FunSubstring : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::StringValue; }
+class FunSubstring final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
};
-class FunStringLength : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunStringLength final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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; }
+class FunNormalizeSpace final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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 FunTranslate final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
};
-class FunBoolean : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunBoolean final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
class FunNot : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
-class FunTrue : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunTrue final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
-class FunFalse : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunFalse final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
};
-class FunLang : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+class FunLang final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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; }
+class FunNumber final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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 FunSum final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
};
-class FunFloor : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunFloor final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
};
-class FunCeiling : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunCeiling final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
};
-class FunRound : public Function {
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+class FunRound final : public Function {
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { 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)
+DEFINE_FUNCTION_CREATOR(Last)
+DEFINE_FUNCTION_CREATOR(Position)
+DEFINE_FUNCTION_CREATOR(Count)
+DEFINE_FUNCTION_CREATOR(Id)
+DEFINE_FUNCTION_CREATOR(LocalName)
+DEFINE_FUNCTION_CREATOR(NamespaceURI)
+DEFINE_FUNCTION_CREATOR(Name)
+
+DEFINE_FUNCTION_CREATOR(String)
+DEFINE_FUNCTION_CREATOR(Concat)
+DEFINE_FUNCTION_CREATOR(StartsWith)
+DEFINE_FUNCTION_CREATOR(Contains)
+DEFINE_FUNCTION_CREATOR(SubstringBefore)
+DEFINE_FUNCTION_CREATOR(SubstringAfter)
+DEFINE_FUNCTION_CREATOR(Substring)
+DEFINE_FUNCTION_CREATOR(StringLength)
+DEFINE_FUNCTION_CREATOR(NormalizeSpace)
+DEFINE_FUNCTION_CREATOR(Translate)
+
+DEFINE_FUNCTION_CREATOR(Boolean)
+DEFINE_FUNCTION_CREATOR(Not)
+DEFINE_FUNCTION_CREATOR(True)
+DEFINE_FUNCTION_CREATOR(False)
+DEFINE_FUNCTION_CREATOR(Lang)
+
+DEFINE_FUNCTION_CREATOR(Number)
+DEFINE_FUNCTION_CREATOR(Sum)
+DEFINE_FUNCTION_CREATOR(Floor)
+DEFINE_FUNCTION_CREATOR(Ceiling)
+DEFINE_FUNCTION_CREATOR(Round)
#undef DEFINE_FUNCTION_CREATOR
@@ -290,17 +281,17 @@ inline bool Interval::contains(int value) const
return value >= m_min && value <= m_max;
}
-void Function::setArguments(const Vector<Expression*>& args)
+void Function::setArguments(const String& name, Vector<std::unique_ptr<Expression>> arguments)
{
- ASSERT(!subExprCount());
+ ASSERT(!subexpressionCount());
- // 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())
+ // Functions that use the context node as an implicit argument are context node sensitive when they
+ // have no arguments, but when explicit arguments are added, they are no longer context node sensitive.
+ // As of this writing, the only exception to this is the "lang" function.
+ if (name != "lang" && !arguments.isEmpty())
setIsContextNodeSensitive(false);
- Vector<Expression*>::const_iterator end = args.end();
- for (Vector<Expression*>::const_iterator it = args.begin(); it != end; ++it)
- addSubExpression(*it);
+ setSubexpressions(WTFMove(arguments));
}
Value FunLast::evaluate() const
@@ -313,24 +304,30 @@ Value FunPosition::evaluate() const
return Expression::evaluationContext().position;
}
+static AtomicString atomicSubstring(StringBuilder& builder, unsigned start, unsigned length)
+{
+ ASSERT(start <= builder.length());
+ ASSERT(length <= builder.length() - start);
+ if (builder.is8Bit())
+ return AtomicString(builder.characters8() + start, length);
+ return AtomicString(builder.characters16() + start, length);
+}
+
Value FunId::evaluate() const
{
- Value a = arg(0)->evaluate();
+ Value a = argument(0).evaluate();
StringBuilder 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);
+ if (!a.isNodeSet())
+ idList.append(a.toString());
+ else {
+ for (auto& node : a.toNodeSet()) {
+ idList.append(stringValue(node.get()));
idList.append(' ');
}
- } else {
- String str = a.toString();
- idList.append(str);
}
- TreeScope* contextScope = evaluationContext().node->treeScope();
+ TreeScope& contextScope = evaluationContext().node->treeScope();
NodeSet result;
HashSet<Node*> resultSet;
@@ -349,7 +346,7 @@ Value FunId::evaluate() const
// 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 = contextScope->getElementById(String(idList.characters() + startPos, endPos - startPos));
+ Node* node = contextScope.getElementById(atomicSubstring(idList, startPos, endPos - startPos));
if (node && resultSet.add(node).isNewEntry)
result.append(node);
@@ -358,15 +355,13 @@ Value FunId::evaluate() const
result.markSorted(false);
- return Value(result, Value::adopt);
+ return Value(WTFMove(result));
}
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();
+ if (is<ProcessingInstruction>(*node))
+ return downcast<ProcessingInstruction>(*node).target();
return node->localName().string();
}
@@ -378,13 +373,13 @@ static inline String expandedName(Node* node)
Value FunLocalName::evaluate() const
{
- if (argCount() > 0) {
- Value a = arg(0)->evaluate();
+ if (argumentCount() > 0) {
+ Value a = argument(0).evaluate();
if (!a.isNodeSet())
- return "";
+ return emptyString();
Node* node = a.toNodeSet().firstNode();
- return node ? expandedNameLocalPart(node) : "";
+ return node ? expandedNameLocalPart(node) : emptyString();
}
return expandedNameLocalPart(evaluationContext().node.get());
@@ -392,13 +387,13 @@ Value FunLocalName::evaluate() const
Value FunNamespaceURI::evaluate() const
{
- if (argCount() > 0) {
- Value a = arg(0)->evaluate();
+ if (argumentCount() > 0) {
+ Value a = argument(0).evaluate();
if (!a.isNodeSet())
- return "";
+ return emptyString();
Node* node = a.toNodeSet().firstNode();
- return node ? node->namespaceURI().string() : "";
+ return node ? node->namespaceURI().string() : emptyString();
}
return evaluationContext().node->namespaceURI().string();
@@ -406,13 +401,13 @@ Value FunNamespaceURI::evaluate() const
Value FunName::evaluate() const
{
- if (argCount() > 0) {
- Value a = arg(0)->evaluate();
+ if (argumentCount() > 0) {
+ Value a = argument(0).evaluate();
if (!a.isNodeSet())
- return "";
+ return emptyString();
Node* node = a.toNodeSet().firstNode();
- return node ? expandedName(node) : "";
+ return node ? expandedName(node) : emptyString();
}
return expandedName(evaluationContext().node.get());
@@ -420,16 +415,16 @@ Value FunName::evaluate() const
Value FunCount::evaluate() const
{
- Value a = arg(0)->evaluate();
+ Value a = argument(0).evaluate();
return double(a.toNodeSet().size());
}
Value FunString::evaluate() const
{
- if (!argCount())
+ if (!argumentCount())
return Value(Expression::evaluationContext().node.get()).toString();
- return arg(0)->evaluate().toString();
+ return argument(0).evaluate().toString();
}
Value FunConcat::evaluate() const
@@ -437,9 +432,8 @@ Value FunConcat::evaluate() const
StringBuilder result;
result.reserveCapacity(1024);
- unsigned count = argCount();
- for (unsigned i = 0; i < count; ++i) {
- String str(arg(i)->evaluate().toString());
+ for (unsigned i = 0, count = argumentCount(); i < count; ++i) {
+ String str(argument(i).evaluate().toString());
result.append(str);
}
@@ -448,8 +442,8 @@ Value FunConcat::evaluate() const
Value FunStartsWith::evaluate() const
{
- String s1 = arg(0)->evaluate().toString();
- String s2 = arg(1)->evaluate().toString();
+ String s1 = argument(0).evaluate().toString();
+ String s2 = argument(1).evaluate().toString();
if (s2.isEmpty())
return true;
@@ -459,8 +453,8 @@ Value FunStartsWith::evaluate() const
Value FunContains::evaluate() const
{
- String s1 = arg(0)->evaluate().toString();
- String s2 = arg(1)->evaluate().toString();
+ String s1 = argument(0).evaluate().toString();
+ String s2 = argument(1).evaluate().toString();
if (s2.isEmpty())
return true;
@@ -470,56 +464,56 @@ Value FunContains::evaluate() const
Value FunSubstringBefore::evaluate() const
{
- String s1 = arg(0)->evaluate().toString();
- String s2 = arg(1)->evaluate().toString();
+ String s1 = argument(0).evaluate().toString();
+ String s2 = argument(1).evaluate().toString();
if (s2.isEmpty())
- return "";
+ return emptyString();
size_t i = s1.find(s2);
if (i == notFound)
- return "";
+ return emptyString();
return s1.left(i);
}
Value FunSubstringAfter::evaluate() const
{
- String s1 = arg(0)->evaluate().toString();
- String s2 = arg(1)->evaluate().toString();
+ String s1 = argument(0).evaluate().toString();
+ String s2 = argument(1).evaluate().toString();
size_t i = s1.find(s2);
if (i == notFound)
- return "";
+ return emptyString();
return s1.substring(i + s2.length());
}
Value FunSubstring::evaluate() const
{
- String s = arg(0)->evaluate().toString();
- double doublePos = arg(1)->evaluate().toNumber();
+ String s = argument(0).evaluate().toString();
+ double doublePos = argument(1).evaluate().toNumber();
if (std::isnan(doublePos))
- return "";
+ return emptyString();
long pos = static_cast<long>(FunRound::round(doublePos));
- bool haveLength = argCount() == 3;
+ bool haveLength = argumentCount() == 3;
long len = -1;
if (haveLength) {
- double doubleLen = arg(2)->evaluate().toNumber();
+ double doubleLen = argument(2).evaluate().toNumber();
if (std::isnan(doubleLen))
- return "";
+ return emptyString();
len = static_cast<long>(FunRound::round(doubleLen));
}
if (pos > long(s.length()))
- return "";
+ return emptyString();
if (pos < 1) {
if (haveLength) {
len -= 1 - pos;
if (len < 1)
- return "";
+ return emptyString();
}
pos = 1;
}
@@ -529,27 +523,27 @@ Value FunSubstring::evaluate() const
Value FunStringLength::evaluate() const
{
- if (!argCount())
+ if (!argumentCount())
return Value(Expression::evaluationContext().node.get()).toString().length();
- return arg(0)->evaluate().toString().length();
+ return argument(0).evaluate().toString().length();
}
Value FunNormalizeSpace::evaluate() const
{
- if (!argCount()) {
+ if (!argumentCount()) {
String s = Value(Expression::evaluationContext().node.get()).toString();
return s.simplifyWhiteSpace();
}
- String s = arg(0)->evaluate().toString();
+ String s = argument(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 s1 = argument(0).evaluate().toString();
+ String s2 = argument(1).evaluate().toString();
+ String s3 = argument(2).evaluate().toString();
StringBuilder result;
for (unsigned i1 = 0; i1 < s1.length(); ++i1) {
@@ -567,12 +561,12 @@ Value FunTranslate::evaluate() const
Value FunBoolean::evaluate() const
{
- return arg(0)->evaluate().toBoolean();
+ return argument(0).evaluate().toBoolean();
}
Value FunNot::evaluate() const
{
- return !arg(0)->evaluate().toBoolean();
+ return !argument(0).evaluate().toBoolean();
}
Value FunTrue::evaluate() const
@@ -582,15 +576,15 @@ Value FunTrue::evaluate() const
Value FunLang::evaluate() const
{
- String lang = arg(0)->evaluate().toString();
+ String lang = argument(0).evaluate().toString();
- const Attribute* languageAttribute = 0;
+ const Attribute* languageAttribute = nullptr;
Node* node = evaluationContext().node.get();
while (node) {
- if (node->isElementNode()) {
- Element* element = toElement(node);
- if (element->hasAttributes())
- languageAttribute = element->getAttributeItem(XMLNames::langAttr);
+ if (is<Element>(*node)) {
+ Element& element = downcast<Element>(*node);
+ if (element.hasAttributes())
+ languageAttribute = element.findAttributeByName(XMLNames::langAttr);
}
if (languageAttribute)
break;
@@ -602,7 +596,7 @@ Value FunLang::evaluate() const
String langValue = languageAttribute->value();
while (true) {
- if (equalIgnoringCase(langValue, lang))
+ if (equalIgnoringASCIICase(langValue, lang))
return true;
// Remove suffixes one by one.
@@ -622,14 +616,14 @@ Value FunFalse::evaluate() const
Value FunNumber::evaluate() const
{
- if (!argCount())
+ if (!argumentCount())
return Value(Expression::evaluationContext().node.get()).toNumber();
- return arg(0)->evaluate().toNumber();
+ return argument(0).evaluate().toNumber();
}
Value FunSum::evaluate() const
{
- Value a = arg(0)->evaluate();
+ Value a = argument(0).evaluate();
if (!a.isNodeSet())
return 0.0;
@@ -638,20 +632,20 @@ Value FunSum::evaluate() const
// 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();
+ for (auto& node : nodes)
+ sum += Value(stringValue(node.get())).toNumber();
return sum;
}
Value FunFloor::evaluate() const
{
- return floor(arg(0)->evaluate().toNumber());
+ return floor(argument(0).evaluate().toNumber());
}
Value FunCeiling::evaluate() const
{
- return ceil(arg(0)->evaluate().toNumber());
+ return ceil(argument(0).evaluate().toNumber());
}
double FunRound::round(double val)
@@ -667,65 +661,81 @@ double FunRound::round(double val)
Value FunRound::evaluate() const
{
- return round(arg(0)->evaluate().toNumber());
+ return round(argument(0).evaluate().toNumber());
}
-struct FunctionMapping {
- const char* name;
- FunctionRec function;
+struct FunctionMapValue {
+ std::unique_ptr<Function> (*creationFunction)();
+ Interval argumentCountInterval;
};
-static void createFunctionMap()
+static void populateFunctionMap(HashMap<String, FunctionMapValue>& functionMap)
{
+ struct FunctionMapping {
+ const char* name;
+ FunctionMapValue function;
+ };
+
static const FunctionMapping functions[] = {
- { "boolean", { &createFunBoolean, 1 } },
- { "ceiling", { &createFunCeiling, 1 } },
- { "concat", { &createFunConcat, Interval(2, Interval::Inf) } },
- { "contains", { &createFunContains, 2 } },
- { "count", { &createFunCount, 1 } },
- { "false", { &createFunFalse, 0 } },
- { "floor", { &createFunFloor, 1 } },
- { "id", { &createFunId, 1 } },
- { "lang", { &createFunLang, 1 } },
- { "last", { &createFunLast, 0 } },
- { "local-name", { &createFunLocalName, Interval(0, 1) } },
- { "name", { &createFunName, Interval(0, 1) } },
- { "namespace-uri", { &createFunNamespaceURI, Interval(0, 1) } },
- { "normalize-space", { &createFunNormalizeSpace, Interval(0, 1) } },
- { "not", { &createFunNot, 1 } },
- { "number", { &createFunNumber, Interval(0, 1) } },
- { "position", { &createFunPosition, 0 } },
- { "round", { &createFunRound, 1 } },
- { "starts-with", { &createFunStartsWith, 2 } },
- { "string", { &createFunString, Interval(0, 1) } },
- { "string-length", { &createFunStringLength, Interval(0, 1) } },
- { "substring", { &createFunSubstring, Interval(2, 3) } },
- { "substring-after", { &createFunSubstringAfter, 2 } },
- { "substring-before", { &createFunSubstringBefore, 2 } },
- { "sum", { &createFunSum, 1 } },
- { "translate", { &createFunTranslate, 3 } },
- { "true", { &createFunTrue, 0 } },
+ { "boolean", { createFunctionBoolean, 1 } },
+ { "ceiling", { createFunctionCeiling, 1 } },
+ { "concat", { createFunctionConcat, Interval(2, Interval::Inf) } },
+ { "contains", { createFunctionContains, 2 } },
+ { "count", { createFunctionCount, 1 } },
+ { "false", { createFunctionFalse, 0 } },
+ { "floor", { createFunctionFloor, 1 } },
+ { "id", { createFunctionId, 1 } },
+ { "lang", { createFunctionLang, 1 } },
+ { "last", { createFunctionLast, 0 } },
+ { "local-name", { createFunctionLocalName, Interval(0, 1) } },
+ { "name", { createFunctionName, Interval(0, 1) } },
+ { "namespace-uri", { createFunctionNamespaceURI, Interval(0, 1) } },
+ { "normalize-space", { createFunctionNormalizeSpace, Interval(0, 1) } },
+ { "not", { createFunctionNot, 1 } },
+ { "number", { createFunctionNumber, Interval(0, 1) } },
+ { "position", { createFunctionPosition, 0 } },
+ { "round", { createFunctionRound, 1 } },
+ { "starts-with", { createFunctionStartsWith, 2 } },
+ { "string", { createFunctionString, Interval(0, 1) } },
+ { "string-length", { createFunctionStringLength, Interval(0, 1) } },
+ { "substring", { createFunctionSubstring, Interval(2, 3) } },
+ { "substring-after", { createFunctionSubstringAfter, 2 } },
+ { "substring-before", { createFunctionSubstringBefore, 2 } },
+ { "sum", { createFunctionSum, 1 } },
+ { "translate", { createFunctionTranslate, 3 } },
+ { "true", { createFunctionTrue, 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);
+ for (auto& function : functions)
+ functionMap.add(function.name, function.function);
}
-Function* createFunction(const String& name, const Vector<Expression*>& args)
+std::unique_ptr<Function> Function::create(const String& name, unsigned numArguments)
{
- if (!functionMap)
- createFunctionMap();
+ static NeverDestroyed<HashMap<String, FunctionMapValue>> functionMap;
+ if (functionMap.get().isEmpty())
+ populateFunctionMap(functionMap);
+
+ auto it = functionMap.get().find(name);
+ if (it == functionMap.get().end())
+ return nullptr;
+
+ if (!it->value.argumentCountInterval.contains(numArguments))
+ return nullptr;
- HashMap<String, FunctionRec>::iterator functionMapIter = functionMap->find(name);
- FunctionRec* functionRec = 0;
+ return it->value.creationFunction();
+}
- if (functionMapIter == functionMap->end() || !(functionRec = &functionMapIter->value)->args.contains(args.size()))
- return 0;
+std::unique_ptr<Function> Function::create(const String& name)
+{
+ return create(name, 0);
+}
- Function* function = functionRec->factoryFn();
- function->setArguments(args);
- function->setName(name);
+std::unique_ptr<Function> Function::create(const String& name, Vector<std::unique_ptr<Expression>> arguments)
+{
+ std::unique_ptr<Function> function = create(name, arguments.size());
+ if (function)
+ function->setArguments(name, WTFMove(arguments));
return function;
}
diff --git a/Source/WebCore/xml/XPathFunctions.h b/Source/WebCore/xml/XPathFunctions.h
index 08698a75b..94347a26a 100644
--- a/Source/WebCore/xml/XPathFunctions.h
+++ b/Source/WebCore/xml/XPathFunctions.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,27 +30,23 @@
#include "XPathExpressionNode.h"
namespace WebCore {
+namespace XPath {
- namespace XPath {
+class Function : public Expression {
+public:
+ static std::unique_ptr<Function> create(const String& name);
+ static std::unique_ptr<Function> create(const String& name, Vector<std::unique_ptr<Expression>> arguments);
- 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; }
+protected:
+ unsigned argumentCount() const { return subexpressionCount(); }
+ const Expression& argument(unsigned i) const { return subexpression(i); }
- private:
- String m_name;
- };
-
- Function* createFunction(const String& name, const Vector<Expression*>& args = Vector<Expression*>());
-
- } // namespace XPath
+private:
+ static std::unique_ptr<Function> create(const String& name, unsigned numArguments);
+ void setArguments(const String& name, Vector<std::unique_ptr<Expression>>);
+};
+} // namespace XPath
} // namespace WebCore
#endif // XPathFunctions_h
diff --git a/Source/WebCore/xml/XPathGrammar.y b/Source/WebCore/xml/XPathGrammar.y
index d558211db..356e11889 100644
--- a/Source/WebCore/xml/XPathGrammar.y
+++ b/Source/WebCore/xml/XPathGrammar.y
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -30,13 +30,9 @@
#include "config.h"
#include "XPathFunctions.h"
-#include "XPathNSResolver.h"
#include "XPathParser.h"
#include "XPathPath.h"
-#include "XPathPredicate.h"
-#include "XPathStep.h"
#include "XPathVariableReference.h"
-#include <wtf/FastMalloc.h>
#define YYMALLOC fastMalloc
#define YYFREE fastFree
@@ -51,94 +47,88 @@ using namespace XPath;
%}
-%pure_parser
-%parse-param { WebCore::XPath::Parser* parser }
+%pure-parser
+%lex-param { parser }
+%parse-param { Parser& parser }
-%union
-{
+%union {
+ NumericOp::Opcode numericOpcode;
+ EqTestOp::Opcode equalityTestOpcode;
+ StringImpl* string;
Step::Axis axis;
+ LocationPath* locationPath;
Step::NodeTest* nodeTest;
- NumericOp::Opcode numop;
- EqTestOp::Opcode eqop;
- String* str;
- Expression* expr;
- Vector<Predicate*>* predList;
- Vector<Expression*>* argList;
+ Vector<std::unique_ptr<Expression>>* expressionVector;
Step* step;
- LocationPath* locationPath;
+ Expression* expression;
}
+%left <numericOpcode> MULOP
-%{
+%left <equalityTestOpcode> EQOP RELOP
-static int xpathyylex(YYSTYPE* yylval) { return Parser::current()->lex(yylval); }
-static void xpathyyerror(void*, const char*) { }
-
-%}
-
-%left <numop> MULOP
-%left <eqop> EQOP RELOP
%left PLUS MINUS
+
%left OR AND
+
+%token <string> FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE
+%destructor { if ($$) $$->deref(); } FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE
+
%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
+
+%token COMMENT DOTDOT PI NODE SLASHSLASH TEXT XPATH_ERROR
+
+%type <locationPath> LocationPath AbsoluteLocationPath RelativeLocationPath
+%destructor { delete $$; } LocationPath AbsoluteLocationPath RelativeLocationPath
+
%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
+%destructor { delete $$; } NodeTest
+
+%type <expressionVector> ArgumentList PredicateList OptionalPredicateList
+%destructor { delete $$; } ArgumentList PredicateList OptionalPredicateList
+
+%type <step> Step AbbreviatedStep DescendantOrSelf
+%destructor { delete $$; } Step AbbreviatedStep DescendantOrSelf
+
+%type <expression> AdditiveExpr AndExpr Argument EqualityExpr Expr FilterExpr FunctionCall MultiplicativeExpr OrExpr PathExpr Predicate PrimaryExpr RelationalExpr UnaryExpr UnionExpr
+%destructor { delete $$; } AdditiveExpr AndExpr Argument EqualityExpr Expr FilterExpr FunctionCall MultiplicativeExpr OrExpr PathExpr Predicate PrimaryExpr RelationalExpr UnaryExpr UnionExpr
+
+
+
+%{
+
+static int xpathyylex(YYSTYPE* yylval, Parser& parser) { return parser.lex(*yylval); }
+static void xpathyyerror(Parser&, const char*) { }
+
+%}
%%
-Expr:
- OrExpr
+Top:
+ Expr
{
- parser->m_topExpr = $1;
+ parser.setParseResult(std::unique_ptr<Expression>($1));
}
;
+Expr:
+ OrExpr
+ ;
+
LocationPath:
- RelativeLocationPath
- {
- $$->setAbsolute(false);
- }
- |
AbsoluteLocationPath
{
- $$->setAbsolute(true);
+ $$ = $1;
+ $$->setAbsolute();
}
+ |
+ RelativeLocationPath
;
AbsoluteLocationPath:
'/'
{
$$ = new LocationPath;
- parser->registerParseNode($$);
}
|
'/' RelativeLocationPath
@@ -149,8 +139,7 @@ AbsoluteLocationPath:
DescendantOrSelf RelativeLocationPath
{
$$ = $2;
- $$->insertFirstStep($1);
- parser->unregisterParseNode($1);
+ $$->prependStep(std::unique_ptr<Step>($1));
}
;
@@ -158,83 +147,79 @@ RelativeLocationPath:
Step
{
$$ = new LocationPath;
- $$->appendStep($1);
- parser->unregisterParseNode($1);
- parser->registerParseNode($$);
+ $$->appendStep(std::unique_ptr<Step>($1));
}
|
RelativeLocationPath '/' Step
{
- $$->appendStep($3);
- parser->unregisterParseNode($3);
+ $$ = $1;
+ $$->appendStep(std::unique_ptr<Step>($3));
}
|
RelativeLocationPath DescendantOrSelf Step
{
- $$->appendStep($2);
- $$->appendStep($3);
- parser->unregisterParseNode($2);
- parser->unregisterParseNode($3);
+ $$ = $1;
+ $$->appendStep(std::unique_ptr<Step>($2));
+ $$->appendStep(std::unique_ptr<Step>($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($$);
+ std::unique_ptr<Step::NodeTest> nodeTest($1);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
+ if (predicateList)
+ $$ = new Step(Step::ChildAxis, WTFMove(*nodeTest), WTFMove(*predicateList));
+ else
+ $$ = new Step(Step::ChildAxis, WTFMove(*nodeTest));
}
|
NAMETEST OptionalPredicateList
{
+ String nametest = adoptRef($1);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
+
String localName;
String namespaceURI;
- if (!parser->expandQName(*$1, localName, namespaceURI)) {
- parser->m_gotNamespaceError = true;
+ if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) {
+ $$ = nullptr;
YYABORT;
}
-
- if ($2) {
- $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$2);
- parser->deletePredicateVector($2);
- } else
+
+ if (predicateList)
+ $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList));
+ 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($$);
+ std::unique_ptr<Step::NodeTest> nodeTest($2);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($3);
+
+ if (predicateList)
+ $$ = new Step($1, WTFMove(*nodeTest), WTFMove(*predicateList));
+ else
+ $$ = new Step($1, WTFMove(*nodeTest));
}
|
AxisSpecifier NAMETEST OptionalPredicateList
{
+ String nametest = adoptRef($2);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($3);
+
String localName;
String namespaceURI;
- if (!parser->expandQName(*$2, localName, namespaceURI)) {
- parser->m_gotNamespaceError = true;
+ if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) {
+ $$ = nullptr;
YYABORT;
}
- if ($3) {
- $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), *$3);
- parser->deletePredicateVector($3);
- } else
+ if (predicateList)
+ $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList));
+ else
$$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
- parser->deleteString($2);
- parser->registerParseNode($$);
}
|
AbbreviatedStep
@@ -250,39 +235,37 @@ AxisSpecifier:
;
NodeTest:
- NODETYPE '(' ')'
+ NODE '(' ')'
{
- 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($$);
+ $$ = new Step::NodeTest(Step::NodeTest::AnyNodeTest);
+ }
+ |
+ TEXT '(' ')'
+ {
+ $$ = new Step::NodeTest(Step::NodeTest::TextNodeTest);
+ }
+ |
+ COMMENT '(' ')'
+ {
+ $$ = new Step::NodeTest(Step::NodeTest::CommentNodeTest);
}
|
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($$);
+ String literal = adoptRef($3);
+ $$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest, literal.stripWhiteSpace());
}
;
OptionalPredicateList:
/* empty */
{
- $$ = 0;
+ $$ = nullptr;
}
|
PredicateList
@@ -291,16 +274,14 @@ OptionalPredicateList:
PredicateList:
Predicate
{
- $$ = new Vector<Predicate*>;
- $$->append(new Predicate($1));
- parser->unregisterParseNode($1);
- parser->registerPredicateVector($$);
+ $$ = new Vector<std::unique_ptr<Expression>>;
+ $$->append(std::unique_ptr<Expression>($1));
}
|
PredicateList Predicate
{
- $$->append(new Predicate($2));
- parser->unregisterParseNode($2);
+ $$ = $1;
+ $$->append(std::unique_ptr<Expression>($2));
}
;
@@ -315,7 +296,6 @@ DescendantOrSelf:
SLASHSLASH
{
$$ = new Step(Step::DescendantOrSelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
- parser->registerParseNode($$);
}
;
@@ -323,22 +303,19 @@ 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($$);
+ String name = adoptRef($1);
+ $$ = new VariableReference(name);
}
|
'(' Expr ')'
@@ -348,16 +325,14 @@ PrimaryExpr:
|
LITERAL
{
- $$ = new StringExpression(*$1);
- parser->deleteString($1);
- parser->registerParseNode($$);
+ String literal = adoptRef($1);
+ $$ = new StringExpression(WTFMove(literal));
}
|
NUMBER
{
- $$ = new Number($1->toDouble());
- parser->deleteString($1);
- parser->registerParseNode($$);
+ String numeral = adoptRef($1);
+ $$ = new Number(numeral.toDouble());
}
|
FunctionCall
@@ -366,37 +341,33 @@ PrimaryExpr:
FunctionCall:
FUNCTIONNAME '(' ')'
{
- $$ = createFunction(*$1);
+ String name = adoptRef($1);
+ $$ = XPath::Function::create(name).release();
if (!$$)
YYABORT;
- parser->deleteString($1);
- parser->registerParseNode($$);
}
|
FUNCTIONNAME '(' ArgumentList ')'
{
- $$ = createFunction(*$1, *$3);
+ String name = adoptRef($1);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> argumentList($3);
+ $$ = XPath::Function::create(name, WTFMove(*argumentList)).release();
if (!$$)
YYABORT;
- parser->deleteString($1);
- parser->deleteExpressionVector($3);
- parser->registerParseNode($$);
}
;
ArgumentList:
Argument
{
- $$ = new Vector<Expression*>;
- $$->append($1);
- parser->unregisterParseNode($1);
- parser->registerExpressionVector($$);
+ $$ = new Vector<std::unique_ptr<Expression>>;
+ $$->append(std::unique_ptr<Expression>($1));
}
|
ArgumentList ',' Argument
{
- $$->append($3);
- parser->unregisterParseNode($3);
+ $$ = $1;
+ $$->append(std::unique_ptr<Expression>($3));
}
;
@@ -409,12 +380,7 @@ UnionExpr:
|
UnionExpr '|' PathExpr
{
- $$ = new Union;
- $$->addSubExpression($1);
- $$->addSubExpression($3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new Union(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -428,22 +394,15 @@ PathExpr:
|
FilterExpr '/' RelativeLocationPath
{
- $3->setAbsolute(true);
- $$ = new Path(static_cast<Filter*>($1), $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $3->setAbsolute();
+ $$ = new Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
}
|
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($$);
+ $3->prependStep(std::unique_ptr<Step>($2));
+ $3->setAbsolute();
+ $$ = new Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
}
;
@@ -452,10 +411,8 @@ FilterExpr:
|
PrimaryExpr PredicateList
{
- $$ = new Filter($1, *$2);
- parser->unregisterParseNode($1);
- parser->deletePredicateVector($2);
- parser->registerParseNode($$);
+ std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
+ $$ = new Filter(std::unique_ptr<Expression>($1), WTFMove(*predicateList));
}
;
@@ -464,10 +421,7 @@ OrExpr:
|
OrExpr OR AndExpr
{
- $$ = new LogicalOp(LogicalOp::OP_Or, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new LogicalOp(LogicalOp::OP_Or, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -476,10 +430,7 @@ AndExpr:
|
AndExpr AND EqualityExpr
{
- $$ = new LogicalOp(LogicalOp::OP_And, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new LogicalOp(LogicalOp::OP_And, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -488,10 +439,7 @@ EqualityExpr:
|
EqualityExpr EQOP RelationalExpr
{
- $$ = new EqTestOp($2, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new EqTestOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -500,10 +448,7 @@ RelationalExpr:
|
RelationalExpr RELOP AdditiveExpr
{
- $$ = new EqTestOp($2, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new EqTestOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -512,18 +457,12 @@ AdditiveExpr:
|
AdditiveExpr PLUS MultiplicativeExpr
{
- $$ = new NumericOp(NumericOp::OP_Add, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new NumericOp(NumericOp::OP_Add, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
|
AdditiveExpr MINUS MultiplicativeExpr
{
- $$ = new NumericOp(NumericOp::OP_Sub, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new NumericOp(NumericOp::OP_Sub, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -532,10 +471,7 @@ MultiplicativeExpr:
|
MultiplicativeExpr MULOP UnaryExpr
{
- $$ = new NumericOp($2, $1, $3);
- parser->unregisterParseNode($1);
- parser->unregisterParseNode($3);
- parser->registerParseNode($$);
+ $$ = new NumericOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
}
;
@@ -544,10 +480,7 @@ UnaryExpr:
|
MINUS UnaryExpr
{
- $$ = new Negative;
- $$->addSubExpression($2);
- parser->unregisterParseNode($2);
- parser->registerParseNode($$);
+ $$ = new Negative(std::unique_ptr<Expression>($2));
}
;
diff --git a/Source/WebCore/xml/XPathNSResolver.cpp b/Source/WebCore/xml/XPathNSResolver.cpp
index 12aeebaf7..cb6ba42d9 100644
--- a/Source/WebCore/xml/XPathNSResolver.cpp
+++ b/Source/WebCore/xml/XPathNSResolver.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/Source/WebCore/xml/XPathNSResolver.h b/Source/WebCore/xml/XPathNSResolver.h
index a62ad203c..eafd8b3de 100644
--- a/Source/WebCore/xml/XPathNSResolver.h
+++ b/Source/WebCore/xml/XPathNSResolver.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/Source/WebCore/xml/XPathNSResolver.idl b/Source/WebCore/xml/XPathNSResolver.idl
index 20da40d2a..5a02bc2d6 100644
--- a/Source/WebCore/xml/XPathNSResolver.idl
+++ b/Source/WebCore/xml/XPathNSResolver.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
[
NoInterfaceObject,
ObjCProtocol,
- SkipVTableValidation
+ SkipVTableValidation,
] interface XPathNSResolver {
[TreatReturnedNullStringAs=Null] DOMString lookupNamespaceURI([Default=Undefined] optional DOMString prefix);
};
diff --git a/Source/WebCore/xml/XPathNodeSet.cpp b/Source/WebCore/xml/XPathNodeSet.cpp
index 5d94b000d..0949c4d61 100644
--- a/Source/WebCore/xml/XPathNodeSet.cpp
+++ b/Source/WebCore/xml/XPathNodeSet.cpp
@@ -28,7 +28,6 @@
#include "Attr.h"
#include "Element.h"
-#include "Node.h"
#include "NodeTraversal.h"
namespace WebCore {
@@ -44,7 +43,7 @@ static inline Node* parentWithDepth(unsigned depth, const Vector<Node*>& parents
return parents[parents.size() - 1 - depth];
}
-static void sortBlock(unsigned from, unsigned to, Vector<Vector<Node*> >& parentMatrix, bool mayContainAttributeNodes)
+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;
@@ -95,8 +94,8 @@ static void sortBlock(unsigned from, unsigned to, Vector<Vector<Node*> >& parent
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)
+ Node* node = parentMatrix[i][0];
+ if (is<Attr>(*node) && downcast<Attr>(*node).ownerElement() == commonAncestor)
parentMatrix[i].swap(parentMatrix[sortedEnd++]);
}
if (sortedEnd != from) {
@@ -142,7 +141,7 @@ void NodeSet::sort() const
unsigned nodeCount = m_nodes.size();
if (nodeCount < 2) {
- const_cast<bool&>(m_isSorted) = true;
+ m_isSorted = true;
return;
}
@@ -153,36 +152,37 @@ void NodeSet::sort() const
bool containsAttributeNodes = false;
- Vector<Vector<Node*> > parentMatrix(nodeCount);
+ 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);
+ Node* node = m_nodes[i].get();
+ parentsVector.append(node);
+ if (is<Attr>(*node)) {
+ node = downcast<Attr>(*node).ownerElement();
+ parentsVector.append(node);
containsAttributeNodes = true;
}
- while ((n = n->parentNode()))
- parentsVector.append(n);
+ while ((node = node->parentNode()))
+ parentsVector.append(node);
}
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;
+ 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);
+ m_nodes = WTFMove(sortedNodes);
+ m_isSorted = true;
}
static Node* findRootNode(Node* node)
{
- if (node->isAttributeNode())
- node = static_cast<Attr*>(node)->ownerElement();
+ if (is<Attr>(*node))
+ node = downcast<Attr>(*node).ownerElement();
if (node->inDocument())
- node = node->document();
+ node = &node->document();
else {
while (Node* parent = node->parentNode())
node = parent;
@@ -197,57 +197,42 @@ void NodeSet::traversalSort() const
unsigned nodeCount = m_nodes.size();
ASSERT(nodeCount > 1);
- for (unsigned i = 0; i < nodeCount; ++i) {
- Node* node = m_nodes[i].get();
- nodes.add(node);
+ for (auto& node : m_nodes) {
+ nodes.add(node.get());
if (node->isAttributeNode())
containsAttributeNodes = true;
}
- Vector<RefPtr<Node> > sortedNodes;
+ Vector<RefPtr<Node>> sortedNodes;
sortedNodes.reserveInitialCapacity(nodeCount);
- for (Node* n = findRootNode(m_nodes.first().get()); n; n = NodeTraversal::next(n)) {
- if (nodes.contains(n))
- sortedNodes.append(n);
+ for (Node* node = findRootNode(m_nodes.first().get()); node; node = NodeTraversal::next(*node)) {
+ if (nodes.contains(node))
+ sortedNodes.append(node);
- if (!containsAttributeNodes || !n->isElementNode())
+ if (!containsAttributeNodes || !is<Element>(*node))
continue;
- Element* element = toElement(n);
- if (!element->hasAttributes())
+ Element& element = downcast<Element>(*node);
+ if (!element.hasAttributes())
continue;
- unsigned attributeCount = element->attributeCount();
- for (unsigned i = 0; i < attributeCount; ++i) {
- RefPtr<Attr> attr = element->attrIfExists(element->attributeItem(i)->name());
+ for (const Attribute& attribute : element.attributesIterator()) {
+ RefPtr<Attr> attr = element.attrIfExists(attribute.name());
if (attr && nodes.contains(attr.get()))
sortedNodes.append(attr);
}
}
ASSERT(sortedNodes.size() == nodeCount);
- 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;
- }
+ m_nodes = WTFMove(sortedNodes);
+ m_isSorted = true;
}
Node* NodeSet::firstNode() const
{
if (isEmpty())
- return 0;
+ return nullptr;
sort(); // FIXME: fully sorting the node-set just to find its first node is wasteful.
return m_nodes.at(0).get();
@@ -256,7 +241,7 @@ Node* NodeSet::firstNode() const
Node* NodeSet::anyNode() const
{
if (isEmpty())
- return 0;
+ return nullptr;
return m_nodes.at(0).get();
}
diff --git a/Source/WebCore/xml/XPathNodeSet.h b/Source/WebCore/xml/XPathNodeSet.h
index 839be8d8f..af505ce58 100644
--- a/Source/WebCore/xml/XPathNodeSet.h
+++ b/Source/WebCore/xml/XPathNodeSet.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +11,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -26,9 +27,6 @@
#ifndef XPathNodeSet_h
#define XPathNodeSet_h
-#include <wtf/Vector.h>
-#include <wtf/Forward.h>
-
#include "Node.h"
namespace WebCore {
@@ -36,26 +34,26 @@ namespace WebCore {
namespace XPath {
class NodeSet {
- WTF_MAKE_FAST_ALLOCATED;
public:
NodeSet() : m_isSorted(true), m_subtreesAreDisjoint(false) { }
+ explicit NodeSet(RefPtr<Node>&& node)
+ : m_isSorted(true), m_subtreesAreDisjoint(false), m_nodes(1, WTFMove(node))
+ { }
size_t size() const { return m_nodes.size(); }
- bool isEmpty() const { return !m_nodes.size(); }
+ bool isEmpty() const { return m_nodes.isEmpty(); }
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(RefPtr<Node>&& node) { m_nodes.append(WTFMove(node)); }
void append(const NodeSet& nodeSet) { m_nodes.appendVector(nodeSet.m_nodes); }
- // Returns the set's first node in document order, or 0 if the set is empty.
+ // Returns the set's first node in document order, or nullptr if the set is empty.
Node* firstNode() const;
- // Returns 0 if the set is empty.
+ // Returns nullptr 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.
@@ -68,14 +66,15 @@ namespace WebCore {
void markSubtreesDisjoint(bool disjoint) { m_subtreesAreDisjoint = disjoint; }
bool subtreesAreDisjoint() const { return m_subtreesAreDisjoint || m_nodes.size() < 2; }
- void reverse();
-
+ const RefPtr<Node>* begin() const { return m_nodes.begin(); }
+ const RefPtr<Node>* end() const { return m_nodes.end(); }
+
private:
void traversalSort() const;
- bool m_isSorted;
+ mutable bool m_isSorted;
bool m_subtreesAreDisjoint;
- Vector<RefPtr<Node> > m_nodes;
+ mutable Vector<RefPtr<Node>> m_nodes;
};
}
diff --git a/Source/WebCore/xml/XPathParser.cpp b/Source/WebCore/xml/XPathParser.cpp
index 749180dbe..c30e9fb1f 100644
--- a/Source/WebCore/xml/XPathParser.cpp
+++ b/Source/WebCore/xml/XPathParser.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Maksim Orlovich <maksim@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,42 +33,52 @@
#include "XPathException.h"
#include "XPathNSResolver.h"
#include "XPathPath.h"
-#include "XPathStep.h"
+#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
using namespace WebCore;
-using namespace WTF;
-using namespace Unicode;
using namespace XPath;
-extern int xpathyyparse(WebCore::XPath::Parser*);
+extern int xpathyyparse(Parser&);
+
#include "XPathGrammar.h"
-Parser* Parser::currentParser = 0;
+namespace WebCore {
+namespace XPath {
-enum XMLCat { NameStart, NameCont, NotPartOfName };
+struct Parser::Token {
+ int type;
+ String string;
+ Step::Axis axis;
+ NumericOp::Opcode numericOpcode;
+ EqTestOp::Opcode equalityTestOpcode;
-typedef HashMap<String, Step::Axis> AxisNamesMap;
+ Token(int type) : type(type) { }
+ Token(int type, const String& string) : type(type), string(string) { }
+ Token(int type, Step::Axis axis) : type(type), axis(axis) { }
+ Token(int type, NumericOp::Opcode opcode) : type(type), numericOpcode(opcode) { }
+ Token(int type, EqTestOp::Opcode opcode) : type(type), equalityTestOpcode(opcode) { }
+};
-static XMLCat charCat(UChar aChar)
-{
- //### might need to add some special cases from the XML spec.
+enum XMLCat { NameStart, NameCont, NotPartOfName };
- if (aChar == '_')
+static XMLCat charCat(UChar character)
+{
+ if (character == '_')
return NameStart;
- if (aChar == '.' || aChar == '-')
+ if (character == '.' || character == '-')
return NameCont;
- CharCategory category = Unicode::category(aChar);
- if (category & (Letter_Uppercase | Letter_Lowercase | Letter_Other | Letter_Titlecase | Number_Letter))
+ unsigned characterTypeMask = U_GET_GC_MASK(character);
+ if (characterTypeMask & (U_GC_LU_MASK | U_GC_LL_MASK | U_GC_LO_MASK | U_GC_LT_MASK | U_GC_NL_MASK))
return NameStart;
- if (category & (Mark_NonSpacing | Mark_SpacingCombining | Mark_Enclosing | Letter_Modifier | Number_DecimalDigit))
+ if (characterTypeMask & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_ND_MASK))
return NameCont;
return NotPartOfName;
}
-static void setUpAxisNamesMap(AxisNamesMap& axisNames)
+static void populateAxisNamesMap(HashMap<String, Step::Axis>& axisNames)
{
struct AxisName {
const char* name;
@@ -89,36 +99,23 @@ static void setUpAxisNamesMap(AxisNamesMap& axisNames)
{ "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);
+ for (auto& axisName : axisNameList)
+ axisNames.add(axisName.name, axisName.axis);
}
-static bool isAxisName(const String& name, Step::Axis& type)
+static bool parseAxisName(const String& name, Step::Axis& type)
{
- DEFINE_STATIC_LOCAL(AxisNamesMap, axisNames, ());
+ static NeverDestroyed<HashMap<String, Step::Axis>> axisNames;
+ if (axisNames.get().isEmpty())
+ populateAxisNamesMap(axisNames);
- if (axisNames.isEmpty())
- setUpAxisNamesMap(axisNames);
-
- AxisNamesMap::iterator it = axisNames.find(name);
- if (it == axisNames.end())
+ auto it = axisNames.get().find(name);
+ if (it == axisNames.get().end())
return false;
type = it->value;
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
@@ -143,25 +140,25 @@ void Parser::skipWS()
++m_nextPos;
}
-Token Parser::makeTokenAndAdvance(int code, int advance)
+Parser::Token Parser::makeTokenAndAdvance(int code, int advance)
{
m_nextPos += advance;
return Token(code);
}
-Token Parser::makeTokenAndAdvance(int code, NumericOp::Opcode val, int advance)
+Parser::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)
+Parser::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
+// Returns next char if it's there and interesting, 0 otherwise.
char Parser::peekAheadHelper()
{
if (m_nextPos + 1 >= m_data.length())
@@ -182,7 +179,7 @@ char Parser::peekCurHelper()
return next;
}
-Token Parser::lexString()
+Parser::Token Parser::lexString()
{
UChar delimiter = m_data[m_nextPos];
int startPos = m_nextPos + 1;
@@ -201,7 +198,7 @@ Token Parser::lexString()
return Token(XPATH_ERROR);
}
-Token Parser::lexNumber()
+Parser::Token Parser::lexNumber()
{
int startPos = m_nextPos;
bool seenDot = false;
@@ -263,7 +260,7 @@ bool Parser::lexQName(String& name)
return true;
}
-Token Parser::nextTokenInternal()
+inline Parser::Token Parser::nextTokenInternal()
{
skipWS();
@@ -351,7 +348,7 @@ Token Parser::nextTokenInternal()
//It might be an axis name.
Step::Axis axis;
- if (isAxisName(name, axis))
+ if (parseAxisName(name, axis))
return Token(AXISNAME, axis);
// Ugh, :: is only valid in axis names -> error
return Token(XPATH_ERROR);
@@ -373,17 +370,21 @@ Token Parser::nextTokenInternal()
}
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);
+ // note: we don't swallow the '(' here!
+
+ // Either node type oor function name.
+
+ if (name == "processing-instruction")
+ return Token(PI);
+ if (name == "node")
+ return Token(NODE);
+ if (name == "text")
+ return Token(TEXT);
+ if (name == "comment")
+ return Token(COMMENT);
- return Token(NODETYPE, name);
- }
- //must be a function name.
return Token(FUNCTIONNAME, name);
}
@@ -391,239 +392,87 @@ Token Parser::nextTokenInternal()
return Token(NAMETEST, name);
}
-Token Parser::nextToken()
+inline Parser::Token Parser::nextToken()
{
- Token toRet = nextTokenInternal();
- m_lastTokenType = toRet.type;
- return toRet;
+ Token token = nextTokenInternal();
+ m_lastTokenType = token.type;
+ return token;
}
-Parser::Parser()
+Parser::Parser(const String& statement, XPathNSResolver* resolver)
+ : m_data(statement)
+ , m_resolver(resolver)
+ , m_nextPos(0)
+ , m_lastTokenType(0)
+ , m_sawNamespaceError(false)
{
- reset(String());
}
-Parser::~Parser()
+int Parser::lex(YYSTYPE& yylval)
{
-}
-
-void Parser::reset(const String& data)
-{
- m_nextPos = 0;
- m_data = data;
- m_lastTokenType = 0;
-
- m_topExpr = 0;
- m_gotNamespaceError = false;
-}
+ Token token = nextToken();
-int Parser::lex(void* data)
-{
- YYSTYPE* yylval = static_cast<YYSTYPE*>(data);
- Token tok = nextToken();
-
- switch (tok.type) {
+ switch (token.type) {
case AXISNAME:
- yylval->axis = tok.axis;
+ yylval.axis = token.axis;
break;
case MULOP:
- yylval->numop = tok.numop;
+ yylval.numericOpcode = token.numericOpcode;
break;
case RELOP:
case EQOP:
- yylval->eqop = tok.eqop;
+ yylval.equalityTestOpcode = token.equalityTestOpcode;
break;
case NODETYPE:
- case PI:
case FUNCTIONNAME:
case LITERAL:
case VARIABLEREFERENCE:
case NUMBER:
case NAMETEST:
- yylval->str = new String(tok.str);
- registerString(yylval->str);
+ yylval.string = token.string.releaseImpl().leakRef();
break;
}
- return tok.type;
+ return token.type;
}
-bool Parser::expandQName(const String& qName, String& localName, String& namespaceURI)
+bool Parser::expandQualifiedName(const String& qualifiedName, String& localName, String& namespaceURI)
{
- size_t colon = qName.find(':');
+ size_t colon = qualifiedName.find(':');
if (colon != notFound) {
- if (!m_resolver)
+ if (!m_resolver) {
+ m_sawNamespaceError = true;
return false;
- namespaceURI = m_resolver->lookupNamespaceURI(qName.left(colon));
- if (namespaceURI.isNull())
+ }
+ namespaceURI = m_resolver->lookupNamespaceURI(qualifiedName.left(colon));
+ if (namespaceURI.isNull()) {
+ m_sawNamespaceError = true;
return false;
- localName = qName.substring(colon + 1);
+ }
+ localName = qualifiedName.substring(colon + 1);
} else
- localName = qName;
-
+ localName = qualifiedName;
+
return true;
}
-Expression* Parser::parseStatement(const String& statement, PassRefPtr<XPathNSResolver> resolver, ExceptionCode& ec)
+std::unique_ptr<Expression> Parser::parseStatement(const String& statement, 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();
+ Parser parser(statement, resolver);
- m_topExpr = 0;
+ int parseError = xpathyyparse(parser);
- if (m_gotNamespaceError)
- ec = NAMESPACE_ERR;
- else
- ec = XPathException::INVALID_EXPRESSION_ERR;
- return 0;
+ if (parser.m_sawNamespaceError) {
+ ec = NAMESPACE_ERR;
+ return nullptr;
}
- 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);
-}
+ if (parseError) {
+ ec = XPathException::INVALID_EXPRESSION_ERR;
+ return nullptr;
+ }
-void Parser::deleteNodeTest(Step::NodeTest* t)
-{
- if (t == 0)
- return;
-
- ASSERT(m_nodeTests.contains(t));
-
- m_nodeTests.remove(t);
- delete t;
+ return WTFMove(parser.m_result);
}
+} }
diff --git a/Source/WebCore/xml/XPathParser.h b/Source/WebCore/xml/XPathParser.h
index e58c444e1..e55ddbbb7 100644
--- a/Source/WebCore/xml/XPathParser.h
+++ b/Source/WebCore/xml/XPathParser.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Maksim Orlovich <maksim@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +30,8 @@
#include "XPathStep.h"
#include "XPathPredicate.h"
+union YYSTYPE;
+
namespace WebCore {
typedef int ExceptionCode;
@@ -38,58 +40,20 @@ namespace WebCore {
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 {
WTF_MAKE_NONCOPYABLE(Parser);
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);
+ static std::unique_ptr<Expression> parseStatement(const String& statement, XPathNSResolver*, ExceptionCode&);
- Expression* m_topExpr;
- bool m_gotNamespaceError;
+ int lex(YYSTYPE&);
+ bool expandQualifiedName(const String& qualifiedName, String& localName, String& namespaceURI);
+ void setParseResult(std::unique_ptr<Expression> expression) { m_result = WTFMove(expression); }
- 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*);
+ private:
+ Parser(const String&, XPathNSResolver*);
- void registerNodeTest(Step::NodeTest*);
- void deleteNodeTest(Step::NodeTest*);
+ struct Token;
- private:
bool isBinaryOperatorContext() const;
void skipWS();
@@ -107,20 +71,14 @@ namespace WebCore {
Token nextToken();
Token nextTokenInternal();
- void reset(const String& data);
-
- static Parser* currentParser;
+ const String& m_data;
+ XPathNSResolver* m_resolver;
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;
+ std::unique_ptr<Expression> m_result;
+ bool m_sawNamespaceError;
};
}
diff --git a/Source/WebCore/xml/XPathPath.cpp b/Source/WebCore/xml/XPathPath.cpp
index bc8a63a40..a72fc31c6 100644
--- a/Source/WebCore/xml/XPathPath.cpp
+++ b/Source/WebCore/xml/XPathPath.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -31,64 +31,50 @@
#include "Document.h"
#include "XPathPredicate.h"
#include "XPathStep.h"
-#include "XPathValue.h"
namespace WebCore {
namespace XPath {
-Filter::Filter(Expression* expr, const Vector<Predicate*>& predicates)
- : m_expr(expr), m_predicates(predicates)
+Filter::Filter(std::unique_ptr<Expression> expression, Vector<std::unique_ptr<Expression>> predicates)
+ : m_expression(WTFMove(expression)), m_predicates(WTFMove(predicates))
{
- setIsContextNodeSensitive(m_expr->isContextNodeSensitive());
- setIsContextPositionSensitive(m_expr->isContextPositionSensitive());
- setIsContextSizeSensitive(m_expr->isContextSizeSensitive());
-}
-
-Filter::~Filter()
-{
- delete m_expr;
- deleteAllValues(m_predicates);
+ setIsContextNodeSensitive(m_expression->isContextNodeSensitive());
+ setIsContextPositionSensitive(m_expression->isContextPositionSensitive());
+ setIsContextSizeSensitive(m_expression->isContextSizeSensitive());
}
Value Filter::evaluate() const
{
- Value v = m_expr->evaluate();
+ Value result = m_expression->evaluate();
- NodeSet& nodes = v.modifiableNodeSet();
+ NodeSet& nodes = result.modifiableNodeSet();
nodes.sort();
EvaluationContext& evaluationContext = Expression::evaluationContext();
- for (unsigned i = 0; i < m_predicates.size(); i++) {
+ for (auto& predicate : m_predicates) {
NodeSet newNodes;
evaluationContext.size = nodes.size();
evaluationContext.position = 0;
- for (unsigned j = 0; j < nodes.size(); j++) {
- Node* node = nodes[j];
-
+ for (auto& node : nodes) {
evaluationContext.node = node;
++evaluationContext.position;
- if (m_predicates[i]->evaluate())
- newNodes.append(node);
+ if (evaluatePredicate(*predicate))
+ newNodes.append(node.copyRef());
}
- nodes.swap(newNodes);
+ nodes = WTFMove(newNodes);
}
- return v;
+ return result;
}
LocationPath::LocationPath()
- : m_absolute(false)
+ : m_isAbsolute(false)
{
setIsContextNodeSensitive(true);
}
-LocationPath::~LocationPath()
-{
- deleteAllValues(m_steps);
-}
-
Value LocationPath::evaluate() const
{
EvaluationContext& evaluationContext = Expression::evaluationContext();
@@ -102,7 +88,7 @@ Value LocationPath::evaluate() const
// This is for compatibility with Firefox, and also seems like a more
// logical treatment of where you would expect the "root" to be.
Node* context = evaluationContext.node.get();
- if (m_absolute && context->nodeType() != Node::DOCUMENT_NODE) {
+ if (m_isAbsolute && !context->isDocumentNode()) {
if (context->inDocument())
context = context->ownerDocument();
else
@@ -114,15 +100,14 @@ Value LocationPath::evaluate() const
evaluate(nodes);
evaluationContext = backupContext;
- return Value(nodes, Value::adopt);
+ return Value(WTFMove(nodes));
}
void LocationPath::evaluate(NodeSet& nodes) const
{
bool resultIsSorted = nodes.isSorted();
- for (unsigned i = 0; i < m_steps.size(); i++) {
- Step* step = m_steps[i];
+ for (auto& step : m_steps) {
NodeSet newNodes;
HashSet<Node*> newNodesSet;
@@ -136,79 +121,69 @@ void LocationPath::evaluate(NodeSet& nodes) const
if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis))
newNodes.markSubtreesDisjoint(true);
- for (unsigned j = 0; j < nodes.size(); j++) {
+ for (auto& node : nodes) {
NodeSet matches;
- step->evaluate(nodes[j], matches);
+ step->evaluate(*node, matches);
if (!matches.isSorted())
resultIsSorted = false;
- for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) {
- Node* node = matches[nodeIndex];
- if (!needToCheckForDuplicateNodes || newNodesSet.add(node).isNewEntry)
- newNodes.append(node);
+ for (auto& match : matches) {
+ if (!needToCheckForDuplicateNodes || newNodesSet.add(match.get()).isNewEntry)
+ newNodes.append(match.copyRef());
}
}
- nodes.swap(newNodes);
+ nodes = WTFMove(newNodes);
}
nodes.markSorted(resultIsSorted);
}
-void LocationPath::appendStep(Step* step)
+void LocationPath::appendStep(std::unique_ptr<Step> step)
{
unsigned stepCount = m_steps.size();
if (stepCount) {
bool dropSecondStep;
- optimizeStepPair(m_steps[stepCount - 1], step, dropSecondStep);
- if (dropSecondStep) {
- delete step;
+ optimizeStepPair(*m_steps[stepCount - 1], *step, dropSecondStep);
+ if (dropSecondStep)
return;
- }
}
step->optimize();
- m_steps.append(step);
+ m_steps.append(WTFMove(step));
}
-void LocationPath::insertFirstStep(Step* step)
+void LocationPath::prependStep(std::unique_ptr<Step> step)
{
if (m_steps.size()) {
bool dropSecondStep;
- optimizeStepPair(step, m_steps[0], dropSecondStep);
+ optimizeStepPair(*step, *m_steps[0], dropSecondStep);
if (dropSecondStep) {
- delete m_steps[0];
- m_steps[0] = step;
+ m_steps[0] = WTFMove(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());
+ m_steps.insert(0, WTFMove(step));
}
-Path::~Path()
+Path::Path(std::unique_ptr<Expression> filter, std::unique_ptr<LocationPath> path)
+ : m_filter(WTFMove(filter))
+ , m_path(WTFMove(path))
{
- delete m_filter;
- delete m_path;
+ setIsContextNodeSensitive(m_filter->isContextNodeSensitive());
+ setIsContextPositionSensitive(m_filter->isContextPositionSensitive());
+ setIsContextSizeSensitive(m_filter->isContextSizeSensitive());
}
Value Path::evaluate() const
{
- Value v = m_filter->evaluate();
+ Value result = m_filter->evaluate();
- NodeSet& nodes = v.modifiableNodeSet();
+ NodeSet& nodes = result.modifiableNodeSet();
m_path->evaluate(nodes);
- return v;
+ return result;
}
}
diff --git a/Source/WebCore/xml/XPathPath.h b/Source/WebCore/xml/XPathPath.h
index b1a57cbb7..5491618a8 100644
--- a/Source/WebCore/xml/XPathPath.h
+++ b/Source/WebCore/xml/XPathPath.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,60 +28,54 @@
#define XPathPath_h
#include "XPathExpressionNode.h"
-#include "XPathNodeSet.h"
namespace WebCore {
namespace XPath {
- class Predicate;
class Step;
- class Filter : public Expression {
+ class Filter final : public Expression {
public:
- Filter(Expression*, const Vector<Predicate*>& = Vector<Predicate*>());
- virtual ~Filter();
-
- virtual Value evaluate() const;
+ Filter(std::unique_ptr<Expression>, Vector<std::unique_ptr<Expression>> predicates);
private:
- virtual Value::Type resultType() const { return Value::NodeSetValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NodeSetValue; }
- Expression* m_expr;
- Vector<Predicate*> m_predicates;
+ std::unique_ptr<Expression> m_expression;
+ Vector<std::unique_ptr<Expression>> m_predicates;
};
- class LocationPath : public Expression {
+ class LocationPath final : public Expression {
public:
LocationPath();
- virtual ~LocationPath();
- void setAbsolute(bool value) { m_absolute = value; setIsContextNodeSensitive(!m_absolute); }
- virtual Value evaluate() const;
+ void setAbsolute() { m_isAbsolute = true; setIsContextNodeSensitive(false); }
+
void evaluate(NodeSet& nodes) const; // nodes is an input/output parameter
- void appendStep(Step* step);
- void insertFirstStep(Step* step);
+ void appendStep(std::unique_ptr<Step>);
+ void prependStep(std::unique_ptr<Step>);
private:
- virtual Value::Type resultType() const { return Value::NodeSetValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NodeSetValue; }
- Vector<Step*> m_steps;
- bool m_absolute;
+ Vector<std::unique_ptr<Step>> m_steps;
+ bool m_isAbsolute;
};
- class Path : public Expression {
+ class Path final : public Expression {
public:
- Path(Filter*, LocationPath*);
- virtual ~Path();
-
- virtual Value evaluate() const;
+ Path(std::unique_ptr<Expression> filter, std::unique_ptr<LocationPath>);
private:
- virtual Value::Type resultType() const { return Value::NodeSetValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NodeSetValue; }
- Filter* m_filter;
- LocationPath* m_path;
+ std::unique_ptr<Expression> m_filter;
+ std::unique_ptr<LocationPath> m_path;
};
}
diff --git a/Source/WebCore/xml/XPathPredicate.cpp b/Source/WebCore/xml/XPathPredicate.cpp
index 36800a117..ee7cccdba 100644
--- a/Source/WebCore/xml/XPathPredicate.cpp
+++ b/Source/WebCore/xml/XPathPredicate.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -28,10 +28,8 @@
#include "config.h"
#include "XPathPredicate.h"
-#include "Node.h"
#include "XPathFunctions.h"
#include "XPathUtil.h"
-#include "XPathValue.h"
#include <math.h>
#include <wtf/MathExtras.h>
@@ -48,8 +46,8 @@ Value Number::evaluate() const
return m_value;
}
-StringExpression::StringExpression(const String& value)
- : m_value(value)
+StringExpression::StringExpression(String&& value)
+ : m_value(WTFMove(value))
{
}
@@ -58,26 +56,27 @@ Value StringExpression::evaluate() const
return m_value;
}
+Negative::Negative(std::unique_ptr<Expression> expression)
+{
+ addSubexpression(WTFMove(expression));
+}
+
Value Negative::evaluate() const
{
- Value p(subExpr(0)->evaluate());
- return -p.toNumber();
+ return -subexpression(0).evaluate().toNumber();
}
-NumericOp::NumericOp(Opcode opcode, Expression* lhs, Expression* rhs)
+NumericOp::NumericOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs)
: m_opcode(opcode)
{
- addSubExpression(lhs);
- addSubExpression(rhs);
+ addSubexpression(WTFMove(lhs));
+ addSubexpression(WTFMove(rhs));
}
Value NumericOp::evaluate() const
{
- Value lhs(subExpr(0)->evaluate());
- Value rhs(subExpr(1)->evaluate());
-
- double leftVal = lhs.toNumber();
- double rightVal = rhs.toNumber();
+ double leftVal = subexpression(0).evaluate().toNumber();
+ double rightVal = subexpression(1).evaluate().toNumber();
switch (m_opcode) {
case OP_Add:
@@ -91,15 +90,16 @@ Value NumericOp::evaluate() const
case OP_Mod:
return fmod(leftVal, rightVal);
}
+
ASSERT_NOT_REACHED();
return 0.0;
}
-EqTestOp::EqTestOp(Opcode opcode, Expression* lhs, Expression* rhs)
+EqTestOp::EqTestOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs)
: m_opcode(opcode)
{
- addSubExpression(lhs);
- addSubExpression(rhs);
+ addSubexpression(WTFMove(lhs));
+ addSubexpression(WTFMove(rhs));
}
bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
@@ -111,28 +111,32 @@ bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
// 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])))
+ for (auto& lhs : lhsSet) {
+ for (auto& rhs : rhsSet) {
+ if (compare(stringValue(lhs.get()), stringValue(rhs.get())))
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))
+ for (auto& lhs : lhsSet) {
+ if (compare(Value(stringValue(lhs.get())).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))
+ for (auto& lhs : lhsSet) {
+ if (compare(stringValue(lhs.get()), rhs))
return true;
+ }
return false;
}
if (rhs.isBoolean()) {
@@ -141,25 +145,27 @@ bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
// the node-set to a boolean using the boolean function is true.
return compare(lhs.toBoolean(), rhs);
}
- ASSERT(0);
+ ASSERT_NOT_REACHED();
}
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()))
+ for (auto& rhs : rhsSet) {
+ if (compare(lhs, Value(stringValue(rhs.get())).toNumber()))
return true;
+ }
return false;
}
if (lhs.isString()) {
- for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)
- if (compare(lhs, stringValue(rhsSet[rindex])))
+ for (auto& rhs : rhsSet) {
+ if (compare(lhs, stringValue(rhs.get())))
return true;
+ }
return false;
}
if (lhs.isBoolean())
return compare(lhs, rhs.toBoolean());
- ASSERT(0);
+ ASSERT_NOT_REACHED();
}
// Neither side is a NodeSet.
@@ -186,92 +192,86 @@ bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
case OP_LE:
return lhs.toNumber() <= rhs.toNumber();
}
- ASSERT(0);
+
+ ASSERT_NOT_REACHED();
return false;
}
Value EqTestOp::evaluate() const
{
- Value lhs(subExpr(0)->evaluate());
- Value rhs(subExpr(1)->evaluate());
-
+ Value lhs(subexpression(0).evaluate());
+ Value rhs(subexpression(1).evaluate());
return compare(lhs, rhs);
}
-LogicalOp::LogicalOp(Opcode opcode, Expression* lhs, Expression* rhs)
+LogicalOp::LogicalOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs)
: m_opcode(opcode)
{
- addSubExpression(lhs);
- addSubExpression(rhs);
+ addSubexpression(WTFMove(lhs));
+ addSubexpression(WTFMove(rhs));
}
-bool LogicalOp::shortCircuitOn() const
+inline bool LogicalOp::shortCircuitOn() const
{
- if (m_opcode == OP_And)
- return false; //false and foo
-
- return true; //true or bar
+ return m_opcode != OP_And;
}
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();
+ bool lhsBool = subexpression(0).evaluate().toBoolean();
if (lhsBool == shortCircuitOn())
return lhsBool;
- return subExpr(1)->evaluate().toBoolean();
+ return subexpression(1).evaluate().toBoolean();
+}
+
+Union::Union(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs)
+{
+ addSubexpression(WTFMove(lhs));
+ addSubexpression(WTFMove(rhs));
}
Value Union::evaluate() const
{
- Value lhsResult = subExpr(0)->evaluate();
- Value rhs = subExpr(1)->evaluate();
-
+ Value lhsResult = subexpression(0).evaluate();
+ Value rhs = subexpression(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).isNewEntry)
- resultSet.append(node);
+ for (auto& result : resultSet)
+ nodes.add(result.get());
+
+ for (auto& node : rhsNodes) {
+ if (nodes.add(node.get()).isNewEntry)
+ resultSet.append(node.get());
}
- // 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.
+ // It would also be possible to perform a merge sort here to avoid making an unsorted result,
+ // but that 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;
+ return lhsResult;
}
-bool Predicate::evaluate() const
+bool evaluatePredicate(const Expression& expression)
{
- ASSERT(m_expr != 0);
-
- Value result(m_expr->evaluate());
+ Value result(expression.evaluate());
// foo[3] means foo[position()=3]
if (result.isNumber())
- return EqTestOp(EqTestOp::OP_EQ, createFunction("position"), new Number(result.toNumber())).evaluate().toBoolean();
+ return EqTestOp(EqTestOp::OP_EQ, Function::create(ASCIILiteral("position")), std::make_unique<Number>(result.toNumber())).evaluate().toBoolean();
return result.toBoolean();
}
+bool predicateIsContextPositionSensitive(const Expression& expression)
+{
+ return expression.isContextPositionSensitive() || expression.resultType() == Value::NumberValue;
+}
+
}
}
diff --git a/Source/WebCore/xml/XPathPredicate.h b/Source/WebCore/xml/XPathPredicate.h
index 013ccda23..c657c8a55 100644
--- a/Source/WebCore/xml/XPathPredicate.h
+++ b/Source/WebCore/xml/XPathPredicate.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,95 +28,92 @@
#define XPathPredicate_h
#include "XPathExpressionNode.h"
-#include "XPathValue.h"
namespace WebCore {
namespace XPath {
- class Number : public Expression {
+ class Number final : public Expression {
public:
explicit Number(double);
+
private:
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
Value m_value;
};
- class StringExpression : public Expression {
+ class StringExpression final : public Expression {
public:
- explicit StringExpression(const String&);
+ explicit StringExpression(String&&);
+
private:
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::StringValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::StringValue; }
Value m_value;
};
- class Negative : public Expression {
+ class Negative final : public Expression {
+ public:
+ explicit Negative(std::unique_ptr<Expression>);
+
private:
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
};
- class NumericOp : public Expression {
+ class NumericOp final : public Expression {
public:
- enum Opcode {
- OP_Add, OP_Sub, OP_Mul, OP_Div, OP_Mod
- };
- NumericOp(Opcode, Expression* lhs, Expression* rhs);
+ enum Opcode { OP_Add, OP_Sub, OP_Mul, OP_Div, OP_Mod };
+ NumericOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs);
+
private:
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NumberValue; }
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NumberValue; }
Opcode m_opcode;
};
- class EqTestOp : public Expression {
+ class EqTestOp final : 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;
+ EqTestOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs);
+ virtual Value evaluate() const override;
+
private:
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
bool compare(const Value&, const Value&) const;
Opcode m_opcode;
};
- class LogicalOp : public Expression {
+ class LogicalOp final : public Expression {
public:
enum Opcode { OP_And, OP_Or };
- LogicalOp(Opcode, Expression* lhs, Expression* rhs);
+ LogicalOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs);
+
private:
- virtual Value::Type resultType() const { return Value::BooleanValue; }
+ virtual Value::Type resultType() const override { return Value::BooleanValue; }
bool shortCircuitOn() const;
- virtual Value evaluate() const;
+ virtual Value evaluate() const override;
Opcode m_opcode;
};
- class Union : public Expression {
- private:
- virtual Value evaluate() const;
- virtual Value::Type resultType() const { return Value::NodeSetValue; }
- };
-
- class Predicate {
- WTF_MAKE_NONCOPYABLE(Predicate); WTF_MAKE_FAST_ALLOCATED;
+ class Union final : public Expression {
public:
- explicit 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(); }
+ Union(std::unique_ptr<Expression>, std::unique_ptr<Expression>);
private:
- Expression* m_expr;
+ virtual Value evaluate() const override;
+ virtual Value::Type resultType() const override { return Value::NodeSetValue; }
};
+ bool evaluatePredicate(const Expression&);
+ bool predicateIsContextPositionSensitive(const Expression&);
+
}
}
diff --git a/Source/WebCore/xml/XPathResult.cpp b/Source/WebCore/xml/XPathResult.cpp
index 3ea768ac6..82c6c7fa1 100644
--- a/Source/WebCore/xml/XPathResult.cpp
+++ b/Source/WebCore/xml/XPathResult.cpp
@@ -28,7 +28,6 @@
#include "XPathResult.h"
#include "Document.h"
-#include "Node.h"
#include "ExceptionCode.h"
#include "XPathEvaluator.h"
#include "XPathException.h"
diff --git a/Source/WebCore/xml/XPathResult.h b/Source/WebCore/xml/XPathResult.h
index affc076b7..a2140f137 100644
--- a/Source/WebCore/xml/XPathResult.h
+++ b/Source/WebCore/xml/XPathResult.h
@@ -53,7 +53,7 @@ namespace WebCore {
FIRST_ORDERED_NODE_TYPE = 9
};
- static PassRefPtr<XPathResult> create(Document* document, const XPath::Value& value) { return adoptRef(new XPathResult(document, value)); }
+ static Ref<XPathResult> create(Document* document, const XPath::Value& value) { return adoptRef(*new XPathResult(document, value)); }
~XPathResult();
void convertTo(unsigned short type, ExceptionCode&);
diff --git a/Source/WebCore/xml/XPathResult.idl b/Source/WebCore/xml/XPathResult.idl
index 9a047ad1f..15d06e3f2 100644
--- a/Source/WebCore/xml/XPathResult.idl
+++ b/Source/WebCore/xml/XPathResult.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,7 +19,7 @@
[
JSCustomMarkFunction,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface XPathResult {
const unsigned short ANY_TYPE = 0;
const unsigned short NUMBER_TYPE = 1;
@@ -33,16 +33,16 @@
const unsigned short FIRST_ORDERED_NODE_TYPE = 9;
readonly attribute unsigned short resultType;
- [GetterRaisesException] readonly attribute double numberValue;
+ [GetterRaisesException] readonly attribute unrestricted double numberValue;
- [GetterRaisesException] readonly attribute DOMString stringValue;
+ [GetterRaisesException] readonly attribute DOMString stringValue;
- [GetterRaisesException] readonly attribute boolean booleanValue;
+ [GetterRaisesException] readonly attribute boolean booleanValue;
- [GetterRaisesException] readonly attribute Node singleNodeValue;
+ [GetterRaisesException] readonly attribute Node singleNodeValue;
readonly attribute boolean invalidIteratorState;
- [GetterRaisesException] readonly attribute unsigned long snapshotLength;
+ [GetterRaisesException] readonly attribute unsigned long snapshotLength;
[RaisesException] Node iterateNext();
[RaisesException] Node snapshotItem([Default=Undefined] optional unsigned long index);
diff --git a/Source/WebCore/xml/XPathStep.cpp b/Source/WebCore/xml/XPathStep.cpp
index 154dcd894..0ae340360 100644
--- a/Source/WebCore/xml/XPathStep.cpp
+++ b/Source/WebCore/xml/XPathStep.cpp
@@ -30,7 +30,8 @@
#include "Attr.h"
#include "Document.h"
-#include "Element.h"
+#include "HTMLDocument.h"
+#include "HTMLElement.h"
#include "NodeTraversal.h"
#include "XMLNSNames.h"
#include "XPathParser.h"
@@ -39,17 +40,21 @@
namespace WebCore {
namespace XPath {
-Step::Step(Axis axis, const NodeTest& nodeTest, const Vector<Predicate*>& predicates)
+Step::Step(Axis axis, NodeTest nodeTest)
: m_axis(axis)
- , m_nodeTest(nodeTest)
- , m_predicates(predicates)
+ , m_nodeTest(WTFMove(nodeTest))
+{
+}
+
+Step::Step(Axis axis, NodeTest nodeTest, Vector<std::unique_ptr<Expression>> predicates)
+ : m_axis(axis)
+ , m_nodeTest(WTFMove(nodeTest))
+ , m_predicates(WTFMove(predicates))
{
}
Step::~Step()
{
- deleteAllValues(m_predicates);
- deleteAllValues(m_nodeTest.mergedPredicates());
}
void Step::optimize()
@@ -57,59 +62,65 @@ 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);
+ Vector<std::unique_ptr<Expression>> remainingPredicates;
+ for (auto& predicate : m_predicates) {
+ if ((!predicateIsContextPositionSensitive(*predicate) || m_nodeTest.m_mergedPredicates.isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates.isEmpty())
+ m_nodeTest.m_mergedPredicates.append(WTFMove(predicate));
+ else
+ remainingPredicates.append(WTFMove(predicate));
}
- swap(remainingPredicates, m_predicates);
+ m_predicates = WTFMove(remainingPredicates);
}
-void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep)
+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;
- }
- }
+ if (first.m_axis != Step::DescendantOrSelfAxis)
+ return;
+
+ if (first.m_nodeTest.m_kind != Step::NodeTest::AnyNodeTest)
+ return;
+
+ if (!first.m_predicates.isEmpty())
+ return;
+
+ if (!first.m_nodeTest.m_mergedPredicates.isEmpty())
+ return;
+
+ ASSERT(first.m_nodeTest.m_data.isEmpty());
+ ASSERT(first.m_nodeTest.m_namespaceURI.isEmpty());
+
+ // Optimize the common case of "//" AKA /descendant-or-self::node()/child::NodeTest to /descendant::NodeTest.
+ if (second.m_axis != Step::ChildAxis)
+ return;
+
+ if (!second.predicatesAreContextListInsensitive())
+ return;
+
+ first.m_axis = Step::DescendantAxis;
+ first.m_nodeTest = WTFMove(second.m_nodeTest);
+ first.m_predicates = WTFMove(second.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())
+ for (auto& predicate : m_predicates) {
+ if (predicateIsContextPositionSensitive(*predicate) || 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())
+ for (auto& predicate : m_nodeTest.m_mergedPredicates) {
+ if (predicateIsContextPositionSensitive(*predicate) || predicate->isContextSizeSensitive())
return false;
}
return true;
}
-void Step::evaluate(Node* context, NodeSet& nodes) const
+void Step::evaluate(Node& context, NodeSet& nodes) const
{
EvaluationContext& evaluationContext = Expression::evaluationContext();
evaluationContext.position = 0;
@@ -117,9 +128,7 @@ void Step::evaluate(Node* context, NodeSet& nodes) const
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];
-
+ for (auto& predicate : m_predicates) {
NodeSet newNodes;
if (!nodes.isSorted())
newNodes.markSorted(false);
@@ -130,55 +139,55 @@ void Step::evaluate(Node* context, NodeSet& nodes) const
evaluationContext.node = node;
evaluationContext.size = nodes.size();
evaluationContext.position = j + 1;
- if (predicate->evaluate())
+ if (evaluatePredicate(*predicate))
newNodes.append(node);
}
- nodes.swap(newNodes);
+ nodes = WTFMove(newNodes);
}
}
+#if !ASSERT_DISABLED
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;
}
}
+#endif
// Evaluate NodeTest without considering merged predicates.
-static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest)
+inline bool nodeMatchesBasicTest(Node& node, Step::Axis axis, const Step::NodeTest& nodeTest)
{
- switch (nodeTest.kind()) {
+ switch (nodeTest.m_kind) {
case Step::NodeTest::TextNodeTest:
- return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE;
+ return node.nodeType() == Node::TEXT_NODE || node.nodeType() == Node::CDATA_SECTION_NODE;
case Step::NodeTest::CommentNodeTest:
- return node->nodeType() == Node::COMMENT_NODE;
+ 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);
+ const AtomicString& name = nodeTest.m_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();
+ const AtomicString& name = nodeTest.m_data;
+ const AtomicString& namespaceURI = nodeTest.m_namespaceURI;
if (axis == Step::AttributeAxis) {
- ASSERT(node->isAttributeNode());
+ ASSERT(node.isAttributeNode());
// In XPath land, namespace nodes are not accessible on the attribute axis.
- if (node->namespaceURI() == XMLNSNames::xmlnsNamespaceURI)
+ if (node.namespaceURI() == XMLNSNames::xmlnsNamespaceURI)
return false;
if (name == starAtom)
- return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI;
+ return namespaceURI.isEmpty() || node.namespaceURI() == namespaceURI;
- return node->localName() == name && 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.
@@ -186,28 +195,28 @@ static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step:
// For other axes, the principal node type is element.
ASSERT(primaryNodeType(axis) == Node::ELEMENT_NODE);
- if (node->nodeType() != Node::ELEMENT_NODE)
+ if (!is<Element>(node))
return false;
if (name == starAtom)
- return namespaceURI.isEmpty() || namespaceURI == node->namespaceURI();
+ return namespaceURI.isEmpty() || namespaceURI == node.namespaceURI();
- if (node->document()->isHTMLDocument()) {
- if (node->isHTMLElement()) {
+ if (is<HTMLDocument>(node.document())) {
+ if (is<HTMLElement>(node)) {
// Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively.
- return equalIgnoringCase(toElement(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI());
+ return equalIgnoringASCIICase(downcast<HTMLElement>(node).localName(), name) && (namespaceURI.isNull() || namespaceURI == node.namespaceURI());
}
// An expression without any prefix shouldn't match no-namespace nodes (because HTML5 says so).
- return toElement(node)->hasLocalName(name) && namespaceURI == node->namespaceURI() && !namespaceURI.isNull();
+ return downcast<Element>(node).hasLocalName(name) && namespaceURI == node.namespaceURI() && !namespaceURI.isNull();
}
- return toElement(node)->hasLocalName(name) && namespaceURI == node->namespaceURI();
+ return downcast<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)
+inline bool nodeMatches(Node& node, Step::Axis axis, const Step::NodeTest& nodeTest)
{
if (!nodeMatchesBasicTest(node, axis, nodeTest))
return false;
@@ -217,13 +226,10 @@ static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
// 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;
+ for (auto& predicate : nodeTest.m_mergedPredicates) {
// No need to set context size - we only get here when evaluating predicates that do not depend on it.
- if (!predicate->evaluate())
+ evaluationContext.node = &node;
+ if (!evaluatePredicate(*predicate))
return false;
}
@@ -231,124 +237,126 @@ static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
}
// Result nodes are ordered in axis order. Node test (including merged predicates) is applied.
-void Step::nodesInAxis(Node* context, NodeSet& nodes) const
+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.
+ 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);
+ for (Node* node = context.firstChild(); node; node = node->nextSibling()) {
+ if (nodeMatches(*node, ChildAxis, m_nodeTest))
+ nodes.append(node);
+ }
return;
case DescendantAxis:
- if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
+ if (context.isAttributeNode()) // In XPath model, attribute nodes do not have children.
return;
-
- for (Node* n = context->firstChild(); n; n = NodeTraversal::next(n, context))
- if (nodeMatches(n, DescendantAxis, m_nodeTest))
- nodes.append(n);
+ for (Node* node = context.firstChild(); node; node = NodeTraversal::next(*node, &context)) {
+ if (nodeMatches(*node, DescendantAxis, m_nodeTest))
+ nodes.append(node);
+ }
return;
case ParentAxis:
- if (context->isAttributeNode()) {
- Element* n = static_cast<Attr*>(context)->ownerElement();
- if (nodeMatches(n, ParentAxis, m_nodeTest))
- nodes.append(n);
+ if (context.isAttributeNode()) {
+ Element* node = static_cast<Attr&>(context).ownerElement();
+ if (nodeMatches(*node, ParentAxis, m_nodeTest))
+ nodes.append(node);
} else {
- ContainerNode* n = context->parentNode();
- if (n && nodeMatches(n, ParentAxis, m_nodeTest))
- nodes.append(n);
+ ContainerNode* node = context.parentNode();
+ if (node && nodeMatches(*node, ParentAxis, m_nodeTest))
+ nodes.append(node);
}
return;
case AncestorAxis: {
- Node* n = context;
- if (context->isAttributeNode()) {
- n = static_cast<Attr*>(context)->ownerElement();
- if (nodeMatches(n, AncestorAxis, m_nodeTest))
- nodes.append(n);
+ Node* node = &context;
+ if (context.isAttributeNode()) {
+ node = static_cast<Attr&>(context).ownerElement();
+ if (nodeMatches(*node, AncestorAxis, m_nodeTest))
+ nodes.append(node);
+ }
+ for (node = node->parentNode(); node; node = node->parentNode()) {
+ if (nodeMatches(*node, AncestorAxis, m_nodeTest))
+ nodes.append(node);
}
- 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)
+ if (context.isAttributeNode())
return;
-
- for (Node* n = context->nextSibling(); n; n = n->nextSibling())
- if (nodeMatches(n, FollowingSiblingAxis, m_nodeTest))
- nodes.append(n);
+ for (Node* node = context.nextSibling(); node; node = node->nextSibling()) {
+ if (nodeMatches(*node, FollowingSiblingAxis, m_nodeTest))
+ nodes.append(node);
+ }
return;
case PrecedingSiblingAxis:
- if (context->nodeType() == Node::ATTRIBUTE_NODE ||
- context->nodeType() == Node::XPATH_NAMESPACE_NODE)
+ if (context.isAttributeNode())
return;
-
- for (Node* n = context->previousSibling(); n; n = n->previousSibling())
- if (nodeMatches(n, PrecedingSiblingAxis, m_nodeTest))
- nodes.append(n);
-
+ for (Node* node = context.previousSibling(); node; node = node->previousSibling()) {
+ if (nodeMatches(*node, PrecedingSiblingAxis, m_nodeTest))
+ nodes.append(node);
+ }
nodes.markSorted(false);
return;
case FollowingAxis:
- if (context->isAttributeNode()) {
- Node* p = static_cast<Attr*>(context)->ownerElement();
- while ((p = NodeTraversal::next(p)))
- if (nodeMatches(p, FollowingAxis, m_nodeTest))
- nodes.append(p);
+ if (context.isAttributeNode()) {
+ Node* node = static_cast<Attr&>(context).ownerElement();
+ while ((node = NodeTraversal::next(*node))) {
+ if (nodeMatches(*node, FollowingAxis, m_nodeTest))
+ nodes.append(node);
+ }
} 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 = NodeTraversal::next(c, n))
- if (nodeMatches(c, FollowingAxis, m_nodeTest))
- nodes.append(c);
+ for (Node* parent = &context; !isRootDomNode(parent); parent = parent->parentNode()) {
+ for (Node* node = parent->nextSibling(); node; node = node->nextSibling()) {
+ if (nodeMatches(*node, FollowingAxis, m_nodeTest))
+ nodes.append(node);
+ for (Node* child = node->firstChild(); child; child = NodeTraversal::next(*child, node)) {
+ if (nodeMatches(*child, FollowingAxis, m_nodeTest))
+ nodes.append(child);
+ }
}
}
}
return;
case PrecedingAxis: {
- if (context->isAttributeNode())
- context = static_cast<Attr*>(context)->ownerElement();
-
- Node* n = context;
- while (ContainerNode* parent = n->parentNode()) {
- for (n = NodeTraversal::previous(n); n != parent; n = NodeTraversal::previous(n))
- if (nodeMatches(n, PrecedingAxis, m_nodeTest))
- nodes.append(n);
- n = parent;
+ Node* node;
+ if (context.isAttributeNode())
+ node = static_cast<Attr&>(context).ownerElement();
+ else
+ node = &context;
+ while (ContainerNode* parent = node->parentNode()) {
+ for (node = NodeTraversal::previous(*node); node != parent; node = NodeTraversal::previous(*node)) {
+ if (nodeMatches(*node, PrecedingAxis, m_nodeTest))
+ nodes.append(node);
+ }
+ node = parent;
}
nodes.markSorted(false);
return;
}
case AttributeAxis: {
- if (!context->isElementNode())
+ if (!is<Element>(context))
return;
- Element* contextElement = toElement(context);
+ Element& contextElement = downcast<Element>(context);
// 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 = contextElement->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());
+ if (m_nodeTest.m_kind == NodeTest::NameTest && m_nodeTest.m_data != starAtom) {
+ RefPtr<Attr> attr = contextElement.getAttributeNodeNS(m_nodeTest.m_namespaceURI, m_nodeTest.m_data);
+ if (attr && attr->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (nodeMatches(*attr, AttributeAxis, m_nodeTest)) // Still need to check merged predicates.
+ nodes.append(attr.release());
}
return;
}
- if (!contextElement->hasAttributes())
+ if (!contextElement.hasAttributes())
return;
- for (unsigned i = 0; i < contextElement->attributeCount(); ++i) {
- RefPtr<Attr> attr = contextElement->ensureAttr(contextElement->attributeItem(i)->name());
- if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest))
+ for (const Attribute& attribute : contextElement.attributesIterator()) {
+ RefPtr<Attr> attr = contextElement.ensureAttr(attribute.name());
+ if (nodeMatches(*attr, AttributeAxis, m_nodeTest))
nodes.append(attr.release());
}
return;
@@ -358,31 +366,31 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
case SelfAxis:
if (nodeMatches(context, SelfAxis, m_nodeTest))
- nodes.append(context);
+ 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.
+ nodes.append(&context);
+ if (context.isAttributeNode()) // In XPath model, attribute nodes do not have children.
return;
-
- for (Node* n = context->firstChild(); n; n = NodeTraversal::next(n, context))
- if (nodeMatches(n, DescendantOrSelfAxis, m_nodeTest))
- nodes.append(n);
+ for (Node* node = context.firstChild(); node; node = NodeTraversal::next(*node, &context)) {
+ if (nodeMatches(*node, DescendantOrSelfAxis, m_nodeTest))
+ nodes.append(node);
+ }
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);
+ nodes.append(&context);
+ Node* node = &context;
+ if (context.isAttributeNode()) {
+ node = static_cast<Attr&>(context).ownerElement();
+ if (nodeMatches(*node, AncestorOrSelfAxis, m_nodeTest))
+ nodes.append(node);
+ }
+ for (node = node->parentNode(); node; node = node->parentNode()) {
+ if (nodeMatches(*node, AncestorOrSelfAxis, m_nodeTest))
+ nodes.append(node);
}
- for (n = n->parentNode(); n; n = n->parentNode())
- if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
- nodes.append(n);
-
nodes.markSorted(false);
return;
}
@@ -390,6 +398,5 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
ASSERT_NOT_REACHED();
}
-
}
}
diff --git a/Source/WebCore/xml/XPathStep.h b/Source/WebCore/xml/XPathStep.h
index f678f9228..edfc87337 100644
--- a/Source/WebCore/xml/XPathStep.h
+++ b/Source/WebCore/xml/XPathStep.h
@@ -27,8 +27,8 @@
#ifndef XPathStep_h
#define XPathStep_h
-#include "XPathExpressionNode.h"
-#include "XPathNodeSet.h"
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
namespace WebCore {
@@ -36,10 +36,10 @@ class Node;
namespace XPath {
-class Predicate;
-
-class Step : public ParseNode {
- WTF_MAKE_NONCOPYABLE(Step);
+class Expression;
+class NodeSet;
+
+class Step {
WTF_MAKE_FAST_ALLOCATED;
public:
enum Axis {
@@ -49,57 +49,73 @@ public:
ParentAxis, PrecedingAxis, PrecedingSiblingAxis,
SelfAxis
};
-
+
class NodeTest {
WTF_MAKE_FAST_ALLOCATED;
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; }
-
+ enum Kind { TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest };
+
+ explicit NodeTest(Kind kind) : m_kind(kind) { }
+ NodeTest(Kind kind, const AtomicString& data) : m_kind(kind), m_data(data) { }
+ NodeTest(Kind kind, const AtomicString& data, const AtomicString& namespaceURI) : m_kind(kind), m_data(data), m_namespaceURI(namespaceURI) { }
+
+#if COMPILER(MSVC)
+ NodeTest(const NodeTest&);
+ void operator=(const NodeTest&);
+
+ NodeTest(NodeTest&& other)
+ : m_kind(other.m_kind)
+ , m_data(WTFMove(other.m_data))
+ , m_namespaceURI(WTFMove(other.m_namespaceURI))
+ , m_mergedPredicates(WTFMove(other.m_mergedPredicates))
+ {
+ }
+ NodeTest& operator=(NodeTest&& other)
+ {
+ m_kind = other.m_kind;
+ m_data = WTFMove(other.m_data);
+ m_namespaceURI = WTFMove(other.m_namespaceURI);
+ m_mergedPredicates = WTFMove(other.m_mergedPredicates);
+ return *this;
+ }
+#endif
+
private:
+ friend class Step;
+ friend void optimizeStepPair(Step&, Step&, bool&);
+ friend bool nodeMatchesBasicTest(Node&, Axis, const NodeTest&);
+ friend bool nodeMatches(Node&, Axis, const NodeTest&);
+
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;
+ Vector<std::unique_ptr<Expression>> m_mergedPredicates;
};
- Step(Axis, const NodeTest&, const Vector<Predicate*>& predicates = Vector<Predicate*>());
+ Step(Axis, NodeTest);
+ Step(Axis, NodeTest, Vector<std::unique_ptr<Expression>>);
~Step();
void optimize();
- void evaluate(Node* context, NodeSet&) const;
+ 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&);
+ 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;
+ void nodesInAxis(Node& context, NodeSet&) const;
Axis m_axis;
NodeTest m_nodeTest;
- Vector<Predicate*> m_predicates;
+ Vector<std::unique_ptr<Expression>> m_predicates;
};
-void optimizeStepPair(Step*, Step*, bool& dropSecondStep);
+void optimizeStepPair(Step&, Step&, bool& dropSecondStep);
} // namespace XPath
diff --git a/Source/WebCore/xml/XPathUtil.cpp b/Source/WebCore/xml/XPathUtil.cpp
index 3a790e809..03127af5b 100644
--- a/Source/WebCore/xml/XPathUtil.cpp
+++ b/Source/WebCore/xml/XPathUtil.cpp
@@ -28,7 +28,7 @@
#include "XPathUtil.h"
#include "ContainerNode.h"
-#include "NodeTraversal.h"
+#include "TextNodeTraversal.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -47,24 +47,11 @@ String stringValue(Node* 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) {
- StringBuilder result;
- result.reserveCapacity(1024);
-
- for (Node* n = node->firstChild(); n; n = NodeTraversal::next(n, node)) {
- if (n->isTextNode()) {
- const String& nodeValue = n->nodeValue();
- result.append(nodeValue);
- }
- }
-
- return result.toString();
- }
+ if (isRootDomNode(node) || node->isElementNode())
+ return TextNodeTraversal::contentsAsString(*node);
}
-
return String();
}
@@ -79,13 +66,9 @@ bool isValidContextNode(Node* 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());
diff --git a/Source/WebCore/xml/XPathUtil.h b/Source/WebCore/xml/XPathUtil.h
index e0c877234..8d837cf83 100644
--- a/Source/WebCore/xml/XPathUtil.h
+++ b/Source/WebCore/xml/XPathUtil.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/Source/WebCore/xml/XPathValue.cpp b/Source/WebCore/xml/XPathValue.cpp
index ed43f48be..14095053a 100644
--- a/Source/WebCore/xml/XPathValue.cpp
+++ b/Source/WebCore/xml/XPathValue.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,31 +27,27 @@
#include "config.h"
#include "XPathValue.h"
-#include "Node.h"
#include "XPathExpressionNode.h"
#include "XPathUtil.h"
#include <limits>
#include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.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, ());
+ static NeverDestroyed<NodeSet> emptyNodeSet;
return emptyNodeSet;
}
- return m_data->m_nodeSet;
+ return m_data->nodeSet;
}
NodeSet& Value::modifiableNodeSet()
@@ -60,23 +56,23 @@ NodeSet& Value::modifiableNodeSet()
Expression::evaluationContext().hadTypeConversionError = true;
if (!m_data)
- m_data = ValueData::create();
-
+ m_data = Data::create();
+
m_type = NodeSetValue;
- return m_data->m_nodeSet;
+ return m_data->nodeSet;
}
bool Value::toBoolean() const
{
switch (m_type) {
case NodeSetValue:
- return !m_data->m_nodeSet.isEmpty();
+ return !m_data->nodeSet.isEmpty();
case BooleanValue:
return m_bool;
case NumberValue:
return m_number && !std::isnan(m_number);
case StringValue:
- return !m_data->m_string.isEmpty();
+ return !m_data->string.isEmpty();
}
ASSERT_NOT_REACHED();
return false;
@@ -90,25 +86,26 @@ double Value::toNumber() const
case NumberValue:
return m_number;
case StringValue: {
- const String& str = m_data->m_string.simplifyWhiteSpace();
+ const String& str = m_data->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();
+ return std::numeric_limits<double>::quiet_NaN();
}
bool canConvert;
double value = str.toDouble(&canConvert);
if (canConvert)
return value;
- return numeric_limits<double>::quiet_NaN();
+ return std::numeric_limits<double>::quiet_NaN();
}
case BooleanValue:
return m_bool;
}
+
ASSERT_NOT_REACHED();
return 0.0;
}
@@ -117,22 +114,23 @@ String Value::toString() const
{
switch (m_type) {
case NodeSetValue:
- if (m_data->m_nodeSet.isEmpty())
- return "";
- return stringValue(m_data->m_nodeSet.firstNode());
+ if (m_data->nodeSet.isEmpty())
+ return emptyString();
+ return stringValue(m_data->nodeSet.firstNode());
case StringValue:
- return m_data->m_string;
+ return m_data->string;
case NumberValue:
if (std::isnan(m_number))
- return "NaN";
+ return ASCIILiteral("NaN");
if (m_number == 0)
- return "0";
+ return ASCIILiteral("0");
if (std::isinf(m_number))
- return std::signbit(m_number) ? "-Infinity" : "Infinity";
+ return ASCIILiteral(std::signbit(m_number) ? "-Infinity" : "Infinity");
return String::number(m_number);
case BooleanValue:
- return m_bool ? "true" : "false";
+ return ASCIILiteral(m_bool ? "true" : "false");
}
+
ASSERT_NOT_REACHED();
return String();
}
diff --git a/Source/WebCore/xml/XPathValue.h b/Source/WebCore/xml/XPathValue.h
index 490bb2d7b..3f3c51e28 100644
--- a/Source/WebCore/xml/XPathValue.h
+++ b/Source/WebCore/xml/XPathValue.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,46 +28,31 @@
#define XPathValue_h
#include "XPathNodeSet.h"
-#include <wtf/text/WTFString.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() { }
- explicit ValueData(const NodeSet& nodeSet) : m_nodeSet(nodeSet) { }
- explicit 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); }
+ Value(bool value) : m_type(BooleanValue), m_bool(value) { }
+ Value(unsigned value) : m_type(NumberValue), m_number(value) { }
+ Value(double value) : m_type(NumberValue), m_number(value) { }
- // This is needed to safely implement constructing from bool - with normal function overloading, any pointer type would match.
- template<typename T> Value(T);
+ Value(const String& value) : m_type(StringValue), m_data(Data::create(value)) { }
+ Value(const char* value) : m_type(StringValue), m_data(Data::create(value)) { }
- 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); }
+ explicit Value(NodeSet&& value)
+ : m_type(NodeSetValue), m_data(Data::create(WTFMove(value)))
+ { }
+ explicit Value(Node* value)
+ : m_type(NodeSetValue), m_data(Data::create(value))
+ { }
+ explicit Value(RefPtr<Node>&& value)
+ : m_type(NodeSetValue), m_data(Data::create(WTFMove(value)))
+ { }
Type type() const { return m_type; }
@@ -77,25 +62,45 @@ namespace WebCore {
bool isString() const { return m_type == StringValue; }
const NodeSet& toNodeSet() const;
- NodeSet& modifiableNodeSet();
bool toBoolean() const;
double toNumber() const;
String toString() const;
+ // Note that the NodeSet is shared with other Values that this one was copied from or that are copies of this one.
+ NodeSet& modifiableNodeSet();
+
private:
+ // This constructor creates ambiguity so that we don't accidentally call the boolean overload for pointer types.
+ Value(void*) = delete;
+
+ struct Data : public RefCounted<Data> {
+ static Ref<Data> create() { return adoptRef(*new Data); }
+ static Ref<Data> create(const String& string) { return adoptRef(*new Data(string)); }
+ static Ref<Data> create(NodeSet&& nodeSet) { return adoptRef(*new Data(WTFMove(nodeSet))); }
+ static Ref<Data> create(RefPtr<Node>&& node) { return adoptRef(*new Data(WTFMove(node))); }
+
+ String string;
+ NodeSet nodeSet;
+
+ private:
+ Data() { }
+ explicit Data(const String& string)
+ : string(string)
+ { }
+ explicit Data(NodeSet&& nodeSet)
+ : nodeSet(WTFMove(nodeSet))
+ { }
+ explicit Data(RefPtr<Node>&& node)
+ : nodeSet(WTFMove(node))
+ { }
+ };
+
Type m_type;
bool m_bool;
double m_number;
- RefPtr<ValueData> m_data;
+ RefPtr<Data> m_data;
};
- template<>
- inline Value::Value(bool value)
- : m_type(BooleanValue)
- , m_bool(value)
- , m_number(0)
- {
- }
}
}
diff --git a/Source/WebCore/xml/XPathVariableReference.cpp b/Source/WebCore/xml/XPathVariableReference.cpp
index ae2b29a3a..274ce5ab1 100644
--- a/Source/WebCore/xml/XPathVariableReference.cpp
+++ b/Source/WebCore/xml/XPathVariableReference.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,8 +27,6 @@
#include "config.h"
#include "XPathVariableReference.h"
-#include "Node.h"
-#include "XPathValue.h"
namespace WebCore {
namespace XPath {
diff --git a/Source/WebCore/xml/XSLImportRule.cpp b/Source/WebCore/xml/XSLImportRule.cpp
index e62959e99..e99c424ef 100644
--- a/Source/WebCore/xml/XSLImportRule.cpp
+++ b/Source/WebCore/xml/XSLImportRule.cpp
@@ -28,14 +28,13 @@
#include "CachedResourceLoader.h"
#include "CachedResourceRequest.h"
#include "Document.h"
-#include "XSLStyleSheet.h"
namespace WebCore {
XSLImportRule::XSLImportRule(XSLStyleSheet* parent, const String& href)
: m_parentStyleSheet(parent)
, m_strHref(href)
- , m_cachedSheet(0)
+ , m_cachedSheet(nullptr)
, m_loading(false)
{
}
@@ -43,16 +42,16 @@ XSLImportRule::XSLImportRule(XSLStyleSheet* parent, const String& href)
XSLImportRule::~XSLImportRule()
{
if (m_styleSheet)
- m_styleSheet->setParentStyleSheet(0);
+ m_styleSheet->setParentStyleSheet(nullptr);
if (m_cachedSheet)
m_cachedSheet->removeClient(this);
}
-void XSLImportRule::setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet)
+void XSLImportRule::setXSLStyleSheet(const String& href, const URL& baseURL, const String& sheet)
{
if (m_styleSheet)
- m_styleSheet->setParentStyleSheet(0);
+ m_styleSheet->setParentStyleSheet(nullptr);
m_styleSheet = XSLStyleSheet::create(this, href, baseURL);
@@ -74,7 +73,7 @@ bool XSLImportRule::isLoading()
void XSLImportRule::loadSheet()
{
- CachedResourceLoader* cachedResourceLoader = 0;
+ CachedResourceLoader* cachedResourceLoader = nullptr;
XSLStyleSheet* rootSheet = parentStyleSheet();
@@ -90,7 +89,7 @@ void XSLImportRule::loadSheet()
XSLStyleSheet* parentSheet = parentStyleSheet();
if (!parentSheet->baseURL().isNull())
// use parent styleheet's URL as the base URL
- absHref = KURL(parentSheet->baseURL(), m_strHref).string();
+ absHref = URL(parentSheet->baseURL(), 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.
@@ -100,6 +99,8 @@ void XSLImportRule::loadSheet()
}
CachedResourceRequest request(ResourceRequest(cachedResourceLoader->document()->completeURL(absHref)));
+ if (m_cachedSheet)
+ m_cachedSheet->removeClient(this);
m_cachedSheet = cachedResourceLoader->requestXSLStyleSheet(request);
if (m_cachedSheet) {
diff --git a/Source/WebCore/xml/XSLImportRule.h b/Source/WebCore/xml/XSLImportRule.h
index 350cdd9b1..252d07fa6 100644
--- a/Source/WebCore/xml/XSLImportRule.h
+++ b/Source/WebCore/xml/XSLImportRule.h
@@ -28,7 +28,6 @@
#include "CachedResourceHandle.h"
#include "CachedStyleSheetClient.h"
#include "XSLStyleSheet.h"
-#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -37,11 +36,7 @@ class CachedXSLStyleSheet;
class XSLImportRule : private CachedStyleSheetClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<XSLImportRule> create(XSLStyleSheet* parentSheet, const String& href)
- {
- return adoptPtr(new XSLImportRule(parentSheet, href));
- }
-
+ XSLImportRule(XSLStyleSheet* parentSheet, const String& href);
virtual ~XSLImportRule();
const String& href() const { return m_strHref; }
@@ -54,9 +49,7 @@ public:
void loadSheet();
private:
- XSLImportRule(XSLStyleSheet* parentSheet, const String& href);
-
- virtual void setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet);
+ virtual void setXSLStyleSheet(const String& href, const URL& baseURL, const String& sheet);
XSLStyleSheet* m_parentStyleSheet;
String m_strHref;
diff --git a/Source/WebCore/xml/XSLStyleSheet.h b/Source/WebCore/xml/XSLStyleSheet.h
index 8d263a752..5f60dd711 100644
--- a/Source/WebCore/xml/XSLStyleSheet.h
+++ b/Source/WebCore/xml/XSLStyleSheet.h
@@ -28,40 +28,37 @@
#include "ProcessingInstruction.h"
#include "StyleSheet.h"
-#if !USE(QXMLQUERY)
#include <libxml/parser.h>
#include <libxslt/transform.h>
-#endif
-#include <wtf/PassRefPtr.h>
+#include <wtf/Ref.h>
+#include <wtf/TypeCasts.h>
namespace WebCore {
class CachedResourceLoader;
class XSLImportRule;
-class XSLStyleSheet : public StyleSheet {
+class XSLStyleSheet final : public StyleSheet {
public:
-#if !USE(QXMLQUERY)
- static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& originalURL, const KURL& finalURL)
+ static Ref<XSLStyleSheet> create(XSLImportRule* parentImport, const String& originalURL, const URL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentImport, originalURL, finalURL));
+ return adoptRef(*new XSLStyleSheet(parentImport, originalURL, finalURL));
}
-#endif
- static PassRefPtr<XSLStyleSheet> create(ProcessingInstruction* parentNode, const String& originalURL, const KURL& finalURL)
+ static Ref<XSLStyleSheet> create(ProcessingInstruction* parentNode, const String& originalURL, const URL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentNode, originalURL, finalURL, false));
+ return adoptRef(*new XSLStyleSheet(parentNode, originalURL, finalURL, false));
}
- static PassRefPtr<XSLStyleSheet> createEmbedded(ProcessingInstruction* parentNode, const KURL& finalURL)
+ static Ref<XSLStyleSheet> createEmbedded(ProcessingInstruction* parentNode, const URL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentNode, finalURL.string(), finalURL, true));
+ 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)
+ static Ref<XSLStyleSheet> createForXSLTProcessor(Node* parentNode, const String& originalURL, const URL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentNode, originalURL, finalURL, false));
+ return adoptRef(*new XSLStyleSheet(parentNode, originalURL, finalURL, false));
}
virtual ~XSLStyleSheet();
@@ -70,7 +67,7 @@ public:
void checkLoaded();
- const KURL& finalURL() const { return m_finalURL; }
+ const URL& finalURL() const { return m_finalURL; }
void loadChildSheets();
void loadChildSheet(const String& href);
@@ -78,63 +75,58 @@ public:
CachedResourceLoader* cachedResourceLoader();
Document* ownerDocument();
- virtual XSLStyleSheet* parentStyleSheet() const OVERRIDE { return m_parentStyleSheet; }
+ virtual XSLStyleSheet* parentStyleSheet() const override { return m_parentStyleSheet; }
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; }
- virtual String type() const OVERRIDE { return "text/xml"; }
- virtual bool disabled() const OVERRIDE { return m_isDisabled; }
- virtual void setDisabled(bool b) OVERRIDE { m_isDisabled = b; }
- virtual Node* ownerNode() const OVERRIDE { return m_ownerNode; }
- virtual String href() const OVERRIDE { return m_originalURL; }
- virtual String title() const OVERRIDE { return emptyString(); }
+ virtual String type() const override { return "text/xml"; }
+ virtual bool disabled() const override { return m_isDisabled; }
+ virtual void setDisabled(bool b) override { m_isDisabled = b; }
+ virtual Node* ownerNode() const override { return m_ownerNode; }
+ virtual String href() const override { return m_originalURL; }
+ virtual String title() const override { return emptyString(); }
- virtual void clearOwnerNode() OVERRIDE { m_ownerNode = 0; }
- virtual KURL baseURL() const OVERRIDE { return m_finalURL; }
- virtual bool isLoading() const OVERRIDE;
-
- virtual bool isXSLStyleSheet() const OVERRIDE { return true; }
+ virtual void clearOwnerNode() override { m_ownerNode = nullptr; }
+ virtual URL baseURL() const override { return m_finalURL; }
+ virtual bool isLoading() const override;
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
+ XSLStyleSheet(Node* parentNode, const String& originalURL, const URL& finalURL, bool embedded);
+ XSLStyleSheet(XSLImportRule* parentImport, const String& originalURL, const URL& finalURL);
+
+ virtual bool isXSLStyleSheet() const override { return true; }
Node* m_ownerNode;
String m_originalURL;
- KURL m_finalURL;
+ URL m_finalURL;
bool m_isDisabled;
- Vector<OwnPtr<XSLImportRule> > m_children;
+ Vector<std::unique_ptr<XSLImportRule>> m_children;
bool m_embedded;
bool m_processed;
-#if USE(QXMLQUERY)
- String m_sheetString;
-#else
xmlDocPtr m_stylesheetDoc;
bool m_stylesheetDocTaken;
-#endif
-
+ bool m_compilationFailed { false };
+
XSLStyleSheet* m_parentStyleSheet;
};
} // namespace WebCore
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::XSLStyleSheet)
+ static bool isType(const WebCore::StyleSheet& styleSheet) { return styleSheet.isXSLStyleSheet(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
#endif // ENABLE(XSLT)
#endif // XSLStyleSheet_h
diff --git a/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
index 8e24b7421..9ab001677 100644
--- a/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
+++ b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
@@ -20,31 +20,28 @@
*/
#include "config.h"
-#include "XSLStyleSheet.h"
#if ENABLE(XSLT)
#include "CachedResourceLoader.h"
#include "Document.h"
#include "Frame.h"
-#include "Node.h"
#include "Page.h"
-#include "PageConsole.h"
+#include "PageConsoleClient.h"
#include "TransformSource.h"
#include "XMLDocumentParser.h"
#include "XMLDocumentParserScope.h"
#include "XSLImportRule.h"
#include "XSLTProcessor.h"
-#include <wtf/text/CString.h>
-
+#include <JavaScriptCore/Profile.h>
#include <libxml/uri.h>
#include <libxslt/xsltutils.h>
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
#include "SoftLinking.h"
#endif
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
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))
@@ -54,29 +51,29 @@ SOFT_LINK(libxslt, xsltLoadStylesheetPI, xsltStylesheetPtr, (xmlDocPtr doc), (do
namespace WebCore {
-XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const KURL& finalURL)
- : m_ownerNode(0)
+XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const URL& finalURL)
+ : m_ownerNode(nullptr)
, m_originalURL(originalURL)
, m_finalURL(finalURL)
, m_isDisabled(false)
, m_embedded(false)
, m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them.
- , m_stylesheetDoc(0)
+ , m_stylesheetDoc(nullptr)
, m_stylesheetDocTaken(false)
- , m_parentStyleSheet(parentRule ? parentRule->parentStyleSheet() : 0)
+ , m_parentStyleSheet(parentRule ? parentRule->parentStyleSheet() : nullptr)
{
}
-XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const URL& finalURL, bool embedded)
: m_ownerNode(parentNode)
, m_originalURL(originalURL)
, m_finalURL(finalURL)
, m_isDisabled(false)
, m_embedded(embedded)
, m_processed(true) // The root sheet starts off processed.
- , m_stylesheetDoc(0)
+ , m_stylesheetDoc(nullptr)
, m_stylesheetDocTaken(false)
- , m_parentStyleSheet(0)
+ , m_parentStyleSheet(nullptr)
{
}
@@ -85,16 +82,16 @@ XSLStyleSheet::~XSLStyleSheet()
if (!m_stylesheetDocTaken)
xmlFreeDoc(m_stylesheetDoc);
- for (unsigned i = 0; i < m_children.size(); ++i) {
- ASSERT(m_children.at(i)->parentStyleSheet() == this);
- m_children.at(i)->setParentStyleSheet(0);
+ for (auto& child : m_children) {
+ ASSERT(child->parentStyleSheet() == this);
+ child->setParentStyleSheet(nullptr);
}
}
bool XSLStyleSheet::isLoading() const
{
- for (unsigned i = 0; i < m_children.size(); ++i) {
- if (m_children.at(i)->isLoading())
+ for (auto& child : m_children) {
+ if (child->isLoading())
return true;
}
return false;
@@ -119,9 +116,8 @@ xmlDocPtr XSLStyleSheet::document()
void XSLStyleSheet::clearDocuments()
{
- m_stylesheetDoc = 0;
- for (unsigned i = 0; i < m_children.size(); ++i) {
- XSLImportRule* import = m_children.at(i).get();
+ m_stylesheetDoc = nullptr;
+ for (auto& import : m_children) {
if (import->styleSheet())
import->styleSheet()->clearDocuments();
}
@@ -131,8 +127,8 @@ CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
{
Document* document = ownerDocument();
if (!document)
- return 0;
- return document->cachedResourceLoader();
+ return nullptr;
+ return &document->cachedResourceLoader();
}
bool XSLStyleSheet::parseString(const String& string)
@@ -144,14 +140,15 @@ bool XSLStyleSheet::parseString(const String& string)
xmlFreeDoc(m_stylesheetDoc);
m_stylesheetDocTaken = false;
- PageConsole* console = 0;
+ PageConsoleClient* console = nullptr;
Frame* frame = ownerDocument()->frame();
if (frame && frame->page())
- console = frame->page()->console();
+ console = &frame->page()->console();
XMLDocumentParserScope scope(cachedResourceLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);
- const char* buffer = reinterpret_cast<const char*>(string.characters());
+ auto upconvertedCharacters = StringView(string).upconvertedCharacters();
+ const char* buffer = reinterpret_cast<const char*>(upconvertedCharacters.get());
int size = string.length() * sizeof(UChar);
xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size);
@@ -236,7 +233,7 @@ void XSLStyleSheet::loadChildSheets()
void XSLStyleSheet::loadChildSheet(const String& href)
{
- OwnPtr<XSLImportRule> childRule = XSLImportRule::create(this, href);
+ auto childRule = std::make_unique<XSLImportRule>(this, href);
XSLImportRule* c = childRule.get();
m_children.append(childRule.release());
c->loadSheet();
@@ -248,12 +245,19 @@ xsltStylesheetPtr XSLStyleSheet::compileStyleSheet()
if (m_embedded)
return xsltLoadStylesheetPI(document());
+ // Certain libxslt versions are corrupting the xmlDoc on compilation
+ // failures - hence attempting to recompile after a failure is unsafe.
+ if (m_compilationFailed)
+ return nullptr;
+
// 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;
+ else
+ m_compilationFailed = true;
return result;
}
@@ -267,7 +271,7 @@ Document* XSLStyleSheet::ownerDocument()
for (XSLStyleSheet* styleSheet = this; styleSheet; styleSheet = styleSheet->parentStyleSheet()) {
Node* node = styleSheet->ownerNode();
if (node)
- return node->document();
+ return &node->document();
}
return 0;
}
@@ -275,8 +279,7 @@ Document* XSLStyleSheet::ownerDocument()
xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri)
{
bool matchedParent = (parentDoc == document());
- for (unsigned i = 0; i < m_children.size(); ++i) {
- XSLImportRule* import = m_children.at(i).get();
+ for (auto& import : m_children) {
XSLStyleSheet* child = import->styleSheet();
if (!child)
continue;
diff --git a/Source/WebCore/xml/XSLStyleSheetQt.cpp b/Source/WebCore/xml/XSLStyleSheetQt.cpp
deleted file mode 100644
index d7802add2..000000000
--- a/Source/WebCore/xml/XSLStyleSheetQt.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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 "XSLImportRule.h"
-#include "XSLTProcessor.h"
-
-namespace WebCore {
-
-XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
- : m_ownerNode(parentNode)
- , m_originalURL(originalURL)
- , m_finalURL(finalURL)
- , m_isDisabled(false)
- , m_embedded(embedded)
-{
-}
-
-XSLStyleSheet::~XSLStyleSheet()
-{
- for (unsigned i = 0; i < m_children.size(); ++i) {
- ASSERT(m_children.at(i)->parentStyleSheet() == this);
- m_children.at(i)->setParentStyleSheet(0);
- }
-}
-
-bool XSLStyleSheet::isLoading() const
-{
- notImplemented();
- return false;
-}
-
-void XSLStyleSheet::checkLoaded()
-{
- if (ownerNode())
- ownerNode()->sheetLoaded();
-}
-
-void XSLStyleSheet::clearDocuments()
-{
- notImplemented();
-}
-
-CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
-{
- Document* document = ownerDocument();
- if (!document)
- return 0;
- return document->cachedResourceLoader();
-}
-
-bool XSLStyleSheet::parseString(const String& string)
-{
- // 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();
-}
-
-Document* XSLStyleSheet::ownerDocument()
-{
- Node* node = ownerNode();
- return node ? node->document() : 0;
-}
-
-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
index 069ddd81b..4b715c1d6 100644
--- a/Source/WebCore/xml/XSLTExtensions.cpp
+++ b/Source/WebCore/xml/XSLTExtensions.cpp
@@ -35,11 +35,11 @@
#include <libxslt/extensions.h>
#include <libxslt/extra.h>
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
#include "SoftLinking.h"
#endif
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
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))
diff --git a/Source/WebCore/xml/XSLTProcessor.cpp b/Source/WebCore/xml/XSLTProcessor.cpp
index 21eff80b0..db6f9ac67 100644
--- a/Source/WebCore/xml/XSLTProcessor.cpp
+++ b/Source/WebCore/xml/XSLTProcessor.cpp
@@ -37,8 +37,10 @@
#include "HTMLDocument.h"
#include "Page.h"
#include "SecurityOrigin.h"
+#include "SecurityOriginPolicy.h"
#include "Text.h"
#include "TextResourceDecoder.h"
+#include "XMLDocument.h"
#include "markup.h"
#include <wtf/Assertions.h>
@@ -67,19 +69,19 @@ XSLTProcessor::~XSLTProcessor()
ASSERT(!m_stylesheetRootNode || !m_stylesheet || m_stylesheet->hasOneRef());
}
-PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString,
+Ref<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());
+ Ref<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());
+ result = XMLDocument::createXHTML(frame, sourceIsDocument ? ownerDocument->url() : URL());
transformTextStringToXHTMLDocumentString(documentSource);
} else
- result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : KURL(), false);
+ result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : URL());
// 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.
@@ -90,41 +92,41 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc
if (Document* oldDocument = frame->document()) {
result->setTransformSourceDocument(oldDocument);
result->takeDOMWindowFrom(oldDocument);
- result->setSecurityOrigin(oldDocument->securityOrigin());
+ result->setSecurityOriginPolicy(oldDocument->securityOriginPolicy());
result->setCookieURL(oldDocument->cookieURL());
result->setFirstPartyForCookies(oldDocument->firstPartyForCookies());
result->contentSecurityPolicy()->copyStateFrom(oldDocument->contentSecurityPolicy());
}
- frame->setDocument(result);
+ frame->setDocument(result.copyRef());
}
RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(sourceMIMEType);
decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader);
- result->setDecoder(decoder.release());
+ result->setDecoder(WTFMove(decoder));
result->setContent(documentSource);
- return result.release();
+ return result.releaseNonNull();
}
-PassRefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode)
+RefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode)
{
if (!sourceNode)
- return 0;
+ return nullptr;
String resultMIMEType;
String resultString;
String resultEncoding;
- if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding))
- return 0;
+ if (!transformToString(*sourceNode, resultMIMEType, resultString, resultEncoding))
+ return nullptr;
return createDocumentFromSource(resultString, resultEncoding, resultMIMEType, sourceNode, 0);
}
-PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode, Document* outputDoc)
+RefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode, Document* outputDoc)
{
if (!sourceNode || !outputDoc)
- return 0;
+ return nullptr;
String resultMIMEType;
String resultString;
@@ -134,8 +136,8 @@ PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode
if (outputDoc->isHTMLDocument())
resultMIMEType = "text/html";
- if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding))
- return 0;
+ if (!transformToString(*sourceNode, resultMIMEType, resultString, resultEncoding))
+ return nullptr;
return createFragmentForTransformToFragment(resultString, resultMIMEType, outputDoc);
}
@@ -161,8 +163,8 @@ void XSLTProcessor::removeParameter(const String& /*namespaceURI*/, const String
void XSLTProcessor::reset()
{
- m_stylesheet.clear();
- m_stylesheetRootNode.clear();
+ m_stylesheet = nullptr;
+ m_stylesheetRootNode = nullptr;
m_parameters.clear();
}
diff --git a/Source/WebCore/xml/XSLTProcessor.h b/Source/WebCore/xml/XSLTProcessor.h
index 81f4a6a26..cffd1c45d 100644
--- a/Source/WebCore/xml/XSLTProcessor.h
+++ b/Source/WebCore/xml/XSLTProcessor.h
@@ -30,10 +30,8 @@
#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
-#if !USE(QXMLQUERY)
#include <libxml/parserInternals.h>
#include <libxslt/documents.h>
-#endif
namespace WebCore {
@@ -43,21 +41,21 @@ class DocumentFragment;
class XSLTProcessor : public RefCounted<XSLTProcessor> {
public:
- static PassRefPtr<XSLTProcessor> create() { return adoptRef(new XSLTProcessor); }
+ static Ref<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);
+ void setXSLStyleSheet(RefPtr<XSLStyleSheet>&& styleSheet) { m_stylesheet = WTFMove(styleSheet); }
+ bool transformToString(Node& source, String& resultMIMEType, String& resultString, String& resultEncoding);
+ Ref<Document> createDocumentFromSource(const String& source, const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame);
// DOM methods
- void importStylesheet(PassRefPtr<Node> style)
+ void importStylesheet(RefPtr<Node>&& style)
{
if (style)
- m_stylesheetRootNode = style;
+ m_stylesheetRootNode = WTFMove(style);
}
- PassRefPtr<DocumentFragment> transformToFragment(Node* source, Document* ouputDoc);
- PassRefPtr<Document> transformToDocument(Node* source);
+ RefPtr<DocumentFragment> transformToFragment(Node* source, Document* ouputDoc);
+ RefPtr<Document> transformToDocument(Node* source);
void setParameter(const String& namespaceURI, const String& localName, const String& value);
String getParameter(const String& namespaceURI, const String& localName) const;
@@ -66,13 +64,11 @@ public:
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;
diff --git a/Source/WebCore/xml/XSLTProcessor.idl b/Source/WebCore/xml/XSLTProcessor.idl
index 57580348e..1ecd61f7b 100644
--- a/Source/WebCore/xml/XSLTProcessor.idl
+++ b/Source/WebCore/xml/XSLTProcessor.idl
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -33,7 +33,7 @@
[
Conditional=XSLT,
Constructor,
- ImplementationLacksVTable
+ ImplementationLacksVTable,
] interface XSLTProcessor {
void importStylesheet([Default=Undefined] optional Node stylesheet);
diff --git a/Source/WebCore/xml/XSLTProcessorLibxslt.cpp b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
index 14cdab909..8587b006c 100644
--- a/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
+++ b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
@@ -30,28 +30,27 @@
#include "Document.h"
#include "Frame.h"
#include "Page.h"
-#include "PageConsole.h"
+#include "PageConsoleClient.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "SecurityOrigin.h"
#include "TransformSource.h"
#include "XMLDocumentParser.h"
-#include "XSLStyleSheet.h"
#include "XSLTExtensions.h"
#include "XSLTUnicodeSort.h"
#include "markup.h"
+#include <JavaScriptCore/Profile.h>
#include <libxslt/imports.h>
#include <libxslt/security.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)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
#include "SoftLinking.h"
SOFT_LINK_LIBRARY(libxslt);
@@ -81,32 +80,32 @@ void XSLTProcessor::genericErrorFunc(void*, const char*, ...)
void XSLTProcessor::parseErrorFunc(void* userData, xmlError* error)
{
- PageConsole* console = static_cast<PageConsole*>(userData);
+ PageConsoleClient* console = static_cast<PageConsoleClient*>(userData);
if (!console)
return;
MessageLevel level;
switch (error->level) {
case XML_ERR_NONE:
- level = DebugMessageLevel;
+ level = MessageLevel::Debug;
break;
case XML_ERR_WARNING:
- level = WarningMessageLevel;
+ level = MessageLevel::Warning;
break;
case XML_ERR_ERROR:
case XML_ERR_FATAL:
default:
- level = ErrorMessageLevel;
+ level = MessageLevel::Error;
break;
}
// xmlError->int2 is the column number of the error or 0 if N/A.
- console->addMessage(XMLMessageSource, level, error->message, error->file, error->line, error->int2);
+ console->addMessage(MessageSource::XML, level, error->message, error->file, error->line, error->int2);
}
// 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 XSLTProcessor* globalProcessor = nullptr;
+static CachedResourceLoader* globalCachedResourceLoader = nullptr;
static xmlDocPtr docLoaderFunc(const xmlChar* uri,
xmlDictPtr,
int options,
@@ -120,33 +119,37 @@ static xmlDocPtr docLoaderFunc(const xmlChar* uri,
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));
+ URL url(URL(ParsedURLString, reinterpret_cast<const char*>(base)), reinterpret_cast<const char*>(uri));
xmlFree(base);
ResourceError error;
ResourceResponse response;
- Vector<char> data;
+ RefPtr<SharedBuffer> data;
bool requestAllowed = globalCachedResourceLoader->frame() && globalCachedResourceLoader->document()->securityOrigin()->canRequest(url);
if (requestAllowed) {
- globalCachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data);
- requestAllowed = globalCachedResourceLoader->document()->securityOrigin()->canRequest(response.url());
+ globalCachedResourceLoader->frame()->loader().loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data);
+ if (error.isNull())
+ requestAllowed = globalCachedResourceLoader->document()->securityOrigin()->canRequest(response.url());
+ else if (data)
+ data = nullptr;
}
if (!requestAllowed) {
- data.clear();
+ if (data)
+ data = nullptr;
globalCachedResourceLoader->printAccessDeniedMessage(url);
}
- PageConsole* console = 0;
+ PageConsoleClient* console = nullptr;
Frame* frame = globalProcessor->xslStylesheet()->ownerDocument()->frame();
if (frame && frame->page())
- console = frame->page()->console();
+ console = &frame->page()->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);
+ xmlDocPtr doc = xmlReadMemory(data ? data->data() : nullptr, data ? data->size() : 0, (const char*)uri, 0, options);
xmlSetStructuredErrorFunc(0, 0);
xmlSetGenericErrorFunc(0, 0);
@@ -194,7 +197,7 @@ static int writeToStringBuilder(void* context, const char* buffer, int len)
static bool saveResultToString(xmlDocPtr resultDoc, xsltStylesheetPtr sheet, String& resultString)
{
- xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(0);
+ xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(nullptr);
if (!outputBuf)
return false;
@@ -223,13 +226,12 @@ static const char** xsltParamArrayFromParameterMap(XSLTProcessor::ParameterMap&
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->key.utf8().data());
- parameterArray[index++] = fastStrDup(it->value.utf8().data());
+ for (auto& parameter : parameters) {
+ parameterArray[index++] = fastStrDup(parameter.key.utf8().data());
+ parameterArray[index++] = fastStrDup(parameter.value.utf8().data());
}
- parameterArray[index] = 0;
+ parameterArray[index] = nullptr;
return parameterArray;
}
@@ -251,12 +253,12 @@ static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStyl
{
if (!cachedStylesheet && stylesheetRootNode) {
cachedStylesheet = XSLStyleSheet::createForXSLTProcessor(stylesheetRootNode->parentNode() ? stylesheetRootNode->parentNode() : stylesheetRootNode,
- stylesheetRootNode->document()->url().string(),
- stylesheetRootNode->document()->url()); // FIXME: Should we use baseURL here?
+ 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));
+ cachedStylesheet->parseString(createMarkup(*stylesheetRootNode));
}
if (!cachedStylesheet || !cachedStylesheet->document())
@@ -265,12 +267,12 @@ static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStyl
return cachedStylesheet->compileStyleSheet();
}
-static inline xmlDocPtr xmlDocPtrFromNode(Node* sourceNode, bool& shouldDelete)
+static inline xmlDocPtr xmlDocPtrFromNode(Node& sourceNode, bool& shouldDelete)
{
- RefPtr<Document> ownerDocument = sourceNode->document();
- bool sourceIsDocument = (sourceNode == ownerDocument.get());
+ Ref<Document> ownerDocument(sourceNode.document());
+ bool sourceIsDocument = (&sourceNode == &ownerDocument.get());
- xmlDocPtr sourceDoc = 0;
+ xmlDocPtr sourceDoc = nullptr;
if (sourceIsDocument && ownerDocument->transformSource())
sourceDoc = (xmlDocPtr)ownerDocument->transformSource()->platformSource();
if (!sourceDoc) {
@@ -287,7 +289,7 @@ static inline String resultMIMEType(xmlDocPtr resultDoc, xsltStylesheetPtr sheet
// 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;
+ const xmlChar* resultType = nullptr;
XSLT_GET_IMPORT_PTR(resultType, sheet, method);
if (!resultType && resultDoc->type == XML_HTML_DOCUMENT_NODE)
resultType = (const xmlChar*)"html";
@@ -300,15 +302,15 @@ static inline String resultMIMEType(xmlDocPtr resultDoc, xsltStylesheetPtr sheet
return "application/xml";
}
-bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String& resultString, String& resultEncoding)
+bool XSLTProcessor::transformToString(Node& sourceNode, String& mimeType, String& resultString, String& resultEncoding)
{
- RefPtr<Document> ownerDocument = sourceNode->document();
+ Ref<Document> ownerDocument(sourceNode.document());
- setXSLTLoadCallBack(docLoaderFunc, this, ownerDocument->cachedResourceLoader());
+ setXSLTLoadCallBack(docLoaderFunc, this, &ownerDocument->cachedResourceLoader());
xsltStylesheetPtr sheet = xsltStylesheetPointer(m_stylesheet, m_stylesheetRootNode.get());
if (!sheet) {
- setXSLTLoadCallBack(0, 0, 0);
- m_stylesheet = 0;
+ setXSLTLoadCallBack(nullptr, nullptr, nullptr);
+ m_stylesheet = nullptr;
return false;
}
m_stylesheet->clearDocuments();
@@ -367,7 +369,7 @@ bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String
sheet->method = origMethod;
setXSLTLoadCallBack(0, 0, 0);
xsltFreeStylesheet(sheet);
- m_stylesheet = 0;
+ m_stylesheet = nullptr;
return success;
}
diff --git a/Source/WebCore/xml/XSLTProcessorQt.cpp b/Source/WebCore/xml/XSLTProcessorQt.cpp
deleted file mode 100644
index e8b2427f1..000000000
--- a/Source/WebCore/xml/XSLTProcessorQt.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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 "Document.h"
-#include "DOMWindow.h"
-#include "Frame.h"
-#include "SecurityOrigin.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 = DebugMessageLevel;
- break;
- case QtWarningMsg:
- level = WarningMessageLevel;
- break;
- case QtCriticalMsg:
- case QtFatalMsg:
- level = ErrorMessageLevel;
- break;
- default:
- level = LogMessageLevel;
- break;
- }
-
- Console* console = m_document->domWindow()->console();
- console->addMessage(XMLMessageSource, level, description, sourceLocation.uri().toString(), sourceLocation.line(), sourceLocation.column());
-}
-
-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->key), QXmlItem(QVariant(QString(it->value))));
-
- 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
index 66b8a6d5e..54d5abd10 100644
--- a/Source/WebCore/xml/XSLTUnicodeSort.cpp
+++ b/Source/WebCore/xml/XSLTUnicodeSort.cpp
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -33,14 +33,13 @@
#include <libxslt/templates.h>
#include <libxslt/xsltutils.h>
-#include <wtf/text/WTFString.h>
#include <wtf/unicode/Collator.h>
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
#include "SoftLinking.h"
#endif
-#if PLATFORM(MAC)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && !PLATFORM(QT)
SOFT_LINK_LIBRARY(libxslt)
SOFT_LINK(libxslt, xsltComputeSortResult, xmlXPathObjectPtr*, (xsltTransformContextPtr ctxt, xmlNodePtr sort), (ctxt, sort))
@@ -162,10 +161,9 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in
// 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
+ // This lets an author 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);
+ Collator collator(comp->has_lang ? reinterpret_cast<const char*>(comp->lang) : "en", comp->lower_first);
/* Shell's sort of node-set */
for (incr = len / 2; incr > 0; incr /= 2) {
@@ -195,11 +193,8 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in
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());
- }
+ } else
+ tst = collator.collateUTF8(reinterpret_cast<const char*>(results[j]->stringval), reinterpret_cast<const char*>(results[j + incr]->stringval));
if (descending)
tst = -tst;
}
@@ -250,11 +245,8 @@ void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, in
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());
- }
+ } else
+ tst = collator.collateUTF8(reinterpret_cast<const char*>(res[j]->stringval), reinterpret_cast<const char*>(res[j + incr]->stringval));
if (desc)
tst = -tst;
}
diff --git a/Source/WebCore/xml/XSLTUnicodeSort.h b/Source/WebCore/xml/XSLTUnicodeSort.h
index c8d395b9c..ddd5e4fcf 100644
--- a/Source/WebCore/xml/XSLTUnicodeSort.h
+++ b/Source/WebCore/xml/XSLTUnicodeSort.h
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
diff --git a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h
index 62780c7dc..f0f4ff76b 100644
--- a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h
+++ b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h
@@ -31,20 +31,9 @@
namespace WebCore {
-inline bool isHexDigit(UChar cc)
-{
- return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f') || (cc >= 'A' && cc <= 'F');
-}
-
inline void unconsumeCharacters(SegmentedString& source, const StringBuilder& consumedCharacters)
{
- if (consumedCharacters.length() == 1)
- source.push(consumedCharacters[0]);
- else if (consumedCharacters.length() == 2) {
- source.push(consumedCharacters[0]);
- source.push(consumedCharacters[1]);
- } else
- source.prepend(SegmentedString(consumedCharacters.toStringPreserveCapacity()));
+ source.pushBack(SegmentedString(consumedCharacters.toStringPreserveCapacity()));
}
template <typename ParserFunctions>
@@ -54,7 +43,7 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh
ASSERT(!notEnoughCharacters);
ASSERT(decodedCharacter.isEmpty());
- enum EntityState {
+ enum {
Initial,
Number,
MaybeHexLowerCaseX,
@@ -62,105 +51,101 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh
Hex,
Decimal,
Named
- };
- EntityState entityState = Initial;
+ } state = Initial;
UChar32 result = 0;
+ bool overflow = false;
StringBuilder consumedCharacters;
while (!source.isEmpty()) {
- UChar cc = source.currentChar();
- switch (entityState) {
- case Initial: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '<' || cc == '&')
+ UChar character = source.currentChar();
+ switch (state) {
+ case Initial:
+ if (character == '\x09' || character == '\x0A' || character == '\x0C' || character == ' ' || character == '<' || character == '&')
return false;
- if (additionalAllowedCharacter && cc == additionalAllowedCharacter)
+ if (additionalAllowedCharacter && character == additionalAllowedCharacter)
return false;
- if (cc == '#') {
- entityState = Number;
+ if (character == '#') {
+ state = Number;
break;
}
- if ((cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')) {
- entityState = Named;
- continue;
+ if (isASCIIAlpha(character)) {
+ state = Named;
+ goto Named;
}
return false;
- }
- case Number: {
- if (cc == 'x') {
- entityState = MaybeHexLowerCaseX;
+ case Number:
+ if (character == 'x') {
+ state = MaybeHexLowerCaseX;
break;
}
- if (cc == 'X') {
- entityState = MaybeHexUpperCaseX;
+ if (character == 'X') {
+ state = MaybeHexUpperCaseX;
break;
}
- if (cc >= '0' && cc <= '9') {
- entityState = Decimal;
- continue;
+ if (isASCIIDigit(character)) {
+ state = Decimal;
+ goto Decimal;
}
- source.push('#');
+ source.pushBack(SegmentedString(ASCIILiteral("#")));
return false;
- }
- case MaybeHexLowerCaseX: {
- if (isHexDigit(cc)) {
- entityState = Hex;
- continue;
+ case MaybeHexLowerCaseX:
+ if (isASCIIHexDigit(character)) {
+ state = Hex;
+ goto Hex;
}
- source.push('#');
- source.push('x');
+ source.pushBack(SegmentedString(ASCIILiteral("#x")));
return false;
- }
- case MaybeHexUpperCaseX: {
- if (isHexDigit(cc)) {
- entityState = Hex;
- continue;
+ case MaybeHexUpperCaseX:
+ if (isASCIIHexDigit(character)) {
+ state = Hex;
+ goto Hex;
}
- source.push('#');
- source.push('X');
+ source.pushBack(SegmentedString(ASCIILiteral("#X")));
return false;
- }
- case Hex: {
- if (cc >= '0' && cc <= '9')
- result = result * 16 + cc - '0';
- else if (cc >= 'a' && cc <= 'f')
- result = result * 16 + 10 + cc - 'a';
- else if (cc >= 'A' && cc <= 'F')
- result = result * 16 + 10 + cc - 'A';
- else if (cc == ';') {
- source.advanceAndASSERT(cc);
- decodedCharacter.append(ParserFunctions::legalEntityFor(result));
+ case Hex:
+ Hex:
+ if (isASCIIHexDigit(character)) {
+ result = result * 16 + toASCIIHexValue(character);
+ if (result > UCHAR_MAX_VALUE)
+ overflow = true;
+ break;
+ }
+ if (character == ';') {
+ source.advance();
+ decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
return true;
- } else if (ParserFunctions::acceptMalformed()) {
- decodedCharacter.append(ParserFunctions::legalEntityFor(result));
+ }
+ if (ParserFunctions::acceptMalformed()) {
+ decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
return true;
- } else {
- unconsumeCharacters(source, consumedCharacters);
- return false;
}
- break;
- }
- case Decimal: {
- if (cc >= '0' && cc <= '9')
- result = result * 10 + cc - '0';
- else if (cc == ';') {
- source.advanceAndASSERT(cc);
- decodedCharacter.append(ParserFunctions::legalEntityFor(result));
+ unconsumeCharacters(source, consumedCharacters);
+ return false;
+ case Decimal:
+ Decimal:
+ if (isASCIIDigit(character)) {
+ result = result * 10 + character - '0';
+ if (result > UCHAR_MAX_VALUE)
+ overflow = true;
+ break;
+ }
+ if (character == ';') {
+ source.advance();
+ decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
return true;
- } else if (ParserFunctions::acceptMalformed()) {
- decodedCharacter.append(ParserFunctions::legalEntityFor(result));
+ }
+ if (ParserFunctions::acceptMalformed()) {
+ decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
return true;
- } else {
- unconsumeCharacters(source, consumedCharacters);
- return false;
}
- break;
- }
- case Named: {
- return ParserFunctions::consumeNamedEntity(source, decodedCharacter, notEnoughCharacters, additionalAllowedCharacter, cc);
- }
+ unconsumeCharacters(source, consumedCharacters);
+ return false;
+ case Named:
+ Named:
+ return ParserFunctions::consumeNamedEntity(source, decodedCharacter, notEnoughCharacters, additionalAllowedCharacter, character);
}
- consumedCharacters.append(cc);
- source.advanceAndASSERT(cc);
+ consumedCharacters.append(character);
+ source.advance();
}
ASSERT(source.isEmpty());
notEnoughCharacters = true;
diff --git a/Source/WebCore/xml/parser/MarkupTokenizerInlines.h b/Source/WebCore/xml/parser/MarkupTokenizerInlines.h
index e0b3156bb..987510e8a 100644
--- a/Source/WebCore/xml/parser/MarkupTokenizerInlines.h
+++ b/Source/WebCore/xml/parser/MarkupTokenizerInlines.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2015 Apple Inc. All Rights Reserved.
* Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
* Copyright (C) 2010 Google, Inc. All Rights Reserved.
*
@@ -30,64 +30,61 @@
#include "SegmentedString.h"
+#if COMPILER(MSVC)
+// Disable the "unreachable code" warning so we can compile the ASSERT_NOT_REACHED in the END_STATE macro.
+#pragma warning(disable: 4702)
+#endif
+
namespace WebCore {
-inline bool isTokenizerWhitespace(UChar cc)
+inline bool isTokenizerWhitespace(UChar character)
{
- return cc == ' ' || cc == '\x0A' || cc == '\x09' || cc == '\x0C';
+ return character == ' ' || character == '\x0A' || character == '\x09' || character == '\x0C';
}
-inline void advanceStringAndASSERTIgnoringCase(SegmentedString& source, const char* expectedCharacters)
-{
- while (*expectedCharacters)
- source.advanceAndASSERTIgnoringCase(*expectedCharacters++);
-}
+#define BEGIN_STATE(stateName) \
+ case stateName: \
+ stateName: { \
+ const auto currentState = stateName; \
+ UNUSED_PARAM(currentState);
-inline void advanceStringAndASSERT(SegmentedString& source, const char* expectedCharacters)
-{
- while (*expectedCharacters)
- source.advanceAndASSERT(*expectedCharacters++);
-}
-
-#if COMPILER(MSVC)
-// We need to disable the "unreachable code" warning because we want to assert
-// that some code points aren't reached in the state machine.
-#pragma warning(disable: 4702)
-#endif
+#define END_STATE() \
+ ASSERT_NOT_REACHED(); \
+ break; \
+ }
-#define BEGIN_STATE(prefix, stateName) case prefix::stateName: stateName:
-#define END_STATE() ASSERT_NOT_REACHED(); break;
+#define RETURN_IN_CURRENT_STATE(expression) \
+ do { \
+ m_state = currentState; \
+ return expression; \
+ } while (false)
-// We use this macro when the HTML5 spec says "reconsume the current input
-// character in the <mumble> state."
-#define RECONSUME_IN(prefix, stateName) \
- do { \
- m_state = prefix::stateName; \
- goto stateName; \
+// We use this macro when the HTML spec says "reconsume the current input character in the <mumble> state."
+#define RECONSUME_IN(newState) \
+ do { \
+ goto newState; \
} while (false)
-// We use this macro when the HTML5 spec says "consume the next input
-// character ... and switch to the <mumble> state."
-#define ADVANCE_TO(prefix, stateName) \
- do { \
- m_state = prefix::stateName; \
- if (!m_inputStreamPreprocessor.advance(source)) \
- return haveBufferedCharacterToken(); \
- cc = m_inputStreamPreprocessor.nextInputCharacter(); \
- goto stateName; \
+// We use this macro when the HTML spec says "consume the next input character ... and switch to the <mumble> state."
+#define ADVANCE_TO(newState) \
+ do { \
+ if (!m_preprocessor.advance(source, isNullCharacterSkippingState(newState))) { \
+ m_state = newState; \
+ return haveBufferedCharacterToken(); \
+ } \
+ character = m_preprocessor.nextInputCharacter(); \
+ goto newState; \
} while (false)
-// Sometimes there's more complicated logic in the spec that separates when
-// we consume the next input character and when we switch to a particular
-// state. We handle those cases by advancing the source directly and using
-// this macro to switch to the indicated state.
-#define SWITCH_TO(prefix, stateName) \
- do { \
- m_state = prefix::stateName; \
- if (source.isEmpty() || !m_inputStreamPreprocessor.peek(source)) \
- return haveBufferedCharacterToken(); \
- cc = m_inputStreamPreprocessor.nextInputCharacter(); \
- goto stateName; \
+// For more complex cases, caller consumes the characters first and then uses this macro.
+#define SWITCH_TO(newState) \
+ do { \
+ if (!m_preprocessor.peek(source, isNullCharacterSkippingState(newState))) { \
+ m_state = newState; \
+ return haveBufferedCharacterToken(); \
+ } \
+ character = m_preprocessor.nextInputCharacter(); \
+ goto newState; \
} while (false)
}
diff --git a/Source/WebCore/xml/parser/XMLDocumentParser.cpp b/Source/WebCore/xml/parser/XMLDocumentParser.cpp
index cb4abc800..3fd7dbbee 100644
--- a/Source/WebCore/xml/parser/XMLDocumentParser.cpp
+++ b/Source/WebCore/xml/parser/XMLDocumentParser.cpp
@@ -44,23 +44,17 @@
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
+#include "SVGNames.h"
+#include "SVGStyleElement.h"
#include "ScriptElement.h"
#include "ScriptSourceCode.h"
-#include "ScriptValue.h"
#include "TextResourceDecoder.h"
#include "TreeDepthLimit.h"
-#include "XMLErrors.h"
+#include <wtf/Ref.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
#include <wtf/Vector.h>
-#if ENABLE(SVG)
-#include "SVGNames.h"
-#include "SVGStyleElement.h"
-#endif
-
-using namespace std;
-
namespace WebCore {
using namespace HTMLNames;
@@ -94,8 +88,8 @@ void XMLDocumentParser::clearCurrentNodeStack()
{
if (m_currentNode && m_currentNode != document())
m_currentNode->deref();
- m_currentNode = 0;
- m_leafTextNode = 0;
+ m_currentNode = nullptr;
+ m_leafTextNode = nullptr;
if (m_currentNodeStack.size()) { // Aborted parsing.
for (size_t i = m_currentNodeStack.size() - 1; i != 0; --i)
@@ -111,9 +105,9 @@ void XMLDocumentParser::insert(const SegmentedString&)
ASSERT_NOT_REACHED();
}
-void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource)
+void XMLDocumentParser::append(RefPtr<StringImpl>&& inputSource)
{
- SegmentedString source(inputSource);
+ SegmentedString source(WTFMove(inputSource));
if (m_sawXSLTransform || !m_sawFirstElement)
m_originalSourceForTransform.append(source);
@@ -127,56 +121,55 @@ void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource)
doWrite(source.toString());
- // After parsing, go ahead and dispatch image beforeload events.
+ // After parsing, dispatch image beforeload events.
ImageLoader::dispatchPendingBeforeLoadEvents();
}
void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* m, TextPosition position)
{
- m_xmlErrors.handleError(type, m, position);
+ if (!m_xmlErrors)
+ m_xmlErrors = std::make_unique<XMLErrors>(document());
+ m_xmlErrors->handleError(type, m, position);
if (type != XMLErrors::warning)
m_sawError = true;
if (type == XMLErrors::fatal)
stopParsing();
}
-void XMLDocumentParser::enterText()
+void XMLDocumentParser::createLeafTextNode()
{
-#if !USE(QXMLSTREAM)
+ if (m_leafTextNode)
+ return;
+
ASSERT(m_bufferedText.size() == 0);
-#endif
ASSERT(!m_leafTextNode);
m_leafTextNode = Text::create(m_currentNode->document(), "");
- m_currentNode->parserAppendChild(m_leafTextNode.get());
+ m_currentNode->parserAppendChild(*m_leafTextNode);
}
-#if !USE(QXMLSTREAM)
static inline String toString(const xmlChar* string, size_t size)
{
return String::fromUTF8(reinterpret_cast<const char*>(string), size);
}
-#endif
-void XMLDocumentParser::exitText()
+bool XMLDocumentParser::updateLeafTextNode()
{
if (isStopped())
- return;
+ return false;
if (!m_leafTextNode)
- return;
+ return true;
-#if !USE(QXMLSTREAM)
- m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size()), IGNORE_EXCEPTION);
- Vector<xmlChar> empty;
- m_bufferedText.swap(empty);
-#endif
+ // This operation might fire mutation event, see below.
+ m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size()));
+ m_bufferedText = { };
- if (m_view && m_leafTextNode->parentNode() && m_leafTextNode->parentNode()->attached()
- && !m_leafTextNode->attached())
- m_leafTextNode->attach();
+ m_leafTextNode = nullptr;
- m_leafTextNode = 0;
+ // Hence, we need to check again whether the parser is stopped, since mutation
+ // event handlers executed by appendData might have detached this parser.
+ return !isStopped();
}
void XMLDocumentParser::detach()
@@ -205,7 +198,7 @@ void XMLDocumentParser::end()
if (m_sawError)
insertErrorMessageBlock();
else {
- exitText();
+ updateLeafTextNode();
document()->styleResolverChanged(RecalcStyleImmediately);
}
@@ -230,12 +223,8 @@ void XMLDocumentParser::finish()
void XMLDocumentParser::insertErrorMessageBlock()
{
-#if USE(QXMLSTREAM)
- if (m_parsingFragment)
- return;
-#endif
-
- m_xmlErrors.insertErrorMessageBlock();
+ ASSERT(m_xmlErrors);
+ m_xmlErrors->insertErrorMessageBlock();
}
void XMLDocumentParser::notifyFinished(CachedResource* unusedResource)
@@ -248,16 +237,16 @@ void XMLDocumentParser::notifyFinished(CachedResource* unusedResource)
bool wasCanceled = m_pendingScript->wasCanceled();
m_pendingScript->removeClient(this);
- m_pendingScript = 0;
+ m_pendingScript = nullptr;
RefPtr<Element> e = m_scriptElement;
- m_scriptElement = 0;
+ m_scriptElement = nullptr;
ScriptElement* scriptElement = toScriptElementIfPossible(e.get());
ASSERT(scriptElement);
// JavaScript can detach this parser, make sure it's kept alive even if detached.
- RefPtr<XMLDocumentParser> protect(this);
+ Ref<XMLDocumentParser> protect(*this);
if (errorOccurred)
scriptElement->dispatchErrorEvent();
@@ -266,7 +255,7 @@ void XMLDocumentParser::notifyFinished(CachedResource* unusedResource)
scriptElement->dispatchLoadEvent();
}
- m_scriptElement = 0;
+ m_scriptElement = nullptr;
if (!isDetached() && !m_requestingScript)
resumeParsing();
@@ -279,13 +268,15 @@ bool XMLDocumentParser::isWaitingForScripts() const
void XMLDocumentParser::pauseParsing()
{
+ ASSERT(!m_parserPaused);
+
if (m_parsingFragment)
return;
m_parserPaused = true;
}
-bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy)
+bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragment& fragment, Element* contextElement, ParserContentPolicy parserContentPolicy)
{
if (!chunk.length())
return true;
@@ -293,17 +284,16 @@ bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragm
// FIXME: We need to implement the HTML5 XML Fragment parsing algorithm:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#xml-fragment-parsing-algorithm
// For now we have a hack for script/style innerHTML support:
- if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag) || contextElement->hasLocalName(HTMLNames::styleTag))) {
- fragment->parserAppendChild(fragment->document()->createTextNode(chunk));
+ if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag.localName()) || contextElement->hasLocalName(HTMLNames::styleTag.localName()))) {
+ fragment.parserAppendChild(fragment.document().createTextNode(chunk));
return true;
}
RefPtr<XMLDocumentParser> parser = XMLDocumentParser::create(fragment, contextElement, parserContentPolicy);
bool wellFormed = parser->appendFragmentSource(chunk);
- // Do not call finish(). Current finish() and doEnd() implementations touch the main Document/loader
- // and can cause crashes in the fragment case.
+ // Do not call finish(). The finish() and doEnd() implementations touch the main document and loader and can cause crashes in the fragment case.
parser->detach(); // Allows ~DocumentParser to assert it was detached before destruction.
- return wellFormed; // appendFragmentSource()'s wellFormed is more permissive than wellFormed().
+ return wellFormed; // appendFragmentSource()'s wellFormed is more permissive than Document::wellFormed().
}
} // namespace WebCore
diff --git a/Source/WebCore/xml/parser/XMLDocumentParser.h b/Source/WebCore/xml/parser/XMLDocumentParser.h
index 149ad6e1a..ad876cb99 100644
--- a/Source/WebCore/xml/parser/XMLDocumentParser.h
+++ b/Source/WebCore/xml/parser/XMLDocumentParser.h
@@ -32,16 +32,11 @@
#include "SegmentedString.h"
#include "XMLErrors.h"
#include <wtf/HashMap.h>
-#include <wtf/OwnPtr.h>
#include <wtf/text/AtomicStringHash.h>
#include <wtf/text/CString.h>
-#if USE(QXMLSTREAM)
-#include <qxmlstream.h>
-#else
#include <libxml/tree.h>
#include <libxml/xmlstring.h>
-#endif
namespace WebCore {
@@ -55,11 +50,10 @@ class FrameView;
class PendingCallbacks;
class Text;
-#if !USE(QXMLSTREAM)
class XMLParserContext : public RefCounted<XMLParserContext> {
public:
- static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk);
- static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData);
+ static RefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk);
+ static Ref<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData);
~XMLParserContext();
xmlParserCtxtPtr context() const { return m_context; }
@@ -70,18 +64,17 @@ class Text;
}
xmlParserCtxtPtr m_context;
};
-#endif
- class XMLDocumentParser : public ScriptableDocumentParser, public CachedResourceClient {
+ class XMLDocumentParser final : public ScriptableDocumentParser, public CachedResourceClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<XMLDocumentParser> create(Document* document, FrameView* view)
+ static Ref<XMLDocumentParser> create(Document& document, FrameView* view)
{
- return adoptRef(new XMLDocumentParser(document, view));
+ return adoptRef(*new XMLDocumentParser(document, view));
}
- static PassRefPtr<XMLDocumentParser> create(DocumentFragment* fragment, Element* element, ParserContentPolicy parserContentPolicy)
+ static Ref<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy)
{
- return adoptRef(new XMLDocumentParser(fragment, element, parserContentPolicy));
+ return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy));
}
~XMLDocumentParser();
@@ -92,31 +85,30 @@ class Text;
void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; }
bool isXHTMLDocument() const { return m_isXHTMLDocument; }
- static bool parseDocumentFragment(const String&, DocumentFragment*, Element* parent = 0, ParserContentPolicy = AllowScriptingContent);
+ static bool parseDocumentFragment(const String&, DocumentFragment&, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent);
// Used by the XMLHttpRequest to check if the responseXML was well formed.
- virtual bool wellFormed() const { return !m_sawError; }
-
- TextPosition textPosition() const;
+ virtual bool wellFormed() const override { return !m_sawError; }
static bool supportsXMLVersion(const String&);
private:
- XMLDocumentParser(Document*, FrameView* = 0);
- XMLDocumentParser(DocumentFragment*, Element*, ParserContentPolicy);
+ XMLDocumentParser(Document&, FrameView* = nullptr);
+ XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy);
// From DocumentParser
- virtual void insert(const SegmentedString&);
- virtual void append(PassRefPtr<StringImpl>);
- virtual void finish();
- virtual bool isWaitingForScripts() const;
- virtual void stopParsing();
- virtual void detach();
- virtual OrdinalNumber lineNumber() const;
- OrdinalNumber columnNumber() const;
+ virtual void insert(const SegmentedString&) override;
+ virtual void append(RefPtr<StringImpl>&&) override;
+ virtual void finish() override;
+ virtual bool isWaitingForScripts() const override;
+ virtual void stopParsing() override;
+ virtual void detach() override;
+
+ virtual TextPosition textPosition() const override;
+ virtual bool shouldAssociateConsoleMessagesWithTextPosition() const override;
// from CachedResourceClient
- virtual void notifyFinished(CachedResource*);
+ virtual void notifyFinished(CachedResource*) override;
void end();
@@ -125,21 +117,7 @@ class Text;
bool appendFragmentSource(const String&);
-#if USE(QXMLSTREAM)
-private:
- void parse();
- void startDocument();
- void parseStartElement();
- void parseEndElement();
- void parseCharacters();
- void parseProcessingInstruction();
- void parseCdata();
- void parseComment();
- void endDocument();
- void parseDtd();
- bool hasError() const;
-#else
-public:
+ public:
// callbacks from parser SAX
void error(XMLErrors::ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0);
void startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
@@ -158,7 +136,7 @@ public:
int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; }
void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; }
-#endif
+
private:
void initializeParserContext(const CString& chunk = CString());
@@ -168,8 +146,8 @@ public:
void insertErrorMessageBlock();
- void enterText();
- void exitText();
+ void createLeafTextNode();
+ bool updateLeafTextNode();
void doWrite(const String&);
void doEnd();
@@ -178,17 +156,13 @@ public:
SegmentedString m_originalSourceForTransform;
-#if USE(QXMLSTREAM)
- QXmlStreamReader m_stream;
- bool m_wroteText;
-#else
- xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; };
+ xmlParserCtxtPtr context() const { return m_context ? m_context->context() : nullptr; };
RefPtr<XMLParserContext> m_context;
- OwnPtr<PendingCallbacks> m_pendingCallbacks;
+ std::unique_ptr<PendingCallbacks> m_pendingCallbacks;
Vector<xmlChar> m_bufferedText;
int m_depthTriggeringEntityExpansion;
bool m_isParsingEntityDeclaration;
-#endif
+
ContainerNode* m_currentNode;
Vector<ContainerNode*> m_currentNodeStack;
@@ -203,7 +177,7 @@ public:
bool m_requestingScript;
bool m_finishCalled;
- XMLErrors m_xmlErrors;
+ std::unique_ptr<XMLErrors> m_xmlErrors;
CachedResourceHandle<CachedScript> m_pendingScript;
RefPtr<Element> m_scriptElement;
@@ -218,7 +192,7 @@ public:
};
#if ENABLE(XSLT)
-void* xmlDocPtrForString(CachedResourceLoader*, const String& source, const String& url);
+void* xmlDocPtrForString(CachedResourceLoader&, const String& source, const String& url);
#endif
HashMap<String, String> parseAttributes(const String&, bool& attrsOK);
diff --git a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
index 8b8786b7a..0e77eac4d 100644
--- a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
+++ b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
@@ -7,6 +7,7 @@
* Copyright (C) 2008 Holger Hans Peter Freyther
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ * Copyright (C) 2013 Samsung Electronics. 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
@@ -44,21 +45,21 @@
#include "HTMLNames.h"
#include "HTMLStyleElement.h"
#include "HTMLTemplateElement.h"
+#include "Page.h"
#include "ProcessingInstruction.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "ScriptElement.h"
#include "ScriptSourceCode.h"
-#include "ScriptValue.h"
#include "SecurityOrigin.h"
+#include "Settings.h"
#include "TextResourceDecoder.h"
#include "TransformSource.h"
#include "XMLNSNames.h"
#include "XMLDocumentParserScope.h"
-#include <libxml/parser.h>
#include <libxml/parserInternals.h>
-#include <wtf/text/CString.h>
+#include <wtf/Ref.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
#include <wtf/Vector.h>
@@ -69,23 +70,40 @@
#include <libxslt/xslt.h>
#endif
-using namespace std;
-
namespace WebCore {
+#if ENABLE(XSLT)
+static inline bool hasNoStyleInformation(Document* document)
+{
+ if (document->sawElementsInKnownNamespaces())
+ return false;
+
+ if (document->transformSourceDocument())
+ return false;
+
+ if (!document->frame() || !document->frame()->page())
+ return false;
+
+ if (!document->frame()->page()->settings().developerExtrasEnabled())
+ return false;
+
+ if (document->frame()->tree().parent())
+ return false; // This document is not in a top frame
+
+ return true;
+}
+#endif
+
class PendingCallbacks {
WTF_MAKE_NONCOPYABLE(PendingCallbacks); WTF_MAKE_FAST_ALLOCATED;
public:
+ PendingCallbacks() { }
~PendingCallbacks() { }
- static PassOwnPtr<PendingCallbacks> create()
- {
- return adoptPtr(new PendingCallbacks);
- }
-
+
void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes)
{
- OwnPtr<PendingStartElementNSCallback> callback = adoptPtr(new PendingStartElementNSCallback);
+ auto callback = std::make_unique<PendingStartElementNSCallback>();
callback->xmlLocalName = xmlStrdup(xmlLocalName);
callback->xmlPrefix = xmlStrdup(xmlPrefix);
@@ -110,87 +128,85 @@ public:
callback->attributes[i * 5 + 4] = callback->attributes[i * 5 + 3] + len;
}
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendEndElementNSCallback()
{
- m_callbacks.append(adoptPtr(new PendingEndElementNSCallback));
+ m_callbacks.append(std::make_unique<PendingEndElementNSCallback>());
}
void appendCharactersCallback(const xmlChar* s, int len)
{
- OwnPtr<PendingCharactersCallback> callback = adoptPtr(new PendingCharactersCallback);
+ auto callback = std::make_unique<PendingCharactersCallback>();
callback->s = xmlStrndup(s, len);
callback->len = len;
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data)
{
- OwnPtr<PendingProcessingInstructionCallback> callback = adoptPtr(new PendingProcessingInstructionCallback);
+ auto callback = std::make_unique<PendingProcessingInstructionCallback>();
callback->target = xmlStrdup(target);
callback->data = xmlStrdup(data);
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendCDATABlockCallback(const xmlChar* s, int len)
{
- OwnPtr<PendingCDATABlockCallback> callback = adoptPtr(new PendingCDATABlockCallback);
+ auto callback = std::make_unique<PendingCDATABlockCallback>();
callback->s = xmlStrndup(s, len);
callback->len = len;
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendCommentCallback(const xmlChar* s)
{
- OwnPtr<PendingCommentCallback> callback = adoptPtr(new PendingCommentCallback);
+ auto callback = std::make_unique<PendingCommentCallback>();
callback->s = xmlStrdup(s);
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendInternalSubsetCallback(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
{
- OwnPtr<PendingInternalSubsetCallback> callback = adoptPtr(new PendingInternalSubsetCallback);
+ auto callback = std::make_unique<PendingInternalSubsetCallback>();
callback->name = xmlStrdup(name);
callback->externalID = xmlStrdup(externalID);
callback->systemID = xmlStrdup(systemID);
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void appendErrorCallback(XMLErrors::ErrorType type, const xmlChar* message, OrdinalNumber lineNumber, OrdinalNumber columnNumber)
{
- OwnPtr<PendingErrorCallback> callback = adoptPtr(new PendingErrorCallback);
+ auto callback = std::make_unique<PendingErrorCallback>();
callback->message = xmlStrdup(message);
callback->type = type;
callback->lineNumber = lineNumber;
callback->columnNumber = columnNumber;
- m_callbacks.append(callback.release());
+ m_callbacks.append(WTFMove(callback));
}
void callAndRemoveFirstCallback(XMLDocumentParser* parser)
{
- OwnPtr<PendingCallback> callback = m_callbacks.takeFirst();
+ std::unique_ptr<PendingCallback> callback = m_callbacks.takeFirst();
callback->call(parser);
}
bool isEmpty() const { return m_callbacks.isEmpty(); }
private:
- PendingCallbacks() { }
-
struct PendingCallback {
virtual ~PendingCallback() { }
virtual void call(XMLDocumentParser* parser) = 0;
@@ -330,7 +346,7 @@ private:
OrdinalNumber columnNumber;
};
- Deque<OwnPtr<PendingCallback> > m_callbacks;
+ Deque<std::unique_ptr<PendingCallback>> m_callbacks;
};
// --------------------------------
@@ -347,12 +363,16 @@ static int matchFunc(const char*)
class OffsetBuffer {
WTF_MAKE_FAST_ALLOCATED;
public:
- OffsetBuffer(const Vector<char>& b) : m_buffer(b), m_currentOffset(0) { }
+ OffsetBuffer(Vector<char> buffer)
+ : m_buffer(WTFMove(buffer))
+ , m_currentOffset(0)
+ {
+ }
int readOutBytes(char* outputBuffer, unsigned askedToRead)
{
unsigned bytesLeft = m_buffer.size() - m_currentOffset;
- unsigned lenToCopy = min(askedToRead, bytesLeft);
+ unsigned lenToCopy = std::min(askedToRead, bytesLeft);
if (lenToCopy) {
memcpy(outputBuffer, m_buffer.data() + m_currentOffset, lenToCopy);
m_currentOffset += lenToCopy;
@@ -386,7 +406,7 @@ static void switchToUTF16(xmlParserCtxtPtr ctxt)
xmlSwitchEncoding(ctxt, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
}
-static bool shouldAllowExternalLoad(const KURL& url)
+static bool shouldAllowExternalLoad(const URL& url)
{
String urlString = url.string();
@@ -427,31 +447,33 @@ static void* openFunc(const char* uri)
ASSERT(XMLDocumentParserScope::currentCachedResourceLoader);
ASSERT(currentThread() == libxmlLoaderThread);
- KURL url(KURL(), uri);
+ URL url(URL(), uri);
if (!shouldAllowExternalLoad(url))
return &globalDescriptor;
ResourceError error;
ResourceResponse response;
- Vector<char> data;
+ RefPtr<SharedBuffer> data;
{
CachedResourceLoader* cachedResourceLoader = XMLDocumentParserScope::currentCachedResourceLoader;
- XMLDocumentParserScope scope(0);
+ XMLDocumentParserScope scope(nullptr);
// FIXME: We should restore the original global error handler as well.
if (cachedResourceLoader->frame())
- cachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data);
+ cachedResourceLoader->frame()->loader().loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data);
}
// We have to check the URL again after the load to catch redirects.
// See <https://bugs.webkit.org/show_bug.cgi?id=21963>.
if (!shouldAllowExternalLoad(response.url()))
return &globalDescriptor;
-
- return new OffsetBuffer(data);
+ Vector<char> buffer;
+ if (data)
+ buffer.append(data->data(), data->size());
+ return new OffsetBuffer(WTFMove(buffer));
}
static int readFunc(void* context, char* buffer, int len)
@@ -488,7 +510,7 @@ static void errorFunc(void*, const char*, ...)
static bool didInit = false;
-PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
+Ref<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
{
if (!didInit) {
xmlInitParser();
@@ -506,12 +528,12 @@ PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerP
switchToUTF16(parser);
- return adoptRef(new XMLParserContext(parser));
+ return adoptRef(*new XMLParserContext(parser));
}
// Chunk should be encoded in UTF-8
-PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const CString& chunk)
+RefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const CString& chunk)
{
if (!didInit) {
xmlInitParser();
@@ -542,7 +564,7 @@ PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerP
parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
parser->_private = userData;
- return adoptRef(new XMLParserContext(parser));
+ return adoptRef(*new XMLParserContext(parser));
}
// --------------------------------
@@ -552,14 +574,14 @@ bool XMLDocumentParser::supportsXMLVersion(const String& version)
return version == "1.0";
}
-XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView)
+XMLDocumentParser::XMLDocumentParser(Document& document, FrameView* frameView)
: ScriptableDocumentParser(document)
, m_view(frameView)
- , m_context(0)
- , m_pendingCallbacks(PendingCallbacks::create())
+ , m_context(nullptr)
+ , m_pendingCallbacks(std::make_unique<PendingCallbacks>())
, m_depthTriggeringEntityExpansion(-1)
, m_isParsingEntityDeclaration(false)
- , m_currentNode(document)
+ , m_currentNode(&document)
, m_sawError(false)
, m_sawCSS(false)
, m_sawXSLTransform(false)
@@ -568,21 +590,20 @@ XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView)
, m_parserPaused(false)
, m_requestingScript(false)
, m_finishCalled(false)
- , m_xmlErrors(document)
- , m_pendingScript(0)
+ , m_pendingScript(nullptr)
, m_scriptStartPosition(TextPosition::belowRangePosition())
, m_parsingFragment(false)
{
}
-XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
- : ScriptableDocumentParser(fragment->document(), parserContentPolicy)
- , m_view(0)
- , m_context(0)
- , m_pendingCallbacks(PendingCallbacks::create())
+XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
+ : ScriptableDocumentParser(fragment.document(), parserContentPolicy)
+ , m_view(nullptr)
+ , m_context(nullptr)
+ , m_pendingCallbacks(std::make_unique<PendingCallbacks>())
, m_depthTriggeringEntityExpansion(-1)
, m_isParsingEntityDeclaration(false)
- , m_currentNode(fragment)
+ , m_currentNode(&fragment)
, m_sawError(false)
, m_sawCSS(false)
, m_sawXSLTransform(false)
@@ -591,42 +612,40 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent
, m_parserPaused(false)
, m_requestingScript(false)
, m_finishCalled(false)
- , m_xmlErrors(fragment->document())
, m_pendingScript(0)
, m_scriptStartPosition(TextPosition::belowRangePosition())
, m_parsingFragment(true)
{
- fragment->ref();
+ fragment.ref();
// Add namespaces based on the parent node
Vector<Element*> elemStack;
while (parentElement) {
elemStack.append(parentElement);
- ContainerNode* n = parentElement->parentNode();
- if (!n || !n->isElementNode())
+ ContainerNode* node = parentElement->parentNode();
+ if (!is<Element>(node))
break;
- parentElement = toElement(n);
+ parentElement = downcast<Element>(node);
}
if (elemStack.isEmpty())
return;
+ // FIXME: Share code with isDefaultNamespace() per http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#parsing-xhtml-fragments
for (; !elemStack.isEmpty(); elemStack.removeLast()) {
Element* element = elemStack.last();
if (element->hasAttributes()) {
- for (unsigned i = 0; i < element->attributeCount(); i++) {
- const Attribute* attribute = element->attributeItem(i);
- if (attribute->localName() == xmlnsAtom)
- m_defaultNamespaceURI = attribute->value();
- else if (attribute->prefix() == xmlnsAtom)
- m_prefixToNamespaceMap.set(attribute->localName(), attribute->value());
+ for (const Attribute& attribute : element->attributesIterator()) {
+ if (attribute.localName() == xmlnsAtom)
+ m_defaultNamespaceURI = attribute.value();
+ else if (attribute.prefix() == xmlnsAtom)
+ m_prefixToNamespaceMap.set(attribute.localName(), attribute.value());
}
}
}
- // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace.
- if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument())
+ if (m_defaultNamespaceURI.isNull())
m_defaultNamespaceURI = parentElement->namespaceURI();
}
@@ -661,11 +680,13 @@ void XMLDocumentParser::doWrite(const String& parseString)
if (parseString.length()) {
// JavaScript may cause the parser to detach during xmlParseChunk
// keep this alive until this function is done.
- RefPtr<XMLDocumentParser> protect(this);
+ Ref<XMLDocumentParser> protect(*this);
+
+ XMLDocumentParserScope scope(&document()->cachedResourceLoader());
+ // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16?
switchToUTF16(context->context());
- XMLDocumentParserScope scope(document()->cachedResourceLoader());
- xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
+ xmlParseChunk(context->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), sizeof(UChar) * parseString.length(), 0);
// JavaScript (which may be run under the xmlParseChunk callstack) may
// cause the parser to be stopped or detached.
@@ -776,7 +797,8 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha
return;
}
- exitText();
+ if (!updateLeafTextNode())
+ return;
AtomicString localName = toAtomicString(xmlLocalName);
AtomicString uri = toAtomicString(xmlURI);
@@ -798,23 +820,19 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha
m_sawFirstElement = true;
QualifiedName qName(prefix, localName, uri);
- RefPtr<Element> newElement = m_currentNode->document()->createElement(qName, true);
- if (!newElement) {
- stopParsing();
- return;
- }
+ auto newElement = m_currentNode->document().createElement(qName, true);
Vector<Attribute> prefixedAttributes;
ExceptionCode ec = 0;
handleNamespaceAttributes(prefixedAttributes, libxmlNamespaces, nb_namespaces, ec);
if (ec) {
- setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy());
+ setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy());
stopParsing();
return;
}
handleElementAttributes(prefixedAttributes, libxmlAttributes, nb_attributes, ec);
- setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy());
+ setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy());
if (ec) {
stopParsing();
return;
@@ -822,30 +840,28 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha
newElement->beginParsingChildren();
- ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get());
+ ScriptElement* scriptElement = toScriptElementIfPossible(newElement.ptr());
if (scriptElement)
m_scriptStartPosition = textPosition();
- m_currentNode->parserAppendChild(newElement.get());
+ m_currentNode->parserAppendChild(newElement.copyRef());
+ if (!m_currentNode) // Synchronous DOM events may have removed the current node.
+ return;
- const ContainerNode* currentNode = m_currentNode;
#if ENABLE(TEMPLATE_ELEMENT)
- if (newElement->hasTagName(HTMLNames::templateTag))
- pushCurrentNode(toHTMLTemplateElement(newElement.get())->content());
+ if (is<HTMLTemplateElement>(newElement))
+ pushCurrentNode(downcast<HTMLTemplateElement>(newElement.get()).content());
else
- pushCurrentNode(newElement.get());
+ pushCurrentNode(newElement.ptr());
#else
- pushCurrentNode(newElement.get());
+ pushCurrentNode(newElement.ptr());
#endif
- if (m_view && currentNode->attached() && !newElement->attached())
- newElement->attach();
-
- if (newElement->hasTagName(HTMLNames::htmlTag))
- static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser();
+ if (is<HTMLHtmlElement>(newElement))
+ downcast<HTMLHtmlElement>(newElement.get()).insertedByParser();
if (!m_parsingFragment && isFirstElement && document()->frame())
- document()->frame()->loader()->dispatchDocumentElementAvailable();
+ document()->frame()->injectUserScripts(InjectAtDocumentStart);
}
void XMLDocumentParser::endElementNs()
@@ -860,38 +876,39 @@ void XMLDocumentParser::endElementNs()
// JavaScript can detach the parser. Make sure this is not released
// before the end of this method.
- RefPtr<XMLDocumentParser> protect(this);
+ Ref<XMLDocumentParser> protect(*this);
- exitText();
+ if (!updateLeafTextNode())
+ return;
- RefPtr<ContainerNode> n = m_currentNode;
- n->finishParsingChildren();
+ RefPtr<ContainerNode> node = m_currentNode;
+ node->finishParsingChildren();
// Once we reach the depth again where entity expansion started, stop executing the work-around.
if (hackAroundLibXMLEntityParsingBug() && context()->depth <= depthTriggeringEntityExpansion())
setDepthTriggeringEntityExpansion(-1);
- if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptElementIfPossible(toElement(n.get()))) {
+ if (!scriptingContentIsAllowed(parserContentPolicy()) && is<Element>(*node) && toScriptElementIfPossible(downcast<Element>(node.get()))) {
popCurrentNode();
- n->remove(IGNORE_EXCEPTION);
+ node->remove(IGNORE_EXCEPTION);
return;
}
- if (!n->isElementNode() || !m_view) {
+ if (!node->isElementNode() || !m_view) {
popCurrentNode();
return;
}
- Element* element = toElement(n.get());
+ Element& element = downcast<Element>(*node);
// The element's parent may have already been removed from document.
// Parsing continues in this case, but scripts aren't executed.
- if (!element->inDocument()) {
+ if (!element.inDocument()) {
popCurrentNode();
return;
}
- ScriptElement* scriptElement = toScriptElementIfPossible(element);
+ ScriptElement* scriptElement = toScriptElementIfPossible(&element);
if (!scriptElement) {
popCurrentNode();
return;
@@ -909,14 +926,14 @@ void XMLDocumentParser::endElementNs()
scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition));
else if (scriptElement->willBeParserExecuted()) {
m_pendingScript = scriptElement->cachedScript();
- m_scriptElement = element;
+ m_scriptElement = &element;
m_pendingScript->addClient(this);
// m_pendingScript will be 0 if script was already loaded and addClient() executed it.
if (m_pendingScript)
pauseParsing();
} else
- m_scriptElement = 0;
+ m_scriptElement = nullptr;
// JavaScript may have detached the parser
if (isDetached())
@@ -937,7 +954,7 @@ void XMLDocumentParser::characters(const xmlChar* s, int len)
}
if (!m_leafTextNode)
- enterText();
+ createLeafTextNode();
m_bufferedText.append(s, len);
}
@@ -955,8 +972,9 @@ void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va
vsnprintf(m, sizeof(m) - 1, message, args);
#endif
+ TextPosition position = textPosition();
if (m_parserPaused)
- m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(m), lineNumber(), columnNumber());
+ m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(m), position.m_line, position.m_column);
else
handleError(type, m, textPosition());
@@ -975,20 +993,19 @@ void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlCh
return;
}
- exitText();
+ if (!updateLeafTextNode())
+ return;
// ### handle exceptions
ExceptionCode ec = 0;
- RefPtr<ProcessingInstruction> pi = m_currentNode->document()->createProcessingInstruction(
+ Ref<ProcessingInstruction> pi = *m_currentNode->document().createProcessingInstruction(
toString(target), toString(data), ec);
if (ec)
return;
pi->setCreatedByParser(true);
- m_currentNode->parserAppendChild(pi.get());
- if (m_view && !pi->attached())
- pi->attach();
+ m_currentNode->parserAppendChild(pi.copyRef());
pi->finishParsingChildren();
@@ -1011,12 +1028,11 @@ void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
return;
}
- exitText();
+ if (!updateLeafTextNode())
+ return;
- RefPtr<CDATASection> newNode = CDATASection::create(m_currentNode->document(), toString(s, len));
- m_currentNode->parserAppendChild(newNode.get());
- if (m_view && !newNode->attached())
- newNode->attach();
+ auto newNode = CDATASection::create(m_currentNode->document(), toString(s, len));
+ m_currentNode->parserAppendChild(WTFMove(newNode));
}
void XMLDocumentParser::comment(const xmlChar* s)
@@ -1029,12 +1045,11 @@ void XMLDocumentParser::comment(const xmlChar* s)
return;
}
- exitText();
+ if (!updateLeafTextNode())
+ return;
- RefPtr<Comment> newNode = Comment::create(m_currentNode->document(), toString(s));
- m_currentNode->parserAppendChild(newNode.get());
- if (m_view && !newNode->attached())
- newNode->attach();
+ auto newNode = Comment::create(m_currentNode->document(), toString(s));
+ m_currentNode->parserAppendChild(WTFMove(newNode));
}
enum StandaloneInfo {
@@ -1063,7 +1078,7 @@ void XMLDocumentParser::startDocument(const xmlChar* version, const xmlChar* enc
void XMLDocumentParser::endDocument()
{
- exitText();
+ updateLeafTextNode();
}
void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
@@ -1077,7 +1092,7 @@ void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* exter
}
if (document())
- document()->parserAppendChild(DocumentType::create(document(), toString(name), toString(externalID), toString(systemID)));
+ document()->parserAppendChild(DocumentType::create(*document(), toString(name), toString(externalID), toString(systemID)));
}
static inline XMLDocumentParser* getParser(void* closure)
@@ -1340,7 +1355,7 @@ void XMLDocumentParser::initializeParserContext(const CString& chunk)
m_sawXSLTransform = false;
m_sawFirstElement = false;
- XMLDocumentParserScope scope(document()->cachedResourceLoader());
+ XMLDocumentParserScope scope(&document()->cachedResourceLoader());
if (m_parsingFragment)
m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
else {
@@ -1355,23 +1370,22 @@ void XMLDocumentParser::doEnd()
if (m_context) {
// Tell libxml we're done.
{
- XMLDocumentParserScope scope(document()->cachedResourceLoader());
+ XMLDocumentParserScope scope(&document()->cachedResourceLoader());
xmlParseChunk(context(), 0, 0, 1);
}
- m_context = 0;
+ m_context = nullptr;
}
}
#if ENABLE(XSLT)
- XMLTreeViewer xmlTreeViewer(document());
- bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && xmlTreeViewer.hasNoStyleInformation();
- if (xmlViewerMode)
+ bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && hasNoStyleInformation(document());
+ if (xmlViewerMode) {
+ XMLTreeViewer xmlTreeViewer(*document());
xmlTreeViewer.transformDocumentToTreeView();
-
- if (m_sawXSLTransform) {
+ } else if (m_sawXSLTransform) {
void* doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform.toString(), document()->url().string());
- document()->setTransformSource(adoptPtr(new TransformSource(doc)));
+ document()->setTransformSource(std::make_unique<TransformSource>(doc));
document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets.
document()->styleResolverChanged(RecalcStyleImmediately);
@@ -1395,10 +1409,10 @@ static inline const char* nativeEndianUTF16Encoding()
return BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE";
}
-void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const String& source, const String& url)
+void* xmlDocPtrForString(CachedResourceLoader& cachedResourceLoader, const String& source, const String& url)
{
if (source.isEmpty())
- return 0;
+ return nullptr;
// Parse in a single chunk into an xmlDocPtr
// FIXME: Hook up error handlers so that a failure to parse the main document results in
@@ -1409,21 +1423,11 @@ void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const Strin
size_t sizeInBytes = source.length() * (is8Bit ? sizeof(LChar) : sizeof(UChar));
const char* encoding = is8Bit ? "iso-8859-1" : nativeEndianUTF16Encoding();
- XMLDocumentParserScope scope(cachedResourceLoader, errorFunc, 0);
+ XMLDocumentParserScope scope(&cachedResourceLoader, errorFunc);
return xmlReadMemory(characters, sizeInBytes, url.latin1().data(), encoding, XSLT_PARSE_OPTIONS);
}
#endif
-OrdinalNumber XMLDocumentParser::lineNumber() const
-{
- return OrdinalNumber::fromOneBasedInt(context() ? context()->input->line : 1);
-}
-
-OrdinalNumber XMLDocumentParser::columnNumber() const
-{
- return OrdinalNumber::fromOneBasedInt(context() ? context()->input->col : 1);
-}
-
TextPosition XMLDocumentParser::textPosition() const
{
xmlParserCtxtPtr context = this->context();
@@ -1433,6 +1437,11 @@ TextPosition XMLDocumentParser::textPosition() const
OrdinalNumber::fromOneBasedInt(context->input->col));
}
+bool XMLDocumentParser::shouldAssociateConsoleMessagesWithTextPosition() const
+{
+ return !m_parserPaused && !m_requestingScript;
+}
+
void XMLDocumentParser::stopParsing()
{
DocumentParser::stopParsing();
@@ -1533,6 +1542,8 @@ static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc
HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
{
+ String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
+
AttributeParseState state;
state.gotAttributes = false;
@@ -1540,11 +1551,14 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
memset(&sax, 0, sizeof(sax));
sax.startElementNs = attributesStartElementNsHandler;
sax.initialized = XML_SAX2_MAGIC;
+
RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
- String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
- xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
+
+ // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16?
+ xmlParseChunk(parser->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), parseString.length() * sizeof(UChar), 1);
+
attrsOK = state.gotAttributes;
- return state.attributes;
+ return WTFMove(state.attributes);
}
}
diff --git a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp b/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp
deleted file mode 100644
index 83fb33422..000000000
--- a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * Copyright (C) 2000 Peter Kelly (pmk@post.com)
- * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "XMLDocumentParser.h"
-
-#include "CDATASection.h"
-#include "CachedScript.h"
-#include "Comment.h"
-#include "CachedResourceLoader.h"
-#include "Document.h"
-#include "DocumentFragment.h"
-#include "DocumentType.h"
-#include "ExceptionCodePlaceholder.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameView.h"
-#include "HTMLEntityParser.h"
-#include "HTMLHtmlElement.h"
-#include "HTMLLinkElement.h"
-#include "HTMLNames.h"
-#include "HTMLStyleElement.h"
-#include "ProcessingInstruction.h"
-#include "ResourceError.h"
-#include "ResourceHandle.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
-#include "ScriptableDocumentParser.h"
-#include "ScriptElement.h"
-#include "ScriptSourceCode.h"
-#include "ScriptValue.h"
-#include "TextResourceDecoder.h"
-#include "TransformSource.h"
-#include "XMLNSNames.h"
-#include <QDebug>
-#include <wtf/StringExtras.h>
-#include <wtf/Threading.h>
-#include <wtf/Vector.h>
-#include <wtf/text/CString.h>
-
-using namespace std;
-
-namespace WebCore {
-
-static inline void setAttributes(Element* element, Vector<Attribute>& attributeVector, ParserContentPolicy parserContentPolicy)
-{
- if (!scriptingContentIsAllowed(parserContentPolicy))
- element->stripScriptingAttributes(attributeVector);
- element->parserSetAttributes(attributeVector);
-}
-
-class EntityResolver : public QXmlStreamEntityResolver {
- virtual QString resolveUndeclaredEntity(const QString &name);
-};
-
-static QString decodeNamedEntity(const QString& entityName)
-{
- UChar utf16DecodedEntity[4];
- size_t numberOfCodePoints = decodeNamedEntityToUCharArray(entityName.toUtf8().constData(), utf16DecodedEntity);
- return QString(reinterpret_cast<const QChar*>(utf16DecodedEntity), numberOfCodePoints);
-}
-
-QString EntityResolver::resolveUndeclaredEntity(const QString &name)
-{
- return decodeNamedEntity(name);
-}
-
-// --------------------------------
-
-bool XMLDocumentParser::supportsXMLVersion(const String& version)
-{
- return version == "1.0";
-}
-
-XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView)
- : ScriptableDocumentParser(document)
- , m_view(frameView)
- , m_wroteText(false)
- , m_currentNode(document)
- , m_sawError(false)
- , m_sawCSS(false)
- , m_sawXSLTransform(false)
- , m_sawFirstElement(false)
- , m_isXHTMLDocument(false)
- , m_parserPaused(false)
- , m_requestingScript(false)
- , m_finishCalled(false)
- , m_xmlErrors(document)
- , m_pendingScript(0)
- , m_scriptStartPosition(TextPosition::belowRangePosition())
- , m_parsingFragment(false)
-{
- m_stream.setEntityResolver(new EntityResolver);
-}
-
-XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
- : ScriptableDocumentParser(fragment->document(), parserContentPolicy)
- , m_view(0)
- , m_wroteText(false)
- , m_currentNode(fragment)
- , m_sawError(false)
- , m_sawCSS(false)
- , m_sawXSLTransform(false)
- , m_sawFirstElement(false)
- , m_isXHTMLDocument(false)
- , m_parserPaused(false)
- , m_requestingScript(false)
- , m_finishCalled(false)
- , m_xmlErrors(fragment->document())
- , m_pendingScript(0)
- , m_scriptStartPosition(TextPosition::belowRangePosition())
- , m_parsingFragment(true)
-{
- fragment->ref();
-
- // Add namespaces based on the parent node
- Vector<Element*> elemStack;
- while (parentElement) {
- elemStack.append(parentElement);
-
- Node* n = parentElement->parentNode();
- if (!n || !n->isElementNode())
- break;
- parentElement = toElement(n);
- }
-
- if (elemStack.isEmpty())
- return;
-
- QXmlStreamNamespaceDeclarations namespaces;
- for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {
- element->synchronizeAllAttributes();
- if (const ElementData* attrs = element->elementData()) {
- for (unsigned i = 0; i < attrs->length(); i++) {
- const Attribute* attr = attrs->attributeItem(i);
- if (attr->localName() == "xmlns")
- m_defaultNamespaceURI = attr->value();
- else if (attr->prefix() == "xmlns")
- namespaces.append(QXmlStreamNamespaceDeclaration(attr->localName(), attr->value()));
- }
- }
- }
- m_stream.addExtraNamespaceDeclarations(namespaces);
- m_stream.setEntityResolver(new EntityResolver);
-
- // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace.
- if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument())
- m_defaultNamespaceURI = parentElement->namespaceURI();
-}
-
-XMLDocumentParser::~XMLDocumentParser()
-{
- clearCurrentNodeStack();
- if (m_pendingScript)
- m_pendingScript->removeClient(this);
- delete m_stream.entityResolver();
-}
-
-void XMLDocumentParser::doWrite(const String& parseString)
-{
- m_wroteText = true;
-
- if (document()->decoder() && document()->decoder()->sawError()) {
- // If the decoder saw an error, report it as fatal (stops parsing)
- handleError(XMLErrors::fatal, "Encoding error", textPosition());
- return;
- }
-
- QString data(parseString);
- if (!data.isEmpty()) {
- // JavaScript may cause the parser to detach,
- // keep this alive until this function is done.
- RefPtr<XMLDocumentParser> protect(this);
-
- m_stream.addData(data);
- parse();
- }
-
- return;
-}
-
-void XMLDocumentParser::initializeParserContext(const CString&)
-{
- DocumentParser::startParsing();
- m_sawError = false;
- m_sawCSS = false;
- m_sawXSLTransform = false;
- m_sawFirstElement = false;
-}
-
-void XMLDocumentParser::doEnd()
-{
-#if ENABLE(XSLT)
- if (m_sawXSLTransform) {
- document()->setTransformSource(adoptPtr(new TransformSource(m_originalSourceForTransform.toString())));
- document()->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets.
- document()->styleResolverChanged(RecalcStyleImmediately);
-
- // styleResolverChanged() call can detach the parser and null out its document.
- // In that case, we just bail out.
- if (isDetached())
- return;
-
- document()->setParsing(true);
- DocumentParser::stopParsing();
- }
-#endif
-
- if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError
- || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform && !m_sawError))
- handleError(XMLErrors::fatal, qPrintable(m_stream.errorString()), textPosition());
-}
-
-OrdinalNumber XMLDocumentParser::lineNumber() const
-{
- return OrdinalNumber::fromOneBasedInt(m_stream.lineNumber());
-}
-
-OrdinalNumber XMLDocumentParser::columnNumber() const
-{
- return OrdinalNumber::fromOneBasedInt(m_stream.columnNumber());
-}
-
-TextPosition XMLDocumentParser::textPosition() const
-{
- return TextPosition(lineNumber(), columnNumber());
-}
-
-void XMLDocumentParser::stopParsing()
-{
- ScriptableDocumentParser::stopParsing();
-}
-
-void XMLDocumentParser::resumeParsing()
-{
- ASSERT(m_parserPaused);
-
- m_parserPaused = false;
-
- // First, execute any pending callbacks
- parse();
- if (m_parserPaused)
- return;
-
- // Then, write any pending data
- SegmentedString rest = m_pendingSrc;
- m_pendingSrc.clear();
- append(rest.toString().impl());
-
- // Finally, if finish() has been called and append() didn't result
- // in any further callbacks being queued, call end()
- if (m_finishCalled && !m_parserPaused && !m_pendingScript)
- end();
-}
-
-bool XMLDocumentParser::appendFragmentSource(const String& source)
-{
- ASSERT(!m_sawFirstElement);
- append(String("<qxmlstreamdummyelement>").impl());
- append(source.impl());
- append(String("</qxmlstreamdummyelement>").impl());
- return !hasError();
-}
-
-// --------------------------------
-
-struct AttributeParseState {
- HashMap<String, String> attributes;
- bool gotAttributes;
-};
-
-static void attributesStartElementNsHandler(AttributeParseState* state, const QXmlStreamAttributes& attrs)
-{
- if (attrs.count() <= 0)
- return;
-
- state->gotAttributes = true;
-
- for (int i = 0; i < attrs.count(); i++) {
- const QXmlStreamAttribute& attr = attrs[i];
- String attrLocalName = attr.name();
- String attrValue = attr.value();
- String attrURI = attr.namespaceUri();
- String attrQName = attr.qualifiedName();
- state->attributes.set(attrQName, attrValue);
- }
-}
-
-HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
-{
- AttributeParseState state;
- state.gotAttributes = false;
-
- QXmlStreamReader stream;
- QString dummy = QString(QLatin1String("<?xml version=\"1.0\"?><attrs %1 />")).arg(string);
- stream.addData(dummy);
- while (!stream.atEnd()) {
- stream.readNext();
- if (stream.isStartElement()) {
- attributesStartElementNsHandler(&state, stream.attributes());
- }
- }
- attrsOK = state.gotAttributes;
- return state.attributes;
-}
-
-static inline String prefixFromQName(const QString& qName)
-{
- const int offset = qName.indexOf(QLatin1Char(':'));
- if (offset <= 0)
- return String();
- else
- return qName.left(offset);
-}
-
-static inline void handleNamespaceAttributes(Vector<Attribute>& prefixedAttributes, const QXmlStreamNamespaceDeclarations &ns, ExceptionCode& ec)
-{
- for (int i = 0; i < ns.count(); ++i) {
- const QXmlStreamNamespaceDeclaration &decl = ns[i];
- String namespaceURI = decl.namespaceUri();
- String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:");
- namespaceQName.append(decl.prefix());
-
- QualifiedName parsedName = anyName;
- if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceURI, namespaceQName, ec))
- return;
-
- prefixedAttributes.append(Attribute(parsedName, namespaceURI));
- }
-}
-
-static inline void handleElementAttributes(Vector<Attribute>& prefixedAttributes, const QXmlStreamAttributes &attrs, ExceptionCode& ec)
-{
- for (int i = 0; i < attrs.count(); ++i) {
- const QXmlStreamAttribute &attr = attrs[i];
- String attrLocalName = attr.name();
- String attrValue = attr.value();
- String attrURI = attr.namespaceUri().isEmpty() ? String() : String(attr.namespaceUri());
- String attrQName = attr.qualifiedName();
-
- QualifiedName parsedName = anyName;
- if (!Element::parseAttributeName(parsedName, attrURI, attrQName, ec))
- return;
-
- prefixedAttributes.append(Attribute(parsedName, attrValue));
- }
-}
-
-void XMLDocumentParser::parse()
-{
- while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) {
- m_stream.readNext();
- switch (m_stream.tokenType()) {
- case QXmlStreamReader::StartDocument:
- startDocument();
- break;
- case QXmlStreamReader::EndDocument:
- endDocument();
- break;
- case QXmlStreamReader::StartElement:
- parseStartElement();
- break;
- case QXmlStreamReader::EndElement:
- parseEndElement();
- break;
- case QXmlStreamReader::Characters: {
- if (m_stream.isCDATA()) {
- //cdata
- parseCdata();
- } else {
- //characters
- parseCharacters();
- }
- break;
- }
- case QXmlStreamReader::Comment:
- parseComment();
- break;
- case QXmlStreamReader::DTD:
- //qDebug()<<"------------- DTD";
- parseDtd();
- break;
- case QXmlStreamReader::EntityReference: {
- //qDebug()<<"---------- ENTITY = "<<m_stream.name().toString()
- // <<", t = "<<m_stream.text().toString();
- if (isXHTMLDocument()) {
- QString entity = m_stream.name().toString();
- if (!m_leafTextNode)
- enterText();
- // qDebug()<<" ------- adding entity "<<str;
- m_leafTextNode->appendData(decodeNamedEntity(entity), IGNORE_EXCEPTION);
- }
- break;
- }
- case QXmlStreamReader::ProcessingInstruction:
- parseProcessingInstruction();
- break;
- default: {
- if (m_stream.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
- XMLErrors::ErrorType type = (m_stream.error() == QXmlStreamReader::NotWellFormedError) ?
- XMLErrors::fatal : XMLErrors::warning;
- handleError(type, qPrintable(m_stream.errorString()), textPosition());
- }
- break;
- }
- }
- }
-}
-
-void XMLDocumentParser::startDocument()
-{
- initializeParserContext();
-
- if (!m_parsingFragment) {
- document()->setXMLStandalone(m_stream.isStandaloneDocument(), IGNORE_EXCEPTION);
-
- QStringRef version = m_stream.documentVersion();
- if (!version.isEmpty())
- document()->setXMLVersion(version, IGNORE_EXCEPTION);
- QStringRef encoding = m_stream.documentEncoding();
- if (!encoding.isEmpty())
- document()->setXMLEncoding(encoding);
- document()->setHasXMLDeclaration(!version.isEmpty());
- }
-}
-
-void XMLDocumentParser::parseStartElement()
-{
- if (!m_sawFirstElement && m_parsingFragment) {
- // skip dummy element for fragments
- m_sawFirstElement = true;
- return;
- }
-
- exitText();
-
- String localName = m_stream.name();
- String uri = m_stream.namespaceUri();
- String prefix = prefixFromQName(m_stream.qualifiedName().toString());
-
- if (m_parsingFragment && uri.isNull()) {
- Q_ASSERT(prefix.isNull());
- uri = m_defaultNamespaceURI;
- }
-
- QualifiedName qName(prefix, localName, uri);
- RefPtr<Element> newElement = document()->createElement(qName, true);
- if (!newElement) {
- stopParsing();
- return;
- }
-
- bool isFirstElement = !m_sawFirstElement;
- m_sawFirstElement = true;
-
- Vector<Attribute> prefixedAttributes;
- ExceptionCode ec = 0;
- handleNamespaceAttributes(prefixedAttributes, m_stream.namespaceDeclarations(), ec);
- if (ec) {
- setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy());
- stopParsing();
- return;
- }
-
- handleElementAttributes(prefixedAttributes, m_stream.attributes(), ec);
- setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy());
- if (ec) {
- stopParsing();
- return;
- }
-
- ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get());
- if (scriptElement)
- m_scriptStartPosition = textPosition();
-
- m_currentNode->parserAppendChild(newElement.get());
-
- pushCurrentNode(newElement.get());
- if (m_view && !newElement->attached())
- newElement->attach();
-
- if (newElement->hasTagName(HTMLNames::htmlTag))
- static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser();
-
- if (isFirstElement && document()->frame())
- document()->frame()->loader()->dispatchDocumentElementAvailable();
-}
-
-void XMLDocumentParser::parseEndElement()
-{
- exitText();
-
- RefPtr<ContainerNode> n = m_currentNode;
- n->finishParsingChildren();
-
- if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptElementIfPossible(toElement(n.get()))) {
- popCurrentNode();
- n->remove(IGNORE_EXCEPTION);
- return;
- }
-
- if (!n->isElementNode() || !m_view) {
- if (!m_currentNodeStack.isEmpty())
- popCurrentNode();
- return;
- }
-
- Element* element = toElement(n.get());
-
- // The element's parent may have already been removed from document.
- // Parsing continues in this case, but scripts aren't executed.
- if (!element->inDocument()) {
- popCurrentNode();
- return;
- }
-
- ScriptElement* scriptElement = toScriptElementIfPossible(element);
- if (!scriptElement) {
- popCurrentNode();
- return;
- }
-
- // don't load external scripts for standalone documents (for now)
- ASSERT(!m_pendingScript);
- m_requestingScript = true;
-
- if (scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) {
- if (scriptElement->readyToBeParserExecuted())
- scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition));
- else if (scriptElement->willBeParserExecuted()) {
- m_pendingScript = scriptElement->cachedScript();
- m_scriptElement = element;
- m_pendingScript->addClient(this);
-
- // m_pendingScript will be 0 if script was already loaded and addClient() executed it.
- if (m_pendingScript)
- pauseParsing();
- } else
- m_scriptElement = 0;
- }
- m_requestingScript = false;
- popCurrentNode();
-}
-
-void XMLDocumentParser::parseCharacters()
-{
- if (!m_leafTextNode)
- enterText();
- m_leafTextNode->appendData(m_stream.text(), IGNORE_EXCEPTION);
-}
-
-void XMLDocumentParser::parseProcessingInstruction()
-{
- exitText();
-
- // ### handle exceptions
- int exception = 0;
- RefPtr<ProcessingInstruction> pi = document()->createProcessingInstruction(
- m_stream.processingInstructionTarget(),
- m_stream.processingInstructionData(), exception);
- if (exception)
- return;
-
- pi->setCreatedByParser(true);
-
- m_currentNode->parserAppendChild(pi.get());
- if (m_view && !pi->attached())
- pi->attach();
-
- pi->finishParsingChildren();
-
- if (pi->isCSS())
- m_sawCSS = true;
-#if ENABLE(XSLT)
- m_sawXSLTransform = !m_sawFirstElement && pi->isXSL();
- if (m_sawXSLTransform && !document()->transformSourceDocument())
- stopParsing();
-#endif
-}
-
-void XMLDocumentParser::parseCdata()
-{
- exitText();
-
- RefPtr<CDATASection> newNode = CDATASection::create(document(), m_stream.text());
-
- m_currentNode->parserAppendChild(newNode.get());
- if (m_view && !newNode->attached())
- newNode->attach();
-}
-
-void XMLDocumentParser::parseComment()
-{
- exitText();
-
- RefPtr<Comment> newNode = Comment::create(document(), m_stream.text());
-
- m_currentNode->parserAppendChild(newNode.get());
- if (m_view && !newNode->attached())
- newNode->attach();
-}
-
-void XMLDocumentParser::endDocument()
-{
-}
-
-bool XMLDocumentParser::hasError() const
-{
- return m_stream.hasError();
-}
-
-void XMLDocumentParser::parseDtd()
-{
- QStringRef name = m_stream.dtdName();
- QStringRef publicId = m_stream.dtdPublicId();
- QStringRef systemId = m_stream.dtdSystemId();
-
- //qDebug() << dtd << name << publicId << systemId;
- if ((publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Transitional//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Strict//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Frameset//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML Basic 1.0//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"))
- || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"))
- || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.0//EN"))
- || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.1//EN"))
- || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.2//EN"))
- )
- setIsXHTMLDocument(true); // controls if we replace entities or not.
- if (!m_parsingFragment)
- document()->parserAppendChild(DocumentType::create(document(), name, publicId, systemId));
-
-}
-}
diff --git a/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp b/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp
index 0a473ed23..c0f3590bf 100644
--- a/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp
+++ b/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp
@@ -28,7 +28,7 @@
namespace WebCore {
-CachedResourceLoader* XMLDocumentParserScope::currentCachedResourceLoader = 0;
+CachedResourceLoader* XMLDocumentParserScope::currentCachedResourceLoader = nullptr;
XMLDocumentParserScope::XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader)
: m_oldCachedResourceLoader(currentCachedResourceLoader)
diff --git a/Source/WebCore/xml/parser/XMLDocumentParserScope.h b/Source/WebCore/xml/parser/XMLDocumentParserScope.h
index c04043b48..82eabbfbb 100644
--- a/Source/WebCore/xml/parser/XMLDocumentParserScope.h
+++ b/Source/WebCore/xml/parser/XMLDocumentParserScope.h
@@ -39,13 +39,13 @@ namespace WebCore {
class XMLDocumentParserScope {
WTF_MAKE_NONCOPYABLE(XMLDocumentParserScope);
public:
- XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader);
+ explicit XMLDocumentParserScope(CachedResourceLoader*);
~XMLDocumentParserScope();
static CachedResourceLoader* currentCachedResourceLoader;
#if ENABLE(XSLT)
- XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader, xmlGenericErrorFunc genericErrorFunc, xmlStructuredErrorFunc structuredErrorFunc = 0, void* errorContext = 0);
+ XMLDocumentParserScope(CachedResourceLoader*, xmlGenericErrorFunc, xmlStructuredErrorFunc structuredErrorFunc = 0, void* errorContext = nullptr);
#endif
private: