OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 upstream--; | 725 upstream--; |
726 | 726 |
727 int downstream = endOffset; | 727 int downstream = endOffset; |
728 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) | 728 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) |
729 downstream++; | 729 downstream++; |
730 | 730 |
731 int length = downstream - upstream; | 731 int length = downstream - upstream; |
732 if (!length) | 732 if (!length) |
733 return; | 733 return; |
734 | 734 |
735 VisiblePosition visibleUpstreamPos = createVisiblePosition(Position(textNode
, upstream)); | 735 VisiblePosition visibleUpstreamPos = createVisiblePositionDeprecated(Positio
n(textNode, upstream)); |
736 VisiblePosition visibleDownstreamPos = createVisiblePosition(Position(textNo
de, downstream)); | 736 VisiblePosition visibleDownstreamPos = createVisiblePositionDeprecated(Posit
ion(textNode, downstream)); |
737 | 737 |
738 String string = text.substring(upstream, length); | 738 String string = text.substring(upstream, length); |
739 // FIXME: Because of the problem mentioned at the top of this function, we | 739 // FIXME: Because of the problem mentioned at the top of this function, we |
740 // must also use nbsps at the start/end of the string because this function | 740 // must also use nbsps at the start/end of the string because this function |
741 // doesn't get all surrounding whitespace, just the whitespace in the | 741 // doesn't get all surrounding whitespace, just the whitespace in the |
742 // current text node. However, if the next sibling node is a text node | 742 // current text node. However, if the next sibling node is a text node |
743 // (not empty, see http://crbug.com/632300), we should use a plain space. | 743 // (not empty, see http://crbug.com/632300), we should use a plain space. |
744 // See http://crbug.com/310149 | 744 // See http://crbug.com/310149 |
745 const bool nextSiblingIsTextNode = textNode->nextSibling() && textNode->next
Sibling()->isTextNode() | 745 const bool nextSiblingIsTextNode = textNode->nextSibling() && textNode->next
Sibling()->isTextNode() |
746 && toText(textNode->nextSibling())->data().length(); | 746 && toText(textNode->nextSibling())->data().length(); |
(...skipping 18 matching lines...) Expand all Loading... |
765 return; | 765 return; |
766 LayoutText* layoutText = textNode->layoutObject(); | 766 LayoutText* layoutText = textNode->layoutObject(); |
767 if (layoutText && !layoutText->style()->collapseWhiteSpace()) | 767 if (layoutText && !layoutText->style()->collapseWhiteSpace()) |
768 return; | 768 return; |
769 | 769 |
770 // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it
. | 770 // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it
. |
771 Position upstreamPos = mostBackwardCaretPosition(position); | 771 Position upstreamPos = mostBackwardCaretPosition(position); |
772 deleteInsignificantText(upstreamPos, mostForwardCaretPosition(position)); | 772 deleteInsignificantText(upstreamPos, mostForwardCaretPosition(position)); |
773 position = mostForwardCaretPosition(upstreamPos); | 773 position = mostForwardCaretPosition(upstreamPos); |
774 | 774 |
775 VisiblePosition visiblePos = createVisiblePosition(position); | 775 VisiblePosition visiblePos = createVisiblePositionDeprecated(position); |
776 VisiblePosition previousVisiblePos = previousPositionOf(visiblePos); | 776 VisiblePosition previousVisiblePos = previousPositionOf(visiblePos); |
777 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos)
; | 777 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos)
; |
778 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos); | 778 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos); |
779 } | 779 } |
780 | 780 |
781 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee
ded(const VisiblePosition& visiblePosition) | 781 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee
ded(const VisiblePosition& visiblePosition) |
782 { | 782 { |
783 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) | 783 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) |
784 return; | 784 return; |
785 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); | 785 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 for (const auto& node : nodes) { | 900 for (const auto& node : nodes) { |
901 Text* textNode = node; | 901 Text* textNode = node; |
902 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; | 902 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; |
903 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); | 903 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); |
904 deleteInsignificantText(textNode, startOffset, endOffset); | 904 deleteInsignificantText(textNode, startOffset, endOffset); |
905 } | 905 } |
906 } | 906 } |
907 | 907 |
908 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 908 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
909 { | 909 { |
910 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); | 910 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
Deprecated(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); |
911 deleteInsignificantText(pos, end); | 911 deleteInsignificantText(pos, end); |
912 } | 912 } |
913 | 913 |
914 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder(Element* container,
EditingState* editingState) | 914 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder(Element* container,
EditingState* editingState) |
915 { | 915 { |
916 if (!container) | 916 if (!container) |
917 return nullptr; | 917 return nullptr; |
918 | 918 |
919 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 919 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
920 | 920 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 } | 989 } |
990 | 990 |
991 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 991 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
992 // it, and return that block. Otherwise return 0. | 992 // it, and return that block. Otherwise return 0. |
993 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(co
nst Position& pos, EditingState* editingState) | 993 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(co
nst Position& pos, EditingState* editingState) |
994 { | 994 { |
995 DCHECK(isEditablePosition(pos)) << pos; | 995 DCHECK(isEditablePosition(pos)) << pos; |
996 | 996 |
997 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 997 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
998 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 998 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
999 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; | 999 VisiblePosition visiblePos = createVisiblePositionDeprecated(pos, VP_DEFAULT
_AFFINITY); |
1000 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); | 1000 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
1001 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 1001 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
1002 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 1002 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
1003 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 1003 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
1004 | 1004 |
1005 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); | 1005 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); |
1006 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()
); | 1006 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()
); |
1007 | 1007 |
1008 // If there are no VisiblePositions in the same block as pos then | 1008 // If there are no VisiblePositions in the same block as pos then |
1009 // upstreamStart will be outside the paragraph | 1009 // upstreamStart will be outside the paragraph |
(...skipping 29 matching lines...) Expand all Loading... |
1039 return nullptr; | 1039 return nullptr; |
1040 | 1040 |
1041 HTMLElement* newBlock = insertNewDefaultParagraphElementAt(upstreamStart, ed
itingState); | 1041 HTMLElement* newBlock = insertNewDefaultParagraphElementAt(upstreamStart, ed
itingState); |
1042 if (editingState->isAborted()) | 1042 if (editingState->isAborted()) |
1043 return nullptr; | 1043 return nullptr; |
1044 | 1044 |
1045 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); | 1045 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); |
1046 | 1046 |
1047 // Inserting default paragraph element can change visible position. We | 1047 // Inserting default paragraph element can change visible position. We |
1048 // should update visible positions before use them. | 1048 // should update visible positions before use them. |
1049 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); | 1049 visiblePos = createVisiblePositionDeprecated(pos, VP_DEFAULT_AFFINITY); |
1050 visibleParagraphStart = startOfParagraph(visiblePos); | 1050 visibleParagraphStart = startOfParagraph(visiblePos); |
1051 visibleParagraphEnd = endOfParagraph(visiblePos); | 1051 visibleParagraphEnd = endOfParagraph(visiblePos); |
1052 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition::
firstPositionInNode(newBlock), editingState); | 1052 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition::
firstPositionInNode(newBlock), editingState); |
1053 if (editingState->isAborted()) | 1053 if (editingState->isAborted()) |
1054 return nullptr; | 1054 return nullptr; |
1055 | 1055 |
1056 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) { | 1056 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) { |
1057 removeNode(newBlock->lastChild(), editingState); | 1057 removeNode(newBlock->lastChild(), editingState); |
1058 if (editingState->isAborted()) | 1058 if (editingState->isAborted()) |
1059 return nullptr; | 1059 return nullptr; |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 | 1251 |
1252 // Add a br if pruning an empty block level element caused a collapse. For
example: | 1252 // Add a br if pruning an empty block level element caused a collapse. For
example: |
1253 // foo^ | 1253 // foo^ |
1254 // <div>bar</div> | 1254 // <div>bar</div> |
1255 // baz | 1255 // baz |
1256 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would | 1256 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would |
1257 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1257 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
1258 // Must recononicalize these two VisiblePositions after the pruning above. | 1258 // Must recononicalize these two VisiblePositions after the pruning above. |
1259 // TODO(yosin): We should abort when |beforeParagraph| is a orphan when | 1259 // TODO(yosin): We should abort when |beforeParagraph| is a orphan when |
1260 // we have a sample. | 1260 // we have a sample. |
1261 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); | 1261 beforeParagraph = createVisiblePositionDeprecated(beforeParagraph.deepEquiva
lent()); |
1262 if (afterParagraph.isOrphan()) { | 1262 if (afterParagraph.isOrphan()) { |
1263 editingState->abort(); | 1263 editingState->abort(); |
1264 return; | 1264 return; |
1265 } | 1265 } |
1266 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); | 1266 afterParagraph = createVisiblePositionDeprecated(afterParagraph.deepEquivale
nt()); |
1267 | 1267 |
1268 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) | 1268 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) |
1269 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { | 1269 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { |
1270 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1270 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
1271 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1271 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
1272 } | 1272 } |
1273 } | 1273 } |
1274 | 1274 |
1275 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, ShouldPreserveSelection shouldPreserveSelec
tion, ShouldPreserveStyle shouldPreserveStyle, Node* constrainingAncestor) | 1275 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, ShouldPreserveSelection shouldPreserveSelec
tion, ShouldPreserveStyle shouldPreserveStyle, Node* constrainingAncestor) |
1276 { | 1276 { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1350 return; | 1350 return; |
1351 DCHECK(destination.deepEquivalent().isConnected()) << destination; | 1351 DCHECK(destination.deepEquivalent().isConnected()) << destination; |
1352 | 1352 |
1353 // Add a br if pruning an empty block level element caused a collapse. For e
xample: | 1353 // Add a br if pruning an empty block level element caused a collapse. For e
xample: |
1354 // foo^ | 1354 // foo^ |
1355 // <div>bar</div> | 1355 // <div>bar</div> |
1356 // baz | 1356 // baz |
1357 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would | 1357 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would |
1358 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1358 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
1359 // Must recononicalize these two VisiblePositions after the pruning above. | 1359 // Must recononicalize these two VisiblePositions after the pruning above. |
1360 VisiblePosition beforeParagraph = createVisiblePosition(beforeParagraphPosit
ion.position()); | 1360 VisiblePosition beforeParagraph = createVisiblePositionDeprecated(beforePara
graphPosition.position()); |
1361 VisiblePosition afterParagraph = createVisiblePosition(afterParagraphPositio
n.position()); | 1361 VisiblePosition afterParagraph = createVisiblePositionDeprecated(afterParagr
aphPosition.position()); |
1362 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1362 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
1363 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1363 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
1364 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1364 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
1365 if (editingState->isAborted()) | 1365 if (editingState->isAborted()) |
1366 return; | 1366 return; |
1367 // Need an updateLayout here in case inserting the br has split a text n
ode. | 1367 // Need an updateLayout here in case inserting the br has split a text n
ode. |
1368 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 1368 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
1369 } | 1369 } |
1370 | 1370 |
1371 destinationIndex = TextIterator::rangeLength(Position::firstPositionInNode(d
ocument().documentElement()), destination.toParentAnchoredPosition(), true); | 1371 destinationIndex = TextIterator::rangeLength(Position::firstPositionInNode(d
ocument().documentElement()), destination.toParentAnchoredPosition(), true); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 | 1564 |
1565 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of | 1565 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of |
1566 // that anchor, as in NSTextView. | 1566 // that anchor, as in NSTextView. |
1567 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how | 1567 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how |
1568 // the caret was made. | 1568 // the caret was made. |
1569 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original, EditingState* editingState) | 1569 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original, EditingState* editingState) |
1570 { | 1570 { |
1571 if (original.isNull()) | 1571 if (original.isNull()) |
1572 return original; | 1572 return original; |
1573 | 1573 |
1574 VisiblePosition visiblePos = createVisiblePosition(original); | 1574 VisiblePosition visiblePos = createVisiblePositionDeprecated(original); |
1575 Element* enclosingAnchor = enclosingAnchorElement(original); | 1575 Element* enclosingAnchor = enclosingAnchorElement(original); |
1576 Position result = original; | 1576 Position result = original; |
1577 | 1577 |
1578 if (!enclosingAnchor) | 1578 if (!enclosingAnchor) |
1579 return result; | 1579 return result; |
1580 | 1580 |
1581 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. | 1581 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. |
1582 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { | 1582 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { |
1583 VisiblePosition firstInAnchor = VisiblePosition::firstPositionInNode(enc
losingAnchor); | 1583 VisiblePosition firstInAnchor = VisiblePosition::firstPositionInNode(enc
losingAnchor); |
1584 VisiblePosition lastInAnchor = VisiblePosition::lastPositionInNode(enclo
singAnchor); | 1584 VisiblePosition lastInAnchor = VisiblePosition::lastPositionInNode(enclo
singAnchor); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 return end; | 1641 return end; |
1642 | 1642 |
1643 Node* endNode = end; | 1643 Node* endNode = end; |
1644 Node* node = nullptr; | 1644 Node* node = nullptr; |
1645 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ | 1645 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ |
1646 Element* parentElement = node->parentElement(); | 1646 Element* parentElement = node->parentElement(); |
1647 if (!parentElement) | 1647 if (!parentElement) |
1648 break; | 1648 break; |
1649 // Do not split a node when doing so introduces an empty node. | 1649 // Do not split a node when doing so introduces an empty node. |
1650 VisiblePosition positionInParent = VisiblePosition::firstPositionInNode(
parentElement); | 1650 VisiblePosition positionInParent = VisiblePosition::firstPositionInNode(
parentElement); |
1651 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node)); | 1651 VisiblePosition positionInNode = createVisiblePositionDeprecated(firstPo
sitionInOrBeforeNode(node)); |
1652 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) | 1652 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) |
1653 splitElement(parentElement, node); | 1653 splitElement(parentElement, node); |
1654 } | 1654 } |
1655 | 1655 |
1656 return node; | 1656 return node; |
1657 } | 1657 } |
1658 | 1658 |
1659 DEFINE_TRACE(CompositeEditCommand) | 1659 DEFINE_TRACE(CompositeEditCommand) |
1660 { | 1660 { |
1661 visitor->trace(m_commands); | 1661 visitor->trace(m_commands); |
1662 visitor->trace(m_composition); | 1662 visitor->trace(m_composition); |
1663 EditCommand::trace(visitor); | 1663 EditCommand::trace(visitor); |
1664 } | 1664 } |
1665 | 1665 |
1666 } // namespace blink | 1666 } // namespace blink |
OLD | NEW |