src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp
changeset 19 fcece45ef507
parent 3 41300fa6a67c
child 30 5dc02b23752f
--- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp	Mon May 03 13:17:34 2010 +0300
@@ -465,7 +465,7 @@
 
 static bool didInit = false;
 
-static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData)
+PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
 {
     if (!didInit) {
         xmlInitParser();
@@ -482,12 +482,12 @@
     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
     xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
 
-    return parser;
+    return adoptRef(new XMLParserContext(parser));
 }
 
 
 // Chunk should be encoded in UTF-8
-static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
+PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
 {
     if (!didInit) {
         xmlInitParser();
@@ -518,8 +518,8 @@
     parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5);
     parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
     parser->_private = userData;
-
-    return parser;
+    
+    return adoptRef(new XMLParserContext(parser));
 }
 
 // --------------------------------
@@ -609,6 +609,13 @@
         m_defaultNamespaceURI = parentElement->namespaceURI();
 }
 
+XMLParserContext::~XMLParserContext()
+{
+    if (m_context->myDoc)
+        xmlFreeDoc(m_context->myDoc);
+    xmlFreeParserCtxt(m_context);
+}
+
 XMLTokenizer::~XMLTokenizer()
 {
     clearCurrentNodeStack();
@@ -616,15 +623,16 @@
         m_doc->deref();
     if (m_pendingScript)
         m_pendingScript->removeClient(this);
-    if (m_context)
-        xmlFreeParserCtxt(m_context);
 }
 
 void XMLTokenizer::doWrite(const String& parseString)
 {
     if (!m_context)
         initializeParserContext();
-    
+
+    // Protect the libxml context from deletion during a callback
+    RefPtr<XMLParserContext> context = m_context;
+
     // libXML throws an error if you try to switch the encoding for an empty string.
     if (parseString.length()) {
         // Hack around libxml2's lack of encoding overide support by manually
@@ -633,15 +641,15 @@
         // and switch encodings, causing the parse to fail.
         const UChar BOM = 0xFEFF;
         const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
-        xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
+        xmlSwitchEncoding(context->context(), BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
 
         XMLTokenizerScope scope(m_doc->docLoader());
-        xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
+        xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
     }
     
     if (m_doc->decoder() && m_doc->decoder()->sawError()) {
         // If the decoder saw an error, report it as fatal (stops parsing)
-        handleError(fatal, "Encoding error", lineNumber(), columnNumber());
+        handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col);
     }
 
     return;
@@ -1277,9 +1285,9 @@
 
     XMLTokenizerScope scope(m_doc->docLoader());
     if (m_parsingFragment)
-        m_context = createMemoryParser(&sax, this, chunk);
+        m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
     else
-        m_context = createStringParser(&sax, this);
+        m_context = XMLParserContext::createStringParser(&sax, this);
 }
 
 void XMLTokenizer::doEnd()
@@ -1300,12 +1308,9 @@
         // Tell libxml we're done.
         {
             XMLTokenizerScope scope(m_doc->docLoader());
-            xmlParseChunk(m_context, 0, 0, 1);
+            xmlParseChunk(context(), 0, 0, 1);
         }
 
-        if (m_context->myDoc)
-            xmlFreeDoc(m_context->myDoc);
-        xmlFreeParserCtxt(m_context);
         m_context = 0;
     }
 }
@@ -1334,18 +1339,19 @@
 
 int XMLTokenizer::lineNumber() const
 {
-    return m_context ? m_context->input->line : 1;
+    return context() ? context()->input->line : 1;
 }
 
 int XMLTokenizer::columnNumber() const
 {
-    return m_context ? m_context->input->col : 1;
+    return context() ? context()->input->col : 1;
 }
 
 void XMLTokenizer::stopParsing()
 {
     Tokenizer::stopParsing();
-    xmlStopParser(m_context);
+    if (context())
+        xmlStopParser(context());
 }
 
 void XMLTokenizer::resumeParsing()
@@ -1384,17 +1390,17 @@
     CString chunkAsUtf8 = chunk.utf8();
     tokenizer.initializeParserContext(chunkAsUtf8.data());
 
-    xmlParseContent(tokenizer.m_context);
+    xmlParseContent(tokenizer.context());
 
     tokenizer.endDocument();
 
     // Check if all the chunk has been processed.
-    long bytesProcessed = xmlByteConsumed(tokenizer.m_context);
+    long bytesProcessed = xmlByteConsumed(tokenizer.context());
     if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length())
         return false;
 
     // No error if the chunk is well formed or it is not but we have no error.
-    return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0;
+    return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0;
 }
 
 // --------------------------------
@@ -1437,12 +1443,9 @@
     memset(&sax, 0, sizeof(sax));
     sax.startElementNs = attributesStartElementNsHandler;
     sax.initialized = XML_SAX2_MAGIC;
-    xmlParserCtxtPtr parser = createStringParser(&sax, &state);
+    RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
     String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
-    xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
-    if (parser->myDoc)
-        xmlFreeDoc(parser->myDoc);
-    xmlFreeParserCtxt(parser);
+    xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
     attrsOK = state.gotAttributes;
     return state.attributes;
 }