summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/XMLDocumentParserLibxml2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom/XMLDocumentParserLibxml2.cpp')
-rw-r--r--WebCore/dom/XMLDocumentParserLibxml2.cpp90
1 files changed, 59 insertions, 31 deletions
diff --git a/WebCore/dom/XMLDocumentParserLibxml2.cpp b/WebCore/dom/XMLDocumentParserLibxml2.cpp
index 1309827..37da83c 100644
--- a/WebCore/dom/XMLDocumentParserLibxml2.cpp
+++ b/WebCore/dom/XMLDocumentParserLibxml2.cpp
@@ -522,6 +522,11 @@ PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerP
// --------------------------------
+bool XMLDocumentParser::supportsXMLVersion(const String& version)
+{
+ return version == "1.0";
+}
+
XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView)
: ScriptableDocumentParser(document)
, m_view(frameView)
@@ -616,13 +621,18 @@ XMLParserContext::~XMLParserContext()
XMLDocumentParser::~XMLDocumentParser()
{
- clearCurrentNodeStack();
+ // The XMLDocumentParser will always be detached before being destroyed.
+ ASSERT(m_currentNodeStack.isEmpty());
+ ASSERT(!m_currentNode);
+
+ // FIXME: m_pendingScript handling should be moved into XMLDocumentParser.cpp!
if (m_pendingScript)
m_pendingScript->removeClient(this);
}
void XMLDocumentParser::doWrite(const String& parseString)
{
+ ASSERT(!isDetached());
if (!m_context)
initializeParserContext();
@@ -631,6 +641,10 @@ void XMLDocumentParser::doWrite(const String& parseString)
// libXML throws an error if you try to switch the encoding for an empty string.
if (parseString.length()) {
+ // JavaScript may cause the parser to detach during xmlParseChunk
+ // keep this alive until this function is done.
+ RefPtr<XMLDocumentParser> protect(this);
+
// Hack around libxml2's lack of encoding overide support by manually
// resetting the encoding to UTF-16 before every chunk. Otherwise libxml
// will detect <?xml version="1.0" encoding="<encoding name>"?> blocks
@@ -641,14 +655,18 @@ void XMLDocumentParser::doWrite(const String& parseString)
XMLDocumentParserScope scope(document()->docLoader());
xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
+
+ // JavaScript (which may be run under the xmlParseChunk callstack) may
+ // cause the parser to be stopped or detached.
+ if (isDetached() || m_parserStopped)
+ return;
}
+ // FIXME: Why is this here? And why is it after we process the passed source?
if (document()->decoder() && document()->decoder()->sawError()) {
// If the decoder saw an error, report it as fatal (stops parsing)
handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col);
}
-
- return;
}
static inline String toString(const xmlChar* str, unsigned len)
@@ -790,10 +808,7 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha
if (scriptElement)
m_scriptStartLine = lineNumber();
- if (!m_currentNode->legacyParserAddChild(newElement.get())) {
- stopParsing();
- return;
- }
+ m_currentNode->deprecatedParserAddChild(newElement.get());
pushCurrentNode(newElement.get());
if (m_view && !newElement->attached())
@@ -855,6 +870,13 @@ void XMLDocumentParser::endElementNs()
else
#endif
{
+ // FIXME: Script execution should be shared should be shared between
+ // the libxml2 and Qt XMLDocumentParser implementations.
+
+ // JavaScript can detach the parser. Make sure this is not released
+ // before the end of this method.
+ RefPtr<XMLDocumentParser> protect(this);
+
String scriptHref = scriptElement->sourceAttributeValue();
if (!scriptHref.isEmpty()) {
// we have a src attribute
@@ -871,6 +893,10 @@ void XMLDocumentParser::endElementNs()
m_scriptElement = 0;
} else
m_view->frame()->script()->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartLine));
+
+ // JavaScript may have detached the parser
+ if (isDetached())
+ return;
}
m_requestingScript = false;
popCurrentNode();
@@ -886,8 +912,9 @@ void XMLDocumentParser::characters(const xmlChar* s, int len)
return;
}
- if (m_currentNode->isTextNode() || enterText())
- m_bufferedText.append(s, len);
+ if (!m_currentNode->isTextNode())
+ enterText();
+ m_bufferedText.append(s, len);
}
void XMLDocumentParser::error(ErrorType type, const char* message, va_list args)
@@ -935,8 +962,7 @@ void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlCh
pi->setCreatedByParser(true);
- if (!m_currentNode->legacyParserAddChild(pi.get()))
- return;
+ m_currentNode->deprecatedParserAddChild(pi.get());
if (m_view && !pi->attached())
pi->attach();
@@ -962,8 +988,7 @@ void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
exitText();
RefPtr<Node> newNode = CDATASection::create(document(), toString(s, len));
- if (!m_currentNode->legacyParserAddChild(newNode.get()))
- return;
+ m_currentNode->deprecatedParserAddChild(newNode.get());
if (m_view && !newNode->attached())
newNode->attach();
}
@@ -981,7 +1006,7 @@ void XMLDocumentParser::comment(const xmlChar* s)
exitText();
RefPtr<Node> newNode = Comment::create(document(), toString(s));
- m_currentNode->legacyParserAddChild(newNode.get());
+ m_currentNode->deprecatedParserAddChild(newNode.get());
if (m_view && !newNode->attached())
newNode->attach();
}
@@ -1045,7 +1070,7 @@ void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* exter
}
#endif
- document()->legacyParserAddChild(DocumentType::create(document(), toString(name), toString(externalID), toString(systemID)));
+ document()->parserAddChild(DocumentType::create(document(), toString(name), toString(externalID), toString(systemID)));
}
}
@@ -1274,8 +1299,10 @@ void XMLDocumentParser::initializeParserContext(const char* chunk)
XMLDocumentParserScope scope(document()->docLoader());
if (m_parsingFragment)
m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
- else
+ else {
+ ASSERT(!chunk);
m_context = XMLParserContext::createStringParser(&sax, this);
+ }
}
void XMLDocumentParser::doEnd()
@@ -1347,6 +1374,7 @@ void XMLDocumentParser::stopParsing()
void XMLDocumentParser::resumeParsing()
{
+ ASSERT(!isDetached());
ASSERT(m_parserPaused);
m_parserPaused = false;
@@ -1371,29 +1399,29 @@ void XMLDocumentParser::resumeParsing()
end();
}
-// FIXME: This method should be possible to implement using the DocumentParser
-// API, instead of needing to grab at libxml2 state directly.
-bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* parent, FragmentScriptingPermission scriptingPermission)
+bool XMLDocumentParser::appendFragmentSource(const String& chunk)
{
- if (!chunk.length())
- return true;
-
- XMLDocumentParser parser(fragment, parent, scriptingPermission);
+ ASSERT(!m_context);
+ ASSERT(m_parsingFragment);
CString chunkAsUtf8 = chunk.utf8();
- parser.initializeParserContext(chunkAsUtf8.data());
-
- xmlParseContent(parser.context());
-
- parser.endDocument();
+ initializeParserContext(chunkAsUtf8.data());
+ xmlParseContent(context());
+ endDocument(); // Close any open text nodes.
+ // FIXME: If this code is actually needed, it should probably move to finish()
+ // XMLDocumentParserQt has a similar check (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError) in doEnd().
// Check if all the chunk has been processed.
- long bytesProcessed = xmlByteConsumed(parser.context());
- if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length())
+ long bytesProcessed = xmlByteConsumed(context());
+ if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length()) {
+ // FIXME: I don't believe we can hit this case without also having seen an error.
+ // If we hit this ASSERT, we've found a test case which demonstrates the need for this code.
+ ASSERT(m_sawError);
return false;
+ }
// No error if the chunk is well formed or it is not but we have no error.
- return parser.context()->wellFormed || xmlCtxtGetLastError(parser.context()) == 0;
+ return context()->wellFormed || !xmlCtxtGetLastError(context());
}
// --------------------------------