diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/xml/parser | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/xml/parser')
-rw-r--r-- | Source/WebCore/xml/parser/CharacterReferenceParserInlines.h | 155 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/MarkupTokenizerInlines.h | 91 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParser.cpp | 90 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParser.h | 86 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp | 308 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParserQt.cpp | 657 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParserScope.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/xml/parser/XMLDocumentParserScope.h | 4 |
8 files changed, 348 insertions, 1045 deletions
diff --git a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h index 62780c7dc..f0f4ff76b 100644 --- a/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h +++ b/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h @@ -31,20 +31,9 @@ namespace WebCore { -inline bool isHexDigit(UChar cc) -{ - return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f') || (cc >= 'A' && cc <= 'F'); -} - inline void unconsumeCharacters(SegmentedString& source, const StringBuilder& consumedCharacters) { - if (consumedCharacters.length() == 1) - source.push(consumedCharacters[0]); - else if (consumedCharacters.length() == 2) { - source.push(consumedCharacters[0]); - source.push(consumedCharacters[1]); - } else - source.prepend(SegmentedString(consumedCharacters.toStringPreserveCapacity())); + source.pushBack(SegmentedString(consumedCharacters.toStringPreserveCapacity())); } template <typename ParserFunctions> @@ -54,7 +43,7 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh ASSERT(!notEnoughCharacters); ASSERT(decodedCharacter.isEmpty()); - enum EntityState { + enum { Initial, Number, MaybeHexLowerCaseX, @@ -62,105 +51,101 @@ bool consumeCharacterReference(SegmentedString& source, StringBuilder& decodedCh Hex, Decimal, Named - }; - EntityState entityState = Initial; + } state = Initial; UChar32 result = 0; + bool overflow = false; StringBuilder consumedCharacters; while (!source.isEmpty()) { - UChar cc = source.currentChar(); - switch (entityState) { - case Initial: { - if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '<' || cc == '&') + UChar character = source.currentChar(); + switch (state) { + case Initial: + if (character == '\x09' || character == '\x0A' || character == '\x0C' || character == ' ' || character == '<' || character == '&') return false; - if (additionalAllowedCharacter && cc == additionalAllowedCharacter) + if (additionalAllowedCharacter && character == additionalAllowedCharacter) return false; - if (cc == '#') { - entityState = Number; + if (character == '#') { + state = Number; break; } - if ((cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')) { - entityState = Named; - continue; + if (isASCIIAlpha(character)) { + state = Named; + goto Named; } return false; - } - case Number: { - if (cc == 'x') { - entityState = MaybeHexLowerCaseX; + case Number: + if (character == 'x') { + state = MaybeHexLowerCaseX; break; } - if (cc == 'X') { - entityState = MaybeHexUpperCaseX; + if (character == 'X') { + state = MaybeHexUpperCaseX; break; } - if (cc >= '0' && cc <= '9') { - entityState = Decimal; - continue; + if (isASCIIDigit(character)) { + state = Decimal; + goto Decimal; } - source.push('#'); + source.pushBack(SegmentedString(ASCIILiteral("#"))); return false; - } - case MaybeHexLowerCaseX: { - if (isHexDigit(cc)) { - entityState = Hex; - continue; + case MaybeHexLowerCaseX: + if (isASCIIHexDigit(character)) { + state = Hex; + goto Hex; } - source.push('#'); - source.push('x'); + source.pushBack(SegmentedString(ASCIILiteral("#x"))); return false; - } - case MaybeHexUpperCaseX: { - if (isHexDigit(cc)) { - entityState = Hex; - continue; + case MaybeHexUpperCaseX: + if (isASCIIHexDigit(character)) { + state = Hex; + goto Hex; } - source.push('#'); - source.push('X'); + source.pushBack(SegmentedString(ASCIILiteral("#X"))); return false; - } - case Hex: { - if (cc >= '0' && cc <= '9') - result = result * 16 + cc - '0'; - else if (cc >= 'a' && cc <= 'f') - result = result * 16 + 10 + cc - 'a'; - else if (cc >= 'A' && cc <= 'F') - result = result * 16 + 10 + cc - 'A'; - else if (cc == ';') { - source.advanceAndASSERT(cc); - decodedCharacter.append(ParserFunctions::legalEntityFor(result)); + case Hex: + Hex: + if (isASCIIHexDigit(character)) { + result = result * 16 + toASCIIHexValue(character); + if (result > UCHAR_MAX_VALUE) + overflow = true; + break; + } + if (character == ';') { + source.advance(); + decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result)); return true; - } else if (ParserFunctions::acceptMalformed()) { - decodedCharacter.append(ParserFunctions::legalEntityFor(result)); + } + if (ParserFunctions::acceptMalformed()) { + decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result)); return true; - } else { - unconsumeCharacters(source, consumedCharacters); - return false; } - break; - } - case Decimal: { - if (cc >= '0' && cc <= '9') - result = result * 10 + cc - '0'; - else if (cc == ';') { - source.advanceAndASSERT(cc); - decodedCharacter.append(ParserFunctions::legalEntityFor(result)); + unconsumeCharacters(source, consumedCharacters); + return false; + case Decimal: + Decimal: + if (isASCIIDigit(character)) { + result = result * 10 + character - '0'; + if (result > UCHAR_MAX_VALUE) + overflow = true; + break; + } + if (character == ';') { + source.advance(); + decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result)); return true; - } else if (ParserFunctions::acceptMalformed()) { - decodedCharacter.append(ParserFunctions::legalEntityFor(result)); + } + if (ParserFunctions::acceptMalformed()) { + decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result)); return true; - } else { - unconsumeCharacters(source, consumedCharacters); - return false; } - break; - } - case Named: { - return ParserFunctions::consumeNamedEntity(source, decodedCharacter, notEnoughCharacters, additionalAllowedCharacter, cc); - } + unconsumeCharacters(source, consumedCharacters); + return false; + case Named: + Named: + return ParserFunctions::consumeNamedEntity(source, decodedCharacter, notEnoughCharacters, additionalAllowedCharacter, character); } - consumedCharacters.append(cc); - source.advanceAndASSERT(cc); + consumedCharacters.append(character); + source.advance(); } ASSERT(source.isEmpty()); notEnoughCharacters = true; diff --git a/Source/WebCore/xml/parser/MarkupTokenizerInlines.h b/Source/WebCore/xml/parser/MarkupTokenizerInlines.h index e0b3156bb..987510e8a 100644 --- a/Source/WebCore/xml/parser/MarkupTokenizerInlines.h +++ b/Source/WebCore/xml/parser/MarkupTokenizerInlines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2015 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ * Copyright (C) 2010 Google, Inc. All Rights Reserved. * @@ -30,64 +30,61 @@ #include "SegmentedString.h" +#if COMPILER(MSVC) +// Disable the "unreachable code" warning so we can compile the ASSERT_NOT_REACHED in the END_STATE macro. +#pragma warning(disable: 4702) +#endif + namespace WebCore { -inline bool isTokenizerWhitespace(UChar cc) +inline bool isTokenizerWhitespace(UChar character) { - return cc == ' ' || cc == '\x0A' || cc == '\x09' || cc == '\x0C'; + return character == ' ' || character == '\x0A' || character == '\x09' || character == '\x0C'; } -inline void advanceStringAndASSERTIgnoringCase(SegmentedString& source, const char* expectedCharacters) -{ - while (*expectedCharacters) - source.advanceAndASSERTIgnoringCase(*expectedCharacters++); -} +#define BEGIN_STATE(stateName) \ + case stateName: \ + stateName: { \ + const auto currentState = stateName; \ + UNUSED_PARAM(currentState); -inline void advanceStringAndASSERT(SegmentedString& source, const char* expectedCharacters) -{ - while (*expectedCharacters) - source.advanceAndASSERT(*expectedCharacters++); -} - -#if COMPILER(MSVC) -// We need to disable the "unreachable code" warning because we want to assert -// that some code points aren't reached in the state machine. -#pragma warning(disable: 4702) -#endif +#define END_STATE() \ + ASSERT_NOT_REACHED(); \ + break; \ + } -#define BEGIN_STATE(prefix, stateName) case prefix::stateName: stateName: -#define END_STATE() ASSERT_NOT_REACHED(); break; +#define RETURN_IN_CURRENT_STATE(expression) \ + do { \ + m_state = currentState; \ + return expression; \ + } while (false) -// We use this macro when the HTML5 spec says "reconsume the current input -// character in the <mumble> state." -#define RECONSUME_IN(prefix, stateName) \ - do { \ - m_state = prefix::stateName; \ - goto stateName; \ +// We use this macro when the HTML spec says "reconsume the current input character in the <mumble> state." +#define RECONSUME_IN(newState) \ + do { \ + goto newState; \ } while (false) -// We use this macro when the HTML5 spec says "consume the next input -// character ... and switch to the <mumble> state." -#define ADVANCE_TO(prefix, stateName) \ - do { \ - m_state = prefix::stateName; \ - if (!m_inputStreamPreprocessor.advance(source)) \ - return haveBufferedCharacterToken(); \ - cc = m_inputStreamPreprocessor.nextInputCharacter(); \ - goto stateName; \ +// We use this macro when the HTML spec says "consume the next input character ... and switch to the <mumble> state." +#define ADVANCE_TO(newState) \ + do { \ + if (!m_preprocessor.advance(source, isNullCharacterSkippingState(newState))) { \ + m_state = newState; \ + return haveBufferedCharacterToken(); \ + } \ + character = m_preprocessor.nextInputCharacter(); \ + goto newState; \ } while (false) -// Sometimes there's more complicated logic in the spec that separates when -// we consume the next input character and when we switch to a particular -// state. We handle those cases by advancing the source directly and using -// this macro to switch to the indicated state. -#define SWITCH_TO(prefix, stateName) \ - do { \ - m_state = prefix::stateName; \ - if (source.isEmpty() || !m_inputStreamPreprocessor.peek(source)) \ - return haveBufferedCharacterToken(); \ - cc = m_inputStreamPreprocessor.nextInputCharacter(); \ - goto stateName; \ +// For more complex cases, caller consumes the characters first and then uses this macro. +#define SWITCH_TO(newState) \ + do { \ + if (!m_preprocessor.peek(source, isNullCharacterSkippingState(newState))) { \ + m_state = newState; \ + return haveBufferedCharacterToken(); \ + } \ + character = m_preprocessor.nextInputCharacter(); \ + goto newState; \ } while (false) } diff --git a/Source/WebCore/xml/parser/XMLDocumentParser.cpp b/Source/WebCore/xml/parser/XMLDocumentParser.cpp index cb4abc800..3fd7dbbee 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParser.cpp +++ b/Source/WebCore/xml/parser/XMLDocumentParser.cpp @@ -44,23 +44,17 @@ #include "ResourceError.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include "SVGNames.h" +#include "SVGStyleElement.h" #include "ScriptElement.h" #include "ScriptSourceCode.h" -#include "ScriptValue.h" #include "TextResourceDecoder.h" #include "TreeDepthLimit.h" -#include "XMLErrors.h" +#include <wtf/Ref.h> #include <wtf/StringExtras.h> #include <wtf/Threading.h> #include <wtf/Vector.h> -#if ENABLE(SVG) -#include "SVGNames.h" -#include "SVGStyleElement.h" -#endif - -using namespace std; - namespace WebCore { using namespace HTMLNames; @@ -94,8 +88,8 @@ void XMLDocumentParser::clearCurrentNodeStack() { if (m_currentNode && m_currentNode != document()) m_currentNode->deref(); - m_currentNode = 0; - m_leafTextNode = 0; + m_currentNode = nullptr; + m_leafTextNode = nullptr; if (m_currentNodeStack.size()) { // Aborted parsing. for (size_t i = m_currentNodeStack.size() - 1; i != 0; --i) @@ -111,9 +105,9 @@ void XMLDocumentParser::insert(const SegmentedString&) ASSERT_NOT_REACHED(); } -void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) +void XMLDocumentParser::append(RefPtr<StringImpl>&& inputSource) { - SegmentedString source(inputSource); + SegmentedString source(WTFMove(inputSource)); if (m_sawXSLTransform || !m_sawFirstElement) m_originalSourceForTransform.append(source); @@ -127,56 +121,55 @@ void XMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) doWrite(source.toString()); - // After parsing, go ahead and dispatch image beforeload events. + // After parsing, dispatch image beforeload events. ImageLoader::dispatchPendingBeforeLoadEvents(); } void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* m, TextPosition position) { - m_xmlErrors.handleError(type, m, position); + if (!m_xmlErrors) + m_xmlErrors = std::make_unique<XMLErrors>(document()); + m_xmlErrors->handleError(type, m, position); if (type != XMLErrors::warning) m_sawError = true; if (type == XMLErrors::fatal) stopParsing(); } -void XMLDocumentParser::enterText() +void XMLDocumentParser::createLeafTextNode() { -#if !USE(QXMLSTREAM) + if (m_leafTextNode) + return; + ASSERT(m_bufferedText.size() == 0); -#endif ASSERT(!m_leafTextNode); m_leafTextNode = Text::create(m_currentNode->document(), ""); - m_currentNode->parserAppendChild(m_leafTextNode.get()); + m_currentNode->parserAppendChild(*m_leafTextNode); } -#if !USE(QXMLSTREAM) static inline String toString(const xmlChar* string, size_t size) { return String::fromUTF8(reinterpret_cast<const char*>(string), size); } -#endif -void XMLDocumentParser::exitText() +bool XMLDocumentParser::updateLeafTextNode() { if (isStopped()) - return; + return false; if (!m_leafTextNode) - return; + return true; -#if !USE(QXMLSTREAM) - m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size()), IGNORE_EXCEPTION); - Vector<xmlChar> empty; - m_bufferedText.swap(empty); -#endif + // This operation might fire mutation event, see below. + m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.size())); + m_bufferedText = { }; - if (m_view && m_leafTextNode->parentNode() && m_leafTextNode->parentNode()->attached() - && !m_leafTextNode->attached()) - m_leafTextNode->attach(); + m_leafTextNode = nullptr; - m_leafTextNode = 0; + // Hence, we need to check again whether the parser is stopped, since mutation + // event handlers executed by appendData might have detached this parser. + return !isStopped(); } void XMLDocumentParser::detach() @@ -205,7 +198,7 @@ void XMLDocumentParser::end() if (m_sawError) insertErrorMessageBlock(); else { - exitText(); + updateLeafTextNode(); document()->styleResolverChanged(RecalcStyleImmediately); } @@ -230,12 +223,8 @@ void XMLDocumentParser::finish() void XMLDocumentParser::insertErrorMessageBlock() { -#if USE(QXMLSTREAM) - if (m_parsingFragment) - return; -#endif - - m_xmlErrors.insertErrorMessageBlock(); + ASSERT(m_xmlErrors); + m_xmlErrors->insertErrorMessageBlock(); } void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) @@ -248,16 +237,16 @@ void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) bool wasCanceled = m_pendingScript->wasCanceled(); m_pendingScript->removeClient(this); - m_pendingScript = 0; + m_pendingScript = nullptr; RefPtr<Element> e = m_scriptElement; - m_scriptElement = 0; + m_scriptElement = nullptr; ScriptElement* scriptElement = toScriptElementIfPossible(e.get()); ASSERT(scriptElement); // JavaScript can detach this parser, make sure it's kept alive even if detached. - RefPtr<XMLDocumentParser> protect(this); + Ref<XMLDocumentParser> protect(*this); if (errorOccurred) scriptElement->dispatchErrorEvent(); @@ -266,7 +255,7 @@ void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) scriptElement->dispatchLoadEvent(); } - m_scriptElement = 0; + m_scriptElement = nullptr; if (!isDetached() && !m_requestingScript) resumeParsing(); @@ -279,13 +268,15 @@ bool XMLDocumentParser::isWaitingForScripts() const void XMLDocumentParser::pauseParsing() { + ASSERT(!m_parserPaused); + if (m_parsingFragment) return; m_parserPaused = true; } -bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) +bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragment& fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) { if (!chunk.length()) return true; @@ -293,17 +284,16 @@ bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragm // FIXME: We need to implement the HTML5 XML Fragment parsing algorithm: // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#xml-fragment-parsing-algorithm // For now we have a hack for script/style innerHTML support: - if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag) || contextElement->hasLocalName(HTMLNames::styleTag))) { - fragment->parserAppendChild(fragment->document()->createTextNode(chunk)); + if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag.localName()) || contextElement->hasLocalName(HTMLNames::styleTag.localName()))) { + fragment.parserAppendChild(fragment.document().createTextNode(chunk)); return true; } RefPtr<XMLDocumentParser> parser = XMLDocumentParser::create(fragment, contextElement, parserContentPolicy); bool wellFormed = parser->appendFragmentSource(chunk); - // Do not call finish(). Current finish() and doEnd() implementations touch the main Document/loader - // and can cause crashes in the fragment case. + // Do not call finish(). The finish() and doEnd() implementations touch the main document and loader and can cause crashes in the fragment case. parser->detach(); // Allows ~DocumentParser to assert it was detached before destruction. - return wellFormed; // appendFragmentSource()'s wellFormed is more permissive than wellFormed(). + return wellFormed; // appendFragmentSource()'s wellFormed is more permissive than Document::wellFormed(). } } // namespace WebCore diff --git a/Source/WebCore/xml/parser/XMLDocumentParser.h b/Source/WebCore/xml/parser/XMLDocumentParser.h index 149ad6e1a..ad876cb99 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParser.h +++ b/Source/WebCore/xml/parser/XMLDocumentParser.h @@ -32,16 +32,11 @@ #include "SegmentedString.h" #include "XMLErrors.h" #include <wtf/HashMap.h> -#include <wtf/OwnPtr.h> #include <wtf/text/AtomicStringHash.h> #include <wtf/text/CString.h> -#if USE(QXMLSTREAM) -#include <qxmlstream.h> -#else #include <libxml/tree.h> #include <libxml/xmlstring.h> -#endif namespace WebCore { @@ -55,11 +50,10 @@ class FrameView; class PendingCallbacks; class Text; -#if !USE(QXMLSTREAM) class XMLParserContext : public RefCounted<XMLParserContext> { public: - static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk); - static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData); + static RefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk); + static Ref<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData); ~XMLParserContext(); xmlParserCtxtPtr context() const { return m_context; } @@ -70,18 +64,17 @@ class Text; } xmlParserCtxtPtr m_context; }; -#endif - class XMLDocumentParser : public ScriptableDocumentParser, public CachedResourceClient { + class XMLDocumentParser final : public ScriptableDocumentParser, public CachedResourceClient { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<XMLDocumentParser> create(Document* document, FrameView* view) + static Ref<XMLDocumentParser> create(Document& document, FrameView* view) { - return adoptRef(new XMLDocumentParser(document, view)); + return adoptRef(*new XMLDocumentParser(document, view)); } - static PassRefPtr<XMLDocumentParser> create(DocumentFragment* fragment, Element* element, ParserContentPolicy parserContentPolicy) + static Ref<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy) { - return adoptRef(new XMLDocumentParser(fragment, element, parserContentPolicy)); + return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy)); } ~XMLDocumentParser(); @@ -92,31 +85,30 @@ class Text; void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; } bool isXHTMLDocument() const { return m_isXHTMLDocument; } - static bool parseDocumentFragment(const String&, DocumentFragment*, Element* parent = 0, ParserContentPolicy = AllowScriptingContent); + static bool parseDocumentFragment(const String&, DocumentFragment&, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent); // Used by the XMLHttpRequest to check if the responseXML was well formed. - virtual bool wellFormed() const { return !m_sawError; } - - TextPosition textPosition() const; + virtual bool wellFormed() const override { return !m_sawError; } static bool supportsXMLVersion(const String&); private: - XMLDocumentParser(Document*, FrameView* = 0); - XMLDocumentParser(DocumentFragment*, Element*, ParserContentPolicy); + XMLDocumentParser(Document&, FrameView* = nullptr); + XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy); // From DocumentParser - virtual void insert(const SegmentedString&); - virtual void append(PassRefPtr<StringImpl>); - virtual void finish(); - virtual bool isWaitingForScripts() const; - virtual void stopParsing(); - virtual void detach(); - virtual OrdinalNumber lineNumber() const; - OrdinalNumber columnNumber() const; + virtual void insert(const SegmentedString&) override; + virtual void append(RefPtr<StringImpl>&&) override; + virtual void finish() override; + virtual bool isWaitingForScripts() const override; + virtual void stopParsing() override; + virtual void detach() override; + + virtual TextPosition textPosition() const override; + virtual bool shouldAssociateConsoleMessagesWithTextPosition() const override; // from CachedResourceClient - virtual void notifyFinished(CachedResource*); + virtual void notifyFinished(CachedResource*) override; void end(); @@ -125,21 +117,7 @@ class Text; bool appendFragmentSource(const String&); -#if USE(QXMLSTREAM) -private: - void parse(); - void startDocument(); - void parseStartElement(); - void parseEndElement(); - void parseCharacters(); - void parseProcessingInstruction(); - void parseCdata(); - void parseComment(); - void endDocument(); - void parseDtd(); - bool hasError() const; -#else -public: + public: // callbacks from parser SAX void error(XMLErrors::ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0); void startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces, @@ -158,7 +136,7 @@ public: int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; } void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; } -#endif + private: void initializeParserContext(const CString& chunk = CString()); @@ -168,8 +146,8 @@ public: void insertErrorMessageBlock(); - void enterText(); - void exitText(); + void createLeafTextNode(); + bool updateLeafTextNode(); void doWrite(const String&); void doEnd(); @@ -178,17 +156,13 @@ public: SegmentedString m_originalSourceForTransform; -#if USE(QXMLSTREAM) - QXmlStreamReader m_stream; - bool m_wroteText; -#else - xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; }; + xmlParserCtxtPtr context() const { return m_context ? m_context->context() : nullptr; }; RefPtr<XMLParserContext> m_context; - OwnPtr<PendingCallbacks> m_pendingCallbacks; + std::unique_ptr<PendingCallbacks> m_pendingCallbacks; Vector<xmlChar> m_bufferedText; int m_depthTriggeringEntityExpansion; bool m_isParsingEntityDeclaration; -#endif + ContainerNode* m_currentNode; Vector<ContainerNode*> m_currentNodeStack; @@ -203,7 +177,7 @@ public: bool m_requestingScript; bool m_finishCalled; - XMLErrors m_xmlErrors; + std::unique_ptr<XMLErrors> m_xmlErrors; CachedResourceHandle<CachedScript> m_pendingScript; RefPtr<Element> m_scriptElement; @@ -218,7 +192,7 @@ public: }; #if ENABLE(XSLT) -void* xmlDocPtrForString(CachedResourceLoader*, const String& source, const String& url); +void* xmlDocPtrForString(CachedResourceLoader&, const String& source, const String& url); #endif HashMap<String, String> parseAttributes(const String&, bool& attrsOK); diff --git a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp index 8b8786b7a..0e77eac4d 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp +++ b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp @@ -7,6 +7,7 @@ * Copyright (C) 2008 Holger Hans Peter Freyther * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * Copyright (C) 2013 Samsung Electronics. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -44,21 +45,21 @@ #include "HTMLNames.h" #include "HTMLStyleElement.h" #include "HTMLTemplateElement.h" +#include "Page.h" #include "ProcessingInstruction.h" #include "ResourceError.h" #include "ResourceRequest.h" #include "ResourceResponse.h" #include "ScriptElement.h" #include "ScriptSourceCode.h" -#include "ScriptValue.h" #include "SecurityOrigin.h" +#include "Settings.h" #include "TextResourceDecoder.h" #include "TransformSource.h" #include "XMLNSNames.h" #include "XMLDocumentParserScope.h" -#include <libxml/parser.h> #include <libxml/parserInternals.h> -#include <wtf/text/CString.h> +#include <wtf/Ref.h> #include <wtf/StringExtras.h> #include <wtf/Threading.h> #include <wtf/Vector.h> @@ -69,23 +70,40 @@ #include <libxslt/xslt.h> #endif -using namespace std; - namespace WebCore { +#if ENABLE(XSLT) +static inline bool hasNoStyleInformation(Document* document) +{ + if (document->sawElementsInKnownNamespaces()) + return false; + + if (document->transformSourceDocument()) + return false; + + if (!document->frame() || !document->frame()->page()) + return false; + + if (!document->frame()->page()->settings().developerExtrasEnabled()) + return false; + + if (document->frame()->tree().parent()) + return false; // This document is not in a top frame + + return true; +} +#endif + class PendingCallbacks { WTF_MAKE_NONCOPYABLE(PendingCallbacks); WTF_MAKE_FAST_ALLOCATED; public: + PendingCallbacks() { } ~PendingCallbacks() { } - static PassOwnPtr<PendingCallbacks> create() - { - return adoptPtr(new PendingCallbacks); - } - + void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces, const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes) { - OwnPtr<PendingStartElementNSCallback> callback = adoptPtr(new PendingStartElementNSCallback); + auto callback = std::make_unique<PendingStartElementNSCallback>(); callback->xmlLocalName = xmlStrdup(xmlLocalName); callback->xmlPrefix = xmlStrdup(xmlPrefix); @@ -110,87 +128,85 @@ public: callback->attributes[i * 5 + 4] = callback->attributes[i * 5 + 3] + len; } - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendEndElementNSCallback() { - m_callbacks.append(adoptPtr(new PendingEndElementNSCallback)); + m_callbacks.append(std::make_unique<PendingEndElementNSCallback>()); } void appendCharactersCallback(const xmlChar* s, int len) { - OwnPtr<PendingCharactersCallback> callback = adoptPtr(new PendingCharactersCallback); + auto callback = std::make_unique<PendingCharactersCallback>(); callback->s = xmlStrndup(s, len); callback->len = len; - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data) { - OwnPtr<PendingProcessingInstructionCallback> callback = adoptPtr(new PendingProcessingInstructionCallback); + auto callback = std::make_unique<PendingProcessingInstructionCallback>(); callback->target = xmlStrdup(target); callback->data = xmlStrdup(data); - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendCDATABlockCallback(const xmlChar* s, int len) { - OwnPtr<PendingCDATABlockCallback> callback = adoptPtr(new PendingCDATABlockCallback); + auto callback = std::make_unique<PendingCDATABlockCallback>(); callback->s = xmlStrndup(s, len); callback->len = len; - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendCommentCallback(const xmlChar* s) { - OwnPtr<PendingCommentCallback> callback = adoptPtr(new PendingCommentCallback); + auto callback = std::make_unique<PendingCommentCallback>(); callback->s = xmlStrdup(s); - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendInternalSubsetCallback(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID) { - OwnPtr<PendingInternalSubsetCallback> callback = adoptPtr(new PendingInternalSubsetCallback); + auto callback = std::make_unique<PendingInternalSubsetCallback>(); callback->name = xmlStrdup(name); callback->externalID = xmlStrdup(externalID); callback->systemID = xmlStrdup(systemID); - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void appendErrorCallback(XMLErrors::ErrorType type, const xmlChar* message, OrdinalNumber lineNumber, OrdinalNumber columnNumber) { - OwnPtr<PendingErrorCallback> callback = adoptPtr(new PendingErrorCallback); + auto callback = std::make_unique<PendingErrorCallback>(); callback->message = xmlStrdup(message); callback->type = type; callback->lineNumber = lineNumber; callback->columnNumber = columnNumber; - m_callbacks.append(callback.release()); + m_callbacks.append(WTFMove(callback)); } void callAndRemoveFirstCallback(XMLDocumentParser* parser) { - OwnPtr<PendingCallback> callback = m_callbacks.takeFirst(); + std::unique_ptr<PendingCallback> callback = m_callbacks.takeFirst(); callback->call(parser); } bool isEmpty() const { return m_callbacks.isEmpty(); } private: - PendingCallbacks() { } - struct PendingCallback { virtual ~PendingCallback() { } virtual void call(XMLDocumentParser* parser) = 0; @@ -330,7 +346,7 @@ private: OrdinalNumber columnNumber; }; - Deque<OwnPtr<PendingCallback> > m_callbacks; + Deque<std::unique_ptr<PendingCallback>> m_callbacks; }; // -------------------------------- @@ -347,12 +363,16 @@ static int matchFunc(const char*) class OffsetBuffer { WTF_MAKE_FAST_ALLOCATED; public: - OffsetBuffer(const Vector<char>& b) : m_buffer(b), m_currentOffset(0) { } + OffsetBuffer(Vector<char> buffer) + : m_buffer(WTFMove(buffer)) + , m_currentOffset(0) + { + } int readOutBytes(char* outputBuffer, unsigned askedToRead) { unsigned bytesLeft = m_buffer.size() - m_currentOffset; - unsigned lenToCopy = min(askedToRead, bytesLeft); + unsigned lenToCopy = std::min(askedToRead, bytesLeft); if (lenToCopy) { memcpy(outputBuffer, m_buffer.data() + m_currentOffset, lenToCopy); m_currentOffset += lenToCopy; @@ -386,7 +406,7 @@ static void switchToUTF16(xmlParserCtxtPtr ctxt) xmlSwitchEncoding(ctxt, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); } -static bool shouldAllowExternalLoad(const KURL& url) +static bool shouldAllowExternalLoad(const URL& url) { String urlString = url.string(); @@ -427,31 +447,33 @@ static void* openFunc(const char* uri) ASSERT(XMLDocumentParserScope::currentCachedResourceLoader); ASSERT(currentThread() == libxmlLoaderThread); - KURL url(KURL(), uri); + URL url(URL(), uri); if (!shouldAllowExternalLoad(url)) return &globalDescriptor; ResourceError error; ResourceResponse response; - Vector<char> data; + RefPtr<SharedBuffer> data; { CachedResourceLoader* cachedResourceLoader = XMLDocumentParserScope::currentCachedResourceLoader; - XMLDocumentParserScope scope(0); + XMLDocumentParserScope scope(nullptr); // FIXME: We should restore the original global error handler as well. if (cachedResourceLoader->frame()) - cachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data); + cachedResourceLoader->frame()->loader().loadResourceSynchronously(url, AllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data); } // We have to check the URL again after the load to catch redirects. // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. if (!shouldAllowExternalLoad(response.url())) return &globalDescriptor; - - return new OffsetBuffer(data); + Vector<char> buffer; + if (data) + buffer.append(data->data(), data->size()); + return new OffsetBuffer(WTFMove(buffer)); } static int readFunc(void* context, char* buffer, int len) @@ -488,7 +510,7 @@ static void errorFunc(void*, const char*, ...) static bool didInit = false; -PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData) +Ref<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData) { if (!didInit) { xmlInitParser(); @@ -506,12 +528,12 @@ PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerP switchToUTF16(parser); - return adoptRef(new XMLParserContext(parser)); + return adoptRef(*new XMLParserContext(parser)); } // Chunk should be encoded in UTF-8 -PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const CString& chunk) +RefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const CString& chunk) { if (!didInit) { xmlInitParser(); @@ -542,7 +564,7 @@ PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerP parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36); parser->_private = userData; - return adoptRef(new XMLParserContext(parser)); + return adoptRef(*new XMLParserContext(parser)); } // -------------------------------- @@ -552,14 +574,14 @@ bool XMLDocumentParser::supportsXMLVersion(const String& version) return version == "1.0"; } -XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView) +XMLDocumentParser::XMLDocumentParser(Document& document, FrameView* frameView) : ScriptableDocumentParser(document) , m_view(frameView) - , m_context(0) - , m_pendingCallbacks(PendingCallbacks::create()) + , m_context(nullptr) + , m_pendingCallbacks(std::make_unique<PendingCallbacks>()) , m_depthTriggeringEntityExpansion(-1) , m_isParsingEntityDeclaration(false) - , m_currentNode(document) + , m_currentNode(&document) , m_sawError(false) , m_sawCSS(false) , m_sawXSLTransform(false) @@ -568,21 +590,20 @@ XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView) , m_parserPaused(false) , m_requestingScript(false) , m_finishCalled(false) - , m_xmlErrors(document) - , m_pendingScript(0) + , m_pendingScript(nullptr) , m_scriptStartPosition(TextPosition::belowRangePosition()) , m_parsingFragment(false) { } -XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parentElement, ParserContentPolicy parserContentPolicy) - : ScriptableDocumentParser(fragment->document(), parserContentPolicy) - , m_view(0) - , m_context(0) - , m_pendingCallbacks(PendingCallbacks::create()) +XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parentElement, ParserContentPolicy parserContentPolicy) + : ScriptableDocumentParser(fragment.document(), parserContentPolicy) + , m_view(nullptr) + , m_context(nullptr) + , m_pendingCallbacks(std::make_unique<PendingCallbacks>()) , m_depthTriggeringEntityExpansion(-1) , m_isParsingEntityDeclaration(false) - , m_currentNode(fragment) + , m_currentNode(&fragment) , m_sawError(false) , m_sawCSS(false) , m_sawXSLTransform(false) @@ -591,42 +612,40 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent , m_parserPaused(false) , m_requestingScript(false) , m_finishCalled(false) - , m_xmlErrors(fragment->document()) , m_pendingScript(0) , m_scriptStartPosition(TextPosition::belowRangePosition()) , m_parsingFragment(true) { - fragment->ref(); + fragment.ref(); // Add namespaces based on the parent node Vector<Element*> elemStack; while (parentElement) { elemStack.append(parentElement); - ContainerNode* n = parentElement->parentNode(); - if (!n || !n->isElementNode()) + ContainerNode* node = parentElement->parentNode(); + if (!is<Element>(node)) break; - parentElement = toElement(n); + parentElement = downcast<Element>(node); } if (elemStack.isEmpty()) return; + // FIXME: Share code with isDefaultNamespace() per http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#parsing-xhtml-fragments for (; !elemStack.isEmpty(); elemStack.removeLast()) { Element* element = elemStack.last(); if (element->hasAttributes()) { - for (unsigned i = 0; i < element->attributeCount(); i++) { - const Attribute* attribute = element->attributeItem(i); - if (attribute->localName() == xmlnsAtom) - m_defaultNamespaceURI = attribute->value(); - else if (attribute->prefix() == xmlnsAtom) - m_prefixToNamespaceMap.set(attribute->localName(), attribute->value()); + for (const Attribute& attribute : element->attributesIterator()) { + if (attribute.localName() == xmlnsAtom) + m_defaultNamespaceURI = attribute.value(); + else if (attribute.prefix() == xmlnsAtom) + m_prefixToNamespaceMap.set(attribute.localName(), attribute.value()); } } } - // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace. - if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument()) + if (m_defaultNamespaceURI.isNull()) m_defaultNamespaceURI = parentElement->namespaceURI(); } @@ -661,11 +680,13 @@ void XMLDocumentParser::doWrite(const String& parseString) if (parseString.length()) { // JavaScript may cause the parser to detach during xmlParseChunk // keep this alive until this function is done. - RefPtr<XMLDocumentParser> protect(this); + Ref<XMLDocumentParser> protect(*this); + + XMLDocumentParserScope scope(&document()->cachedResourceLoader()); + // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16? switchToUTF16(context->context()); - XMLDocumentParserScope scope(document()->cachedResourceLoader()); - xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0); + xmlParseChunk(context->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), sizeof(UChar) * parseString.length(), 0); // JavaScript (which may be run under the xmlParseChunk callstack) may // cause the parser to be stopped or detached. @@ -776,7 +797,8 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha return; } - exitText(); + if (!updateLeafTextNode()) + return; AtomicString localName = toAtomicString(xmlLocalName); AtomicString uri = toAtomicString(xmlURI); @@ -798,23 +820,19 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha m_sawFirstElement = true; QualifiedName qName(prefix, localName, uri); - RefPtr<Element> newElement = m_currentNode->document()->createElement(qName, true); - if (!newElement) { - stopParsing(); - return; - } + auto newElement = m_currentNode->document().createElement(qName, true); Vector<Attribute> prefixedAttributes; ExceptionCode ec = 0; handleNamespaceAttributes(prefixedAttributes, libxmlNamespaces, nb_namespaces, ec); if (ec) { - setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); + setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy()); stopParsing(); return; } handleElementAttributes(prefixedAttributes, libxmlAttributes, nb_attributes, ec); - setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); + setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy()); if (ec) { stopParsing(); return; @@ -822,30 +840,28 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha newElement->beginParsingChildren(); - ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get()); + ScriptElement* scriptElement = toScriptElementIfPossible(newElement.ptr()); if (scriptElement) m_scriptStartPosition = textPosition(); - m_currentNode->parserAppendChild(newElement.get()); + m_currentNode->parserAppendChild(newElement.copyRef()); + if (!m_currentNode) // Synchronous DOM events may have removed the current node. + return; - const ContainerNode* currentNode = m_currentNode; #if ENABLE(TEMPLATE_ELEMENT) - if (newElement->hasTagName(HTMLNames::templateTag)) - pushCurrentNode(toHTMLTemplateElement(newElement.get())->content()); + if (is<HTMLTemplateElement>(newElement)) + pushCurrentNode(downcast<HTMLTemplateElement>(newElement.get()).content()); else - pushCurrentNode(newElement.get()); + pushCurrentNode(newElement.ptr()); #else - pushCurrentNode(newElement.get()); + pushCurrentNode(newElement.ptr()); #endif - if (m_view && currentNode->attached() && !newElement->attached()) - newElement->attach(); - - if (newElement->hasTagName(HTMLNames::htmlTag)) - static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser(); + if (is<HTMLHtmlElement>(newElement)) + downcast<HTMLHtmlElement>(newElement.get()).insertedByParser(); if (!m_parsingFragment && isFirstElement && document()->frame()) - document()->frame()->loader()->dispatchDocumentElementAvailable(); + document()->frame()->injectUserScripts(InjectAtDocumentStart); } void XMLDocumentParser::endElementNs() @@ -860,38 +876,39 @@ void XMLDocumentParser::endElementNs() // JavaScript can detach the parser. Make sure this is not released // before the end of this method. - RefPtr<XMLDocumentParser> protect(this); + Ref<XMLDocumentParser> protect(*this); - exitText(); + if (!updateLeafTextNode()) + return; - RefPtr<ContainerNode> n = m_currentNode; - n->finishParsingChildren(); + RefPtr<ContainerNode> node = m_currentNode; + node->finishParsingChildren(); // Once we reach the depth again where entity expansion started, stop executing the work-around. if (hackAroundLibXMLEntityParsingBug() && context()->depth <= depthTriggeringEntityExpansion()) setDepthTriggeringEntityExpansion(-1); - if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptElementIfPossible(toElement(n.get()))) { + if (!scriptingContentIsAllowed(parserContentPolicy()) && is<Element>(*node) && toScriptElementIfPossible(downcast<Element>(node.get()))) { popCurrentNode(); - n->remove(IGNORE_EXCEPTION); + node->remove(IGNORE_EXCEPTION); return; } - if (!n->isElementNode() || !m_view) { + if (!node->isElementNode() || !m_view) { popCurrentNode(); return; } - Element* element = toElement(n.get()); + Element& element = downcast<Element>(*node); // The element's parent may have already been removed from document. // Parsing continues in this case, but scripts aren't executed. - if (!element->inDocument()) { + if (!element.inDocument()) { popCurrentNode(); return; } - ScriptElement* scriptElement = toScriptElementIfPossible(element); + ScriptElement* scriptElement = toScriptElementIfPossible(&element); if (!scriptElement) { popCurrentNode(); return; @@ -909,14 +926,14 @@ void XMLDocumentParser::endElementNs() scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); else if (scriptElement->willBeParserExecuted()) { m_pendingScript = scriptElement->cachedScript(); - m_scriptElement = element; + m_scriptElement = &element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and addClient() executed it. if (m_pendingScript) pauseParsing(); } else - m_scriptElement = 0; + m_scriptElement = nullptr; // JavaScript may have detached the parser if (isDetached()) @@ -937,7 +954,7 @@ void XMLDocumentParser::characters(const xmlChar* s, int len) } if (!m_leafTextNode) - enterText(); + createLeafTextNode(); m_bufferedText.append(s, len); } @@ -955,8 +972,9 @@ void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va vsnprintf(m, sizeof(m) - 1, message, args); #endif + TextPosition position = textPosition(); if (m_parserPaused) - m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(m), lineNumber(), columnNumber()); + m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(m), position.m_line, position.m_column); else handleError(type, m, textPosition()); @@ -975,20 +993,19 @@ void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlCh return; } - exitText(); + if (!updateLeafTextNode()) + return; // ### handle exceptions ExceptionCode ec = 0; - RefPtr<ProcessingInstruction> pi = m_currentNode->document()->createProcessingInstruction( + Ref<ProcessingInstruction> pi = *m_currentNode->document().createProcessingInstruction( toString(target), toString(data), ec); if (ec) return; pi->setCreatedByParser(true); - m_currentNode->parserAppendChild(pi.get()); - if (m_view && !pi->attached()) - pi->attach(); + m_currentNode->parserAppendChild(pi.copyRef()); pi->finishParsingChildren(); @@ -1011,12 +1028,11 @@ void XMLDocumentParser::cdataBlock(const xmlChar* s, int len) return; } - exitText(); + if (!updateLeafTextNode()) + return; - RefPtr<CDATASection> newNode = CDATASection::create(m_currentNode->document(), toString(s, len)); - m_currentNode->parserAppendChild(newNode.get()); - if (m_view && !newNode->attached()) - newNode->attach(); + auto newNode = CDATASection::create(m_currentNode->document(), toString(s, len)); + m_currentNode->parserAppendChild(WTFMove(newNode)); } void XMLDocumentParser::comment(const xmlChar* s) @@ -1029,12 +1045,11 @@ void XMLDocumentParser::comment(const xmlChar* s) return; } - exitText(); + if (!updateLeafTextNode()) + return; - RefPtr<Comment> newNode = Comment::create(m_currentNode->document(), toString(s)); - m_currentNode->parserAppendChild(newNode.get()); - if (m_view && !newNode->attached()) - newNode->attach(); + auto newNode = Comment::create(m_currentNode->document(), toString(s)); + m_currentNode->parserAppendChild(WTFMove(newNode)); } enum StandaloneInfo { @@ -1063,7 +1078,7 @@ void XMLDocumentParser::startDocument(const xmlChar* version, const xmlChar* enc void XMLDocumentParser::endDocument() { - exitText(); + updateLeafTextNode(); } void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID) @@ -1077,7 +1092,7 @@ void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* exter } if (document()) - document()->parserAppendChild(DocumentType::create(document(), toString(name), toString(externalID), toString(systemID))); + document()->parserAppendChild(DocumentType::create(*document(), toString(name), toString(externalID), toString(systemID))); } static inline XMLDocumentParser* getParser(void* closure) @@ -1340,7 +1355,7 @@ void XMLDocumentParser::initializeParserContext(const CString& chunk) m_sawXSLTransform = false; m_sawFirstElement = false; - XMLDocumentParserScope scope(document()->cachedResourceLoader()); + XMLDocumentParserScope scope(&document()->cachedResourceLoader()); if (m_parsingFragment) m_context = XMLParserContext::createMemoryParser(&sax, this, chunk); else { @@ -1355,23 +1370,22 @@ void XMLDocumentParser::doEnd() if (m_context) { // Tell libxml we're done. { - XMLDocumentParserScope scope(document()->cachedResourceLoader()); + XMLDocumentParserScope scope(&document()->cachedResourceLoader()); xmlParseChunk(context(), 0, 0, 1); } - m_context = 0; + m_context = nullptr; } } #if ENABLE(XSLT) - XMLTreeViewer xmlTreeViewer(document()); - bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && xmlTreeViewer.hasNoStyleInformation(); - if (xmlViewerMode) + bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && hasNoStyleInformation(document()); + if (xmlViewerMode) { + XMLTreeViewer xmlTreeViewer(*document()); xmlTreeViewer.transformDocumentToTreeView(); - - if (m_sawXSLTransform) { + } else if (m_sawXSLTransform) { void* doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform.toString(), document()->url().string()); - document()->setTransformSource(adoptPtr(new TransformSource(doc))); + document()->setTransformSource(std::make_unique<TransformSource>(doc)); document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets. document()->styleResolverChanged(RecalcStyleImmediately); @@ -1395,10 +1409,10 @@ static inline const char* nativeEndianUTF16Encoding() return BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE"; } -void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const String& source, const String& url) +void* xmlDocPtrForString(CachedResourceLoader& cachedResourceLoader, const String& source, const String& url) { if (source.isEmpty()) - return 0; + return nullptr; // Parse in a single chunk into an xmlDocPtr // FIXME: Hook up error handlers so that a failure to parse the main document results in @@ -1409,21 +1423,11 @@ void* xmlDocPtrForString(CachedResourceLoader* cachedResourceLoader, const Strin size_t sizeInBytes = source.length() * (is8Bit ? sizeof(LChar) : sizeof(UChar)); const char* encoding = is8Bit ? "iso-8859-1" : nativeEndianUTF16Encoding(); - XMLDocumentParserScope scope(cachedResourceLoader, errorFunc, 0); + XMLDocumentParserScope scope(&cachedResourceLoader, errorFunc); return xmlReadMemory(characters, sizeInBytes, url.latin1().data(), encoding, XSLT_PARSE_OPTIONS); } #endif -OrdinalNumber XMLDocumentParser::lineNumber() const -{ - return OrdinalNumber::fromOneBasedInt(context() ? context()->input->line : 1); -} - -OrdinalNumber XMLDocumentParser::columnNumber() const -{ - return OrdinalNumber::fromOneBasedInt(context() ? context()->input->col : 1); -} - TextPosition XMLDocumentParser::textPosition() const { xmlParserCtxtPtr context = this->context(); @@ -1433,6 +1437,11 @@ TextPosition XMLDocumentParser::textPosition() const OrdinalNumber::fromOneBasedInt(context->input->col)); } +bool XMLDocumentParser::shouldAssociateConsoleMessagesWithTextPosition() const +{ + return !m_parserPaused && !m_requestingScript; +} + void XMLDocumentParser::stopParsing() { DocumentParser::stopParsing(); @@ -1533,6 +1542,8 @@ static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) { + String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; + AttributeParseState state; state.gotAttributes = false; @@ -1540,11 +1551,14 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) memset(&sax, 0, sizeof(sax)); sax.startElementNs = attributesStartElementNsHandler; sax.initialized = XML_SAX2_MAGIC; + RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state); - String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; - xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1); + + // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16? + xmlParseChunk(parser->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), parseString.length() * sizeof(UChar), 1); + attrsOK = state.gotAttributes; - return state.attributes; + return WTFMove(state.attributes); } } diff --git a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp b/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp deleted file mode 100644 index 83fb33422..000000000 --- a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (C) 2000 Peter Kelly (pmk@post.com) - * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) - * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008 Holger Hans Peter Freyther - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "XMLDocumentParser.h" - -#include "CDATASection.h" -#include "CachedScript.h" -#include "Comment.h" -#include "CachedResourceLoader.h" -#include "Document.h" -#include "DocumentFragment.h" -#include "DocumentType.h" -#include "ExceptionCodePlaceholder.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameView.h" -#include "HTMLEntityParser.h" -#include "HTMLHtmlElement.h" -#include "HTMLLinkElement.h" -#include "HTMLNames.h" -#include "HTMLStyleElement.h" -#include "ProcessingInstruction.h" -#include "ResourceError.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "ScriptableDocumentParser.h" -#include "ScriptElement.h" -#include "ScriptSourceCode.h" -#include "ScriptValue.h" -#include "TextResourceDecoder.h" -#include "TransformSource.h" -#include "XMLNSNames.h" -#include <QDebug> -#include <wtf/StringExtras.h> -#include <wtf/Threading.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> - -using namespace std; - -namespace WebCore { - -static inline void setAttributes(Element* element, Vector<Attribute>& attributeVector, ParserContentPolicy parserContentPolicy) -{ - if (!scriptingContentIsAllowed(parserContentPolicy)) - element->stripScriptingAttributes(attributeVector); - element->parserSetAttributes(attributeVector); -} - -class EntityResolver : public QXmlStreamEntityResolver { - virtual QString resolveUndeclaredEntity(const QString &name); -}; - -static QString decodeNamedEntity(const QString& entityName) -{ - UChar utf16DecodedEntity[4]; - size_t numberOfCodePoints = decodeNamedEntityToUCharArray(entityName.toUtf8().constData(), utf16DecodedEntity); - return QString(reinterpret_cast<const QChar*>(utf16DecodedEntity), numberOfCodePoints); -} - -QString EntityResolver::resolveUndeclaredEntity(const QString &name) -{ - return decodeNamedEntity(name); -} - -// -------------------------------- - -bool XMLDocumentParser::supportsXMLVersion(const String& version) -{ - return version == "1.0"; -} - -XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView) - : ScriptableDocumentParser(document) - , m_view(frameView) - , m_wroteText(false) - , m_currentNode(document) - , m_sawError(false) - , m_sawCSS(false) - , m_sawXSLTransform(false) - , m_sawFirstElement(false) - , m_isXHTMLDocument(false) - , m_parserPaused(false) - , m_requestingScript(false) - , m_finishCalled(false) - , m_xmlErrors(document) - , m_pendingScript(0) - , m_scriptStartPosition(TextPosition::belowRangePosition()) - , m_parsingFragment(false) -{ - m_stream.setEntityResolver(new EntityResolver); -} - -XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parentElement, ParserContentPolicy parserContentPolicy) - : ScriptableDocumentParser(fragment->document(), parserContentPolicy) - , m_view(0) - , m_wroteText(false) - , m_currentNode(fragment) - , m_sawError(false) - , m_sawCSS(false) - , m_sawXSLTransform(false) - , m_sawFirstElement(false) - , m_isXHTMLDocument(false) - , m_parserPaused(false) - , m_requestingScript(false) - , m_finishCalled(false) - , m_xmlErrors(fragment->document()) - , m_pendingScript(0) - , m_scriptStartPosition(TextPosition::belowRangePosition()) - , m_parsingFragment(true) -{ - fragment->ref(); - - // Add namespaces based on the parent node - Vector<Element*> elemStack; - while (parentElement) { - elemStack.append(parentElement); - - Node* n = parentElement->parentNode(); - if (!n || !n->isElementNode()) - break; - parentElement = toElement(n); - } - - if (elemStack.isEmpty()) - return; - - QXmlStreamNamespaceDeclarations namespaces; - for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { - element->synchronizeAllAttributes(); - if (const ElementData* attrs = element->elementData()) { - for (unsigned i = 0; i < attrs->length(); i++) { - const Attribute* attr = attrs->attributeItem(i); - if (attr->localName() == "xmlns") - m_defaultNamespaceURI = attr->value(); - else if (attr->prefix() == "xmlns") - namespaces.append(QXmlStreamNamespaceDeclaration(attr->localName(), attr->value())); - } - } - } - m_stream.addExtraNamespaceDeclarations(namespaces); - m_stream.setEntityResolver(new EntityResolver); - - // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace. - if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument()) - m_defaultNamespaceURI = parentElement->namespaceURI(); -} - -XMLDocumentParser::~XMLDocumentParser() -{ - clearCurrentNodeStack(); - if (m_pendingScript) - m_pendingScript->removeClient(this); - delete m_stream.entityResolver(); -} - -void XMLDocumentParser::doWrite(const String& parseString) -{ - m_wroteText = true; - - if (document()->decoder() && document()->decoder()->sawError()) { - // If the decoder saw an error, report it as fatal (stops parsing) - handleError(XMLErrors::fatal, "Encoding error", textPosition()); - return; - } - - QString data(parseString); - if (!data.isEmpty()) { - // JavaScript may cause the parser to detach, - // keep this alive until this function is done. - RefPtr<XMLDocumentParser> protect(this); - - m_stream.addData(data); - parse(); - } - - return; -} - -void XMLDocumentParser::initializeParserContext(const CString&) -{ - DocumentParser::startParsing(); - m_sawError = false; - m_sawCSS = false; - m_sawXSLTransform = false; - m_sawFirstElement = false; -} - -void XMLDocumentParser::doEnd() -{ -#if ENABLE(XSLT) - if (m_sawXSLTransform) { - document()->setTransformSource(adoptPtr(new TransformSource(m_originalSourceForTransform.toString()))); - document()->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets. - document()->styleResolverChanged(RecalcStyleImmediately); - - // styleResolverChanged() call can detach the parser and null out its document. - // In that case, we just bail out. - if (isDetached()) - return; - - document()->setParsing(true); - DocumentParser::stopParsing(); - } -#endif - - if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError - || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform && !m_sawError)) - handleError(XMLErrors::fatal, qPrintable(m_stream.errorString()), textPosition()); -} - -OrdinalNumber XMLDocumentParser::lineNumber() const -{ - return OrdinalNumber::fromOneBasedInt(m_stream.lineNumber()); -} - -OrdinalNumber XMLDocumentParser::columnNumber() const -{ - return OrdinalNumber::fromOneBasedInt(m_stream.columnNumber()); -} - -TextPosition XMLDocumentParser::textPosition() const -{ - return TextPosition(lineNumber(), columnNumber()); -} - -void XMLDocumentParser::stopParsing() -{ - ScriptableDocumentParser::stopParsing(); -} - -void XMLDocumentParser::resumeParsing() -{ - ASSERT(m_parserPaused); - - m_parserPaused = false; - - // First, execute any pending callbacks - parse(); - if (m_parserPaused) - return; - - // Then, write any pending data - SegmentedString rest = m_pendingSrc; - m_pendingSrc.clear(); - append(rest.toString().impl()); - - // Finally, if finish() has been called and append() didn't result - // in any further callbacks being queued, call end() - if (m_finishCalled && !m_parserPaused && !m_pendingScript) - end(); -} - -bool XMLDocumentParser::appendFragmentSource(const String& source) -{ - ASSERT(!m_sawFirstElement); - append(String("<qxmlstreamdummyelement>").impl()); - append(source.impl()); - append(String("</qxmlstreamdummyelement>").impl()); - return !hasError(); -} - -// -------------------------------- - -struct AttributeParseState { - HashMap<String, String> attributes; - bool gotAttributes; -}; - -static void attributesStartElementNsHandler(AttributeParseState* state, const QXmlStreamAttributes& attrs) -{ - if (attrs.count() <= 0) - return; - - state->gotAttributes = true; - - for (int i = 0; i < attrs.count(); i++) { - const QXmlStreamAttribute& attr = attrs[i]; - String attrLocalName = attr.name(); - String attrValue = attr.value(); - String attrURI = attr.namespaceUri(); - String attrQName = attr.qualifiedName(); - state->attributes.set(attrQName, attrValue); - } -} - -HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) -{ - AttributeParseState state; - state.gotAttributes = false; - - QXmlStreamReader stream; - QString dummy = QString(QLatin1String("<?xml version=\"1.0\"?><attrs %1 />")).arg(string); - stream.addData(dummy); - while (!stream.atEnd()) { - stream.readNext(); - if (stream.isStartElement()) { - attributesStartElementNsHandler(&state, stream.attributes()); - } - } - attrsOK = state.gotAttributes; - return state.attributes; -} - -static inline String prefixFromQName(const QString& qName) -{ - const int offset = qName.indexOf(QLatin1Char(':')); - if (offset <= 0) - return String(); - else - return qName.left(offset); -} - -static inline void handleNamespaceAttributes(Vector<Attribute>& prefixedAttributes, const QXmlStreamNamespaceDeclarations &ns, ExceptionCode& ec) -{ - for (int i = 0; i < ns.count(); ++i) { - const QXmlStreamNamespaceDeclaration &decl = ns[i]; - String namespaceURI = decl.namespaceUri(); - String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:"); - namespaceQName.append(decl.prefix()); - - QualifiedName parsedName = anyName; - if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceURI, namespaceQName, ec)) - return; - - prefixedAttributes.append(Attribute(parsedName, namespaceURI)); - } -} - -static inline void handleElementAttributes(Vector<Attribute>& prefixedAttributes, const QXmlStreamAttributes &attrs, ExceptionCode& ec) -{ - for (int i = 0; i < attrs.count(); ++i) { - const QXmlStreamAttribute &attr = attrs[i]; - String attrLocalName = attr.name(); - String attrValue = attr.value(); - String attrURI = attr.namespaceUri().isEmpty() ? String() : String(attr.namespaceUri()); - String attrQName = attr.qualifiedName(); - - QualifiedName parsedName = anyName; - if (!Element::parseAttributeName(parsedName, attrURI, attrQName, ec)) - return; - - prefixedAttributes.append(Attribute(parsedName, attrValue)); - } -} - -void XMLDocumentParser::parse() -{ - while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) { - m_stream.readNext(); - switch (m_stream.tokenType()) { - case QXmlStreamReader::StartDocument: - startDocument(); - break; - case QXmlStreamReader::EndDocument: - endDocument(); - break; - case QXmlStreamReader::StartElement: - parseStartElement(); - break; - case QXmlStreamReader::EndElement: - parseEndElement(); - break; - case QXmlStreamReader::Characters: { - if (m_stream.isCDATA()) { - //cdata - parseCdata(); - } else { - //characters - parseCharacters(); - } - break; - } - case QXmlStreamReader::Comment: - parseComment(); - break; - case QXmlStreamReader::DTD: - //qDebug()<<"------------- DTD"; - parseDtd(); - break; - case QXmlStreamReader::EntityReference: { - //qDebug()<<"---------- ENTITY = "<<m_stream.name().toString() - // <<", t = "<<m_stream.text().toString(); - if (isXHTMLDocument()) { - QString entity = m_stream.name().toString(); - if (!m_leafTextNode) - enterText(); - // qDebug()<<" ------- adding entity "<<str; - m_leafTextNode->appendData(decodeNamedEntity(entity), IGNORE_EXCEPTION); - } - break; - } - case QXmlStreamReader::ProcessingInstruction: - parseProcessingInstruction(); - break; - default: { - if (m_stream.error() != QXmlStreamReader::PrematureEndOfDocumentError) { - XMLErrors::ErrorType type = (m_stream.error() == QXmlStreamReader::NotWellFormedError) ? - XMLErrors::fatal : XMLErrors::warning; - handleError(type, qPrintable(m_stream.errorString()), textPosition()); - } - break; - } - } - } -} - -void XMLDocumentParser::startDocument() -{ - initializeParserContext(); - - if (!m_parsingFragment) { - document()->setXMLStandalone(m_stream.isStandaloneDocument(), IGNORE_EXCEPTION); - - QStringRef version = m_stream.documentVersion(); - if (!version.isEmpty()) - document()->setXMLVersion(version, IGNORE_EXCEPTION); - QStringRef encoding = m_stream.documentEncoding(); - if (!encoding.isEmpty()) - document()->setXMLEncoding(encoding); - document()->setHasXMLDeclaration(!version.isEmpty()); - } -} - -void XMLDocumentParser::parseStartElement() -{ - if (!m_sawFirstElement && m_parsingFragment) { - // skip dummy element for fragments - m_sawFirstElement = true; - return; - } - - exitText(); - - String localName = m_stream.name(); - String uri = m_stream.namespaceUri(); - String prefix = prefixFromQName(m_stream.qualifiedName().toString()); - - if (m_parsingFragment && uri.isNull()) { - Q_ASSERT(prefix.isNull()); - uri = m_defaultNamespaceURI; - } - - QualifiedName qName(prefix, localName, uri); - RefPtr<Element> newElement = document()->createElement(qName, true); - if (!newElement) { - stopParsing(); - return; - } - - bool isFirstElement = !m_sawFirstElement; - m_sawFirstElement = true; - - Vector<Attribute> prefixedAttributes; - ExceptionCode ec = 0; - handleNamespaceAttributes(prefixedAttributes, m_stream.namespaceDeclarations(), ec); - if (ec) { - setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); - stopParsing(); - return; - } - - handleElementAttributes(prefixedAttributes, m_stream.attributes(), ec); - setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); - if (ec) { - stopParsing(); - return; - } - - ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get()); - if (scriptElement) - m_scriptStartPosition = textPosition(); - - m_currentNode->parserAppendChild(newElement.get()); - - pushCurrentNode(newElement.get()); - if (m_view && !newElement->attached()) - newElement->attach(); - - if (newElement->hasTagName(HTMLNames::htmlTag)) - static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser(); - - if (isFirstElement && document()->frame()) - document()->frame()->loader()->dispatchDocumentElementAvailable(); -} - -void XMLDocumentParser::parseEndElement() -{ - exitText(); - - RefPtr<ContainerNode> n = m_currentNode; - n->finishParsingChildren(); - - if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptElementIfPossible(toElement(n.get()))) { - popCurrentNode(); - n->remove(IGNORE_EXCEPTION); - return; - } - - if (!n->isElementNode() || !m_view) { - if (!m_currentNodeStack.isEmpty()) - popCurrentNode(); - return; - } - - Element* element = toElement(n.get()); - - // The element's parent may have already been removed from document. - // Parsing continues in this case, but scripts aren't executed. - if (!element->inDocument()) { - popCurrentNode(); - return; - } - - ScriptElement* scriptElement = toScriptElementIfPossible(element); - if (!scriptElement) { - popCurrentNode(); - return; - } - - // don't load external scripts for standalone documents (for now) - ASSERT(!m_pendingScript); - m_requestingScript = true; - - if (scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) { - if (scriptElement->readyToBeParserExecuted()) - scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); - else if (scriptElement->willBeParserExecuted()) { - m_pendingScript = scriptElement->cachedScript(); - m_scriptElement = element; - m_pendingScript->addClient(this); - - // m_pendingScript will be 0 if script was already loaded and addClient() executed it. - if (m_pendingScript) - pauseParsing(); - } else - m_scriptElement = 0; - } - m_requestingScript = false; - popCurrentNode(); -} - -void XMLDocumentParser::parseCharacters() -{ - if (!m_leafTextNode) - enterText(); - m_leafTextNode->appendData(m_stream.text(), IGNORE_EXCEPTION); -} - -void XMLDocumentParser::parseProcessingInstruction() -{ - exitText(); - - // ### handle exceptions - int exception = 0; - RefPtr<ProcessingInstruction> pi = document()->createProcessingInstruction( - m_stream.processingInstructionTarget(), - m_stream.processingInstructionData(), exception); - if (exception) - return; - - pi->setCreatedByParser(true); - - m_currentNode->parserAppendChild(pi.get()); - if (m_view && !pi->attached()) - pi->attach(); - - pi->finishParsingChildren(); - - if (pi->isCSS()) - m_sawCSS = true; -#if ENABLE(XSLT) - m_sawXSLTransform = !m_sawFirstElement && pi->isXSL(); - if (m_sawXSLTransform && !document()->transformSourceDocument()) - stopParsing(); -#endif -} - -void XMLDocumentParser::parseCdata() -{ - exitText(); - - RefPtr<CDATASection> newNode = CDATASection::create(document(), m_stream.text()); - - m_currentNode->parserAppendChild(newNode.get()); - if (m_view && !newNode->attached()) - newNode->attach(); -} - -void XMLDocumentParser::parseComment() -{ - exitText(); - - RefPtr<Comment> newNode = Comment::create(document(), m_stream.text()); - - m_currentNode->parserAppendChild(newNode.get()); - if (m_view && !newNode->attached()) - newNode->attach(); -} - -void XMLDocumentParser::endDocument() -{ -} - -bool XMLDocumentParser::hasError() const -{ - return m_stream.hasError(); -} - -void XMLDocumentParser::parseDtd() -{ - QStringRef name = m_stream.dtdName(); - QStringRef publicId = m_stream.dtdPublicId(); - QStringRef systemId = m_stream.dtdSystemId(); - - //qDebug() << dtd << name << publicId << systemId; - if ((publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Transitional//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Strict//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Frameset//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML Basic 1.0//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")) - || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")) - || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.0//EN")) - || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.1//EN")) - || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.2//EN")) - ) - setIsXHTMLDocument(true); // controls if we replace entities or not. - if (!m_parsingFragment) - document()->parserAppendChild(DocumentType::create(document(), name, publicId, systemId)); - -} -} diff --git a/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp b/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp index 0a473ed23..c0f3590bf 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp +++ b/Source/WebCore/xml/parser/XMLDocumentParserScope.cpp @@ -28,7 +28,7 @@ namespace WebCore { -CachedResourceLoader* XMLDocumentParserScope::currentCachedResourceLoader = 0; +CachedResourceLoader* XMLDocumentParserScope::currentCachedResourceLoader = nullptr; XMLDocumentParserScope::XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader) : m_oldCachedResourceLoader(currentCachedResourceLoader) diff --git a/Source/WebCore/xml/parser/XMLDocumentParserScope.h b/Source/WebCore/xml/parser/XMLDocumentParserScope.h index c04043b48..82eabbfbb 100644 --- a/Source/WebCore/xml/parser/XMLDocumentParserScope.h +++ b/Source/WebCore/xml/parser/XMLDocumentParserScope.h @@ -39,13 +39,13 @@ namespace WebCore { class XMLDocumentParserScope { WTF_MAKE_NONCOPYABLE(XMLDocumentParserScope); public: - XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader); + explicit XMLDocumentParserScope(CachedResourceLoader*); ~XMLDocumentParserScope(); static CachedResourceLoader* currentCachedResourceLoader; #if ENABLE(XSLT) - XMLDocumentParserScope(CachedResourceLoader* cachedResourceLoader, xmlGenericErrorFunc genericErrorFunc, xmlStructuredErrorFunc structuredErrorFunc = 0, void* errorContext = 0); + XMLDocumentParserScope(CachedResourceLoader*, xmlGenericErrorFunc, xmlStructuredErrorFunc structuredErrorFunc = 0, void* errorContext = nullptr); #endif private: |