Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: Source/core/xml/parser/XMLDocumentParser.cpp

Issue 1267283002: Gracefully handle XMLDocumentParser being detached by mutation events. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: add clarifying comment Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/xml/parser/XMLDocumentParser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2000 Peter Kelly (pmk@post.com) 2 * Copyright (C) 2000 Peter Kelly (pmk@post.com)
3 * Copyright (C) 2005, 2006, 2008, 2014 Apple Inc. All rights reserved. 3 * Copyright (C) 2005, 2006, 2008, 2014 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
5 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) 5 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7 * Copyright (C) 2008 Holger Hans Peter Freyther 7 * Copyright (C) 2008 Holger Hans Peter Freyther
8 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 8 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 373
374 void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* forma ttedMessage, TextPosition position) 374 void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* forma ttedMessage, TextPosition position)
375 { 375 {
376 m_xmlErrors.handleError(type, formattedMessage, position); 376 m_xmlErrors.handleError(type, formattedMessage, position);
377 if (type != XMLErrors::ErrorTypeWarning) 377 if (type != XMLErrors::ErrorTypeWarning)
378 m_sawError = true; 378 m_sawError = true;
379 if (type == XMLErrors::ErrorTypeFatal) 379 if (type == XMLErrors::ErrorTypeFatal)
380 stopParsing(); 380 stopParsing();
381 } 381 }
382 382
383 void XMLDocumentParser::enterText() 383 void XMLDocumentParser::createLeafTextNodeIfNeeded()
384 { 384 {
385 if (m_leafTextNode)
386 return;
387
385 ASSERT(m_bufferedText.size() == 0); 388 ASSERT(m_bufferedText.size() == 0);
386 ASSERT(!m_leafTextNode);
387 m_leafTextNode = Text::create(m_currentNode->document(), ""); 389 m_leafTextNode = Text::create(m_currentNode->document(), "");
388 m_currentNode->parserAppendChild(m_leafTextNode.get()); 390 m_currentNode->parserAppendChild(m_leafTextNode.get());
389 } 391 }
390 392
391 void XMLDocumentParser::exitText() 393 bool XMLDocumentParser::updateLeafTextNode()
392 { 394 {
393 if (isStopped()) 395 if (isStopped())
394 return; 396 return false;
395 397
396 if (!m_leafTextNode) 398 if (!m_leafTextNode)
397 return; 399 return true;
398 400
399 m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.si ze())); 401 m_leafTextNode->appendData(toString(m_bufferedText.data(), m_bufferedText.si ze()));
400 m_bufferedText.clear(); 402 m_bufferedText.clear();
401 m_leafTextNode = nullptr; 403 m_leafTextNode = nullptr;
404
405 // Mutation event handlers executed by appendData() might detach this parser .
406 return !isStopped();
402 } 407 }
403 408
404 void XMLDocumentParser::detach() 409 void XMLDocumentParser::detach()
405 { 410 {
406 clearCurrentNodeStack(); 411 clearCurrentNodeStack();
407 ScriptableDocumentParser::detach(); 412 ScriptableDocumentParser::detach();
408 } 413 }
409 414
410 void XMLDocumentParser::end() 415 void XMLDocumentParser::end()
411 { 416 {
412 TRACE_EVENT0("blink", "XMLDocumentParser::end"); 417 TRACE_EVENT0("blink", "XMLDocumentParser::end");
413 // XMLDocumentParserLibxml2 will do bad things to the document if doEnd() is called. 418 // XMLDocumentParserLibxml2 will do bad things to the document if doEnd() is called.
414 // I don't believe XMLDocumentParserQt needs doEnd called in the fragment ca se. 419 // I don't believe XMLDocumentParserQt needs doEnd called in the fragment ca se.
415 ASSERT(!m_parsingFragment); 420 ASSERT(!m_parsingFragment);
416 421
417 doEnd(); 422 doEnd();
418 423
419 // doEnd() call above can detach the parser and null out its document. 424 // doEnd() call above can detach the parser and null out its document.
420 // In that case, we just bail out. 425 // In that case, we just bail out.
421 if (isDetached()) 426 if (isDetached())
422 return; 427 return;
423 428
424 // doEnd() could process a script tag, thus pausing parsing. 429 // doEnd() could process a script tag, thus pausing parsing.
425 if (m_parserPaused) 430 if (m_parserPaused)
426 return; 431 return;
427 432
428 if (m_sawError) { 433 if (m_sawError) {
429 insertErrorMessageBlock(); 434 insertErrorMessageBlock();
430 } else { 435 } else {
431 exitText(); 436 updateLeafTextNode();
437 // Do not bail out if in a stopped state, but notify document that
438 // parsing has finished.
432 document()->styleResolverChanged(); 439 document()->styleResolverChanged();
433 } 440 }
434 441
435 if (isParsing()) 442 if (isParsing())
436 prepareToStopParsing(); 443 prepareToStopParsing();
437 document()->setReadyState(Document::Interactive); 444 document()->setReadyState(Document::Interactive);
438 clearCurrentNodeStack(); 445 clearCurrentNodeStack();
439 document()->finishedParsing(); 446 document()->finishedParsing();
440 } 447 }
441 448
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 { 992 {
986 if (isStopped()) 993 if (isStopped())
987 return; 994 return;
988 995
989 if (m_parserPaused) { 996 if (m_parserPaused) {
990 m_pendingCallbacks.append(adoptPtr(new PendingStartElementNSCallback(loc alName, prefix, uri, nbNamespaces, libxmlNamespaces, 997 m_pendingCallbacks.append(adoptPtr(new PendingStartElementNSCallback(loc alName, prefix, uri, nbNamespaces, libxmlNamespaces,
991 nbAttributes, nbDefaulted, libxmlAttributes))); 998 nbAttributes, nbDefaulted, libxmlAttributes)));
992 return; 999 return;
993 } 1000 }
994 1001
995 exitText(); 1002 if (!updateLeafTextNode())
1003 return;
996 1004
997 AtomicString adjustedURI = uri; 1005 AtomicString adjustedURI = uri;
998 if (m_parsingFragment && adjustedURI.isNull()) { 1006 if (m_parsingFragment && adjustedURI.isNull()) {
999 if (!prefix.isNull()) 1007 if (!prefix.isNull())
1000 adjustedURI = m_prefixToNamespaceMap.get(prefix); 1008 adjustedURI = m_prefixToNamespaceMap.get(prefix);
1001 else 1009 else
1002 adjustedURI = m_defaultNamespaceURI; 1010 adjustedURI = m_defaultNamespaceURI;
1003 } 1011 }
1004 1012
1005 bool isFirstElement = !m_sawFirstElement; 1013 bool isFirstElement = !m_sawFirstElement;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 1070
1063 if (m_parserPaused) { 1071 if (m_parserPaused) {
1064 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback())); 1072 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback()));
1065 return; 1073 return;
1066 } 1074 }
1067 1075
1068 // JavaScript can detach the parser. Make sure this is not released before 1076 // JavaScript can detach the parser. Make sure this is not released before
1069 // the end of this method. 1077 // the end of this method.
1070 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); 1078 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this);
1071 1079
1072 exitText(); 1080 if (!updateLeafTextNode())
1081 return;
1073 1082
1074 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode; 1083 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode;
1075 if (m_currentNode->isElementNode()) 1084 if (m_currentNode->isElementNode())
1076 toElement(n.get())->finishParsingChildren(); 1085 toElement(n.get())->finishParsingChildren();
1077 1086
1078 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptLoaderIfPossible(toElement(n))) { 1087 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptLoaderIfPossible(toElement(n))) {
1079 popCurrentNode(); 1088 popCurrentNode();
1080 n->remove(IGNORE_EXCEPTION); 1089 n->remove(IGNORE_EXCEPTION);
1081 return; 1090 return;
1082 } 1091 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 void XMLDocumentParser::characters(const xmlChar* chars, int length) 1147 void XMLDocumentParser::characters(const xmlChar* chars, int length)
1139 { 1148 {
1140 if (isStopped()) 1149 if (isStopped())
1141 return; 1150 return;
1142 1151
1143 if (m_parserPaused) { 1152 if (m_parserPaused) {
1144 m_pendingCallbacks.append(adoptPtr(new PendingCharactersCallback(chars, length))); 1153 m_pendingCallbacks.append(adoptPtr(new PendingCharactersCallback(chars, length)));
1145 return; 1154 return;
1146 } 1155 }
1147 1156
1148 if (!m_leafTextNode) 1157 createLeafTextNodeIfNeeded();
1149 enterText();
1150 m_bufferedText.append(chars, length); 1158 m_bufferedText.append(chars, length);
1151 } 1159 }
1152 1160
1153 void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va _list args) 1161 void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va _list args)
1154 { 1162 {
1155 if (isStopped()) 1163 if (isStopped())
1156 return; 1164 return;
1157 1165
1158 char formattedMessage[1024]; 1166 char formattedMessage[1024];
1159 vsnprintf(formattedMessage, sizeof(formattedMessage) - 1, message, args); 1167 vsnprintf(formattedMessage, sizeof(formattedMessage) - 1, message, args);
1160 1168
1161 if (m_parserPaused) { 1169 if (m_parserPaused) {
1162 m_pendingCallbacks.append(adoptPtr(new PendingErrorCallback(type, reinte rpret_cast<const xmlChar*>(formattedMessage), lineNumber(), columnNumber()))); 1170 m_pendingCallbacks.append(adoptPtr(new PendingErrorCallback(type, reinte rpret_cast<const xmlChar*>(formattedMessage), lineNumber(), columnNumber())));
1163 return; 1171 return;
1164 } 1172 }
1165 1173
1166 handleError(type, formattedMessage, textPosition()); 1174 handleError(type, formattedMessage, textPosition());
1167 } 1175 }
1168 1176
1169 void XMLDocumentParser::processingInstruction(const String& target, const String & data) 1177 void XMLDocumentParser::processingInstruction(const String& target, const String & data)
1170 { 1178 {
1171 if (isStopped()) 1179 if (isStopped())
1172 return; 1180 return;
1173 1181
1174 if (m_parserPaused) { 1182 if (m_parserPaused) {
1175 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb ack(target, data))); 1183 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb ack(target, data)));
1176 return; 1184 return;
1177 } 1185 }
1178 1186
1179 exitText(); 1187 if (!updateLeafTextNode())
1188 return;
1180 1189
1181 // ### handle exceptions 1190 // ### handle exceptions
1182 TrackExceptionState exceptionState; 1191 TrackExceptionState exceptionState;
1183 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre ateProcessingInstruction(target, data, exceptionState); 1192 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre ateProcessingInstruction(target, data, exceptionState);
1184 if (exceptionState.hadException()) 1193 if (exceptionState.hadException())
1185 return; 1194 return;
1186 1195
1187 pi->setCreatedByParser(true); 1196 pi->setCreatedByParser(true);
1188 1197
1189 m_currentNode->parserAppendChild(pi.get()); 1198 m_currentNode->parserAppendChild(pi.get());
(...skipping 21 matching lines...) Expand all
1211 void XMLDocumentParser::cdataBlock(const String& text) 1220 void XMLDocumentParser::cdataBlock(const String& text)
1212 { 1221 {
1213 if (isStopped()) 1222 if (isStopped())
1214 return; 1223 return;
1215 1224
1216 if (m_parserPaused) { 1225 if (m_parserPaused) {
1217 m_pendingCallbacks.append(adoptPtr(new PendingCDATABlockCallback(text))) ; 1226 m_pendingCallbacks.append(adoptPtr(new PendingCDATABlockCallback(text))) ;
1218 return; 1227 return;
1219 } 1228 }
1220 1229
1221 exitText(); 1230 if (!updateLeafTextNode())
1231 return;
1222 1232
1223 m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->documen t(), text)); 1233 m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->documen t(), text));
1224 } 1234 }
1225 1235
1226 void XMLDocumentParser::comment(const String& text) 1236 void XMLDocumentParser::comment(const String& text)
1227 { 1237 {
1228 if (isStopped()) 1238 if (isStopped())
1229 return; 1239 return;
1230 1240
1231 if (m_parserPaused) { 1241 if (m_parserPaused) {
1232 m_pendingCallbacks.append(adoptPtr(new PendingCommentCallback(text))); 1242 m_pendingCallbacks.append(adoptPtr(new PendingCommentCallback(text)));
1233 return; 1243 return;
1234 } 1244 }
1235 1245
1236 exitText(); 1246 if (!updateLeafTextNode())
1247 return;
1237 1248
1238 m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), text)); 1249 m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), text));
1239 } 1250 }
1240 1251
1241 enum StandaloneInfo { 1252 enum StandaloneInfo {
1242 StandaloneUnspecified = -2, 1253 StandaloneUnspecified = -2,
1243 NoXMlDeclaration, 1254 NoXMlDeclaration,
1244 StandaloneNo, 1255 StandaloneNo,
1245 StandaloneYes 1256 StandaloneYes
1246 }; 1257 };
(...skipping 10 matching lines...) Expand all
1257 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION); 1268 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION);
1258 if (standalone != StandaloneUnspecified) 1269 if (standalone != StandaloneUnspecified)
1259 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_ EXCEPTION); 1270 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_ EXCEPTION);
1260 if (!encoding.isNull()) 1271 if (!encoding.isNull())
1261 document()->setXMLEncoding(encoding); 1272 document()->setXMLEncoding(encoding);
1262 document()->setHasXMLDeclaration(true); 1273 document()->setHasXMLDeclaration(true);
1263 } 1274 }
1264 1275
1265 void XMLDocumentParser::endDocument() 1276 void XMLDocumentParser::endDocument()
1266 { 1277 {
1267 exitText(); 1278 updateLeafTextNode();
1268 } 1279 }
1269 1280
1270 void XMLDocumentParser::internalSubset(const String& name, const String& externa lID, const String& systemID) 1281 void XMLDocumentParser::internalSubset(const String& name, const String& externa lID, const String& systemID)
1271 { 1282 {
1272 if (isStopped()) 1283 if (isStopped())
1273 return; 1284 return;
1274 1285
1275 if (m_parserPaused) { 1286 if (m_parserPaused) {
1276 m_pendingCallbacks.append(adoptPtr(new PendingInternalSubsetCallback(nam e, externalID, systemID))); 1287 m_pendingCallbacks.append(adoptPtr(new PendingInternalSubsetCallback(nam e, externalID, systemID)));
1277 return; 1288 return;
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 sax.initialized = XML_SAX2_MAGIC; 1682 sax.initialized = XML_SAX2_MAGIC;
1672 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state); 1683 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
1673 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; 1684 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
1674 parseChunk(parser->context(), parseString); 1685 parseChunk(parser->context(), parseString);
1675 finishParsing(parser->context()); 1686 finishParsing(parser->context());
1676 attrsOK = state.gotAttributes; 1687 attrsOK = state.gotAttributes;
1677 return state.attributes; 1688 return state.attributes;
1678 } 1689 }
1679 1690
1680 } // namespace blink 1691 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/xml/parser/XMLDocumentParser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698