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

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

Issue 2653523003: Make DOMSelection cache Range (Closed)
Patch Set: cache Range in SelectionEditor 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 (isTreeScopeDocument() && documentCachedRange())
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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 return; 281 return;
280 } 282 }
281 if (!extentNode) { 283 if (!extentNode) {
282 UseCounter::count(frame(), UseCounter::SelectionSetBaseAndExtentNull); 284 UseCounter::count(frame(), UseCounter::SelectionSetBaseAndExtentNull);
283 extentOffset = 0; 285 extentOffset = 0;
284 } 286 }
285 287
286 if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode)) 288 if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode))
287 return; 289 return;
288 290
291 if (isTreeScopeDocument())
292 clearDocumentCachedRange();
293
289 // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets 294 // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
290 // needs to be audited. See http://crbug.com/590369 for more details. 295 // needs to be audited. See http://crbug.com/590369 for more details.
291 // In the long term, we should change FrameSelection::setSelection to take a 296 // In the long term, we should change FrameSelection::setSelection to take a
292 // parameter that does not require clean layout, so that modifying selection 297 // parameter that does not require clean layout, so that modifying selection
293 // no longer performs synchronous layout by itself. 298 // no longer performs synchronous layout by itself.
294 // TODO(editing-dev): Once SVG USE element doesn't modifies DOM tree, we 299 // TODO(editing-dev): Once SVG USE element doesn't modifies DOM tree, we
295 // should get rid of this update layout call. 300 // should get rid of this update layout call.
296 // See http://crbug.com/566281 301 // See http://crbug.com/566281
297 // See "svg/text/textpath-reference-crash.html" 302 // See "svg/text/textpath-reference-crash.html"
298 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets(); 303 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 if (static_cast<unsigned>(offset) > node->lengthOfContents()) { 381 if (static_cast<unsigned>(offset) > node->lengthOfContents()) {
377 exceptionState.throwDOMException( 382 exceptionState.throwDOMException(
378 IndexSizeError, 383 IndexSizeError,
379 String::number(offset) + " is larger than the given node's length."); 384 String::number(offset) + " is larger than the given node's length.");
380 return; 385 return;
381 } 386 }
382 387
383 if (!isValidForPosition(node)) 388 if (!isValidForPosition(node))
384 return; 389 return;
385 390
391 if (isTreeScopeDocument())
392 clearDocumentCachedRange();
386 const Position& base = frame()->selection().base(); 393 const Position& base = frame()->selection().base();
387 if (base.isNull()) { 394 if (base.isNull()) {
388 // TODO(editing-dev): We should throw |InvalidStateError| if selection is 395 // TODO(editing-dev): We should throw |InvalidStateError| if selection is
389 // none to follow the spec. 396 // none to follow the spec.
390 frame()->selection().setSelection(SelectionInDOMTree::Builder() 397 frame()->selection().setSelection(SelectionInDOMTree::Builder()
391 .collapse(Position(node, offset)) 398 .collapse(Position(node, offset))
392 .setIsDirectional(true) 399 .setIsDirectional(true)
393 .build()); 400 .build());
394 return; 401 return;
395 } 402 }
(...skipping 10 matching lines...) Expand all
406 413
407 if (index < 0 || index >= rangeCount()) { 414 if (index < 0 || index >= rangeCount()) {
408 exceptionState.throwDOMException( 415 exceptionState.throwDOMException(
409 IndexSizeError, String::number(index) + " is not a valid index."); 416 IndexSizeError, String::number(index) + " is not a valid index.");
410 return nullptr; 417 return nullptr;
411 } 418 }
412 419
413 // If you're hitting this, you've added broken multi-range selection support 420 // If you're hitting this, you've added broken multi-range selection support
414 DCHECK_EQ(rangeCount(), 1); 421 DCHECK_EQ(rangeCount(), 1);
415 422
423 if (!isTreeScopeDocument())
yosin_UTC9 2017/02/09 06:52:06 If we have |cachedRangeIfDocumentSlection()| and |
yoichio 2017/02/09 09:31:19 Done.
424 return createRangeFromSelectionEditor();
425
426 if (Range* cachedRange = documentCachedRange())
427 return cachedRange;
428
429 Range* range = createRangeFromSelectionEditor();
430 cacheRangeOfDocument(range);
431 return range;
432 }
433
434 Range* DOMSelection::createRangeFromSelectionEditor() {
416 Position anchor = anchorPosition(visibleSelection()); 435 Position anchor = anchorPosition(visibleSelection());
417 if (!anchor.anchorNode()->isInShadowTree()) 436 if (!anchor.anchorNode()->isInShadowTree())
418 return frame()->selection().firstRange(); 437 return frame()->selection().firstRange();
419 438
420 Node* node = shadowAdjustedNode(anchor); 439 Node* node = shadowAdjustedNode(anchor);
421 if (!node) // crbug.com/595100 440 if (!node) // crbug.com/595100
422 return nullptr; 441 return nullptr;
423 if (!visibleSelection().isBaseFirst()) 442 if (!visibleSelection().isBaseFirst())
424 return Range::create(*anchor.document(), focusNode(), focusOffset(), node, 443 return Range::create(*anchor.document(), focusNode(), focusOffset(), node,
425 anchorOffset()); 444 anchorOffset());
426 return Range::create(*anchor.document(), node, anchorOffset(), focusNode(), 445 return Range::create(*anchor.document(), node, anchorOffset(), focusNode(),
427 focusOffset()); 446 focusOffset());
428 } 447 }
429 448
449 bool DOMSelection::isTreeScopeDocument() const {
yosin_UTC9 2017/02/09 06:52:06 nit: s/isTreeScopeDocument/isSelectionForDocument/
yoichio 2017/02/09 09:31:19 Done.
450 return m_treeScope == m_treeScope->document();
451 }
452
453 void DOMSelection::cacheRangeOfDocument(Range* range) {
454 DCHECK(isTreeScopeDocument());
455 frame()->selection().cacheRangeOfDocument(range);
456 }
457
458 Range* DOMSelection::documentCachedRange() const {
459 DCHECK(isTreeScopeDocument());
460 return frame()->selection().documentCachedRange();
461 }
462
463 void DOMSelection::clearDocumentCachedRange() {
464 frame()->selection().clearDocumentCachedRange();
yosin_UTC9 2017/02/09 06:52:06 Let's add |DCHECK(isTreeScopeDocument())|. It see
yoichio 2017/02/09 09:31:19 Done.
465 }
466
430 void DOMSelection::removeAllRanges() { 467 void DOMSelection::removeAllRanges() {
431 if (!isAvailable()) 468 if (!isAvailable())
432 return; 469 return;
433 frame()->selection().clear(); 470 frame()->selection().clear();
434 } 471 }
435 472
436 void DOMSelection::addRange(Range* newRange) { 473 void DOMSelection::addRange(Range* newRange) {
437 DCHECK(newRange); 474 DCHECK(newRange);
438 475
439 if (!isAvailable()) 476 if (!isAvailable())
(...skipping 16 matching lines...) Expand all
456 493
457 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 494 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
458 // needs to be audited. See http://crbug.com/590369 for more details. 495 // 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 496 // In the long term, we should change FrameSelection::setSelection to take a
460 // parameter that does not require clean layout, so that modifying selection 497 // parameter that does not require clean layout, so that modifying selection
461 // no longer performs synchronous layout by itself. 498 // no longer performs synchronous layout by itself.
462 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets(); 499 frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
463 500
464 if (selection.isNone()) { 501 if (selection.isNone()) {
465 selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY); 502 selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY);
503 if (isTreeScopeDocument())
yosin_UTC9 2017/02/09 06:52:06 |cacheRangeIfDocumentSlection(newRange)| is simple
yoichio 2017/02/09 09:31:19 Done.
504 cacheRangeOfDocument(newRange);
466 return; 505 return;
467 } 506 }
468 507
469 Range* originalRange = selection.firstRange(); 508 Range* originalRange = selection.firstRange();
470 509
471 if (originalRange->startContainer()->document() != 510 if (originalRange->startContainer()->document() !=
472 newRange->startContainer()->document()) { 511 newRange->startContainer()->document()) {
473 addConsoleError( 512 addConsoleError(
474 "The given range does not belong to the current selection's document."); 513 "The given range does not belong to the current selection's document.");
475 return; 514 return;
(...skipping 27 matching lines...) Expand all
503 ? originalRange 542 ? originalRange
504 : newRange; 543 : newRange;
505 Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange, 544 Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange,
506 ASSERT_NO_EXCEPTION) < 0 545 ASSERT_NO_EXCEPTION) < 0
507 ? newRange 546 ? newRange
508 : originalRange; 547 : originalRange;
509 const EphemeralRange merged = 548 const EphemeralRange merged =
510 EphemeralRange(start->startPosition(), end->endPosition()); 549 EphemeralRange(start->startPosition(), end->endPosition());
511 TextAffinity affinity = selection.selection().affinity(); 550 TextAffinity affinity = selection.selection().affinity();
512 selection.setSelectedRange(merged, affinity); 551 selection.setSelectedRange(merged, affinity);
552 if (isTreeScopeDocument())
553 cacheRangeOfDocument(newRange);
513 } 554 }
514 555
515 void DOMSelection::deleteFromDocument() { 556 void DOMSelection::deleteFromDocument() {
516 if (!isAvailable()) 557 if (!isAvailable())
517 return; 558 return;
518 559
519 FrameSelection& selection = frame()->selection(); 560 FrameSelection& selection = frame()->selection();
520 561
521 if (selection.isNone()) 562 if (selection.isNone())
522 return; 563 return;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 m_treeScope->document().addConsoleMessage( 709 m_treeScope->document().addConsoleMessage(
669 ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message)); 710 ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
670 } 711 }
671 712
672 DEFINE_TRACE(DOMSelection) { 713 DEFINE_TRACE(DOMSelection) {
673 visitor->trace(m_treeScope); 714 visitor->trace(m_treeScope);
674 ContextClient::trace(visitor); 715 ContextClient::trace(visitor);
675 } 716 }
676 717
677 } // namespace blink 718 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698