Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
| 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. |
| 4 * Copyright (C) 2011 Igalia S.L. | 4 * Copyright (C) 2011 Igalia S.L. |
| 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 | 63 |
| 64 using namespace HTMLNames; | 64 using namespace HTMLNames; |
| 65 | 65 |
| 66 static Position toPositionInDOMTree(const Position& position) | 66 static Position toPositionInDOMTree(const Position& position) |
| 67 { | 67 { |
| 68 return position; | 68 return position; |
| 69 } | 69 } |
| 70 | 70 |
| 71 template<typename Strategy> | 71 template<typename Strategy> |
| 72 StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldRes olveURLs, EAnnotateForInterchange shouldAnnotate, const PositionType& start, con st PositionType& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines co nvertBlocksToInlines) | 72 StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldRes olveURLs, EAnnotateForInterchange shouldAnnotate, const PositionType& start, con st PositionType& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines co nvertBlocksToInlines) |
| 73 : m_markupAccumulator(shouldResolveURLs, toTextOffset(start.parentAnchoredEq uivalent()), toTextOffset(end.parentAnchoredEquivalent()), start.document(), sho uldAnnotate, highestNodeToBeSerialized, convertBlocksToInlines) | 73 : m_start(start) |
| 74 , m_start(start) | |
| 75 , m_end(end) | 74 , m_end(end) |
| 75 , m_shouldResolveURLs(shouldResolveURLs) | |
| 76 , m_shouldAnnotate(shouldAnnotate) | 76 , m_shouldAnnotate(shouldAnnotate) |
| 77 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) | 77 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) |
| 78 , m_convertBlocksToInlines(convertBlocksToInlines) | |
| 78 { | 79 { |
| 79 } | 80 } |
| 80 | 81 |
| 81 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 82 static bool needInterchangeNewlineAfter(const VisiblePosition& v) |
| 82 { | 83 { |
| 83 VisiblePosition next = v.next(); | 84 VisiblePosition next = v.next(); |
| 84 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | 85 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); |
| 85 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | 86 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); |
| 86 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. | 87 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. |
| 87 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); | 88 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 111 // the non-const-ness of styleFromMatchedRulesForElement. | 112 // the non-const-ness of styleFromMatchedRulesForElement. |
| 112 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | 113 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); |
| 113 return style.release(); | 114 return style.release(); |
| 114 } | 115 } |
| 115 | 116 |
| 116 template<typename Strategy> | 117 template<typename Strategy> |
| 117 String StyledMarkupSerializer<Strategy>::createMarkup() | 118 String StyledMarkupSerializer<Strategy>::createMarkup() |
| 118 { | 119 { |
| 119 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); | 120 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); |
| 120 | 121 |
| 122 StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset( m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent ()), m_start.document(), m_shouldAnnotate, m_highestNodeToBeSerialized.get(), m_ convertBlocksToInlines); | |
| 123 | |
| 121 Node* pastEnd = m_end.nodeAsRangePastLastNode(); | 124 Node* pastEnd = m_end.nodeAsRangePastLastNode(); |
| 122 | 125 |
| 123 Node* firstNode = m_start.nodeAsRangeFirstNode(); | 126 Node* firstNode = m_start.nodeAsRangeFirstNode(); |
| 124 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); | 127 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); |
| 125 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); | 128 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); |
| 126 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfte r(visibleStart)) { | 129 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfte r(visibleStart)) { |
| 127 if (visibleStart == visibleEnd.previous()) | 130 if (visibleStart == visibleEnd.previous()) |
| 128 return interchangeNewlineString; | 131 return interchangeNewlineString; |
| 129 | 132 |
| 130 m_markupAccumulator.appendString(interchangeNewlineString); | 133 markupAccumulator.appendString(interchangeNewlineString); |
| 131 firstNode = visibleStart.next().deepEquivalent().deprecatedNode(); | 134 firstNode = visibleStart.next().deepEquivalent().deprecatedNode(); |
| 132 | 135 |
| 133 if (pastEnd && Strategy::PositionType::beforeNode(firstNode).compareTo(S trategy::PositionType::beforeNode(pastEnd)) >= 0) { | 136 if (pastEnd && Strategy::PositionType::beforeNode(firstNode).compareTo(S trategy::PositionType::beforeNode(pastEnd)) >= 0) { |
| 134 // This condition hits in editing/pasteboard/copy-display-none.html. | 137 // This condition hits in editing/pasteboard/copy-display-none.html. |
| 135 return interchangeNewlineString; | 138 return interchangeNewlineString; |
| 136 } | 139 } |
| 137 } | 140 } |
| 138 | 141 |
| 139 Node* lastClosed = serializeNodes(firstNode, pastEnd); | 142 Node* lastClosed = serializeNodes(firstNode, pastEnd, &markupAccumulator); |
| 140 | 143 |
| 141 if (m_highestNodeToBeSerialized && lastClosed) { | 144 if (m_highestNodeToBeSerialized && lastClosed) { |
| 142 // TODO(hajimehoshi): This is calculated at createMarkupInternal too. | 145 // TODO(hajimehoshi): This is calculated at createMarkupInternal too. |
| 143 Node* commonAncestor = Strategy::commonAncestor(*m_start.containerNode() , *m_end.containerNode()); | 146 Node* commonAncestor = Strategy::commonAncestor(*m_start.containerNode() , *m_end.containerNode()); |
| 144 ASSERT(commonAncestor); | 147 ASSERT(commonAncestor); |
| 145 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); | 148 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); |
| 146 HTMLBodyElement* fullySelectedRoot = nullptr; | 149 HTMLBodyElement* fullySelectedRoot = nullptr; |
| 147 // FIXME: Do this for all fully selected blocks, not just the body. | 150 // FIXME: Do this for all fully selected blocks, not just the body. |
| 148 if (body && areSameRanges(body, m_start, m_end)) | 151 if (body && areSameRanges(body, m_start, m_end)) |
| 149 fullySelectedRoot = body; | 152 fullySelectedRoot = body; |
| 150 | 153 |
| 151 // Also include all of the ancestors of lastClosed up to this special an cestor. | 154 // Also include all of the ancestors of lastClosed up to this special an cestor. |
| 152 // FIXME: What is ancestor? | 155 // FIXME: What is ancestor? |
| 153 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { | 156 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { |
| 154 if (ancestor == fullySelectedRoot && !m_markupAccumulator.convertBlo cksToInlines()) { | 157 if (ancestor == fullySelectedRoot && !markupAccumulator.convertBlock sToInlines()) { |
| 155 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); | 158 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); |
| 156 | 159 |
| 157 // Bring the background attribute over, but not as an attribute because a background attribute on a div | 160 // Bring the background attribute over, but not as an attribute because a background attribute on a div |
| 158 // appears to have no effect. | 161 // appears to have no effect. |
| 159 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) | 162 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) |
| 160 && fullySelectedRoot->hasAttribute(backgroundAttr)) | 163 && fullySelectedRoot->hasAttribute(backgroundAttr)) |
| 161 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | 164 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); |
| 162 | 165 |
| 163 if (fullySelectedRootStyle->style()) { | 166 if (fullySelectedRootStyle->style()) { |
| 164 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). | 167 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). |
| 165 // This assertion is caused at least when we select all text of a <body> element whose | 168 // This assertion is caused at least when we select all text of a <body> element whose |
| 166 // 'text-decoration' property is "inherit", and copy it. | 169 // 'text-decoration' property is "inherit", and copy it. |
| 167 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) | 170 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) |
| 168 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); | 171 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); |
| 169 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 172 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) |
| 170 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); | 173 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); |
| 171 m_markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle ->style(), true); | 174 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle-> style(), true); |
| 172 } | 175 } |
| 173 } else { | 176 } else { |
| 174 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode | 177 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode |
| 175 // so that styles that affect the exterior of the node are not i ncluded. | 178 // so that styles that affect the exterior of the node are not i ncluded. |
| 176 m_markupAccumulator.wrapWithNode(*ancestor, StyledMarkupAccumula tor::DoesNotFullySelectNode); | 179 markupAccumulator.wrapWithNode(*ancestor, StyledMarkupAccumulato r::DoesNotFullySelectNode); |
| 177 } | 180 } |
| 178 | 181 |
| 179 if (ancestor == m_highestNodeToBeSerialized) | 182 if (ancestor == m_highestNodeToBeSerialized) |
| 180 break; | 183 break; |
| 181 } | 184 } |
| 182 } | 185 } |
| 183 | 186 |
| 184 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. | 187 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. |
| 185 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd)) | 188 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd)) |
| 186 m_markupAccumulator.appendString(interchangeNewlineString); | 189 markupAccumulator.appendString(interchangeNewlineString); |
| 187 | 190 |
| 188 return m_markupAccumulator.takeResults(); | 191 return markupAccumulator.takeResults(); |
| 189 } | 192 } |
| 190 | 193 |
| 191 template<typename Strategy> | 194 template<typename Strategy> |
| 192 Node* StyledMarkupSerializer<Strategy>::serializeNodes(Node* startNode, Node* pa stEnd) | 195 Node* StyledMarkupSerializer<Strategy>::serializeNodes(Node* startNode, Node* pa stEnd, StyledMarkupAccumulator* markupAccumulator) |
| 193 { | 196 { |
| 194 if (!m_markupAccumulator.highestNodeToBeSerialized()) { | 197 if (!markupAccumulator->highestNodeToBeSerialized()) { |
| 195 Node* lastClosed = traverseNodesForSerialization(startNode, pastEnd, Nod eTraversalMode::DoNotEmitString); | 198 Node* lastClosed = traverseNodesForSerialization(startNode, pastEnd, nul lptr); |
| 196 m_markupAccumulator.setHighestNodeToBeSerialized(lastClosed); | 199 markupAccumulator->setHighestNodeToBeSerialized(lastClosed); |
| 197 } | 200 } |
| 198 | 201 |
| 199 Node* highestNodeToBeSerialized = m_markupAccumulator.highestNodeToBeSeriali zed(); | 202 Node* highestNodeToBeSerialized = markupAccumulator->highestNodeToBeSerializ ed(); |
| 200 if (highestNodeToBeSerialized && Strategy::parent(*highestNodeToBeSerialized )) { | 203 if (highestNodeToBeSerialized && Strategy::parent(*highestNodeToBeSerialized )) { |
| 201 bool shouldAnnotate = m_shouldAnnotate == AnnotateForInterchange; | 204 bool shouldAnnotate = m_shouldAnnotate == AnnotateForInterchange; |
| 202 RefPtrWillBeRawPtr<EditingStyle> wrappingStyle = EditingStyle::wrappingS tyleForSerialization(Strategy::parent(*highestNodeToBeSerialized), shouldAnnotat e); | 205 RefPtrWillBeRawPtr<EditingStyle> wrappingStyle = EditingStyle::wrappingS tyleForSerialization(Strategy::parent(*highestNodeToBeSerialized), shouldAnnotat e); |
| 203 m_markupAccumulator.setWrappingStyle(wrappingStyle.release()); | 206 markupAccumulator->setWrappingStyle(wrappingStyle.release()); |
| 204 } | 207 } |
| 205 return traverseNodesForSerialization(startNode, pastEnd, NodeTraversalMode:: EmitString); | 208 return traverseNodesForSerialization(startNode, pastEnd, markupAccumulator); |
| 206 } | 209 } |
| 207 | 210 |
| 208 template<typename Strategy> | 211 template<typename Strategy> |
| 209 Node* StyledMarkupSerializer<Strategy>::traverseNodesForSerialization(Node* star tNode, Node* pastEnd, NodeTraversalMode traversalMode) | 212 Node* StyledMarkupSerializer<Strategy>::traverseNodesForSerialization(Node* star tNode, Node* pastEnd, StyledMarkupAccumulator* markupAccumulator) |
|
tkent
2015/06/07 23:39:01
If |markupAccumulator| can't be nullptr, use a ref
yosin_UTC9
2015/06/08 02:00:05
|markupAcccumlator| is |nullptr| at L198.
This p
tkent
2015/06/08 02:03:29
Thank you. lgtm.
| |
| 210 { | 213 { |
| 211 const bool shouldEmit = traversalMode == NodeTraversalMode::EmitString; | |
| 212 WillBeHeapVector<RawPtrWillBeMember<ContainerNode>> ancestorsToClose; | 214 WillBeHeapVector<RawPtrWillBeMember<ContainerNode>> ancestorsToClose; |
| 213 Node* next; | 215 Node* next; |
| 214 Node* lastClosed = nullptr; | 216 Node* lastClosed = nullptr; |
| 215 for (Node* n = startNode; n != pastEnd; n = next) { | 217 for (Node* n = startNode; n != pastEnd; n = next) { |
| 216 // According to <rdar://problem/5730668>, it is possible for n to blow | 218 // According to <rdar://problem/5730668>, it is possible for n to blow |
| 217 // past pastEnd and become null here. This shouldn't be possible. | 219 // past pastEnd and become null here. This shouldn't be possible. |
| 218 // This null check will prevent crashes (but create too much markup) | 220 // This null check will prevent crashes (but create too much markup) |
| 219 // and the ASSERT will hopefully lead us to understanding the problem. | 221 // and the ASSERT will hopefully lead us to understanding the problem. |
| 220 ASSERT(n); | 222 ASSERT(n); |
| 221 if (!n) | 223 if (!n) |
| 222 break; | 224 break; |
| 223 | 225 |
| 224 next = Strategy::next(*n); | 226 next = Strategy::next(*n); |
| 225 | 227 |
| 226 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) { | 228 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) { |
| 227 // Don't write out empty block containers that aren't fully selected . | 229 // Don't write out empty block containers that aren't fully selected . |
| 228 continue; | 230 continue; |
| 229 } | 231 } |
| 230 | 232 |
| 231 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { | 233 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { |
| 232 next = Strategy::nextSkippingChildren(*n); | 234 next = Strategy::nextSkippingChildren(*n); |
| 233 // Don't skip over pastEnd. | 235 // Don't skip over pastEnd. |
| 234 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) | 236 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) |
| 235 next = pastEnd; | 237 next = pastEnd; |
| 236 } else { | 238 } else { |
| 237 // Add the node to the markup if we're not skipping the descendants | 239 // Add the node to the markup if we're not skipping the descendants |
| 238 if (shouldEmit) | 240 if (markupAccumulator) |
| 239 m_markupAccumulator.appendStartTag(*n); | 241 markupAccumulator->appendStartTag(*n); |
| 240 | 242 |
| 241 // If node has no children, close the tag now. | 243 // If node has no children, close the tag now. |
| 242 if (Strategy::hasChildren(*n)) { | 244 if (Strategy::hasChildren(*n)) { |
| 243 ancestorsToClose.append(toContainerNode(n)); | 245 ancestorsToClose.append(toContainerNode(n)); |
| 244 continue; | 246 continue; |
| 245 } | 247 } |
| 246 if (shouldEmit && n->isElementNode()) | 248 if (markupAccumulator && n->isElementNode()) |
| 247 m_markupAccumulator.appendEndTag(toElement(*n)); | 249 markupAccumulator->appendEndTag(toElement(*n)); |
| 248 lastClosed = n; | 250 lastClosed = n; |
| 249 } | 251 } |
| 250 | 252 |
| 251 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. | 253 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. |
| 252 // FIXME: What happens if we just inserted open tag and reached the end? | 254 // FIXME: What happens if we just inserted open tag and reached the end? |
| 253 if (Strategy::nextSibling(*n) && next != pastEnd) | 255 if (Strategy::nextSibling(*n) && next != pastEnd) |
| 254 continue; | 256 continue; |
| 255 | 257 |
| 256 // Close up the ancestors. | 258 // Close up the ancestors. |
| 257 while (!ancestorsToClose.isEmpty()) { | 259 while (!ancestorsToClose.isEmpty()) { |
| 258 ContainerNode* ancestor = ancestorsToClose.last(); | 260 ContainerNode* ancestor = ancestorsToClose.last(); |
| 259 ASSERT(ancestor); | 261 ASSERT(ancestor); |
| 260 if (next != pastEnd && Strategy::isDescendantOf(*next, *ancestor)) | 262 if (next != pastEnd && Strategy::isDescendantOf(*next, *ancestor)) |
| 261 break; | 263 break; |
| 262 // Not at the end of the range, close ancestors up to sibling of nex t node. | 264 // Not at the end of the range, close ancestors up to sibling of nex t node. |
| 263 if (shouldEmit && ancestor->isElementNode()) | 265 if (markupAccumulator && ancestor->isElementNode()) |
| 264 m_markupAccumulator.appendEndTag(toElement(*ancestor)); | 266 markupAccumulator->appendEndTag(toElement(*ancestor)); |
| 265 lastClosed = ancestor; | 267 lastClosed = ancestor; |
| 266 ancestorsToClose.removeLast(); | 268 ancestorsToClose.removeLast(); |
| 267 } | 269 } |
| 268 | 270 |
| 269 // Surround the currently accumulated markup with markup for ancestors w e never opened as we leave the subtree(s) rooted at those ancestors. | 271 // Surround the currently accumulated markup with markup for ancestors w e never opened as we leave the subtree(s) rooted at those ancestors. |
| 270 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr; | 272 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr; |
| 271 if (next == pastEnd || n == nextParent) | 273 if (next == pastEnd || n == nextParent) |
| 272 continue; | 274 continue; |
| 273 | 275 |
| 274 ASSERT(n); | 276 ASSERT(n); |
| 275 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; | 277 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; |
| 276 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { | 278 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { |
| 277 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: | 279 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: |
| 278 if (!parent->layoutObject()) | 280 if (!parent->layoutObject()) |
| 279 continue; | 281 continue; |
| 280 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: | 282 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: |
| 281 ASSERT(startNode); | 283 ASSERT(startNode); |
| 282 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); | 284 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); |
| 283 if (shouldEmit) | 285 if (markupAccumulator) |
| 284 m_markupAccumulator.wrapWithNode(*parent); | 286 markupAccumulator->wrapWithNode(*parent); |
| 285 lastClosed = parent; | 287 lastClosed = parent; |
| 286 } | 288 } |
| 287 } | 289 } |
| 288 | 290 |
| 289 return lastClosed; | 291 return lastClosed; |
| 290 } | 292 } |
| 291 | 293 |
| 292 template class StyledMarkupSerializer<EditingStrategy>; | 294 template class StyledMarkupSerializer<EditingStrategy>; |
| 293 | 295 |
| 294 } // namespace blink | 296 } // namespace blink |
| OLD | NEW |