/**
   * Enter a block where the selection will be preserved against the adverse effects of dom
   * mutation.
   *
   * <p>Must be balanced with a call to either {@link #restoreSelection()} or {@link
   * #restoreSelection(DocOp)}
   *
   * <p>Code that mutates the HTML dom must be guarded by calls to save and restore.
   */
  public void saveSelection() {
    if (editingConcerns != null && savedSelectionDepth == 0) {
      needToRestoreSelection = false;
      SelectionHelper helper = editingConcerns.getSelectionHelper();

      // Sometimes the document is not in an editing context, in which
      // case there is no selection helper.
      if (helper != null) {
        FocusedPointRange<Node> htmlSelection = NativeSelectionUtil.get();
        if (htmlSelection != null) {
          savedSelectionAnchor = htmlSelection.getAnchor();
          if (savedSelectionAnchor.isInTextNode()) {
            savedSelectionAnchorTextNodelet = savedSelectionAnchor.getContainer().cast();
            savedSelectionAnchorOffset = savedSelectionAnchor.getTextOffset();
          }
          savedSelectionFocus = htmlSelection.getFocus();
          if (savedSelectionFocus.isInTextNode()) {
            savedSelectionFocusTextNodelet = savedSelectionFocus.getContainer().cast();
            savedSelectionFocusOffset = savedSelectionFocus.getTextOffset();
          }
          savedSelection = helper.getSelectionRange();
        }
      }
    }

    savedSelectionDepth++;
  }
  /**
   * Same as {@link #restoreSelection()}, but if the selection is actually required to be explicitly
   * set, transform its saved location with the given modifier.
   */
  public void restoreSelection(DocOp modifier) {
    savedSelectionDepth--;

    if (editingConcerns != null && savedSelectionDepth == 0) {
      try {
        if (savedSelection != null) {
          // selectionChangedInappropriately() only deals with selection boundaries. If we had
          // a ranged selection, and we're in a browser where changing it internally matters,
          // then just always restore the selection. This is safe to do w.r.t. IMEs because it's
          // unlikely to have a ranged selection during an uncommitted IME state.
          needToRestoreSelection |=
              QuirksConstants.RANGED_SELECTION_AFFECTED_BY_INTERNAL_CHANGED
                  && !savedSelection.isCollapsed();

          if (needToRestoreSelection || selectionChangedInappropriately()) {
            if (modifier != null) {
              savedSelection = RangeHelper.applyModifier(savedSelection, modifier);
            }

            EditorStaticDeps.logger.trace().log("Restoring selection");
            if (document.size() >= 4) {
              editingConcerns.getSelectionHelper().setSelectionRange(savedSelection);
            }
          } else {
            EditorStaticDeps.logger.trace().log("Not restoring selection");
          }
        }
      } finally {
        savedSelection = null;
        savedSelectionAnchor = null;
        savedSelectionAnchorTextNodelet = null;
        savedSelectionAnchorOffset = 0;
        savedSelectionFocus = null;
        savedSelectionFocusTextNodelet = null;
        savedSelectionFocusOffset = 0;
      }
    }
  }