diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/xml | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/xml')
84 files changed, 4586 insertions, 2570 deletions
diff --git a/Source/WebCore/xml/DOMParser.cpp b/Source/WebCore/xml/DOMParser.cpp index 3e20d97eb..2f941e9d2 100644 --- a/Source/WebCore/xml/DOMParser.cpp +++ b/Source/WebCore/xml/DOMParser.cpp @@ -21,24 +21,33 @@ #include "DOMImplementation.h" #include "ExceptionCode.h" -#include <wtf/text/WTFString.h> +#include "SecurityOriginPolicy.h" namespace WebCore { -PassRefPtr<Document> DOMParser::parseFromString(const String& str, const String& contentType, ExceptionCode& ec) +inline DOMParser::DOMParser(Document& contextDocument) + : m_contextDocument(contextDocument.createWeakPtr()) { - if (contentType != "text/html" - && contentType != "text/xml" - && contentType != "application/xml" - && contentType != "application/xhtml+xml" - && contentType != "image/svg+xml") { - ec = TypeError; - return 0; - } +} - RefPtr<Document> doc = DOMImplementation::createDocument(contentType, 0, URL(), false); - doc->setContent(str); - return doc.release(); +Ref<DOMParser> DOMParser::create(Document& contextDocument) +{ + return adoptRef(*new DOMParser(contextDocument)); +} + +ExceptionOr<Ref<Document>> DOMParser::parseFromString(const String& string, const String& contentType) +{ + if (contentType != "text/html" && contentType != "text/xml" && contentType != "application/xml" && contentType != "application/xhtml+xml" && contentType != "image/svg+xml") + return Exception { TypeError }; + auto document = DOMImplementation::createDocument(contentType, nullptr, URL { }); + if (m_contextDocument) + document->setContextDocument(*m_contextDocument.get()); + document->setContent(string); + if (m_contextDocument) { + document->setURL(m_contextDocument->url()); + document->setSecurityOriginPolicy(m_contextDocument->securityOriginPolicy()); + } + return WTFMove(document); } } // namespace WebCore diff --git a/Source/WebCore/xml/DOMParser.h b/Source/WebCore/xml/DOMParser.h index 91ed18427..42ceeb9fa 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. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,28 +16,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef DOMParser_h -#define DOMParser_h +#pragma once -#include <wtf/Forward.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> +#include "ExceptionOr.h" +#include <wtf/WeakPtr.h> namespace WebCore { -typedef int ExceptionCode; class Document; class DOMParser : public RefCounted<DOMParser> { public: - static PassRefPtr<DOMParser> create() { return adoptRef(new DOMParser); } - - PassRefPtr<Document> parseFromString(const String&, const String& contentType, ExceptionCode&); + static Ref<DOMParser> create(Document& contextDocument); + ExceptionOr<Ref<Document>> parseFromString(const String&, const String& contentType); private: - DOMParser() { } + explicit DOMParser(Document& contextDocument); + + WeakPtr<Document> m_contextDocument; }; } - -#endif // XMLSerializer.h diff --git a/Source/WebCore/xml/DOMParser.idl b/Source/WebCore/xml/DOMParser.idl index 4d4c6b160..964e4ad73 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. 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 @@ -19,8 +19,8 @@ [ Constructor, + ConstructorCallWith=Document, ImplementationLacksVTable, ] interface DOMParser { - [RaisesException] Document parseFromString([Default=Undefined] optional DOMString str, - [Default=Undefined] optional DOMString contentType); + [MayThrowException, NewObject] Document parseFromString(DOMString string, DOMString contentType); }; diff --git a/Source/WebCore/xml/NativeXPathNSResolver.cpp b/Source/WebCore/xml/NativeXPathNSResolver.cpp index 54b0d4c46..aba7435ed 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)) { } @@ -48,7 +48,7 @@ String NativeXPathNSResolver::lookupNamespaceURI(const String& prefix) if (prefix == "xml") return XMLNames::xmlNamespaceURI; - return m_node ? m_node->lookupNamespaceURI(prefix) : String(); + return m_node ? m_node->lookupNamespaceURI(prefix).string() : String(); } } // namespace WebCore diff --git a/Source/WebCore/xml/NativeXPathNSResolver.h b/Source/WebCore/xml/NativeXPathNSResolver.h index f71ad9364..0264207c8 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 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NativeXPathNSResolver_h -#define NativeXPathNSResolver_h +#pragma once #include "XPathNSResolver.h" #include <wtf/RefPtr.h> @@ -35,16 +34,14 @@ 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); + String lookupNamespaceURI(const String& prefix) override; private: - explicit NativeXPathNSResolver(PassRefPtr<Node>); + explicit NativeXPathNSResolver(RefPtr<Node>&&); RefPtr<Node> m_node; }; } // namespace WebCore - -#endif // NativeXPathNSResolver_h diff --git a/Source/WebCore/xml/XMLErrors.cpp b/Source/WebCore/xml/XMLErrors.cpp index 6adfded72..d967f13ac 100644 --- a/Source/WebCore/xml/XMLErrors.cpp +++ b/Source/WebCore/xml/XMLErrors.cpp @@ -30,15 +30,17 @@ #include "XMLErrors.h" #include "Document.h" -#include "Element.h" #include "Frame.h" +#include "HTMLBodyElement.h" +#include "HTMLDivElement.h" +#include "HTMLHeadElement.h" +#include "HTMLHeadingElement.h" +#include "HTMLHtmlElement.h" #include "HTMLNames.h" -#include "Text.h" -#include <wtf/text/WTFString.h> - -#if ENABLE(SVG) +#include "HTMLParagraphElement.h" +#include "HTMLStyleElement.h" #include "SVGNames.h" -#endif +#include "Text.h" namespace WebCore { @@ -46,10 +48,8 @@ using namespace HTMLNames; const int maxErrors = 25; -XMLErrors::XMLErrors(Document* document) +XMLErrors::XMLErrors(Document& document) : m_document(document) - , m_errorCount(0) - , m_lastErrorPosition(TextPosition::belowRangePosition()) { } @@ -60,7 +60,7 @@ void XMLErrors::handleError(ErrorType type, const char* message, int lineNumber, void XMLErrors::handleError(ErrorType type, const char* message, TextPosition position) { - if (type == fatal || (m_errorCount < maxErrors && m_lastErrorPosition.m_line != position.m_line && m_lastErrorPosition.m_column != position.m_column)) { + if (type == fatal || (m_errorCount < maxErrors && (!m_lastErrorPosition || (m_lastErrorPosition->m_line != position.m_line && m_lastErrorPosition->m_column != position.m_column)))) { switch (type) { case warning: appendErrorMessage("warning", position, message); @@ -87,31 +87,31 @@ 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& document, const String& errorMessages) { - RefPtr<Element> reportElement = doc->createElement(QualifiedName(nullAtom, "parsererror", xhtmlNamespaceURI), true); + Ref<Element> reportElement = document.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()); - h3->parserAppendChild(doc->createTextNode("This page contains the following errors:")); + auto h3 = HTMLHeadingElement::create(h3Tag, document); + reportElement->parserAppendChild(h3); + h3->parserAppendChild(Text::create(document, ASCIILiteral("This page contains the following errors:"))); - RefPtr<Element> fixed = doc->createElement(divTag, true); + auto fixed = HTMLDivElement::create(document); Vector<Attribute> fixedAttributes; fixedAttributes.append(Attribute(styleAttr, "font-family:monospace;font-size:12px")); fixed->parserSetAttributes(fixedAttributes); - reportElement->parserAppendChild(fixed.get()); + reportElement->parserAppendChild(fixed); - fixed->parserAppendChild(doc->createTextNode(errorMessages)); + fixed->parserAppendChild(Text::create(document, errorMessages)); - h3 = doc->createElement(h3Tag, true); - reportElement->parserAppendChild(h3.get()); - h3->parserAppendChild(doc->createTextNode("Below is a rendering of the page up to the first error.")); + h3 = HTMLHeadingElement::create(h3Tag, document); + reportElement->parserAppendChild(h3); + h3->parserAppendChild(Text::create(document, ASCIILiteral("Below is a rendering of the page up to the first error."))); - return reportElement.release(); + return reportElement; } void XMLErrors::insertErrorMessageBlock() @@ -121,50 +121,54 @@ void XMLErrors::insertErrorMessageBlock() // where the errors are located) // Create elements for display - RefPtr<Element> documentElement = m_document->documentElement(); + RefPtr<Element> documentElement = m_document.documentElement(); if (!documentElement) { - RefPtr<Element> rootElement = m_document->createElement(htmlTag, true); - RefPtr<Element> body = m_document->createElement(bodyTag, true); + auto rootElement = HTMLHtmlElement::create(m_document); + auto body = HTMLBodyElement::create(m_document); rootElement->parserAppendChild(body); - m_document->parserAppendChild(rootElement); - documentElement = body.get(); - } -#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); + m_document.parserAppendChild(rootElement); + documentElement = WTFMove(body); + } else if (documentElement->namespaceURI() == SVGNames::svgNamespaceURI) { + auto rootElement = HTMLHtmlElement::create(m_document); + auto head = HTMLHeadElement::create(m_document); + auto style = HTMLStyleElement::create(m_document); + head->parserAppendChild(style); + style->parserAppendChild(m_document.createTextNode(ASCIILiteral("html, body { height: 100% } parsererror + svg { width: 100%; height: 100% }"))); + style->finishParsingChildren(); + rootElement->parserAppendChild(head); + auto body = HTMLBodyElement::create(m_document); rootElement->parserAppendChild(body); - documentElement->parentNode()->parserRemoveChild(*documentElement); + m_document.parserRemoveChild(*documentElement); + if (!documentElement->parentNode()) + body->parserAppendChild(*documentElement); - body->parserAppendChild(documentElement); - m_document->parserAppendChild(rootElement.get()); + m_document.parserAppendChild(rootElement); - documentElement = body.get(); + 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()) { + if (m_document.transformSourceDocument()) { Vector<Attribute> attributes; attributes.append(Attribute(styleAttr, "white-space: normal")); - RefPtr<Element> paragraph = m_document->createElement(pTag, true); + auto paragraph = HTMLParagraphElement::create(m_document); 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()); + paragraph->parserAppendChild(m_document.createTextNode(ASCIILiteral("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); } #endif Node* firstChild = documentElement->firstChild(); if (firstChild) - documentElement->parserInsertBefore(reportElement, documentElement->firstChild()); + documentElement->parserInsertBefore(reportElement, *firstChild); else documentElement->parserAppendChild(reportElement); - m_document->updateStyleIfNeeded(); + m_document.updateStyleIfNeeded(); } } // namespace WebCore diff --git a/Source/WebCore/xml/XMLErrors.h b/Source/WebCore/xml/XMLErrors.h index 0032e8426..617ceb02b 100644 --- a/Source/WebCore/xml/XMLErrors.h +++ b/Source/WebCore/xml/XMLErrors.h @@ -26,23 +26,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLErrors_h -#define XMLErrors_h +#pragma once +#include <libxml/parser.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/TextPosition.h> -#include <libxml/parser.h> - namespace WebCore { class Document; class XMLErrors { public: - explicit XMLErrors(Document*); + explicit XMLErrors(Document&); - // Exposed for callbacks: enum ErrorType { warning, nonFatal, fatal }; void handleError(ErrorType, const char* message, int lineNumber, int columnNumber); void handleError(ErrorType, const char* message, TextPosition); @@ -52,13 +49,10 @@ public: private: void appendErrorMessage(const String& typeString, TextPosition, const char* message); - Document* m_document; - - int m_errorCount; - TextPosition m_lastErrorPosition; + Document& m_document; + int m_errorCount { 0 }; + std::optional<TextPosition> m_lastErrorPosition; StringBuilder m_errorMessages; }; } // namespace WebCore - -#endif // XMLErrors_h diff --git a/Source/WebCore/xml/XMLHttpRequest.cpp b/Source/WebCore/xml/XMLHttpRequest.cpp index 41ce508da..8ab3557e8 100644 --- a/Source/WebCore/xml/XMLHttpRequest.cpp +++ b/Source/WebCore/xml/XMLHttpRequest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004-2016 Apple Inc. All rights reserved. * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> * Copyright (C) 2008, 2011 Google Inc. All rights reserved. @@ -24,51 +24,46 @@ #include "XMLHttpRequest.h" #include "Blob.h" -#include "BlobData.h" +#include "CachedResourceRequestInitiators.h" #include "ContentSecurityPolicy.h" #include "CrossOriginAccessControl.h" #include "DOMFormData.h" -#include "DOMImplementation.h" #include "Event.h" -#include "EventException.h" +#include "EventNames.h" #include "ExceptionCode.h" #include "File.h" #include "HTMLDocument.h" +#include "HTTPHeaderNames.h" +#include "HTTPHeaderValues.h" #include "HTTPParsers.h" -#include "HistogramSupport.h" #include "InspectorInstrumentation.h" #include "JSDOMBinding.h" #include "JSDOMWindow.h" +#include "MIMETypeRegistry.h" #include "MemoryCache.h" #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 "XMLDocument.h" #include "XMLHttpRequestProgressEvent.h" #include "XMLHttpRequestUpload.h" #include "markup.h" -#include <heap/Strong.h> +#include <interpreter/StackVisitor.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/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")); @@ -80,64 +75,9 @@ enum XMLHttpRequestSendArrayBufferOrView { XMLHttpRequestSendArrayBufferOrViewMax, }; -struct XMLHttpRequestStaticData { - WTF_MAKE_NONCOPYABLE(XMLHttpRequestStaticData); WTF_MAKE_FAST_ALLOCATED; -public: - XMLHttpRequestStaticData(); - const String m_proxyHeaderPrefix; - const String m_secHeaderPrefix; - const HashSet<String, CaseFoldingHash> m_forbiddenRequestHeaders; -}; - -XMLHttpRequestStaticData::XMLHttpRequestStaticData() - : m_proxyHeaderPrefix("proxy-") - , m_secHeaderPrefix("sec-") - , m_forbiddenRequestHeaders({ - "accept-charset", - "accept-encoding", - "access-control-request-headers", - "access-control-request-method", - "connection", - "content-length", - "content-transfer-encoding", - "cookie", - "cookie2", - "date", - "expect", - "host", - "keep-alive", - "origin", - "referer", - "te", - "trailer", - "transfer-encoding", - "upgrade", - "user-agent", - "via", - }) -{ -} - -static const XMLHttpRequestStaticData& staticData() -{ - static std::once_flag onceFlag; - static const XMLHttpRequestStaticData* staticData; - - std::call_once(onceFlag, [] { - staticData = std::make_unique<XMLHttpRequestStaticData>().release(); - }); - - return *staticData; -} - -static bool isSetCookieHeader(const AtomicString& name) -{ - return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2"); -} - static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue) { - unsigned int pos = 0, len = 0; + unsigned pos = 0, len = 0; findCharsetInMediaType(mediaType, pos, len); @@ -149,7 +89,7 @@ static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa // Found at least one existing charset, replace all occurrences with new charset. while (len) { mediaType.replace(pos, len, charsetValue); - unsigned int start = pos + charsetValue.length(); + unsigned start = pos + charsetValue.length(); findCharsetInMediaType(mediaType, pos, len, start); } } @@ -160,37 +100,22 @@ static void logConsoleError(ScriptExecutionContext* context, const String& messa 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))); + auto xmlHttpRequest = adoptRef(*new XMLHttpRequest(context)); xmlHttpRequest->suspendIfNeeded(); - - return xmlHttpRequest.release(); + return xmlHttpRequest; } 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) - , m_uploadEventsAllowed(true) - , m_uploadComplete(false) - , 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_networkErrorTimer(*this, &XMLHttpRequest::networkErrorTimerFired) + , m_timeoutTimer(*this, &XMLHttpRequest::didReachTimeout) { #ifndef NDEBUG xmlHttpRequestCounter.increment(); @@ -206,8 +131,8 @@ XMLHttpRequest::~XMLHttpRequest() Document* XMLHttpRequest::document() const { - ASSERT_WITH_SECURITY_IMPLICATION(scriptExecutionContext()->isDocument()); - return static_cast<Document*>(scriptExecutionContext()); + ASSERT(scriptExecutionContext()); + return downcast<Document>(scriptExecutionContext()); } SecurityOrigin* XMLHttpRequest::securityOrigin() const @@ -216,13 +141,14 @@ SecurityOrigin* XMLHttpRequest::securityOrigin() const } #if ENABLE(DASHBOARD_SUPPORT) + bool XMLHttpRequest::usesDashboardBackwardCompatibilityMode() const { if (scriptExecutionContext()->isWorkerGlobalScope()) return false; - Settings* settings = document()->settings(); - return settings && settings->usesDashboardBackwardCompatibilityMode(); + return document()->settings().usesDashboardBackwardCompatibilityMode(); } + #endif XMLHttpRequest::State XMLHttpRequest::readyState() const @@ -230,51 +156,51 @@ XMLHttpRequest::State XMLHttpRequest::readyState() const return m_state; } -String XMLHttpRequest::responseText(ExceptionCode& ec) +ExceptionOr<String> XMLHttpRequest::responseText() { - if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeText) { - ec = INVALID_STATE_ERR; - return ""; - } + if (m_responseType != ResponseType::EmptyString && m_responseType != ResponseType::Text) + return Exception { INVALID_STATE_ERR }; return responseTextIgnoringResponseType(); } -void XMLHttpRequest::didCacheResponseJSON() +void XMLHttpRequest::didCacheResponse() { - ASSERT(m_responseTypeCode == ResponseTypeJSON && doneWithoutErrors()); + ASSERT(doneWithoutErrors()); m_responseCacheIsValid = true; m_responseBuilder.clear(); } -Document* XMLHttpRequest::responseXML(ExceptionCode& ec) +ExceptionOr<Document*> XMLHttpRequest::responseXML() { - if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) { - ec = INVALID_STATE_ERR; - return 0; - } + if (m_responseType != ResponseType::EmptyString && m_responseType != ResponseType::Document) + return Exception { INVALID_STATE_ERR }; if (!doneWithoutErrors()) - return 0; + 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) + || (isHTML && m_responseType == ResponseType::EmptyString) || 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->setContextDocument(downcast<Document>(*scriptExecutionContext())); + m_responseDocument->setSecurityOriginPolicy(scriptExecutionContext()->securityOriginPolicy()); + m_responseDocument->overrideMIMEType(mimeType); + if (!m_responseDocument->wellFormed()) - m_responseDocument = 0; + m_responseDocument = nullptr; } m_createdDocument = true; } @@ -282,78 +208,52 @@ Document* XMLHttpRequest::responseXML(ExceptionCode& ec) return m_responseDocument.get(); } -Blob* XMLHttpRequest::responseBlob() +Ref<Blob> XMLHttpRequest::createResponseBlob() { - ASSERT(m_responseTypeCode == ResponseTypeBlob); + ASSERT(m_responseType == ResponseType::Blob); + ASSERT(doneWithoutErrors()); - // We always return null before DONE. - if (m_state != DONE) - return 0; - - 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. - auto blobData = std::make_unique<BlobData>(); - // 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(); - } - m_responseBlob = Blob::create(std::move(blobData), size); - } + if (!m_binaryResponseBuilder) + return Blob::create(); - return m_responseBlob.get(); + // 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()); + m_binaryResponseBuilder = nullptr; + String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. + return Blob::create(WTFMove(data), normalizedContentType); } -ArrayBuffer* XMLHttpRequest::responseArrayBuffer() +RefPtr<ArrayBuffer> XMLHttpRequest::createResponseArrayBuffer() { - ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); - - if (m_state != DONE) - return 0; - - if (!m_responseArrayBuffer) { - if (m_binaryResponseBuilder) - m_responseArrayBuffer = ArrayBuffer::create(const_cast<char*>(m_binaryResponseBuilder->data()), static_cast<unsigned>(m_binaryResponseBuilder->size())); - else - m_responseArrayBuffer = ArrayBuffer::create(nullptr, 0); - m_binaryResponseBuilder.clear(); - } + ASSERT(m_responseType == ResponseType::Arraybuffer); + ASSERT(doneWithoutErrors()); - return m_responseArrayBuffer.get(); + auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder->createArrayBuffer() : ArrayBuffer::create(nullptr, 0); + m_binaryResponseBuilder = nullptr; + return result; } -#if ENABLE(XHR_TIMEOUT) -void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::setTimeout(unsigned timeout) { - // 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; + return Exception { INVALID_ACCESS_ERR }; } m_timeoutMilliseconds = timeout; + if (!m_timeoutTimer.isActive()) + return { }; + + // If timeout is zero, we should use the default network timeout. But we disabled it so let's mimic it with a 60 seconds timeout value. + std::chrono::duration<double> interval = std::chrono::milliseconds { m_timeoutMilliseconds ? m_timeoutMilliseconds : 60000 } - (std::chrono::steady_clock::now() - m_sendingTime); + m_timeoutTimer.startOneShot(std::max(0.0, interval.count())); + return { }; } -#endif -void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::setResponseType(ResponseType type) { - if (m_state >= LOADING) { - ec = INVALID_STATE_ERR; - return; - } + if (m_state >= LOADING) + return Exception { INVALID_STATE_ERR }; // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated // attempt to discourage synchronous XHR use. responseType is one such piece of functionality. @@ -361,43 +261,19 @@ void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode& // such as file: and data: still make sense to allow. if (!m_async && scriptExecutionContext()->isDocument() && m_url.protocolIsInHTTPFamily()) { logConsoleError(scriptExecutionContext(), "XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context."); - ec = INVALID_ACCESS_ERR; - return; + return Exception { INVALID_ACCESS_ERR }; } - if (responseType == "") - 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") - m_responseTypeCode = ResponseTypeBlob; - else if (responseType == "arraybuffer") - m_responseTypeCode = ResponseTypeArrayBuffer; - else - ASSERT_NOT_REACHED(); -} - -String XMLHttpRequest::responseType() -{ - switch (m_responseTypeCode) { - case ResponseTypeDefault: - return ""; - case ResponseTypeText: - return "text"; - case ResponseTypeJSON: - return "json"; - case ResponseTypeDocument: - return "document"; - case ResponseTypeBlob: - return "blob"; - case ResponseTypeArrayBuffer: - return "arraybuffer"; - } - return ""; + m_responseType = type; + return { }; +} + +String XMLHttpRequest::responseURL() const +{ + URL responseURL(m_response.url()); + responseURL.removeFragmentIdentifier(); + + return responseURL.string(); } void XMLHttpRequest::setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber) @@ -426,70 +302,113 @@ 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(Event::create(eventNames().readystatechangeEvent, false, false), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent); - InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie); - if (m_state == DONE && !m_error) { - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(scriptExecutionContext(), this); + if (shouldSendLoadEvent) { m_progressEventThrottle.dispatchProgressEvent(eventNames().loadEvent); - InspectorInstrumentation::didDispatchXHRLoadEvent(cookie); m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent); } } -void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::setWithCredentials(bool value) { - if (m_state > OPENED || m_loader) { - ec = INVALID_STATE_ERR; - return; - } + if (m_state > OPENED || m_sendFlag) + return Exception { INVALID_STATE_ERR }; m_includeCredentials = value; + return { }; } 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) { - const char* const methods[] = { "COPY", "DELETE", "GET", "HEAD", "INDEX", "LOCK", "M-POST", "MKCOL", "MOVE", "OPTIONS", "POST", "PROPFIND", "PROPPATCH", "PUT", "UNLOCK" }; - for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) { - if (equalIgnoringCase(method, methods[i])) { + 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 == methods[i]) + if (method == value) break; - return ASCIILiteral(methods[i]); + 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) { - 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 URL& url, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::open(const String& method, const String& url) { - open(method, url, true, ec); + // If the async argument is omitted, set async to true. + return open(method, scriptExecutionContext()->completeURL(url), true); } -void XMLHttpRequest::open(const String& method, const URL& url, bool async, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::open(const String& method, const URL& url, bool async) { if (!internalAbort()) - return; + return { }; State previousState = m_state; m_state = UNSENT; m_error = false; + m_sendFlag = false; m_uploadComplete = false; // clear stuff from possible previous load @@ -498,59 +417,33 @@ void XMLHttpRequest::open(const String& method, const URL& url, bool async, Exce ASSERT(m_state == UNSENT); - if (!isValidHTTPToken(method)) { - ec = SYNTAX_ERR; - return; - } + if (!isValidHTTPToken(method)) + return Exception { SYNTAX_ERR }; - if (!isAllowedHTTPMethod(method)) { - ec = SECURITY_ERR; - return; - } - - // 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)) { - // FIXME: Should this be throwing an exception? - ec = SECURITY_ERR; - return; - } + if (!isAllowedHTTPMethod(method)) + return Exception { SECURITY_ERR }; if (!async && scriptExecutionContext()->isDocument()) { - if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) { - logConsoleError(scriptExecutionContext(), "Synchronous XMLHttpRequests are disabled for this page."); - ec = INVALID_ACCESS_ERR; - return; - } - // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated // attempt to discourage synchronous XHR use. responseType is one such piece of functionality. // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols // such as file: and data: still make sense to allow. - if (url.protocolIsInHTTPFamily() && m_responseTypeCode != ResponseTypeDefault) { + if (url.protocolIsInHTTPFamily() && m_responseType != ResponseType::EmptyString) { logConsoleError(scriptExecutionContext(), "Synchronous HTTP(S) requests made from the window context cannot have XMLHttpRequest.responseType set."); - ec = INVALID_ACCESS_ERR; - return; + return Exception { INVALID_ACCESS_ERR }; } -#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; + return Exception { INVALID_ACCESS_ERR }; } -#endif } m_method = uppercaseKnownHTTPMethod(method); m_url = url; + scriptExecutionContext()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(m_url, ContentSecurityPolicy::InsecureRequestType::Load); m_async = async; @@ -562,177 +455,223 @@ void XMLHttpRequest::open(const String& method, const URL& url, bool async, Exce changeState(OPENED); else m_state = OPENED; -} -void XMLHttpRequest::open(const String& method, const URL& url, bool async, const String& user, ExceptionCode& ec) -{ - URL urlWithCredentials(url); - urlWithCredentials.setUser(user); - - open(method, urlWithCredentials, async, ec); + return { }; } -void XMLHttpRequest::open(const String& method, const URL& url, bool async, const String& user, const String& password, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::open(const String& method, const String& url, bool async, const String& user, const String& password) { - URL urlWithCredentials(url); - urlWithCredentials.setUser(user); - urlWithCredentials.setPass(password); + URL urlWithCredentials = scriptExecutionContext()->completeURL(url); + if (!user.isNull()) { + urlWithCredentials.setUser(user); + if (!password.isNull()) + urlWithCredentials.setPass(password); + } - open(method, urlWithCredentials, async, ec); + return open(method, urlWithCredentials, async); } -bool XMLHttpRequest::initSend(ExceptionCode& ec) +std::optional<ExceptionOr<void>> XMLHttpRequest::prepareToSend() { + // A return value other than std::nullopt means we should not try to send, and we should return that value to the caller. + // std::nullopt means we are ready to send and should continue with the send algorithm. + if (!scriptExecutionContext()) - return false; + return ExceptionOr<void> { }; - if (m_state != OPENED || m_loader) { - ec = INVALID_STATE_ERR; - return false; + auto& context = *scriptExecutionContext(); + + if (m_state != OPENED || m_sendFlag) + return ExceptionOr<void> { Exception { INVALID_STATE_ERR } }; + ASSERT(!m_loader); + + // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. + if (!context.shouldBypassMainWorldContentSecurityPolicy() && !context.contentSecurityPolicy()->allowConnectToSource(m_url)) { + if (!m_async) + return ExceptionOr<void> { Exception { NETWORK_ERR } }; + setPendingActivity(this); + m_timeoutTimer.stop(); + m_networkErrorTimer.startOneShot(0); + return ExceptionOr<void> { }; } m_error = false; - return true; + return std::nullopt; } -void XMLHttpRequest::send(ExceptionCode& ec) -{ - send(String(), ec); +namespace { + +// FIXME: This should be abstracted out, so that any IDL function can be passed the line/column/url tuple. + +// FIXME: This should probably use ShadowChicken so that we get the right frame even when it did a tail call. +// https://bugs.webkit.org/show_bug.cgi?id=155688 + +class SendFunctor { +public: + SendFunctor() = default; + + unsigned line() const { return m_line; } + unsigned column() const { return m_column; } + String url() const { return m_url; } + + JSC::StackVisitor::Status operator()(JSC::StackVisitor& visitor) const + { + if (!m_hasSkippedFirstFrame) { + m_hasSkippedFirstFrame = true; + return JSC::StackVisitor::Continue; + } + + unsigned line = 0; + unsigned column = 0; + visitor->computeLineAndColumn(line, column); + m_line = line; + m_column = column; + m_url = visitor->sourceURL(); + return JSC::StackVisitor::Done; + } + +private: + mutable bool m_hasSkippedFirstFrame { false }; + mutable unsigned m_line { 0 }; + mutable unsigned m_column { 0 }; + mutable String m_url; +}; + } -void XMLHttpRequest::send(Document* document, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(JSC::ExecState& state, std::optional<SendTypes>&& sendType) { - ASSERT(document); + InspectorInstrumentation::willSendXMLHttpRequest(scriptExecutionContext(), url()); - if (!initSend(ec)) - return; + ExceptionOr<void> result; + if (!sendType) + result = send(); + else { + result = WTF::switchOn(sendType.value(), + [this] (const RefPtr<Document>& document) -> ExceptionOr<void> { return send(*document); }, + [this] (const RefPtr<Blob>& blob) -> ExceptionOr<void> { return send(*blob); }, + [this] (const RefPtr<JSC::ArrayBufferView>& arrayBufferView) -> ExceptionOr<void> { return send(*arrayBufferView); }, + [this] (const RefPtr<JSC::ArrayBuffer>& arrayBuffer) -> ExceptionOr<void> { return send(*arrayBuffer); }, + [this] (const RefPtr<DOMFormData>& formData) -> ExceptionOr<void> { return send(*formData); }, + [this] (const String& string) -> ExceptionOr<void> { return send(string); } + ); + } + + SendFunctor functor; + state.iterate(functor); + setLastSendLineAndColumnNumber(functor.line(), functor.column()); + setLastSendURL(functor.url()); + + return result; +} + +ExceptionOr<void> XMLHttpRequest::send(Document& document) +{ + if (auto result = prepareToSend()) + return WTFMove(result.value()); 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); - - // FIXME: this should use value of document.inputEncoding to determine the encoding to use. - TextEncoding encoding = UTF8Encoding(); - m_requestEntityBody = FormData::create(encoding.encode(body.deprecatedCharacters(), body.length(), EntitiesForUnencodables)); + m_requestEntityBody = FormData::create(UTF8Encoding().encode(createMarkup(document), EntitiesForUnencodables)); if (m_upload) m_requestEntityBody->setAlwaysStream(true); } - createRequest(ec); + return createRequest(); } -void XMLHttpRequest::send(const String& body, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(const String& body) { - if (!initSend(ec)) - return; + if (auto result = prepareToSend()) + return WTFMove(result.value()); 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, HTTPHeaderValues::textPlainContentType()); } else { replaceCharsetInMediaType(contentType, "UTF-8"); - m_requestHeaders.set("Content-Type", contentType); + m_requestHeaders.set(HTTPHeaderName::ContentType, contentType); } - m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.deprecatedCharacters(), body.length(), EntitiesForUnencodables)); + m_requestEntityBody = FormData::create(UTF8Encoding().encode(body, EntitiesForUnencodables)); if (m_upload) m_requestEntityBody->setAlwaysStream(true); } - createRequest(ec); + return createRequest(); } -void XMLHttpRequest::send(Blob* body, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(Blob& body) { - if (!initSend(ec)) - return; + if (auto result = prepareToSend()) + return WTFMove(result.value()); if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) { - const String& contentType = getRequestHeader("Content-Type"); - if (contentType.isEmpty()) { - const String& blobType = body->type(); + 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); + return createRequest(); } -void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(DOMFormData& body) { - if (!initSend(ec)) - return; + if (auto result = prepareToSend()) + return WTFMove(result.value()); 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 = FormData::createMultiPart(body, body.encoding(), document()); 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); + return createRequest(); } -void XMLHttpRequest::send(ArrayBuffer* body, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(ArrayBuffer& body) { - String consoleMessage("ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead."); - scriptExecutionContext()->addConsoleMessage(JSMessageSource, WarningMessageLevel, consoleMessage); - - HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBuffer, XMLHttpRequestSendArrayBufferOrViewMax); - - sendBytesData(body->data(), body->byteLength(), ec); + ASCIILiteral consoleMessage("ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead."); + scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, consoleMessage); + return sendBytesData(body.data(), body.byteLength()); } -void XMLHttpRequest::send(ArrayBufferView* body, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::send(ArrayBufferView& body) { - HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBufferView, XMLHttpRequestSendArrayBufferOrViewMax); - - sendBytesData(body->baseAddress(), body->byteLength(), ec); + return sendBytesData(body.baseAddress(), body.byteLength()); } -void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::sendBytesData(const void* data, size_t length) { - if (!initSend(ec)) - return; + if (auto result = prepareToSend()) + return WTFMove(result.value()); if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) { m_requestEntityBody = FormData::create(data, length); @@ -740,25 +679,16 @@ void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionCod m_requestEntityBody->setAlwaysStream(true); } - createRequest(ec); -} - -void XMLHttpRequest::sendFromInspector(PassRefPtr<FormData> formData, ExceptionCode& ec) -{ - m_requestEntityBody = formData ? formData->deepCopy() : 0; - createRequest(ec); - m_exceptionCode = ec; + return createRequest(); } -void XMLHttpRequest::createRequest(ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::createRequest() { -#if ENABLE(BLOB) // Only GET request is supported for blob URL. - if (m_url.protocolIs("blob") && m_method != "GET") { - ec = XMLHttpRequestException::NETWORK_ERR; - return; - } -#endif + if (!m_async && m_url.protocolIsBlob() && m_method != "GET") + return Exception { NETWORK_ERR }; + + 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. @@ -779,34 +709,38 @@ 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.setInitiatorIdentifier(scriptExecutionContext()->resourceRequestIdentifier()); request.setHTTPMethod(m_method); - 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.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; - options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; - options.crossOriginRequestPolicy = UseAccessControl; - options.securityOrigin = securityOrigin(); -#if ENABLE(RESOURCE_TIMING) + options.credentials = m_includeCredentials ? FetchOptions::Credentials::Include : FetchOptions::Credentials::SameOrigin; + options.mode = FetchOptions::Mode::Cors; + 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 + options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set; + options.filteringPolicy = ResponseFilteringPolicy::Enable; + + if (m_timeoutMilliseconds) { + if (!m_async) + request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0); + else { + request.setTimeoutInterval(std::numeric_limits<double>::infinity()); + m_sendingTime = std::chrono::steady_clock::now(); + m_timeoutTimer.startOneShot(std::chrono::milliseconds { m_timeoutMilliseconds }); + } + } m_exceptionCode = 0; m_error = false; @@ -815,34 +749,36 @@ 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. + m_loader = ThreadableLoader::create(*scriptExecutionContext(), *this, WTFMove(request), options); + + // Either loader is null or some error was synchronously sent to us. + ASSERT(m_loader || !m_sendFlag); + + // 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. + if (m_loader) setPendingActivity(this); - } } else { InspectorInstrumentation::willLoadXHRSynchronously(scriptExecutionContext()); - ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options); + ThreadableLoader::loadResourceSynchronously(*scriptExecutionContext(), WTFMove(request), *this, options); InspectorInstrumentation::didLoadXHRSynchronously(scriptExecutionContext()); } - if (!m_exceptionCode && m_error) - m_exceptionCode = XMLHttpRequestException::NETWORK_ERR; - ec = m_exceptionCode; + if (m_exceptionCode) + return Exception { m_exceptionCode }; + if (m_error) + return Exception { NETWORK_ERR }; + return { }; } void XMLHttpRequest::abort() { // internalAbort() calls dropProtection(), which may release the last reference. - Ref<XMLHttpRequest> protect(*this); - - bool sendFlag = m_loader; + Ref<XMLHttpRequest> protectedThis(*this); if (!internalAbort()) return; @@ -851,16 +787,13 @@ void XMLHttpRequest::abort() // 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; + dispatchErrorEvents(eventNames().abortEvent); } - - dispatchErrorEvents(eventNames().abortEvent); + m_state = UNSENT; } bool XMLHttpRequest::internalAbort() @@ -870,9 +803,9 @@ bool XMLHttpRequest::internalAbort() // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization. m_receivedLength = 0; - m_decoder = 0; + m_decoder = nullptr; - InspectorInstrumentation::didFailXHRLoading(scriptExecutionContext(), this); + m_timeoutTimer.stop(); if (!m_loader) return true; @@ -880,7 +813,7 @@ bool XMLHttpRequest::internalAbort() // 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(); + auto loader = WTFMove(m_loader); loader->cancel(); // If window.onload callback calls open() and send() on the same xhr, m_loader is now set to a new value. @@ -905,23 +838,22 @@ 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_binaryResponseBuilder = 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); @@ -934,6 +866,12 @@ void XMLHttpRequest::networkError() internalAbort(); } +void XMLHttpRequest::networkErrorTimerFired() +{ + networkError(); + dropProtection(); +} + void XMLHttpRequest::abortError() { genericError(); @@ -948,83 +886,60 @@ 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) +ExceptionOr<void> XMLHttpRequest::overrideMimeType(const String& override) { + if (m_state == LOADING || m_state == DONE) + return Exception { INVALID_STATE_ERR }; + m_mimeTypeOverride = override; + return { }; } -void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& value, ExceptionCode& ec) +ExceptionOr<void> XMLHttpRequest::setRequestHeader(const String& name, const String& value) { - if (m_state != OPENED || m_loader) { + if (m_state != OPENED || m_sendFlag) { #if ENABLE(DASHBOARD_SUPPORT) if (usesDashboardBackwardCompatibilityMode()) - return; + return { }; #endif - - ec = INVALID_STATE_ERR; - return; + return Exception { INVALID_STATE_ERR }; } - if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(value)) { - ec = SYNTAX_ERR; - return; - } + String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value); + if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(normalizedValue)) + return Exception { SYNTAX_ERR }; // A privileged script (e.g. a Dashboard widget) can set any headers. if (!securityOrigin()->canLoadLocalResources() && !isAllowedHTTPHeader(name)) { logConsoleError(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\""); - return; + return { }; } - setRequestHeaderInternal(name, value); -} - -void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value) -{ - 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); + m_requestHeaders.add(name, normalizedValue); + return { }; } String XMLHttpRequest::getAllResponseHeaders() const { if (m_state < HEADERS_RECEIVED || m_error) - return ""; + return emptyString(); 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) { - // 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()) - continue; - - if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key)) - continue; - - stringBuilder.append(it->key); + for (const auto& header : m_response.httpHeaderFields()) { + stringBuilder.append(header.key); stringBuilder.append(':'); stringBuilder.append(' '); - stringBuilder.append(it->value); + stringBuilder.append(header.value); stringBuilder.append('\r'); stringBuilder.append('\n'); } @@ -1032,24 +947,11 @@ String XMLHttpRequest::getAllResponseHeaders() const return stringBuilder.toString(); } -String XMLHttpRequest::getResponseHeader(const AtomicString& name) const +String XMLHttpRequest::getResponseHeader(const String& name) const { if (m_state < HEADERS_RECEIVED || m_error) return String(); - // See comment in getAllResponseHeaders above. - if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) { - logConsoleError(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\""); - return String(); - } - - HTTPHeaderSet accessControlExposeHeaderSet; - parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet); - - if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) { - logConsoleError(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\""); - return String(); - } return m_response.httpHeaderField(name); } @@ -1058,80 +960,72 @@ 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(); + if (mimeType.isEmpty()) + mimeType = ASCIILiteral("text/xml"); } - if (mimeType.isEmpty()) - mimeType = "text/xml"; - return mimeType; } 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 MIMETypeRegistry::isXMLMIMEType(responseMIMEType()); } -int XMLHttpRequest::status(ExceptionCode& ec) const +int XMLHttpRequest::status() const { - if (m_response.httpStatusCode()) - return m_response.httpStatusCode(); - - if (m_state == OPENED) { - // Firefox only raises an exception in this state; we match it. - // Note the case of local file requests, where we have no HTTP response code! Firefox never raises an exception for those, but we match HTTP case for consistency. - ec = INVALID_STATE_ERR; - } + if (m_state == UNSENT || m_state == OPENED || m_error) + return 0; - return 0; + return m_response.httpStatusCode(); } -String XMLHttpRequest::statusText(ExceptionCode& ec) const +String XMLHttpRequest::statusText() const { - if (!m_response.httpStatusText().isNull()) - return m_response.httpStatusText(); - - if (m_state == OPENED) { - // See comments in status() above. - ec = INVALID_STATE_ERR; - } + if (m_state == UNSENT || m_state == OPENED || m_error) + return String(); - return String(); + return m_response.httpStatusText(); } void XMLHttpRequest::didFail(const ResourceError& error) { - // If we are already in an error state, for instance we called abort(), bail out early. if (m_error) return; if (error.isCancellation()) { - m_exceptionCode = XMLHttpRequestException::ABORT_ERR; + 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()); - - m_exceptionCode = XMLHttpRequestException::NETWORK_ERR; - networkError(); -} + if (error.domain() == errorDomainWebKitInternal) { + String message = makeString("XMLHttpRequest cannot load ", error.failingURL().string(), ". ", error.localizedDescription()); + logConsoleError(scriptExecutionContext(), message); + } else if (error.isAccessControl()) { + String message = makeString("XMLHttpRequest cannot load ", error.failingURL().string(), " due to access control checks."); + logConsoleError(scriptExecutionContext(), message); + } -void XMLHttpRequest::didFailRedirectCheck() -{ + // In case didFail is called synchronously on an asynchronous XHR call, let's dispatch network error asynchronously + if (m_async && m_sendFlag && !m_loader) { + m_sendFlag = false; + setPendingActivity(this); + m_timeoutTimer.stop(); + m_networkErrorTimer.startOneShot(0); + return; + } + m_exceptionCode = NETWORK_ERR; networkError(); } @@ -1148,14 +1042,20 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) m_responseBuilder.shrinkToFit(); - InspectorInstrumentation::didFinishXHRLoading(scriptExecutionContext(), this, identifier, m_responseBuilder.toStringPreserveCapacity(), m_url, m_lastSendURL, m_lastSendLineNumber, m_lastSendColumnNumber); + std::optional<String> decodedText; + if (!m_binaryResponseBuilder) + decodedText = m_responseBuilder.toStringPreserveCapacity(); + InspectorInstrumentation::didFinishXHRLoading(scriptExecutionContext(), identifier, decodedText, 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(); @@ -1177,18 +1077,27 @@ void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon } } -void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response) +void XMLHttpRequest::didReceiveResponse(unsigned long, const ResourceResponse& response) { - 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_mimeTypeOverride.isEmpty()) + m_response.setHTTPHeaderField(HTTPHeaderName::ContentType, m_mimeTypeOverride); +} - if (m_responseEncoding.isEmpty()) - m_responseEncoding = response.textEncodingName(); +static inline bool shouldDecodeResponse(XMLHttpRequest::ResponseType type) +{ + switch (type) { + case XMLHttpRequest::ResponseType::EmptyString: + case XMLHttpRequest::ResponseType::Document: + case XMLHttpRequest::ResponseType::Json: + case XMLHttpRequest::ResponseType::Text: + return true; + case XMLHttpRequest::ResponseType::Arraybuffer: + case XMLHttpRequest::ResponseType::Blob: + return false; + } + ASSERT_NOT_REACHED(); + return true; } void XMLHttpRequest::didReceiveData(const char* data, int len) @@ -1199,7 +1108,13 @@ void XMLHttpRequest::didReceiveData(const char* data, int len) if (m_state < HEADERS_RECEIVED) changeState(HEADERS_RECEIVED); - bool useDecoder = shouldDecodeResponse(); + // 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(m_responseType); if (useDecoder && !m_decoder) { if (!m_responseEncoding.isEmpty()) @@ -1209,7 +1124,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"); @@ -1223,7 +1138,7 @@ void XMLHttpRequest::didReceiveData(const char* data, int len) if (useDecoder) m_responseBuilder.append(m_decoder->decode(data, len)); - else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) { + else { // Buffer binary data. if (!m_binaryResponseBuilder) m_binaryResponseBuilder = SharedBuffer::create(); @@ -1263,19 +1178,19 @@ void XMLHttpRequest::dispatchErrorEvents(const AtomicString& type) m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent); } -#if ENABLE(XHR_TIMEOUT) -void XMLHttpRequest::didTimeout() +void XMLHttpRequest::didReachTimeout() { // internalAbort() calls dropProtection(), which may release the last reference. - Ref<XMLHttpRequest> protect(*this); + Ref<XMLHttpRequest> protectedThis(*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; @@ -1287,21 +1202,55 @@ void XMLHttpRequest::didTimeout() dispatchErrorEvents(eventNames().timeoutEvent); } -#endif -bool XMLHttpRequest::canSuspend() const +bool XMLHttpRequest::canSuspendForDocumentSuspension() const +{ + // 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(); +} + +const char* XMLHttpRequest::activeDOMObjectName() const { - return !m_loader; + return "XMLHttpRequest"; } -void XMLHttpRequest::suspend(ReasonForSuspension) +void XMLHttpRequest::suspend(ReasonForSuspension reason) { m_progressEventThrottle.suspend(); + + if (m_resumeTimer.isActive()) { + m_resumeTimer.stop(); + m_dispatchErrorOnResuming = true; + } + + 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); + } } void XMLHttpRequest::resume() { 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); +} + +void XMLHttpRequest::resumeTimerFired() +{ + ASSERT(m_dispatchErrorOnResuming); + m_dispatchErrorOnResuming = false; + dispatchErrorEvents(eventNames().errorEvent); } void XMLHttpRequest::stop() diff --git a/Source/WebCore/xml/XMLHttpRequest.h b/Source/WebCore/xml/XMLHttpRequest.h index 51cd5aa1d..0c61fdbee 100644 --- a/Source/WebCore/xml/XMLHttpRequest.h +++ b/Source/WebCore/xml/XMLHttpRequest.h @@ -19,24 +19,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef XMLHttpRequest_h -#define XMLHttpRequest_h +#pragma once #include "ActiveDOMObject.h" -#include "EventListener.h" -#include "EventNames.h" -#include "EventTarget.h" +#include "ExceptionOr.h" #include "FormData.h" #include "ResourceResponse.h" -#include "ScriptWrappable.h" #include "ThreadableLoaderClient.h" +#include "URL.h" +#include "XMLHttpRequestEventTarget.h" #include "XMLHttpRequestProgressEventThrottle.h" -#include <wtf/text/AtomicStringHash.h> +#include <wtf/Variant.h> #include <wtf/text/StringBuilder.h> namespace JSC { class ArrayBuffer; class ArrayBufferView; +class ExecState; } namespace WebCore { @@ -44,19 +43,18 @@ namespace WebCore { class Blob; class Document; class DOMFormData; -class ResourceRequest; class SecurityOrigin; class SharedBuffer; class TextResourceDecoder; class ThreadableLoader; +class XMLHttpRequestUpload; -class XMLHttpRequest final : public ScriptWrappable, public RefCounted<XMLHttpRequest>, public EventTargetWithInlineData, 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 { UNSENT = 0, OPENED = 1, @@ -64,77 +62,56 @@ public: LOADING = 3, DONE = 4 }; - - enum ResponseTypeCode { - ResponseTypeDefault, - ResponseTypeText, - ResponseTypeJSON, - ResponseTypeDocument, - - // Binary format - ResponseTypeBlob, - ResponseTypeArrayBuffer - }; - static const ResponseTypeCode FirstBinaryResponseType = ResponseTypeBlob; -#if ENABLE(XHR_TIMEOUT) - virtual void didTimeout(); -#endif + virtual void didReachTimeout(); + + EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestEventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); } - virtual EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestEventTargetInterfaceType; } - virtual ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); } + using SendTypes = Variant<RefPtr<Document>, RefPtr<Blob>, RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<DOMFormData>, String>; const URL& url() const { return m_url; } - String statusText(ExceptionCode&) const; - int status(ExceptionCode&) const; + 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 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(JSC::ArrayBuffer*, ExceptionCode&); - void send(JSC::ArrayBufferView*, ExceptionCode&); + ExceptionOr<void> setWithCredentials(bool); + ExceptionOr<void> open(const String& method, const String& url); + ExceptionOr<void> open(const String& method, const URL&, bool async); + ExceptionOr<void> open(const String& method, const String&, bool async, const String& user, const String& password); + ExceptionOr<void> send(JSC::ExecState&, std::optional<SendTypes>&&); void abort(); - void setRequestHeader(const AtomicString& name, const String& value, ExceptionCode&); - void overrideMimeType(const String& override); + ExceptionOr<void> setRequestHeader(const String& name, const String& value); + ExceptionOr<void> overrideMimeType(const String& override); bool doneWithoutErrors() const { return !m_error && m_state == DONE; } String getAllResponseHeaders() const; - String getResponseHeader(const AtomicString& name) const; - String responseText(ExceptionCode&); + String getResponseHeader(const String& name) const; + ExceptionOr<String> responseText(); String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); } - Document* responseXML(ExceptionCode&); + String responseMIMEType() const; + Document* optionalResponseXML() const { return m_responseDocument.get(); } - 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 + ExceptionOr<Document*> responseXML(); - bool responseCacheIsValid() const { return m_responseCacheIsValid; } - void didCacheResponseJSON(); + Ref<Blob> createResponseBlob(); + RefPtr<JSC::ArrayBuffer> createResponseArrayBuffer(); + + unsigned timeout() const { return m_timeoutMilliseconds; } + ExceptionOr<void> setTimeout(unsigned); - void sendFromInspector(PassRefPtr<FormData>, ExceptionCode&); + bool responseCacheIsValid() const { return m_responseCacheIsValid; } + void didCacheResponse(); // Expose HTTP validation methods for other untrusted requests. static bool isAllowedHTTPMethod(const String&); static String uppercaseKnownHTTPMethod(const String&); static bool isAllowedHTTPHeader(const String&); - void setResponseType(const String&, ExceptionCode&); - String responseType(); - ResponseTypeCode responseTypeCode() const { return m_responseTypeCode; } + enum class ResponseType { EmptyString, Arraybuffer, Blob, Document, Json, Text }; + ExceptionOr<void> setResponseType(ResponseType); + ResponseType responseType() const; - // response attribute has custom getter. - JSC::ArrayBuffer* responseArrayBuffer(); - JSC::ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); } + String responseURL() const; void setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber); void setLastSendURL(const String& url) { m_lastSendURL = url; } @@ -142,16 +119,7 @@ public: 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; @@ -160,14 +128,15 @@ private: explicit XMLHttpRequest(ScriptExecutionContext&); // ActiveDOMObject - virtual void contextDestroyed() override; - virtual bool canSuspend() const override; - virtual void suspend(ReasonForSuspension) override; - virtual void resume() override; - virtual void stop() override; + 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(); } + void refEventTarget() override { ref(); } + void derefEventTarget() override { deref(); } Document* document() const; SecurityOrigin* securityOrigin() const; @@ -176,23 +145,25 @@ private: bool usesDashboardBackwardCompatibilityMode() const; #endif - 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; + // ThreadableLoaderClient + void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override; + void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override; + void didReceiveData(const char* data, int dataLength) override; + void didFinishLoading(unsigned long identifier, double finishTime) override; + void didFail(const ResourceError&) override; - String responseMIMEType() const; bool responseIsXML() const; - bool initSend(ExceptionCode&); - void sendBytesData(const void*, size_t, ExceptionCode&); + std::optional<ExceptionOr<void>> prepareToSend(); + ExceptionOr<void> send(Document&); + ExceptionOr<void> send(const String& = { }); + ExceptionOr<void> send(Blob&); + ExceptionOr<void> send(DOMFormData&); + ExceptionOr<void> send(JSC::ArrayBuffer&); + ExceptionOr<void> send(JSC::ArrayBufferView&); + ExceptionOr<void> sendBytesData(const void*, size_t); - String getRequestHeader(const AtomicString& name) const; - void setRequestHeaderInternal(const AtomicString& name, const String& value); - - void changeState(State newState); + void changeState(State); void callReadyStateChangeListener(); void dropProtection(); @@ -204,16 +175,16 @@ private: void clearResponseBuffers(); void clearRequest(); - void createRequest(ExceptionCode&); + ExceptionOr<void> createRequest(); void genericError(); void networkError(); void abortError(); - bool shouldDecodeResponse() const { return m_responseTypeCode < FirstBinaryResponseType; } - void dispatchErrorEvents(const AtomicString&); + void resumeTimerFired(); + std::unique_ptr<XMLHttpRequestUpload> m_upload; URL m_url; @@ -221,15 +192,12 @@ private: 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; + bool m_async { true }; + bool m_includeCredentials { false }; RefPtr<ThreadableLoader> m_loader; - State m_state; + State m_state { UNSENT }; + bool m_sendFlag { false }; ResourceResponse m_response; String m_responseEncoding; @@ -237,34 +205,45 @@ private: RefPtr<TextResourceDecoder> m_decoder; StringBuilder m_responseBuilder; - bool m_createdDocument; + bool m_createdDocument { false }; RefPtr<Document> m_responseDocument; - + RefPtr<SharedBuffer> m_binaryResponseBuilder; - RefPtr<JSC::ArrayBuffer> m_responseArrayBuffer; - bool m_error; + bool m_error { false }; - bool m_uploadEventsAllowed; - bool m_uploadComplete; + bool m_uploadEventsAllowed { true }; + bool m_uploadComplete { false }; - bool m_sameOriginRequest; + bool m_sameOriginRequest { true }; - // Used for onprogress tracking - long long m_receivedLength; + // Used for progress event tracking. + long long m_receivedLength { 0 }; - unsigned m_lastSendLineNumber; - unsigned m_lastSendColumnNumber; + unsigned m_lastSendLineNumber { 0 }; + unsigned m_lastSendColumnNumber { 0 }; String m_lastSendURL; - ExceptionCode m_exceptionCode; + ExceptionCode m_exceptionCode { 0 }; XMLHttpRequestProgressEventThrottle m_progressEventThrottle; - // An enum corresponding to the allowed string values for the responseType attribute. - ResponseTypeCode m_responseTypeCode; - bool m_responseCacheIsValid; + ResponseType m_responseType { ResponseType::EmptyString }; + bool m_responseCacheIsValid { false }; + + Timer m_resumeTimer; + bool m_dispatchErrorOnResuming { false }; + + Timer m_networkErrorTimer; + void networkErrorTimerFired(); + + unsigned m_timeoutMilliseconds { 0 }; + std::chrono::steady_clock::time_point m_sendingTime; + Timer m_timeoutTimer; }; -} // namespace WebCore +inline auto XMLHttpRequest::responseType() const -> ResponseType +{ + return m_responseType; +} -#endif // XMLHttpRequest_h +} // namespace WebCore diff --git a/Source/WebCore/xml/XMLHttpRequest.idl b/Source/WebCore/xml/XMLHttpRequest.idl index ef1a21ae6..5daad5b01 100644 --- a/Source/WebCore/xml/XMLHttpRequest.idl +++ b/Source/WebCore/xml/XMLHttpRequest.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2008-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. * @@ -26,6 +26,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +typedef (ArrayBufferView or ArrayBuffer) BufferSource; +// FIXME: Add URLSearchParams and ReadableStream to the union when supported. +typedef (Blob or BufferSource or DOMFormData or USVString) BodyInit; + enum XMLHttpRequestResponseType { "", "arraybuffer", @@ -36,26 +40,19 @@ enum XMLHttpRequestResponseType { }; [ - GlobalContext=DOMWindow&WorkerGlobalScope, ActiveDOMObject, Constructor, ConstructorCallWith=ScriptExecutionContext, + ExportMacro=WEBCORE_EXPORT, + Exposed=(Window,Worker), 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; + JSGenerateToJSObject, + JSGenerateToNativeObject, + PrivateIdentifier, + PublicIdentifier, +] interface XMLHttpRequest : XMLHttpRequestEventTarget { + // event handler + attribute EventHandler onreadystatechange; // state const unsigned short UNSENT = 0; @@ -63,43 +60,33 @@ enum XMLHttpRequestResponseType { const unsigned short HEADERS_RECEIVED = 2; const unsigned short LOADING = 3; const unsigned short DONE = 4; - - [Conditional=XHR_TIMEOUT, SetterRaisesException] attribute unsigned long timeout; readonly attribute unsigned short readyState; - [SetterRaisesException] attribute boolean withCredentials; - - [Custom, RaisesException] void open(DOMString method, DOMString url, optional boolean async, optional DOMString user, optional DOMString password); - - [RaisesException] void setRequestHeader(DOMString header, DOMString value); - - [Custom, RaisesException] void send(); - - void abort(); - + // request + [MayThrowException] void open(ByteString method, DOMString url); // FIXME: url should be a USVString. + [MayThrowException] void open(ByteString method, DOMString url, boolean async, optional DOMString? user = null, optional DOMString? password = null); // FIXME: url/user/password should all be a USVStrings. + [MayThrowException] void setRequestHeader(ByteString header, ByteString value); + [SetterMayThrowException] attribute unsigned long timeout; + [SetterMayThrowException] attribute boolean withCredentials; readonly attribute XMLHttpRequestUpload upload; + [CallWith=ScriptState, MayThrowException] void send(optional (Document or BodyInit)? body = null); + void abort(); // response - [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, CachedAttribute, CustomGetter] readonly attribute Object response; - - [GetterRaisesException] readonly attribute unsigned short status; - [GetterRaisesException] readonly attribute DOMString statusText; - - // Extension - void overrideMimeType(DOMString override); + readonly attribute USVString responseURL; + readonly attribute unsigned short status; + readonly attribute ByteString statusText; + ByteString? getResponseHeader(ByteString name); + ByteString getAllResponseHeaders(); + [MayThrowException] void overrideMimeType(DOMString mime); + [SetterMayThrowException] attribute XMLHttpRequestResponseType responseType; + [JSBuiltin] readonly attribute any response; + [GetterMayThrowException, CustomGetter] readonly attribute USVString? responseText; + // FIXME: responseXML should be annotated with [Exposed=Window]. + [GetterMayThrowException] readonly attribute Document? responseXML; + + // internals + [PrivateIdentifier] boolean responseCacheIsValid(); + [PrivateIdentifier, Custom] any retrieveResponse(); - // 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); }; diff --git a/Source/WebCore/xml/XMLHttpRequest.js b/Source/WebCore/xml/XMLHttpRequest.js new file mode 100644 index 000000000..6ae546b08 --- /dev/null +++ b/Source/WebCore/xml/XMLHttpRequest.js @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Apple Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +function response() +{ + "use strict"; + + // FIXME: Add a helper routine for that kind of checks. + if (!(this instanceof @XMLHttpRequest)) + @throwTypeError("The XMLHttpRequest.response getter can only be used on instances of XMLHttpRequest"); + + if (@XMLHttpRequest.prototype.@responseCacheIsValid.@call(this)) + return this.@response; + + this.@response = @XMLHttpRequest.prototype.@retrieveResponse.@call(this); + return this.@response; +} diff --git a/Source/WebCore/xml/XMLHttpRequestEventTarget.h b/Source/WebCore/xml/XMLHttpRequestEventTarget.h new file mode 100644 index 000000000..9f3270827 --- /dev/null +++ b/Source/WebCore/xml/XMLHttpRequestEventTarget.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#pragma once + +#include "EventTarget.h" + +namespace WebCore { + +class XMLHttpRequestEventTarget : public EventTargetWithInlineData { +}; + +} // namespace WebCore diff --git a/Source/WebCore/xml/XMLHttpRequestException.idl b/Source/WebCore/xml/XMLHttpRequestEventTarget.idl index 156410157..09ddc7796 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; + Exposed=(Window,Worker), + 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 d3fa0b41e..c0aeddd2d 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 @@ -24,33 +24,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLHttpRequestProgressEvent_h -#define XMLHttpRequestProgressEvent_h +#pragma once -#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 EventInterface eventInterface() const { return XMLHttpRequestProgressEventInterfaceType; } + EventInterface eventInterface() const override { return XMLHttpRequestProgressEventInterfaceType; } private: - XMLHttpRequestProgressEvent() { } XMLHttpRequestProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total) : ProgressEvent(type, lengthComputable, loaded, total) { @@ -58,5 +50,3 @@ private: }; } // namespace WebCore - -#endif // XMLHttpRequestProgressEvent_h 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 615e515bb..36662656b 100644 --- a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp +++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp @@ -27,6 +27,7 @@ #include "config.h" #include "XMLHttpRequestProgressEventThrottle.h" +#include "EventNames.h" #include "EventTarget.h" #include "XMLHttpRequestProgressEvent.h" @@ -41,7 +42,7 @@ XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTa , m_loaded(0) , m_total(0) , m_deferEvents(false) - , m_dispatchDeferredEventsTimer(this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents) + , m_dispatchDeferredEventsTimer(*this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents) { ASSERT(target); } @@ -55,6 +56,9 @@ void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool le 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. @@ -63,8 +67,7 @@ void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool le } 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 throttled progress event. ASSERT(!m_hasThrottledProgressEvent); @@ -79,7 +82,7 @@ void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool le m_hasThrottledProgressEvent = true; } -void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(PassRefPtr<Event> event, ProgressEventAction progressEventAction) +void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(Event& event, ProgressEventAction progressEventAction) { if (progressEventAction == FlushProgressEvent) flushProgressEvent(); @@ -87,11 +90,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; } @@ -100,7 +102,7 @@ void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event) m_target->dispatchEvent(event); } -void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString &type) +void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString& type) { ASSERT(type == eventNames().loadstartEvent || type == eventNames().progressEvent || type == eventNames().loadEvent || type == eventNames().loadendEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent); @@ -110,51 +112,46 @@ void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicStri m_total = 0; } - dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total)); + 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); + 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() diff --git a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h index 33758a94c..781d6ece6 100644 --- a/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h +++ b/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h @@ -24,13 +24,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLHttpRequestProgressEventThrottle_h -#define XMLHttpRequestProgressEventThrottle_h +#pragma once #include "Timer.h" -#include "wtf/PassRefPtr.h" -#include "wtf/Vector.h" #include <wtf/Forward.h> +#include <wtf/Vector.h> namespace WebCore { @@ -50,8 +48,7 @@ public: virtual ~XMLHttpRequestProgressEventThrottle(); void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total); - void dispatchReadyStateChangeEvent(PassRefPtr<Event>, ProgressEventAction = DoNotFlushProgressEvent); - void dispatchEvent(PassRefPtr<Event>); + void dispatchReadyStateChangeEvent(Event&, ProgressEventAction = DoNotFlushProgressEvent); void dispatchProgressEvent(const AtomicString&); void suspend(); @@ -60,9 +57,10 @@ public: private: static const double minimumProgressEventDispatchingIntervalInSeconds; - virtual void fired(); - void dispatchDeferredEvents(Timer<XMLHttpRequestProgressEventThrottle>*); + void fired() override; + void dispatchDeferredEvents(); void flushProgressEvent(); + void dispatchEvent(Event&); bool hasEventToDispatch() const; @@ -76,10 +74,8 @@ private: 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 - -#endif // XMLHttpRequestProgressEventThrottle_h diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.cpp b/Source/WebCore/xml/XMLHttpRequestUpload.cpp index e1f6bebf0..c96809951 100644 --- a/Source/WebCore/xml/XMLHttpRequestUpload.cpp +++ b/Source/WebCore/xml/XMLHttpRequestUpload.cpp @@ -27,7 +27,7 @@ #include "XMLHttpRequestUpload.h" #include "Event.h" -#include "EventException.h" +#include "EventNames.h" #include "XMLHttpRequestProgressEvent.h" #include <wtf/Assertions.h> #include <wtf/text/AtomicString.h> diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.h b/Source/WebCore/xml/XMLHttpRequestUpload.h index 3c15e3b82..3ef2a6698 100644 --- a/Source/WebCore/xml/XMLHttpRequestUpload.h +++ b/Source/WebCore/xml/XMLHttpRequestUpload.h @@ -23,12 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLHttpRequestUpload_h -#define XMLHttpRequestUpload_h +#pragma once #include "XMLHttpRequest.h" #include <wtf/Forward.h> -#include <wtf/HashMap.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -37,7 +35,8 @@ namespace WebCore { class ScriptExecutionContext; class XMLHttpRequest; - class XMLHttpRequestUpload final : public EventTargetWithInlineData { + class XMLHttpRequestUpload final : public XMLHttpRequestEventTarget { + WTF_MAKE_FAST_ALLOCATED; public: explicit XMLHttpRequestUpload(XMLHttpRequest*); @@ -45,22 +44,15 @@ namespace WebCore { void deref() { m_xmlHttpRequest->deref(); } XMLHttpRequest* xmlHttpRequest() const { return m_xmlHttpRequest; } - virtual EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestUploadEventTargetInterfaceType; } - virtual ScriptExecutionContext* scriptExecutionContext() const override { return m_xmlHttpRequest->scriptExecutionContext(); } - - 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); + EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestUploadEventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const override { return m_xmlHttpRequest->scriptExecutionContext(); } void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total); void dispatchProgressEvent(const AtomicString &type); private: - virtual void refEventTarget() override final { ref(); } - virtual void derefEventTarget() override final { deref(); } + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } XMLHttpRequest* m_xmlHttpRequest; bool m_lengthComputable; @@ -69,5 +61,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // XMLHttpRequestUpload_h diff --git a/Source/WebCore/xml/XMLHttpRequestUpload.idl b/Source/WebCore/xml/XMLHttpRequestUpload.idl index 0cee24aad..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 9a9f9a392..cb84bf9bf 100644 --- a/Source/WebCore/xml/XMLSerializer.cpp +++ b/Source/WebCore/xml/XMLSerializer.cpp @@ -20,20 +20,13 @@ #include "config.h" #include "XMLSerializer.h" -#include "Document.h" -#include "ExceptionCode.h" #include "markup.h" -#include <wtf/text/WTFString.h> namespace WebCore { -String XMLSerializer::serializeToString(Node* node, ExceptionCode& ec) +String XMLSerializer::serializeToString(Node& node) { - if (!node) { - ec = TypeError; - return String(); - } - return createMarkup(*node, IncludeNode, 0, DoNotResolveURLs, 0, XMLFragmentSerialization); + return createMarkup(node, IncludeNode, nullptr, DoNotResolveURLs, nullptr, XMLFragmentSerialization); } } // namespace WebCore diff --git a/Source/WebCore/xml/XMLSerializer.h b/Source/WebCore/xml/XMLSerializer.h index 4d255b0e5..02cdfdd88 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 @@ -17,29 +17,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef XMLSerializer_h -#define XMLSerializer_h +#pragma once #include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> #include <wtf/RefCounted.h> namespace WebCore { - typedef int ExceptionCode; +class Node; - class Node; +// FIXME: This object has no state, so it seems a waste to allocate and reference count it. +class XMLSerializer : public RefCounted<XMLSerializer> { +public: + static Ref<XMLSerializer> create() { return adoptRef(*new XMLSerializer); } - class XMLSerializer : public RefCounted<XMLSerializer> { - public: - static PassRefPtr<XMLSerializer> create() { return adoptRef(new XMLSerializer); } - - String serializeToString(Node*, ExceptionCode&); - - private: - XMLSerializer() { } - }; + static String serializeToString(Node&); -} // namespace WebCore +private: + XMLSerializer() = default; +}; -#endif // XMLSerializer_h +} // namespace WebCore diff --git a/Source/WebCore/xml/XMLSerializer.idl b/Source/WebCore/xml/XMLSerializer.idl index 2870595b5..fb4d17c1e 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 @@ -22,6 +22,6 @@ Constructor, ImplementationLacksVTable, ] interface XMLSerializer { - [RaisesException] DOMString serializeToString([Default=Undefined] optional Node node); + DOMString serializeToString(Node node); }; diff --git a/Source/WebCore/xml/XMLTreeViewer.cpp b/Source/WebCore/xml/XMLTreeViewer.cpp index 1a85dc7c2..d641d76cb 100644 --- a/Source/WebCore/xml/XMLTreeViewer.cpp +++ b/Source/WebCore/xml/XMLTreeViewer.cpp @@ -34,15 +34,15 @@ #include "Document.h" #include "Element.h" -#include "ExceptionCodePlaceholder.h" #include "Frame.h" #include "ScriptController.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" +#include "SecurityOriginPolicy.h" +#include "StyleScope.h" #include "Text.h" #include "XMLViewerCSS.h" #include "XMLViewerJS.h" -#include <bindings/ScriptValue.h> namespace WebCore { @@ -53,17 +53,16 @@ XMLTreeViewer::XMLTreeViewer(Document& document) void XMLTreeViewer::transformDocumentToTreeView() { - m_document.setSecurityOrigin(SecurityOrigin::createUnique()); + m_document.setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique())); String scriptString = StringImpl::createWithoutCopying(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.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 = StringImpl::createWithoutCopying(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); + auto text = m_document.createTextNode(cssString); + m_document.getElementById(String(ASCIILiteral("xml-viewer-style")))->appendChild(text); + m_document.styleScope().didChangeActiveStyleSheetCandidates(); } } // namespace WebCore diff --git a/Source/WebCore/xml/XMLTreeViewer.h b/Source/WebCore/xml/XMLTreeViewer.h index 599bc194a..f9d60df0f 100644 --- a/Source/WebCore/xml/XMLTreeViewer.h +++ b/Source/WebCore/xml/XMLTreeViewer.h @@ -27,8 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLTreeViewer_h -#define XMLTreeViewer_h +#pragma once #if ENABLE(XSLT) @@ -49,4 +48,3 @@ private: } // namespace WebCore #endif // ENABLE(XSLT) -#endif // XMLTreeViewer_h diff --git a/Source/WebCore/xml/XMLViewer.css b/Source/WebCore/xml/XMLViewer.css index 851499272..6b35890eb 100644 --- a/Source/WebCore/xml/XMLViewer.css +++ b/Source/WebCore/xml/XMLViewer.css @@ -59,7 +59,7 @@ div.collapsible > div.hidden { } .tag { - /* Keep this in sync with inspector.css (.webkit-html-tag) */ + /* Keep this in sync with inspector.css (.tag-name) */ color: rgb(136, 18, 128); } diff --git a/Source/WebCore/xml/XPathEvaluator.cpp b/Source/WebCore/xml/XPathEvaluator.cpp index b405ff1c6..3aa141b27 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 @@ -37,36 +37,26 @@ namespace WebCore { using namespace XPath; -PassRefPtr<XPathExpression> XPathEvaluator::createExpression(const String& expression, - XPathNSResolver* resolver, - ExceptionCode& ec) +ExceptionOr<Ref<XPathExpression>> XPathEvaluator::createExpression(const String& expression, RefPtr<XPathNSResolver>&& resolver) { - return XPathExpression::createExpression(expression, resolver, ec); + return XPathExpression::createExpression(expression, WTFMove(resolver)); } -PassRefPtr<XPathNSResolver> XPathEvaluator::createNSResolver(Node* nodeResolver) +Ref<XPathNSResolver> XPathEvaluator::createNSResolver(Node* nodeResolver) { return NativeXPathNSResolver::create(nodeResolver); } -PassRefPtr<XPathResult> XPathEvaluator::evaluate(const String& expression, - Node* contextNode, - XPathNSResolver* resolver, - unsigned short type, - XPathResult* result, - ExceptionCode& ec) +ExceptionOr<Ref<XPathResult>> XPathEvaluator::evaluate(const String& expression, Node* contextNode, RefPtr<XPathNSResolver>&& resolver, unsigned short type, XPathResult* result) { - if (!isValidContextNode(contextNode)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!isValidContextNode(contextNode)) + return Exception { NOT_SUPPORTED_ERR }; - ec = 0; - RefPtr<XPathExpression> expr = createExpression(expression, resolver, ec); - if (ec) - return 0; - - return expr->evaluate(contextNode, type, result, ec); + auto createResult = createExpression(expression, WTFMove(resolver)); + if (createResult.hasException()) + return createResult.releaseException(); + + return createResult.releaseReturnValue()->evaluate(contextNode, type, result); } } diff --git a/Source/WebCore/xml/XPathEvaluator.h b/Source/WebCore/xml/XPathEvaluator.h index ca35f2101..4a478548f 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. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,35 +24,27 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathEvaluator_h -#define XPathEvaluator_h +#pragma once -#include <wtf/Forward.h> -#include <wtf/RefCounted.h> -#include <wtf/PassRefPtr.h> +#include "ExceptionOr.h" namespace WebCore { - typedef int ExceptionCode; +class Node; +class XPathExpression; +class XPathNSResolver; +class XPathResult; - class Node; - class XPathExpression; - class XPathNSResolver; - class XPathResult; +class XPathEvaluator : public RefCounted<XPathEvaluator> { +public: + static Ref<XPathEvaluator> create() { return adoptRef(*new XPathEvaluator); } - class XPathEvaluator : public RefCounted<XPathEvaluator> { - public: - static PassRefPtr<XPathEvaluator> create() { return adoptRef(new XPathEvaluator); } - - PassRefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&); - PassRefPtr<XPathNSResolver> createNSResolver(Node* nodeResolver); - PassRefPtr<XPathResult> evaluate(const String& expression, Node* contextNode, - XPathNSResolver*, unsigned short type, XPathResult*, ExceptionCode&); + ExceptionOr<Ref<XPathExpression>> createExpression(const String& expression, RefPtr<XPathNSResolver>&&); + Ref<XPathNSResolver> createNSResolver(Node* nodeResolver); + ExceptionOr<Ref<XPathResult>> evaluate(const String& expression, Node* contextNode, RefPtr<XPathNSResolver>&&, unsigned short type, XPathResult*); - private: - XPathEvaluator() { } - }; +private: + XPathEvaluator() = default; +}; } - -#endif // XPathEvaluator_h diff --git a/Source/WebCore/xml/XPathEvaluator.idl b/Source/WebCore/xml/XPathEvaluator.idl index 3a07dbaae..faad6182d 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. 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 @@ -21,14 +21,11 @@ Constructor, ImplementationLacksVTable, ] interface XPathEvaluator { - [RaisesException] XPathExpression createExpression([Default=Undefined] optional DOMString expression, - [Default=Undefined] optional XPathNSResolver resolver); + // FIXME: Using "undefined" as default parameter value is wrong. + [MayThrowException] XPathExpression createExpression(optional DOMString expression = "undefined", optional XPathNSResolver? resolver); - XPathNSResolver createNSResolver([Default=Undefined] optional Node nodeResolver); + XPathNSResolver createNSResolver(optional Node? nodeResolver); - [RaisesException] XPathResult evaluate([Default=Undefined] optional DOMString expression, - [Default=Undefined] optional Node contextNode, - [Default=Undefined] optional XPathNSResolver resolver, - [Default=Undefined] optional unsigned short type, - [Default=Undefined] optional XPathResult inResult); + // FIXME: Using "undefined" as default parameter value is wrong. + [MayThrowException] XPathResult evaluate(optional DOMString expression = "undefined", optional Node? contextNode, optional XPathNSResolver? resolver, optional unsigned short type = 0, optional XPathResult? inResult); }; 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..3855203d7 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. * @@ -26,8 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathException_h -#define XPathException_h +#pragma once #include "ExceptionBase.h" @@ -35,9 +34,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; @@ -58,5 +57,3 @@ private: }; } // namespace WebCore - -#endif // XPathException_h diff --git a/Source/WebCore/xml/XPathException.idl b/Source/WebCore/xml/XPathException.idl index c1db5eed9..4e08fe1f4 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. * @@ -30,15 +30,11 @@ DoNotCheckConstants, ImplementationLacksVTable, ] exception XPathException { + readonly attribute unsigned short code; + readonly attribute DOMString name; + readonly attribute DOMString message; - 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 // XPathExceptionCode const unsigned short INVALID_EXPRESSION_ERR = 51; diff --git a/Source/WebCore/xml/XPathExpression.cpp b/Source/WebCore/xml/XPathExpression.cpp index c659c829a..99aacfde1 100644 --- a/Source/WebCore/xml/XPathExpression.cpp +++ b/Source/WebCore/xml/XPathExpression.cpp @@ -34,60 +34,56 @@ #include "XPathParser.h" #include "XPathResult.h" #include "XPathUtil.h" -#include <wtf/text/WTFString.h> namespace WebCore { using namespace XPath; inline XPathExpression::XPathExpression(std::unique_ptr<XPath::Expression> expression) - : m_topExpression(std::move(expression)) + : m_topExpression(WTFMove(expression)) { } -PassRefPtr<XPathExpression> XPathExpression::createExpression(const String& expression, XPathNSResolver* resolver, ExceptionCode& ec) +ExceptionOr<Ref<XPathExpression>> XPathExpression::createExpression(const String& expression, RefPtr<XPathNSResolver>&& resolver) { - auto parsedExpression = Parser::parseStatement(expression, resolver, ec); - if (!parsedExpression) - return nullptr; + auto parseResult = Parser::parseStatement(expression, WTFMove(resolver)); + if (parseResult.hasException()) + return parseResult.releaseException(); - return adoptRef(new XPathExpression(std::move(parsedExpression))); + return adoptRef(*new XPathExpression(parseResult.releaseReturnValue())); } XPathExpression::~XPathExpression() { } -PassRefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode& ec) +// FIXME: Why does this take an XPathResult that it ignores? +ExceptionOr<Ref<XPathResult>> XPathExpression::evaluate(Node* contextNode, unsigned short type, XPathResult*) { - if (!isValidContextNode(contextNode)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!isValidContextNode(contextNode)) + return Exception { NOT_SUPPORTED_ERR }; EvaluationContext& evaluationContext = Expression::evaluationContext(); evaluationContext.node = contextNode; evaluationContext.size = 1; evaluationContext.position = 1; evaluationContext.hadTypeConversionError = false; - RefPtr<XPathResult> result = XPathResult::create(&contextNode->document(), m_topExpression->evaluate()); + auto 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 nullptr; + return Exception { XPathException::INVALID_EXPRESSION_ERR }; } if (type != XPathResult::ANY_TYPE) { - ec = 0; - result->convertTo(type, ec); - if (ec) - return nullptr; + auto convertToResult = result->convertTo(type); + if (convertToResult.hasException()) + return convertToResult.releaseException(); } - return result; + return WTFMove(result); } } diff --git a/Source/WebCore/xml/XPathExpression.h b/Source/WebCore/xml/XPathExpression.h index 8fd2a3eed..5a478a82e 100644 --- a/Source/WebCore/xml/XPathExpression.h +++ b/Source/WebCore/xml/XPathExpression.h @@ -24,37 +24,31 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathExpression_h -#define XPathExpression_h +#pragma once -#include <wtf/Forward.h> -#include <wtf/RefCounted.h> +#include "ExceptionOr.h" namespace WebCore { - typedef int ExceptionCode; +class Node; +class XPathNSResolver; +class XPathResult; - class Node; - class XPathNSResolver; - class XPathResult; +namespace XPath { +class Expression; +} - namespace XPath { - class Expression; - } +class XPathExpression : public RefCounted<XPathExpression> { +public: + static ExceptionOr<Ref<XPathExpression>> createExpression(const String& expression, RefPtr<XPathNSResolver>&&); + WEBCORE_EXPORT ~XPathExpression(); - class XPathExpression : public RefCounted<XPathExpression> { - public: - static PassRefPtr<XPathExpression> createExpression(const String& expression, XPathNSResolver*, ExceptionCode&); - ~XPathExpression(); - - PassRefPtr<XPathResult> evaluate(Node* contextNode, unsigned short type, XPathResult*, ExceptionCode&); - - private: - explicit XPathExpression(std::unique_ptr<XPath::Expression>); + WEBCORE_EXPORT ExceptionOr<Ref<XPathResult>> evaluate(Node* contextNode, unsigned short type, XPathResult*); - std::unique_ptr<XPath::Expression> m_topExpression; - }; +private: + explicit XPathExpression(std::unique_ptr<XPath::Expression>); -} + std::unique_ptr<XPath::Expression> m_topExpression; +}; -#endif // XPathExpression_h +} diff --git a/Source/WebCore/xml/XPathExpression.idl b/Source/WebCore/xml/XPathExpression.idl index 4707630ea..19758dc23 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. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * This library is free software; you can redistribute it and/or @@ -17,11 +17,10 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + [ + ExportToWrappedFunction, ImplementationLacksVTable, ] interface XPathExpression { - [ObjCLegacyUnnamedParameters, RaisesException] XPathResult evaluate([Default=Undefined] optional Node contextNode, - [Default=Undefined] optional unsigned short type, - [Default=Undefined] optional XPathResult inResult); + [MayThrowException] XPathResult evaluate(optional Node? contextNode = null, optional unsigned short type = 0, optional XPathResult? inResult = null); }; - diff --git a/Source/WebCore/xml/XPathExpressionNode.cpp b/Source/WebCore/xml/XPathExpressionNode.cpp index 05e4d6abb..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, 2013 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 @@ -49,11 +49,11 @@ Expression::Expression() void Expression::setSubexpressions(Vector<std::unique_ptr<Expression>> subexpressions) { ASSERT(m_subexpressions.isEmpty()); - m_subexpressions = std::move(subexpressions); - for (unsigned i = 0; i < m_subexpressions.size(); ++i) { - m_isContextNodeSensitive |= m_subexpressions[i]->m_isContextNodeSensitive; - m_isContextPositionSensitive |= m_subexpressions[i]->m_isContextPositionSensitive; - m_isContextSizeSensitive |= m_subexpressions[i]->m_isContextSizeSensitive; + m_subexpressions = WTFMove(subexpressions); + for (auto& subexpression : m_subexpressions) { + m_isContextNodeSensitive |= subexpression->m_isContextNodeSensitive; + m_isContextPositionSensitive |= subexpression->m_isContextPositionSensitive; + m_isContextSizeSensitive |= subexpression->m_isContextSizeSensitive; } } diff --git a/Source/WebCore/xml/XPathExpressionNode.h b/Source/WebCore/xml/XPathExpressionNode.h index cf261138f..319b1d145 100644 --- a/Source/WebCore/xml/XPathExpressionNode.h +++ b/Source/WebCore/xml/XPathExpressionNode.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathExpressionNode_h -#define XPathExpressionNode_h +#pragma once #include "XPathValue.h" @@ -66,7 +65,7 @@ protected: m_isContextNodeSensitive |= expression->m_isContextNodeSensitive; m_isContextPositionSensitive |= expression->m_isContextPositionSensitive; m_isContextSizeSensitive |= expression->m_isContextSizeSensitive; - m_subexpressions.append(std::move(expression)); + m_subexpressions.append(WTFMove(expression)); } void setSubexpressions(Vector<std::unique_ptr<Expression>>); @@ -86,5 +85,3 @@ private: } // namespace XPath } // namespace WebCore - -#endif // XPathExpressionNode_h diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp index e6d9809f3..f81b9af86 100644 --- a/Source/WebCore/xml/XPathFunctions.cpp +++ b/Source/WebCore/xml/XPathFunctions.cpp @@ -63,158 +63,158 @@ private: }; class FunLast final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } public: FunLast() { setIsContextSizeSensitive(true); } }; class FunPosition final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } public: FunPosition() { setIsContextPositionSensitive(true); } }; class FunCount final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } }; class FunId final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NodeSetValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NodeSetValue; } }; class FunLocalName final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } public: FunLocalName() { setIsContextNodeSensitive(true); } // local-name() with no arguments uses context node. }; class FunNamespaceURI final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } public: FunNamespaceURI() { setIsContextNodeSensitive(true); } // namespace-uri() with no arguments uses context node. }; class FunName final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } public: FunName() { setIsContextNodeSensitive(true); } // name() with no arguments uses context node. }; class FunString final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } public: FunString() { setIsContextNodeSensitive(true); } // string() with no arguments uses context node. }; class FunConcat final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } }; class FunStartsWith final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunContains final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunSubstringBefore final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } }; class FunSubstringAfter final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } }; class FunSubstring final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } }; class FunStringLength final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } public: FunStringLength() { setIsContextNodeSensitive(true); } // string-length() with no arguments uses context node. }; class FunNormalizeSpace final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } public: FunNormalizeSpace() { setIsContextNodeSensitive(true); } // normalize-space() with no arguments uses context node. }; class FunTranslate final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } }; class FunBoolean final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunNot : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunTrue final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunFalse final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } }; class FunLang final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::BooleanValue; } public: FunLang() { setIsContextNodeSensitive(true); } // lang() always works on context node. }; class FunNumber final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } public: FunNumber() { setIsContextNodeSensitive(true); } // number() with no arguments uses context node. }; class FunSum final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } }; class FunFloor final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } }; class FunCeiling final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } }; class FunRound final : public Function { - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } public: static double round(double); }; @@ -291,7 +291,7 @@ void Function::setArguments(const String& name, Vector<std::unique_ptr<Expressio if (name != "lang" && !arguments.isEmpty()) setIsContextNodeSensitive(false); - setSubexpressions(std::move(arguments)); + setSubexpressions(WTFMove(arguments)); } Value FunLast::evaluate() const @@ -304,21 +304,27 @@ 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 = 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(); @@ -340,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.deprecatedCharacters() + startPos, endPos - startPos)); + Node* node = contextScope.getElementById(atomicSubstring(idList, startPos, endPos - startPos)); if (node && resultSet.add(node).isNewEntry) result.append(node); @@ -349,15 +355,13 @@ Value FunId::evaluate() const result.markSorted(false); - return Value(std::move(result)); + 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 toProcessingInstruction(node)->target(); + if (is<ProcessingInstruction>(*node)) + return downcast<ProcessingInstruction>(*node).target(); return node->localName().string(); } @@ -574,13 +578,13 @@ Value FunLang::evaluate() const { 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->findAttributeByName(XMLNames::langAttr); + if (is<Element>(*node)) { + Element& element = downcast<Element>(*node); + if (element.hasAttributes()) + languageAttribute = element.findAttributeByName(XMLNames::langAttr); } if (languageAttribute) break; @@ -592,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. @@ -628,8 +632,8 @@ 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; } @@ -702,8 +706,8 @@ static void populateFunctionMap(HashMap<String, FunctionMapValue>& functionMap) { "true", { createFunctionTrue, 0 } }, }; - for (size_t i = 0; i < WTF_ARRAY_LENGTH(functions); ++i) - functionMap.add(functions[i].name, functions[i].function); + for (auto& function : functions) + functionMap.add(function.name, function.function); } std::unique_ptr<Function> Function::create(const String& name, unsigned numArguments) @@ -731,7 +735,7 @@ std::unique_ptr<Function> Function::create(const String& name, Vector<std::uniqu { std::unique_ptr<Function> function = create(name, arguments.size()); if (function) - function->setArguments(name, std::move(arguments)); + function->setArguments(name, WTFMove(arguments)); return function; } diff --git a/Source/WebCore/xml/XPathFunctions.h b/Source/WebCore/xml/XPathFunctions.h index 94347a26a..90a29c1b7 100644 --- a/Source/WebCore/xml/XPathFunctions.h +++ b/Source/WebCore/xml/XPathFunctions.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathFunctions_h -#define XPathFunctions_h +#pragma once #include "XPathExpressionNode.h" @@ -48,5 +47,3 @@ private: } // namespace XPath } // namespace WebCore - -#endif // XPathFunctions_h diff --git a/Source/WebCore/xml/XPathGrammar.cpp b/Source/WebCore/xml/XPathGrammar.cpp new file mode 100644 index 000000000..87bed8412 --- /dev/null +++ b/Source/WebCore/xml/XPathGrammar.cpp @@ -0,0 +1,2275 @@ +/* This file is generated using the following command: + bison -d -p xpathyy XPathGrammar.y -o XPathGrammar.cpp + */ + +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse xpathyyparse +#define yylex xpathyylex +#define yyerror xpathyyerror +#define yylval xpathyylval +#define yychar xpathyychar +#define yydebug xpathyydebug +#define yynerrs xpathyynerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + MULOP = 258, + RELOP = 259, + EQOP = 260, + MINUS = 261, + PLUS = 262, + AND = 263, + OR = 264, + FUNCTIONNAME = 265, + LITERAL = 266, + NAMETEST = 267, + NUMBER = 268, + NODETYPE = 269, + VARIABLEREFERENCE = 270, + AXISNAME = 271, + COMMENT = 272, + DOTDOT = 273, + PI = 274, + NODE = 275, + SLASHSLASH = 276, + TEXT_ = 277, + XPATH_ERROR = 278 + }; +#endif +/* Tokens. */ +#define MULOP 258 +#define RELOP 259 +#define EQOP 260 +#define MINUS 261 +#define PLUS 262 +#define AND 263 +#define OR 264 +#define FUNCTIONNAME 265 +#define LITERAL 266 +#define NAMETEST 267 +#define NUMBER 268 +#define NODETYPE 269 +#define VARIABLEREFERENCE 270 +#define AXISNAME 271 +#define COMMENT 272 +#define DOTDOT 273 +#define PI 274 +#define NODE 275 +#define SLASHSLASH 276 +#define TEXT_ 277 +#define XPATH_ERROR 278 + + + +/* Copy the first part of user declarations. */ +#line 28 "WebCore/xml/XPathGrammar.y" + + +#include "config.h" + +#include "XPathFunctions.h" +#include "XPathParser.h" +#include "XPathPath.h" +#include "XPathStep.h" +#include "XPathVariableReference.h" + + +#if COMPILER(MSVC) +// See https://msdn.microsoft.com/en-us/library/1wea5zwe.aspx +#pragma warning(disable: 4701) +#endif + +#define YYMALLOC fastMalloc +#define YYFREE fastFree + +#define YYENABLE_NLS 0 +#define YYLTYPE_IS_TRIVIAL 1 +#define YYDEBUG 0 +#define YYMAXDEPTH 10000 + +using namespace WebCore; +using namespace XPath; + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 60 "WebCore/xml/XPathGrammar.y" +{ + NumericOp::Opcode numericOpcode; + EqTestOp::Opcode equalityTestOpcode; + StringImpl* string; + Step::Axis axis; + LocationPath* locationPath; + Step::NodeTest* nodeTest; + Vector<std::unique_ptr<Expression>>* expressionVector; + Step* step; + Expression* expression; +} +/* Line 193 of yacc.c. */ +#line 190 "./XPathGrammar.cpp" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ +#line 104 "WebCore/xml/XPathGrammar.y" + + +static int xpathyylex(YYSTYPE* yylval, Parser& parser) { return parser.lex(*yylval); } +static void xpathyyerror(Parser&, const char*) { } + + + +/* Line 216 of yacc.c. */ +#line 209 "./XPathGrammar.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 52 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 132 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 33 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 28 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 64 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 101 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 278 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 26, 27, 2, 2, 31, 2, 30, 24, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 25, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 28, 2, 29, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 11, 13, 16, 19, + 21, 25, 29, 32, 35, 39, 43, 45, 47, 49, + 53, 57, 61, 65, 70, 71, 73, 75, 78, 82, + 84, 86, 88, 90, 94, 96, 98, 100, 104, 109, + 111, 115, 117, 119, 123, 125, 127, 131, 135, 137, + 140, 142, 146, 148, 152, 154, 158, 160, 164, 166, + 170, 174, 176, 180, 182 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 34, 0, -1, 35, -1, 54, -1, 37, -1, 38, + -1, 24, -1, 24, 38, -1, 45, 38, -1, 39, + -1, 38, 24, 39, -1, 38, 45, 39, -1, 41, + 42, -1, 12, 42, -1, 40, 41, 42, -1, 40, + 12, 42, -1, 46, -1, 16, -1, 25, -1, 20, + 26, 27, -1, 22, 26, 27, -1, 17, 26, 27, + -1, 19, 26, 27, -1, 19, 26, 11, 27, -1, + -1, 43, -1, 44, -1, 43, 44, -1, 28, 35, + 29, -1, 21, -1, 30, -1, 18, -1, 15, -1, + 26, 35, 27, -1, 11, -1, 13, -1, 48, -1, + 10, 26, 27, -1, 10, 26, 49, 27, -1, 50, + -1, 49, 31, 50, -1, 35, -1, 52, -1, 51, + 32, 52, -1, 36, -1, 53, -1, 53, 24, 38, + -1, 53, 45, 38, -1, 47, -1, 47, 43, -1, + 55, -1, 54, 9, 55, -1, 56, -1, 55, 8, + 56, -1, 57, -1, 56, 5, 57, -1, 58, -1, + 57, 4, 58, -1, 59, -1, 58, 7, 59, -1, + 58, 6, 59, -1, 60, -1, 59, 3, 60, -1, + 51, -1, 6, 60, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 114, 114, 121, 125, 131, 135, 140, 145, 153, + 159, 165, 174, 184, 202, 213, 231, 235, 237, 244, + 249, 254, 259, 264, 273, 277, 281, 287, 295, 302, + 309, 314, 321, 327, 332, 338, 344, 348, 356, 367, + 373, 381, 385, 387, 394, 399, 401, 407, 416, 418, + 426, 428, 435, 437, 444, 446, 453, 455, 462, 464, + 469, 476, 478, 485, 487 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "MULOP", "RELOP", "EQOP", "MINUS", + "PLUS", "AND", "OR", "FUNCTIONNAME", "LITERAL", "NAMETEST", "NUMBER", + "NODETYPE", "VARIABLEREFERENCE", "AXISNAME", "COMMENT", "DOTDOT", "PI", + "NODE", "SLASHSLASH", "TEXT", "XPATH_ERROR", "'/'", "'@'", "'('", "')'", + "'['", "']'", "'.'", "','", "'|'", "$accept", "Top", "Expr", + "LocationPath", "AbsoluteLocationPath", "RelativeLocationPath", "Step", + "AxisSpecifier", "NodeTest", "OptionalPredicateList", "PredicateList", + "Predicate", "DescendantOrSelf", "AbbreviatedStep", "PrimaryExpr", + "FunctionCall", "ArgumentList", "Argument", "UnionExpr", "PathExpr", + "FilterExpr", "OrExpr", "AndExpr", "EqualityExpr", "RelationalExpr", + "AdditiveExpr", "MultiplicativeExpr", "UnaryExpr", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 47, 64, 40, 41, 91, 93, + 46, 44, 124 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 33, 34, 35, 36, 36, 37, 37, 37, 38, + 38, 38, 39, 39, 39, 39, 39, 40, 40, 41, + 41, 41, 41, 41, 42, 42, 43, 43, 44, 45, + 46, 46, 47, 47, 47, 47, 47, 48, 48, 49, + 49, 50, 51, 51, 52, 52, 52, 52, 53, 53, + 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, + 58, 59, 59, 60, 60 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 2, 2, 1, + 3, 3, 2, 2, 3, 3, 1, 1, 1, 3, + 3, 3, 3, 4, 0, 1, 1, 2, 3, 1, + 1, 1, 1, 3, 1, 1, 1, 3, 4, 1, + 3, 1, 1, 3, 1, 1, 3, 3, 1, 2, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 3, 1, 3, 1, 2 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 34, 24, 35, 32, 17, 0, 31, + 0, 0, 29, 0, 6, 18, 0, 30, 0, 2, + 44, 4, 5, 9, 0, 24, 0, 16, 48, 36, + 63, 42, 45, 3, 50, 52, 54, 56, 58, 61, + 64, 0, 0, 13, 25, 26, 0, 0, 0, 0, + 7, 0, 1, 0, 0, 24, 24, 12, 8, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37, 41, 0, 39, 0, 27, 21, 0, 22, 19, + 20, 33, 10, 11, 15, 14, 43, 46, 47, 51, + 53, 55, 57, 60, 59, 62, 38, 0, 28, 23, + 40 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 18, 71, 20, 21, 22, 23, 24, 25, 43, + 44, 45, 26, 27, 28, 29, 72, 73, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -37 +static const yytype_int8 yypact[] = +{ + 81, 81, -8, -37, -7, -37, -37, -37, 14, -37, + 17, 20, -37, 21, 8, -37, 81, -37, 48, -37, + -37, -37, -17, -37, 22, -7, 8, -37, -7, -37, + 23, -37, -9, 1, 45, 49, 52, 10, 54, -37, + -37, 59, 81, -37, -7, -37, 31, -5, 32, 33, + -17, 34, -37, 8, 8, -7, -7, -37, -17, -7, + 102, 8, 8, 81, 81, 81, 81, 81, 81, 81, + -37, -37, -18, -37, 35, -37, -37, 36, -37, -37, + -37, -37, -37, -37, -37, -37, -37, -17, -17, 45, + 49, 52, 10, 54, 54, -37, -37, 81, -37, -37, + -37 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -37, -37, 3, -37, -37, -12, -22, -37, 38, -20, + 60, -36, -21, -37, -37, -37, -37, -24, -37, 30, + -37, -37, 19, 40, 43, 29, -16, -1 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 40, 54, 50, 19, 12, 57, 77, 53, 75, 96, + 63, 62, 12, 97, 58, 61, 67, 68, 41, 51, + 4, 42, 78, 75, 7, 8, 9, 10, 11, 54, + 13, 82, 83, 15, 55, 84, 85, 54, 17, 8, + 46, 10, 11, 47, 13, 74, 48, 49, 52, 87, + 88, 93, 94, 64, 65, 60, 66, 69, 76, 79, + 80, 81, 56, 99, 98, 1, 54, 54, 95, 2, + 3, 4, 5, 100, 6, 7, 8, 9, 10, 11, + 12, 13, 89, 14, 15, 16, 70, 1, 59, 17, + 86, 2, 3, 4, 5, 92, 6, 7, 8, 9, + 10, 11, 12, 13, 90, 14, 15, 16, 91, 0, + 0, 17, 2, 3, 4, 5, 0, 6, 7, 8, + 9, 10, 11, 12, 13, 0, 14, 15, 16, 0, + 0, 0, 17 +}; + +static const yytype_int8 yycheck[] = +{ + 1, 22, 14, 0, 21, 25, 11, 24, 44, 27, + 9, 32, 21, 31, 26, 24, 6, 7, 26, 16, + 12, 28, 27, 59, 16, 17, 18, 19, 20, 50, + 22, 53, 54, 25, 12, 55, 56, 58, 30, 17, + 26, 19, 20, 26, 22, 42, 26, 26, 0, 61, + 62, 67, 68, 8, 5, 32, 4, 3, 27, 27, + 27, 27, 24, 27, 29, 6, 87, 88, 69, 10, + 11, 12, 13, 97, 15, 16, 17, 18, 19, 20, + 21, 22, 63, 24, 25, 26, 27, 6, 28, 30, + 60, 10, 11, 12, 13, 66, 15, 16, 17, 18, + 19, 20, 21, 22, 64, 24, 25, 26, 65, -1, + -1, 30, 10, 11, 12, 13, -1, 15, 16, 17, + 18, 19, 20, 21, 22, -1, 24, 25, 26, -1, + -1, -1, 30 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 6, 10, 11, 12, 13, 15, 16, 17, 18, + 19, 20, 21, 22, 24, 25, 26, 30, 34, 35, + 36, 37, 38, 39, 40, 41, 45, 46, 47, 48, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 60, 26, 28, 42, 43, 44, 26, 26, 26, 26, + 38, 35, 0, 24, 45, 12, 41, 42, 38, 43, + 32, 24, 45, 9, 8, 5, 4, 6, 7, 3, + 27, 35, 49, 50, 35, 44, 27, 11, 27, 27, + 27, 27, 39, 39, 42, 42, 52, 38, 38, 55, + 56, 57, 58, 59, 59, 60, 27, 31, 29, 27, + 50 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (parser, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, parser) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, parser); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Parser& parser) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, parser) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + Parser& parser; +#endif +{ + if (!yyvaluep) + return; + YYUSE (parser); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Parser& parser) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, parser) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + Parser& parser; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, parser); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, Parser& parser) +#else +static void +yy_reduce_print (yyvsp, yyrule, parser) + YYSTYPE *yyvsp; + int yyrule; + Parser& parser; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , parser); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule, parser); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, Parser& parser) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, parser) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + Parser& parser; +#endif +{ + YYUSE (yyvaluep); + YYUSE (parser); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 10: /* "FUNCTIONNAME" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1205 "./XPathGrammar.cpp" + break; + case 11: /* "LITERAL" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1210 "./XPathGrammar.cpp" + break; + case 12: /* "NAMETEST" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1215 "./XPathGrammar.cpp" + break; + case 13: /* "NUMBER" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1220 "./XPathGrammar.cpp" + break; + case 14: /* "NODETYPE" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1225 "./XPathGrammar.cpp" + break; + case 15: /* "VARIABLEREFERENCE" */ +#line 80 "WebCore/xml/XPathGrammar.y" + { if ((yyvaluep->string)) (yyvaluep->string)->deref(); }; +#line 1230 "./XPathGrammar.cpp" + break; + case 35: /* "Expr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1235 "./XPathGrammar.cpp" + break; + case 36: /* "LocationPath" */ +#line 88 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->locationPath); }; +#line 1240 "./XPathGrammar.cpp" + break; + case 37: /* "AbsoluteLocationPath" */ +#line 88 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->locationPath); }; +#line 1245 "./XPathGrammar.cpp" + break; + case 38: /* "RelativeLocationPath" */ +#line 88 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->locationPath); }; +#line 1250 "./XPathGrammar.cpp" + break; + case 39: /* "Step" */ +#line 97 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->step); }; +#line 1255 "./XPathGrammar.cpp" + break; + case 41: /* "NodeTest" */ +#line 91 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->nodeTest); }; +#line 1260 "./XPathGrammar.cpp" + break; + case 42: /* "OptionalPredicateList" */ +#line 94 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expressionVector); }; +#line 1265 "./XPathGrammar.cpp" + break; + case 43: /* "PredicateList" */ +#line 94 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expressionVector); }; +#line 1270 "./XPathGrammar.cpp" + break; + case 44: /* "Predicate" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1275 "./XPathGrammar.cpp" + break; + case 45: /* "DescendantOrSelf" */ +#line 97 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->step); }; +#line 1280 "./XPathGrammar.cpp" + break; + case 46: /* "AbbreviatedStep" */ +#line 97 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->step); }; +#line 1285 "./XPathGrammar.cpp" + break; + case 47: /* "PrimaryExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1290 "./XPathGrammar.cpp" + break; + case 48: /* "FunctionCall" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1295 "./XPathGrammar.cpp" + break; + case 49: /* "ArgumentList" */ +#line 94 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expressionVector); }; +#line 1300 "./XPathGrammar.cpp" + break; + case 50: /* "Argument" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1305 "./XPathGrammar.cpp" + break; + case 51: /* "UnionExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1310 "./XPathGrammar.cpp" + break; + case 52: /* "PathExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1315 "./XPathGrammar.cpp" + break; + case 53: /* "FilterExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1320 "./XPathGrammar.cpp" + break; + case 54: /* "OrExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1325 "./XPathGrammar.cpp" + break; + case 55: /* "AndExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1330 "./XPathGrammar.cpp" + break; + case 56: /* "EqualityExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1335 "./XPathGrammar.cpp" + break; + case 57: /* "RelationalExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1340 "./XPathGrammar.cpp" + break; + case 58: /* "AdditiveExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1345 "./XPathGrammar.cpp" + break; + case 59: /* "MultiplicativeExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1350 "./XPathGrammar.cpp" + break; + case 60: /* "UnaryExpr" */ +#line 100 "WebCore/xml/XPathGrammar.y" + { delete (yyvaluep->expression); }; +#line 1355 "./XPathGrammar.cpp" + break; + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (Parser& parser); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (Parser& parser) +#else +int +yyparse (parser) + Parser& parser; +#endif +#endif +{ + /* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 115 "WebCore/xml/XPathGrammar.y" + { + parser.setParseResult(std::unique_ptr<Expression>((yyvsp[(1) - (1)].expression))); + ;} + break; + + case 4: +#line 126 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = (yyvsp[(1) - (1)].locationPath); + (yyval.locationPath)->setAbsolute(); + ;} + break; + + case 6: +#line 136 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = new LocationPath; + ;} + break; + + case 7: +#line 141 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = (yyvsp[(2) - (2)].locationPath); + ;} + break; + + case 8: +#line 146 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = (yyvsp[(2) - (2)].locationPath); + (yyval.locationPath)->prependStep(std::unique_ptr<Step>((yyvsp[(1) - (2)].step))); + ;} + break; + + case 9: +#line 154 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = new LocationPath; + (yyval.locationPath)->appendStep(std::unique_ptr<Step>((yyvsp[(1) - (1)].step))); + ;} + break; + + case 10: +#line 160 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = (yyvsp[(1) - (3)].locationPath); + (yyval.locationPath)->appendStep(std::unique_ptr<Step>((yyvsp[(3) - (3)].step))); + ;} + break; + + case 11: +#line 166 "WebCore/xml/XPathGrammar.y" + { + (yyval.locationPath) = (yyvsp[(1) - (3)].locationPath); + (yyval.locationPath)->appendStep(std::unique_ptr<Step>((yyvsp[(2) - (3)].step))); + (yyval.locationPath)->appendStep(std::unique_ptr<Step>((yyvsp[(3) - (3)].step))); + ;} + break; + + case 12: +#line 175 "WebCore/xml/XPathGrammar.y" + { + std::unique_ptr<Step::NodeTest> nodeTest((yyvsp[(1) - (2)].nodeTest)); + std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList((yyvsp[(2) - (2)].expressionVector)); + if (predicateList) + (yyval.step) = new Step(Step::ChildAxis, WTFMove(*nodeTest), WTFMove(*predicateList)); + else + (yyval.step) = new Step(Step::ChildAxis, WTFMove(*nodeTest)); + ;} + break; + + case 13: +#line 185 "WebCore/xml/XPathGrammar.y" + { + String nametest = adoptRef((yyvsp[(1) - (2)].string)); + std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList((yyvsp[(2) - (2)].expressionVector)); + + String localName; + String namespaceURI; + if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) { + (yyval.step) = nullptr; + YYABORT; + } + + if (predicateList) + (yyval.step) = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList)); + else + (yyval.step) = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI)); + ;} + break; + + case 14: +#line 203 "WebCore/xml/XPathGrammar.y" + { + std::unique_ptr<Step::NodeTest> nodeTest((yyvsp[(2) - (3)].nodeTest)); + std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList((yyvsp[(3) - (3)].expressionVector)); + + if (predicateList) + (yyval.step) = new Step((yyvsp[(1) - (3)].axis), WTFMove(*nodeTest), WTFMove(*predicateList)); + else + (yyval.step) = new Step((yyvsp[(1) - (3)].axis), WTFMove(*nodeTest)); + ;} + break; + + case 15: +#line 214 "WebCore/xml/XPathGrammar.y" + { + String nametest = adoptRef((yyvsp[(2) - (3)].string)); + std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList((yyvsp[(3) - (3)].expressionVector)); + + String localName; + String namespaceURI; + if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) { + (yyval.step) = nullptr; + YYABORT; + } + + if (predicateList) + (yyval.step) = new Step((yyvsp[(1) - (3)].axis), Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList)); + else + (yyval.step) = new Step((yyvsp[(1) - (3)].axis), Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI)); + ;} + break; + + case 18: +#line 238 "WebCore/xml/XPathGrammar.y" + { + (yyval.axis) = Step::AttributeAxis; + ;} + break; + + case 19: +#line 245 "WebCore/xml/XPathGrammar.y" + { + (yyval.nodeTest) = new Step::NodeTest(Step::NodeTest::AnyNodeTest); + ;} + break; + + case 20: +#line 250 "WebCore/xml/XPathGrammar.y" + { + (yyval.nodeTest) = new Step::NodeTest(Step::NodeTest::TextNodeTest); + ;} + break; + + case 21: +#line 255 "WebCore/xml/XPathGrammar.y" + { + (yyval.nodeTest) = new Step::NodeTest(Step::NodeTest::CommentNodeTest); + ;} + break; + + case 22: +#line 260 "WebCore/xml/XPathGrammar.y" + { + (yyval.nodeTest) = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest); + ;} + break; + + case 23: +#line 265 "WebCore/xml/XPathGrammar.y" + { + String literal = adoptRef((yyvsp[(3) - (4)].string)); + (yyval.nodeTest) = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest, literal.stripWhiteSpace()); + ;} + break; + + case 24: +#line 273 "WebCore/xml/XPathGrammar.y" + { + (yyval.expressionVector) = nullptr; + ;} + break; + + case 26: +#line 282 "WebCore/xml/XPathGrammar.y" + { + (yyval.expressionVector) = new Vector<std::unique_ptr<Expression>>; + (yyval.expressionVector)->append(std::unique_ptr<Expression>((yyvsp[(1) - (1)].expression))); + ;} + break; + + case 27: +#line 288 "WebCore/xml/XPathGrammar.y" + { + (yyval.expressionVector) = (yyvsp[(1) - (2)].expressionVector); + (yyval.expressionVector)->append(std::unique_ptr<Expression>((yyvsp[(2) - (2)].expression))); + ;} + break; + + case 28: +#line 296 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = (yyvsp[(2) - (3)].expression); + ;} + break; + + case 29: +#line 303 "WebCore/xml/XPathGrammar.y" + { + (yyval.step) = new Step(Step::DescendantOrSelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest)); + ;} + break; + + case 30: +#line 310 "WebCore/xml/XPathGrammar.y" + { + (yyval.step) = new Step(Step::SelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest)); + ;} + break; + + case 31: +#line 315 "WebCore/xml/XPathGrammar.y" + { + (yyval.step) = new Step(Step::ParentAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest)); + ;} + break; + + case 32: +#line 322 "WebCore/xml/XPathGrammar.y" + { + String name = adoptRef((yyvsp[(1) - (1)].string)); + (yyval.expression) = new VariableReference(name); + ;} + break; + + case 33: +#line 328 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = (yyvsp[(2) - (3)].expression); + ;} + break; + + case 34: +#line 333 "WebCore/xml/XPathGrammar.y" + { + String literal = adoptRef((yyvsp[(1) - (1)].string)); + (yyval.expression) = new StringExpression(WTFMove(literal)); + ;} + break; + + case 35: +#line 339 "WebCore/xml/XPathGrammar.y" + { + String numeral = adoptRef((yyvsp[(1) - (1)].string)); + (yyval.expression) = new Number(numeral.toDouble()); + ;} + break; + + case 37: +#line 349 "WebCore/xml/XPathGrammar.y" + { + String name = adoptRef((yyvsp[(1) - (3)].string)); + (yyval.expression) = XPath::Function::create(name).release(); + if (!(yyval.expression)) + YYABORT; + ;} + break; + + case 38: +#line 357 "WebCore/xml/XPathGrammar.y" + { + String name = adoptRef((yyvsp[(1) - (4)].string)); + std::unique_ptr<Vector<std::unique_ptr<Expression>>> argumentList((yyvsp[(3) - (4)].expressionVector)); + (yyval.expression) = XPath::Function::create(name, WTFMove(*argumentList)).release(); + if (!(yyval.expression)) + YYABORT; + ;} + break; + + case 39: +#line 368 "WebCore/xml/XPathGrammar.y" + { + (yyval.expressionVector) = new Vector<std::unique_ptr<Expression>>; + (yyval.expressionVector)->append(std::unique_ptr<Expression>((yyvsp[(1) - (1)].expression))); + ;} + break; + + case 40: +#line 374 "WebCore/xml/XPathGrammar.y" + { + (yyval.expressionVector) = (yyvsp[(1) - (3)].expressionVector); + (yyval.expressionVector)->append(std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 43: +#line 388 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new Union(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 44: +#line 395 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = (yyvsp[(1) - (1)].locationPath); + ;} + break; + + case 46: +#line 402 "WebCore/xml/XPathGrammar.y" + { + (yyvsp[(3) - (3)].locationPath)->setAbsolute(); + (yyval.expression) = new Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath))); + ;} + break; + + case 47: +#line 408 "WebCore/xml/XPathGrammar.y" + { + (yyvsp[(3) - (3)].locationPath)->prependStep(std::unique_ptr<Step>((yyvsp[(2) - (3)].step))); + (yyvsp[(3) - (3)].locationPath)->setAbsolute(); + (yyval.expression) = new Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath))); + ;} + break; + + case 49: +#line 419 "WebCore/xml/XPathGrammar.y" + { + std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList((yyvsp[(2) - (2)].expressionVector)); + (yyval.expression) = new Filter(std::unique_ptr<Expression>((yyvsp[(1) - (2)].expression)), WTFMove(*predicateList)); + ;} + break; + + case 51: +#line 429 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new LogicalOp(LogicalOp::OP_Or, std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 53: +#line 438 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new LogicalOp(LogicalOp::OP_And, std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 55: +#line 447 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new EqTestOp((yyvsp[(2) - (3)].equalityTestOpcode), std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 57: +#line 456 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new EqTestOp((yyvsp[(2) - (3)].equalityTestOpcode), std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 59: +#line 465 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new NumericOp(NumericOp::OP_Add, std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 60: +#line 470 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new NumericOp(NumericOp::OP_Sub, std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 62: +#line 479 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new NumericOp((yyvsp[(2) - (3)].numericOpcode), std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<Expression>((yyvsp[(3) - (3)].expression))); + ;} + break; + + case 64: +#line 488 "WebCore/xml/XPathGrammar.y" + { + (yyval.expression) = new Negative(std::unique_ptr<Expression>((yyvsp[(2) - (2)].expression))); + ;} + break; + + +/* Line 1267 of yacc.c. */ +#line 2049 "./XPathGrammar.cpp" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (parser, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (parser, yymsg); + } + else + { + yyerror (parser, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, parser); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ +#if COMPILER(CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + if (/*CONSTCOND*/ 0) + goto yyerrorlab; +#if COMPILER(CLANG) +#pragma clang diagnostic pop +#endif + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, parser); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (parser, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, parser); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, parser); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 493 "WebCore/xml/XPathGrammar.y" + + diff --git a/Source/WebCore/xml/XPathGrammar.h b/Source/WebCore/xml/XPathGrammar.h new file mode 100644 index 000000000..39b96ca24 --- /dev/null +++ b/Source/WebCore/xml/XPathGrammar.h @@ -0,0 +1,117 @@ +#ifndef CSSGRAMMAR_H +#define CSSGRAMMAR_H +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + MULOP = 258, + RELOP = 259, + EQOP = 260, + MINUS = 261, + PLUS = 262, + AND = 263, + OR = 264, + FUNCTIONNAME = 265, + LITERAL = 266, + NAMETEST = 267, + NUMBER = 268, + NODETYPE = 269, + VARIABLEREFERENCE = 270, + AXISNAME = 271, + COMMENT = 272, + DOTDOT = 273, + PI = 274, + NODE = 275, + SLASHSLASH = 276, + TEXT_ = 277, + XPATH_ERROR = 278 + }; +#endif +/* Tokens. */ +#define MULOP 258 +#define RELOP 259 +#define EQOP 260 +#define MINUS 261 +#define PLUS 262 +#define AND 263 +#define OR 264 +#define FUNCTIONNAME 265 +#define LITERAL 266 +#define NAMETEST 267 +#define NUMBER 268 +#define NODETYPE 269 +#define VARIABLEREFERENCE 270 +#define AXISNAME 271 +#define COMMENT 272 +#define DOTDOT 273 +#define PI 274 +#define NODE 275 +#define SLASHSLASH 276 +#define TEXT_ 277 +#define XPATH_ERROR 278 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 60 "WebCore/xml/XPathGrammar.y" +{ + NumericOp::Opcode numericOpcode; + EqTestOp::Opcode equalityTestOpcode; + StringImpl* string; + Step::Axis axis; + LocationPath* locationPath; + Step::NodeTest* nodeTest; + Vector<std::unique_ptr<Expression>>* expressionVector; + Step* step; + Expression* expression; +} +/* Line 1529 of yacc.c. */ +#line 107 "./XPathGrammar.hpp" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +#endif diff --git a/Source/WebCore/xml/XPathGrammar.y b/Source/WebCore/xml/XPathGrammar.y index a340a6929..4eb20b92a 100644 --- a/Source/WebCore/xml/XPathGrammar.y +++ b/Source/WebCore/xml/XPathGrammar.y @@ -32,8 +32,14 @@ #include "XPathFunctions.h" #include "XPathParser.h" #include "XPathPath.h" +#include "XPathStep.h" #include "XPathVariableReference.h" +#if COMPILER(MSVC) +// See https://msdn.microsoft.com/en-us/library/1wea5zwe.aspx +#pragma warning(disable: 4701) +#endif + #define YYMALLOC fastMalloc #define YYFREE fastFree @@ -47,50 +53,54 @@ using namespace XPath; %} -%pure_parser +%pure-parser %lex-param { parser } %parse-param { Parser& parser } -%union { NumericOp::Opcode numericOpcode; } +%union { + NumericOp::Opcode numericOpcode; + EqTestOp::Opcode equalityTestOpcode; + StringImpl* string; + Step::Axis axis; + LocationPath* locationPath; + Step::NodeTest* nodeTest; + Vector<std::unique_ptr<Expression>>* expressionVector; + Step* step; + Expression* expression; +} %left <numericOpcode> MULOP -%union { EqTestOp::Opcode equalityTestOpcode; } %left <equalityTestOpcode> EQOP RELOP %left PLUS MINUS %left OR AND -%union { StringImpl* string; } %token <string> FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE %destructor { if ($$) $$->deref(); } FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE -%union { Step::Axis axis; } %token <axis> AXISNAME %type <axis> AxisSpecifier -%token COMMENT DOTDOT PI NODE SLASHSLASH TEXT XPATH_ERROR +%token COMMENT DOTDOT PI NODE SLASHSLASH TEXT_ XPATH_ERROR -%union { LocationPath* locationPath; } %type <locationPath> LocationPath AbsoluteLocationPath RelativeLocationPath %destructor { delete $$; } LocationPath AbsoluteLocationPath RelativeLocationPath -%union { Step::NodeTest* nodeTest; } %type <nodeTest> NodeTest %destructor { delete $$; } NodeTest -%union { Vector<std::unique_ptr<Expression>>* expressionVector; } %type <expressionVector> ArgumentList PredicateList OptionalPredicateList %destructor { delete $$; } ArgumentList PredicateList OptionalPredicateList -%union { Step* step; } %type <step> Step AbbreviatedStep DescendantOrSelf %destructor { delete $$; } Step AbbreviatedStep DescendantOrSelf -%union { Expression* expression; } %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); } @@ -166,9 +176,9 @@ Step: std::unique_ptr<Step::NodeTest> nodeTest($1); std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2); if (predicateList) - $$ = new Step(Step::ChildAxis, std::move(*nodeTest), std::move(*predicateList)); + $$ = new Step(Step::ChildAxis, WTFMove(*nodeTest), WTFMove(*predicateList)); else - $$ = new Step(Step::ChildAxis, std::move(*nodeTest)); + $$ = new Step(Step::ChildAxis, WTFMove(*nodeTest)); } | NAMETEST OptionalPredicateList @@ -184,7 +194,7 @@ Step: } if (predicateList) - $$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), std::move(*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)); } @@ -195,9 +205,9 @@ Step: std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($3); if (predicateList) - $$ = new Step($1, std::move(*nodeTest), std::move(*predicateList)); + $$ = new Step($1, WTFMove(*nodeTest), WTFMove(*predicateList)); else - $$ = new Step($1, std::move(*nodeTest)); + $$ = new Step($1, WTFMove(*nodeTest)); } | AxisSpecifier NAMETEST OptionalPredicateList @@ -213,7 +223,7 @@ Step: } if (predicateList) - $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), std::move(*predicateList)); + $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList)); else $$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI)); } @@ -236,7 +246,7 @@ NodeTest: $$ = new Step::NodeTest(Step::NodeTest::AnyNodeTest); } | - TEXT '(' ')' + TEXT_ '(' ')' { $$ = new Step::NodeTest(Step::NodeTest::TextNodeTest); } @@ -322,7 +332,7 @@ PrimaryExpr: LITERAL { String literal = adoptRef($1); - $$ = new StringExpression(std::move(literal)); + $$ = new StringExpression(WTFMove(literal)); } | NUMBER @@ -347,7 +357,7 @@ FunctionCall: { String name = adoptRef($1); std::unique_ptr<Vector<std::unique_ptr<Expression>>> argumentList($3); - $$ = XPath::Function::create(name, std::move(*argumentList)).release(); + $$ = XPath::Function::create(name, WTFMove(*argumentList)).release(); if (!$$) YYABORT; } @@ -408,7 +418,7 @@ FilterExpr: PrimaryExpr PredicateList { std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2); - $$ = new Filter(std::unique_ptr<Expression>($1), std::move(*predicateList)); + $$ = new Filter(std::unique_ptr<Expression>($1), WTFMove(*predicateList)); } ; 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..b50e13c63 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 @@ -24,23 +24,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathNSResolver_h -#define XPathNSResolver_h +#pragma once #include <wtf/Forward.h> #include <wtf/RefCounted.h> namespace WebCore { - class XPathNSResolver : public RefCounted<XPathNSResolver> { - public: - virtual ~XPathNSResolver(); - virtual String lookupNamespaceURI(const String& prefix) = 0; - - protected: - XPathNSResolver() { } - }; +class WEBCORE_EXPORT XPathNSResolver : public RefCounted<XPathNSResolver> { +public: + virtual ~XPathNSResolver(); + virtual String lookupNamespaceURI(const String& prefix) = 0; -} +protected: + XPathNSResolver() { } +}; -#endif // XPathNSResolver_h +} diff --git a/Source/WebCore/xml/XPathNSResolver.idl b/Source/WebCore/xml/XPathNSResolver.idl index d9737aebf..36b781b06 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 @@ -19,10 +19,10 @@ */ [ + JSCustomToNativeObject, NoInterfaceObject, - ObjCProtocol, SkipVTableValidation, ] interface XPathNSResolver { - [TreatReturnedNullStringAs=Null] DOMString lookupNamespaceURI([Default=Undefined] optional DOMString prefix); + // FIXME: Using "undefined" as default parameter value is wrong. + DOMString? lookupNamespaceURI(optional DOMString prefix = "undefined"); }; - diff --git a/Source/WebCore/xml/XPathNodeSet.cpp b/Source/WebCore/xml/XPathNodeSet.cpp index 5fcbfaa53..d04bd62c1 100644 --- a/Source/WebCore/xml/XPathNodeSet.cpp +++ b/Source/WebCore/xml/XPathNodeSet.cpp @@ -94,8 +94,8 @@ static void sortBlock(unsigned from, unsigned to, Vector<Vector<Node*>>& parentM unsigned sortedEnd = from; // FIXME: namespace nodes are not implemented. for (unsigned i = sortedEnd; i < to; ++i) { - Node* n = parentMatrix[i][0]; - if (n->isAttributeNode() && toAttr(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) { @@ -155,15 +155,15 @@ void NodeSet::sort() const 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 = toAttr(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); @@ -173,15 +173,15 @@ void NodeSet::sort() const for (unsigned i = 0; i < nodeCount; ++i) sortedNodes.append(parentMatrix[i][0]); - m_nodes = std::move(sortedNodes); + m_nodes = WTFMove(sortedNodes); m_isSorted = true; } static Node* findRootNode(Node* node) { - if (node->isAttributeNode()) - node = toAttr(node)->ownerElement(); - if (node->inDocument()) + if (is<Attr>(*node)) + node = downcast<Attr>(*node).ownerElement(); + if (node->isConnected()) node = &node->document(); else { while (Node* parent = node->parentNode()) @@ -197,9 +197,8 @@ 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; } @@ -207,26 +206,26 @@ void NodeSet::traversalSort() const 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; - for (const Attribute& attribute : element->attributesIterator()) { - RefPtr<Attr> attr = element->attrIfExists(attribute.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); - m_nodes = std::move(sortedNodes); + m_nodes = WTFMove(sortedNodes); m_isSorted = true; } diff --git a/Source/WebCore/xml/XPathNodeSet.h b/Source/WebCore/xml/XPathNodeSet.h index 459fcf3c4..6ea91b904 100644 --- a/Source/WebCore/xml/XPathNodeSet.h +++ b/Source/WebCore/xml/XPathNodeSet.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 @@ -24,19 +24,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathNodeSet_h -#define XPathNodeSet_h +#pragma once #include "Node.h" namespace WebCore { - namespace XPath { class NodeSet { public: NodeSet() : m_isSorted(true), m_subtreesAreDisjoint(false) { } - explicit NodeSet(PassRefPtr<Node> node) : m_isSorted(true), m_subtreesAreDisjoint(false), m_nodes(1, node) { } + 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.isEmpty(); } @@ -45,7 +45,7 @@ namespace WebCore { void clear() { m_nodes.clear(); } // NodeSet itself does not verify that nodes in it are unique. - 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 nullptr if the set is empty. @@ -64,6 +64,9 @@ namespace WebCore { void markSubtreesDisjoint(bool disjoint) { m_subtreesAreDisjoint = disjoint; } bool subtreesAreDisjoint() const { return m_subtreesAreDisjoint || m_nodes.size() < 2; } + const RefPtr<Node>* begin() const { return m_nodes.begin(); } + const RefPtr<Node>* end() const { return m_nodes.end(); } + private: void traversalSort() const; @@ -72,7 +75,5 @@ namespace WebCore { mutable Vector<RefPtr<Node>> m_nodes; }; - } -} - -#endif // XPathNodeSet_h + } // namespace XPath +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathParser.cpp b/Source/WebCore/xml/XPathParser.cpp index 1dae7f2c7..b6bb205dc 100644 --- a/Source/WebCore/xml/XPathParser.cpp +++ b/Source/WebCore/xml/XPathParser.cpp @@ -33,6 +33,7 @@ #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> @@ -99,8 +100,8 @@ static void populateAxisNamesMap(HashMap<String, Step::Axis>& axisNames) { "preceding-sibling", Step::PrecedingSiblingAxis }, { "self", Step::SelfAxis } }; - for (unsigned i = 0; i < WTF_ARRAY_LENGTH(axisNameList); ++i) - axisNames.add(axisNameList[i].name, axisNameList[i].axis); + for (auto& axisName : axisNameList) + axisNames.add(axisName.name, axisName.axis); } static bool parseAxisName(const String& name, Step::Axis& type) @@ -188,7 +189,7 @@ Parser::Token Parser::lexString() if (m_data[m_nextPos] == delimiter) { String value = m_data.substring(startPos, m_nextPos - startPos); if (value.isNull()) - value = ""; + value = emptyString(); ++m_nextPos; // Consume the char. return Token(LITERAL, value); } @@ -208,7 +209,7 @@ Parser::Token Parser::lexNumber() UChar aChar = m_data[m_nextPos]; if (aChar >= 0xff) break; - if (aChar < '0' || aChar > '9') { + if (!isASCIIDigit(aChar)) { if (aChar == '.' && !seenDot) seenDot = true; else @@ -282,7 +283,7 @@ inline Parser::Token Parser::nextTokenInternal() char next = peekAheadHelper(); if (next == '.') return makeTokenAndAdvance(DOTDOT, 2); - if (next >= '0' && next <= '9') + if (isASCIIDigit(next)) return lexNumber(); return makeTokenAndAdvance('.'); } @@ -381,7 +382,7 @@ inline Parser::Token Parser::nextTokenInternal() if (name == "node") return Token(NODE); if (name == "text") - return Token(TEXT); + return Token(TEXT_); if (name == "comment") return Token(COMMENT); @@ -399,12 +400,9 @@ inline Parser::Token Parser::nextToken() return token; } -Parser::Parser(const String& statement, XPathNSResolver* resolver) +Parser::Parser(const String& statement, RefPtr<XPathNSResolver>&& resolver) : m_data(statement) - , m_resolver(resolver) - , m_nextPos(0) - , m_lastTokenType(0) - , m_sawNamespaceError(false) + , m_resolver(WTFMove(resolver)) { } @@ -452,27 +450,22 @@ bool Parser::expandQualifiedName(const String& qualifiedName, String& localName, localName = qualifiedName.substring(colon + 1); } else localName = qualifiedName; - return true; } -std::unique_ptr<Expression> Parser::parseStatement(const String& statement, XPathNSResolver* resolver, ExceptionCode& ec) +ExceptionOr<std::unique_ptr<Expression>> Parser::parseStatement(const String& statement, RefPtr<XPathNSResolver>&& resolver) { - Parser parser(statement, resolver); + Parser parser { statement, WTFMove(resolver) }; int parseError = xpathyyparse(parser); - if (parser.m_sawNamespaceError) { - ec = NAMESPACE_ERR; - return nullptr; - } + if (parser.m_sawNamespaceError) + return Exception { NAMESPACE_ERR }; - if (parseError) { - ec = XPathException::INVALID_EXPRESSION_ERR; - return nullptr; - } + if (parseError) + return Exception { XPathException::INVALID_EXPRESSION_ERR }; - return std::move(parser.m_result); + return WTFMove(parser.m_result); } } } diff --git a/Source/WebCore/xml/XPathParser.h b/Source/WebCore/xml/XPathParser.h index 4e6f437e6..68289caa5 100644 --- a/Source/WebCore/xml/XPathParser.h +++ b/Source/WebCore/xml/XPathParser.h @@ -24,64 +24,58 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathParser_h -#define XPathParser_h +#pragma once -#include "XPathStep.h" +#include "ExceptionOr.h" #include "XPathPredicate.h" union YYSTYPE; namespace WebCore { - typedef int ExceptionCode; +class XPathNSResolver; - class XPathNSResolver; +namespace XPath { - namespace XPath { +class Parser { + WTF_MAKE_NONCOPYABLE(Parser); +public: + static ExceptionOr<std::unique_ptr<Expression>> parseStatement(const String& statement, RefPtr<XPathNSResolver>&&); - class Parser { - WTF_MAKE_NONCOPYABLE(Parser); - public: - static std::unique_ptr<Expression> parseStatement(const String& statement, XPathNSResolver*, ExceptionCode&); + int lex(YYSTYPE&); + bool expandQualifiedName(const String& qualifiedName, String& localName, String& namespaceURI); + void setParseResult(std::unique_ptr<Expression>&& expression) { m_result = WTFMove(expression); } - int lex(YYSTYPE&); - bool expandQualifiedName(const String& qualifiedName, String& localName, String& namespaceURI); - void setParseResult(std::unique_ptr<Expression> expression) { m_result = std::move(expression); } +private: + Parser(const String&, RefPtr<XPathNSResolver>&&); - private: - Parser(const String&, XPathNSResolver*); + struct Token; - struct Token; + bool isBinaryOperatorContext() const; - bool isBinaryOperatorContext() const; + void skipWS(); + Token makeTokenAndAdvance(int type, int advance = 1); + Token makeTokenAndAdvance(int type, NumericOp::Opcode, int advance = 1); + Token makeTokenAndAdvance(int type, EqTestOp::Opcode, int advance = 1); + char peekAheadHelper(); + char peekCurHelper(); - void skipWS(); - Token makeTokenAndAdvance(int type, int advance = 1); - Token makeTokenAndAdvance(int type, NumericOp::Opcode, int advance = 1); - Token makeTokenAndAdvance(int type, EqTestOp::Opcode, int advance = 1); - char peekAheadHelper(); - char peekCurHelper(); + Token lexString(); + Token lexNumber(); + bool lexNCName(String&); + bool lexQName(String&); - Token lexString(); - Token lexNumber(); - bool lexNCName(String&); - bool lexQName(String&); + Token nextToken(); + Token nextTokenInternal(); - Token nextToken(); - Token nextTokenInternal(); + const String& m_data; + RefPtr<XPathNSResolver> m_resolver; - const String& m_data; - XPathNSResolver* m_resolver; + unsigned m_nextPos { 0 }; + int m_lastTokenType { 0 }; - unsigned m_nextPos; - int m_lastTokenType; + std::unique_ptr<Expression> m_result; + bool m_sawNamespaceError { false }; +}; - std::unique_ptr<Expression> m_result; - bool m_sawNamespaceError; - }; - - } -} - -#endif +} } diff --git a/Source/WebCore/xml/XPathPath.cpp b/Source/WebCore/xml/XPathPath.cpp index 06d73f9b0..a20524d9c 100644 --- a/Source/WebCore/xml/XPathPath.cpp +++ b/Source/WebCore/xml/XPathPath.cpp @@ -36,7 +36,7 @@ namespace WebCore { namespace XPath { Filter::Filter(std::unique_ptr<Expression> expression, Vector<std::unique_ptr<Expression>> predicates) - : m_expression(std::move(expression)), m_predicates(std::move(predicates)) + : m_expression(WTFMove(expression)), m_predicates(WTFMove(predicates)) { setIsContextNodeSensitive(m_expression->isContextNodeSensitive()); setIsContextPositionSensitive(m_expression->isContextPositionSensitive()); @@ -51,21 +51,19 @@ Value Filter::evaluate() const 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 (evaluatePredicate(*m_predicates[i])) - newNodes.append(node); + if (evaluatePredicate(*predicate)) + newNodes.append(node.copyRef()); } - nodes = std::move(newNodes); + nodes = WTFMove(newNodes); } return result; @@ -90,55 +88,49 @@ 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_isAbsolute && !context->isDocumentNode()) { - if (context->inDocument()) - context = context->ownerDocument(); - else - context = context->highestAncestor(); - } + if (m_isAbsolute && !context->isDocumentNode()) + context = &context->rootNode(); NodeSet nodes; nodes.append(context); evaluate(nodes); evaluationContext = backupContext; - return Value(std::move(nodes)); + 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; - bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step.axis() != Step::ChildAxis && step.axis() != Step::SelfAxis - && step.axis() != Step::DescendantAxis && step.axis() != Step::DescendantOrSelfAxis && step.axis() != Step::AttributeAxis); + bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis + && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis); if (needToCheckForDuplicateNodes) resultIsSorted = false; // This is a simplified check that can be improved to handle more cases. - if (nodes.subtreesAreDisjoint() && (step.axis() == Step::ChildAxis || step.axis() == Step::SelfAxis)) + 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 = std::move(newNodes); + nodes = WTFMove(newNodes); } nodes.markSorted(resultIsSorted); @@ -154,7 +146,7 @@ void LocationPath::appendStep(std::unique_ptr<Step> step) return; } step->optimize(); - m_steps.append(std::move(step)); + m_steps.append(WTFMove(step)); } void LocationPath::prependStep(std::unique_ptr<Step> step) @@ -163,17 +155,17 @@ void LocationPath::prependStep(std::unique_ptr<Step> step) bool dropSecondStep; optimizeStepPair(*step, *m_steps[0], dropSecondStep); if (dropSecondStep) { - m_steps[0] = std::move(step); + m_steps[0] = WTFMove(step); return; } } step->optimize(); - m_steps.insert(0, std::move(step)); + m_steps.insert(0, WTFMove(step)); } Path::Path(std::unique_ptr<Expression> filter, std::unique_ptr<LocationPath> path) - : m_filter(std::move(filter)) - , m_path(std::move(path)) + : m_filter(WTFMove(filter)) + , m_path(WTFMove(path)) { setIsContextNodeSensitive(m_filter->isContextNodeSensitive()); setIsContextPositionSensitive(m_filter->isContextPositionSensitive()); diff --git a/Source/WebCore/xml/XPathPath.h b/Source/WebCore/xml/XPathPath.h index 5491618a8..e5725208a 100644 --- a/Source/WebCore/xml/XPathPath.h +++ b/Source/WebCore/xml/XPathPath.h @@ -24,13 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathPath_h -#define XPathPath_h +#pragma once #include "XPathExpressionNode.h" namespace WebCore { - namespace XPath { class Step; @@ -40,8 +38,8 @@ namespace WebCore { Filter(std::unique_ptr<Expression>, Vector<std::unique_ptr<Expression>> predicates); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NodeSetValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NodeSetValue; } std::unique_ptr<Expression> m_expression; Vector<std::unique_ptr<Expression>> m_predicates; @@ -59,8 +57,8 @@ namespace WebCore { void prependStep(std::unique_ptr<Step>); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NodeSetValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NodeSetValue; } Vector<std::unique_ptr<Step>> m_steps; bool m_isAbsolute; @@ -71,14 +69,12 @@ namespace WebCore { Path(std::unique_ptr<Expression> filter, std::unique_ptr<LocationPath>); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NodeSetValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NodeSetValue; } std::unique_ptr<Expression> m_filter; std::unique_ptr<LocationPath> m_path; }; - } -} - -#endif // XPath_Path_H + } // namespace XPath +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathPredicate.cpp b/Source/WebCore/xml/XPathPredicate.cpp index 143126751..ee7cccdba 100644 --- a/Source/WebCore/xml/XPathPredicate.cpp +++ b/Source/WebCore/xml/XPathPredicate.cpp @@ -47,7 +47,7 @@ Value Number::evaluate() const } StringExpression::StringExpression(String&& value) - : m_value(std::move(value)) + : m_value(WTFMove(value)) { } @@ -58,7 +58,7 @@ Value StringExpression::evaluate() const Negative::Negative(std::unique_ptr<Expression> expression) { - addSubexpression(std::move(expression)); + addSubexpression(WTFMove(expression)); } Value Negative::evaluate() const @@ -69,8 +69,8 @@ Value Negative::evaluate() const NumericOp::NumericOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) : m_opcode(opcode) { - addSubexpression(std::move(lhs)); - addSubexpression(std::move(rhs)); + addSubexpression(WTFMove(lhs)); + addSubexpression(WTFMove(rhs)); } Value NumericOp::evaluate() const @@ -98,8 +98,8 @@ Value NumericOp::evaluate() const EqTestOp::EqTestOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) : m_opcode(opcode) { - addSubexpression(std::move(lhs)); - addSubexpression(std::move(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()) { @@ -146,15 +150,17 @@ bool EqTestOp::compare(const Value& lhs, const Value& rhs) const 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()) @@ -201,8 +207,8 @@ Value EqTestOp::evaluate() const LogicalOp::LogicalOp(Opcode opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) : m_opcode(opcode) { - addSubexpression(std::move(lhs)); - addSubexpression(std::move(rhs)); + addSubexpression(WTFMove(lhs)); + addSubexpression(WTFMove(rhs)); } inline bool LogicalOp::shortCircuitOn() const @@ -223,8 +229,8 @@ Value LogicalOp::evaluate() const Union::Union(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) { - addSubexpression(std::move(lhs)); - addSubexpression(std::move(rhs)); + addSubexpression(WTFMove(lhs)); + addSubexpression(WTFMove(rhs)); } Value Union::evaluate() const @@ -236,13 +242,12 @@ Value Union::evaluate() const const NodeSet& rhsNodes = rhs.toNodeSet(); HashSet<Node*> nodes; - for (size_t i = 0; i < resultSet.size(); ++i) - nodes.add(resultSet[i]); + for (auto& result : resultSet) + nodes.add(result.get()); - for (size_t i = 0; i < rhsNodes.size(); ++i) { - Node* node = rhsNodes[i]; - if (nodes.add(node).isNewEntry) - resultSet.append(node); + for (auto& node : rhsNodes) { + if (nodes.add(node.get()).isNewEntry) + resultSet.append(node.get()); } // It would also be possible to perform a merge sort here to avoid making an unsorted result, diff --git a/Source/WebCore/xml/XPathPredicate.h b/Source/WebCore/xml/XPathPredicate.h index c657c8a55..69d15c22f 100644 --- a/Source/WebCore/xml/XPathPredicate.h +++ b/Source/WebCore/xml/XPathPredicate.h @@ -24,13 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathPredicate_h -#define XPathPredicate_h +#pragma once #include "XPathExpressionNode.h" namespace WebCore { - namespace XPath { class Number final : public Expression { @@ -38,8 +36,8 @@ namespace WebCore { explicit Number(double); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } Value m_value; }; @@ -49,8 +47,8 @@ namespace WebCore { explicit StringExpression(String&&); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::StringValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::StringValue; } Value m_value; }; @@ -60,8 +58,8 @@ namespace WebCore { explicit Negative(std::unique_ptr<Expression>); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } }; class NumericOp final : public Expression { @@ -70,8 +68,8 @@ namespace WebCore { NumericOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NumberValue; } Opcode m_opcode; }; @@ -80,10 +78,10 @@ namespace WebCore { public: enum Opcode { OP_EQ, OP_NE, OP_GT, OP_LT, OP_GE, OP_LE }; EqTestOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs); - virtual Value evaluate() const override; + Value evaluate() const override; private: - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value::Type resultType() const override { return Value::BooleanValue; } bool compare(const Value&, const Value&) const; Opcode m_opcode; @@ -95,9 +93,9 @@ namespace WebCore { LogicalOp(Opcode, std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs); private: - virtual Value::Type resultType() const override { return Value::BooleanValue; } + Value::Type resultType() const override { return Value::BooleanValue; } bool shortCircuitOn() const; - virtual Value evaluate() const override; + Value evaluate() const override; Opcode m_opcode; }; @@ -107,15 +105,12 @@ namespace WebCore { Union(std::unique_ptr<Expression>, std::unique_ptr<Expression>); private: - virtual Value evaluate() const override; - virtual Value::Type resultType() const override { return Value::NodeSetValue; } + Value evaluate() const override; + Value::Type resultType() const override { return Value::NodeSetValue; } }; bool evaluatePredicate(const Expression&); bool predicateIsContextPositionSensitive(const Expression&); - } - -} - -#endif // XPathPredicate_h + } // namespace XPath +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathResult.cpp b/Source/WebCore/xml/XPathResult.cpp index 82c6c7fa1..7508c021c 100644 --- a/Source/WebCore/xml/XPathResult.cpp +++ b/Source/WebCore/xml/XPathResult.cpp @@ -36,10 +36,8 @@ namespace WebCore { using namespace XPath; -XPathResult::XPathResult(Document* document, const Value& value) +XPathResult::XPathResult(Document& document, const Value& value) : m_value(value) - , m_nodeSetPosition(0) - , m_domTreeVersion(0) { switch (m_value.type()) { case Value::BooleanValue: @@ -55,8 +53,8 @@ XPathResult::XPathResult(Document* document, const Value& value) m_resultType = UNORDERED_NODE_ITERATOR_TYPE; m_nodeSetPosition = 0; m_nodeSet = m_value.toNodeSet(); - m_document = document; - m_domTreeVersion = document->domTreeVersion(); + m_document = &document; + m_domTreeVersion = document.domTreeVersion(); return; } ASSERT_NOT_REACHED(); @@ -66,50 +64,45 @@ XPathResult::~XPathResult() { } -void XPathResult::convertTo(unsigned short type, ExceptionCode& ec) +ExceptionOr<void> XPathResult::convertTo(unsigned short type) { switch (type) { - case ANY_TYPE: - break; - case NUMBER_TYPE: - m_resultType = type; - m_value = m_value.toNumber(); - break; - case STRING_TYPE: - m_resultType = type; - m_value = m_value.toString(); - break; - case BOOLEAN_TYPE: - m_resultType = type; - m_value = m_value.toBoolean(); - break; - case UNORDERED_NODE_ITERATOR_TYPE: - case UNORDERED_NODE_SNAPSHOT_TYPE: - case ANY_UNORDERED_NODE_TYPE: - case FIRST_ORDERED_NODE_TYPE: // This is correct - singleNodeValue() will take care of ordering. - if (!m_value.isNodeSet()) { - ec = XPathException::TYPE_ERR; - return; - } - m_resultType = type; - break; - case ORDERED_NODE_ITERATOR_TYPE: - if (!m_value.isNodeSet()) { - ec = XPathException::TYPE_ERR; - return; - } - m_nodeSet.sort(); - m_resultType = type; - break; - case ORDERED_NODE_SNAPSHOT_TYPE: - if (!m_value.isNodeSet()) { - ec = XPathException::TYPE_ERR; - return; - } - m_value.toNodeSet().sort(); - m_resultType = type; - break; + case ANY_TYPE: + break; + case NUMBER_TYPE: + m_resultType = type; + m_value = m_value.toNumber(); + break; + case STRING_TYPE: + m_resultType = type; + m_value = m_value.toString(); + break; + case BOOLEAN_TYPE: + m_resultType = type; + m_value = m_value.toBoolean(); + break; + case UNORDERED_NODE_ITERATOR_TYPE: + case UNORDERED_NODE_SNAPSHOT_TYPE: + case ANY_UNORDERED_NODE_TYPE: + case FIRST_ORDERED_NODE_TYPE: // This is correct - singleNodeValue() will take care of ordering. + if (!m_value.isNodeSet()) + return Exception { XPathException::TYPE_ERR }; + m_resultType = type; + break; + case ORDERED_NODE_ITERATOR_TYPE: + if (!m_value.isNodeSet()) + return Exception { XPathException::TYPE_ERR }; + m_nodeSet.sort(); + m_resultType = type; + break; + case ORDERED_NODE_SNAPSHOT_TYPE: + if (!m_value.isNodeSet()) + return Exception { XPathException::TYPE_ERR }; + m_value.toNodeSet().sort(); + m_resultType = type; + break; } + return { }; } unsigned short XPathResult::resultType() const @@ -117,41 +110,33 @@ unsigned short XPathResult::resultType() const return m_resultType; } -double XPathResult::numberValue(ExceptionCode& ec) const +ExceptionOr<double> XPathResult::numberValue() const { - if (resultType() != NUMBER_TYPE) { - ec = XPathException::TYPE_ERR; - return 0.0; - } + if (resultType() != NUMBER_TYPE) + return Exception { XPathException::TYPE_ERR }; return m_value.toNumber(); } -String XPathResult::stringValue(ExceptionCode& ec) const +ExceptionOr<String> XPathResult::stringValue() const { - if (resultType() != STRING_TYPE) { - ec = XPathException::TYPE_ERR; - return String(); - } + if (resultType() != STRING_TYPE) + return Exception { XPathException::TYPE_ERR }; return m_value.toString(); } -bool XPathResult::booleanValue(ExceptionCode& ec) const +ExceptionOr<bool> XPathResult::booleanValue() const { - if (resultType() != BOOLEAN_TYPE) { - ec = XPathException::TYPE_ERR; - return false; - } + if (resultType() != BOOLEAN_TYPE) + return Exception { XPathException::TYPE_ERR }; return m_value.toBoolean(); } -Node* XPathResult::singleNodeValue(ExceptionCode& ec) const +ExceptionOr<Node*> XPathResult::singleNodeValue() const { - if (resultType() != ANY_UNORDERED_NODE_TYPE && resultType() != FIRST_ORDERED_NODE_TYPE) { - ec = XPathException::TYPE_ERR; - return 0; - } - - const NodeSet& nodes = m_value.toNodeSet(); + if (resultType() != ANY_UNORDERED_NODE_TYPE && resultType() != FIRST_ORDERED_NODE_TYPE) + return Exception { XPathException::TYPE_ERR }; + + auto& nodes = m_value.toNodeSet(); if (resultType() == FIRST_ORDERED_NODE_TYPE) return nodes.firstNode(); else @@ -167,49 +152,37 @@ bool XPathResult::invalidIteratorState() const return m_document->domTreeVersion() != m_domTreeVersion; } -unsigned long XPathResult::snapshotLength(ExceptionCode& ec) const +ExceptionOr<unsigned> XPathResult::snapshotLength() const { - if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) { - ec = XPathException::TYPE_ERR; - return 0; - } + if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) + return Exception { XPathException::TYPE_ERR }; return m_value.toNodeSet().size(); } -Node* XPathResult::iterateNext(ExceptionCode& ec) +ExceptionOr<Node*> XPathResult::iterateNext() { - if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE) { - ec = XPathException::TYPE_ERR; - return 0; - } - - if (invalidIteratorState()) { - ec = INVALID_STATE_ERR; - return 0; - } - - if (m_nodeSetPosition + 1 > m_nodeSet.size()) - return 0; + if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE) + return Exception { XPathException::TYPE_ERR }; + + if (invalidIteratorState()) + return Exception { INVALID_STATE_ERR }; - Node* node = m_nodeSet[m_nodeSetPosition]; - - m_nodeSetPosition++; + if (m_nodeSetPosition >= m_nodeSet.size()) + return nullptr; - return node; + return m_nodeSet[m_nodeSetPosition++]; } -Node* XPathResult::snapshotItem(unsigned long index, ExceptionCode& ec) +ExceptionOr<Node*> XPathResult::snapshotItem(unsigned index) { - if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) { - ec = XPathException::TYPE_ERR; - return 0; - } - - const NodeSet& nodes = m_value.toNodeSet(); + if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) + return Exception { XPathException::TYPE_ERR }; + + auto& nodes = m_value.toNodeSet(); if (index >= nodes.size()) - return 0; - + return nullptr; + return nodes[index]; } diff --git a/Source/WebCore/xml/XPathResult.h b/Source/WebCore/xml/XPathResult.h index affc076b7..aea8535c3 100644 --- a/Source/WebCore/xml/XPathResult.h +++ b/Source/WebCore/xml/XPathResult.h @@ -24,65 +24,56 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathResult_h -#define XPathResult_h +#pragma once +#include "ExceptionOr.h" #include "XPathValue.h" -#include <wtf/Forward.h> -#include <wtf/RefCounted.h> namespace WebCore { - typedef int ExceptionCode; +class XPathResult : public RefCounted<XPathResult> { +public: + enum XPathResultType { + ANY_TYPE = 0, + NUMBER_TYPE = 1, + STRING_TYPE = 2, + BOOLEAN_TYPE = 3, + UNORDERED_NODE_ITERATOR_TYPE = 4, + ORDERED_NODE_ITERATOR_TYPE = 5, + UNORDERED_NODE_SNAPSHOT_TYPE = 6, + ORDERED_NODE_SNAPSHOT_TYPE = 7, + ANY_UNORDERED_NODE_TYPE = 8, + FIRST_ORDERED_NODE_TYPE = 9 + }; - class Document; - class Node; + static Ref<XPathResult> create(Document& document, const XPath::Value& value) { return adoptRef(*new XPathResult(document, value)); } + WEBCORE_EXPORT ~XPathResult(); - class XPathResult : public RefCounted<XPathResult> { - public: - enum XPathResultType { - ANY_TYPE = 0, - NUMBER_TYPE = 1, - STRING_TYPE = 2, - BOOLEAN_TYPE = 3, - UNORDERED_NODE_ITERATOR_TYPE = 4, - ORDERED_NODE_ITERATOR_TYPE = 5, - UNORDERED_NODE_SNAPSHOT_TYPE = 6, - ORDERED_NODE_SNAPSHOT_TYPE = 7, - ANY_UNORDERED_NODE_TYPE = 8, - FIRST_ORDERED_NODE_TYPE = 9 - }; - - static PassRefPtr<XPathResult> create(Document* document, const XPath::Value& value) { return adoptRef(new XPathResult(document, value)); } - ~XPathResult(); - - void convertTo(unsigned short type, ExceptionCode&); + ExceptionOr<void> convertTo(unsigned short type); - unsigned short resultType() const; + WEBCORE_EXPORT unsigned short resultType() const; - double numberValue(ExceptionCode&) const; - String stringValue(ExceptionCode&) const; - bool booleanValue(ExceptionCode&) const; - Node* singleNodeValue(ExceptionCode&) const; + WEBCORE_EXPORT ExceptionOr<double> numberValue() const; + WEBCORE_EXPORT ExceptionOr<String> stringValue() const; + WEBCORE_EXPORT ExceptionOr<bool> booleanValue() const; + WEBCORE_EXPORT ExceptionOr<Node*> singleNodeValue() const; - bool invalidIteratorState() const; - unsigned long snapshotLength(ExceptionCode&) const; - Node* iterateNext(ExceptionCode&); - Node* snapshotItem(unsigned long index, ExceptionCode&); + WEBCORE_EXPORT bool invalidIteratorState() const; + WEBCORE_EXPORT ExceptionOr<unsigned> snapshotLength() const; + WEBCORE_EXPORT ExceptionOr<Node*> iterateNext(); + WEBCORE_EXPORT ExceptionOr<Node*> snapshotItem(unsigned index); - const XPath::Value& value() const { return m_value; } + const XPath::Value& value() const { return m_value; } - private: - XPathResult(Document*, const XPath::Value&); - - XPath::Value m_value; - unsigned m_nodeSetPosition; - XPath::NodeSet m_nodeSet; // FIXME: why duplicate the node set stored in m_value? - unsigned short m_resultType; - RefPtr<Document> m_document; - uint64_t m_domTreeVersion; - }; +private: + XPathResult(Document&, const XPath::Value&); -} // namespace WebCore + XPath::Value m_value; + unsigned m_nodeSetPosition { 0 }; + XPath::NodeSet m_nodeSet; // FIXME: why duplicate the node set stored in m_value? + unsigned short m_resultType; + RefPtr<Document> m_document; + uint64_t m_domTreeVersion { 0 }; +}; -#endif // XPathResult_h +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathResult.idl b/Source/WebCore/xml/XPathResult.idl index 7a844466a..9752cf687 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. 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 @@ -18,33 +18,30 @@ */ [ - JSCustomMarkFunction, + ExportToWrappedFunction, ImplementationLacksVTable, + JSCustomMarkFunction, ] interface XPathResult { - const unsigned short ANY_TYPE = 0; - const unsigned short NUMBER_TYPE = 1; - const unsigned short STRING_TYPE = 2; - const unsigned short BOOLEAN_TYPE = 3; - const unsigned short UNORDERED_NODE_ITERATOR_TYPE = 4; - const unsigned short ORDERED_NODE_ITERATOR_TYPE = 5; - const unsigned short UNORDERED_NODE_SNAPSHOT_TYPE = 6; - const unsigned short ORDERED_NODE_SNAPSHOT_TYPE = 7; - const unsigned short ANY_UNORDERED_NODE_TYPE = 8; - const unsigned short FIRST_ORDERED_NODE_TYPE = 9; + const unsigned short ANY_TYPE = 0; + const unsigned short NUMBER_TYPE = 1; + const unsigned short STRING_TYPE = 2; + const unsigned short BOOLEAN_TYPE = 3; + const unsigned short UNORDERED_NODE_ITERATOR_TYPE = 4; + const unsigned short ORDERED_NODE_ITERATOR_TYPE = 5; + const unsigned short UNORDERED_NODE_SNAPSHOT_TYPE = 6; + const unsigned short ORDERED_NODE_SNAPSHOT_TYPE = 7; + const unsigned short ANY_UNORDERED_NODE_TYPE = 8; + const unsigned short FIRST_ORDERED_NODE_TYPE = 9; - readonly attribute unsigned short resultType; - [GetterRaisesException] readonly attribute double numberValue; - - [GetterRaisesException] readonly attribute DOMString stringValue; + readonly attribute unsigned short resultType; + [GetterMayThrowException] readonly attribute unrestricted double numberValue; + [GetterMayThrowException] readonly attribute DOMString stringValue; + [GetterMayThrowException] readonly attribute boolean booleanValue; + [GetterMayThrowException] readonly attribute Node singleNodeValue; - [GetterRaisesException] readonly attribute boolean booleanValue; + readonly attribute boolean invalidIteratorState; + [GetterMayThrowException] readonly attribute unsigned long snapshotLength; - [GetterRaisesException] readonly attribute Node singleNodeValue; - - readonly attribute boolean invalidIteratorState; - [GetterRaisesException] readonly attribute unsigned long snapshotLength; - - [RaisesException] Node iterateNext(); - [RaisesException] Node snapshotItem([Default=Undefined] optional unsigned long index); + [MayThrowException] Node iterateNext(); + [MayThrowException] Node snapshotItem(optional unsigned long index = 0); }; - diff --git a/Source/WebCore/xml/XPathStep.cpp b/Source/WebCore/xml/XPathStep.cpp index 5b813445b..c557e136e 100644 --- a/Source/WebCore/xml/XPathStep.cpp +++ b/Source/WebCore/xml/XPathStep.cpp @@ -30,6 +30,7 @@ #include "Attr.h" #include "Document.h" +#include "HTMLDocument.h" #include "HTMLElement.h" #include "NodeTraversal.h" #include "XMLNSNames.h" @@ -41,14 +42,14 @@ namespace XPath { Step::Step(Axis axis, NodeTest nodeTest) : m_axis(axis) - , m_nodeTest(std::move(nodeTest)) + , m_nodeTest(WTFMove(nodeTest)) { } Step::Step(Axis axis, NodeTest nodeTest, Vector<std::unique_ptr<Expression>> predicates) : m_axis(axis) - , m_nodeTest(std::move(nodeTest)) - , m_predicates(std::move(predicates)) + , m_nodeTest(WTFMove(nodeTest)) + , m_predicates(WTFMove(predicates)) { } @@ -62,14 +63,13 @@ void Step::optimize() // 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<std::unique_ptr<Expression>> remainingPredicates; - for (size_t i = 0; i < m_predicates.size(); ++i) { - auto& predicate = m_predicates[i]; + for (auto& predicate : m_predicates) { if ((!predicateIsContextPositionSensitive(*predicate) || m_nodeTest.m_mergedPredicates.isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates.isEmpty()) - m_nodeTest.m_mergedPredicates.append(std::move(predicate)); + m_nodeTest.m_mergedPredicates.append(WTFMove(predicate)); else - remainingPredicates.append(std::move(predicate)); + remainingPredicates.append(WTFMove(predicate)); } - m_predicates = std::move(remainingPredicates); + m_predicates = WTFMove(remainingPredicates); } void optimizeStepPair(Step& first, Step& second, bool& dropSecondStep) @@ -99,23 +99,21 @@ void optimizeStepPair(Step& first, Step& second, bool& dropSecondStep) return; first.m_axis = Step::DescendantAxis; - first.m_nodeTest = std::move(second.m_nodeTest); - first.m_predicates = std::move(second.m_predicates); + 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) { - auto& predicate = *m_predicates[i]; - if (predicateIsContextPositionSensitive(predicate) || predicate.isContextSizeSensitive()) + for (auto& predicate : m_predicates) { + if (predicateIsContextPositionSensitive(*predicate) || predicate->isContextSizeSensitive()) return false; } - for (size_t i = 0; i < m_nodeTest.m_mergedPredicates.size(); ++i) { - auto& predicate = *m_nodeTest.m_mergedPredicates[i]; - if (predicateIsContextPositionSensitive(predicate) || predicate.isContextSizeSensitive()) + for (auto& predicate : m_nodeTest.m_mergedPredicates) { + if (predicateIsContextPositionSensitive(*predicate) || predicate->isContextSizeSensitive()) return false; } @@ -130,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++) { - auto& predicate = *m_predicates[i]; - + for (auto& predicate : m_predicates) { NodeSet newNodes; if (!nodes.isSorted()) newNodes.markSorted(false); @@ -143,11 +139,11 @@ void Step::evaluate(Node& context, NodeSet& nodes) const evaluationContext.node = node; evaluationContext.size = nodes.size(); evaluationContext.position = j + 1; - if (evaluatePredicate(predicate)) + if (evaluatePredicate(*predicate)) newNodes.append(node); } - nodes = std::move(newNodes); + nodes = WTFMove(newNodes); } } @@ -157,8 +153,6 @@ 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; } @@ -201,21 +195,21 @@ inline bool nodeMatchesBasicTest(Node& node, Step::Axis axis, const Step::NodeTe // For other axes, the principal node type is element. ASSERT(primaryNodeType(axis) == Node::ELEMENT_NODE); - if (!node.isElementNode()) + if (!is<Element>(node)) return false; if (name == starAtom) 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(toHTMLElement(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(); @@ -232,11 +226,10 @@ inline bool nodeMatches(Node& node, Step::Axis axis, const Step::NodeTest& nodeT // Only the first merged predicate may depend on position. ++evaluationContext.position; - auto& mergedPredicates = nodeTest.m_mergedPredicates; - for (unsigned i = 0; i < mergedPredicates.size(); i++) { + 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. evaluationContext.node = &node; - if (!evaluatePredicate(*mergedPredicates[i])) + if (!evaluatePredicate(*predicate)) return false; } @@ -259,7 +252,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const case DescendantAxis: if (context.isAttributeNode()) // In XPath model, attribute nodes do not have children. return; - for (Node* node = context.firstChild(); node; node = NodeTraversal::next(node, &context)) { + for (Node* node = context.firstChild(); node; node = NodeTraversal::next(*node, &context)) { if (nodeMatches(*node, DescendantAxis, m_nodeTest)) nodes.append(node); } @@ -290,7 +283,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const return; } case FollowingSiblingAxis: - if (context.nodeType() == Node::ATTRIBUTE_NODE || context.nodeType() == Node::XPATH_NAMESPACE_NODE) + if (context.isAttributeNode()) return; for (Node* node = context.nextSibling(); node; node = node->nextSibling()) { if (nodeMatches(*node, FollowingSiblingAxis, m_nodeTest)) @@ -298,7 +291,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const } return; case PrecedingSiblingAxis: - if (context.nodeType() == Node::ATTRIBUTE_NODE || context.nodeType() == Node::XPATH_NAMESPACE_NODE) + if (context.isAttributeNode()) return; for (Node* node = context.previousSibling(); node; node = node->previousSibling()) { if (nodeMatches(*node, PrecedingSiblingAxis, m_nodeTest)) @@ -309,7 +302,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const case FollowingAxis: if (context.isAttributeNode()) { Node* node = static_cast<Attr&>(context).ownerElement(); - while ((node = NodeTraversal::next(node))) { + while ((node = NodeTraversal::next(*node))) { if (nodeMatches(*node, FollowingAxis, m_nodeTest)) nodes.append(node); } @@ -318,7 +311,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const 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)) { + for (Node* child = node->firstChild(); child; child = NodeTraversal::next(*child, node)) { if (nodeMatches(*child, FollowingAxis, m_nodeTest)) nodes.append(child); } @@ -333,7 +326,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const else node = &context; while (ContainerNode* parent = node->parentNode()) { - for (node = NodeTraversal::previous(node); node != parent; node = NodeTraversal::previous(node)) { + for (node = NodeTraversal::previous(*node); node != parent; node = NodeTraversal::previous(*node)) { if (nodeMatches(*node, PrecedingAxis, m_nodeTest)) nodes.append(node); } @@ -343,17 +336,17 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const 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.m_kind == NodeTest::NameTest && m_nodeTest.m_data != starAtom) { - RefPtr<Attr> attr = contextElement.getAttributeNodeNS(m_nodeTest.m_namespaceURI, m_nodeTest.m_data); + auto 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()); + nodes.append(WTFMove(attr)); } return; } @@ -362,9 +355,9 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const return; for (const Attribute& attribute : contextElement.attributesIterator()) { - RefPtr<Attr> attr = contextElement.ensureAttr(attribute.name()); - if (nodeMatches(*attr, AttributeAxis, m_nodeTest)) - nodes.append(attr.release()); + auto attr = contextElement.ensureAttr(attribute.name()); + if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest)) + nodes.append(WTFMove(attr)); } return; } @@ -380,7 +373,7 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const nodes.append(&context); if (context.isAttributeNode()) // In XPath model, attribute nodes do not have children. return; - for (Node* node = context.firstChild(); node; node = NodeTraversal::next(node, &context)) { + for (Node* node = context.firstChild(); node; node = NodeTraversal::next(*node, &context)) { if (nodeMatches(*node, DescendantOrSelfAxis, m_nodeTest)) nodes.append(node); } diff --git a/Source/WebCore/xml/XPathStep.h b/Source/WebCore/xml/XPathStep.h index c91613183..d2ef5bb00 100644 --- a/Source/WebCore/xml/XPathStep.h +++ b/Source/WebCore/xml/XPathStep.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathStep_h -#define XPathStep_h +#pragma once #include <wtf/Vector.h> #include <wtf/text/AtomicString.h> @@ -65,17 +64,17 @@ public: NodeTest(NodeTest&& other) : m_kind(other.m_kind) - , m_data(std::move(other.m_data)) - , m_namespaceURI(std::move(other.m_namespaceURI)) - , m_mergedPredicates(std::move(other.m_mergedPredicates)) + , 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 = std::move(other.m_data); - m_namespaceURI = std::move(other.m_namespaceURI); - m_mergedPredicates = std::move(other.m_mergedPredicates); + m_data = WTFMove(other.m_data); + m_namespaceURI = WTFMove(other.m_namespaceURI); + m_mergedPredicates = WTFMove(other.m_mergedPredicates); return *this; } #endif @@ -118,7 +117,4 @@ private: void optimizeStepPair(Step&, Step&, bool& dropSecondStep); } // namespace XPath - } // namespace WebCore - -#endif // XPathStep_h diff --git a/Source/WebCore/xml/XPathUtil.cpp b/Source/WebCore/xml/XPathUtil.cpp index 8d3cba79e..ad0c4754b 100644 --- a/Source/WebCore/xml/XPathUtil.cpp +++ b/Source/WebCore/xml/XPathUtil.cpp @@ -29,7 +29,6 @@ #include "ContainerNode.h" #include "TextNodeTraversal.h" -#include <wtf/text/StringBuilder.h> namespace WebCore { namespace XPath { @@ -47,11 +46,10 @@ 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->isElementNode()) - return TextNodeTraversal::contentsAsString(node); + return TextNodeTraversal::contentsAsString(*node); } return String(); } @@ -67,13 +65,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..0b05a6039 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 @@ -24,11 +24,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathUtil_h -#define XPathUtil_h +#pragma once #include <wtf/Forward.h> -#include <wtf/Vector.h> namespace WebCore { @@ -45,8 +43,6 @@ namespace WebCore { /* @return whether the given node is a valid context node */ bool isValidContextNode(Node*); - } + } // namespace XPath -} - -#endif // XPath_Util_H +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathValue.h b/Source/WebCore/xml/XPathValue.h index ff80e1cd9..d91c77d10 100644 --- a/Source/WebCore/xml/XPathValue.h +++ b/Source/WebCore/xml/XPathValue.h @@ -24,13 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathValue_h -#define XPathValue_h +#pragma once #include "XPathNodeSet.h" namespace WebCore { - namespace XPath { class Value { @@ -44,9 +42,15 @@ namespace WebCore { Value(const String& value) : m_type(StringValue), m_data(Data::create(value)) { } Value(const char* value) : m_type(StringValue), m_data(Data::create(value)) { } - explicit Value(NodeSet value) : m_type(NodeSetValue), m_data(Data::create(std::move(value))) { } - explicit Value(Node* value) : m_type(NodeSetValue), m_data(Data::create(value)) { } - explicit Value(PassRefPtr<Node> value) : m_type(NodeSetValue), m_data(Data::create(value)) { } + 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; } @@ -68,19 +72,25 @@ namespace WebCore { Value(void*) = delete; struct Data : public RefCounted<Data> { - static PassRefPtr<Data> create() { return adoptRef(new Data); } - static PassRefPtr<Data> create(const String& string) { return adoptRef(new Data(string)); } - static PassRefPtr<Data> create(NodeSet nodeSet) { return adoptRef(new Data(std::move(nodeSet))); } - static PassRefPtr<Data> create(PassRefPtr<Node> node) { return adoptRef(new Data(node)); } + 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(std::move(nodeSet)) { } - explicit Data(PassRefPtr<Node> node) : nodeSet(node) { } + 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; @@ -89,7 +99,5 @@ namespace WebCore { RefPtr<Data> m_data; }; - } -} - -#endif // XPath_Value_H + } // namespace XPath +} // namespace WebCore diff --git a/Source/WebCore/xml/XPathVariableReference.cpp b/Source/WebCore/xml/XPathVariableReference.cpp index 7f25c3ea4..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 diff --git a/Source/WebCore/xml/XPathVariableReference.h b/Source/WebCore/xml/XPathVariableReference.h index 042a18897..dc6e74edb 100644 --- a/Source/WebCore/xml/XPathVariableReference.h +++ b/Source/WebCore/xml/XPathVariableReference.h @@ -23,13 +23,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XPathVariableReference_h -#define XPathVariableReference_h +#pragma once #include "XPathExpressionNode.h" namespace WebCore { - namespace XPath { // Variable references are not used with XPathEvaluator. @@ -37,12 +35,10 @@ namespace WebCore { public: explicit VariableReference(const String& name); private: - virtual Value evaluate() const; - virtual Value::Type resultType() const { ASSERT_NOT_REACHED(); return Value::NumberValue; } + Value evaluate() const override; + Value::Type resultType() const override { ASSERT_NOT_REACHED(); return Value::NumberValue; } String m_name; }; - } -} - -#endif // XPath_VariableReference_H + } // namespace XPath +} // namespace WebCore diff --git a/Source/WebCore/xml/XSLImportRule.cpp b/Source/WebCore/xml/XSLImportRule.cpp index bfec5c85c..61de1115d 100644 --- a/Source/WebCore/xml/XSLImportRule.cpp +++ b/Source/WebCore/xml/XSLImportRule.cpp @@ -34,7 +34,7 @@ namespace WebCore { XSLImportRule::XSLImportRule(XSLStyleSheet* parent, const String& href) : m_parentStyleSheet(parent) , m_strHref(href) - , m_cachedSheet(0) + , m_cachedSheet(nullptr) , m_loading(false) { } @@ -42,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); + m_cachedSheet->removeClient(*this); } 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); @@ -61,7 +61,7 @@ void XSLImportRule::setXSLStyleSheet(const String& href, const URL& baseURL, con m_styleSheet->parseString(sheet); m_loading = false; - + if (parent) parent->checkLoaded(); } @@ -73,7 +73,7 @@ bool XSLImportRule::isLoading() void XSLImportRule::loadSheet() { - CachedResourceLoader* cachedResourceLoader = 0; + CachedResourceLoader* cachedResourceLoader = nullptr; XSLStyleSheet* rootSheet = parentStyleSheet(); @@ -84,28 +84,30 @@ void XSLImportRule::loadSheet() if (rootSheet) cachedResourceLoader = rootSheet->cachedResourceLoader(); - + String absHref = m_strHref; XSLStyleSheet* parentSheet = parentStyleSheet(); if (!parentSheet->baseURL().isNull()) // use parent styleheet's URL as the base URL 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. for (XSLStyleSheet* parentSheet = parentStyleSheet(); parentSheet; parentSheet = parentSheet->parentStyleSheet()) { if (absHref == parentSheet->baseURL().string()) return; } - - CachedResourceRequest request(ResourceRequest(cachedResourceLoader->document()->completeURL(absHref))); + if (m_cachedSheet) - m_cachedSheet->removeClient(this); - m_cachedSheet = cachedResourceLoader->requestXSLStyleSheet(request); - + m_cachedSheet->removeClient(*this); + + auto options = CachedResourceLoader::defaultCachedResourceOptions(); + options.mode = FetchOptions::Mode::SameOrigin; + m_cachedSheet = cachedResourceLoader->requestXSLStyleSheet({ResourceRequest(cachedResourceLoader->document()->completeURL(absHref)), options}); + if (m_cachedSheet) { - m_cachedSheet->addClient(this); - + m_cachedSheet->addClient(*this); + // If the imported sheet is in the cache, then setXSLStyleSheet gets called, // and the sheet even gets parsed (via parseString). In this case we have // loaded (even if our subresources haven't), so if we have a stylesheet after diff --git a/Source/WebCore/xml/XSLImportRule.h b/Source/WebCore/xml/XSLImportRule.h index 252d07fa6..f3f9ffe38 100644 --- a/Source/WebCore/xml/XSLImportRule.h +++ b/Source/WebCore/xml/XSLImportRule.h @@ -20,8 +20,7 @@ * */ -#ifndef XSLImportRule_h -#define XSLImportRule_h +#pragma once #if ENABLE(XSLT) @@ -49,7 +48,7 @@ public: void loadSheet(); private: - virtual void setXSLStyleSheet(const String& href, const URL& baseURL, const String& sheet); + void setXSLStyleSheet(const String& href, const URL& baseURL, const String& sheet) override; XSLStyleSheet* m_parentStyleSheet; String m_strHref; @@ -61,5 +60,3 @@ private: } // namespace WebCore #endif // ENABLE(XSLT) - -#endif // XSLImportRule_h diff --git a/Source/WebCore/xml/XSLStyleSheet.h b/Source/WebCore/xml/XSLStyleSheet.h index 0e0043e27..644df34bd 100644 --- a/Source/WebCore/xml/XSLStyleSheet.h +++ b/Source/WebCore/xml/XSLStyleSheet.h @@ -20,18 +20,16 @@ * */ -#ifndef XSLStyleSheet_h -#define XSLStyleSheet_h +#pragma once #if ENABLE(XSLT) #include "ProcessingInstruction.h" #include "StyleSheet.h" - #include <libxml/parser.h> #include <libxslt/transform.h> - -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> +#include <wtf/TypeCasts.h> namespace WebCore { @@ -40,24 +38,24 @@ class XSLImportRule; class XSLStyleSheet final : public StyleSheet { public: - static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& originalURL, const URL& 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)); } - static PassRefPtr<XSLStyleSheet> create(ProcessingInstruction* parentNode, const String& originalURL, const URL& 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 URL& 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 URL& 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(); @@ -74,7 +72,7 @@ public: CachedResourceLoader* cachedResourceLoader(); Document* ownerDocument(); - virtual XSLStyleSheet* parentStyleSheet() const override { return m_parentStyleSheet; } + XSLStyleSheet* parentStyleSheet() const override { return m_parentStyleSheet; } void setParentStyleSheet(XSLStyleSheet* parent); xmlDocPtr document(); @@ -86,41 +84,46 @@ public: 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 void clearOwnerNode() override { m_ownerNode = 0; } - virtual URL baseURL() const override { return m_finalURL; } - virtual bool isLoading() const override; + String type() const override { return "text/xml"; } + bool disabled() const override { return m_isDisabled; } + void setDisabled(bool b) override { m_isDisabled = b; } + Node* ownerNode() const override { return m_ownerNode; } + String href() const override { return m_originalURL; } + String title() const override { return emptyString(); } - virtual bool isXSLStyleSheet() const override { return true; } + void clearOwnerNode() override { m_ownerNode = nullptr; } + URL baseURL() const override { return m_finalURL; } + bool isLoading() const override; private: XSLStyleSheet(Node* parentNode, const String& originalURL, const URL& finalURL, bool embedded); XSLStyleSheet(XSLImportRule* parentImport, const String& originalURL, const URL& finalURL); - + + bool isXSLStyleSheet() const override { return true; } + + void clearXSLStylesheetDocument(); + Node* m_ownerNode; String m_originalURL; URL m_finalURL; - bool m_isDisabled; + bool m_isDisabled { false }; Vector<std::unique_ptr<XSLImportRule>> m_children; bool m_embedded; bool m_processed; - xmlDocPtr m_stylesheetDoc; - bool m_stylesheetDocTaken; - - XSLStyleSheet* m_parentStyleSheet; + xmlDocPtr m_stylesheetDoc { nullptr }; + bool m_stylesheetDocTaken { false }; + bool m_compilationFailed { false }; + + XSLStyleSheet* m_parentStyleSheet { nullptr }; }; } // namespace WebCore -#endif // ENABLE(XSLT) +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::XSLStyleSheet) + static bool isType(const WebCore::StyleSheet& styleSheet) { return styleSheet.isXSLStyleSheet(); } +SPECIALIZE_TYPE_TRAITS_END() -#endif // XSLStyleSheet_h +#endif // ENABLE(XSLT) diff --git a/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp index 28a430446..deeaf5a4e 100644 --- a/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp +++ b/Source/WebCore/xml/XSLStyleSheetLibxslt.cpp @@ -27,21 +27,21 @@ #include "Document.h" #include "Frame.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 <libxml/uri.h> #include <libxslt/xsltutils.h> +#include <wtf/CheckedArithmetic.h> -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) #include "SoftLinking.h" #endif -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) 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)) @@ -52,46 +52,39 @@ SOFT_LINK(libxslt, xsltLoadStylesheetPI, xsltStylesheetPtr, (xmlDocPtr doc), (do namespace WebCore { XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const URL& finalURL) - : m_ownerNode(0) + : 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_stylesheetDocTaken(false) - , m_parentStyleSheet(parentRule ? parentRule->parentStyleSheet() : 0) { + if (parentRule) + m_parentStyleSheet = parentRule->parentStyleSheet(); } 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_stylesheetDocTaken(false) - , m_parentStyleSheet(0) { } XSLStyleSheet::~XSLStyleSheet() { - if (!m_stylesheetDocTaken) - xmlFreeDoc(m_stylesheetDoc); + clearXSLStylesheetDocument(); - for (unsigned i = 0; i < m_children.size(); ++i) { - ASSERT(m_children.at(i)->parentStyleSheet() == this); - m_children.at(i)->setParentStyleSheet(0); + for (auto& import : m_children) { + ASSERT(import->parentStyleSheet() == this); + import->setParentStyleSheet(nullptr); } } bool XSLStyleSheet::isLoading() const { - for (unsigned i = 0; i < m_children.size(); ++i) { - if (m_children.at(i)->isLoading()) + for (auto& import : m_children) { + if (import->isLoading()) return true; } return false; @@ -110,26 +103,36 @@ void XSLStyleSheet::checkLoaded() xmlDocPtr XSLStyleSheet::document() { if (m_embedded && ownerDocument() && ownerDocument()->transformSource()) - return (xmlDocPtr)ownerDocument()->transformSource()->platformSource(); + return ownerDocument()->transformSource()->platformSource(); return m_stylesheetDoc; } void XSLStyleSheet::clearDocuments() { - m_stylesheetDoc = 0; - for (unsigned i = 0; i < m_children.size(); ++i) { - XSLImportRule* import = m_children.at(i).get(); + clearXSLStylesheetDocument(); + + for (auto& import : m_children) { if (import->styleSheet()) import->styleSheet()->clearDocuments(); } } +void XSLStyleSheet::clearXSLStylesheetDocument() +{ + if (!m_stylesheetDocTaken) { + if (m_stylesheetDoc) + xmlFreeDoc(m_stylesheetDoc); + } else + m_stylesheetDocTaken = false; + m_stylesheetDoc = nullptr; +} + CachedResourceLoader* XSLStyleSheet::cachedResourceLoader() { Document* document = ownerDocument(); if (!document) - return 0; - return document->cachedResourceLoader(); + return nullptr; + return &document->cachedResourceLoader(); } bool XSLStyleSheet::parseString(const String& string) @@ -137,25 +140,28 @@ bool XSLStyleSheet::parseString(const String& string) // Parse in a single chunk into an xmlDocPtr const UChar BOM = 0xFEFF; const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); - if (!m_stylesheetDocTaken) - xmlFreeDoc(m_stylesheetDoc); - m_stylesheetDocTaken = false; + clearXSLStylesheetDocument(); - PageConsole* console = 0; + PageConsoleClient* console = nullptr; Frame* frame = ownerDocument()->frame(); if (frame && frame->page()) console = &frame->page()->console(); XMLDocumentParserScope scope(cachedResourceLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console); - const char* buffer = reinterpret_cast<const char*>(string.deprecatedCharacters()); - int size = string.length() * sizeof(UChar); + auto upconvertedCharacters = StringView(string).upconvertedCharacters(); + const char* buffer = reinterpret_cast<const char*>(upconvertedCharacters.get()); + Checked<unsigned, RecordOverflow> unsignedSize = string.length(); + unsignedSize *= sizeof(UChar); + if (unsignedSize.hasOverflowed() || unsignedSize.unsafeGet() > std::numeric_limits<int>::max()) + return false; + int size = static_cast<int>(unsignedSize.unsafeGet()); xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buffer, size); if (!ctxt) - return 0; + return false; - if (m_parentStyleSheet) { + if (m_parentStyleSheet && m_parentStyleSheet->m_stylesheetDoc) { // The XSL transform may leave the newly-transformed document // with references to the symbol dictionaries of the style sheet // and any of its children. XML document disposal can corrupt memory @@ -175,7 +181,7 @@ bool XSLStyleSheet::parseString(const String& string) loadChildSheets(); - return m_stylesheetDoc; + return !!m_stylesheetDoc; } void XSLStyleSheet::loadChildSheets() @@ -234,9 +240,8 @@ void XSLStyleSheet::loadChildSheets() void XSLStyleSheet::loadChildSheet(const String& href) { auto childRule = std::make_unique<XSLImportRule>(this, href); - XSLImportRule* c = childRule.get(); m_children.append(childRule.release()); - c->loadSheet(); + m_children.last()->loadSheet(); } xsltStylesheetPtr XSLStyleSheet::compileStyleSheet() @@ -245,12 +250,20 @@ 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_stylesheetDoc); ASSERT(!m_stylesheetDocTaken); xsltStylesheetPtr result = xsltParseStylesheetDoc(m_stylesheetDoc); if (result) m_stylesheetDocTaken = true; + else + m_compilationFailed = true; return result; } @@ -272,8 +285,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/XSLTExtensions.cpp b/Source/WebCore/xml/XSLTExtensions.cpp index 069ddd81b..a151594ab 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(GTK) #include "SoftLinking.h" #endif -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) 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/XSLTExtensions.h b/Source/WebCore/xml/XSLTExtensions.h index 4e4224f95..575c01c0f 100644 --- a/Source/WebCore/xml/XSLTExtensions.h +++ b/Source/WebCore/xml/XSLTExtensions.h @@ -23,8 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XSLTExtensions_h -#define XSLTExtensions_h +#pragma once #if ENABLE(XSLT) @@ -34,7 +33,6 @@ namespace WebCore { void registerXSLTExtensions(xsltTransformContextPtr ctxt); -} +} // namespace WebCore -#endif -#endif +#endif // ENABLE(XSLT) diff --git a/Source/WebCore/xml/XSLTProcessor.cpp b/Source/WebCore/xml/XSLTProcessor.cpp index cf0c15ab6..a90b96500 100644 --- a/Source/WebCore/xml/XSLTProcessor.cpp +++ b/Source/WebCore/xml/XSLTProcessor.cpp @@ -33,16 +33,14 @@ #include "Frame.h" #include "FrameLoader.h" #include "FrameView.h" -#include "HTMLBodyElement.h" #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> -#include <wtf/Vector.h> namespace WebCore { @@ -67,7 +65,7 @@ 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) { Ref<Document> ownerDocument(sourceNode->document()); @@ -76,10 +74,10 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc RefPtr<Document> result; if (sourceMIMEType == "text/plain") { - result = Document::create(frame, sourceIsDocument ? ownerDocument->url() : URL()); + result = XMLDocument::createXHTML(frame, sourceIsDocument ? ownerDocument->url() : URL()); transformTextStringToXHTMLDocumentString(documentSource); } else - result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : URL(), 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 +88,43 @@ 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->setStrictMixedContentMode(oldDocument->isStrictMixedContentMode()); result->contentSecurityPolicy()->copyStateFrom(oldDocument->contentSecurityPolicy()); + result->contentSecurityPolicy()->copyUpgradeInsecureRequestStateFrom(*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; + 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; @@ -135,12 +135,15 @@ PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode resultMIMEType = "text/html"; if (!transformToString(*sourceNode, resultMIMEType, resultString, resultEncoding)) - return 0; - return createFragmentForTransformToFragment(resultString, resultMIMEType, outputDoc); + return nullptr; + return createFragmentForTransformToFragment(*outputDoc, resultString, resultMIMEType); } void XSLTProcessor::setParameter(const String& /*namespaceURI*/, const String& localName, const String& value) { + if (localName.isNull() || value.isNull()) + return; + // FIXME: namespace support? // should make a QualifiedName here but we'd have to expose the impl m_parameters.set(localName, value); @@ -148,6 +151,9 @@ void XSLTProcessor::setParameter(const String& /*namespaceURI*/, const String& l String XSLTProcessor::getParameter(const String& /*namespaceURI*/, const String& localName) const { + if (localName.isNull()) + return { }; + // FIXME: namespace support? // should make a QualifiedName here but we'd have to expose the impl return m_parameters.get(localName); @@ -155,14 +161,17 @@ String XSLTProcessor::getParameter(const String& /*namespaceURI*/, const String& void XSLTProcessor::removeParameter(const String& /*namespaceURI*/, const String& localName) { + if (localName.isNull()) + return; + // FIXME: namespace support? m_parameters.remove(localName); } 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 518e1e2af..0792f1ae2 100644 --- a/Source/WebCore/xml/XSLTProcessor.h +++ b/Source/WebCore/xml/XSLTProcessor.h @@ -20,18 +20,16 @@ * */ -#ifndef XSLTProcessor_h -#define XSLTProcessor_h +#pragma once #if ENABLE(XSLT) #include "Node.h" #include "XSLStyleSheet.h" -#include <wtf/HashMap.h> -#include <wtf/text/StringHash.h> - #include <libxml/parserInternals.h> #include <libxslt/documents.h> +#include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> namespace WebCore { @@ -41,21 +39,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; } + void setXSLStyleSheet(RefPtr<XSLStyleSheet>&& styleSheet) { m_stylesheet = WTFMove(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); + 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; @@ -80,7 +78,6 @@ private: ParameterMap m_parameters; }; -} +} // namespace WebCore -#endif -#endif +#endif // ENABLE(XSLT) diff --git a/Source/WebCore/xml/XSLTProcessor.idl b/Source/WebCore/xml/XSLTProcessor.idl index 9dd659381..25129861a 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. * @@ -35,17 +35,14 @@ Constructor, ImplementationLacksVTable, ] interface XSLTProcessor { - - void importStylesheet([Default=Undefined] optional Node stylesheet); - DocumentFragment transformToFragment([Default=Undefined] optional Node source, [Default=Undefined] optional Document docVal); - Document transformToDocument([Default=Undefined] optional Node source); + void importStylesheet(optional Node? stylesheet = null); + DocumentFragment transformToFragment(optional Node? source = null, optional Document? docVal = null); + Document transformToDocument(optional Node? source = null); - [Custom] void setParameter(DOMString namespaceURI, DOMString localName, DOMString value); - [Custom, TreatReturnedNullStringAs=Undefined] DOMString getParameter(DOMString namespaceURI, DOMString localName); - [Custom] void removeParameter(DOMString namespaceURI, DOMString localName); + void setParameter(DOMString? namespaceURI, DOMString? localName, DOMString? value); + DOMString? getParameter(DOMString? namespaceURI, DOMString? localName); + void removeParameter(DOMString? namespaceURI, DOMString? localName); void clearParameters(); void reset(); - }; - diff --git a/Source/WebCore/xml/XSLTProcessorLibxslt.cpp b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp index 80931181f..120a90141 100644 --- a/Source/WebCore/xml/XSLTProcessorLibxslt.cpp +++ b/Source/WebCore/xml/XSLTProcessorLibxslt.cpp @@ -30,7 +30,7 @@ #include "Document.h" #include "Frame.h" #include "Page.h" -#include "PageConsole.h" +#include "PageConsoleClient.h" #include "ResourceError.h" #include "ResourceRequest.h" #include "ResourceResponse.h" @@ -45,11 +45,10 @@ #include <libxslt/variables.h> #include <libxslt/xsltutils.h> #include <wtf/Assertions.h> -#include <wtf/Vector.h> #include <wtf/text/StringBuffer.h> #include <wtf/unicode/UTF8.h> -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) #include "SoftLinking.h" SOFT_LINK_LIBRARY(libxslt); @@ -79,32 +78,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, @@ -123,19 +122,23 @@ static xmlDocPtr docLoaderFunc(const xmlChar* uri, ResourceError error; ResourceResponse response; - Vector<char> data; + RefPtr<SharedBuffer> data; - bool requestAllowed = globalCachedResourceLoader->frame() && globalCachedResourceLoader->document()->securityOrigin()->canRequest(url); + 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, ClientCredentialPolicy::MayAskClientForCredentials, 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(); @@ -144,7 +147,7 @@ static xmlDocPtr docLoaderFunc(const xmlChar* uri, // 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); @@ -192,7 +195,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; @@ -221,13 +224,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; } @@ -268,11 +270,11 @@ static inline xmlDocPtr xmlDocPtrFromNode(Node& sourceNode, bool& shouldDelete) 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(); + sourceDoc = ownerDocument->transformSource()->platformSource(); if (!sourceDoc) { - sourceDoc = (xmlDocPtr)xmlDocPtrForString(ownerDocument->cachedResourceLoader(), createMarkup(sourceNode), + sourceDoc = xmlDocPtrForString(ownerDocument->cachedResourceLoader(), createMarkup(sourceNode), sourceIsDocument ? ownerDocument->url().string() : String()); shouldDelete = sourceDoc; } @@ -285,7 +287,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"; @@ -302,11 +304,11 @@ bool XSLTProcessor::transformToString(Node& sourceNode, String& mimeType, String { 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(); @@ -365,7 +367,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/XSLTUnicodeSort.cpp b/Source/WebCore/xml/XSLTUnicodeSort.cpp index a8537340a..142e960a3 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,15 @@ #include <libxslt/templates.h> #include <libxslt/xsltutils.h> -#include <wtf/text/WTFString.h> +#include <wtf/StringExtras.h> +#include <wtf/Vector.h> #include <wtf/unicode/Collator.h> -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) #include "SoftLinking.h" #endif -#if PLATFORM(MAC) +#if OS(DARWIN) && !PLATFORM(GTK) SOFT_LINK_LIBRARY(libxslt) SOFT_LINK(libxslt, xsltComputeSortResult, xmlXPathObjectPtr*, (xsltTransformContextPtr ctxt, xmlNodePtr sort), (ctxt, sort)) @@ -52,15 +53,19 @@ void xsltTransformErrorTrampoline(xsltTransformContextPtr context, xsltStyleshee { va_list args; va_start(args, message); - char* messageWithArgs; - vasprintf(&messageWithArgs, message, args); + + va_list preflightArgs; + va_copy(preflightArgs, args); + size_t stringLength = vsnprintf(nullptr, 0, message, preflightArgs); + va_end(preflightArgs); + + Vector<char, 1024> buffer(stringLength + 1); + vsnprintf(buffer.data(), stringLength + 1, message, args); va_end(args); static void (*xsltTransformErrorPointer)(xsltTransformContextPtr, xsltStylesheetPtr, xmlNodePtr, const char*, ...) WTF_ATTRIBUTE_PRINTF(4, 5) = reinterpret_cast<void (*)(xsltTransformContextPtr, xsltStylesheetPtr, xmlNodePtr, const char*, ...)>(dlsym(libxsltLibrary(), "xsltTransformError")); - xsltTransformErrorPointer(context, style, node, "%s", messageWithArgs); - - free(messageWithArgs); + xsltTransformErrorPointer(context, style, node, "%s", buffer.data()); } #define xsltTransformError xsltTransformErrorTrampoline @@ -162,10 +167,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 +199,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.deprecatedCharacters(), str1.length(), str2.deprecatedCharacters(), 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 +251,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.deprecatedCharacters(), str1.length(), str2.deprecatedCharacters(), 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..1c688d44a 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. * @@ -25,8 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XSLTUnicodeSort_h -#define XSLTUnicodeSort_h + +#pragma once #if ENABLE(XSLT) @@ -34,9 +34,8 @@ namespace WebCore { - void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr* sorts, int nbsorts); +void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr* sorts, int nbsorts); -} +} // namespace WebCore -#endif -#endif +#endif // ENABLE(XSLT) diff --git a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h index 62780c7dc..76862683f 100644 --- a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h +++ b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h @@ -24,27 +24,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CharacterReferenceParserInlines_h -#define CharacterReferenceParserInlines_h +#pragma once #include <wtf/text/StringBuilder.h> namespace WebCore { -inline bool isHexDigit(UChar cc) +inline void unconsumeCharacters(SegmentedString& source, StringBuilder& consumedCharacters) { - 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(consumedCharacters.toString()); } template <typename ParserFunctions> @@ -54,7 +42,7 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh ASSERT(!notEnoughCharacters); ASSERT(decodedCharacter.isEmpty()); - enum EntityState { + enum { Initial, Number, MaybeHexLowerCaseX, @@ -62,105 +50,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.currentCharacter(); + 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(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(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(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.advancePastNonNewline(); + 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.advancePastNonNewline(); + 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.advancePastNonNewline(); } ASSERT(source.isEmpty()); notEnoughCharacters = true; @@ -168,6 +152,4 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh return false; } -} - -#endif // CharacterReferenceParserInlines_h +} // namespace WebCore diff --git a/Source/WebCore/xml/parser/MarkupTokenizerInlines.h b/Source/WebCore/xml/parser/MarkupTokenizerInlines.h index e0b3156bb..58ef106ae 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-2016 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ * Copyright (C) 2010 Google, Inc. All Rights Reserved. * @@ -25,71 +25,72 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MarkupTokenizerInlines_h -#define MarkupTokenizerInlines_h +#pragma once -#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: { \ + constexpr auto currentState = stateName; \ + UNUSED_PARAM(currentState); -inline void advanceStringAndASSERT(SegmentedString& source, const char* expectedCharacters) -{ - while (*expectedCharacters) - source.advanceAndASSERT(*expectedCharacters++); -} +#define END_STATE() \ + ASSERT_NOT_REACHED(); \ + break; \ + } -#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 BEGIN_STATE(prefix, stateName) case prefix::stateName: stateName: -#define END_STATE() ASSERT_NOT_REACHED(); break; - -// 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; \ +#define RETURN_IN_CURRENT_STATE(expression) \ + do { \ + m_state = currentState; \ + return expression; \ } 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 "reconsume the current input character in the <mumble> state." +#define RECONSUME_IN(newState) \ + do { \ + 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; \ +// 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) +#define ADVANCE_PAST_NON_NEWLINE_TO(newState) \ + do { \ + if (!m_preprocessor.advancePastNonNewline(source, isNullCharacterSkippingState(newState))) { \ + m_state = newState; \ + return haveBufferedCharacterToken(); \ + } \ + character = m_preprocessor.nextInputCharacter(); \ + goto newState; \ } while (false) -} +// 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) -#endif // MarkupTokenizerInlines_h +} // namespace WebCore diff --git a/Source/WebCore/xml/parser/XMLDocumentParser.cpp b/Source/WebCore/xml/parser/XMLDocumentParser.cpp index 547ffcb05..4cbccd970 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParser.cpp +++ b/Source/WebCore/xml/parser/XMLDocumentParser.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005-2017 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) @@ -27,9 +27,7 @@ #include "XMLDocumentParser.h" #include "CDATASection.h" -#include "CachedScript.h" #include "Comment.h" -#include "CachedResourceLoader.h" #include "Document.h" #include "DocumentFragment.h" #include "DocumentType.h" @@ -40,12 +38,16 @@ #include "HTMLNames.h" #include "HTMLStyleElement.h" #include "ImageLoader.h" +#include "PendingScript.h" #include "ProcessingInstruction.h" #include "ResourceError.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include "SVGNames.h" +#include "SVGStyleElement.h" #include "ScriptElement.h" #include "ScriptSourceCode.h" +#include "StyleScope.h" #include "TextResourceDecoder.h" #include "TreeDepthLimit.h" #include <wtf/Ref.h> @@ -53,11 +55,6 @@ #include <wtf/Threading.h> #include <wtf/Vector.h> -#if ENABLE(SVG) -#include "SVGNames.h" -#include "SVGStyleElement.h" -#endif - namespace WebCore { using namespace HTMLNames; @@ -91,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) @@ -103,14 +100,15 @@ void XMLDocumentParser::clearCurrentNodeStack() } } -void XMLDocumentParser::insert(const SegmentedString&) +void XMLDocumentParser::insert(SegmentedString&&) { ASSERT_NOT_REACHED(); } -void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) +void XMLDocumentParser::append(RefPtr<StringImpl>&& inputSource) { - SegmentedString source(inputSource); + String source { WTFMove(inputSource) }; + if (m_sawXSLTransform || !m_sawFirstElement) m_originalSourceForTransform.append(source); @@ -122,16 +120,16 @@ void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) return; } - doWrite(source.toString()); + doWrite(source); - // 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) { if (!m_xmlErrors) - m_xmlErrors = std::make_unique<XMLErrors>(document()); + m_xmlErrors = std::make_unique<XMLErrors>(*document()); m_xmlErrors->handleError(type, m, position); if (type != XMLErrors::warning) m_sawError = true; @@ -139,12 +137,15 @@ void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* m, Te stopParsing(); } -void XMLDocumentParser::enterText() +void XMLDocumentParser::createLeafTextNode() { + if (m_leafTextNode) + return; + ASSERT(m_bufferedText.size() == 0); ASSERT(!m_leafTextNode); m_leafTextNode = Text::create(m_currentNode->document(), ""); - m_currentNode->parserAppendChild(m_leafTextNode.get()); + m_currentNode->parserAppendChild(*m_leafTextNode); } static inline String toString(const xmlChar* string, size_t size) @@ -152,20 +153,23 @@ static inline String toString(const xmlChar* string, size_t size) return String::fromUTF8(reinterpret_cast<const char*>(string), size); } - -void XMLDocumentParser::exitText() +bool XMLDocumentParser::updateLeafTextNode() { if (isStopped()) - return; + return false; if (!m_leafTextNode) - return; + return true; + + // This operation might fire mutation event, see below. + m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size())); + m_bufferedText = { }; - m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size()), IGNORE_EXCEPTION); - Vector<xmlChar> empty; - m_bufferedText.swap(empty); + 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() @@ -191,11 +195,13 @@ void XMLDocumentParser::end() if (m_parserPaused) return; - if (m_sawError) + if (m_sawError) { insertErrorMessageBlock(); - else { - exitText(); - document()->styleResolverChanged(RecalcStyleImmediately); + if (isDetached()) // Inserting an error message may have ran arbitrary scripts. + return; + } else { + updateLeafTextNode(); + document()->styleScope().didChangeStyleSheetEnvironment(); } if (isParsing()) @@ -211,6 +217,8 @@ void XMLDocumentParser::finish() // makes sense to call any methods on DocumentParser once it's been stopped. // However, FrameLoader::stop calls DocumentParser::finish unconditionally. + Ref<XMLDocumentParser> protectedThis(*this); + if (m_parserPaused) m_finishCalled = true; else @@ -223,35 +231,17 @@ void XMLDocumentParser::insertErrorMessageBlock() m_xmlErrors->insertErrorMessageBlock(); } -void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) +void XMLDocumentParser::notifyFinished(PendingScript& pendingScript) { - ASSERT_UNUSED(unusedResource, unusedResource == m_pendingScript); - ASSERT(m_pendingScript->accessCount() > 0); - - ScriptSourceCode sourceCode(m_pendingScript.get()); - bool errorOccurred = m_pendingScript->errorOccurred(); - bool wasCanceled = m_pendingScript->wasCanceled(); - - m_pendingScript->removeClient(this); - m_pendingScript = 0; - - RefPtr<Element> e = m_scriptElement; - m_scriptElement = 0; - - ScriptElement* scriptElement = toScriptElementIfPossible(e.get()); - ASSERT(scriptElement); + ASSERT(&pendingScript == m_pendingScript.get()); // JavaScript can detach this parser, make sure it's kept alive even if detached. - Ref<XMLDocumentParser> protect(*this); - - if (errorOccurred) - scriptElement->dispatchErrorEvent(); - else if (!wasCanceled) { - scriptElement->executeScript(sourceCode); - scriptElement->dispatchLoadEvent(); - } + Ref<XMLDocumentParser> protectedThis(*this); - m_scriptElement = 0; + m_pendingScript = nullptr; + pendingScript.clearClient(); + + pendingScript.element().executePendingScript(pendingScript); if (!isDetached() && !m_requestingScript) resumeParsing(); @@ -264,6 +254,8 @@ bool XMLDocumentParser::isWaitingForScripts() const void XMLDocumentParser::pauseParsing() { + ASSERT(!m_parserPaused); + if (m_parsingFragment) return; @@ -278,17 +270,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))) { + 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 7b7e22038..161fd5db8 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParser.h +++ b/Source/WebCore/xml/parser/XMLDocumentParser.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2005-2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) @@ -22,180 +22,174 @@ * */ -#ifndef XMLDocumentParser_h -#define XMLDocumentParser_h +#pragma once -#include "CachedResourceClient.h" -#include "CachedResourceHandle.h" #include "FragmentScriptingPermission.h" +#include "PendingScriptClient.h" #include "ScriptableDocumentParser.h" #include "SegmentedString.h" #include "XMLErrors.h" +#include <libxml/tree.h> +#include <libxml/xmlstring.h> #include <wtf/HashMap.h> #include <wtf/text/AtomicStringHash.h> #include <wtf/text/CString.h> -#include <libxml/tree.h> -#include <libxml/xmlstring.h> - namespace WebCore { class ContainerNode; -class CachedScript; class CachedResourceLoader; class DocumentFragment; -class Document; class Element; class FrameView; class PendingCallbacks; class Text; - class XMLParserContext : public RefCounted<XMLParserContext> { - public: - static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk); - static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData); - ~XMLParserContext(); - xmlParserCtxtPtr context() const { return m_context; } +class XMLParserContext : public RefCounted<XMLParserContext> { +public: + static RefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk); + static Ref<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData); + ~XMLParserContext(); + xmlParserCtxtPtr context() const { return m_context; } + +private: + XMLParserContext(xmlParserCtxtPtr context) + : m_context(context) + { + } + xmlParserCtxtPtr m_context; +}; + +class XMLDocumentParser final : public ScriptableDocumentParser, public PendingScriptClient { + WTF_MAKE_FAST_ALLOCATED; +public: + static Ref<XMLDocumentParser> create(Document& document, FrameView* view) + { + return adoptRef(*new XMLDocumentParser(document, view)); + } + static Ref<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy) + { + return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy)); + } - private: - XMLParserContext(xmlParserCtxtPtr context) - : m_context(context) - { - } - xmlParserCtxtPtr m_context; - }; + ~XMLDocumentParser(); - class XMLDocumentParser : public ScriptableDocumentParser, public CachedResourceClient { - WTF_MAKE_FAST_ALLOCATED; - public: - static PassRefPtr<XMLDocumentParser> create(Document& document, FrameView* view) - { - return adoptRef(new XMLDocumentParser(document, view)); - } - static PassRefPtr<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy) - { - return adoptRef(new XMLDocumentParser(fragment, element, parserContentPolicy)); - } + // Exposed for callbacks: + void handleError(XMLErrors::ErrorType, const char* message, TextPosition); - ~XMLDocumentParser(); + void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; } + bool isXHTMLDocument() const { return m_isXHTMLDocument; } - // Exposed for callbacks: - void handleError(XMLErrors::ErrorType, const char* message, TextPosition); + static bool parseDocumentFragment(const String&, DocumentFragment&, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent); - void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; } - bool isXHTMLDocument() const { return m_isXHTMLDocument; } + // Used by XMLHttpRequest to check if the responseXML was well formed. + bool wellFormed() const final { return !m_sawError; } - static bool parseDocumentFragment(const String&, DocumentFragment&, Element* parent = 0, ParserContentPolicy = AllowScriptingContent); + static bool supportsXMLVersion(const String&); - // Used by the XMLHttpRequest to check if the responseXML was well formed. - virtual bool wellFormed() const { return !m_sawError; } +private: + explicit XMLDocumentParser(Document&, FrameView* = nullptr); + XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy); - TextPosition textPosition() const; + void insert(SegmentedString&&) final; + void append(RefPtr<StringImpl>&&) final; + void finish() final; + bool isWaitingForScripts() const final; + void stopParsing() final; + void detach() final; - static bool supportsXMLVersion(const String&); + TextPosition textPosition() const final; + bool shouldAssociateConsoleMessagesWithTextPosition() const final; - private: - XMLDocumentParser(Document&, FrameView* = 0); - XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy); + void notifyFinished(PendingScript&) final; - // 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(); + void end(); - // from CachedResourceClient - virtual void notifyFinished(CachedResource*); + void pauseParsing(); + void resumeParsing(); - void end(); + bool appendFragmentSource(const String&); - void pauseParsing(); - void resumeParsing(); +public: + // Callbacks from parser SAX, and other functions needed inside + // the parser implementation, but outside this class. - bool appendFragmentSource(const String&); + 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 numNamespaces, const xmlChar** namespaces, + int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes); + void endElementNs(); + void characters(const xmlChar*, int length); + void processingInstruction(const xmlChar* target, const xmlChar* data); + void cdataBlock(const xmlChar*, int length); + void comment(const xmlChar*); + void startDocument(const xmlChar* version, const xmlChar* encoding, int standalone); + void internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID); + void endDocument(); -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, - const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes); - void endElementNs(); - void characters(const xmlChar* s, int len); - void processingInstruction(const xmlChar* target, const xmlChar* data); - void cdataBlock(const xmlChar* s, int len); - void comment(const xmlChar* s); - void startDocument(const xmlChar* version, const xmlChar* encoding, int standalone); - void internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID); - void endDocument(); + bool isParsingEntityDeclaration() const { return m_isParsingEntityDeclaration; } + void setIsParsingEntityDeclaration(bool value) { m_isParsingEntityDeclaration = value; } - bool isParsingEntityDeclaration() const { return m_isParsingEntityDeclaration; } - void setIsParsingEntityDeclaration(bool value) { m_isParsingEntityDeclaration = value; } + int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; } + void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; } - int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; } - void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; } +private: + void initializeParserContext(const CString& chunk = CString()); - private: - void initializeParserContext(const CString& chunk = CString()); + void pushCurrentNode(ContainerNode*); + void popCurrentNode(); + void clearCurrentNodeStack(); - void pushCurrentNode(ContainerNode*); - void popCurrentNode(); - void clearCurrentNodeStack(); + void insertErrorMessageBlock(); - void insertErrorMessageBlock(); + void createLeafTextNode(); + bool updateLeafTextNode(); - void enterText(); - void exitText(); + void doWrite(const String&); + void doEnd(); - void doWrite(const String&); - void doEnd(); + xmlParserCtxtPtr context() const { return m_context ? m_context->context() : nullptr; }; - FrameView* m_view; + FrameView* m_view { nullptr }; - SegmentedString m_originalSourceForTransform; + SegmentedString m_originalSourceForTransform; - xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; }; - RefPtr<XMLParserContext> m_context; - std::unique_ptr<PendingCallbacks> m_pendingCallbacks; - Vector<xmlChar> m_bufferedText; - int m_depthTriggeringEntityExpansion; - bool m_isParsingEntityDeclaration; + RefPtr<XMLParserContext> m_context; + std::unique_ptr<PendingCallbacks> m_pendingCallbacks; + Vector<xmlChar> m_bufferedText; + int m_depthTriggeringEntityExpansion { -1 }; + bool m_isParsingEntityDeclaration { false }; - ContainerNode* m_currentNode; - Vector<ContainerNode*> m_currentNodeStack; + ContainerNode* m_currentNode { nullptr }; + Vector<ContainerNode*> m_currentNodeStack; - RefPtr<Text> m_leafTextNode; + RefPtr<Text> m_leafTextNode; - bool m_sawError; - bool m_sawCSS; - bool m_sawXSLTransform; - bool m_sawFirstElement; - bool m_isXHTMLDocument; - bool m_parserPaused; - bool m_requestingScript; - bool m_finishCalled; + bool m_sawError { false }; + bool m_sawCSS { false }; + bool m_sawXSLTransform { false }; + bool m_sawFirstElement { false }; + bool m_isXHTMLDocument { false }; + bool m_parserPaused { false }; + bool m_requestingScript { false }; + bool m_finishCalled { false }; - std::unique_ptr<XMLErrors> m_xmlErrors; + std::unique_ptr<XMLErrors> m_xmlErrors; - CachedResourceHandle<CachedScript> m_pendingScript; - RefPtr<Element> m_scriptElement; - TextPosition m_scriptStartPosition; + RefPtr<PendingScript> m_pendingScript; + TextPosition m_scriptStartPosition; - bool m_parsingFragment; - AtomicString m_defaultNamespaceURI; + bool m_parsingFragment { false }; + AtomicString m_defaultNamespaceURI; - typedef HashMap<AtomicString, AtomicString> PrefixForNamespaceMap; - PrefixForNamespaceMap m_prefixToNamespaceMap; - SegmentedString m_pendingSrc; - }; + HashMap<AtomicString, AtomicString> m_prefixToNamespaceMap; + SegmentedString m_pendingSrc; +}; #if ENABLE(XSLT) -void* xmlDocPtrForString(CachedResourceLoader*, const String& source, const String& url); +xmlDocPtr xmlDocPtrForString(CachedResourceLoader&, const String& source, const String& url); #endif HashMap<String, String> parseAttributes(const String&, bool& attrsOK); } // namespace WebCore - -#endif // XMLDocumentParser_h diff --git a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp index 1c1c61911..3d7f0e37e 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp +++ b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Peter Kelly <pmk@post.com> - * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005-2017 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) @@ -29,40 +29,29 @@ #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 "HTMLTemplateElement.h" -#include "Page.h" +#include "InlineClassicScript.h" +#include "PendingScript.h" #include "ProcessingInstruction.h" #include "ResourceError.h" -#include "ResourceRequest.h" #include "ResourceResponse.h" #include "ScriptElement.h" #include "ScriptSourceCode.h" -#include "SecurityOrigin.h" #include "Settings.h" -#include "TextResourceDecoder.h" +#include "StyleScope.h" #include "TransformSource.h" #include "XMLNSNames.h" #include "XMLDocumentParserScope.h" #include <libxml/parserInternals.h> -#include <wtf/Ref.h> #include <wtf/StringExtras.h> -#include <wtf/Threading.h> -#include <wtf/Vector.h> #include <wtf/unicode/UTF8.h> #if ENABLE(XSLT) @@ -72,48 +61,49 @@ namespace WebCore { -static inline bool hasNoStyleInformation(Document* document) +#if ENABLE(XSLT) + +static inline bool shouldRenderInXMLTreeViewerMode(Document& document) { - if (document->sawElementsInKnownNamespaces()) + if (document.sawElementsInKnownNamespaces()) return false; -#if ENABLE(XSLT) - if (document->transformSourceDocument()) + + if (document.transformSourceDocument()) return false; -#endif - if (!document->frame() || !document->frame()->page()) + + auto* frame = document.frame(); + if (!frame) return false; - if (!document->frame()->page()->settings().developerExtrasEnabled()) + if (!frame->settings().developerExtrasEnabled()) return false; - if (document->frame()->tree().parent()) + if (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; + WTF_MAKE_FAST_ALLOCATED; public: - PendingCallbacks() { } - ~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) + void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int numNamespaces, const xmlChar** namespaces, int numAttributes, int numDefaulted, const xmlChar** attributes) { auto callback = std::make_unique<PendingStartElementNSCallback>(); callback->xmlLocalName = xmlStrdup(xmlLocalName); callback->xmlPrefix = xmlStrdup(xmlPrefix); callback->xmlURI = xmlStrdup(xmlURI); - callback->nb_namespaces = nb_namespaces; - callback->namespaces = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_namespaces * 2)); - for (int i = 0; i < nb_namespaces * 2 ; i++) + callback->numNamespaces = numNamespaces; + callback->namespaces = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * numNamespaces * 2)); + for (int i = 0; i < numNamespaces * 2 ; i++) callback->namespaces[i] = xmlStrdup(namespaces[i]); - callback->nb_attributes = nb_attributes; - callback->nb_defaulted = nb_defaulted; - callback->attributes = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_attributes * 5)); - for (int i = 0; i < nb_attributes; i++) { + callback->numAttributes = numAttributes; + callback->numDefaulted = numDefaulted; + callback->attributes = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * numAttributes * 5)); + for (int i = 0; i < numAttributes; i++) { // Each attribute has 5 elements in the array: // name, prefix, uri, value and an end pointer. @@ -126,7 +116,7 @@ public: callback->attributes[i * 5 + 4] = callback->attributes[i * 5 + 3] + len; } - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendEndElementNSCallback() @@ -141,7 +131,7 @@ public: callback->s = xmlStrndup(s, len); callback->len = len; - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data) @@ -151,7 +141,7 @@ public: callback->target = xmlStrdup(target); callback->data = xmlStrdup(data); - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendCDATABlockCallback(const xmlChar* s, int len) @@ -161,7 +151,7 @@ public: callback->s = xmlStrndup(s, len); callback->len = len; - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendCommentCallback(const xmlChar* s) @@ -170,7 +160,7 @@ public: callback->s = xmlStrdup(s); - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendInternalSubsetCallback(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID) @@ -181,7 +171,7 @@ public: callback->externalID = xmlStrdup(externalID); callback->systemID = xmlStrdup(systemID); - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void appendErrorCallback(XMLErrors::ErrorType type, const xmlChar* message, OrdinalNumber lineNumber, OrdinalNumber columnNumber) @@ -193,7 +183,7 @@ public: callback->lineNumber = lineNumber; callback->columnNumber = columnNumber; - m_callbacks.append(std::move(callback)); + m_callbacks.append(WTFMove(callback)); } void callAndRemoveFirstCallback(XMLDocumentParser* parser) @@ -216,34 +206,33 @@ private: xmlFree(xmlLocalName); xmlFree(xmlPrefix); xmlFree(xmlURI); - for (int i = 0; i < nb_namespaces * 2; i++) + for (int i = 0; i < numNamespaces * 2; i++) xmlFree(namespaces[i]); xmlFree(namespaces); - for (int i = 0; i < nb_attributes; i++) + for (int i = 0; i < numAttributes; i++) { for (int j = 0; j < 4; j++) xmlFree(attributes[i * 5 + j]); + } xmlFree(attributes); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { - parser->startElementNs(xmlLocalName, xmlPrefix, xmlURI, - nb_namespaces, const_cast<const xmlChar**>(namespaces), - nb_attributes, nb_defaulted, const_cast<const xmlChar**>(attributes)); + parser->startElementNs(xmlLocalName, xmlPrefix, xmlURI, numNamespaces, const_cast<const xmlChar**>(namespaces), numAttributes, numDefaulted, const_cast<const xmlChar**>(attributes)); } xmlChar* xmlLocalName; xmlChar* xmlPrefix; xmlChar* xmlURI; - int nb_namespaces; + int numNamespaces; xmlChar** namespaces; - int nb_attributes; - int nb_defaulted; + int numAttributes; + int numDefaulted; xmlChar** attributes; }; struct PendingEndElementNSCallback : public PendingCallback { - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->endElementNs(); } @@ -255,7 +244,7 @@ private: xmlFree(s); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->characters(s, len); } @@ -271,7 +260,7 @@ private: xmlFree(data); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->processingInstruction(target, data); } @@ -286,7 +275,7 @@ private: xmlFree(s); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->cdataBlock(s, len); } @@ -301,7 +290,7 @@ private: xmlFree(s); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->comment(s); } @@ -317,7 +306,7 @@ private: xmlFree(systemID); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->internalSubset(name, externalID, systemID); } @@ -333,7 +322,7 @@ private: xmlFree(message); } - virtual void call(XMLDocumentParser* parser) + void call(XMLDocumentParser* parser) override { parser->handleError(type, reinterpret_cast<char*>(message), TextPosition(lineNumber, columnNumber)); } @@ -361,7 +350,11 @@ 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) { @@ -428,7 +421,7 @@ static bool shouldAllowExternalLoad(const URL& url) // retrieved content. If we had more context, we could potentially allow // the parser to load a DTD. As things stand, we take the conservative // route and allow same-origin requests only. - if (!XMLDocumentParserScope::currentCachedResourceLoader->document()->securityOrigin()->canRequest(url)) { + if (!XMLDocumentParserScope::currentCachedResourceLoader->document()->securityOrigin().canRequest(url)) { XMLDocumentParserScope::currentCachedResourceLoader->printAccessDeniedMessage(url); return false; } @@ -448,24 +441,26 @@ static void* openFunc(const char* uri) 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, ClientCredentialPolicy::MayAskClientForCredentials, 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) @@ -502,7 +497,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(); @@ -516,16 +511,16 @@ PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerP parser->_private = userData; // Substitute entities. - xmlCtxtUseOptions(parser, XML_PARSE_NOENT); + xmlCtxtUseOptions(parser, XML_PARSE_NOENT | XML_PARSE_HUGE); 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(); @@ -545,7 +540,7 @@ PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerP // Substitute entities. // FIXME: Why is XML_PARSE_NODICT needed? This is different from what createStringParser does. - xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT); + xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT | XML_PARSE_HUGE); // Internal initialization parser->sax2 = 1; @@ -556,7 +551,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)); } // -------------------------------- @@ -569,42 +564,16 @@ bool XMLDocumentParser::supportsXMLVersion(const String& version) XMLDocumentParser::XMLDocumentParser(Document& document, FrameView* frameView) : ScriptableDocumentParser(document) , m_view(frameView) - , m_context(0) , m_pendingCallbacks(std::make_unique<PendingCallbacks>()) - , m_depthTriggeringEntityExpansion(-1) - , m_isParsingEntityDeclaration(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_pendingScript(0) , 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(std::make_unique<PendingCallbacks>()) - , m_depthTriggeringEntityExpansion(-1) - , m_isParsingEntityDeclaration(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_pendingScript(0) , m_scriptStartPosition(TextPosition::belowRangePosition()) , m_parsingFragment(true) { @@ -615,10 +584,10 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parent 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()) @@ -656,7 +625,7 @@ XMLDocumentParser::~XMLDocumentParser() // FIXME: m_pendingScript handling should be moved into XMLDocumentParser.cpp! if (m_pendingScript) - m_pendingScript->removeClient(this); + m_pendingScript->clearClient(); } void XMLDocumentParser::doWrite(const String& parseString) @@ -672,11 +641,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. - Ref<XMLDocumentParser> protect(*this); + Ref<XMLDocumentParser> protectedThis(*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.deprecatedCharacters()), 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. @@ -718,21 +689,22 @@ struct _xmlSAX2Namespace { }; typedef struct _xmlSAX2Namespace xmlSAX2Namespace; -static inline void handleNamespaceAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlNamespaces, int nb_namespaces, ExceptionCode& ec) +static inline bool handleNamespaceAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlNamespaces, int numNamespaces) { xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces); - for (int i = 0; i < nb_namespaces; i++) { + for (int i = 0; i < numNamespaces; i++) { AtomicString namespaceQName = xmlnsAtom; AtomicString namespaceURI = toAtomicString(namespaces[i].uri); if (namespaces[i].prefix) namespaceQName = "xmlns:" + toString(namespaces[i].prefix); - QualifiedName parsedName = anyName; - if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceURI, namespaceQName, ec)) - return; - - prefixedAttributes.append(Attribute(parsedName, namespaceURI)); + auto result = Element::parseAttributeName(XMLNSNames::xmlnsNamespaceURI, namespaceQName); + if (result.hasException()) + return false; + + prefixedAttributes.append(Attribute(result.releaseReturnValue(), namespaceURI)); } + return true; } struct _xmlSAX2Attributes { @@ -744,22 +716,23 @@ struct _xmlSAX2Attributes { }; typedef struct _xmlSAX2Attributes xmlSAX2Attributes; -static inline void handleElementAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlAttributes, int nb_attributes, ExceptionCode& ec) +static inline bool handleElementAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlAttributes, int numAttributes) { xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes); - for (int i = 0; i < nb_attributes; i++) { + for (int i = 0; i < numAttributes; i++) { int valueLength = static_cast<int>(attributes[i].end - attributes[i].value); AtomicString attrValue = toAtomicString(attributes[i].value, valueLength); String attrPrefix = toString(attributes[i].prefix); - AtomicString attrURI = attrPrefix.isEmpty() ? AtomicString() : toAtomicString(attributes[i].uri); + AtomicString attrURI = attrPrefix.isEmpty() ? nullAtom : toAtomicString(attributes[i].uri); AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attributes[i].localname) : attrPrefix + ":" + toString(attributes[i].localname); - QualifiedName parsedName = anyName; - if (!Element::parseAttributeName(parsedName, attrURI, attrQName, ec)) - return; + auto result = Element::parseAttributeName(attrURI, attrQName); + if (result.hasException()) + return false; - prefixedAttributes.append(Attribute(parsedName, attrValue)); + prefixedAttributes.append(Attribute(result.releaseReturnValue(), attrValue)); } + return true; } // This is a hack around https://bugzilla.gnome.org/show_bug.cgi?id=502960 @@ -775,19 +748,18 @@ static inline bool hackAroundLibXMLEntityParsingBug() #endif } -void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces, - const xmlChar** libxmlNamespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes) +void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int numNamespaces, const xmlChar** libxmlNamespaces, int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes) { if (isStopped()) return; if (m_parserPaused) { - m_pendingCallbacks->appendStartElementNSCallback(xmlLocalName, xmlPrefix, xmlURI, nb_namespaces, libxmlNamespaces, - nb_attributes, nb_defaulted, libxmlAttributes); + m_pendingCallbacks->appendStartElementNSCallback(xmlLocalName, xmlPrefix, xmlURI, numNamespaces, libxmlNamespaces, numAttributes, numDefaulted, libxmlAttributes); return; } - exitText(); + if (!updateLeafTextNode()) + return; AtomicString localName = toAtomicString(xmlLocalName); AtomicString uri = toAtomicString(xmlURI); @@ -809,49 +781,38 @@ 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()); + if (!handleNamespaceAttributes(prefixedAttributes, libxmlNamespaces, numNamespaces)) { + setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy()); stopParsing(); return; } - handleElementAttributes(prefixedAttributes, libxmlAttributes, nb_attributes, ec); - setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); - if (ec) { + bool success = handleElementAttributes(prefixedAttributes, libxmlAttributes, numAttributes); + setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy()); + if (!success) { stopParsing(); return; } newElement->beginParsingChildren(); - ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get()); - if (scriptElement) + if (isScriptElement(newElement.get())) m_scriptStartPosition = textPosition(); - m_currentNode->parserAppendChild(newElement.get()); + m_currentNode->parserAppendChild(newElement); if (!m_currentNode) // Synchronous DOM events may have removed the current node. return; -#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()); -#else - pushCurrentNode(newElement.get()); -#endif + pushCurrentNode(newElement.ptr()); - if (newElement->hasTagName(HTMLNames::htmlTag)) - toHTMLHtmlElement(newElement.get())->insertedByParser(); + if (is<HTMLHtmlElement>(newElement)) + downcast<HTMLHtmlElement>(newElement.get()).insertedByParser(); if (!m_parsingFragment && isFirstElement && document()->frame()) document()->frame()->injectUserScripts(InjectAtDocumentStart); @@ -869,39 +830,39 @@ void XMLDocumentParser::endElementNs() // JavaScript can detach the parser. Make sure this is not released // before the end of this method. - Ref<XMLDocumentParser> protect(*this); + Ref<XMLDocumentParser> protectedThis(*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) && isScriptElement(downcast<Element>(*node))) { popCurrentNode(); - n->remove(IGNORE_EXCEPTION); + node->remove(); return; } - if (!n->isElementNode() || !m_view) { + if (!node->isElementNode() || !m_view) { popCurrentNode(); return; } - Element* element = toElement(n.get()); + auto& 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.isConnected()) { popCurrentNode(); return; } - ScriptElement* scriptElement = toScriptElementIfPossible(element); - if (!scriptElement) { + if (!isScriptElement(element)) { popCurrentNode(); return; } @@ -910,22 +871,21 @@ void XMLDocumentParser::endElementNs() ASSERT(!m_pendingScript); m_requestingScript = true; - if (scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) { + auto& scriptElement = downcastScriptElement(element); + if (scriptElement.prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) { // FIXME: Script execution should be shared between // the libxml2 and Qt XMLDocumentParser implementations. - 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); + if (scriptElement.readyToBeParserExecuted()) + scriptElement.executeClassicScript(ScriptSourceCode(scriptElement.scriptContent(), document()->url(), m_scriptStartPosition, JSC::SourceProviderSourceType::Program, InlineClassicScript::create(scriptElement))); + else if (scriptElement.willBeParserExecuted() && scriptElement.loadableScript()) { + m_pendingScript = PendingScript::create(scriptElement, *scriptElement.loadableScript()); + m_pendingScript->setClient(*this); - // m_pendingScript will be 0 if script was already loaded and addClient() executed it. + // m_pendingScript will be nullptr if script was already loaded and setClient() executed it. if (m_pendingScript) pauseParsing(); - } else - m_scriptElement = 0; + } // JavaScript may have detached the parser if (isDetached()) @@ -935,19 +895,19 @@ void XMLDocumentParser::endElementNs() popCurrentNode(); } -void XMLDocumentParser::characters(const xmlChar* s, int len) +void XMLDocumentParser::characters(const xmlChar* characters, int length) { if (isStopped()) return; if (m_parserPaused) { - m_pendingCallbacks->appendCharactersCallback(s, len); + m_pendingCallbacks->appendCharactersCallback(characters, length); return; } if (!m_leafTextNode) - enterText(); - m_bufferedText.append(s, len); + createLeafTextNode(); + m_bufferedText.append(characters, length); } void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va_list args) @@ -955,24 +915,19 @@ void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va if (isStopped()) return; -#if HAVE(VASPRINTF) - char* m; - if (vasprintf(&m, message, args) == -1) - return; -#else - char m[1024]; - vsnprintf(m, sizeof(m) - 1, message, args); -#endif + va_list preflightArgs; + va_copy(preflightArgs, args); + size_t stringLength = vsnprintf(nullptr, 0, message, preflightArgs); + va_end(preflightArgs); + + Vector<char, 1024> buffer(stringLength + 1); + vsnprintf(buffer.data(), stringLength + 1, message, args); TextPosition position = textPosition(); if (m_parserPaused) - m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(m), position.m_line, position.m_column); + m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(buffer.data()), position.m_line, position.m_column); else - handleError(type, m, textPosition()); - -#if HAVE(VASPRINTF) - free(m); -#endif + handleError(type, buffer.data(), textPosition()); } void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlChar* data) @@ -985,23 +940,23 @@ 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( - toString(target), toString(data), ec); - if (ec) + auto result = m_currentNode->document().createProcessingInstruction(toString(target), toString(data)); + if (result.hasException()) return; + auto pi = result.releaseReturnValue(); pi->setCreatedByParser(true); - m_currentNode->parserAppendChild(pi.get()); + m_currentNode->parserAppendChild(pi); pi->finishParsingChildren(); if (pi->isCSS()) m_sawCSS = true; + #if ENABLE(XSLT) m_sawXSLTransform = !m_sawFirstElement && pi->isXSL(); if (m_sawXSLTransform && !document()->transformSourceDocument()) @@ -1019,10 +974,10 @@ 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.release()); + m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->document(), toString(s, len))); } void XMLDocumentParser::comment(const xmlChar* s) @@ -1035,10 +990,10 @@ 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.release()); + m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), toString(s))); } enum StandaloneInfo { @@ -1057,9 +1012,9 @@ void XMLDocumentParser::startDocument(const xmlChar* version, const xmlChar* enc } if (version) - document()->setXMLVersion(toString(version), ASSERT_NO_EXCEPTION); + document()->setXMLVersion(toString(version)); if (standalone != StandaloneUnspecified) - document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_EXCEPTION); + document()->setXMLStandalone(standaloneInfo == StandaloneYes); if (encoding) document()->setXMLEncoding(toString(encoding)); document()->setHasXMLDeclaration(true); @@ -1067,7 +1022,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) @@ -1095,21 +1050,20 @@ static inline XMLDocumentParser* getParser(void* closure) static inline bool hackAroundLibXMLEntityBug(void* closure) { #if LIBXML_VERSION >= 20627 - UNUSED_PARAM(closure); - // This bug has been fixed in libxml 2.6.27. + UNUSED_PARAM(closure); return false; #else return static_cast<xmlParserCtxtPtr>(closure)->node; #endif } -static void startElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri, int nb_namespaces, const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes) +static void startElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri, int numNamespaces, const xmlChar** namespaces, int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes) { if (hackAroundLibXMLEntityBug(closure)) return; - getParser(closure)->startElementNs(localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, libxmlAttributes); + getParser(closure)->startElementNs(localname, prefix, uri, numNamespaces, namespaces, numAttributes, numDefaulted, libxmlAttributes); } static void endElementNsHandler(void* closure, const xmlChar*, const xmlChar*, const xmlChar*) @@ -1199,13 +1153,12 @@ static xmlEntityPtr sharedXHTMLEntity() static size_t convertUTF16EntityToUTF8(const UChar* utf16Entity, size_t numberOfCodeUnits, char* target, size_t targetSize) { const char* originalTarget = target; - WTF::Unicode::ConversionResult conversionResult = WTF::Unicode::convertUTF16ToUTF8(&utf16Entity, - utf16Entity + numberOfCodeUnits, &target, target + targetSize); + auto conversionResult = WTF::Unicode::convertUTF16ToUTF8(&utf16Entity, utf16Entity + numberOfCodeUnits, &target, target + targetSize); if (conversionResult != WTF::Unicode::conversionOK) return 0; // Even though we must pass the length, libxml expects the entity string to be null terminated. - ASSERT(target > originalTarget + 1); + ASSERT(target >= originalTarget + 1); *target = '\0'; return target - originalTarget; } @@ -1303,6 +1256,7 @@ static void externalSubsetHandler(void* closure, const xmlChar*, const xmlChar* || (extId == "-//W3C//DTD XHTML Basic 1.0//EN") || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN") || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN") + || (extId == "-//W3C//DTD MathML 2.0//EN") || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN") || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.1//EN") || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.2//EN")) @@ -1344,7 +1298,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 { @@ -1359,25 +1313,25 @@ 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) - bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && hasNoStyleInformation(document()); + bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && shouldRenderInXMLTreeViewerMode(*document()); if (xmlViewerMode) { XMLTreeViewer xmlTreeViewer(*document()); xmlTreeViewer.transformDocumentToTreeView(); } else if (m_sawXSLTransform) { - void* doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform.toString(), document()->url().string()); - document()->setTransformSource(adoptPtr(new TransformSource(doc))); + xmlDocPtr doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform.toString(), document()->url().string()); + 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); + document()->styleScope().didChangeActiveStyleSheetCandidates(); // styleResolverChanged() call can detach the parser and null out its document. // In that case, we just bail out. @@ -1398,10 +1352,10 @@ static inline const char* nativeEndianUTF16Encoding() return BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE"; } -void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const String& source, const String& url) +xmlDocPtr 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 @@ -1412,7 +1366,7 @@ 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 @@ -1421,11 +1375,16 @@ TextPosition XMLDocumentParser::textPosition() const { xmlParserCtxtPtr context = this->context(); if (!context) - return TextPosition::minimumPosition(); + return TextPosition(); return TextPosition(OrdinalNumber::fromOneBasedInt(context->input->line), OrdinalNumber::fromOneBasedInt(context->input->col)); } +bool XMLDocumentParser::shouldAssociateConsoleMessagesWithTextPosition() const +{ + return !m_parserPaused && !m_requestingScript; +} + void XMLDocumentParser::stopParsing() { DocumentParser::stopParsing(); @@ -1449,13 +1408,12 @@ void XMLDocumentParser::resumeParsing() return; } - // Then, write any pending data - SegmentedString rest = m_pendingSrc; - m_pendingSrc.clear(); // There is normally only one string left, so toString() shouldn't copy. // In any case, the XML parser runs on the main thread and it's OK if // the passed string has more than one reference. - append(rest.toString().impl()); + auto rest = m_pendingSrc.toString(); + m_pendingSrc.clear(); + append(rest.impl()); // Finally, if finish() has been called and write() didn't result // in any further callbacks being queued, call end() @@ -1500,9 +1458,7 @@ struct AttributeParseState { bool gotAttributes; }; -static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLocalName, const xmlChar* /*xmlPrefix*/, - const xmlChar* /*xmlURI*/, int /*nb_namespaces*/, const xmlChar** /*namespaces*/, - int nb_attributes, int /*nb_defaulted*/, const xmlChar** libxmlAttributes) +static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLocalName, const xmlChar* /*xmlPrefix*/, const xmlChar* /*xmlURI*/, int /*numNamespaces*/, const xmlChar** /*namespaces*/, int numAttributes, int /*numDefaulted*/, const xmlChar** libxmlAttributes) { if (strcmp(reinterpret_cast<const char*>(xmlLocalName), "attrs") != 0) return; @@ -1513,7 +1469,7 @@ static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc state->gotAttributes = true; xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes); - for (int i = 0; i < nb_attributes; i++) { + for (int i = 0; i < numAttributes; i++) { String attrLocalName = toString(attributes[i].localname); int valueLength = (int) (attributes[i].end - attributes[i].value); String attrValue = toString(attributes[i].value, valueLength); @@ -1526,6 +1482,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; @@ -1533,11 +1491,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.deprecatedCharacters()), 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/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..828214d87 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParserScope.h +++ b/Source/WebCore/xml/parser/XMLDocumentParserScope.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef XMLDocumentParserScope_h -#define XMLDocumentParserScope_h +#pragma once #include <wtf/Noncopyable.h> @@ -39,13 +38,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: @@ -59,5 +58,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // XMLDocumentParserScope_h |