Nullptr crash in EditCommand::EditCommand via CompositeEditCommand::removeNode
authorshihchieh_lee@apple.com <shihchieh_lee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2020 16:36:38 +0000 (16:36 +0000)
committershihchieh_lee@apple.com <shihchieh_lee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2020 16:36:38 +0000 (16:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=207600
<rdar://problem/56969450>

Reviewed by Geoffrey Garen.

Source/WebCore:

Move FrameSelection and Editor objects from Frame to Document so when a document is detached
in nested command executions, the next EditCommand would not fail in constructor.

Test: editing/inserting/insert-list-then-edit-command-crash.html

* dom/Document.cpp:
(WebCore::m_selection):
(WebCore::Document::prepareForDestruction):
(WebCore::m_undoManager): Deleted.
* dom/Document.h:
(WebCore::Document::editor):
(WebCore::Document::editor const):
(WebCore::Document::selection):
(WebCore::Document::selection const):
* dom/PositionIterator.cpp:
(WebCore::PositionIterator::isCandidate const):
* editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::AlternativeTextController):
(WebCore::AlternativeTextController::stopPendingCorrection):
(WebCore::AlternativeTextController::isSpellingMarkerAllowed const):
(WebCore::AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate):
(WebCore::AlternativeTextController::respondToUnappliedSpellCorrection):
(WebCore::AlternativeTextController::timerFired):
(WebCore::AlternativeTextController::handleAlternativeTextUIResult):
(WebCore::AlternativeTextController::rootViewRectForRange const):
(WebCore::AlternativeTextController::respondToChangedSelection):
(WebCore::AlternativeTextController::respondToAppliedEditing):
(WebCore::AlternativeTextController::respondToUnappliedEditing):
(WebCore::AlternativeTextController::editorClient):
(WebCore::AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand):
(WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult):
(WebCore::AlternativeTextController::respondToMarkerAtEndOfWord):
(WebCore::AlternativeTextController::alternativeTextClient):
(WebCore::AlternativeTextController::applyAlternativeTextToRange):
(WebCore::AlternativeTextController::insertDictatedText):
(WebCore::AlternativeTextController::applyDictationAlternative):
* editing/AlternativeTextController.h:
(WebCore::AlternativeTextController::UNLESS_ENABLED):
* editing/CompositeEditCommand.cpp:
(WebCore::EditCommandComposition::unapply):
(WebCore::EditCommandComposition::reapply):
(WebCore::CompositeEditCommand::willApplyCommand):
(WebCore::CompositeEditCommand::didApplyCommand):
(WebCore::CompositeEditCommand::targetRanges const):
(WebCore::CompositeEditCommand::moveParagraphs):
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::saveTypingStyleState):
(WebCore::DeleteSelectionCommand::mergeParagraphs):
(WebCore::DeleteSelectionCommand::calculateTypingStyleAfterDelete):
(WebCore::DeleteSelectionCommand::doApply):
* editing/EditCommand.cpp:
(WebCore::EditCommand::EditCommand):
(WebCore::EditCommand::isEditingTextAreaOrTextInput const):
(WebCore::EditCommand::postTextStateChangeNotification):
(WebCore::EditCommand::frame): Deleted.
(WebCore::EditCommand::frame const): Deleted.
* editing/EditCommand.h:
* editing/Editing.cpp:
(WebCore::createDefaultParagraphElement):
* editing/EditingStyle.cpp:
(WebCore::StyleChange::StyleChange):
* editing/Editor.cpp:
(WebCore::ClearTextCommand::CreateAndApply):
(WebCore::TemporarySelectionChange::TemporarySelectionChange):
(WebCore::TemporarySelectionChange::~TemporarySelectionChange):
(WebCore::TemporarySelectionChange::setSelection):
(WebCore::Editor::selectionForCommand):
(WebCore::Editor::behavior const):
(WebCore::Editor::client const):
(WebCore::Editor::canEdit const):
(WebCore::Editor::canEditRichly const):
(WebCore::Editor::canDHTMLCut):
(WebCore::Editor::canDHTMLCopy):
(WebCore::Editor::canCopy const):
(WebCore::Editor::canPaste const):
(WebCore::Editor::canDelete const):
(WebCore::Editor::shouldSmartDelete):
(WebCore::Editor::deleteWithDirection):
(WebCore::Editor::deleteSelectionWithSmartDelete):
(WebCore::Editor::clearText):
(WebCore::Editor::replaceSelectionWithFragment):
(WebCore::Editor::selectedRange):
(WebCore::Editor::tryDHTMLCopy):
(WebCore::Editor::tryDHTMLCut):
(WebCore::Editor::shouldInsertText const):
(WebCore::Editor::hasBidiSelection const):
(WebCore::Editor::selectionUnorderedListState const):
(WebCore::Editor::selectionOrderedListState const):
(WebCore::Editor::increaseSelectionListLevel):
(WebCore::Editor::increaseSelectionListLevelOrdered):
(WebCore::Editor::increaseSelectionListLevelUnordered):
(WebCore::Editor::decreaseSelectionListLevel):
(WebCore::Editor::findEventTargetFromSelection const):
(WebCore::Editor::applyStyle):
(WebCore::Editor::applyParagraphStyle):
(WebCore::Editor::applyStyleToSelection):
(WebCore::Editor::applyParagraphStyleToSelection):
(WebCore::Editor::selectionStartHasStyle const):
(WebCore::Editor::selectionHasStyle const):
(WebCore::Editor::selectionStartCSSPropertyValue):
(WebCore::Editor::appliedEditing):
(WebCore::Editor::Editor):
(WebCore::Editor::clear):
(WebCore::Editor::insertText):
(WebCore::Editor::insertTextForConfirmedComposition):
(WebCore::Editor::insertTextWithoutSendingTextEvent):
(WebCore::Editor::insertLineBreak):
(WebCore::Editor::insertParagraphSeparator):
(WebCore::Editor::performCutOrCopy):
(WebCore::Editor::paste):
(WebCore::Editor::pasteAsQuotation):
(WebCore::Editor::renderLayerDidScroll):
(WebCore::Editor::setBaseWritingDirection):
(WebCore::Editor::baseWritingDirectionForSelectionStart const):
(WebCore::Editor::selectComposition):
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
(WebCore::Editor::setComposition):
(WebCore::Editor::ignoreSpelling):
(WebCore::Editor::learnSpelling):
(WebCore::Editor::advanceToNextMisspelling):
(WebCore::Editor::misspelledWordAtCaretOrRange const):
(WebCore::Editor::isSelectionUngrammatical):
(WebCore::Editor::guessesForMisspelledWord const):
(WebCore::Editor::guessesForMisspelledOrUngrammatical):
(WebCore::Editor::markMisspellingsAfterTypingToWord):
(WebCore::Editor::isSpellCheckingEnabledInFocusedNode const):
(WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
(WebCore::Editor::markAndReplaceFor):
(WebCore::Editor::updateMarkersForWordsAffectedByEditing):
(WebCore::Editor::rangeForPoint):
(WebCore::Editor::revealSelectionAfterEditingOperation):
(WebCore::Editor::setIgnoreSelectionChanges):
(WebCore::Editor::getCompositionSelection const):
(WebCore::Editor::transpose):
(WebCore::Editor::changeSelectionAfterCommand):
(WebCore::Editor::selectedText const):
(WebCore::Editor::selectedTextForDataTransfer const):
(WebCore::Editor::insertTextPlaceholder):
(WebCore::Editor::removeTextPlaceholder):
(WebCore::Editor::shouldChangeSelection const):
(WebCore::Editor::computeAndSetTypingStyle):
(WebCore::Editor::findString):
(WebCore::Editor::countMatchesForText):
(WebCore::Editor::respondToChangedSelection):
(WebCore::Editor::shouldDetectTelephoneNumbers):
(WebCore::Editor::scanSelectionForTelephoneNumbers):
(WebCore::Editor::editorUIUpdateTimerFired):
(WebCore::Editor::selectionStartHasMarkerFor const):
(WebCore::candidateRangeForSelection):
(WebCore::Editor::stringForCandidateRequest const):
(WebCore::Editor::contextRangeForCandidateRequest const):
(WebCore::Editor::fontAttributesAtSelectionStart const):
(WebCore::Editor::notifyClientOfAttachmentUpdates):
(WebCore::Editor::handleAcceptedCandidate):
(WebCore::Editor::unifiedTextCheckerEnabled const):
(WebCore::Editor::toggleOverwriteModeEnabled):
(WebCore::Editor::fontForSelection const):
(WebCore::Editor::canCopyExcludingStandaloneImages const):
(WebCore::Editor::document const): Deleted.
* editing/Editor.h:
(WebCore::TemporarySelectionChange::TemporarySelectionChange):
(WebCore::IgnoreSelectionChangeForScope::IgnoreSelectionChangeForScope):
(WebCore::Editor::document const):
* editing/EditorCommand.cpp:
(WebCore::executeSwapWithMark):
(WebCore::Editor::command):
(WebCore::Editor::Command::Command):
(WebCore::Editor::Command::execute const):
* editing/FrameSelection.cpp:
(WebCore::shouldAlwaysUseDirectionalSelection):
(WebCore::FrameSelection::FrameSelection):
(WebCore::FrameSelection::rootEditableElementOrDocumentElement const):
(WebCore::FrameSelection::setSelectionByMouseIfDifferent):
(WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance):
(WebCore::FrameSelection::setSelection):
(WebCore::updateSelectionByUpdatingLayoutOrStyle):
(WebCore::FrameSelection::setNeedsSelectionUpdate):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::updateDataDetectorsForSelection):
(WebCore::FrameSelection::positionForPlatform const):
(WebCore::FrameSelection::nextWordPositionForPlatform):
(WebCore::FrameSelection::modifyMovingRight):
(WebCore::FrameSelection::modifyMovingLeft):
(WebCore::FrameSelection::modify):
(WebCore::FrameSelection::prepareForDestruction):
(WebCore::FrameSelection::absoluteCaretBounds):
(WebCore::FrameSelection::recomputeCaretRect):
(WebCore::FrameSelection::contains const):
(WebCore::FrameSelection::selectAll):
(WebCore::FrameSelection::focusedOrActiveStateChanged):
(WebCore::FrameSelection::isFocusedAndActive const):
(WebCore::shouldStopBlinkingDueToTypingCommand):
(WebCore::FrameSelection::updateAppearance):
(WebCore::FrameSelection::setCaretVisibility):
(WebCore::FrameSelection::setFocusedElementIfNeeded):
(WebCore::FrameSelection::shouldDeleteSelection const):
(WebCore::FrameSelection::selectionBounds const):
(WebCore::FrameSelection::getClippedVisibleTextRectangles const):
(WebCore::FrameSelection::currentForm const):
(WebCore::FrameSelection::revealSelection):
(WebCore::FrameSelection::setSelectionFromNone):
(WebCore::FrameSelection::shouldChangeSelection const):
(WebCore::FrameSelection::setShouldShowBlockCursor):
(WebCore::FrameSelection::appearanceUpdateTimerFired):
(WebCore::FrameSelection::updateAppearanceAfterLayoutOrStyleChange):
(WebCore::FrameSelection::selectRangeOnElement):
(WebCore::FrameSelection::setCaretBlinks):
* editing/FrameSelection.h:
* editing/InsertIntoTextNodeCommand.cpp:
(WebCore::InsertIntoTextNodeCommand::doApply):
* editing/InsertLineBreakCommand.cpp:
(WebCore::InsertLineBreakCommand::doApply):
* editing/InsertTextCommand.cpp:
(WebCore::InsertTextCommand::doApply):
* editing/ReplaceRangeWithTextCommand.cpp:
(WebCore::ReplaceRangeWithTextCommand::doApply):
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::doApply):
* editing/SetSelectionCommand.cpp:
(WebCore::SetSelectionCommand::doApply):
(WebCore::SetSelectionCommand::doUnapply):
* editing/SpellChecker.cpp:
(WebCore::SpellChecker::SpellChecker):
(WebCore::SpellChecker::client const):
(WebCore::SpellChecker::isAsynchronousEnabled const):
(WebCore::SpellChecker::invokeRequest):
(WebCore::SpellChecker::didCheck):
(WebCore::SpellChecker::didCheckSucceed):
* editing/SpellChecker.h:
* editing/SpellingCorrectionCommand.cpp:
(WebCore::SpellingCorrectionCommand::doApply):
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::deleteSelection):
(WebCore::TypingCommand::deleteKeyPressed):
(WebCore::TypingCommand::forwardDeleteKeyPressed):
(WebCore::TypingCommand::updateSelectionIfDifferentFromCurrentSelection):
(WebCore::TypingCommand::insertText):
(WebCore::TypingCommand::insertLineBreak):
(WebCore::TypingCommand::insertParagraphSeparatorInQuotedContent):
(WebCore::TypingCommand::insertParagraphSeparator):
(WebCore::TypingCommand::lastTypingCommandIfStillOpenForTyping):
(WebCore::TypingCommand::closeTyping):
(WebCore::TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping):
(WebCore::TypingCommand::markMisspellingsAfterTyping):
(WebCore::TypingCommand::willAddTypingToOpenCommand):
(WebCore::TypingCommand::typingAddedToOpenCommand):
(WebCore::TypingCommand::insertTextAndNotifyAccessibility):
(WebCore::TypingCommand::insertTextRunWithoutNewlines):
(WebCore::TypingCommand::insertLineBreakAndNotifyAccessibility):
(WebCore::TypingCommand::insertParagraphSeparatorAndNotifyAccessibility):
(WebCore::TypingCommand::insertParagraphSeparatorInQuotedContentAndNotifyAccessibility):
* editing/TypingCommand.h:
* editing/cocoa/EditorCocoa.mm:
(WebCore::Editor::selectionInHTMLFormat):
(WebCore::Editor::writeSelectionToPasteboard):
(WebCore::Editor::writeSelection):
(WebCore::Editor::selectionInWebArchiveFormat):
(WebCore::Editor::replaceSelectionWithAttributedString):
(WebCore::Editor::webContentFromPasteboard):
(WebCore::Editor::takeFindStringFromSelection):
* editing/gtk/EditorGtk.cpp:
(WebCore::Editor::pasteWithPasteboard):
(WebCore::Editor::writeSelectionToPasteboard):
(WebCore::Editor::webContentFromPasteboard):
* editing/ios/EditorIOS.mm:
(WebCore::Editor::setTextAlignmentForChangedBaseWritingDirection):
(WebCore::Editor::removeUnchangeableStyles):
(WebCore::Editor::pasteWithPasteboard):
(WebCore::Editor::insertDictationPhrases):
(WebCore::Editor::setDictationPhrasesAsChildOfElement):
(WebCore::Editor::setTextAsChildOfElement):
(WebCore::Editor::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping):
* editing/libwpe/EditorLibWPE.cpp:
(WebCore::Editor::writeSelectionToPasteboard):
(WebCore::Editor::pasteWithPasteboard):
* editing/mac/EditorMac.mm:
(WebCore::Editor::readSelectionFromPasteboard):
(WebCore::Editor::replaceNodeFromPasteboard):
(WebCore::Editor::selectionWillChange):
* editing/win/EditorWin.cpp:
(WebCore::Editor::pasteWithPasteboard):
(WebCore::Editor::webContentFromPasteboard):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::willTransitionToCommitted):
(WebCore::FrameLoader::closeURL):
(WebCore::FrameLoader::didOpenURL):
(WebCore::FrameLoader::clear):
* page/Frame.cpp:
(WebCore::Frame::Frame):
(WebCore::Frame::requestDOMPasteAccess):
(WebCore::Frame::setPageAndTextZoomFactors):
* page/Frame.h:
* page/TextIndicator.cpp:
(WebCore::TextIndicator::createWithRange):

LayoutTests:

Added a regression test for the crash.

* editing/inserting/insert-list-then-edit-command-crash-expected.txt: Added.
* editing/inserting/insert-list-then-edit-command-crash.html: Added.

Modify the test result. FrameSelection is being destructed along with
document so an additional selection change notification is expected.

* platform/mac/editing/pasteboard/drag-drop-dead-frame-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@260831 268f45cc-cd09-0410-ab3c-d52691b4dbfc

42 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/inserting/insert-list-then-edit-command-crash-expected.txt [new file with mode: 0644]
LayoutTests/editing/inserting/insert-list-then-edit-command-crash.html [new file with mode: 0644]
LayoutTests/platform/mac/editing/pasteboard/drag-drop-dead-frame-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/editing/AlternativeTextController.cpp
Source/WebCore/editing/AlternativeTextController.h
Source/WebCore/editing/CompositeEditCommand.cpp
Source/WebCore/editing/DeleteSelectionCommand.cpp
Source/WebCore/editing/EditCommand.cpp
Source/WebCore/editing/EditCommand.h
Source/WebCore/editing/Editing.cpp
Source/WebCore/editing/EditingStyle.cpp
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/EditorCommand.cpp
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/FrameSelection.h
Source/WebCore/editing/InsertIntoTextNodeCommand.cpp
Source/WebCore/editing/InsertLineBreakCommand.cpp
Source/WebCore/editing/InsertTextCommand.cpp
Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp
Source/WebCore/editing/ReplaceSelectionCommand.cpp
Source/WebCore/editing/SetSelectionCommand.cpp
Source/WebCore/editing/SpellChecker.cpp
Source/WebCore/editing/SpellChecker.h
Source/WebCore/editing/SpellingCorrectionCommand.cpp
Source/WebCore/editing/TypingCommand.cpp
Source/WebCore/editing/TypingCommand.h
Source/WebCore/editing/cocoa/EditorCocoa.mm
Source/WebCore/editing/gtk/EditorGtk.cpp
Source/WebCore/editing/ios/EditorIOS.mm
Source/WebCore/editing/libwpe/EditorLibWPE.cpp
Source/WebCore/editing/mac/EditorMac.mm
Source/WebCore/editing/win/EditorWin.cpp
Source/WebCore/history/CachedFrame.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/page/Frame.cpp
Source/WebCore/page/Frame.h
Source/WebCore/page/TextIndicator.cpp

index 0c66593..a849bca 100644 (file)
@@ -1,3 +1,21 @@
+2020-04-28  Jack Lee  <shihchieh_lee@apple.com>
+
+        Nullptr crash in EditCommand::EditCommand via CompositeEditCommand::removeNode
+        https://bugs.webkit.org/show_bug.cgi?id=207600
+        <rdar://problem/56969450>
+
+        Reviewed by Geoffrey Garen.
+
+        Added a regression test for the crash.
+
+        * editing/inserting/insert-list-then-edit-command-crash-expected.txt: Added.
+        * editing/inserting/insert-list-then-edit-command-crash.html: Added.
+
+        Modify the test result. FrameSelection is being destructed along with
+        document so an additional selection change notification is expected.
+
+        * platform/mac/editing/pasteboard/drag-drop-dead-frame-expected.txt:
+
 2020-04-28  Alejandro G. Castro  <alex@igalia.com>
 
         [GTK][WebGL] compositing/clipping/border-radius-on-webgl.html is failing since added
diff --git a/LayoutTests/editing/inserting/insert-list-then-edit-command-crash-expected.txt b/LayoutTests/editing/inserting/insert-list-then-edit-command-crash-expected.txt
new file mode 100644 (file)
index 0000000..3040342
--- /dev/null
@@ -0,0 +1 @@
+Tests inserting list followed by an edit command. The test passes if WebKit doesn't crash or hit an assertion.
diff --git a/LayoutTests/editing/inserting/insert-list-then-edit-command-crash.html b/LayoutTests/editing/inserting/insert-list-then-edit-command-crash.html
new file mode 100644 (file)
index 0000000..3af381d
--- /dev/null
@@ -0,0 +1,19 @@
+<body><image></image><form id=form contentEditable=true><object data=? onload=objectOnLoad()></object></form><dialog open="true">a</dialog>
+<script>
+    document.getSelection().empty();
+    document.execCommand("selectAll", false);
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    function objectOnLoad() {
+        document.execCommand("insertUnorderedList", false);
+        document.execCommand("italic", false);
+        requestAnimationFrame(function () {
+            document.body.innerHTML = "<p> Tests inserting list followed by an edit command. The test passes if WebKit doesn't crash or hit an assertion.</p>";
+            if (window.testRunner)
+                testRunner.notifyDone();
+        });
+    }
+</script>
index d6bc7b1..e5bdd2a 100644 (file)
@@ -4,6 +4,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of BODY > HTML > #document to 0 of BODY > HTML > #document toDOMRange:range from 0 of #text > BODY > HTML > #document to 5 of #text > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 layer at (0,0) size 800x600
   RenderView at (0,0) size 800x600
 layer at (0,0) size 800x600
index 7dbde77..c0e3fab 100644 (file)
@@ -1,3 +1,307 @@
+2020-04-28  Jack Lee  <shihchieh_lee@apple.com>
+
+        Nullptr crash in EditCommand::EditCommand via CompositeEditCommand::removeNode
+        https://bugs.webkit.org/show_bug.cgi?id=207600
+        <rdar://problem/56969450>
+
+        Reviewed by Geoffrey Garen.
+
+        Move FrameSelection and Editor objects from Frame to Document so when a document is detached
+        in nested command executions, the next EditCommand would not fail in constructor.
+
+        Test: editing/inserting/insert-list-then-edit-command-crash.html
+
+        * dom/Document.cpp:
+        (WebCore::m_selection):
+        (WebCore::Document::prepareForDestruction):
+        (WebCore::m_undoManager): Deleted.
+        * dom/Document.h:
+        (WebCore::Document::editor):
+        (WebCore::Document::editor const):
+        (WebCore::Document::selection):
+        (WebCore::Document::selection const):
+        * dom/PositionIterator.cpp:
+        (WebCore::PositionIterator::isCandidate const):
+        * editing/AlternativeTextController.cpp:
+        (WebCore::AlternativeTextController::AlternativeTextController):
+        (WebCore::AlternativeTextController::stopPendingCorrection):
+        (WebCore::AlternativeTextController::isSpellingMarkerAllowed const):
+        (WebCore::AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate):
+        (WebCore::AlternativeTextController::respondToUnappliedSpellCorrection):
+        (WebCore::AlternativeTextController::timerFired):
+        (WebCore::AlternativeTextController::handleAlternativeTextUIResult):
+        (WebCore::AlternativeTextController::rootViewRectForRange const):
+        (WebCore::AlternativeTextController::respondToChangedSelection):
+        (WebCore::AlternativeTextController::respondToAppliedEditing):
+        (WebCore::AlternativeTextController::respondToUnappliedEditing):
+        (WebCore::AlternativeTextController::editorClient):
+        (WebCore::AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand):
+        (WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult):
+        (WebCore::AlternativeTextController::respondToMarkerAtEndOfWord):
+        (WebCore::AlternativeTextController::alternativeTextClient):
+        (WebCore::AlternativeTextController::applyAlternativeTextToRange):
+        (WebCore::AlternativeTextController::insertDictatedText):
+        (WebCore::AlternativeTextController::applyDictationAlternative):
+        * editing/AlternativeTextController.h:
+        (WebCore::AlternativeTextController::UNLESS_ENABLED):
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::EditCommandComposition::unapply):
+        (WebCore::EditCommandComposition::reapply):
+        (WebCore::CompositeEditCommand::willApplyCommand):
+        (WebCore::CompositeEditCommand::didApplyCommand):
+        (WebCore::CompositeEditCommand::targetRanges const):
+        (WebCore::CompositeEditCommand::moveParagraphs):
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::DeleteSelectionCommand::saveTypingStyleState):
+        (WebCore::DeleteSelectionCommand::mergeParagraphs):
+        (WebCore::DeleteSelectionCommand::calculateTypingStyleAfterDelete):
+        (WebCore::DeleteSelectionCommand::doApply):
+        * editing/EditCommand.cpp:
+        (WebCore::EditCommand::EditCommand):
+        (WebCore::EditCommand::isEditingTextAreaOrTextInput const):
+        (WebCore::EditCommand::postTextStateChangeNotification):
+        (WebCore::EditCommand::frame): Deleted.
+        (WebCore::EditCommand::frame const): Deleted.
+        * editing/EditCommand.h:
+        * editing/Editing.cpp:
+        (WebCore::createDefaultParagraphElement):
+        * editing/EditingStyle.cpp:
+        (WebCore::StyleChange::StyleChange):
+        * editing/Editor.cpp:
+        (WebCore::ClearTextCommand::CreateAndApply):
+        (WebCore::TemporarySelectionChange::TemporarySelectionChange):
+        (WebCore::TemporarySelectionChange::~TemporarySelectionChange):
+        (WebCore::TemporarySelectionChange::setSelection):
+        (WebCore::Editor::selectionForCommand):
+        (WebCore::Editor::behavior const):
+        (WebCore::Editor::client const):
+        (WebCore::Editor::canEdit const):
+        (WebCore::Editor::canEditRichly const):
+        (WebCore::Editor::canDHTMLCut):
+        (WebCore::Editor::canDHTMLCopy):
+        (WebCore::Editor::canCopy const):
+        (WebCore::Editor::canPaste const):
+        (WebCore::Editor::canDelete const):
+        (WebCore::Editor::shouldSmartDelete):
+        (WebCore::Editor::deleteWithDirection):
+        (WebCore::Editor::deleteSelectionWithSmartDelete):
+        (WebCore::Editor::clearText):
+        (WebCore::Editor::replaceSelectionWithFragment):
+        (WebCore::Editor::selectedRange):
+        (WebCore::Editor::tryDHTMLCopy):
+        (WebCore::Editor::tryDHTMLCut):
+        (WebCore::Editor::shouldInsertText const):
+        (WebCore::Editor::hasBidiSelection const):
+        (WebCore::Editor::selectionUnorderedListState const):
+        (WebCore::Editor::selectionOrderedListState const):
+        (WebCore::Editor::increaseSelectionListLevel):
+        (WebCore::Editor::increaseSelectionListLevelOrdered):
+        (WebCore::Editor::increaseSelectionListLevelUnordered):
+        (WebCore::Editor::decreaseSelectionListLevel):
+        (WebCore::Editor::findEventTargetFromSelection const):
+        (WebCore::Editor::applyStyle):
+        (WebCore::Editor::applyParagraphStyle):
+        (WebCore::Editor::applyStyleToSelection):
+        (WebCore::Editor::applyParagraphStyleToSelection):
+        (WebCore::Editor::selectionStartHasStyle const):
+        (WebCore::Editor::selectionHasStyle const):
+        (WebCore::Editor::selectionStartCSSPropertyValue):
+        (WebCore::Editor::appliedEditing):
+        (WebCore::Editor::Editor):
+        (WebCore::Editor::clear):
+        (WebCore::Editor::insertText):
+        (WebCore::Editor::insertTextForConfirmedComposition):
+        (WebCore::Editor::insertTextWithoutSendingTextEvent):
+        (WebCore::Editor::insertLineBreak):
+        (WebCore::Editor::insertParagraphSeparator):
+        (WebCore::Editor::performCutOrCopy):
+        (WebCore::Editor::paste):
+        (WebCore::Editor::pasteAsQuotation):
+        (WebCore::Editor::renderLayerDidScroll):
+        (WebCore::Editor::setBaseWritingDirection):
+        (WebCore::Editor::baseWritingDirectionForSelectionStart const):
+        (WebCore::Editor::selectComposition):
+        (WebCore::SetCompositionScope::SetCompositionScope):
+        (WebCore::SetCompositionScope::~SetCompositionScope):
+        (WebCore::Editor::setComposition):
+        (WebCore::Editor::ignoreSpelling):
+        (WebCore::Editor::learnSpelling):
+        (WebCore::Editor::advanceToNextMisspelling):
+        (WebCore::Editor::misspelledWordAtCaretOrRange const):
+        (WebCore::Editor::isSelectionUngrammatical):
+        (WebCore::Editor::guessesForMisspelledWord const):
+        (WebCore::Editor::guessesForMisspelledOrUngrammatical):
+        (WebCore::Editor::markMisspellingsAfterTypingToWord):
+        (WebCore::Editor::isSpellCheckingEnabledInFocusedNode const):
+        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
+        (WebCore::Editor::markAndReplaceFor):
+        (WebCore::Editor::updateMarkersForWordsAffectedByEditing):
+        (WebCore::Editor::rangeForPoint):
+        (WebCore::Editor::revealSelectionAfterEditingOperation):
+        (WebCore::Editor::setIgnoreSelectionChanges):
+        (WebCore::Editor::getCompositionSelection const):
+        (WebCore::Editor::transpose):
+        (WebCore::Editor::changeSelectionAfterCommand):
+        (WebCore::Editor::selectedText const):
+        (WebCore::Editor::selectedTextForDataTransfer const):
+        (WebCore::Editor::insertTextPlaceholder):
+        (WebCore::Editor::removeTextPlaceholder):
+        (WebCore::Editor::shouldChangeSelection const):
+        (WebCore::Editor::computeAndSetTypingStyle):
+        (WebCore::Editor::findString):
+        (WebCore::Editor::countMatchesForText):
+        (WebCore::Editor::respondToChangedSelection):
+        (WebCore::Editor::shouldDetectTelephoneNumbers):
+        (WebCore::Editor::scanSelectionForTelephoneNumbers):
+        (WebCore::Editor::editorUIUpdateTimerFired):
+        (WebCore::Editor::selectionStartHasMarkerFor const):
+        (WebCore::candidateRangeForSelection):
+        (WebCore::Editor::stringForCandidateRequest const):
+        (WebCore::Editor::contextRangeForCandidateRequest const):
+        (WebCore::Editor::fontAttributesAtSelectionStart const):
+        (WebCore::Editor::notifyClientOfAttachmentUpdates):
+        (WebCore::Editor::handleAcceptedCandidate):
+        (WebCore::Editor::unifiedTextCheckerEnabled const):
+        (WebCore::Editor::toggleOverwriteModeEnabled):
+        (WebCore::Editor::fontForSelection const):
+        (WebCore::Editor::canCopyExcludingStandaloneImages const):
+        (WebCore::Editor::document const): Deleted.
+        * editing/Editor.h:
+        (WebCore::TemporarySelectionChange::TemporarySelectionChange):
+        (WebCore::IgnoreSelectionChangeForScope::IgnoreSelectionChangeForScope):
+        (WebCore::Editor::document const):
+        * editing/EditorCommand.cpp:
+        (WebCore::executeSwapWithMark):
+        (WebCore::Editor::command):
+        (WebCore::Editor::Command::Command):
+        (WebCore::Editor::Command::execute const):
+        * editing/FrameSelection.cpp:
+        (WebCore::shouldAlwaysUseDirectionalSelection):
+        (WebCore::FrameSelection::FrameSelection):
+        (WebCore::FrameSelection::rootEditableElementOrDocumentElement const):
+        (WebCore::FrameSelection::setSelectionByMouseIfDifferent):
+        (WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance):
+        (WebCore::FrameSelection::setSelection):
+        (WebCore::updateSelectionByUpdatingLayoutOrStyle):
+        (WebCore::FrameSelection::setNeedsSelectionUpdate):
+        (WebCore::FrameSelection::updateAndRevealSelection):
+        (WebCore::FrameSelection::updateDataDetectorsForSelection):
+        (WebCore::FrameSelection::positionForPlatform const):
+        (WebCore::FrameSelection::nextWordPositionForPlatform):
+        (WebCore::FrameSelection::modifyMovingRight):
+        (WebCore::FrameSelection::modifyMovingLeft):
+        (WebCore::FrameSelection::modify):
+        (WebCore::FrameSelection::prepareForDestruction):
+        (WebCore::FrameSelection::absoluteCaretBounds):
+        (WebCore::FrameSelection::recomputeCaretRect):
+        (WebCore::FrameSelection::contains const):
+        (WebCore::FrameSelection::selectAll):
+        (WebCore::FrameSelection::focusedOrActiveStateChanged):
+        (WebCore::FrameSelection::isFocusedAndActive const):
+        (WebCore::shouldStopBlinkingDueToTypingCommand):
+        (WebCore::FrameSelection::updateAppearance):
+        (WebCore::FrameSelection::setCaretVisibility):
+        (WebCore::FrameSelection::setFocusedElementIfNeeded):
+        (WebCore::FrameSelection::shouldDeleteSelection const):
+        (WebCore::FrameSelection::selectionBounds const):
+        (WebCore::FrameSelection::getClippedVisibleTextRectangles const):
+        (WebCore::FrameSelection::currentForm const):
+        (WebCore::FrameSelection::revealSelection):
+        (WebCore::FrameSelection::setSelectionFromNone):
+        (WebCore::FrameSelection::shouldChangeSelection const):
+        (WebCore::FrameSelection::setShouldShowBlockCursor):
+        (WebCore::FrameSelection::appearanceUpdateTimerFired):
+        (WebCore::FrameSelection::updateAppearanceAfterLayoutOrStyleChange):
+        (WebCore::FrameSelection::selectRangeOnElement):
+        (WebCore::FrameSelection::setCaretBlinks):
+        * editing/FrameSelection.h:
+        * editing/InsertIntoTextNodeCommand.cpp:
+        (WebCore::InsertIntoTextNodeCommand::doApply):
+        * editing/InsertLineBreakCommand.cpp:
+        (WebCore::InsertLineBreakCommand::doApply):
+        * editing/InsertTextCommand.cpp:
+        (WebCore::InsertTextCommand::doApply):
+        * editing/ReplaceRangeWithTextCommand.cpp:
+        (WebCore::ReplaceRangeWithTextCommand::doApply):
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::doApply):
+        * editing/SetSelectionCommand.cpp:
+        (WebCore::SetSelectionCommand::doApply):
+        (WebCore::SetSelectionCommand::doUnapply):
+        * editing/SpellChecker.cpp:
+        (WebCore::SpellChecker::SpellChecker):
+        (WebCore::SpellChecker::client const):
+        (WebCore::SpellChecker::isAsynchronousEnabled const):
+        (WebCore::SpellChecker::invokeRequest):
+        (WebCore::SpellChecker::didCheck):
+        (WebCore::SpellChecker::didCheckSucceed):
+        * editing/SpellChecker.h:
+        * editing/SpellingCorrectionCommand.cpp:
+        (WebCore::SpellingCorrectionCommand::doApply):
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::deleteSelection):
+        (WebCore::TypingCommand::deleteKeyPressed):
+        (WebCore::TypingCommand::forwardDeleteKeyPressed):
+        (WebCore::TypingCommand::updateSelectionIfDifferentFromCurrentSelection):
+        (WebCore::TypingCommand::insertText):
+        (WebCore::TypingCommand::insertLineBreak):
+        (WebCore::TypingCommand::insertParagraphSeparatorInQuotedContent):
+        (WebCore::TypingCommand::insertParagraphSeparator):
+        (WebCore::TypingCommand::lastTypingCommandIfStillOpenForTyping):
+        (WebCore::TypingCommand::closeTyping):
+        (WebCore::TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping):
+        (WebCore::TypingCommand::markMisspellingsAfterTyping):
+        (WebCore::TypingCommand::willAddTypingToOpenCommand):
+        (WebCore::TypingCommand::typingAddedToOpenCommand):
+        (WebCore::TypingCommand::insertTextAndNotifyAccessibility):
+        (WebCore::TypingCommand::insertTextRunWithoutNewlines):
+        (WebCore::TypingCommand::insertLineBreakAndNotifyAccessibility):
+        (WebCore::TypingCommand::insertParagraphSeparatorAndNotifyAccessibility):
+        (WebCore::TypingCommand::insertParagraphSeparatorInQuotedContentAndNotifyAccessibility):
+        * editing/TypingCommand.h:
+        * editing/cocoa/EditorCocoa.mm:
+        (WebCore::Editor::selectionInHTMLFormat):
+        (WebCore::Editor::writeSelectionToPasteboard):
+        (WebCore::Editor::writeSelection):
+        (WebCore::Editor::selectionInWebArchiveFormat):
+        (WebCore::Editor::replaceSelectionWithAttributedString):
+        (WebCore::Editor::webContentFromPasteboard):
+        (WebCore::Editor::takeFindStringFromSelection):
+        * editing/gtk/EditorGtk.cpp:
+        (WebCore::Editor::pasteWithPasteboard):
+        (WebCore::Editor::writeSelectionToPasteboard):
+        (WebCore::Editor::webContentFromPasteboard):
+        * editing/ios/EditorIOS.mm:
+        (WebCore::Editor::setTextAlignmentForChangedBaseWritingDirection):
+        (WebCore::Editor::removeUnchangeableStyles):
+        (WebCore::Editor::pasteWithPasteboard):
+        (WebCore::Editor::insertDictationPhrases):
+        (WebCore::Editor::setDictationPhrasesAsChildOfElement):
+        (WebCore::Editor::setTextAsChildOfElement):
+        (WebCore::Editor::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping):
+        * editing/libwpe/EditorLibWPE.cpp:
+        (WebCore::Editor::writeSelectionToPasteboard):
+        (WebCore::Editor::pasteWithPasteboard):
+        * editing/mac/EditorMac.mm:
+        (WebCore::Editor::readSelectionFromPasteboard):
+        (WebCore::Editor::replaceNodeFromPasteboard):
+        (WebCore::Editor::selectionWillChange):
+        * editing/win/EditorWin.cpp:
+        (WebCore::Editor::pasteWithPasteboard):
+        (WebCore::Editor::webContentFromPasteboard):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::willTransitionToCommitted):
+        (WebCore::FrameLoader::closeURL):
+        (WebCore::FrameLoader::didOpenURL):
+        (WebCore::FrameLoader::clear):
+        * page/Frame.cpp:
+        (WebCore::Frame::Frame):
+        (WebCore::Frame::requestDOMPasteAccess):
+        (WebCore::Frame::setPageAndTextZoomFactors):
+        * page/Frame.h:
+        * page/TextIndicator.cpp:
+        (WebCore::TextIndicator::createWithRange):
+
 2020-04-28  Antti Koivisto  <antti@apple.com>
 
         msn.com: Header flickers when scrolling articles
index 0e18cc8..6907862 100644 (file)
@@ -582,6 +582,8 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig
     , m_orientationNotifier(currentOrientation(frame))
     , m_identifier(DocumentIdentifier::generate())
     , m_undoManager(UndoManager::create(*this))
+    , m_editor(makeUniqueRef<Editor>(*this))
+    , m_selection(makeUniqueRef<FrameSelection>(this))
 {
     auto addResult = allDocumentsMap().add(m_identifier, this);
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
@@ -2499,7 +2501,7 @@ void Document::destroyRenderTree()
         view()->didDestroyRenderTree();
 }
 
-void Document::prepareForDestruction()
+void Document::willBeRemovedFromFrame()
 {
     if (m_hasPreparedForDestruction)
         return;
@@ -2592,6 +2594,8 @@ void Document::prepareForDestruction()
         page()->updateIsPlayingMedia(HTMLMediaElementInvalidID);
     }
 
+    editor().clear();
+    selection().willBeRemovedFromFrame();
     detachFromFrame();
 
 #if ENABLE(CSS_PAINTING_API)
index 2182c43..1869e28 100644 (file)
@@ -120,6 +120,7 @@ class DocumentSharedObjectPool;
 class DocumentTimeline;
 class DocumentType;
 class EditingBehavior;
+class Editor;
 class EventLoop;
 class EventLoopTaskGroup;
 class ExtensionStyleSheets;
@@ -128,6 +129,7 @@ class FloatRect;
 class FontFaceSet;
 class FormController;
 class Frame;
+class FrameSelection;
 class FrameView;
 class FullscreenManager;
 class GPUCanvasContext;
@@ -626,7 +628,7 @@ public:
 
     void didBecomeCurrentDocumentInFrame();
     void destroyRenderTree();
-    void prepareForDestruction();
+    void willBeRemovedFromFrame();
 
     // Override ScriptExecutionContext methods to do additional work
     WEBCORE_EXPORT bool shouldBypassMainWorldContentSecurityPolicy() const final;
@@ -1578,6 +1580,11 @@ public:
     void setHasVisuallyNonEmptyCustomContent() { m_hasVisuallyNonEmptyCustomContent = true; }
     bool hasVisuallyNonEmptyCustomContent() const { return m_hasVisuallyNonEmptyCustomContent; }
 
+    Editor& editor() { return m_editor; }
+    const Editor& editor() const { return m_editor; }
+    FrameSelection& selection() { return m_selection; }
+    const FrameSelection& selection() const { return m_selection; }
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -2113,6 +2120,9 @@ private:
     std::unique_ptr<TextManipulationController> m_textManipulationController;
 
     HashMap<Element*, ElementIdentifier> m_identifiedElementsMap;
+
+    UniqueRef<Editor> m_editor;
+    UniqueRef<FrameSelection> m_selection;
 };
 
 Element* eventTargetElementForDocument(Document*);
index 3bd658d..aef4bc5 100644 (file)
@@ -82,9 +82,9 @@ static bool markersHaveIdenticalDescription(const Vector<RenderedDocumentMarker*
     return true;
 }
 
-AlternativeTextController::AlternativeTextController(Frame& frame)
+AlternativeTextController::AlternativeTextController(Document& document)
     : m_timer(*this, &AlternativeTextController::timerFired)
-    , m_frame(frame)
+    , m_document(document)
 {
 }
 
@@ -115,7 +115,7 @@ void AlternativeTextController::stopAlternativeTextUITimer()
 void AlternativeTextController::stopPendingCorrection(const VisibleSelection& oldSelection)
 {
     // Make sure there's no pending autocorrection before we call markMisspellingsAndBadGrammar() below.
-    VisibleSelection currentSelection(m_frame.selection().selection());
+    VisibleSelection currentSelection(m_document.selection().selection());
     if (currentSelection == oldSelection)
         return;
 
@@ -149,7 +149,7 @@ bool AlternativeTextController::hasPendingCorrection() const
 
 bool AlternativeTextController::isSpellingMarkerAllowed(Range& misspellingRange) const
 {
-    return !m_frame.document()->markers().hasMarkers(misspellingRange, DocumentMarker::SpellCheckingExemption);
+    return !m_document.markers().hasMarkers(misspellingRange, DocumentMarker::SpellCheckingExemption);
 }
 
 void AlternativeTextController::show(Range& rangeToReplace, const String& replacement)
@@ -202,7 +202,7 @@ bool AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate()
     if (m_type != AlternativeTextTypeCorrection)
         return false;
 
-    Position caretPosition = m_frame.selection().selection().start();
+    Position caretPosition = m_document.selection().selection().start();
 
     if (m_rangeWithAlternative->endPosition() == caretPosition) {
         handleAlternativeTextUIResult(dismissSoon(ReasonForDismissingAlternativeTextAccepted));
@@ -220,14 +220,14 @@ void AlternativeTextController::respondToUnappliedSpellCorrection(const VisibleS
     if (auto client = alternativeTextClient())
         client->recordAutocorrectionResponse(AutocorrectionResponse::Reverted, corrected, correction);
 
-    Ref<Frame> protector(m_frame);
-    m_frame.document()->updateLayout();
+    RefPtr<Frame> protector(m_document.frame());
+    m_document.updateLayout();
 
-    m_frame.selection().setSelection(selectionOfCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered);
-    auto range = m_frame.selection().selection().firstRange();
+    m_document.selection().setSelection(selectionOfCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered);
+    auto range = m_document.selection().selection().firstRange();
     if (!range)
         return;
-    auto& markers = m_frame.document()->markers();
+    auto& markers = m_document.markers();
     markers.removeMarkers(*range, OptionSet<DocumentMarker::MarkerType> { DocumentMarker::Spelling, DocumentMarker::Autocorrected }, DocumentMarkerController::RemovePartiallyOverlappingMarker);
     markers.addMarker(*range, DocumentMarker::Replacement);
     markers.addMarker(*range, DocumentMarker::SpellCheckingExemption);
@@ -238,12 +238,12 @@ void AlternativeTextController::timerFired()
     m_isDismissedByEditing = false;
     switch (m_type) {
     case AlternativeTextTypeCorrection: {
-        VisibleSelection selection(m_frame.selection().selection());
+        VisibleSelection selection(m_document.selection().selection());
         VisiblePosition start(selection.start(), selection.affinity());
         VisiblePosition p = startOfWord(start, LeftWordIfOnBoundary);
         VisibleSelection adjacentWords = VisibleSelection(p, start);
         auto adjacentWordRange = adjacentWords.toNormalizedRange();
-        m_frame.editor().markAllMisspellingsAndBadGrammarInRanges({ TextCheckingType::Spelling, TextCheckingType::Replacement, TextCheckingType::ShowCorrectionPanel }, createLiveRange(adjacentWordRange), createLiveRange(adjacentWordRange), nullptr);
+        m_document.editor().markAllMisspellingsAndBadGrammarInRanges({ TextCheckingType::Spelling, TextCheckingType::Replacement, TextCheckingType::ShowCorrectionPanel }, createLiveRange(adjacentWordRange), createLiveRange(adjacentWordRange), nullptr);
     }
         break;
     case AlternativeTextTypeReversion: {
@@ -266,7 +266,7 @@ void AlternativeTextController::timerFired()
             break;
         String paragraphText = plainText(TextCheckingParagraph(*m_rangeWithAlternative).paragraphRange());
         Vector<String> suggestions;
-        textChecker()->getGuessesForWord(m_originalText, paragraphText, m_frame.selection().selection(), suggestions);
+        textChecker()->getGuessesForWord(m_originalText, paragraphText, m_document.selection().selection(), suggestions);
         if (suggestions.isEmpty()) {
             m_rangeWithAlternative = nullptr;
             break;
@@ -304,7 +304,7 @@ void AlternativeTextController::timerFired()
 void AlternativeTextController::handleAlternativeTextUIResult(const String& result)
 {
     Range* rangeWithAlternative = m_rangeWithAlternative.get();
-    if (!rangeWithAlternative || m_frame.document() != &rangeWithAlternative->ownerDocument())
+    if (!rangeWithAlternative || m_document != rangeWithAlternative->ownerDocument())
         return;
 
     String currentWord = plainText(*rangeWithAlternative);
@@ -342,7 +342,7 @@ bool AlternativeTextController::isAutomaticSpellingCorrectionEnabled()
 
 FloatRect AlternativeTextController::rootViewRectForRange(const SimpleRange& range) const
 {
-    auto* view = m_frame.view();
+    auto* view = m_document.frame()->view();
     if (!view)
         return { };
     return view->contentsToRootView(unitedBoundingBoxes(RenderObject::absoluteTextQuads(range)));
@@ -350,7 +350,7 @@ FloatRect AlternativeTextController::rootViewRectForRange(const SimpleRange& ran
 
 void AlternativeTextController::respondToChangedSelection(const VisibleSelection& oldSelection)
 {
-    VisibleSelection currentSelection(m_frame.selection().selection());
+    VisibleSelection currentSelection(m_document.selection().selection());
     // When user moves caret to the end of autocorrected word and pauses, we show the panel
     // containing the original pre-correction word so that user can quickly revert the
     // undesired autocorrection. Here, we start correction panel timer once we confirm that
@@ -385,7 +385,7 @@ void AlternativeTextController::respondToChangedSelection(const VisibleSelection
 void AlternativeTextController::respondToAppliedEditing(CompositeEditCommand* command)
 {
     if (command->isTopLevelCommand() && !command->shouldRetainAutocorrectionIndicator())
-        m_frame.document()->markers().removeMarkers(DocumentMarker::CorrectionIndicator);
+        m_document.markers().removeMarkers(DocumentMarker::CorrectionIndicator);
 
     markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand(command);
     m_originalStringForLastDeletedAutocorrection = String();
@@ -400,14 +400,14 @@ void AlternativeTextController::respondToUnappliedEditing(EditCommandComposition
     auto range = command->startingSelection().firstRange();
     if (!range)
         return;
-    auto& markers = m_frame.document()->markers();
+    auto& markers = m_document.markers();
     markers.addMarker(*range, DocumentMarker::Replacement);
     markers.addMarker(*range, DocumentMarker::SpellCheckingExemption);
 }
 
 EditorClient* AlternativeTextController::editorClient()
 {
-    return m_frame.page() ? &m_frame.page()->editorClient() : nullptr;
+    return m_document.page() ? &m_document.page()->editorClient() : nullptr;
 }
 
 TextCheckerClient* AlternativeTextController::textChecker()
@@ -483,12 +483,12 @@ void AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionA
     // Mark this whitespace to indicate we have deleted an autocorrection following this
     // whitespace. So if the user types the same original word again at this position, we
     // won't autocorrect it again.
-    m_frame.document()->markers().addMarker(precedingCharacterRange, DocumentMarker::DeletedAutocorrection, m_originalStringForLastDeletedAutocorrection);
+    m_document.markers().addMarker(precedingCharacterRange, DocumentMarker::DeletedAutocorrection, m_originalStringForLastDeletedAutocorrection);
 }
 
 bool AlternativeTextController::processMarkersOnTextToBeReplacedByResult(const TextCheckingResult& result, Range& rangeWithAlternative, const String& stringToBeReplaced)
 {
-    auto& markers = m_frame.document()->markers();
+    auto& markers = m_document.markers();
     if (markers.hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) {
         if (result.type == TextCheckingType::Correction)
             recordSpellcheckerResponseForModifiedCorrection(rangeWithAlternative, stringToBeReplaced, result.replacement);
@@ -524,7 +524,7 @@ bool AlternativeTextController::respondToMarkerAtEndOfWord(const DocumentMarker&
     if (!shouldStartTimerFor(marker, endOfWordPosition.offsetInContainerNode()))
         return false;
     Node* node = endOfWordPosition.containerNode();
-    auto wordRange = Range::create(*m_frame.document(), node, marker.startOffset(), node, marker.endOffset());
+    auto wordRange = Range::create(m_document, node, marker.startOffset(), node, marker.endOffset());
     String currentWord = plainText(wordRange);
     if (!currentWord.length())
         return false;
@@ -562,7 +562,7 @@ bool AlternativeTextController::respondToMarkerAtEndOfWord(const DocumentMarker&
 
 AlternativeTextClient* AlternativeTextController::alternativeTextClient()
 {
-    return m_frame.page() ? m_frame.page()->alternativeTextClient() : nullptr;
+    return m_document.frame() && m_document.page() ? m_document.page()->alternativeTextClient() : nullptr;
 }
 
 String AlternativeTextController::markerDescriptionForAppliedAlternativeText(AlternativeTextType alternativeTextType, DocumentMarker::MarkerType markerType)
@@ -599,7 +599,7 @@ void AlternativeTextController::applyAlternativeTextToRange(const Range& range,
 
     // Recalculate pragraphRangeContainingCorrection, since SpellingCorrectionCommand modified the DOM, such that the original paragraphRangeContainingCorrection is no longer valid. Radar: 10305315 Bugzilla: 89526
     auto updatedParagraphStartContainingCorrection = resolveCharacterLocation(makeRangeSelectingNodeContents(treeScopeRoot), paragraphOffsetInTreeScope);
-    auto updatedParagraphEndContainingCorrection = makeBoundaryPoint(m_frame.selection().selection().start());
+    auto updatedParagraphEndContainingCorrection = makeBoundaryPoint(m_document.selection().selection().start());
     if (!updatedParagraphEndContainingCorrection)
         return;
     auto replacementRange = resolveCharacterRange({ updatedParagraphStartContainingCorrection, *updatedParagraphEndContainingCorrection }, CharacterRange(correctionOffsetInParagraph, alternative.length()));
@@ -621,11 +621,11 @@ bool AlternativeTextController::insertDictatedText(const String& text, const Vec
     if (triggeringEvent)
         target = triggeringEvent->target();
     else
-        target = eventTargetElementForDocument(m_frame.document());
+        target = eventTargetElementForDocument(&m_document);
     if (!target)
         return false;
 
-    auto event = TextEvent::createForDictation(&m_frame.windowProxy(), text, dictationAlternatives);
+    auto event = TextEvent::createForDictation(&m_document.frame()->windowProxy(), text, dictationAlternatives);
     event->setUnderlyingEvent(triggeringEvent);
 
     target->dispatchEvent(event);
@@ -657,7 +657,7 @@ Vector<String> AlternativeTextController::dictationAlternativesForMarker(const D
 void AlternativeTextController::applyDictationAlternative(const String& alternativeString)
 {
 #if USE(DICTATION_ALTERNATIVES)
-    auto& editor = m_frame.editor();
+    auto& editor = m_document.editor();
     auto selection = editor.selectedRange();
     if (!selection || !editor.shouldInsertText(alternativeString, selection.get(), EditorInsertAction::Pasted))
         return;
index 94774a7..e3df9b5 100644 (file)
 namespace WebCore {
 
 class CompositeEditCommand;
+class Document;
 class EditCommand;
 class EditCommandComposition;
 class EditorClient;
 class Event;
-class Frame;
 class Range;
 class TextCheckerClient;
 class VisibleSelection;
@@ -61,7 +61,7 @@ class AlternativeTextController {
     WTF_MAKE_NONCOPYABLE(AlternativeTextController);
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit AlternativeTextController(Frame& frame) UNLESS_ENABLED( : m_frame(frame) { })
+    explicit AlternativeTextController(Document& document) UNLESS_ENABLED(: m_document(document) { })
     ~AlternativeTextController() UNLESS_ENABLED({ })
 
     void startAlternativeTextUITimer(AlternativeTextType) UNLESS_ENABLED({ })
@@ -145,7 +145,7 @@ private:
     AlternativeTextClient* alternativeTextClient();
 #endif
 
-    Frame& m_frame;
+    Document& m_document;
 };
 
 #undef UNLESS_ENABLED
index 350fd6f..807ee7b 100644 (file)
@@ -228,17 +228,17 @@ void EditCommandComposition::unapply()
     // up the composition will leave a stale, invalid composition, as in <rdar://problem/6831637>.
     // Desktop handles this in -[WebHTMLView _updateSelectionForInputManager], but the phone
     // goes another route.
-    frame->editor().cancelComposition();
+    m_document->editor().cancelComposition();
 #endif
 
-    if (!frame->editor().willUnapplyEditing(*this))
+    if (!m_document->editor().willUnapplyEditing(*this))
         return;
 
     size_t size = m_commands.size();
     for (size_t i = size; i; --i)
         m_commands[i - 1]->doUnapply();
 
-    frame->editor().unappliedEditing(*this);
+    m_document->editor().unappliedEditing(*this);
 
     if (AXObjectCache::accessibilityEnabled())
         m_replacedText.postTextStateChangeNotificationForUnapply(m_document->existingAXObjectCache());
@@ -258,13 +258,13 @@ void EditCommandComposition::reapply()
     // if one is necessary (like for the creation of VisiblePositions).
     m_document->updateLayoutIgnorePendingStylesheets();
 
-    if (!frame->editor().willReapplyEditing(*this))
+    if (!m_document->editor().willReapplyEditing(*this))
         return;
 
     for (auto& command : m_commands)
         command->doReapply();
 
-    frame->editor().reappliedEditing(*this);
+    m_document->editor().reappliedEditing(*this);
 
     if (AXObjectCache::accessibilityEnabled())
         m_replacedText.postTextStateChangeNotificationForReapply(m_document->existingAXObjectCache());
@@ -319,7 +319,7 @@ CompositeEditCommand::~CompositeEditCommand()
 
 bool CompositeEditCommand::willApplyCommand()
 {
-    return frame().editor().willApplyEditing(*this, targetRangesForBindings());
+    return document().editor().willApplyEditing(*this, targetRangesForBindings());
 }
 
 void CompositeEditCommand::apply()
@@ -378,13 +378,13 @@ void CompositeEditCommand::apply()
 
 void CompositeEditCommand::didApplyCommand()
 {
-    frame().editor().appliedEditing(*this);
+    document().editor().appliedEditing(*this);
 }
 
 Vector<RefPtr<StaticRange>> CompositeEditCommand::targetRanges() const
 {
     ASSERT(!isEditingTextAreaOrTextInput());
-    auto firstRange = frame().selection().selection().firstRange();
+    auto firstRange = document().selection().selection().firstRange();
     if (!firstRange)
         return { };
 
@@ -1468,7 +1468,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
     // FIXME (5098931): We should add a new insert action "WebViewInsertActionMoved" and call shouldInsertFragment here.
 
     setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
-    frame().editor().clearMisspellingsAndBadGrammar(endingSelection());
+    document().editor().clearMisspellingsAndBadGrammar(endingSelection());
     deleteSelection(false, false, false, false);
 
     ASSERT(destination.deepEquivalent().anchorNode()->isConnected());
@@ -1504,7 +1504,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
         options.add(ReplaceSelectionCommand::MatchStyle);
     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), options));
 
-    frame().editor().markMisspellingsAndBadGrammar(endingSelection());
+    document().editor().markMisspellingsAndBadGrammar(endingSelection());
 
     // If the selection is in an empty paragraph, restore styles from the old empty paragraph to the new empty paragraph.
     bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfParagraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().visibleStart());
index ca56f30..e20a8d8 100644 (file)
@@ -334,7 +334,7 @@ void DeleteSelectionCommand::saveTypingStyleState()
     // However, if typing style was previously set from another text node at the previous
     // position (now deleted), we need to clear that style as well.
     if (m_upstreamStart.deprecatedNode() == m_downstreamEnd.deprecatedNode() && m_upstreamStart.deprecatedNode()->isTextNode()) {
-        frame().selection().clearTypingStyle();
+        document().selection().clearTypingStyle();
         return;
     }
 
@@ -744,7 +744,7 @@ void DeleteSelectionCommand::mergeParagraphs()
     
     auto range = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), endOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent());
     auto rangeToBeReplaced = Range::create(document(), mergeDestination.deepEquivalent().parentAnchoredEquivalent(), mergeDestination.deepEquivalent().parentAnchoredEquivalent());
-    if (!frame().editor().client()->shouldMoveRangeAfterDelete(range.ptr(), rangeToBeReplaced.ptr()))
+    if (!document().editor().client()->shouldMoveRangeAfterDelete(range.ptr(), rangeToBeReplaced.ptr()))
         return;
     
     // moveParagraphs will insert placeholders if it removes blocks that would require their use, don't let block
@@ -818,7 +818,7 @@ void DeleteSelectionCommand::calculateTypingStyleAfterDelete()
     // In this case if we start typing, the new characters should have the same style as the just deleted ones,
     // but, if we change the selection, come back and start typing that style should be lost.  Also see 
     // preserveTypingStyle() below.
-    frame().selection().setTypingStyle(m_typingStyle.copyRef());
+    document().selection().setTypingStyle(m_typingStyle.copyRef());
 }
 
 void DeleteSelectionCommand::clearTransientState()
@@ -889,7 +889,7 @@ void DeleteSelectionCommand::doApply()
     if (!m_replace) {
         Element* textControl = enclosingTextFormControl(m_selectionToDelete.start());
         if (textControl && textControl->focused())
-            frame().editor().textWillBeDeletedInTextField(textControl);
+            document().editor().textWillBeDeletedInTextField(textControl);
     }
 
     // save this to later make the selection with
@@ -944,7 +944,7 @@ void DeleteSelectionCommand::doApply()
     }
 
     bool shouldRebalaceWhiteSpace = true;
-    if (!frame().editor().behavior().shouldRebalanceWhiteSpacesInSecureField()) {
+    if (!document().editor().behavior().shouldRebalanceWhiteSpacesInSecureField()) {
         Node* node = m_endingPosition.deprecatedNode();
         if (is<Text>(node)) {
             Text& textNode = downcast<Text>(*node);
@@ -958,7 +958,7 @@ void DeleteSelectionCommand::doApply()
     calculateTypingStyleAfterDelete();
 
     if (!originalString.isEmpty())
-        frame().editor().deletedAutocorrectionAtPosition(m_endingPosition, originalString);
+        document().editor().deletedAutocorrectionAtPosition(m_endingPosition, originalString);
 
     setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSelection().isDirectional()));
     clearTransientState();
index df098c3..1f5b6ac 100644 (file)
@@ -32,7 +32,6 @@
 #include "Editing.h"
 #include "Editor.h"
 #include "Element.h"
-#include "Frame.h"
 #include "HTMLInputElement.h"
 #include "HTMLTextAreaElement.h"
 #include "NodeTraversal.h"
@@ -127,33 +126,19 @@ EditCommand::EditCommand(Document& document, EditAction editingAction)
     : m_document(document)
     , m_editingAction(editingAction)
 {
-    ASSERT(document.frame());
-    setStartingSelection(m_document->frame()->selection().selection());
+    setStartingSelection(m_document->selection().selection());
     setEndingSelection(m_startingSelection);
 }
 
 EditCommand::EditCommand(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection)
     : m_document(document)
 {
-    ASSERT(document.frame());
     setStartingSelection(startingSelection);
     setEndingSelection(endingSelection);
 }
 
 EditCommand::~EditCommand() = default;
 
-Frame& EditCommand::frame()
-{
-    ASSERT(document().frame());
-    return *document().frame();
-}
-
-const Frame& EditCommand::frame() const
-{
-    ASSERT(document().frame());
-    return *document().frame();
-}
-
 EditAction EditCommand::editingAction() const
 {
     return m_editingAction;
@@ -168,11 +153,7 @@ static inline EditCommandComposition* compositionIfPossible(EditCommand* command
 
 bool EditCommand::isEditingTextAreaOrTextInput() const
 {
-    auto* frame = m_document->frame();
-    if (!frame)
-        return false;
-
-    auto* container = frame->selection().selection().start().containerNode();
+    auto* container = m_document->selection().selection().start().containerNode();
     if (!container)
         return false;
 
@@ -217,7 +198,7 @@ void EditCommand::postTextStateChangeNotification(AXTextEditType type, const Str
 {
     if (!AXObjectCache::accessibilityEnabled())
         return;
-    postTextStateChangeNotification(type, text, frame().selection().selection().start());
+    postTextStateChangeNotification(type, text, m_document->selection().selection().start());
 }
 
 void EditCommand::postTextStateChangeNotification(AXTextEditType type, const String& text, const VisiblePosition& position)
index debcff0..2f67cd7 100644 (file)
@@ -38,7 +38,6 @@ namespace WebCore {
 class CompositeEditCommand;
 class Document;
 class Element;
-class Frame;
 
 String inputTypeNameForEditingAction(EditAction);
 
@@ -64,8 +63,6 @@ protected:
     explicit EditCommand(Document&, EditAction = EditAction::Unspecified);
     EditCommand(Document&, const VisibleSelection&, const VisibleSelection&);
 
-    const Frame& frame() const;
-    Frame& frame();
     const Document& document() const { return m_document; }
     Document& document() { return m_document; }
     CompositeEditCommand* parent() const { return m_parent; }
index c113c01..4bb4466 100644 (file)
@@ -898,7 +898,7 @@ bool isEmptyTableCell(const Node* node)
 
 Ref<HTMLElement> createDefaultParagraphElement(Document& document)
 {
-    switch (document.frame()->editor().defaultParagraphSeparator()) {
+    switch (document.editor().defaultParagraphSeparator()) {
     case EditorParagraphSeparatorIsDiv:
         return HTMLDivElement::create(document);
     case EditorParagraphSeparatorIsP:
index d5424ac..2f6354a 100644 (file)
@@ -1686,7 +1686,7 @@ StyleChange::StyleChange(EditingStyle* style, const Position& position)
         getPropertiesNotIn(*style->style(), computedStyle) : MutableStyleProperties::create();
 
     reconcileTextDecorationProperties(mutableStyle.get());
-    bool shouldStyleWithCSS = document->frame()->editor().shouldStyleWithCSS();
+    bool shouldStyleWithCSS = document->editor().shouldStyleWithCSS();
     if (!shouldStyleWithCSS)
         extractTextStyles(*document, *mutableStyle, computedStyle.useFixedFontDefaultSize());
 
index 2b10606..63cce39 100644 (file)
@@ -173,8 +173,8 @@ static String inputEventDataForEditingStyleAndAction(EditingStyle& style, EditAc
 class ClearTextCommand : public DeleteSelectionCommand {
 public:
     ClearTextCommand(Document& document);
-    static void CreateAndApply(const RefPtr<Frame> frame);
-    
+    static void CreateAndApply(Document&);
+
 private:
     EditAction editingAction() const override;
 };
@@ -189,17 +189,17 @@ EditAction ClearTextCommand::editingAction() const
     return EditAction::Delete;
 }
 
-void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
+void ClearTextCommand::CreateAndApply(Document& document)
 {
-    if (frame->selection().isNone())
+    if (document.selection().isNone())
         return;
 
     // Don't leave around stale composition state.
-    frame->editor().clear();
+    document.editor().clear();
     
-    const VisibleSelection oldSelection = frame->selection().selection();
-    frame->selection().selectAll();
-    auto clearCommand = adoptRef(*new ClearTextCommand(*frame->document()));
+    const VisibleSelection oldSelection = document.selection().selection();
+    document.selection().selectAll();
+    auto clearCommand = adoptRef(*new ClearTextCommand(document));
     clearCommand->setStartingSelection(oldSelection);
     clearCommand->apply();
 }
@@ -207,24 +207,24 @@ void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
 using namespace HTMLNames;
 using namespace WTF::Unicode;
 
-TemporarySelectionChange::TemporarySelectionChange(Frame& frame, Optional<VisibleSelection> temporarySelection, OptionSet<TemporarySelectionOption> options)
-    : m_frame(frame)
+TemporarySelectionChange::TemporarySelectionChange(Document& document, Optional<VisibleSelection> temporarySelection, OptionSet<TemporarySelectionOption> options)
+    : m_document(RefPtr(&document))
     , m_options(options)
-    , m_wasIgnoringSelectionChanges(frame.editor().ignoreSelectionChanges())
+    , m_wasIgnoringSelectionChanges(document.editor().ignoreSelectionChanges())
 #if PLATFORM(IOS_FAMILY)
-    , m_appearanceUpdatesWereEnabled(frame.selection().isUpdateAppearanceEnabled())
+    , m_appearanceUpdatesWereEnabled(document.selection().isUpdateAppearanceEnabled())
 #endif
 {
 #if PLATFORM(IOS_FAMILY)
     if (options & TemporarySelectionOption::EnableAppearanceUpdates)
-        frame.selection().setUpdateAppearanceEnabled(true);
+        document.selection().setUpdateAppearanceEnabled(true);
 #endif
 
     if (options & TemporarySelectionOption::IgnoreSelectionChanges)
-        frame.editor().setIgnoreSelectionChanges(true);
+        document.editor().setIgnoreSelectionChanges(true);
 
     if (temporarySelection) {
-        m_selectionToRestore = frame.selection().selection();
+        m_selectionToRestore = document.selection().selection();
         setSelection(temporarySelection.value());
     }
 }
@@ -236,12 +236,12 @@ TemporarySelectionChange::~TemporarySelectionChange()
 
     if (m_options & TemporarySelectionOption::IgnoreSelectionChanges) {
         auto revealSelection = m_options & TemporarySelectionOption::RevealSelection ? Editor::RevealSelection::Yes : Editor::RevealSelection::No;
-        m_frame->editor().setIgnoreSelectionChanges(m_wasIgnoringSelectionChanges, revealSelection);
+        m_document->editor().setIgnoreSelectionChanges(m_wasIgnoringSelectionChanges, revealSelection);
     }
 
 #if PLATFORM(IOS_FAMILY)
     if (m_options & TemporarySelectionOption::EnableAppearanceUpdates)
-        m_frame->selection().setUpdateAppearanceEnabled(m_appearanceUpdatesWereEnabled);
+        m_document->selection().setUpdateAppearanceEnabled(m_appearanceUpdatesWereEnabled);
 #endif
 }
 
@@ -250,14 +250,14 @@ void TemporarySelectionChange::setSelection(const VisibleSelection& selection)
     auto options = FrameSelection::defaultSetSelectionOptions();
     if (m_options & TemporarySelectionOption::DoNotSetFocus)
         options.add(FrameSelection::DoNotSetFocus);
-    m_frame->selection().setSelection(selection, options);
+    m_document->selection().setSelection(selection, options);
 }
 
 // When an event handler has moved the selection outside of a text control
 // we should use the target control's selection for this editing operation.
 VisibleSelection Editor::selectionForCommand(Event* event)
 {
-    auto selection = m_frame.selection().selection();
+    auto selection = m_document.selection().selection();
     if (!event)
         return selection;
     // If the target is a text control, and the current selection is outside of its shadow tree,
@@ -276,12 +276,12 @@ VisibleSelection Editor::selectionForCommand(Event* event)
 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
 EditingBehavior Editor::behavior() const
 {
-    return EditingBehavior(m_frame.settings().editingBehaviorType());
+    return EditingBehavior(m_document.settings().editingBehaviorType());
 }
 
 EditorClient* Editor::client() const
 {
-    if (Page* page = m_frame.page())
+    if (Page* page = m_document.page())
         return &page->editorClient();
     return nullptr;
 }
@@ -344,12 +344,12 @@ bool Editor::handleTextEvent(TextEvent& event)
 
 bool Editor::canEdit() const
 {
-    return m_frame.selection().selection().rootEditableElement();
+    return m_document.selection().selection().rootEditableElement();
 }
 
 bool Editor::canEditRichly() const
 {
-    return m_frame.selection().selection().isContentRichlyEditable();
+    return m_document.selection().selection().isContentRichlyEditable();
 }
 
 enum class ClipboardEventKind {
@@ -442,7 +442,7 @@ static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind
 
 bool Editor::canDHTMLCut()
 {
-    if (m_frame.selection().selection().isInPasswordField())
+    if (m_document.selection().selection().isInPasswordField())
         return false;
 
     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCut);
@@ -450,7 +450,7 @@ bool Editor::canDHTMLCut()
 
 bool Editor::canDHTMLCopy()
 {
-    if (m_frame.selection().selection().isInPasswordField())
+    if (m_document.selection().selection().isInPasswordField())
         return false;
     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCopy);
 }
@@ -484,13 +484,13 @@ bool Editor::canCopy() const
 {
     if (imageElementFromImageDocument(document()))
         return true;
-    const VisibleSelection& selection = m_frame.selection().selection();
+    const VisibleSelection& selection = m_document.selection().selection();
     return selection.isRange() && !selection.isInPasswordField();
 }
 
 bool Editor::canPaste() const
 {
-    if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing())
+    if (m_document.frame()->mainFrame().loader().shouldSuppressTextInputFromEditing())
         return false;
 
     return canEdit();
@@ -498,7 +498,7 @@ bool Editor::canPaste() const
 
 bool Editor::canDelete() const
 {
-    const VisibleSelection& selection = m_frame.selection().selection();
+    const VisibleSelection& selection = m_document.selection().selection();
     return selection.isRange() && selection.rootEditableElement();
 }
 
@@ -524,7 +524,7 @@ bool Editor::shouldSmartDelete()
 {
     if (behavior().shouldAlwaysSmartDelete())
         return true;
-    return m_frame.selection().granularity() == WordGranularity;
+    return m_document.selection().granularity() == WordGranularity;
 }
 
 bool Editor::smartInsertDeleteEnabled()
@@ -547,7 +547,7 @@ bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity g
     if (!canEdit())
         return false;
 
-    if (m_frame.selection().isRange()) {
+    if (m_document.selection().isRange()) {
         if (isTypingAction) {
             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
             revealSelectionAfterEditingOperation();
@@ -587,7 +587,7 @@ bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity g
 
 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editingAction)
 {
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return;
 
     DeleteSelectionCommand::create(document(), smartDelete, true, false, false, true, editingAction)->apply();
@@ -595,7 +595,7 @@ void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editing
 
 void Editor::clearText()
 {
-    ClearTextCommand::CreateAndApply(&m_frame);
+    ClearTextCommand::CreateAndApply(m_document);
 }
 
 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
@@ -661,7 +661,7 @@ bool Editor::shouldInsertFragment(DocumentFragment& fragment, Range* replacingDO
 
 void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, SelectReplacement selectReplacement, SmartReplace smartReplace, MatchStyle matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
 {
-    VisibleSelection selection = m_frame.selection().selection();
+    VisibleSelection selection = m_document.selection().selection();
     if (selection.isNone() || !selection.isContentEditable())
         return;
 
@@ -689,19 +689,19 @@ void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, SelectRepl
     if (m_imageElementsToLoadBeforeRevealingSelection.isEmpty())
         revealSelectionAfterEditingOperation();
 
-    selection = m_frame.selection().selection();
+    selection = m_document.selection().selection();
     if (selection.isInPasswordField())
         return;
 
     if (AXObjectCache::accessibilityEnabled() && editingAction == EditAction::Paste) {
         String text = AccessibilityObject::stringForVisiblePositionRange(command->visibleSelectionForInsertedText());
-        replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypePaste, text, m_frame.selection().selection());
+        replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypePaste, text, m_document.selection().selection());
         command->composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
     }
 
     if (AXObjectCache::accessibilityEnabled() && editingAction == EditAction::Insert) {
         String text = command->documentFragmentPlainText();
-        replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeInsert, text, m_frame.selection().selection());
+        replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeInsert, text, m_document.selection().selection());
         command->composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
     }
 
@@ -728,7 +728,7 @@ void Editor::replaceSelectionWithText(const String& text, SelectReplacement sele
 
 RefPtr<Range> Editor::selectedRange()
 {
-    return createLiveRange(m_frame.selection().selection().toNormalizedRange());
+    return createLiveRange(m_document.selection().selection().toNormalizedRange());
 }
 
 bool Editor::shouldDeleteRange(Range* range) const
@@ -744,7 +744,7 @@ bool Editor::shouldDeleteRange(Range* range) const
 
 bool Editor::tryDHTMLCopy()
 {   
-    if (m_frame.selection().selection().isInPasswordField())
+    if (m_document.selection().selection().isInPasswordField())
         return false;
 
     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Copy);
@@ -752,7 +752,7 @@ bool Editor::tryDHTMLCopy()
 
 bool Editor::tryDHTMLCut()
 {
-    if (m_frame.selection().selection().isInPasswordField())
+    if (m_document.selection().selection().isInPasswordField())
         return false;
     
     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Cut);
@@ -760,7 +760,7 @@ bool Editor::tryDHTMLCut()
 
 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
 {
-    if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing() && action == EditorInsertAction::Typed)
+    if (m_document.frame()->mainFrame().loader().shouldSuppressTextInputFromEditing() && action == EditorInsertAction::Typed)
         return false;
 
     return client() && client()->shouldInsertText(text, range, action);
@@ -782,17 +782,17 @@ void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
 
 bool Editor::hasBidiSelection() const
 {
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return false;
 
     Node* startNode;
-    if (m_frame.selection().isRange()) {
-        startNode = m_frame.selection().selection().start().downstream().deprecatedNode();
-        Node* endNode = m_frame.selection().selection().end().upstream().deprecatedNode();
+    if (m_document.selection().isRange()) {
+        startNode = m_document.selection().selection().start().downstream().deprecatedNode();
+        Node* endNode = m_document.selection().selection().end().upstream().deprecatedNode();
         if (enclosingBlock(startNode) != enclosingBlock(endNode))
             return false;
     } else
-        startNode = m_frame.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
+        startNode = m_document.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
 
     if (!startNode)
         return false;
@@ -812,12 +812,12 @@ bool Editor::hasBidiSelection() const
 
 TriState Editor::selectionUnorderedListState() const
 {
-    if (m_frame.selection().isCaret()) {
-        if (enclosingElementWithTag(m_frame.selection().selection().start(), ulTag))
+    if (m_document.selection().isCaret()) {
+        if (enclosingElementWithTag(m_document.selection().selection().start(), ulTag))
             return TrueTriState;
-    } else if (m_frame.selection().isRange()) {
-        auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), ulTag);
-        auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), ulTag);
+    } else if (m_document.selection().isRange()) {
+        auto* startNode = enclosingElementWithTag(m_document.selection().selection().start(), ulTag);
+        auto* endNode = enclosingElementWithTag(m_document.selection().selection().end(), ulTag);
         if (startNode && endNode && startNode == endNode)
             return TrueTriState;
     }
@@ -827,12 +827,12 @@ TriState Editor::selectionUnorderedListState() const
 
 TriState Editor::selectionOrderedListState() const
 {
-    if (m_frame.selection().isCaret()) {
-        if (enclosingElementWithTag(m_frame.selection().selection().start(), olTag))
+    if (m_document.selection().isCaret()) {
+        if (enclosingElementWithTag(m_document.selection().selection().start(), olTag))
             return TrueTriState;
-    } else if (m_frame.selection().isRange()) {
-        auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), olTag);
-        auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), olTag);
+    } else if (m_document.selection().isRange()) {
+        auto* startNode = enclosingElementWithTag(m_document.selection().selection().start(), olTag);
+        auto* endNode = enclosingElementWithTag(m_document.selection().selection().end(), olTag);
         if (startNode && endNode && startNode == endNode)
             return TrueTriState;
     }
@@ -872,7 +872,7 @@ bool Editor::canDecreaseSelectionListLevel()
 
 RefPtr<Node> Editor::increaseSelectionListLevel()
 {
-    if (!canEditRichly() || m_frame.selection().isNone())
+    if (!canEditRichly() || m_document.selection().isNone())
         return nullptr;
     
     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(&document());
@@ -882,7 +882,7 @@ RefPtr<Node> Editor::increaseSelectionListLevel()
 
 RefPtr<Node> Editor::increaseSelectionListLevelOrdered()
 {
-    if (!canEditRichly() || m_frame.selection().isNone())
+    if (!canEditRichly() || m_document.selection().isNone())
         return nullptr;
     
     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(&document());
@@ -892,7 +892,7 @@ RefPtr<Node> Editor::increaseSelectionListLevelOrdered()
 
 RefPtr<Node> Editor::increaseSelectionListLevelUnordered()
 {
-    if (!canEditRichly() || m_frame.selection().isNone())
+    if (!canEditRichly() || m_document.selection().isNone())
         return nullptr;
     
     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(&document());
@@ -902,7 +902,7 @@ RefPtr<Node> Editor::increaseSelectionListLevelUnordered()
 
 void Editor::decreaseSelectionListLevel()
 {
-    if (!canEditRichly() || m_frame.selection().isNone())
+    if (!canEditRichly() || m_document.selection().isNone())
         return;
     
     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(&document());
@@ -932,7 +932,7 @@ Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const
 
 Element* Editor::findEventTargetFromSelection() const
 {
-    return findEventTargetFrom(m_frame.selection().selection());
+    return findEventTargetFrom(m_document.selection().selection());
 }
 
 void Editor::applyStyle(StyleProperties* style, EditAction editingAction)
@@ -946,13 +946,13 @@ void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction,
     if (!style)
         return;
 
-    auto selectionType = m_frame.selection().selection().selectionType();
+    auto selectionType = m_document.selection().selection().selectionType();
     if (selectionType == VisibleSelection::NoSelection)
         return;
 
     String inputTypeName = inputTypeNameForEditingAction(editingAction);
     String inputEventData = inputEventDataForEditingStyleAndAction(*style, editingAction);
-    RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
+    RefPtr<Element> element = m_document.selection().selection().rootEditableElement();
     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
         return;
 
@@ -969,7 +969,8 @@ void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction,
         break;
     }
 
-    client()->didApplyStyle();
+    if (client())
+        client()->didApplyStyle();
     if (element)
         dispatchInputEvent(*element, inputTypeName, inputEventData);
 }
@@ -984,13 +985,13 @@ void Editor::applyParagraphStyle(StyleProperties* style, EditAction editingActio
     if (!style)
         return;
 
-    auto selectionType = m_frame.selection().selection().selectionType();
+    auto selectionType = m_document.selection().selection().selectionType();
     if (selectionType == VisibleSelection::NoSelection)
         return;
 
     String inputTypeName = inputTypeNameForEditingAction(editingAction);
     String inputEventData = inputEventDataForEditingStyleAndAction(style, editingAction);
-    RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
+    RefPtr<Element> element = m_document.selection().selection().rootEditableElement();
     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
         return;
 
@@ -1005,7 +1006,7 @@ void Editor::applyStyleToSelection(StyleProperties* style, EditAction editingAct
     if (!style || style->isEmpty() || !canEditRichly())
         return;
 
-    if (!client() || !client()->shouldApplyStyle(style, createLiveRange(m_frame.selection().selection().toNormalizedRange()).get()))
+    if (!client() || !client()->shouldApplyStyle(style, createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
         return;
     applyStyle(style, editingAction);
 }
@@ -1016,7 +1017,7 @@ void Editor::applyStyleToSelection(Ref<EditingStyle>&& style, EditAction editing
         return;
 
     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
-    if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), createLiveRange(m_frame.selection().selection().toNormalizedRange()).get()))
+    if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
         return;
 
     applyStyle(WTFMove(style), editingAction, colorFilterMode);
@@ -1027,25 +1028,25 @@ void Editor::applyParagraphStyleToSelection(StyleProperties* style, EditAction e
     if (!style || style->isEmpty() || !canEditRichly())
         return;
     
-    if (client() && client()->shouldApplyStyle(style, createLiveRange(m_frame.selection().selection().toNormalizedRange()).get()))
+    if (client() && client()->shouldApplyStyle(style, createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
         applyParagraphStyle(style, editingAction);
 }
 
 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
 {
-    if (auto editingStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor))
+    if (auto editingStyle = EditingStyle::styleAtSelectionStart(m_document.selection().selection(), propertyID == CSSPropertyBackgroundColor))
         return editingStyle->hasStyle(propertyID, value);
     return false;
 }
 
 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
 {
-    return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
+    return EditingStyle::create(propertyID, value)->triStateOfStyle(m_document.selection().selection());
 }
 
 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
 {
-    RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
+    RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_document.selection().selection(),
         propertyID == CSSPropertyBackgroundColor);
     if (!selectionStyle || !selectionStyle->style())
         return String();
@@ -1136,7 +1137,7 @@ void Editor::appliedEditing(CompositeEditCommand& command)
         m_alternativeTextController->respondToAppliedEditing(&command);
 
         if (!command.preservesTypingStyle())
-            m_frame.selection().clearTypingStyle();
+            m_document.selection().clearTypingStyle();
 
         // Command will be equal to last edit command only in the case of typing
         if (m_lastEditCommand.get() == &command)
@@ -1200,11 +1201,11 @@ void Editor::reappliedEditing(EditCommandComposition& composition)
     respondToChangedContents(newSelection);
 }
 
-Editor::Editor(Frame& frame)
-    : m_frame(frame)
+Editor::Editor(Document& document)
+    : m_document(document)
     , m_killRing(makeUnique<PAL::KillRing>())
-    , m_spellChecker(makeUnique<SpellChecker>(frame))
-    , m_alternativeTextController(makeUnique<AlternativeTextController>(frame))
+    , m_spellChecker(makeUnique<SpellChecker>(document))
+    , m_alternativeTextController(makeUnique<AlternativeTextController>(document))
     , m_editorUIUpdateTimer(*this, &Editor::editorUIUpdateTimerFired)
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
     , m_telephoneNumberDetectionUpdateTimer(*this, &Editor::scanSelectionForTelephoneNumbers)
@@ -1220,7 +1221,7 @@ void Editor::clear()
     if (m_compositionNode) {
         m_compositionNode = nullptr;
         if (EditorClient* client = this->client())
-            client->discardedComposition(&m_frame);
+            client->discardedComposition(m_document.frame());
     }
     m_customCompositionUnderlines.clear();
     m_customCompositionHighlights.clear();
@@ -1229,6 +1230,7 @@ void Editor::clear()
     m_mark = { };
     m_oldSelectionForEditorUIUpdate = { };
     m_editorUIUpdateTimer.stop();
+    m_alternativeTextController->stopAlternativeTextUITimer();
 
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
     m_telephoneNumberDetectionUpdateTimer.stop();
@@ -1238,12 +1240,12 @@ void Editor::clear()
 
 bool Editor::insertText(const String& text, Event* triggeringEvent, TextEventInputType inputType)
 {
-    return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent, inputType);
+    return m_document.frame()->eventHandler().handleTextInputEvent(text, triggeringEvent, inputType);
 }
 
 bool Editor::insertTextForConfirmedComposition(const String& text)
 {
-    return m_frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
+    return m_document.frame()->eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
 }
 
 bool Editor::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent)
@@ -1302,10 +1304,8 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
             // then this code should conditionalize revealing selection on whether the ignoreSelectionChanges() bit
             // is set for the newly focused frame.
             if (client() && client()->shouldRevealCurrentSelectionAfterInsertion()) {
-                if (auto* editedFrame = document->frame()) {
-                    if (auto* page = editedFrame->page())
-                        page->revealCurrentSelection();
-                }
+                if (auto* page = document->page())
+                    page->revealCurrentSelection();
             }
         }
     }
@@ -1318,10 +1318,10 @@ bool Editor::insertLineBreak()
     if (!canEdit())
         return false;
 
-    if (!shouldInsertText("\n", createLiveRange(m_frame.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
+    if (!shouldInsertText("\n", createLiveRange(m_document.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
         return true;
 
-    VisiblePosition caret = m_frame.selection().selection().visibleStart();
+    VisiblePosition caret = m_document.selection().selection().visibleStart();
     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
     TypingCommand::insertLineBreak(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
@@ -1337,11 +1337,11 @@ bool Editor::insertParagraphSeparator()
 
     if (!canEditRichly())
         return insertLineBreak();
-
-    if (!shouldInsertText("\n", createLiveRange(m_frame.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
+    
+    if (!shouldInsertText("\n", createLiveRange(m_document.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
         return true;
 
-    VisiblePosition caret = m_frame.selection().selection().visibleStart();
+    VisiblePosition caret = m_document.selection().selection().visibleStart();
     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
     TypingCommand::insertParagraphSeparator(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
@@ -1405,7 +1405,7 @@ void Editor::performCutOrCopy(EditorActionSpecifier action)
         updateMarkersForWordsAffectedByEditing(true);
     }
 
-    if (enclosingTextFormControl(m_frame.selection().selection().start()))
+    if (enclosingTextFormControl(m_document.selection().selection().start()))
         Pasteboard::createForCopyAndPaste()->writePlainText(selectedTextForDataTransfer(), canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
     else {
         HTMLImageElement* imageElement = nullptr;
@@ -1424,7 +1424,7 @@ void Editor::performCutOrCopy(EditorActionSpecifier action)
             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
 #else
             // FIXME: Delete after <http://webkit.org/b/177618> lands.
-            Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForDataTransfer);
+            Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), *m_document.frame(), IncludeImageAltTextForDataTransfer);
 #endif
         }
     }
@@ -1433,10 +1433,10 @@ void Editor::performCutOrCopy(EditorActionSpecifier action)
     if (action == CutAction) {
         String text;
         if (AXObjectCache::accessibilityEnabled())
-            text = AccessibilityObject::stringForVisiblePositionRange(m_frame.selection().selection());
+            text = AccessibilityObject::stringForVisiblePositionRange(m_document.selection().selection());
         deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), EditAction::Cut);
         if (AXObjectCache::accessibilityEnabled())
-            postTextStateChangeNotificationForCut(text, m_frame.selection().selection());
+            postTextStateChangeNotificationForCut(text, m_document.selection().selection());
     }
 }
 
@@ -1453,7 +1453,7 @@ void Editor::paste(Pasteboard& pasteboard)
         return;
     updateMarkersForWordsAffectedByEditing(false);
     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
-    if (m_frame.selection().selection().isContentRichlyEditable())
+    if (m_document.selection().selection().isContentRichlyEditable())
         pasteWithPasteboard(&pasteboard, { PasteOption::AllowPlainText });
     else
         pasteAsPlainTextWithPasteboard(pasteboard);
@@ -1478,7 +1478,7 @@ void Editor::pasteAsQuotation()
     updateMarkersForWordsAffectedByEditing(false);
     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
     auto pasteboard = Pasteboard::createForCopyAndPaste();
-    if (m_frame.selection().selection().isContentRichlyEditable())
+    if (m_document.selection().selection().isContentRichlyEditable())
         pasteWithPasteboard(pasteboard.get(), { PasteOption::AllowPlainText, PasteOption::AsQuotation });
     else
         pasteAsPlainTextWithPasteboard(*pasteboard);
@@ -1616,7 +1616,7 @@ void Editor::renderLayerDidScroll(const RenderLayer& layer)
     if (m_imageElementsToLoadBeforeRevealingSelection.isEmpty())
         return;
 
-    auto startContainer = makeRefPtr(m_frame.selection().selection().start().containerNode());
+    auto startContainer = makeRefPtr(m_document.selection().selection().start().containerNode());
     if (!startContainer)
         return;
 
@@ -1850,8 +1850,8 @@ void Editor::toggleUnderline()
 void Editor::setBaseWritingDirection(WritingDirection direction)
 {
 #if PLATFORM(IOS_FAMILY)
-    if (inSameParagraph(m_frame.selection().selection().visibleStart(), m_frame.selection().selection().visibleEnd()) && 
-        baseWritingDirectionForSelectionStart() == direction)
+    if (inSameParagraph(m_document.selection().selection().visibleStart(), m_document.selection().selection().visibleEnd())
+        && baseWritingDirectionForSelectionStart() == direction)
         return;
 #endif
         
@@ -1881,7 +1881,7 @@ WritingDirection Editor::baseWritingDirectionForSelectionStart() const
 {
     auto result = WritingDirection::LeftToRight;
 
-    Position pos = m_frame.selection().selection().visibleStart().deepEquivalent();
+    Position pos = m_document.selection().selection().visibleStart().deepEquivalent();
     Node* node = pos.deprecatedNode();
     if (!node)
         return result;
@@ -1916,7 +1916,7 @@ void Editor::selectComposition()
     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
     VisibleSelection selection;
     selection.setWithoutValidation(range->startPosition(), range->endPosition());
-    m_frame.selection().setSelection(selection, { });
+    m_document.selection().setSelection(selection, { });
 }
 
 void Editor::confirmComposition()
@@ -1951,28 +1951,28 @@ void Editor::confirmComposition(const String& text)
 
 class SetCompositionScope {
 public:
-    SetCompositionScope(Frame& frame)
-        : m_frame(frame)
-        , m_typingGestureIndicator(frame)
+    SetCompositionScope(Document& document)
+        : m_document(RefPtr(&document))
+        , m_typingGestureIndicator(*document.frame())
     {
-        m_frame->editor().setIgnoreSelectionChanges(true);
+        m_document->editor().setIgnoreSelectionChanges(true);
     }
 
     ~SetCompositionScope()
     {
-        m_frame->editor().setIgnoreSelectionChanges(false);
-        if (auto* editorClient = m_frame->editor().client())
+        m_document->editor().setIgnoreSelectionChanges(false);
+        if (auto* editorClient = m_document->editor().client())
             editorClient->didUpdateComposition();
     }
 
-    Ref<Frame> m_frame;
+    RefPtr<Document> m_document;
     UserTypingGestureIndicator m_typingGestureIndicator;
 };
 
 void Editor::setComposition(const String& text, SetCompositionMode mode)
 {
     ASSERT(mode == ConfirmComposition || mode == CancelComposition);
-    SetCompositionScope setCompositionScope(m_frame);
+    SetCompositionScope setCompositionScope(m_document);
 
     if (mode == CancelComposition)
         ASSERT(text == emptyString());
@@ -1983,7 +1983,7 @@ void Editor::setComposition(const String& text, SetCompositionMode mode)
     m_customCompositionUnderlines.clear();
     m_customCompositionHighlights.clear();
 
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return;
 
     // Always delete the current composition before inserting the finalized composition text if we're confirming our composition.
@@ -1999,13 +1999,13 @@ void Editor::setComposition(const String& text, SetCompositionMode mode)
 
     if (mode == CancelComposition) {
         // An open typing command that disagrees about current selection would cause issues with typing later on.
-        TypingCommand::closeTyping(&m_frame);
+        TypingCommand::closeTyping(m_document);
     }
 }
 
 void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, const Vector<CompositionHighlight>& highlights, unsigned selectionStart, unsigned selectionEnd)
 {
-    SetCompositionScope setCompositionScope(m_frame);
+    SetCompositionScope setCompositionScope(m_document);
 
     // Updates styles before setting selection for composition to prevent
     // inserting the previous composition text into text nodes oddly.
@@ -2014,7 +2014,7 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
 
     selectComposition();
 
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return;
 
     String originalText = selectedText();
@@ -2022,10 +2022,10 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
     if (isStartingToRecomposeExistingRange) {
         // We pass TypingCommand::TextCompositionFinal here to indicate that we are removing composition text that has been finalized.
         TypingCommand::deleteSelection(document(), 0, TypingCommand::TextCompositionFinal);
-        const VisibleSelection& currentSelection = m_frame.selection().selection();
+        const VisibleSelection& currentSelection = m_document.selection().selection();
         if (currentSelection.isRange()) {
             // If deletion was prevented, then we need to collapse the selection to the end so that the original text will not be recomposed.
-            m_frame.selection().setSelection({ currentSelection.end(), currentSelection.end() });
+            m_document.selection().setSelection({ currentSelection.end(), currentSelection.end() });
         }
     }
 
@@ -2081,8 +2081,8 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
         TypingCommand::insertText(document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionPending);
 
         // Find out what node has the composition now.
-        Position base = m_frame.selection().selection().base().downstream();
-        Position extent = m_frame.selection().selection().extent();
+        Position base = m_document.selection().selection().base().downstream();
+        Position extent = m_document.selection().selection().extent();
         Node* baseNode = base.deprecatedNode();
         unsigned baseOffset = base.deprecatedEditingOffset();
         Node* extentNode = extent.deprecatedNode();
@@ -2108,7 +2108,7 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
             unsigned start = std::min(baseOffset + selectionStart, extentOffset);
             unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
             auto selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
-            m_frame.selection().setSelectedRange(selectedRange.ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::No);
+            m_document.selection().setSelectedRange(selectedRange.ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::No);
         }
     }
 
@@ -2122,7 +2122,7 @@ void Editor::ignoreSpelling()
     if (!client())
         return;
         
-    if (auto selectedRange = m_frame.selection().selection().toNormalizedRange())
+    if (auto selectedRange = m_document.selection().selection().toNormalizedRange())
         document().markers().removeMarkers(*selectedRange, DocumentMarker::Spelling);
 
     String text = selectedText();
@@ -2137,7 +2137,7 @@ void Editor::learnSpelling()
         
     // FIXME: On Mac OS X, when use "learn" button on "Spelling and Grammar" panel, we don't call this function. It should remove misspelling markers around the learned word, see <rdar://problem/5396072>.
 
-    if (auto selectedRange = m_frame.selection().selection().toNormalizedRange())
+    if (auto selectedRange = m_document.selection().selection().toNormalizedRange())
         document().markers().removeMarkers(*selectedRange, DocumentMarker::Spelling);
 
     String text = selectedText();
@@ -2149,14 +2149,14 @@ void Editor::learnSpelling()
 
 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
 {
-    Ref<Frame> protection(m_frame);
+    Ref<Document> protectedDocument(m_document);
 
     // The basic approach is to search in two phases - from the selection end to the end of the doc, and
     // then we wrap and search from the doc start to (approximately) where we started.
     
     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
     // repeated "check spelling" commands work.
-    VisibleSelection selection(m_frame.selection().selection());
+    VisibleSelection selection(m_document.selection().selection());
     Ref<Range> spellingSearchRange = rangeOfContents(document());
 
     bool startedWithSelection = false;
@@ -2305,8 +2305,8 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
         
         // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph
         auto badGrammarRange = resolveCharacterRange(*grammarSearchRange, { grammarPhraseOffset + grammarDetail.range.location, grammarDetail.range.length });
-        m_frame.selection().setSelection(VisibleSelection(badGrammarRange, SEL_DEFAULT_AFFINITY));
-        m_frame.selection().revealSelection();
+        m_document.selection().setSelection(VisibleSelection(badGrammarRange, SEL_DEFAULT_AFFINITY));
+        m_document.selection().revealSelection();
         
         client()->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
         document().markers().addMarker(badGrammarRange, DocumentMarker::Grammar, grammarDetail.userDescription);
@@ -2317,8 +2317,8 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
         // a marker so we draw the red squiggle later.
         
         auto misspellingRange = resolveCharacterRange(spellingSearchRange, { misspellingOffset, misspelledWord.length() });
-        m_frame.selection().setSelection(VisibleSelection(misspellingRange, DOWNSTREAM));
-        m_frame.selection().revealSelection();
+        m_document.selection().setSelection(VisibleSelection(misspellingRange, DOWNSTREAM));
+        m_document.selection().revealSelection();
         
         client()->updateSpellingUIWithMisspelledWord(misspelledWord);
         document().markers().addMarker(misspellingRange, DocumentMarker::Spelling);
@@ -2332,7 +2332,7 @@ String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
     if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
         return String();
 
-    VisibleSelection selection = m_frame.selection().selection();
+    VisibleSelection selection = m_document.selection().selection();
     if (!selection.isContentEditable() || selection.isNone())
         return String();
 
@@ -2386,7 +2386,7 @@ String Editor::misspelledSelectionString() const
 bool Editor::isSelectionUngrammatical()
 {
 #if USE(GRAMMAR_CHECKING)
-    auto range = m_frame.selection().selection().toNormalizedRange();
+    auto range = m_document.selection().selection().toNormalizedRange();
     if (!range || !client())
         return false;
     return TextCheckingHelper(*client(), *range).isUngrammatical();
@@ -2401,7 +2401,7 @@ Vector<String> Editor::guessesForMisspelledWord(const String& word) const
 
     Vector<String> guesses;
     if (client())
-        textChecker()->getGuessesForWord(word, String(), m_frame.selection().selection(), guesses);
+        textChecker()->getGuessesForWord(word, String(), m_document.selection().selection(), guesses);
     return guesses;
 }
 
@@ -2409,7 +2409,7 @@ Vector<String> Editor::guessesForMisspelledOrUngrammatical(bool& misspelled, boo
 {
     if (unifiedTextCheckerEnabled()) {
         Optional<SimpleRange> range;
-        VisibleSelection selection = m_frame.selection().selection();
+        VisibleSelection selection = m_document.selection().selection();
         if (selection.isCaret() && behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
             VisibleSelection wordSelection = VisibleSelection(selection.base());
             wordSelection.expandUsingGranularity(WordGranularity);
@@ -2469,7 +2469,7 @@ void Editor::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelecti
 
 void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement)
 {
-    Ref<Frame> protection(m_frame);
+    Ref<Document> protectedDocument(m_document);
 
     if (platformDrivenTextCheckerEnabled())
         return;
@@ -2591,19 +2591,19 @@ void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart,
     // If autocorrected word is non empty, replace the misspelled word by this word.
     if (!autocorrectedString.isEmpty()) {
         VisibleSelection newSelection(*misspellingRange, DOWNSTREAM);
-        if (newSelection != m_frame.selection().selection()) {
-            if (!m_frame.selection().shouldChangeSelection(newSelection))
+        if (newSelection != m_document.selection().selection()) {
+            if (!m_document.selection().shouldChangeSelection(newSelection))
                 return;
-            m_frame.selection().setSelection(newSelection);
+            m_document.selection().setSelection(newSelection);
         }
 
-        if (!m_frame.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertAction::Typed))
+        if (!m_document.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertAction::Typed))
             return;
-        m_frame.editor().replaceSelectionWithText(autocorrectedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
+        m_document.editor().replaceSelectionWithText(autocorrectedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
 
         // Reset the charet one character further.
-        m_frame.selection().moveTo(m_frame.selection().selection().end());
-        m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
+        m_document.selection().moveTo(m_document.selection().selection().end());
+        m_document.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
     }
 
     if (!isGrammarCheckingEnabled())
@@ -2675,7 +2675,7 @@ bool Editor::isSpellCheckingEnabledFor(Node* node) const
 
 bool Editor::isSpellCheckingEnabledInFocusedNode() const
 {
-    return isSpellCheckingEnabledFor(m_frame.selection().selection().start().deprecatedNode());
+    return isSpellCheckingEnabledFor(m_document.selection().selection().start().deprecatedNode());
 }
 
 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
@@ -2723,7 +2723,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType
     if (paragraphToCheck.isEmpty())
         return;
 
-    bool asynchronous = m_frame.settings().asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel;
+    bool asynchronous = m_document.settings().asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel;
 
     // In asynchronous mode, we intentionally check paragraph-wide sentence.
     const auto resolvedOptions = resolveTextCheckingTypeMask(editableNode, textCheckingOptions);
@@ -2738,7 +2738,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType
     }
 
     Vector<TextCheckingResult> results;
-    checkTextOfParagraph(*textChecker(), paragraphToCheck.text(), resolvedOptions, results, m_frame.selection().selection());
+    checkTextOfParagraph(*textChecker(), paragraphToCheck.text(), resolvedOptions, results, m_document.selection().selection());
     markAndReplaceFor(request.releaseNonNull(), results);
 }
 
@@ -2784,7 +2784,7 @@ static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingPara
 
 void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<TextCheckingResult>& results)
 {
-    Ref<Frame> protection(m_frame);
+    Ref<Document> protectedDocument(m_document);
 
     auto textCheckingOptions = request.data().checkingTypes();
     TextCheckingParagraph paragraph(request.checkingRange(), request.automaticReplacementRange(), &request.paragraphRange());
@@ -2808,9 +2808,9 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
     bool adjustSelectionForParagraphBoundaries = false;
 
     if (shouldPerformReplacement || shouldMarkSpelling || shouldCheckForCorrection) {
-        if (m_frame.selection().selection().selectionType() == VisibleSelection::CaretSelection) {
+        if (m_document.selection().selection().selectionType() == VisibleSelection::CaretSelection) {
             // Attempt to save the caret position so we can restore it later if needed
-            Position caretPosition = m_frame.selection().selection().end();
+            Position caretPosition = m_document.selection().selection().end();
             selectionOffset = paragraph.offsetTo(caretPosition).releaseReturnValue();
             restoreSelectionAfterChange = true;
             if (selectionOffset > 0 && (selectionOffset > paragraph.text().length() || paragraph.text()[selectionOffset - 1] == newlineCharacter))
@@ -2892,13 +2892,13 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
             }
 
             VisibleSelection selectionToReplace(rangeToReplace, DOWNSTREAM);
-            if (selectionToReplace != m_frame.selection().selection()) {
-                if (!m_frame.selection().shouldChangeSelection(selectionToReplace))
+            if (selectionToReplace != m_document.selection().selection()) {
+                if (!m_document.selection().shouldChangeSelection(selectionToReplace))
                     continue;
             }
 
             if (resultType == TextCheckingType::Link) {
-                m_frame.selection().setSelection(selectionToReplace);
+                m_document.selection().setSelection(selectionToReplace);
                 selectionChanged = true;
                 restoreSelectionAfterChange = false;
                 if (canEditRichly())
@@ -2907,7 +2907,7 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, { resultLocation, resultLength });
 
                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
-                    if (Element* root = m_frame.selection().selection().rootEditableElement())
+                    if (Element* root = m_document.selection().selection().rootEditableElement())
                         cache->postNotification(root, AXObjectCache::AXAutocorrectionOccured);
                 }
 
@@ -2937,13 +2937,13 @@ void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<Te
         extendedParagraph.expandRangeToNextEnd();
         if (restoreSelectionAfterChange && selectionOffset <= extendedParagraph.rangeLength()) {
             auto selectionRange = extendedParagraph.subrange({ 0, selectionOffset });
-            m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
+            m_document.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
             if (adjustSelectionForParagraphBoundaries)
-                m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
+                m_document.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
         } else {
             // If this fails for any reason, the fallback is to go one position beyond the last replacement
-            m_frame.selection().moveTo(m_frame.selection().selection().end());
-            m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
+            m_document.selection().moveTo(m_document.selection().selection().end());
+            m_document.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
         }
     }
 }
@@ -3020,8 +3020,8 @@ void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionA
     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
     // selection, and remove words between the selection boundaries.
     //
-    VisiblePosition startOfSelection = m_frame.selection().selection().start();
-    VisiblePosition endOfSelection = m_frame.selection().selection().end();
+    VisiblePosition startOfSelection = m_document.selection().selection().start();
+    VisiblePosition endOfSelection = m_document.selection().selection().end();
     if (startOfSelection.isNull())
         return;
     // First word is the word that ends after or on the start of selection.
@@ -3093,14 +3093,14 @@ void Editor::deletedAutocorrectionAtPosition(const Position& position, const Str
 
 RefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
 {
-    auto document = m_frame.documentAtPoint(windowPoint);
+    auto document = m_document.frame()->documentAtPoint(windowPoint);
     if (!document)
         return nullptr;
-
+    
     auto frame = document->frame();
     if (!frame)
         return nullptr;
-
+    
     auto frameView = frame->view();
     if (!frameView)
         return nullptr;
@@ -3116,7 +3116,7 @@ void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignme
         return;
 
     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
-    m_frame.selection().revealSelection(revealMode, alignment, revealExtentOption);
+    m_document.selection().revealSelection(revealMode, alignment, revealExtentOption);
 }
 
 void Editor::setIgnoreSelectionChanges(bool ignore, RevealSelection shouldRevealExistingSelection)
@@ -3128,7 +3128,7 @@ void Editor::setIgnoreSelectionChanges(bool ignore, RevealSelection shouldReveal
 #if PLATFORM(IOS_FAMILY)
     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
     if (!ignore)
-        respondToChangedSelection(m_frame.selection().selection(), { });
+        respondToChangedSelection(m_document.selection().selection(), { });
 #endif
     if (!ignore && shouldRevealExistingSelection == RevealSelection::Yes)
         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
@@ -3151,7 +3151,7 @@ bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selecti
 {
     if (!m_compositionNode)
         return false;
-    const VisibleSelection& selection = m_frame.selection().selection();
+    const VisibleSelection& selection = m_document.selection().selection();
     Position start = selection.start();
     if (start.deprecatedNode() != m_compositionNode)
         return false;
@@ -3174,7 +3174,7 @@ void Editor::transpose()
     if (!canEdit())
         return;
 
-    VisibleSelection selection = m_frame.selection().selection();
+    VisibleSelection selection = m_document.selection().selection();
     if (!selection.isCaret())
         return;
 
@@ -3199,10 +3199,10 @@ void Editor::transpose()
     String transposed = text.right(1) + text.left(1);
 
     // Select the two characters.
-    if (newSelection != m_frame.selection().selection()) {
-        if (!m_frame.selection().shouldChangeSelection(newSelection))
+    if (newSelection != m_document.selection().selection()) {
+        if (!m_document.selection().shouldChangeSelection(newSelection))
             return;
-        m_frame.selection().setSelection(newSelection);
+        m_document.selection().setSelection(newSelection);
     }
 
     // Insert the transposed characters.
@@ -3254,7 +3254,7 @@ void Editor::dismissCorrectionPanelAsIgnored()
 
 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, OptionSet<FrameSelection::SetSelectionOption> options)
 {
-    Ref<Frame> protection(m_frame);
+    Ref<Document> protectedDocument(m_document);
 
     // If the new selection is orphaned, then don't update the selection.
     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
@@ -3264,9 +3264,9 @@ void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, O
     // because there is work that it must do in this situation.
     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
-    bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
-    if (selectionDidNotChangeDOMPosition || m_frame.selection().shouldChangeSelection(newSelection))
-        m_frame.selection().setSelection(newSelection, options);
+    bool selectionDidNotChangeDOMPosition = newSelection == m_document.selection().selection();
+    if (selectionDidNotChangeDOMPosition || m_document.selection().shouldChangeSelection(newSelection))
+        m_document.selection().setSelection(newSelection, options);
 
     // Some editing operations change the selection visually without affecting its position within the DOM.
     // For example when you press return in the following (the caret is marked by ^):
@@ -3281,13 +3281,13 @@ void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, O
         return;
 #endif
     if (selectionDidNotChangeDOMPosition && client())
-        client()->respondToChangedSelection(&m_frame);
+        client()->respondToChangedSelection(m_document.frame());
 }
 
 String Editor::selectedText() const
 {
     TextIteratorBehavior behavior = TextIteratorDefaultBehavior;
-    if (m_frame.settings().selectionAcrossShadowBoundariesEnabled())
+    if (m_document.settings().selectionAcrossShadowBoundariesEnabled())
         behavior |= TextIteratorTraversesFlatTree;
     return selectedText(behavior);
 }
@@ -3295,7 +3295,7 @@ String Editor::selectedText() const
 String Editor::selectedTextForDataTransfer() const
 {
     TextIteratorBehavior behavior = TextIteratorEmitsImageAltText;
-    if (m_frame.settings().selectionAcrossShadowBoundariesEnabled())
+    if (m_document.settings().selectionAcrossShadowBoundariesEnabled())
         behavior |= TextIteratorTraversesFlatTree;
     return selectedText(behavior);
 }
@@ -3303,7 +3303,7 @@ String Editor::selectedTextForDataTransfer() const
 String Editor::selectedText(TextIteratorBehavior behavior) const
 {
     // We remove '\0' characters because they are not visibly rendered to the user.
-    auto& selection = m_frame.selection().selection();
+    auto& selection = m_document.selection().selection();
     auto start = selection.start();
     auto end = selection.end();
     if (start.isNull() || start.isOrphan() || end.isNull() || end.isOrphan())
@@ -3313,7 +3313,7 @@ String Editor::selectedText(TextIteratorBehavior behavior) const
 
 RefPtr<TextPlaceholderElement> Editor::insertTextPlaceholder(const IntSize& size)
 {
-    if (m_frame.selection().isNone() || !m_frame.selection().selection().isContentEditable())
+    if (m_document.selection().isNone() || !m_document.selection().selection().isContentEditable())
         return nullptr;
 
     Ref<Document> document { this->document() };
@@ -3321,7 +3321,7 @@ RefPtr<TextPlaceholderElement> Editor::insertTextPlaceholder(const IntSize& size
     // FIXME: Write in terms of replaceSelectionWithFragment(). See <https://bugs.webkit.org/show_bug.cgi?id=208744>.
     deleteSelectionWithSmartDelete(false);
 
-    auto range = m_frame.selection().selection().toNormalizedRange();
+    auto range = m_document.selection().selection().toNormalizedRange();
     if (!range)
         return nullptr;
 
@@ -3329,7 +3329,7 @@ RefPtr<TextPlaceholderElement> Editor::insertTextPlaceholder(const IntSize& size
     createLiveRange(*range)->insertNode(placeholder.copyRef());
 
     VisibleSelection newSelection { positionBeforeNode(placeholder.ptr()), positionAfterNode(placeholder.ptr()) };
-    m_frame.selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(UserTriggered));
+    m_document.selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(UserTriggered));
 
     return placeholder;
 }
@@ -3349,8 +3349,8 @@ void Editor::removeTextPlaceholder(TextPlaceholderElement& placeholder)
     placeholder.remove();
 
     // To match the Legacy WebKit implementation, set the text insertion point to be before where the placeholder use to be.
-    if (m_frame.selection().isFocusedAndActive() && document->focusedElement() == savedRootEditableElement)
-        m_frame.selection().setSelection(VisibleSelection { savedPositionBeforePlaceholder, SEL_DEFAULT_AFFINITY }, FrameSelection::defaultSetSelectionOptions(UserTriggered));
+    if (m_document.selection().isFocusedAndActive() && document->focusedElement() == savedRootEditableElement)
+        m_document.selection().setSelection(VisibleSelection { savedPositionBeforePlaceholder, SEL_DEFAULT_AFFINITY }, FrameSelection::defaultSetSelectionOptions(UserTriggered));
 }
 
 static inline void collapseCaretWidth(IntRect& rect)
@@ -3402,7 +3402,7 @@ IntRect Editor::firstRectForRange(Range* range) const
 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
 {
 #if PLATFORM(IOS_FAMILY)
-    if (m_frame.selectionChangeCallbacksDisabled())
+    if (m_document.frame() && m_document.frame()->selectionChangeCallbacksDisabled())
         return true;
 #endif
     return client() && client()->shouldChangeSelectedRange(createLiveRange(oldSelection.toNormalizedRange()).get(), createLiveRange(newSelection.toNormalizedRange()).get(), affinity, stillSelecting);
@@ -3411,17 +3411,17 @@ bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const V
 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
 {
     if (style.isEmpty()) {
-        m_frame.selection().clearTypingStyle();
+        m_document.selection().clearTypingStyle();
         return;
     }
 
     // Calculate the current typing style.
     RefPtr<EditingStyle> typingStyle;
-    if (auto existingTypingStyle = m_frame.selection().typingStyle())
+    if (auto existingTypingStyle = m_document.selection().typingStyle())
         typingStyle = existingTypingStyle->copy();
     else
         typingStyle = EditingStyle::create();
-    typingStyle->overrideTypingStyleAt(style, m_frame.selection().selection().visibleStart().deepEquivalent());
+    typingStyle->overrideTypingStyleAt(style, m_document.selection().selection().visibleStart().deepEquivalent());
 
     // Handle block styles, substracting these from the typing style.
     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
@@ -3429,7 +3429,7 @@ void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAct
         ApplyStyleCommand::create(document(), blockStyle.get(), editingAction)->apply();
 
     // Set the remaining style as the typing style.
-    m_frame.selection().setTypingStyle(WTFMove(typingStyle));
+    m_document.selection().setTypingStyle(WTFMove(typingStyle));
 }
 
 void Editor::computeAndSetTypingStyle(StyleProperties& properties, EditAction editingAction)
@@ -3488,18 +3488,18 @@ void Editor::applyEditingStyleToBodyElement() const
 
 bool Editor::findString(const String& target, FindOptions options)
 {
-    Ref<Frame> protection(m_frame);
+    Ref<Document> protectedDocument(m_document);
 
-    VisibleSelection selection = m_frame.selection().selection();
+    VisibleSelection selection = m_document.selection().selection();
 
     auto resultRange = rangeOfString(target, createLiveRange(selection.firstRange()).get(), options);
     if (!resultRange)
         return false;
 
-    m_frame.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
+    m_document.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
 
     if (!(options.contains(DoNotRevealSelection)))
-        m_frame.selection().revealSelection();
+        m_document.selection().revealSelection();
 
     return true;
 }
@@ -3596,7 +3596,7 @@ unsigned Editor::countMatchesForText(const String& target, Range* range, FindOpt
     if (range) {
         if (&range->ownerDocument() == &document())
             searchRange = range;
-        else if (!isFrameInRange(m_frame, *range))
+        else if (!isFrameInRange(*m_document.frame(), *range))
             return 0;
     }
     if (!searchRange)
@@ -3666,7 +3666,7 @@ void Editor::respondToChangedSelection(const VisibleSelection&, OptionSet<FrameS
 #endif
 
     if (client())
-        client()->respondToChangedSelection(&m_frame);
+        client()->respondToChangedSelection(m_document.frame());
 
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
     if (shouldDetectTelephoneNumbers())
@@ -3689,7 +3689,7 @@ void Editor::respondToChangedSelection(const VisibleSelection&, OptionSet<FrameS
 
 bool Editor::shouldDetectTelephoneNumbers() const
 {
-    return m_frame.document() && document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
+    return m_document.isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
 }
 
 static Vector<SimpleRange> scanForTelephoneNumbers(const SimpleRange& range)
@@ -3732,7 +3732,7 @@ void Editor::scanSelectionForTelephoneNumbers()
 
     m_detectedTelephoneNumberRanges.clear();
 
-    auto& selection = m_frame.selection();
+    auto& selection = m_document.selection();
     if (selection.isRange()) {
         if (auto selectedRange = selection.selection().firstRange()) {
             // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
@@ -3749,7 +3749,7 @@ void Editor::scanSelectionForTelephoneNumbers()
         }
     }
 
-    if (auto* page = m_frame.page())
+    if (auto* page = m_document.page())
         page->servicesOverlayController().selectedTelephoneNumberRangesChanged();
 }
 
@@ -3774,9 +3774,9 @@ void Editor::editorUIUpdateTimerFired()
     if (isContinuousSpellCheckingEnabled) {
         VisibleSelection newAdjacentWords;
         VisibleSelection newSelectedSentence;
-        bool caretBrowsing = m_frame.settings().caretBrowsingEnabled();
-        if (m_frame.selection().selection().isContentEditable() || caretBrowsing) {
-            VisiblePosition newStart(m_frame.selection().selection().visibleStart());
+        bool caretBrowsing = m_document.settings().caretBrowsingEnabled();
+        if (m_document.selection().selection().isContentEditable() || caretBrowsing) {
+            VisiblePosition newStart(m_document.selection().selection().visibleStart());
 #if !PLATFORM(IOS_FAMILY)
             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
 #else
@@ -3829,7 +3829,7 @@ void Editor::editorUIUpdateTimerFired()
     if (!m_editorUIUpdateTimerWasTriggeredByDictation)
         m_alternativeTextController->respondToChangedSelection(oldSelection);
 
-    m_oldSelectionForEditorUIUpdate = m_frame.selection().selection();
+    m_oldSelectionForEditorUIUpdate = m_document.selection().selection();
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     notifyClientOfAttachmentUpdates();
@@ -3856,7 +3856,7 @@ static Node* findFirstMarkable(Node* node)
 
 bool Editor::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerType, int from, int length) const
 {
-    Node* node = findFirstMarkable(m_frame.selection().selection().start().deprecatedNode());
+    Node* node = findFirstMarkable(m_document.selection().selection().start().deprecatedNode());
     if (!node)
         return false;
 
@@ -3934,10 +3934,10 @@ static bool candidateWouldReplaceText(const VisibleSelection& selection)
 
 String Editor::stringForCandidateRequest() const
 {
-    auto& selection = m_frame.selection().selection();
+    auto& selection = m_document.selection().selection();
     auto range = selection.isCaret()
-        ? wordRangeFromPosition(selection.start())
-        : createLiveRange(selection.toNormalizedRange());
+    ? wordRangeFromPosition(selection.start())
+    : createLiveRange(selection.toNormalizedRange());
     if (!range)
         return { };
     if (!candidateWouldReplaceText(selection))
@@ -3947,7 +3947,7 @@ String Editor::stringForCandidateRequest() const
 
 RefPtr<Range> Editor::contextRangeForCandidateRequest() const
 {
-    const VisibleSelection& selection = m_frame.selection().selection();
+    const VisibleSelection& selection = m_document.selection().selection();
     return makeRange(startOfParagraph(selection.visibleStart()), endOfParagraph(selection.visibleEnd()));
 }
 
@@ -4014,7 +4014,7 @@ FontAttributes Editor::fontAttributesAtSelectionStart() const
 {
     FontAttributes attributes;
     Node* nodeToRemove = nullptr;
-    auto* style = styleForSelectionStart(&m_frame, nodeToRemove);
+    auto* style = styleForSelectionStart(m_document.frame(), nodeToRemove);
     if (!style) {
         if (nodeToRemove)
             nodeToRemove->remove();
@@ -4055,7 +4055,7 @@ FontAttributes Editor::fontAttributesAtSelectionStart() const
         break;
     }
 
-    attributes.textLists = editableTextListsAtPositionInDescendingOrder(m_frame.selection().selection().start());
+    attributes.textLists = editableTextListsAtPositionInDescendingOrder(m_document.selection().selection().start());
 
     switch (style->textAlign()) {
     case TextAlignMode::Right:
@@ -4081,7 +4081,7 @@ FontAttributes Editor::fontAttributesAtSelectionStart() const
         break;
     }
 
-    auto typingStyle = makeRefPtr(m_frame.selection().typingStyle());
+    auto typingStyle = makeRefPtr(m_document.selection().typingStyle());
     if (typingStyle && typingStyle->style()) {
         auto value = typingStyle->style()->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
         if (value && value->isValueList()) {
@@ -4169,12 +4169,8 @@ void Editor::notifyClientOfAttachmentUpdates()
     for (auto& identifier : removedAttachmentIdentifiers)
         client()->didRemoveAttachmentWithIdentifier(identifier);
 
-    auto* document = m_frame.document();
-    if (!document)
-        return;
-
     for (auto& identifier : insertedAttachmentIdentifiers) {
-        if (auto attachment = document->attachmentForIdentifier(identifier))
+        if (auto attachment = m_document.attachmentForIdentifier(identifier))
             client()->didInsertAttachmentWithIdentifier(identifier, attachment->attributeWithoutSynchronization(HTMLNames::srcAttr), attachment->hasEnclosingImage());
         else
             ASSERT_NOT_REACHED();
@@ -4197,7 +4193,7 @@ void Editor::insertAttachment(const String& identifier, Optional<uint64_t>&& fil
 
 void Editor::handleAcceptedCandidate(TextCheckingResult acceptedCandidate)
 {
-    const VisibleSelection& selection = m_frame.selection().selection();
+    const VisibleSelection& selection = m_document.selection().selection();
 
     m_isHandlingAcceptedCandidate = true;
 
@@ -4216,7 +4212,7 @@ void Editor::handleAcceptedCandidate(TextCheckingResult acceptedCandidate)
 
 bool Editor::unifiedTextCheckerEnabled() const
 {
-    return WebCore::unifiedTextCheckerEnabled(&m_frame);
+    return WebCore::unifiedTextCheckerEnabled(m_document.frame());
 }
 
 Vector<String> Editor::dictationAlternativesForMarker(const DocumentMarker& marker)
@@ -4232,13 +4228,7 @@ void Editor::applyDictationAlternativelternative(const String& alternativeString
 void Editor::toggleOverwriteModeEnabled()
 {
     m_overwriteModeEnabled = !m_overwriteModeEnabled;
-    m_frame.selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
-}
-
-Document& Editor::document() const
-{
-    ASSERT(m_frame.document());
-    return *m_frame.document();
+    m_document.selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
 }
 
 RefPtr<Range> Editor::adjustedSelectionRange()
@@ -4291,9 +4281,9 @@ const Font* Editor::fontForSelection(bool& hasMultipleFonts) const
 {
     hasMultipleFonts = false;
 
-    if (!m_frame.selection().isRange()) {
+    if (!m_document.selection().isRange()) {
         Node* nodeToRemove;
-        auto* style = styleForSelectionStart(&m_frame, nodeToRemove); // sets nodeToRemove
+        auto* style = styleForSelectionStart(m_document.frame(), nodeToRemove); // sets nodeToRemove
 
         const Font* font = nullptr;
         if (style) {
@@ -4305,12 +4295,12 @@ const Font* Editor::fontForSelection(bool& hasMultipleFonts) const
         return font;
     }
 
-    auto range = m_frame.selection().selection().toNormalizedRange();
+    auto range = m_document.selection().selection().toNormalizedRange();
     if (!range)
         return nullptr;
 
     // FIXME: Adjusting the start may move it past the end. In that case the iterator below will go on to the end of the document.
-    auto adjustedStart = makeBoundaryPoint(adjustedSelectionStartForStyleComputation(m_frame.selection().selection()));
+    auto adjustedStart = makeBoundaryPoint(adjustedSelectionStartForStyleComputation(m_document.selection().selection()));
     if (!adjustedStart)
         return nullptr;
     range->start = *adjustedStart;
@@ -4339,7 +4329,7 @@ RefPtr<HTMLImageElement> Editor::insertEditableImage()
 
 bool Editor::canCopyExcludingStandaloneImages() const
 {
-    auto& selection = m_frame.selection().selection();
+    auto& selection = m_document.selection().selection();
     return selection.isRange() && !selection.isInPasswordField();
 }
 
index 23f5de1..56f5ee3 100644 (file)
@@ -33,6 +33,7 @@
 #include "EditingStyle.h"
 #include "EditorInsertAction.h"
 #include "FindOptions.h"
+#include "Frame.h"
 #include "FrameSelection.h"
 #include "PasteboardWriterData.h"
 #include "TextChecking.h"
@@ -119,13 +120,13 @@ enum class TemporarySelectionOption : uint8_t {
 
 class TemporarySelectionChange {
 public:
-    WEBCORE_EXPORT TemporarySelectionChange(Frame&, Optional<VisibleSelection> = WTF::nullopt, OptionSet<TemporarySelectionOption> = { });
+    WEBCORE_EXPORT TemporarySelectionChange(Document&, Optional<VisibleSelection> = WTF::nullopt, OptionSet<TemporarySelectionOption> = { });
     WEBCORE_EXPORT ~TemporarySelectionChange();
 
 private:
     void setSelection(const VisibleSelection&);
 
-    Ref<Frame> m_frame;
+    RefPtr<Document> m_document;
     OptionSet<TemporarySelectionOption> m_options;
     bool m_wasIgnoringSelectionChanges;
 #if PLATFORM(IOS_FAMILY)
@@ -137,7 +138,7 @@ private:
 class IgnoreSelectionChangeForScope {
 public:
     IgnoreSelectionChangeForScope(Frame& frame)
-        : m_selectionChange(frame, WTF::nullopt, TemporarySelectionOption::IgnoreSelectionChanges)
+        : m_selectionChange(*frame.document(), WTF::nullopt, TemporarySelectionOption::IgnoreSelectionChanges)
     {
     }
 
@@ -150,7 +151,7 @@ private:
 class Editor {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit Editor(Frame&);
+    explicit Editor(Document&);
     ~Editor();
 
     enum class PasteOption : uint8_t {
@@ -271,7 +272,7 @@ public:
     class Command {
     public:
         WEBCORE_EXPORT Command();
-        Command(const EditorInternalCommand*, EditorCommandSource, Frame&);
+        Command(const EditorInternalCommand*, EditorCommandSource, Document&);
 
         WEBCORE_EXPORT bool execute(const String& parameter = String(), Event* triggeringEvent = nullptr) const;
         WEBCORE_EXPORT bool execute(Event* triggeringEvent) const;
@@ -288,6 +289,7 @@ public:
     private:
         const EditorInternalCommand* m_command { nullptr };
         EditorCommandSource m_source;
+        RefPtr<Document> m_document;
         RefPtr<Frame> m_frame;
     };
     WEBCORE_EXPORT Command command(const String& commandName); // Command source is CommandFromMenuOrKeyBinding.
@@ -568,7 +570,7 @@ public:
     WEBCORE_EXPORT void removeTextPlaceholder(TextPlaceholderElement&);
 
 private:
-    Document& document() const;
+    Document& document() const { return m_document; }
 
     bool canDeleteRange(Range*) const;
     bool canSmartReplaceWithPasteboard(Pasteboard&);
@@ -619,7 +621,7 @@ private:
 
     void postTextStateChangeNotificationForCut(const String&, const VisibleSelection&);
 
-    Frame& m_frame;
+    Document& m_document;
     RefPtr<CompositeEditCommand> m_lastEditCommand;
     RefPtr<Text> m_compositionNode;
     unsigned m_compositionStart;
index 13f2bed..e1fb3cd 100644 (file)
@@ -1107,6 +1107,7 @@ static bool executeSuperscript(Frame& frame, Event*, EditorCommandSource source,
 
 static bool executeSwapWithMark(Frame& frame, Event*, EditorCommandSource, const String&)
 {
+    RefPtr<Document> protection(frame.document());
     Ref<Frame> protector(frame);
     const VisibleSelection& mark = frame.editor().mark();
     const VisibleSelection& selection = frame.selection().selection();
@@ -1834,12 +1835,12 @@ static const EditorInternalCommand* internalCommand(const String& commandName)
 
 Editor::Command Editor::command(const String& commandName)
 {
-    return Command(internalCommand(commandName), CommandFromMenuOrKeyBinding, m_frame);
+    return Command(internalCommand(commandName), CommandFromMenuOrKeyBinding, m_document);
 }
 
 Editor::Command Editor::command(const String& commandName, EditorCommandSource source)
 {
-    return Command(internalCommand(commandName), source, m_frame);
+    return Command(internalCommand(commandName), source, m_document);
 }
 
 bool Editor::commandIsSupportedFromMenuOrKeyBinding(const String& commandName)
@@ -1851,12 +1852,13 @@ Editor::Command::Command()
 {
 }
 
-Editor::Command::Command(const EditorInternalCommand* command, EditorCommandSource source, Frame& frame)
+Editor::Command::Command(const EditorInternalCommand* command, EditorCommandSource source, Document& document)
     : m_command(command)
     , m_source(source)
-    , m_frame(command ? &frame : nullptr)
+    , m_document(command ? &document : nullptr)
+    , m_frame(command ? document.frame() : nullptr)
 {
-    ASSERT(command || !m_frame);
+    ASSERT(command || !m_document);
 }
 
 bool Editor::Command::execute(const String& parameter, Event* triggeringEvent) const
@@ -1866,9 +1868,9 @@ bool Editor::Command::execute(const String& parameter, Event* triggeringEvent) c
         if (!allowExecutionWhenDisabled())
             return false;
     }
-    auto document = m_frame->document();
-    document->updateLayoutIgnorePendingStylesheets();
-    if (m_frame->document() != document)
+
+    m_document->updateLayoutIgnorePendingStylesheets();
+    if (m_document->frame() != m_frame)
         return false;
 
     return m_command->execute(*m_frame, triggeringEvent, m_source, parameter);
index a0c0909..048ed06 100644 (file)
@@ -139,13 +139,14 @@ IntRect DragCaretController::editableElementRectInRootViewCoordinates() const
     return { };
 }
 
-static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
+static inline bool shouldAlwaysUseDirectionalSelection(Document* document)
 {
-    return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
+    return !document || document->editor().behavior().shouldConsiderSelectionAsDirectional();
 }
 
-FrameSelection::FrameSelection(Frame* frame)
-    : m_frame(frame)
+FrameSelection::FrameSelection(Document* document)
+    : m_document(document)
+    , m_frame(document? document->frame() : nullptr)
     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
     , m_granularity(CharacterGranularity)
 #if ENABLE(TEXT_CARET)
@@ -156,7 +157,7 @@ FrameSelection::FrameSelection(Frame* frame)
     , m_absCaretBoundsDirty(true)
     , m_caretPaint(true)
     , m_isCaretBlinkingSuspended(false)
-    , m_focused(frame && frame->page() && frame->page()->focusController().focusedFrame() == frame)
+    , m_focused(m_frame && m_frame->page() && m_frame->page()->focusController().focusedFrame() == m_frame)
     , m_shouldShowBlockCursor(false)
     , m_pendingSelectionUpdate(false)
     , m_alwaysAlignCursorOnScrollWhenRevealingSelection(false)
@@ -165,14 +166,24 @@ FrameSelection::FrameSelection(Frame* frame)
     , m_caretBlinks(true)
 #endif
 {
-    if (shouldAlwaysUseDirectionalSelection(m_frame))
+    if (shouldAlwaysUseDirectionalSelection(m_document))
         m_selection.setIsDirectional(true);
+
+    bool activeAndFocused = isFocusedAndActive();
+    if (activeAndFocused)
+        setSelectionFromNone();
+#if USE(UIKIT_EDITING)
+    // Caret blinking (blinks | does not blink)
+    setCaretVisible(activeAndFocused);
+#else
+    setCaretVisibility(activeAndFocused ? Visible : Hidden);
+#endif
 }
 
 Element* FrameSelection::rootEditableElementOrDocumentElement() const
 {
     Element* selectionRoot = m_selection.rootEditableElement();
-    return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
+    return selectionRoot ? selectionRoot : m_document->documentElement();
 }
 
 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
@@ -284,7 +295,7 @@ void FrameSelection::setSelectionByMouseIfDifferent(const VisibleSelection& pass
     EndPointsAdjustmentMode endpointsAdjustmentMode)
 {
     VisibleSelection newSelection = passedNewSelection;
-    bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
+    bool isDirectional = shouldAlwaysUseDirectionalSelection(m_document) || newSelection.isDirectional();
 
     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
     VisiblePosition newBase = base;
@@ -322,7 +333,7 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
     bool shouldClearTypingStyle = options.contains(ClearTypingStyle);
 
     VisibleSelection newSelection = newSelectionPossiblyWithoutDirection;
-    if (shouldAlwaysUseDirectionalSelection(m_frame))
+    if (shouldAlwaysUseDirectionalSelection(m_document))
         newSelection.setIsDirectional(true);
 
     if (!m_frame) {
@@ -334,7 +345,7 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
     // if document->frame() == m_frame we can get into an infinite loop
     if (Document* newSelectionDocument = newSelection.base().document()) {
         if (RefPtr<Frame> newSelectionFrame = newSelectionDocument->frame()) {
-            if (newSelectionFrame != m_frame && newSelectionDocument != m_frame->document()) {
+            if (newSelectionFrame != m_frame && newSelectionDocument != m_document) {
                 newSelectionFrame->selection().setSelection(newSelection, options, AXTextStateChangeIntent(), align, granularity);
                 // It's possible that during the above set selection, this FrameSelection has been modified by
                 // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
@@ -349,7 +360,7 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
     m_granularity = granularity;
 
     if (closeTyping)
-        TypingCommand::closeTyping(m_frame);
+        TypingCommand::closeTyping(*m_document);
 
     if (shouldClearTypingStyle)
         clearTypingStyle();
@@ -357,7 +368,7 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
     VisibleSelection oldSelection = m_selection;
     bool didMutateSelection = oldSelection != newSelection;
     if (didMutateSelection)
-        m_frame->editor().selectionWillChange();
+        m_document->editor().selectionWillChange();
 
     m_selection = newSelection;
 
@@ -371,35 +382,31 @@ bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelectio
     setCaretRectNeedsUpdate();
 
     if (!newSelection.isNone() && !(options & DoNotSetFocus)) {
-        auto* oldFocusedElement = m_frame->document()->focusedElement();
+        auto* oldFocusedElement = m_document->focusedElement();
         setFocusedElementIfNeeded();
         // FIXME: Should not be needed.
-        if (m_frame->document()->focusedElement() != oldFocusedElement)
-            m_frame->document()->updateStyleIfNeeded();
+        if (m_document->focusedElement() != oldFocusedElement)
+            m_document->updateStyleIfNeeded();
     }
 
     // Always clear the x position used for vertical arrow navigation.
     // It will be restored by the vertical arrow navigation code if necessary.
     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
     selectFrameElementInParentIfFullySelected();
-    m_frame->editor().respondToChangedSelection(oldSelection, options);
+    m_document->editor().respondToChangedSelection(oldSelection, options);
     // https://www.w3.org/TR/selection-api/#selectionchange-event
     // FIXME: Spec doesn't specify which task source to use.
-    m_frame->document()->queueTaskToDispatchEvent(TaskSource::UserInteraction, Event::create(eventNames().selectionchangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
+    m_document->queueTaskToDispatchEvent(TaskSource::UserInteraction, Event::create(eventNames().selectionchangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
 
     return true;
 }
 
 void FrameSelection::setSelection(const VisibleSelection& selection, OptionSet<SetSelectionOption> options, AXTextStateChangeIntent intent, CursorAlignOnScroll align, TextGranularity granularity)
 {
-    RefPtr<Frame> protectedFrame(m_frame);
+    RefPtr<Document> protector(m_document);
     if (!setSelectionWithoutUpdatingAppearance(selection, options, align, granularity))
         return;
 
-    Document* document = m_frame->document();
-    if (!document)
-        return;
-
     if (options & RevealSelectionUpToMainFrame)
         m_selectionRevealMode = SelectionRevealMode::RevealUpToMainFrame;
     else if (options & RevealSelection)
@@ -411,27 +418,27 @@ void FrameSelection::setSelection(const VisibleSelection& selection, OptionSet<S
     m_selectionRevealIntent = intent;
     m_pendingSelectionUpdate = true;
 
-    if (document->hasPendingStyleRecalc())
+    if (m_document->hasPendingStyleRecalc())
         return;
 
-    FrameView* frameView = document->view();
+    FrameView* frameView = m_document->view();
     if (frameView && frameView->layoutContext().isLayoutPending())
         return;
 
     updateAndRevealSelection(intent);
 
     if (options & IsUserTriggered) {
-        if (auto* client = m_frame->editor().client())
+        if (auto* client = m_document->editor().client())
             client->didEndUserTriggeredSelectionChanges();
     }
 }
 
-static void updateSelectionByUpdatingLayoutOrStyle(Frame& frame)
+static void updateSelectionByUpdatingLayoutOrStyle(Document& document)
 {
 #if ENABLE(TEXT_CARET)
-    frame.document()->updateLayoutIgnorePendingStylesheets();
+    document.updateLayoutIgnorePendingStylesheets();
 #else
-    frame.document()->updateStyleIfNeeded();
+    document.updateStyleIfNeeded();
 #endif
 }
 
@@ -441,7 +448,7 @@ void FrameSelection::setNeedsSelectionUpdate(RevealSelectionAfterUpdate revealMo
     if (revealMode == RevealSelectionAfterUpdate::Forced)
         m_selectionRevealMode = SelectionRevealMode::Reveal;
     m_pendingSelectionUpdate = true;
-    if (RenderView* view = m_frame->contentRenderer())
+    if (RenderView* view = m_document->renderView())
         view->selection().clearSelection();
 }
 
@@ -457,7 +464,7 @@ void FrameSelection::updateAndRevealSelection(const AXTextStateChangeIntent& int
     if (m_selectionRevealMode != SelectionRevealMode::DoNotReveal) {
         ScrollAlignment alignment;
 
-        if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
+        if (m_document->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
             alignment = m_alwaysAlignCursorOnScrollWhenRevealingSelection ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
         else
             alignment = m_alwaysAlignCursorOnScrollWhenRevealingSelection ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
@@ -471,7 +478,7 @@ void FrameSelection::updateAndRevealSelection(const AXTextStateChangeIntent& int
 void FrameSelection::updateDataDetectorsForSelection()
 {
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
-    m_frame->editor().scanSelectionForTelephoneNumbers();
+    m_document->editor().scanSelectionForTelephoneNumbers();
 #endif
 }
 
@@ -703,7 +710,7 @@ VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
     // base/extent always point to the same nodes as start/end, but which points
     // to which depends on the value of isBaseFirst. Then this can be changed
     // to just return m_sel.extent().
-    if (m_frame && m_frame->editor().behavior().shouldAlwaysExtendSelectionFromExtentEndpoint())
+    if (m_document && m_document->editor().behavior().shouldAlwaysExtendSelectionFromExtentEndpoint())
         return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
 
     return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
@@ -723,7 +730,7 @@ VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePositio
 {
     VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
 
-    if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
+    if (m_document && m_document->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
         // In order to skip spaces when moving right, we advance one
         // word further and then move one word back. Given the
         // semantics of previousWordPosition() this will put us at the
@@ -855,7 +862,7 @@ VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity, b
             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true, reachedBoundary);
         break;
     case WordGranularity: {
-        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
+        bool skipsSpaceWhenMovingRight = m_document && m_document->editor().behavior().shouldSkipSpaceWhenMovingRight();
         VisiblePosition currentPosition(m_selection.extent(), m_selection.affinity());
         pos = rightWordPosition(currentPosition, skipsSpaceWhenMovingRight);
         if (reachedBoundary)
@@ -1076,7 +1083,7 @@ VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity, bo
             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true, reachedBoundary);
         break;
     case WordGranularity: {
-        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
+        bool skipsSpaceWhenMovingRight = m_document && m_document->editor().behavior().shouldSkipSpaceWhenMovingRight();
         VisiblePosition currentPosition(m_selection.extent(), m_selection.affinity());
         pos = leftWordPosition(currentPosition, skipsSpaceWhenMovingRight);
         if (reachedBoundary)
@@ -1362,7 +1369,7 @@ bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, Tex
         break;
     }
 
-    if (reachedBoundary && !isRange() && userTriggered == UserTriggered && m_frame && AXObjectCache::accessibilityEnabled()) {
+    if (reachedBoundary && !isRange() && userTriggered == UserTriggered && m_document && AXObjectCache::accessibilityEnabled()) {
         notifyAccessibilityForSelectionChange({ AXTextStateChangeTypeSelectionBoundary, textSelectionWithDirectionAndGranularity(direction, granularity) });
         return true;
     }
@@ -1374,8 +1381,8 @@ bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, Tex
         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
             return false;
 
-    if (m_frame && AXObjectCache::accessibilityEnabled()) {
-        if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
+    if (m_document && AXObjectCache::accessibilityEnabled()) {
+        if (AXObjectCache* cache = m_document->existingAXObjectCache())
             cache->setTextSelectionIntent(textSelectionIntent(alter, direction, granularity));
     }
 
@@ -1384,7 +1391,7 @@ bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, Tex
     // Note: the START position type is arbitrary because it is unused, it would be
     // the requested position type if there were no xPosForVerticalArrowNavigation set.
     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
-    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
+    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_document) || alter == AlterationExtend);
 
     switch (alter) {
     case AlterationMove:
@@ -1394,7 +1401,7 @@ bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, Tex
 
         if (!m_selection.isCaret()
             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
-            && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
+            && m_document && !m_document->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
             // Don't let the selection go across the base position directly. Needed to match mac
             // behavior when, for instance, word-selecting backwards starting with the caret in
             // the middle of a word and then word-selecting forward, leaving the caret in the
@@ -1407,7 +1414,7 @@ bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, Tex
 
         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
         // base in place and moving the extent. Matches NSTextView.
-        if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
+        if (!m_document || !m_document->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
             setExtent(position, userTriggered);
         else {
             TextDirection textDirection = directionOfEnclosingBlock();
@@ -1517,7 +1524,7 @@ bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, Vertic
     if (userTriggered == UserTriggered)
         m_granularity = CharacterGranularity;
 
-    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
+    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_document) || alter == AlterationExtend);
 
     return true;
 }
@@ -1567,7 +1574,7 @@ void FrameSelection::clear()
     setSelection(VisibleSelection());
 }
 
-void FrameSelection::prepareForDestruction()
+void FrameSelection::willBeRemovedFromFrame()
 {
     m_granularity = CharacterGranularity;
 
@@ -1575,7 +1582,7 @@ void FrameSelection::prepareForDestruction()
     m_caretBlinkTimer.stop();
 #endif
 
-    if (auto* view = m_frame->contentRenderer())
+    if (auto* view = m_document->renderView())
         view->selection().clearSelection();
 
     setSelectionWithoutUpdatingAppearance(VisibleSelection(), defaultSetSelectionOptions(), AlignCursorOnScrollIfNeeded, CharacterGranularity);
@@ -1655,9 +1662,9 @@ static bool isNonOrphanedCaret(const VisibleSelection& selection)
 
 IntRect FrameSelection::absoluteCaretBounds(bool* insideFixed)
 {
-    if (!m_frame)
+    if (!m_document)
         return IntRect();
-    updateSelectionByUpdatingLayoutOrStyle(*m_frame);
+    updateSelectionByUpdatingLayoutOrStyle(*m_document);
     recomputeCaretRect();
     if (insideFixed)
         *insideFixed = m_caretInsidePositionFixed;
@@ -1675,10 +1682,10 @@ bool FrameSelection::recomputeCaretRect()
     if (!shouldUpdateCaretRect())
         return false;
 
-    if (!m_frame)
+    if (!m_document)
         return false;
 
-    FrameView* v = m_frame->document()->view();
+    FrameView* v = m_document->view();
     if (!v)
         return false;
 
@@ -1690,7 +1697,7 @@ bool FrameSelection::recomputeCaretRect()
             clearCaretRect();
         else {
             VisiblePosition visibleStart = m_selection.visibleStart();
-            if (updateCaretRect(m_frame->document(), visibleStart)) {
+            if (updateCaretRect(m_document, visibleStart)) {
                 caretNode = visibleStart.deepEquivalent().deprecatedNode();
                 m_absCaretBoundsDirty = true;
             }
@@ -1715,7 +1722,7 @@ bool FrameSelection::recomputeCaretRect()
         return false;
 
 #if ENABLE(TEXT_CARET)
-    if (RenderView* view = m_frame->document()->renderView()) {
+    if (RenderView* view = m_document->renderView()) {
         bool previousOrNewCaretNodeIsContentEditable = m_selection.isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
         if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
             if (m_previousCaretNode)
@@ -1894,12 +1901,11 @@ bool FrameSelection::contains(const LayoutPoint& point) const
     if (!isRange())
         return false;
     
-    auto* document = m_frame->document();
-    if (!document)
+    if (!m_document)
         return false;
     
     HitTestResult result(point);
-    document->hitTest(HitTestRequest(), result);
+    m_document->hitTest(HitTestRequest(), result);
     Node* innerNode = result.innerNode();
     if (!innerNode || !innerNode->renderer())
         return false;
@@ -1968,9 +1974,7 @@ void FrameSelection::selectFrameElementInParentIfFullySelected()
 
 void FrameSelection::selectAll()
 {
-    Document* document = m_frame->document();
-
-    Element* focusedElement = document->focusedElement();
+    Element* focusedElement = m_document->focusedElement();
     if (is<HTMLSelectElement>(focusedElement)) {
         HTMLSelectElement& selectElement = downcast<HTMLSelectElement>(*focusedElement);
         if (selectElement.canSelectAll()) {
@@ -2000,8 +2004,8 @@ void FrameSelection::selectAll()
         if (root)
             selectStartTarget = root->shadowHost();
         else {
-            root = document->documentElement();
-            selectStartTarget = document->bodyOrFrameset();
+            root = m_document->documentElement();
+            selectStartTarget = m_document->bodyOrFrameset();
         }
     }
     if (!root)
@@ -2058,9 +2062,8 @@ bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, ShouldCl
 void FrameSelection::focusedOrActiveStateChanged()
 {
     bool activeAndFocused = isFocusedAndActive();
-    Ref<Document> document(*m_frame->document());
 
-    document->updateStyleIfNeeded();
+    m_document->updateStyleIfNeeded();
 
 #if USE(UIKIT_EDITING)
     // Caret blinking (blinks | does not blink)
@@ -2071,7 +2074,7 @@ void FrameSelection::focusedOrActiveStateChanged()
     // Because RenderObject::selectionBackgroundColor() and
     // RenderObject::selectionForegroundColor() check if the frame is active,
     // we have to update places those colors were painted.
-    if (RenderView* view = document->renderView())
+    if (RenderView* view = m_document->renderView())
         view->selection().repaint();
 
     // Caret appears in the active frame.
@@ -2082,7 +2085,7 @@ void FrameSelection::focusedOrActiveStateChanged()
     // Because Style::Resolver::checkOneSelector() and
     // RenderTheme::isFocused() check if the frame is active, we have to
     // update style and theme state that depended on those.
-    if (Element* element = document->focusedElement()) {
+    if (Element* element = m_document->focusedElement()) {
         element->invalidateStyleForSubtree();
         if (RenderObject* renderer = element->renderer())
             if (renderer && renderer->style().hasAppearance())
@@ -2107,13 +2110,13 @@ void FrameSelection::setFocused(bool flag)
 
 bool FrameSelection::isFocusedAndActive() const
 {
-    return m_focused && m_frame->page() && m_frame->page()->focusController().isActive();
+    return m_focused && m_document->page() && m_document->page()->focusController().isActive();
 }
 
 #if ENABLE(TEXT_CARET)
-inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
+inline static bool shouldStopBlinkingDueToTypingCommand(Document* document)
 {
-    return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
+    return document->editor().lastEditCommand() && document->editor().lastEditCommand()->shouldStopCaretBlinking();
 }
 #endif
 
@@ -2132,12 +2135,12 @@ void FrameSelection::updateAppearance()
     bool paintBlockCursor = m_shouldShowBlockCursor && m_selection.isCaret() && !isLogicalEndOfLine(m_selection.visibleEnd());
     bool caretRectChangedOrCleared = recomputeCaretRect();
 
-    bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
+    bool caretBrowsing = m_document->settings().caretBrowsingEnabled();
     bool shouldBlink = !paintBlockCursor && caretIsVisible() && isCaret() && (oldSelection.isContentEditable() || caretBrowsing);
 
     // If the caret moved, stop the blink timer so we can restart with a
     // black caret in the new location.
-    if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
+    if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_document))
         m_caretBlinkTimer.stop();
 
     // Start blinking with a black caret. Be sure not to restart if we're
@@ -2153,7 +2156,7 @@ void FrameSelection::updateAppearance()
     }
 #endif
 
-    RenderView* view = m_frame->contentRenderer();
+    RenderView* view = m_document->renderView();
     if (!view)
         return;
 
@@ -2202,8 +2205,8 @@ void FrameSelection::setCaretVisibility(CaretVisibility visibility)
         return;
 
     // FIXME: We shouldn't trigger a synchronous layout here.
-    if (m_frame)
-        updateSelectionByUpdatingLayoutOrStyle(*m_frame);
+    if (m_document)
+        updateSelectionByUpdatingLayoutOrStyle(*m_document);
 
 #if ENABLE(TEXT_CARET)
     if (m_caretPaint) {
@@ -2247,10 +2250,10 @@ void FrameSelection::setFocusedElementIfNeeded()
     if (isNone() || !isFocused())
         return;
 
-    bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
+    bool caretBrowsing = m_document->settings().caretBrowsingEnabled();
     if (caretBrowsing) {
         if (Element* anchor = enclosingAnchorElement(m_selection.base())) {
-            m_frame->page()->focusController().setFocusedElement(anchor, *m_frame);
+            m_document->page()->focusController().setFocusedElement(anchor, *m_frame);
             return;
         }
     }
@@ -2262,16 +2265,16 @@ void FrameSelection::setFocusedElementIfNeeded()
             // so add the !isFrameElement check here. There's probably a better way to make this
             // work in the long term, but this is the safest fix at this time.
             if (target->isMouseFocusable() && !isFrameElement(target)) {
-                m_frame->page()->focusController().setFocusedElement(target, *m_frame);
+                m_document->page()->focusController().setFocusedElement(target, *m_frame);
                 return;
             }
             target = target->parentOrShadowHostElement();
         }
-        m_frame->document()->setFocusedElement(nullptr);
+        m_document->setFocusedElement(nullptr);
     }
 
     if (caretBrowsing)
-        m_frame->page()->focusController().setFocusedElement(nullptr, *m_frame);
+        m_document->page()->focusController().setFocusedElement(nullptr, *m_frame);
 }
 
 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext& p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
@@ -2300,16 +2303,16 @@ bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) co
     if (m_frame->selectionChangeCallbacksDisabled())
         return true;
 #endif
-    return m_frame->editor().client()->shouldDeleteRange(createLiveRange(selection.toNormalizedRange()).get());
+    return m_document->editor().client()->shouldDeleteRange(createLiveRange(selection.toNormalizedRange()).get());
 }
 
 FloatRect FrameSelection::selectionBounds(ClipToVisibleContent clipToVisibleContent) const
 {
-    if (!m_frame->document())
+    if (!m_document)
         return LayoutRect();
 
-    updateSelectionByUpdatingLayoutOrStyle(*m_frame);
-    auto* renderView = m_frame->contentRenderer();
+    updateSelectionByUpdatingLayoutOrStyle(*m_document);
+    auto* renderView = m_document->renderView();
     if (!renderView)
         return LayoutRect();
 
@@ -2325,14 +2328,14 @@ FloatRect FrameSelection::selectionBounds(ClipToVisibleContent clipToVisibleCont
 
 void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles, TextRectangleHeight textRectHeight) const
 {
-    if (!m_frame->contentRenderer())
+    if (!m_document->renderView())
         return;
 
     auto range = selection().toNormalizedRange();
     if (!range)
         return;
 
-    auto visibleContentRect = m_frame->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
+    auto visibleContentRect = m_document->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
     for (auto& rect : boundingBoxes(RenderObject::absoluteTextQuads(*range, textRectHeight == TextRectangleHeight::SelectionHeight))) {
         auto intersectionRect = intersection(rect, visibleContentRect);
         if (!intersectionRect.isEmpty())
@@ -2364,7 +2367,7 @@ static HTMLFormElement* scanForForm(Element* start)
 HTMLFormElement* FrameSelection::currentForm() const
 {
     // Start looking either at the active (first responder) node, or where the selection is.
-    Element* start = m_frame->document()->focusedElement();
+    Element* start = m_document->focusedElement();
     if (!start)
         start = m_selection.start().element();
     if (!start)
@@ -2407,8 +2410,8 @@ void FrameSelection::revealSelection(SelectionRevealMode revealMode, const Scrol
                 layer->scrollRectToVisible(rect, insideFixed, { revealMode, alignment, alignment, ShouldAllowCrossOriginScrolling::Yes });
                 layer->setAdjustForIOSCaretWhenScrolling(false);
                 updateAppearance();
-                if (m_frame->page())
-                    m_frame->page()->chrome().client().notifyRevealedSelectionByScrollingFrame(*m_frame);
+                if (m_document->page())
+                    m_document->page()->chrome().client().notifyRevealedSelectionByScrollingFrame(*m_frame);
             }
         }
 #else
@@ -2426,17 +2429,16 @@ void FrameSelection::setSelectionFromNone()
     // Put a caret inside the body if the entire frame is editable (either the
     // entire WebView is editable or designMode is on for this document).
 
-    Document* document = m_frame->document();
 #if !PLATFORM(IOS_FAMILY)
-    bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
-    if (!isNone() || !(document->hasEditableStyle() || caretBrowsing))
+    bool caretBrowsing = m_document->settings().caretBrowsingEnabled();
+    if (!isNone() || !(m_document->hasEditableStyle() || caretBrowsing))
         return;
 #else
-    if (!document || !(isNone() || isStartOfDocument(VisiblePosition(m_selection.start(), m_selection.affinity()))) || !document->hasEditableStyle())
+    if (!m_document || !(isNone() || isStartOfDocument(VisiblePosition(m_selection.start(), m_selection.affinity()))) || !m_document->hasEditableStyle())
         return;
 #endif
 
-    if (auto* body = document->body())
+    if (auto* body = m_document->body())
         setSelection(VisibleSelection(firstPositionInOrBeforeNode(body), DOWNSTREAM));
 }
 
@@ -2446,7 +2448,7 @@ bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection)
     if (m_frame->selectionChangeCallbacksDisabled())
         return true;
 #endif
-    return m_frame->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
+    return m_document->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
 }
 
 bool FrameSelection::dispatchSelectStart()
@@ -2464,7 +2466,7 @@ void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
 {
     m_shouldShowBlockCursor = shouldShowBlockCursor;
 
-    m_frame->document()->updateLayoutIgnorePendingStylesheets();
+    m_document->updateLayoutIgnorePendingStylesheets();
 
     updateAppearance();
 }
@@ -2482,13 +2484,13 @@ void FrameSelection::scheduleAppearanceUpdateAfterStyleChange()
 
 void FrameSelection::appearanceUpdateTimerFired()
 {
-    Ref<Frame> protectedFrame(*m_frame);
+    Ref<Document> protector(*m_document);
     updateAppearanceAfterLayoutOrStyleChange();
 }
 
 void FrameSelection::updateAppearanceAfterLayoutOrStyleChange()
 {
-    if (auto* client = m_frame->editor().client())
+    if (auto* client = m_document->editor().client())
         client->updateEditorStateAfterLayoutIfEditabilityChanged();
 
     setCaretRectNeedsUpdate();
@@ -2708,7 +2710,7 @@ Optional<SimpleRange> FrameSelection::rangeByExtendingCurrentSelection(int amoun
 
 void FrameSelection::selectRangeOnElement(unsigned location, unsigned length, Node& node)
 {
-    RefPtr<Range> resultRange = m_frame->document()->createRange();
+    RefPtr<Range> resultRange = m_document->createRange();
     resultRange->setStart(node, location);
     resultRange->setEnd(node, location + length);
     VisibleSelection selection = VisibleSelection(*resultRange, SEL_DEFAULT_AFFINITY);
@@ -2889,7 +2891,7 @@ void FrameSelection::setCaretBlinks(bool caretBlinks)
     if (m_caretBlinks == caretBlinks)
         return;
 #if ENABLE(TEXT_CARET)
-    m_frame->document()->updateLayoutIgnorePendingStylesheets(); 
+    m_document->updateLayoutIgnorePendingStylesheets();
     if (m_caretPaint) {
         m_caretPaint = false; 
         invalidateCaretRect(); 
index ab28905..3a7b085 100644 (file)
@@ -140,7 +140,7 @@ public:
         return options;
     }
 
-    WEBCORE_EXPORT explicit FrameSelection(Frame* = nullptr);
+    WEBCORE_EXPORT explicit FrameSelection(Document* = nullptr);
 
     WEBCORE_EXPORT Element* rootEditableElementOrDocumentElement() const;
      
@@ -158,7 +158,7 @@ public:
     WEBCORE_EXPORT bool setSelectedRange(Range*, EAffinity, ShouldCloseTyping, EUserTriggered = NotUserTriggered);
     WEBCORE_EXPORT void selectAll();
     WEBCORE_EXPORT void clear();
-    void prepareForDestruction();
+    void willBeRemovedFromFrame();
 
     void updateAppearanceAfterLayout();
     void scheduleAppearanceUpdateAfterStyleChange();
@@ -336,6 +336,7 @@ private:
     Optional<SimpleRange> rangeByAlteringCurrentSelection(EAlteration, int amount) const;
 #endif
 
+    Document* m_document;
     Frame* m_frame;
 
     LayoutUnit m_xPosForVerticalArrowNavigation;
index 73076de..6601db8 100644 (file)
@@ -50,7 +50,7 @@ InsertIntoTextNodeCommand::InsertIntoTextNodeCommand(Ref<Text>&& node, unsigned
 
 void InsertIntoTextNodeCommand::doApply()
 {
-    bool passwordEchoEnabled = frame().settings().passwordEchoEnabled();
+    bool passwordEchoEnabled = document().settings().passwordEchoEnabled();
     if (passwordEchoEnabled)
         document().updateLayoutIgnorePendingStylesheets();
 
index 176d8f0..27355e6 100644 (file)
@@ -142,7 +142,7 @@ void InsertLineBreakCommand::doApply()
 
     // Handle the case where there is a typing style.
 
-    RefPtr<EditingStyle> typingStyle = frame().selection().typingStyle();
+    RefPtr<EditingStyle> typingStyle = document().selection().typingStyle();
 
     if (typingStyle && !typingStyle->isEmpty()) {
         // Apply the typing style to the inserted line break, so that if the selection
index e9131f6..1bb0d05 100644 (file)
@@ -146,7 +146,7 @@ void InsertTextCommand::doApply()
         // anything other than NoSelection. The rest of this function requires a real endingSelection, so bail out.
         if (endingSelection().isNone())
             return;
-    } else if (frame().editor().isOverwriteModeEnabled()) {
+    } else if (document().editor().isOverwriteModeEnabled()) {
         if (performOverwrite(m_text, m_selectInsertedText))
             return;
     }
@@ -222,7 +222,7 @@ void InsertTextCommand::doApply()
     setEndingSelectionWithoutValidation(startPosition, endPosition);
 
     // Handle the case where there is a typing style.
-    if (RefPtr<EditingStyle> typingStyle = frame().selection().typingStyle()) {
+    if (RefPtr<EditingStyle> typingStyle = document().selection().typingStyle()) {
         typingStyle->prepareToApplyAt(endPosition, EditingStyle::PreserveWritingDirection);
         if (!typingStyle->isEmpty())
             applyStyle(typingStyle.get());
index 5460b75..68e0835 100644 (file)
@@ -60,7 +60,7 @@ void ReplaceRangeWithTextCommand::doApply()
     if (!m_rangeToBeReplaced)
         return;
 
-    if (!frame().selection().shouldChangeSelection(selection))
+    if (!document().selection().shouldChangeSelection(selection))
         return;
 
     if (!characterCount(*m_rangeToBeReplaced))
index 1c81984..73863be 100644 (file)
@@ -1181,7 +1181,7 @@ void ReplaceSelectionCommand::doApply()
     
     // FIXME: Can this wait until after the operation has been performed?  There doesn't seem to be
     // any work performed after this that queries or uses the typing style.
-    frame().selection().clearTypingStyle();
+    document().selection().clearTypingStyle();
 
     // We don't want the destination to end up inside nodes that weren't selected.  To avoid that, we move the
     // position forward without changing the visible position so we're still at the same visible location, but
index c065c02..0dd26a8 100644 (file)
@@ -40,7 +40,7 @@ SetSelectionCommand::SetSelectionCommand(const VisibleSelection& selection, Opti
 
 void SetSelectionCommand::doApply()
 {
-    FrameSelection& selection = frame().selection();
+    FrameSelection& selection = document().selection();
 
     if (selection.shouldChangeSelection(m_selectionToSet) && !m_selectionToSet.isNoneOrOrphaned()) {
         selection.setSelection(m_selectionToSet, m_options);
@@ -50,7 +50,7 @@ void SetSelectionCommand::doApply()
 
 void SetSelectionCommand::doUnapply()
 {
-    FrameSelection& selection = frame().selection();
+    FrameSelection& selection = document().selection();
 
     if (selection.shouldChangeSelection(startingSelection()) && !startingSelection().isNoneOrOrphaned())
         selection.setSelection(startingSelection(), m_options);
index 172d85f..50c1753 100644 (file)
@@ -98,8 +98,8 @@ void SpellCheckRequest::requesterDestroyed()
     m_checker = nullptr;
 }
 
-SpellChecker::SpellChecker(Frame& frame)
-    : m_frame(frame)
+SpellChecker::SpellChecker(Document& document)
+    : m_document(document)
     , m_timerToProcessQueuedRequest(*this, &SpellChecker::timerFiredToProcessQueuedRequest)
 {
 }
@@ -114,7 +114,7 @@ SpellChecker::~SpellChecker()
 
 TextCheckerClient* SpellChecker::client() const
 {
-    Page* page = m_frame.page();
+    Page* page = m_document.page();
     if (!page)
         return nullptr;
     return page->editorClient().textChecker();
@@ -131,7 +131,7 @@ void SpellChecker::timerFiredToProcessQueuedRequest()
 
 bool SpellChecker::isAsynchronousEnabled() const
 {
-    return m_frame.settings().asynchronousSpellCheckingEnabled();
+    return m_document.settings().asynchronousSpellCheckingEnabled();
 }
 
 bool SpellChecker::canCheckAsynchronously(Range& range) const
@@ -174,7 +174,7 @@ void SpellChecker::invokeRequest(Ref<SpellCheckRequest>&& request)
     if (!client())
         return;
     m_processingRequest = WTFMove(request);
-    client()->requestCheckingOfString(*m_processingRequest, m_frame.selection().selection());
+    client()->requestCheckingOfString(*m_processingRequest, m_document.selection().selection());
 }
 
 void SpellChecker::enqueueRequest(Ref<SpellCheckRequest>&& request)
@@ -199,7 +199,7 @@ void SpellChecker::didCheck(TextCheckingRequestIdentifier identifier, const Vect
         return;
     }
 
-    m_frame.editor().markAndReplaceFor(*m_processingRequest, results);
+    m_document.editor().markAndReplaceFor(*m_processingRequest, results);
 
     if (m_lastProcessedIdentifier.toUInt64() < identifier.toUInt64())
         m_lastProcessedIdentifier = identifier;
@@ -219,7 +219,7 @@ void SpellChecker::didCheckSucceed(TextCheckingRequestIdentifier identifier, con
         if (requestData.checkingTypes().contains(TextCheckingType::Grammar))
             markerTypes.add(DocumentMarker::Grammar);
         if (!markerTypes.isEmpty())
-            m_frame.document()->markers().removeMarkers(m_processingRequest->checkingRange(), markerTypes);
+            m_document.markers().removeMarkers(m_processingRequest->checkingRange(), markerTypes);
     }
     didCheck(identifier, results);
 }
index c36ae2c..d19fcfd 100644 (file)
@@ -76,7 +76,7 @@ class SpellChecker {
 public:
     friend class SpellCheckRequest;
 
-    explicit SpellChecker(Frame&);
+    explicit SpellChecker(Document&);
     ~SpellChecker();
 
     bool isAsynchronousEnabled() const;
@@ -106,7 +106,7 @@ private:
     void didCheckCancel(TextCheckingRequestIdentifier);
     void didCheck(TextCheckingRequestIdentifier, const Vector<TextCheckingResult>&);
 
-    Frame& m_frame;
+    Document& m_document;
     TextCheckingRequestIdentifier m_lastRequestIdentifier;
     TextCheckingRequestIdentifier m_lastProcessedIdentifier;
 
index 99e8f15..5920845 100644 (file)
@@ -65,7 +65,7 @@ private:
     void doUnapply() override
     {
         if (!m_hasBeenUndone) {
-            frame().editor().unappliedSpellCorrection(startingSelection(), m_corrected, m_correction);
+            document().editor().unappliedSpellCorrection(startingSelection(), m_corrected, m_correction);
             m_hasBeenUndone = true;
         }
         
@@ -103,7 +103,7 @@ void SpellingCorrectionCommand::doApply()
     if (!m_corrected.length())
         return;
 
-    if (!frame().selection().shouldChangeSelection(m_selectionToBeCorrected))
+    if (!document().selection().shouldChangeSelection(m_selectionToBeCorrected))
         return;
 
     applyCommandToComposite(SetSelectionCommand::create(m_selectionToBeCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered));
index 266d23b..8b9e7d0 100644 (file)
@@ -163,13 +163,10 @@ TypingCommand::TypingCommand(Document& document, ETypingCommand commandType, con
 
 void TypingCommand::deleteSelection(Document& document, Options options, TextCompositionType compositionType)
 {
-    Frame* frame = document.frame();
-    ASSERT(frame);
-
-    if (!frame->selection().isRange())
+    if (!document.selection().isRange())
         return;
 
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
         lastTypingCommand->setCompositionType(compositionType);
         lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
@@ -183,8 +180,8 @@ void TypingCommand::deleteSelection(Document& document, Options options, TextCom
 void TypingCommand::deleteKeyPressed(Document& document, Options options, TextGranularity granularity)
 {
     if (granularity == CharacterGranularity) {
-        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
-            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document.frame());
+        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
+            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document);
             lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
             lastTypingCommand->setCompositionType(TextCompositionNone);
             lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
@@ -199,10 +196,9 @@ void TypingCommand::deleteKeyPressed(Document& document, Options options, TextGr
 void TypingCommand::forwardDeleteKeyPressed(Document& document, Options options, TextGranularity granularity)
 {
     // FIXME: Forward delete in TextEdit appears to open and close a new typing command.
-    Frame* frame = document.frame();
     if (granularity == CharacterGranularity) {
-        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
-            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame);
+        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
+            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document);
             lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
             lastTypingCommand->setCompositionType(TextCompositionNone);
             lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
@@ -214,10 +210,9 @@ void TypingCommand::forwardDeleteKeyPressed(Document& document, Options options,
     TypingCommand::create(document, ForwardDeleteKey, emptyString(), options, granularity)->apply();
 }
 
-void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, Frame* frame)
+void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, Document& document)
 {
-    ASSERT(frame);
-    VisibleSelection currentSelection = frame->selection().selection();
+    VisibleSelection currentSelection = document.selection().selection();
     if (currentSelection == typingCommand->endingSelection())
         return;
 
@@ -227,31 +222,25 @@ void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand
 
 void TypingCommand::insertText(Document& document, const String& text, Options options, TextCompositionType composition)
 {
-    Frame* frame = document.frame();
-    ASSERT(frame);
-
     if (!text.isEmpty())
-        frame->editor().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
+        document.editor().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
     
-    insertText(document, text, frame->selection().selection(), options, composition);
+    insertText(document, text, document.selection().selection(), options, composition);
 }
 
 // FIXME: We shouldn't need to take selectionForInsertion. It should be identical to FrameSelection's current selection.
 void TypingCommand::insertText(Document& document, const String& text, const VisibleSelection& selectionForInsertion, Options options, TextCompositionType compositionType)
 {
-    RefPtr<Frame> frame = document.frame();
-    ASSERT(frame);
-
     LOG(Editing, "TypingCommand::insertText (text %s)", text.utf8().data());
 
-    VisibleSelection currentSelection = frame->selection().selection();
+    VisibleSelection currentSelection = document.selection().selection();
 
     String newText = dispatchBeforeTextInsertedEvent(text, selectionForInsertion, compositionType == TextCompositionPending);
     
     // Set the starting and ending selection appropriately if we are using a selection
     // that is different from the current selection.  In the future, we should change EditCommand
     // to deal with custom selections in a general way that can be used by all of the commands.
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         if (lastTypingCommand->endingSelection() != selectionForInsertion) {
             lastTypingCommand->setStartingSelection(selectionForInsertion);
             lastTypingCommand->setEndingSelection(selectionForInsertion);
@@ -266,12 +255,12 @@ void TypingCommand::insertText(Document& document, const String& text, const Vis
     }
 
     auto cmd = TypingCommand::create(document, InsertText, newText, options, compositionType);
-    applyTextInsertionCommand(frame.get(), cmd.get(), selectionForInsertion, currentSelection);
+    applyTextInsertionCommand(document.frame(), cmd.get(), selectionForInsertion, currentSelection);
 }
 
 void TypingCommand::insertLineBreak(Document& document, Options options)
 {
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
         lastTypingCommand->setCompositionType(TextCompositionNone);
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
@@ -284,7 +273,7 @@ void TypingCommand::insertLineBreak(Document& document, Options options)
 
 void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document)
 {
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         lastTypingCommand->setIsAutocompletion(false);
         lastTypingCommand->setCompositionType(TextCompositionNone);
         lastTypingCommand->insertParagraphSeparatorInQuotedContentAndNotifyAccessibility();
@@ -296,7 +285,7 @@ void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document)
 
 void TypingCommand::insertParagraphSeparator(Document& document, Options options)
 {
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
         lastTypingCommand->setCompositionType(TextCompositionNone);
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
@@ -307,9 +296,9 @@ void TypingCommand::insertParagraphSeparator(Document& document, Options options
     TypingCommand::create(document, InsertParagraphSeparator, emptyString(), options)->apply();
 }
 
-RefPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(Frame& frame)
+RefPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(Document& document)
 {
-    RefPtr<CompositeEditCommand> lastEditCommand = frame.editor().lastEditCommand();
+    RefPtr<CompositeEditCommand> lastEditCommand = document.editor().lastEditCommand();
     if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand.get())->isOpenForMoreTyping())
         return nullptr;
 
@@ -321,16 +310,16 @@ bool TypingCommand::shouldDeferWillApplyCommandUntilAddingTypingCommand() const
     return !m_isHandlingInitialTypingCommand || editActionIsDeleteByTyping(editingAction());
 }
 
-void TypingCommand::closeTyping(Frame* frame)
+void TypingCommand::closeTyping(Document& document)
 {
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame))
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document))
         lastTypingCommand->closeTyping();
 }
 
 #if PLATFORM(IOS_FAMILY)
-void TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Frame* frame, const VisibleSelection& newSelection)
+void TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Document& document, const VisibleSelection& newSelection)
 {
-    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document)) {
         lastTypingCommand->setEndingSelection(newSelection);
         lastTypingCommand->setEndingSelectionOnLastInsertCommand(newSelection);
     }
@@ -436,19 +425,17 @@ void TypingCommand::didApplyCommand()
 
 void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType)
 {
-    Frame& frame = this->frame();
-
 #if PLATFORM(MAC)
-    if (!frame.editor().isContinuousSpellCheckingEnabled()
-        && !frame.editor().isAutomaticQuoteSubstitutionEnabled()
-        && !frame.editor().isAutomaticLinkDetectionEnabled()
-        && !frame.editor().isAutomaticDashSubstitutionEnabled()
-        && !frame.editor().isAutomaticTextReplacementEnabled())
+    if (!document().editor().isContinuousSpellCheckingEnabled()
+        && !document().editor().isAutomaticQuoteSubstitutionEnabled()
+        && !document().editor().isAutomaticLinkDetectionEnabled()
+        && !document().editor().isAutomaticDashSubstitutionEnabled()
+        && !document().editor().isAutomaticTextReplacementEnabled())
             return;
-    if (frame.editor().isHandlingAcceptedCandidate())
+    if (document().editor().isHandlingAcceptedCandidate())
         return;
 #else
-    if (!frame.editor().isContinuousSpellCheckingEnabled())
+    if (!document().editor().isContinuousSpellCheckingEnabled())
         return;
 #endif
     // Take a look at the selection that results after typing and determine whether we need to spellcheck. 
@@ -466,9 +453,9 @@ void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType)
             String strippedPreviousWord;
             if (range && (commandType == TypingCommand::InsertText || commandType == TypingCommand::InsertLineBreak || commandType == TypingCommand::InsertParagraphSeparator || commandType == TypingCommand::InsertParagraphSeparatorInQuotedContent))
                 strippedPreviousWord = plainText(*range).stripWhiteSpace();
-            frame.editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), !strippedPreviousWord.isEmpty());
+            document().editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), !strippedPreviousWord.isEmpty());
         } else if (commandType == TypingCommand::InsertText)
-            frame.editor().startAlternativeTextUITimer();
+            document().editor().startAlternativeTextUITimer();
 #else
         UNUSED_PARAM(commandType);
         // If this bug gets fixed, this PLATFORM(IOS_FAMILY) code could be removed:
@@ -483,7 +470,7 @@ void TypingCommand::markMisspellingsAfterTyping(ETypingCommand commandType)
         VisiblePosition p1 = startOfWord(previous, startWordSide);
         VisiblePosition p2 = startOfWord(start, startWordSide);
         if (p1 != p2)
-            frame.editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), false);
+            document().editor().markMisspellingsAfterTypingToWord(p1, endingSelection(), false);
 #endif // !PLATFORM(IOS_FAMILY)
     }
 }
@@ -497,26 +484,26 @@ bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextG
         return true;
 
     if (!range || isEditingTextAreaOrTextInput())
-        return frame().editor().willApplyEditing(*this, CompositeEditCommand::targetRangesForBindings());
+        return document().editor().willApplyEditing(*this, CompositeEditCommand::targetRangesForBindings());
 
-    return frame().editor().willApplyEditing(*this, { 1, StaticRange::create(*range) });
+    return document().editor().willApplyEditing(*this, { 1, StaticRange::create(*range) });
 }
 
 void TypingCommand::typingAddedToOpenCommand(ETypingCommand commandTypeForAddedTyping)
 {
-    Frame& frame = this->frame();
+    RefPtr<Frame> protector(document().frame());
 
     updatePreservesTypingStyle(commandTypeForAddedTyping);
 
 #if PLATFORM(COCOA)
-    frame.editor().appliedEditing(*this);
+    document().editor().appliedEditing(*this);
     // Since the spellchecking code may also perform corrections and other replacements, it should happen after the typing changes.
     if (!m_shouldPreventSpellChecking)
         markMisspellingsAfterTyping(commandTypeForAddedTyping);
 #else
     // The old spellchecking code requires that checking be done first, to prevent issues like that in 6864072, where <doesn't> is marked as misspelled.
     markMisspellingsAfterTyping(commandTypeForAddedTyping);
-    frame.editor().appliedEditing(*this);
+    document().editor().appliedEditing(*this);
 #endif
 }
 
@@ -535,9 +522,9 @@ void TypingCommand::insertTextAndNotifyAccessibility(const String &text, bool se
 {
     LOG(Editing, "TypingCommand %p insertTextAndNotifyAccessibility (text %s, selectInsertedText %d)", this, text.utf8().data(), selectInsertedText);
 
-    AccessibilityReplacedText replacedText(frame().selection().selection());
+    AccessibilityReplacedText replacedText(document().selection().selection());
     insertText(text, selectInsertedText);
-    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, text, frame().selection().selection());
+    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, text, document().selection().selection());
     composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
 }
 
@@ -550,9 +537,6 @@ void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool select
         m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces, EditAction::TypingInsertText);
 
     applyCommandToComposite(WTFMove(command), endingSelection());
-
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
     typingAddedToOpenCommand(InsertText);
 }
 
@@ -565,17 +549,14 @@ void TypingCommand::insertLineBreak()
         return;
 
     applyCommandToComposite(InsertLineBreakCommand::create(document()));
-
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
     typingAddedToOpenCommand(InsertLineBreak);
 }
 
 void TypingCommand::insertLineBreakAndNotifyAccessibility()
 {
-    AccessibilityReplacedText replacedText(frame().selection().selection());
+    AccessibilityReplacedText replacedText(document().selection().selection());
     insertLineBreak();
-    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
+    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", document().selection().selection());
     composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
 }
 
@@ -588,17 +569,14 @@ void TypingCommand::insertParagraphSeparator()
         return;
 
     applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), false, false, EditAction::TypingInsertParagraph));
-
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
     typingAddedToOpenCommand(InsertParagraphSeparator);
 }
 
 void TypingCommand::insertParagraphSeparatorAndNotifyAccessibility()
 {
-    AccessibilityReplacedText replacedText(frame().selection().selection());
+    AccessibilityReplacedText replacedText(document().selection().selection());
     insertParagraphSeparator();
-    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
+    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", document().selection().selection());
     composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
 }
 
@@ -615,17 +593,14 @@ void TypingCommand::insertParagraphSeparatorInQuotedContent()
     }
         
     applyCommandToComposite(BreakBlockquoteCommand::create(document()));
-
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
     typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent);
 }
 
 void TypingCommand::insertParagraphSeparatorInQuotedContentAndNotifyAccessibility()
 {
-    AccessibilityReplacedText replacedText(frame().selection().selection());
+    AccessibilityReplacedText replacedText(document().selection().selection());
     insertParagraphSeparatorInQuotedContent();
-    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", frame().selection().selection());
+    replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypeTyping, "\n", document().selection().selection());
     composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
 }
 
@@ -652,10 +627,9 @@ bool TypingCommand::makeEditableRootEmpty()
 
 void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing)
 {
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
+    RefPtr<Frame> protector(document().frame());
 
-    frame.editor().updateMarkersForWordsAffectedByEditing(false);
+    document().editor().updateMarkersForWordsAffectedByEditing(false);
 
     VisibleSelection selectionToDelete;
     VisibleSelection selectionAfterUndo;
@@ -748,20 +722,20 @@ void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool shouldAdd
 #if PLATFORM(IOS_FAMILY)
         // Workaround for this bug:
         // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text
-        setEndingSelection(frame.selection().selection());
-        closeTyping(&frame);
+        setEndingSelection(document().selection().selection());
+        closeTyping(document());
 #endif
         return;
     }
     
-    if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
+    if (selectionToDelete.isCaret() || !document().selection().shouldDeleteSelection(selectionToDelete))
         return;
     
     if (!willAddTypingToOpenCommand(DeleteKey, granularity, { }, createLiveRange(*selectionToDelete.firstRange())))
         return;
 
     if (shouldAddToKillRing)
-        frame.editor().addRangeToKillRing(createLiveRange(*selectionToDelete.toNormalizedRange()), Editor::KillRingInsertionMode::PrependText);
+        document().editor().addRangeToKillRing(createLiveRange(*selectionToDelete.toNormalizedRange()), Editor::KillRingInsertionMode::PrependText);
 
     // Post the accessibility notification before actually deleting the content while selectionToDelete is still valid
     postTextStateChangeNotificationForDeletion(selectionToDelete);
@@ -778,10 +752,9 @@ void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool shouldAdd
 
 void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing)
 {
-    Frame& frame = this->frame();
-    Ref<Frame> protector(frame);
+    RefPtr<Frame> protector(document().frame());
 
-    frame.editor().updateMarkersForWordsAffectedByEditing(false);
+    document().editor().updateMarkersForWordsAffectedByEditing(false);
 
     VisibleSelection selectionToDelete;
     VisibleSelection selectionAfterUndo;
@@ -857,13 +830,13 @@ void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool sh
 #if PLATFORM(IOS_FAMILY)
         // Workaround for this bug:
         // <rdar://problem/4653755> UIKit text widgets should use WebKit editing API to manipulate text
-        setEndingSelection(frame.selection().selection());
-        closeTyping(&frame);
+        setEndingSelection(document().selection().selection());
+        closeTyping(document());
 #endif
         return;
     }
     
-    if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
+    if (selectionToDelete.isCaret() || !document().selection().shouldDeleteSelection(selectionToDelete))
         return;
 
     if (!willAddTypingToOpenCommand(ForwardDeleteKey, granularity, { }, createLiveRange(selectionToDelete.firstRange())))
@@ -873,7 +846,7 @@ void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool sh
     postTextStateChangeNotificationForDeletion(selectionToDelete);
 
     if (shouldAddToKillRing)
-        frame.editor().addRangeToKillRing(createLiveRange(*selectionToDelete.toNormalizedRange()), Editor::KillRingInsertionMode::AppendText);
+        document().editor().addRangeToKillRing(createLiveRange(*selectionToDelete.toNormalizedRange()), Editor::KillRingInsertionMode::AppendText);
     // make undo select what was deleted
     setStartingSelection(selectionAfterUndo);
     CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete, /* mergeBlocksAfterDelete*/ true, /* replace*/ false, expandForSpecialElements, /*sanitizeMarkup*/ true);
index 76e5f99..896bf0b 100644 (file)
@@ -65,9 +65,9 @@ public:
     static void insertLineBreak(Document&, Options);
     static void insertParagraphSeparator(Document&, Options);
     static void insertParagraphSeparatorInQuotedContent(Document&);
-    static void closeTyping(Frame*);
+    static void closeTyping(Document&);
 #if PLATFORM(IOS_FAMILY)
-    static void ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Frame*, const VisibleSelection&);
+    static void ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(Document&, const VisibleSelection&);
 #endif
 
     void insertText(const String &text, bool selectInsertedText);
@@ -103,7 +103,7 @@ private:
     bool isOpenForMoreTyping() const { return m_openForMoreTyping; }
     void closeTyping() { m_openForMoreTyping = false; }
 
-    static RefPtr<TypingCommand> lastTypingCommandIfStillOpenForTyping(Frame&);
+    static RefPtr<TypingCommand> lastTypingCommandIfStillOpenForTyping(Document&);
 
     void doApply() final;
     bool isTypingCommand() const final;
@@ -122,7 +122,7 @@ private:
     RefPtr<DataTransfer> inputEventDataTransfer() const final;
     bool isBeforeInputEventCancelable() const final;
 
-    static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Frame*);
+    static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Document&);
 
     void updatePreservesTypingStyle(ETypingCommand);
     bool willAddTypingToOpenCommand(ETypingCommand, TextGranularity, const String& = emptyString(), RefPtr<Range>&& = nullptr);
index 7fe30e0..14b35c2 100644 (file)
@@ -80,8 +80,8 @@ static RefPtr<SharedBuffer> archivedDataForAttributedString(NSAttributedString *
 
 String Editor::selectionInHTMLFormat()
 {
-    return serializePreservingVisualAppearance(m_frame.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
-        m_frame.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
+    return serializePreservingVisualAppearance(m_document.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
+        m_document.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
 }
 
 #if ENABLE(ATTACHMENT_ELEMENT)
@@ -105,18 +105,18 @@ void Editor::getPasteboardTypesAndDataForAttachment(Element& element, Vector<Str
 
 #endif
 
-static RetainPtr<NSAttributedString> selectionAsAttributedString(const Frame& frame)
+static RetainPtr<NSAttributedString> selectionAsAttributedString(const Document& document)
 {
-    auto range = frame.selection().selection().firstRange();
+    auto range = document.selection().selection().firstRange();
     return range ? attributedString(*range).string : adoptNS([[NSAttributedString alloc] init]);
 }
 
 void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
 {
-    auto string = selectionAsAttributedString(m_frame);
+    auto string = selectionAsAttributedString(m_document);
 
     PasteboardWebContent content;
-    content.contentOrigin = m_frame.document()->originIdentifierForPasteboard();
+    content.contentOrigin = m_document.originIdentifierForPasteboard();
     content.canSmartCopyOrDelete = canSmartCopyOrDelete();
     content.dataInWebArchiveFormat = selectionInWebArchiveFormat();
     content.dataInRTFDFormat = [string containsAttachments] ? dataInRTFDFormat(string.get()) : nullptr;
@@ -131,10 +131,10 @@ void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
 
 void Editor::writeSelection(PasteboardWriterData& pasteboardWriterData)
 {
-    auto string = selectionAsAttributedString(m_frame);
+    auto string = selectionAsAttributedString(m_document);
 
     PasteboardWriterData::WebContent webContent;
-    webContent.contentOrigin = m_frame.document()->originIdentifierForPasteboard();
+    webContent.contentOrigin = m_document.originIdentifierForPasteboard();
     webContent.canSmartCopyOrDelete = canSmartCopyOrDelete();
     webContent.dataInWebArchiveFormat = selectionInWebArchiveFormat();
     webContent.dataInRTFDFormat = [string containsAttachments] ? dataInRTFDFormat(string.get()) : nullptr;
@@ -149,7 +149,7 @@ void Editor::writeSelection(PasteboardWriterData& pasteboardWriterData)
 
 RefPtr<SharedBuffer> Editor::selectionInWebArchiveFormat()
 {
-    auto archive = LegacyWebArchive::createFromSelection(&m_frame);
+    auto archive = LegacyWebArchive::createFromSelection(m_document.frame());
     if (!archive)
         return nullptr;
     return SharedBuffer::create(archive->rawDataRepresentation().get());
@@ -177,11 +177,11 @@ String Editor::stringSelectionForPasteboardWithImageAltText()
 
 void Editor::replaceSelectionWithAttributedString(NSAttributedString *attributedString, MailBlockquoteHandling mailBlockquoteHandling)
 {
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return;
 
-    if (m_frame.selection().selection().isContentRichlyEditable()) {
-        if (auto fragment = createFragmentAndAddResources(m_frame, attributedString)) {
+    if (m_document.selection().selection().isContentRichlyEditable()) {
+        if (auto fragment = createFragmentAndAddResources(*m_document.frame(), attributedString)) {
             if (shouldInsertFragment(*fragment, selectedRange().get(), EditorInsertAction::Pasted))
                 pasteAsFragment(fragment.releaseNonNull(), false, false, mailBlockquoteHandling);
         }
@@ -227,7 +227,7 @@ RefPtr<SharedBuffer> Editor::dataInRTFFormat(NSAttributedString *string)
 // Or refactor so it does not do that.
 RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText)
 {
-    WebContentReader reader(m_frame, context, allowPlainText);
+    WebContentReader reader(*m_document.frame(), context, allowPlainText);
     pasteboard.read(reader);
     chosePlainText = reader.madeFragmentFromPlainText;
     return WTFMove(reader.fragment);
@@ -240,7 +240,7 @@ void Editor::takeFindStringFromSelection()
         return;
     }
 
-    auto stringFromSelection = m_frame.displayStringModifiedByEncoding(selectedTextForDataTransfer());
+    auto stringFromSelection = m_document.frame()->displayStringModifiedByEncoding(selectedTextForDataTransfer());
 #if PLATFORM(MAC)
     Vector<String> types;
     types.append(String(legacyStringPasteboardType()));
index e9dfdfc..d41e4b9 100644 (file)
@@ -94,7 +94,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = createFragmentFromPasteboardData(*pasteboard, m_frame, *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    RefPtr<DocumentFragment> fragment = createFragmentFromPasteboardData(*pasteboard, *m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
@@ -147,14 +147,14 @@ void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
     PasteboardWebContent pasteboardContent;
     pasteboardContent.canSmartCopyOrDelete = canSmartCopyOrDelete();
     pasteboardContent.text = selectedTextForDataTransfer();
-    pasteboardContent.markup = serializePreservingVisualAppearance(m_frame.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
-        m_frame.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
+    pasteboardContent.markup = serializePreservingVisualAppearance(m_document.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
+        m_document.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
     pasteboard.write(pasteboardContent);
 }
 
 RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText)
 {
-    return createFragmentFromPasteboardData(pasteboard, m_frame, context, allowPlainText, chosePlainText);
+    return createFragmentFromPasteboardData(pasteboard, *m_document.frame(), context, allowPlainText, chosePlainText);
 }
 
 } // namespace WebCore
index 3f29c4e..6724db8 100644 (file)
@@ -82,7 +82,7 @@ void Editor::setTextAlignmentForChangedBaseWritingDirection(WritingDirection dir
     // If the text has left or right alignment, flip left->right and right->left. 
     // Otherwise, do nothing.
 
-    auto selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection());
+    auto selectionStyle = EditingStyle::styleAtSelectionStart(m_document.selection().selection());
     if (!selectionStyle || !selectionStyle->style())
          return;
 
@@ -126,14 +126,14 @@ void Editor::setTextAlignmentForChangedBaseWritingDirection(WritingDirection dir
     if (!newValue)
         return;
 
-    Element* focusedElement = m_frame.document()->focusedElement();
+    Element* focusedElement = m_document.focusedElement();
     if (focusedElement && (is<HTMLTextAreaElement>(*focusedElement) || (is<HTMLInputElement>(*focusedElement)
         && (downcast<HTMLInputElement>(*focusedElement).isTextField()
             || downcast<HTMLInputElement>(*focusedElement).isSearchField())))) {
         if (direction == WritingDirection::Natural)
             return;
         downcast<HTMLElement>(*focusedElement).setAttributeWithoutSynchronization(alignAttr, newValue);
-        m_frame.document()->updateStyleIfNeeded();
+        m_document.updateStyleIfNeeded();
         return;
     }
 
@@ -146,7 +146,7 @@ void Editor::removeUnchangeableStyles()
 {
     // This function removes styles that the user cannot modify by applying their default values.
     
-    auto editingStyle = EditingStyle::create(m_frame.document()->bodyOrFrameset());
+    auto editingStyle = EditingStyle::create(m_document.bodyOrFrameset());
     auto defaultStyle = editingStyle->style()->mutableCopy();
     
     // Text widgets implement background color via the UIView property. Their body element will not have one.
@@ -218,7 +218,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
 {
     RefPtr<Range> range = selectedRange();
     bool allowPlainText = options.contains(PasteOption::AllowPlainText);
-    WebContentReader reader(m_frame, *range, allowPlainText);
+    WebContentReader reader(*m_document.frame(), *range, allowPlainText);
     int numberOfPasteboardItems = client()->getPasteboardItemsCount();
     for (int i = 0; i < numberOfPasteboardItems; ++i) {
         RefPtr<DocumentFragment> fragment = client()->documentFragmentFromDelegate(i);
@@ -242,7 +242,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
 
 void Editor::insertDictationPhrases(Vector<Vector<String>>&& dictationPhrases, id metadata)
 {
-    if (m_frame.selection().isNone())
+    if (m_document.selection().isNone())
         return;
 
     if (dictationPhrases.isEmpty())
@@ -260,7 +260,7 @@ void Editor::setDictationPhrasesAsChildOfElement(const Vector<Vector<String>>& d
     // Some day we could make them Undoable, and let callers clear the Undo stack explicitly if they wish.
     clearUndoRedoOperations();
 
-    m_frame.selection().clear();
+    m_document.selection().clear();
 
     element.removeChildren();
 
@@ -338,7 +338,7 @@ void Editor::setTextAsChildOfElement(const String& text, Element& element)
 
     // As a side effect this function sets a caret selection after the inserted content. Much of what
     // follows is more expensive if there is a selection, so clear it since it's going to change anyway.
-    m_frame.selection().clear();
+    m_document.selection().clear();
 
     // clear out all current children of element
     element.removeChildren();
@@ -379,7 +379,7 @@ void Editor::setTextAsChildOfElement(const String& text, Element& element)
     selection.setBase(visiblePos);
     selection.setExtent(visiblePos);
 
-    m_frame.selection().setSelection(selection);
+    m_document.selection().setSelection(selection);
 
     client()->respondToChangedContents();
 }
@@ -388,7 +388,7 @@ void Editor::setTextAsChildOfElement(const String& text, Element& element)
 // have a stale selection.
 void Editor::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping()
 {
-    TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(&m_frame, m_frame.selection().selection());
+    TypingCommand::ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping(m_document, m_document.selection().selection());
 }
 
 } // namespace WebCore
index 5d15a64..12fd6a4 100644 (file)
@@ -67,8 +67,8 @@ void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
 {
     PasteboardWebContent pasteboardContent;
     pasteboardContent.text = selectedTextForDataTransfer();
-    pasteboardContent.markup = serializePreservingVisualAppearance(m_frame.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
-        m_frame.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
+    pasteboardContent.markup = serializePreservingVisualAppearance(m_document.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy,
+        m_document.settings().selectionAcrossShadowBoundariesEnabled() ? SerializeComposedTree::Yes : SerializeComposedTree::No);
     pasteboard.write(pasteboardContent);
 }
 
@@ -84,7 +84,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = createFragmentFromPasteboardData(*pasteboard, m_frame, *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    RefPtr<DocumentFragment> fragment = createFragmentFromPasteboardData(*pasteboard, *m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
index 931a230..a741e51 100644 (file)
@@ -102,7 +102,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
 void Editor::readSelectionFromPasteboard(const String& pasteboardName)
 {
     Pasteboard pasteboard(pasteboardName);
-    if (m_frame.selection().selection().isContentRichlyEditable())
+    if (m_document.selection().selection().isContentRichlyEditable())
         pasteWithPasteboard(&pasteboard, { PasteOption::AllowPlainText });
     else
         pasteAsPlainTextWithPasteboard(pasteboard);
@@ -136,17 +136,17 @@ void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
 {
     ASSERT(node);
 
-    if (&node->document() != m_frame.document())
+    if (node->document() != m_document)
         return;
 
-    Ref<Frame> protector(m_frame);
+    Ref<Document> protector(m_document);
 
     auto range = makeRangeSelectingNodeContents(*node);
-    m_frame.selection().setSelection(VisibleSelection(range), FrameSelection::DoNotSetFocus);
+    m_document.selection().setSelection(VisibleSelection(range), FrameSelection::DoNotSetFocus);
 
     Pasteboard pasteboard(pasteboardName);
 
-    if (!m_frame.selection().selection().isContentRichlyEditable()) {
+    if (!m_document.selection().selection().isContentRichlyEditable()) {
         pasteAsPlainTextWithPasteboard(pasteboard);
         return;
     }
@@ -220,7 +220,7 @@ static void getImage(Element& imageElement, RefPtr<Image>& image, CachedImage*&
 
 void Editor::selectionWillChange()
 {
-    if (!hasComposition() || ignoreSelectionChanges() || m_frame.selection().isNone())
+    if (!hasComposition() || ignoreSelectionChanges() || m_document.selection().isNone())
         return;
 
     cancelComposition();
index 5e8687f..c796bfa 100644 (file)
@@ -42,7 +42,7 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption>
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(*m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
@@ -69,9 +69,9 @@ static RefPtr<DocumentFragment> createFragmentFromPlatformData(PlatformDragData&
 RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange&, bool /*allowPlainText*/, bool& /*chosePlainText*/)
 {
     if (COMPtr<IDataObject> platformDragData = pasteboard.dataObject())
-        return createFragmentFromPlatformData(*platformDragData, m_frame);
+        return createFragmentFromPlatformData(*platformDragData, *m_document.frame());
 
-    return createFragmentFromPlatformData(pasteboard.dragDataMap(), m_frame);
+    return createFragmentFromPlatformData(pasteboard.dragDataMap(), *m_document.frame());
 }
 
 } // namespace WebCore
index 55e41b7..d3d665f 100644 (file)
@@ -286,7 +286,7 @@ void CachedFrame::destroy()
     m_document->removeAllEventListeners();
 
     m_document->setBackForwardCacheState(Document::NotInBackForwardCache);
-    m_document->prepareForDestruction();
+    m_document->willBeRemovedFromFrame();
 
     clear();
 }
index 8b05f83..59128be 100644 (file)
@@ -548,11 +548,14 @@ void FrameLoader::stop()
 void FrameLoader::willTransitionToCommitted()
 {
     // This function is called when a frame is still fully in place (not cached, not detached), but will be replaced.
+    Document* document = m_frame.document();
+    if (!document)
+        return;
 
-    if (m_frame.editor().hasComposition()) {
+    if (document->editor().hasComposition()) {
         // The text was already present in DOM, so it's better to confirm than to cancel the composition.
-        m_frame.editor().confirmComposition();
-        if (EditorClient* editorClient = m_frame.editor().client()) {
+        document->editor().confirmComposition();
+        if (EditorClient* editorClient = document->editor().client()) {
             editorClient->respondToChangedSelection(&m_frame);
             editorClient->discardedComposition(&m_frame);
         }
@@ -563,7 +566,7 @@ void FrameLoader::closeURL()
 {
     history().saveDocumentState();
 
-    Document* currentDocument = m_frame.document();
+    RefPtr<Document> currentDocument = m_frame.document();
     UnloadEventPolicy unloadEventPolicy;
     if (m_frame.page() && m_frame.page()->chrome().client().isSVGImageChromeClient()) {
         // If this is the SVGDocument of an SVGImage, no need to dispatch events or recalcStyle.
@@ -575,7 +578,8 @@ void FrameLoader::closeURL()
 
     stopLoading(unloadEventPolicy);
     
-    m_frame.editor().clearUndoRedoOperations();
+    if (currentDocument)
+        currentDocument->editor().clearUndoRedoOperations();
 }
 
 bool FrameLoader::didOpenURL()
@@ -587,7 +591,6 @@ bool FrameLoader::didOpenURL()
     }
 
     m_frame.navigationScheduler().cancel();
-    m_frame.editor().clearLastEditCommand();
 
     m_isComplete = false;
     m_didCallImplicitClose = false;
@@ -650,8 +653,6 @@ static inline bool shouldClearWindowName(const Frame& frame, const Document& new
 
 void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView, WTF::Function<void()>&& handleDOMWindowCreation)
 {
-    m_frame.editor().clear();
-
     bool neededClear = m_needsClear;
     m_needsClear = false;
 
@@ -659,7 +660,7 @@ void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool
         m_frame.document()->cancelParsing();
         m_frame.document()->stopActiveDOMObjects();
         bool hadLivingRenderTree = m_frame.document()->hasLivingRenderTree();
-        m_frame.document()->prepareForDestruction();
+        m_frame.document()->willBeRemovedFromFrame();
         if (hadLivingRenderTree)
             m_frame.document()->adjustFocusedNodeOnNodeRemoval(*m_frame.document());
     }
@@ -680,7 +681,6 @@ void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool
             m_frame.tree().setName(nullAtom());
     }
 
-    m_frame.selection().prepareForDestruction();
     m_frame.eventHandler().clear();
 
     if (clearFrameView && m_frame.view())
index 1a60896..39dea4d 100644 (file)
@@ -156,8 +156,6 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, UniqueRef<FrameLoa
     , m_navigationScheduler(makeUniqueRef<NavigationScheduler>(*this))
     , m_ownerElement(ownerElement)
     , m_script(makeUniqueRef<ScriptController>(*this))
-    , m_editor(makeUniqueRef<Editor>(*this))
-    , m_selection(makeUniqueRef<FrameSelection>(this))
     , m_animationController(makeUniqueRef<CSSAnimationController>(*this))
     , m_pageZoomFactor(parentPageZoomFactor(this))
     , m_textZoomFactor(parentTextZoomFactor(this))
@@ -234,7 +232,7 @@ void Frame::setView(RefPtr<FrameView>&& view)
     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
     // these calls to work.
     if (!view && m_doc && m_doc->backForwardCacheState() != Document::InBackForwardCache)
-        m_doc->prepareForDestruction();
+        m_doc->willBeRemovedFromFrame();
     
     if (m_view)
         m_view->layoutContext().unscheduleLayout();
@@ -279,7 +277,7 @@ void Frame::setDocument(RefPtr<Document>&& newDocument)
 #endif
 
     if (m_doc && m_doc->backForwardCacheState() != Document::InBackForwardCache)
-        m_doc->prepareForDestruction();
+        m_doc->willBeRemovedFromFrame();
 
     m_doc = newDocument.copyRef();
     ASSERT(!m_doc || m_doc->domWindow());
@@ -554,7 +552,7 @@ bool Frame::requestDOMPasteAccess()
     case DOMPasteAccessPolicy::Denied:
         return false;
     case DOMPasteAccessPolicy::NotRequestedYet: {
-        auto* client = m_editor->client();
+        auto* client = editor().client();
         if (!client)
             return false;
 
@@ -937,7 +935,7 @@ void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor
     if (!document)
         return;
 
-    m_editor->dismissCorrectionPanelAsIgnored();
+    editor().dismissCorrectionPanelAsIgnored();
 
     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
index e9cab3c..45440ac 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "AbstractFrame.h"
 #include "AdjustViewSizeOrNot.h"
+#include "Document.h"
 #include "FrameIdentifier.h"
 #include "FrameTree.h"
 #include "PageIdentifier.h"
@@ -163,14 +164,14 @@ public:
     Document* document() const;
     FrameView* view() const;
 
-    Editor& editor() { return m_editor; }
-    const Editor& editor() const { return m_editor; }
+    Editor& editor() { return document()->editor(); }
+    const Editor& editor() const { return document()->editor(); }
     EventHandler& eventHandler() { return m_eventHandler; }
     const EventHandler& eventHandler() const { return m_eventHandler; }
     FrameLoader& loader() const;
     NavigationScheduler& navigationScheduler() const;
-    FrameSelection& selection() { return m_selection; }
-    const FrameSelection& selection() const { return m_selection; }
+    FrameSelection& selection() { return document()->selection(); }
+    const FrameSelection& selection() const { return document()->selection(); }
     FrameTree& tree() const;
     CSSAnimationController& legacyAnimation() { return m_animationController; }
     const CSSAnimationController& legacyAnimation() const { return m_animationController; }
@@ -338,8 +339,6 @@ private:
     RefPtr<Document> m_doc;
 
     UniqueRef<ScriptController> m_script;
-    UniqueRef<Editor> m_editor;
-    UniqueRef<FrameSelection> m_selection;
     UniqueRef<CSSAnimationController> m_animationController;
 
 #if ENABLE(DATA_DETECTION)
index 2d6ce80..ae34b3b 100644 (file)
@@ -72,7 +72,11 @@ RefPtr<TextIndicator> TextIndicator::createWithRange(const SimpleRange& range, T
     if (!frame)
         return nullptr;
 
-    bool indicatesCurrentSelection = range == frame->selection().selection().toNormalizedRange();
+    auto document = makeRefPtr(frame->document());
+    if (!document)
+        return nullptr;
+
+    bool indicatesCurrentSelection = range == document->selection().selection().toNormalizedRange();
 
     OptionSet<TemporarySelectionOption> temporarySelectionOptions;
     temporarySelectionOptions.add(TemporarySelectionOption::DoNotSetFocus);
@@ -80,7 +84,7 @@ RefPtr<TextIndicator> TextIndicator::createWithRange(const SimpleRange& range, T
     temporarySelectionOptions.add(TemporarySelectionOption::IgnoreSelectionChanges);
     temporarySelectionOptions.add(TemporarySelectionOption::EnableAppearanceUpdates);
 #endif
-    TemporarySelectionChange selectionChange(*frame, { range }, temporarySelectionOptions);
+    TemporarySelectionChange selectionChange(*document, { range }, temporarySelectionOptions);
 
     TextIndicatorData data;