OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |