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

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: rename as updateLeafTextNode() 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();
haraken 2015/08/04 12:37:58 Don't we need to early-return here?
sof 2015/08/04 12:42:35 No, we could be in a Stopped state and need to bot
sof 2015/08/04 13:52:31 Added clarifying comment.
432 document()->styleResolverChanged(); 437 document()->styleResolverChanged();
433 } 438 }
434 439
435 if (isParsing()) 440 if (isParsing())
436 prepareToStopParsing(); 441 prepareToStopParsing();
437 document()->setReadyState(Document::Interactive); 442 document()->setReadyState(Document::Interactive);
438 clearCurrentNodeStack(); 443 clearCurrentNodeStack();
439 document()->finishedParsing(); 444 document()->finishedParsing();
440 } 445 }
441 446
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 { 990 {
986 if (isStopped()) 991 if (isStopped())
987 return; 992 return;
988 993
989 if (m_parserPaused) { 994 if (m_parserPaused) {
990 m_pendingCallbacks.append(adoptPtr(new PendingStartElementNSCallback(loc alName, prefix, uri, nbNamespaces, libxmlNamespaces, 995 m_pendingCallbacks.append(adoptPtr(new PendingStartElementNSCallback(loc alName, prefix, uri, nbNamespaces, libxmlNamespaces,
991 nbAttributes, nbDefaulted, libxmlAttributes))); 996 nbAttributes, nbDefaulted, libxmlAttributes)));
992 return; 997 return;
993 } 998 }
994 999
995 exitText(); 1000 if (!updateLeafTextNode())
1001 return;
996 1002
997 AtomicString adjustedURI = uri; 1003 AtomicString adjustedURI = uri;
998 if (m_parsingFragment && adjustedURI.isNull()) { 1004 if (m_parsingFragment && adjustedURI.isNull()) {
999 if (!prefix.isNull()) 1005 if (!prefix.isNull())
1000 adjustedURI = m_prefixToNamespaceMap.get(prefix); 1006 adjustedURI = m_prefixToNamespaceMap.get(prefix);
1001 else 1007 else
1002 adjustedURI = m_defaultNamespaceURI; 1008 adjustedURI = m_defaultNamespaceURI;
1003 } 1009 }
1004 1010
1005 bool isFirstElement = !m_sawFirstElement; 1011 bool isFirstElement = !m_sawFirstElement;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 1068
1063 if (m_parserPaused) { 1069 if (m_parserPaused) {
1064 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback())); 1070 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback()));
1065 return; 1071 return;
1066 } 1072 }
1067 1073
1068 // JavaScript can detach the parser. Make sure this is not released before 1074 // JavaScript can detach the parser. Make sure this is not released before
1069 // the end of this method. 1075 // the end of this method.
1070 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); 1076 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this);
1071 1077
1072 exitText(); 1078 if (!updateLeafTextNode())
1079 return;
1073 1080
1074 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode; 1081 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode;
1075 if (m_currentNode->isElementNode()) 1082 if (m_currentNode->isElementNode())
1076 toElement(n.get())->finishParsingChildren(); 1083 toElement(n.get())->finishParsingChildren();
1077 1084
1078 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptLoaderIfPossible(toElement(n))) { 1085 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptLoaderIfPossible(toElement(n))) {
1079 popCurrentNode(); 1086 popCurrentNode();
1080 n->remove(IGNORE_EXCEPTION); 1087 n->remove(IGNORE_EXCEPTION);
1081 return; 1088 return;
1082 } 1089 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 void XMLDocumentParser::characters(const xmlChar* chars, int length) 1145 void XMLDocumentParser::characters(const xmlChar* chars, int length)
1139 { 1146 {
1140 if (isStopped()) 1147 if (isStopped())
1141 return; 1148 return;
1142 1149
1143 if (m_parserPaused) { 1150 if (m_parserPaused) {
1144 m_pendingCallbacks.append(adoptPtr(new PendingCharactersCallback(chars, length))); 1151 m_pendingCallbacks.append(adoptPtr(new PendingCharactersCallback(chars, length)));
1145 return; 1152 return;
1146 } 1153 }
1147 1154
1148 if (!m_leafTextNode) 1155 createLeafTextNodeIfNeeded();
1149 enterText();
1150 m_bufferedText.append(chars, length); 1156 m_bufferedText.append(chars, length);
1151 } 1157 }
1152 1158
1153 void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va _list args) 1159 void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va _list args)
1154 { 1160 {
1155 if (isStopped()) 1161 if (isStopped())
1156 return; 1162 return;
1157 1163
1158 char formattedMessage[1024]; 1164 char formattedMessage[1024];
1159 vsnprintf(formattedMessage, sizeof(formattedMessage) - 1, message, args); 1165 vsnprintf(formattedMessage, sizeof(formattedMessage) - 1, message, args);
1160 1166
1161 if (m_parserPaused) { 1167 if (m_parserPaused) {
1162 m_pendingCallbacks.append(adoptPtr(new PendingErrorCallback(type, reinte rpret_cast<const xmlChar*>(formattedMessage), lineNumber(), columnNumber()))); 1168 m_pendingCallbacks.append(adoptPtr(new PendingErrorCallback(type, reinte rpret_cast<const xmlChar*>(formattedMessage), lineNumber(), columnNumber())));
1163 return; 1169 return;
1164 } 1170 }
1165 1171
1166 handleError(type, formattedMessage, textPosition()); 1172 handleError(type, formattedMessage, textPosition());
1167 } 1173 }
1168 1174
1169 void XMLDocumentParser::processingInstruction(const String& target, const String & data) 1175 void XMLDocumentParser::processingInstruction(const String& target, const String & data)
1170 { 1176 {
1171 if (isStopped()) 1177 if (isStopped())
1172 return; 1178 return;
1173 1179
1174 if (m_parserPaused) { 1180 if (m_parserPaused) {
1175 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb ack(target, data))); 1181 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb ack(target, data)));
1176 return; 1182 return;
1177 } 1183 }
1178 1184
1179 exitText(); 1185 if (!updateLeafTextNode())
1186 return;
1180 1187
1181 // ### handle exceptions 1188 // ### handle exceptions
1182 TrackExceptionState exceptionState; 1189 TrackExceptionState exceptionState;
1183 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre ateProcessingInstruction(target, data, exceptionState); 1190 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre ateProcessingInstruction(target, data, exceptionState);
1184 if (exceptionState.hadException()) 1191 if (exceptionState.hadException())
1185 return; 1192 return;
1186 1193
1187 pi->setCreatedByParser(true); 1194 pi->setCreatedByParser(true);
1188 1195
1189 m_currentNode->parserAppendChild(pi.get()); 1196 m_currentNode->parserAppendChild(pi.get());
(...skipping 21 matching lines...) Expand all
1211 void XMLDocumentParser::cdataBlock(const String& text) 1218 void XMLDocumentParser::cdataBlock(const String& text)
1212 { 1219 {
1213 if (isStopped()) 1220 if (isStopped())
1214 return; 1221 return;
1215 1222
1216 if (m_parserPaused) { 1223 if (m_parserPaused) {
1217 m_pendingCallbacks.append(adoptPtr(new PendingCDATABlockCallback(text))) ; 1224 m_pendingCallbacks.append(adoptPtr(new PendingCDATABlockCallback(text))) ;
1218 return; 1225 return;
1219 } 1226 }
1220 1227
1221 exitText(); 1228 if (!updateLeafTextNode())
1229 return;
1222 1230
1223 m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->documen t(), text)); 1231 m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->documen t(), text));
1224 } 1232 }
1225 1233
1226 void XMLDocumentParser::comment(const String& text) 1234 void XMLDocumentParser::comment(const String& text)
1227 { 1235 {
1228 if (isStopped()) 1236 if (isStopped())
1229 return; 1237 return;
1230 1238
1231 if (m_parserPaused) { 1239 if (m_parserPaused) {
1232 m_pendingCallbacks.append(adoptPtr(new PendingCommentCallback(text))); 1240 m_pendingCallbacks.append(adoptPtr(new PendingCommentCallback(text)));
1233 return; 1241 return;
1234 } 1242 }
1235 1243
1236 exitText(); 1244 if (!updateLeafTextNode())
1245 return;
1237 1246
1238 m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), text)); 1247 m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), text));
1239 } 1248 }
1240 1249
1241 enum StandaloneInfo { 1250 enum StandaloneInfo {
1242 StandaloneUnspecified = -2, 1251 StandaloneUnspecified = -2,
1243 NoXMlDeclaration, 1252 NoXMlDeclaration,
1244 StandaloneNo, 1253 StandaloneNo,
1245 StandaloneYes 1254 StandaloneYes
1246 }; 1255 };
(...skipping 10 matching lines...) Expand all
1257 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION); 1266 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION);
1258 if (standalone != StandaloneUnspecified) 1267 if (standalone != StandaloneUnspecified)
1259 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_ EXCEPTION); 1268 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_ EXCEPTION);
1260 if (!encoding.isNull()) 1269 if (!encoding.isNull())
1261 document()->setXMLEncoding(encoding); 1270 document()->setXMLEncoding(encoding);
1262 document()->setHasXMLDeclaration(true); 1271 document()->setHasXMLDeclaration(true);
1263 } 1272 }
1264 1273
1265 void XMLDocumentParser::endDocument() 1274 void XMLDocumentParser::endDocument()
1266 { 1275 {
1267 exitText(); 1276 updateLeafTextNode();
1268 } 1277 }
1269 1278
1270 void XMLDocumentParser::internalSubset(const String& name, const String& externa lID, const String& systemID) 1279 void XMLDocumentParser::internalSubset(const String& name, const String& externa lID, const String& systemID)
1271 { 1280 {
1272 if (isStopped()) 1281 if (isStopped())
1273 return; 1282 return;
1274 1283
1275 if (m_parserPaused) { 1284 if (m_parserPaused) {
1276 m_pendingCallbacks.append(adoptPtr(new PendingInternalSubsetCallback(nam e, externalID, systemID))); 1285 m_pendingCallbacks.append(adoptPtr(new PendingInternalSubsetCallback(nam e, externalID, systemID)));
1277 return; 1286 return;
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 sax.initialized = XML_SAX2_MAGIC; 1680 sax.initialized = XML_SAX2_MAGIC;
1672 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state); 1681 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
1673 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; 1682 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
1674 parseChunk(parser->context(), parseString); 1683 parseChunk(parser->context(), parseString);
1675 finishParsing(parser->context()); 1684 finishParsing(parser->context());
1676 attrsOK = state.gotAttributes; 1685 attrsOK = state.gotAttributes;
1677 return state.attributes; 1686 return state.attributes;
1678 } 1687 }
1679 1688
1680 } // namespace blink 1689 } // 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