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

Side by Side Diff: third_party/WebKit/Source/core/editing/DOMSelection.cpp

Issue 2653523003: Make DOMSelection cache Range (Closed)
Patch Set: update Created 3 years, 10 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 if (selection.isNone()) 168 if (selection.isNone())
169 return "None"; 169 return "None";
170 if (selection.isCaret()) 170 if (selection.isCaret())
171 return "Caret"; 171 return "Caret";
172 return "Range"; 172 return "Range";
173 } 173 }
174 174
175 int DOMSelection::rangeCount() const { 175 int DOMSelection::rangeCount() const {
176 if (!isAvailable()) 176 if (!isAvailable())
177 return 0; 177 return 0;
178 if (m_range)
179 return 1;
178 return frame()->selection().isNone() ? 0 : 1; 180 return frame()->selection().isNone() ? 0 : 1;
179 } 181 }
180 182
181 void DOMSelection::collapse(Node* node, 183 void DOMSelection::collapse(Node* node,
182 int offset, 184 int offset,
183 ExceptionState& exceptionState) { 185 ExceptionState& exceptionState) {
184 if (!isAvailable()) 186 if (!isAvailable())
185 return; 187 return;
186 188
187 if (!node) { 189 if (!node) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 if (static_cast<unsigned>(offset) > node->lengthOfContents()) { 378 if (static_cast<unsigned>(offset) > node->lengthOfContents()) {
377 exceptionState.throwDOMException( 379 exceptionState.throwDOMException(
378 IndexSizeError, 380 IndexSizeError,
379 String::number(offset) + " is larger than the given node's length."); 381 String::number(offset) + " is larger than the given node's length.");
380 return; 382 return;
381 } 383 }
382 384
383 if (!isValidForPosition(node)) 385 if (!isValidForPosition(node))
384 return; 386 return;
385 387
388 markRangeDirty();
386 const Position& base = frame()->selection().base(); 389 const Position& base = frame()->selection().base();
387 if (base.isNull()) { 390 if (base.isNull()) {
388 // TODO(editing-dev): We should throw |InvalidStateError| if selection is 391 // TODO(editing-dev): We should throw |InvalidStateError| if selection is
389 // none to follow the spec. 392 // none to follow the spec.
390 frame()->selection().setSelection(SelectionInDOMTree::Builder() 393 frame()->selection().setSelection(SelectionInDOMTree::Builder()
391 .collapse(Position(node, offset)) 394 .collapse(Position(node, offset))
392 .setIsDirectional(true) 395 .setIsDirectional(true)
393 .build()); 396 .build());
394 return; 397 return;
395 } 398 }
(...skipping 10 matching lines...) Expand all
406 409
407 if (index < 0 || index >= rangeCount()) { 410 if (index < 0 || index >= rangeCount()) {
408 exceptionState.throwDOMException( 411 exceptionState.throwDOMException(
409 IndexSizeError, String::number(index) + " is not a valid index."); 412 IndexSizeError, String::number(index) + " is not a valid index.");
410 return nullptr; 413 return nullptr;
411 } 414 }
412 415
413 // If you're hitting this, you've added broken multi-range selection support 416 // If you're hitting this, you've added broken multi-range selection support
414 DCHECK_EQ(rangeCount(), 1); 417 DCHECK_EQ(rangeCount(), 1);
415 418
419 if (m_range)
420 return m_range;
421
422 Range* range = createRangeFromSelectionEditor();
423 cacheRangeIfAttachedToRootDocument(range);
424 return range;
425 }
426
427 Range* DOMSelection::createRangeFromSelectionEditor() {
416 Position anchor = anchorPosition(visibleSelection()); 428 Position anchor = anchorPosition(visibleSelection());
417 if (!anchor.anchorNode()->isInShadowTree()) 429 if (!anchor.anchorNode()->isInShadowTree())
418 return frame()->selection().firstRange(); 430 return frame()->selection().firstRange();
419 431
420 Node* node = shadowAdjustedNode(anchor); 432 Node* node = shadowAdjustedNode(anchor);
421 if (!node) // crbug.com/595100 433 if (!node) // crbug.com/595100
422 return nullptr; 434 return nullptr;
423 if (!visibleSelection().isBaseFirst()) 435 if (!visibleSelection().isBaseFirst())
424 return Range::create(*anchor.document(), focusNode(), focusOffset(), node, 436 return Range::create(*anchor.document(), focusNode(), focusOffset(), node,
425 anchorOffset()); 437 anchorOffset());
426 return Range::create(*anchor.document(), node, anchorOffset(), focusNode(), 438 return Range::create(*anchor.document(), node, anchorOffset(), focusNode(),
427 focusOffset()); 439 focusOffset());
428 } 440 }
429 441
442 void DOMSelection::markRangeDirty() {
443 m_range = nullptr;
444 }
445
446 void DOMSelection::cacheRangeIfAttachedToRootDocument(Range* range) {
447 if (m_treeScope->parentTreeScope())
448 return;
449
450 m_range = range;
451 }
452
430 void DOMSelection::removeAllRanges() { 453 void DOMSelection::removeAllRanges() {
454 m_range = nullptr;
431 if (!isAvailable()) 455 if (!isAvailable())
432 return; 456 return;
433 frame()->selection().clear(); 457 frame()->selection().clear();
434 } 458 }
435 459
436 void DOMSelection::addRange(Range* newRange) { 460 void DOMSelection::addRange(Range* newRange) {
437 DCHECK(newRange); 461 DCHECK(newRange);
438 462
439 if (!isAvailable()) 463 if (!isAvailable())
440 return; 464 return;
(...skipping 15 matching lines...) Expand all
456 480
457 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 481 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
458 // needs to be audited. See http://crbug.com/590369 for more details. 482 // needs to be audited. See http://crbug.com/590369 for more details.
459 // In the long term, we should change FrameSelection::setSelection to take a 483 // In the long term, we should change FrameSelection::setSelection to take a
460 // parameter that does not require clean layout, so that modifying selection 484 // parameter that does not require clean layout, so that modifying selection
461 // no longer performs synchronous layout by itself. 485 // no longer performs synchronous layout by itself.
462 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets(); 486 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
463 487
464 if (selection.isNone()) { 488 if (selection.isNone()) {
465 selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY); 489 selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY);
490 cacheRangeIfAttachedToRootDocument(newRange);
466 return; 491 return;
467 } 492 }
468 493
469 Range* originalRange = selection.firstRange(); 494 Range* originalRange = selection.firstRange();
470 495
471 if (originalRange->startContainer()->document() != 496 if (originalRange->startContainer()->document() !=
472 newRange->startContainer()->document()) { 497 newRange->startContainer()->document()) {
473 addConsoleError( 498 addConsoleError(
474 "The given range does not belong to the current selection's document."); 499 "The given range does not belong to the current selection's document.");
475 return; 500 return;
(...skipping 27 matching lines...) Expand all
503 ? originalRange 528 ? originalRange
504 : newRange; 529 : newRange;
505 Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange, 530 Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange,
506 ASSERT_NO_EXCEPTION) < 0 531 ASSERT_NO_EXCEPTION) < 0
507 ? newRange 532 ? newRange
508 : originalRange; 533 : originalRange;
509 const EphemeralRange merged = 534 const EphemeralRange merged =
510 EphemeralRange(start->startPosition(), end->endPosition()); 535 EphemeralRange(start->startPosition(), end->endPosition());
511 TextAffinity affinity = selection.selection().affinity(); 536 TextAffinity affinity = selection.selection().affinity();
512 selection.setSelectedRange(merged, affinity); 537 selection.setSelectedRange(merged, affinity);
538 cacheRangeIfAttachedToRootDocument(createRange(merged));
513 } 539 }
514 540
515 void DOMSelection::deleteFromDocument() { 541 void DOMSelection::deleteFromDocument() {
516 if (!isAvailable()) 542 if (!isAvailable())
517 return; 543 return;
518 544
519 FrameSelection& selection = frame()->selection(); 545 FrameSelection& selection = frame()->selection();
520 546
521 if (selection.isNone()) 547 if (selection.isNone())
522 return; 548 return;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 } 690 }
665 691
666 void DOMSelection::addConsoleError(const String& message) { 692 void DOMSelection::addConsoleError(const String& message) {
667 if (m_treeScope) 693 if (m_treeScope)
668 m_treeScope->document().addConsoleMessage( 694 m_treeScope->document().addConsoleMessage(
669 ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message)); 695 ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
670 } 696 }
671 697
672 DEFINE_TRACE(DOMSelection) { 698 DEFINE_TRACE(DOMSelection) {
673 visitor->trace(m_treeScope); 699 visitor->trace(m_treeScope);
700 visitor->trace(m_range);
674 ContextClient::trace(visitor); 701 ContextClient::trace(visitor);
675 } 702 }
676 703
677 } // namespace blink 704 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698