Bug 590640 part 5 - Delete empty wrappers when we delete the selection; r=ehsan
authorAryeh Gregor <ayg@aryeh.name>
Thu, 10 May 2012 17:54:33 +0300
changeset 94349 62ffb052629d85fa230c1fd659d5e6b5424cee7d
parent 94348 0c5687159491fd51dde71a6cd647736dee0f867d
child 94350 5161427d7c4c7c7f50c29b259084a4f1f25b59ec
push id773
push useremorley@mozilla.com
push dateMon, 21 May 2012 06:50:20 +0000
treeherderfx-team@1158503601be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs590640
milestone15.0a1
Bug 590640 part 5 - Delete empty wrappers when we delete the selection; r=ehsan
accessible/src/html/nsHyperTextAccessible.cpp
content/html/content/src/nsTextEditorState.cpp
dom/imptests/failures/editing/conformancetest/test_runtest.html.json
editor/idl/nsIEditor.idl
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/base/nsEditorCommands.cpp
editor/libeditor/html/TextEditorTest.cpp
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditRules.h
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/html/nsHTMLEditorLog.cpp
editor/libeditor/html/nsHTMLEditorLog.h
editor/libeditor/html/nsTableEditor.cpp
editor/libeditor/html/tests/browserscope/lib/richtext2/currentStatus.js
editor/libeditor/html/tests/test_bug460740.html
editor/libeditor/html/tests/test_bug668599.html
editor/libeditor/text/nsPlaintextDataTransfer.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
editor/libeditor/text/nsPlaintextEditor.h
editor/libeditor/text/nsTextEditRules.cpp
editor/libeditor/text/nsTextEditRules.h
editor/txtsvc/src/nsTextServicesDocument.cpp
extensions/spellcheck/src/mozInlineSpellChecker.cpp
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -1493,17 +1493,17 @@ nsHyperTextAccessible::DeleteText(PRInt3
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIEditor> editor = GetEditor();
   NS_ENSURE_STATE(editor);
 
   nsresult rv = SetSelectionRange(aStartPos, aEndPos);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return editor->DeleteSelection(nsIEditor::eNone);
+  return editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
 }
 
 NS_IMETHODIMP
 nsHyperTextAccessible::PasteText(PRInt32 aPosition)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -1858,17 +1858,17 @@ nsTextEditorState::SetValue(const nsAStr
         mTextListener->SettingValue(true);
 
         // Also don't enforce max-length here
         PRInt32 savedMaxLength;
         plaintextEditor->GetMaxTextLength(&savedMaxLength);
         plaintextEditor->SetMaxTextLength(-1);
 
         if (insertValue.IsEmpty()) {
-          mEditor->DeleteSelection(nsIEditor::eNone);
+          mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
         } else {
           plaintextEditor->InsertText(insertValue);
         }
 
         mTextListener->SettingValue(false);
 
         if (!weakFrame.IsAlive()) {
           // If the frame was destroyed because of a flush somewhere inside
--- a/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
+++ b/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
@@ -1636,32 +1636,22 @@
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p style=color:blue>foo<div style=color:brown><p style=color:green>[]bar\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar]</span>baz\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar]</span>baz\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar}</span>baz\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span>baz]\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span>baz]\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar</span>baz}\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>{bar</span>baz}\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
-  "[[\"delete\",\"\"]] \"foo<span>[bar]</span>baz\" compare innerHTML":true,
-  "[[\"delete\",\"\"]] \"foo<span>{bar}</span>baz\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"<p>foo</p><p>{bar</p>}<p>baz</p>\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<p>foo</p>{<p>bar}</p><p>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
@@ -1740,17 +1730,16 @@
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" checks for modifications to non-editable content":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
@@ -2071,17 +2060,16 @@
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p>fo[o<ol><li>bar<li>baz</ol><p>q]uz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p>fo[o<ol><li>bar<li>baz</ol><p>q]uz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p>fo[o<ol><li>bar<li>baz</ol><p>q]uz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"delete\",\"\"]] \"<p>fo[o<ol><li>bar<li>baz</ol><p>q]uz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"delete\",\"\"]] \"<ol><li>fo[o</ol><ol><li>b]ar</ol>\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"<ol><li>fo[o</ol><ul><li>b]ar</ul>\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"<b>foo [&nbsp;</b>bar]\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"foo<b> [&nbsp;bar]</b>\" compare innerHTML":true,
-  "[[\"delete\",\"\"]] \"[foo<b>&nbsp;] bar</b>\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"<p style=display:inline>fo[o<p style=display:inline>b]ar\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<span style=display:block>fo[o</span><span style=display:block>b]ar</span>\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<span style=display:block>fo[o</span><span style=display:block>b]ar</span>\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"delete\",\"\"]] \"<quasit style=display:block>fo[o</quasit><quasit style=display:block>b]ar</quasit>\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"delete\",\"\"]] \"<quasit style=display:block>fo[o</quasit><quasit style=display:block>b]ar</quasit>\" compare innerHTML":true,
   "[[\"delete\",\"\"]] \"<ol><li>foo</ol>{}<br><ol><li>bar</ol>\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<ol><li>foo</ol><p>{}<br></p><ol><li>bar</ol>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"delete\",\"\"]] \"<ol><li>foo</ol><p>{}<br></p><ol><li>bar</ol>\" compare innerHTML":true,
@@ -10853,45 +10841,37 @@
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p><b>foo[bar</b><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<div><p>foo[bar</div><p>baz]quz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\": execCommand(\"insertimage\", false, \"/img/lion.svg\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandIndeterm(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandState(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<blockquote><p>baz]quz<p>qoz</blockquote\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"stylewithcss\",\"true\"],[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<p style=color:blue>baz]quz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"stylewithcss\",\"true\"],[\"defaultparagraphseparator\",\"div\"],[\"insertimage\",\"/img/lion.svg\"]] \"<p>foo[bar<p style=color:blue>baz]quz\" compare innerHTML":true,
--- a/editor/idl/nsIEditor.idl
+++ b/editor/idl/nsIEditor.idl
@@ -50,31 +50,35 @@ interface nsIDocumentStateListener;
 interface nsIOutputStream;
 interface nsITransactionManager;
 interface nsITransaction;
 interface nsIEditorObserver;
 interface nsIEditActionListener;
 interface nsIInlineSpellChecker;
 interface nsITransferable;
 
-[scriptable, uuid(7861fe14-9977-413f-a893-3e1000c40817)]
+[scriptable, uuid(7ad59e28-f3d5-4e14-8ea3-794ad4a86de3)]
 
 interface nsIEditor  : nsISupports
 {
 %{C++
   typedef short EDirection;
+  typedef short EStripWrappers;
 %}
   const short eNone = 0;
   const short eNext = 1;
   const short ePrevious = 2;
   const short eNextWord = 3;
   const short ePreviousWord = 4;
   const short eToBeginningOfLine = 5;
   const short eToEndOfLine = 6;
 
+  const short eStrip = 0;
+  const short eNoStrip = 1;
+
   readonly attribute nsISelection selection;
 
   /**
    * Init is to tell the implementation of nsIEditor to begin its services
    * @param aDoc          The dom document interface being observed
    * @param aRoot         This is the root of the editable section of this
    *                      document. If it is null then we get root
    *                      from document body.
@@ -141,18 +145,22 @@ interface nsIEditor  : nsISupports
 
 
   /* ------------ Selected content removal -------------- */
 
   /** 
    * DeleteSelection removes all nodes in the current selection.
    * @param aDir  if eNext, delete to the right (for example, the DEL key)
    *              if ePrevious, delete to the left (for example, the BACKSPACE key)
+   * @param stripWrappers If eStrip, strip any empty inline elements left
+   *                      behind after the deletion; if eNoStrip, don't.  If in
+   *                      doubt, pass eStrip -- eNoStrip is only for if you're
+   *                      about to insert text or similar right after.
    */
-  void deleteSelection(in short action);
+  void deleteSelection(in short action, in short stripWrappers);
 
 
   /* ------------ Document info and file methods -------------- */
   
   /** Returns true if the document has no *meaningful* content */
   readonly attribute boolean documentIsEmpty;
   
   /** Returns true if the document is modifed and needs saving */
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -611,34 +611,52 @@ nsEditor::GetSelectionController(nsISele
   }
   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
   NS_ADDREF(*aSel = selCon);
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-nsEditor::DeleteSelection(EDirection aAction)
-{
-  return DeleteSelectionImpl(aAction);
+nsEditor::DeleteSelection(EDirection aAction, EStripWrappers aStripWrappers)
+{
+  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+  return DeleteSelectionImpl(aAction, aStripWrappers);
 }
 
 
 
 NS_IMETHODIMP
 nsEditor::GetSelection(nsISelection **aSelection)
 {
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   *aSelection = nsnull;
   nsCOMPtr<nsISelectionController> selcon;
   GetSelectionController(getter_AddRefs(selcon));
   NS_ENSURE_TRUE(selcon, NS_ERROR_NOT_INITIALIZED);
   return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);  // does an addref
 }
 
+nsTypedSelection*
+nsEditor::GetTypedSelection()
+{
+  nsCOMPtr<nsISelection> sel;
+  nsresult res = GetSelection(getter_AddRefs(sel));
+  NS_ENSURE_SUCCESS(res, nsnull);
+
+  nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(sel);
+  NS_ENSURE_TRUE(selPrivate, nsnull);
+
+  nsRefPtr<nsFrameSelection> frameSel;
+  res = selPrivate->GetFrameSelection(getter_AddRefs(frameSel));
+  NS_ENSURE_SUCCESS(res, nsnull);
+
+  return frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL);
+}
+
 NS_IMETHODIMP 
 nsEditor::DoTransaction(nsITransaction *aTxn)
 {
 #ifdef NS_DEBUG_EDITOR
   if (gNoisy) { printf("Editor::DoTransaction ----------\n"); }
 #endif
 
   nsresult result = NS_OK;
@@ -4296,18 +4314,21 @@ nsresult nsEditor::EndUpdateViewBatch()
 bool 
 nsEditor::GetShouldTxnSetSelection()
 {
   return mShouldTxnSetSelection;
 }
 
 
 NS_IMETHODIMP 
-nsEditor::DeleteSelectionImpl(nsIEditor::EDirection aAction)
-{
+nsEditor::DeleteSelectionImpl(EDirection aAction,
+                              EStripWrappers aStripWrappers)
+{
+  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+
   nsCOMPtr<nsISelection>selection;
   nsresult res = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   nsRefPtr<EditAggregateTxn> txn;
   nsCOMPtr<nsIDOMNode> deleteNode;
   PRInt32 deleteCharOffset = 0, deleteCharLength = 0;
   res = CreateTxnForDeleteSelection(aAction, getter_AddRefs(txn),
                                     getter_AddRefs(deleteNode),
@@ -4426,17 +4447,17 @@ nsEditor::DeleteSelectionAndPrepareToCre
   result = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   bool collapsed;
   result = selection->GetIsCollapsed(&collapsed);
   if (NS_SUCCEEDED(result) && !collapsed) 
   {
-    result = DeleteSelection(nsIEditor::eNone);
+    result = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
     if (NS_FAILED(result)) {
       return result;
     }
     // get the new selection
     result = GetSelection(getter_AddRefs(selection));
     if (NS_FAILED(result)) {
       return result;
     }
@@ -5100,28 +5121,28 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyE
     case nsIDOMKeyEvent::DOM_VK_ALT:
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK;
     case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
       if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
           nativeKeyEvent->IsMeta()) {
         return NS_OK;
       }
-      DeleteSelection(nsIEditor::ePrevious);
+      DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK;
     case nsIDOMKeyEvent::DOM_VK_DELETE:
       // on certain platforms (such as windows) the shift key
       // modifies what delete does (cmd_cut in this case).
       // bailing here to allow the keybindings to do the cut.
       if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
           nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta()) {
         return NS_OK;
       }
-      DeleteSelection(nsIEditor::eNext);
+      DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
       aKeyEvent->PreventDefault(); // consumed
       return NS_OK; 
   }
   return NS_OK;
 }
 
 nsresult
 nsEditor::HandleInlineSpellCheck(OperationID action,
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -45,16 +45,18 @@
 #include "nsIEditor.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsIPhonetic.h"
 
 #include "nsIAtom.h"
 #include "nsIDOMDocument.h"
 #include "nsISelection.h"
+#include "nsRange.h"
+#include "nsTypedSelection.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIPrivateTextRange.h"
 #include "nsITransactionManager.h"
 #include "nsIComponentManager.h"
 #include "nsCOMArray.h"
 #include "nsIEditActionListener.h"
 #include "nsIEditorObserver.h"
 #include "nsIDocumentStateListener.h"
@@ -198,17 +200,18 @@ public:
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                                nsCOMPtr<nsIDOMNode> *aInOutNode, 
                                PRInt32 *aInOutOffset,
                                nsIDOMDocument *aDoc);
   nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, 
                                       nsIDOMCharacterData *aTextNode, 
                                       PRInt32 aOffset,
                                       bool aSuppressIME = false);
-  NS_IMETHOD DeleteSelectionImpl(EDirection aAction);
+  NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
+                                 EStripWrappers aStripWrappers);
   NS_IMETHOD DeleteSelectionAndCreateNode(const nsAString& aTag,
                                            nsIDOMNode ** aNewNode);
 
   /* helper routines for node/parent manipulations */
   nsresult ReplaceContainer(nsIDOMNode *inNode, 
                             nsCOMPtr<nsIDOMNode> *outNode, 
                             const nsAString &aNodeType,
                             const nsAString *aAttribute = nsnull,
@@ -613,16 +616,17 @@ public:
   static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, PRInt32 aOffset);
   static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, PRInt32 aOffset);
 
   static nsresult GetStartNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outStartNode, PRInt32 *outStartOffset);
   static nsresult GetEndNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outEndNode, PRInt32 *outEndOffset);
 #if DEBUG_JOE
   static void DumpNode(nsIDOMNode *aNode, PRInt32 indent=0);
 #endif
+  nsTypedSelection* GetTypedSelection();
 
   // Helpers to add a node to the selection. 
   // Used by table cell selection methods
   nsresult CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset,
                        nsIDOMNode *aEndParent, PRInt32 aEndOffset,
                        nsIDOMRange **aRange);
 
   // Creates a range with just the supplied node and appends that to the selection
--- a/editor/libeditor/base/nsEditorCommands.cpp
+++ b/editor/libeditor/base/nsEditorCommands.cpp
@@ -281,17 +281,17 @@ nsCutOrDeleteCommand::DoCommand(const ch
   {
     nsCOMPtr<nsISelection> selection;
     nsresult rv = editor->GetSelection(getter_AddRefs(selection));
     if (NS_SUCCEEDED(rv) && selection)
     {
       bool isCollapsed;
       rv = selection->GetIsCollapsed(&isCollapsed);
       if (NS_SUCCEEDED(rv) && isCollapsed)
-        return editor->DeleteSelection(nsIEditor::eNext);
+        return editor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
     }
     return editor->Cut();
   }
     
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP 
@@ -379,17 +379,18 @@ nsCopyOrDeleteCommand::DoCommand(const c
   {
     nsCOMPtr<nsISelection> selection;
     nsresult rv = editor->GetSelection(getter_AddRefs(selection));
     if (NS_SUCCEEDED(rv) && selection)
     {
       bool isCollapsed;
       rv = selection->GetIsCollapsed(&isCollapsed);
       if (NS_SUCCEEDED(rv) && isCollapsed)
-        return editor->DeleteSelection(nsIEditor::eNextWord);
+        return editor->DeleteSelection(nsIEditor::eNextWord,
+                                       nsIEditor::eStrip);
     }
     return editor->Copy();
   }
     
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP 
@@ -622,17 +623,17 @@ nsDeleteCommand::DoCommand(const char *a
     deleteDir = nsIEditor::ePreviousWord;
   else if (!nsCRT::strcmp("cmd_deleteWordForward",aCommandName))
     deleteDir = nsIEditor::eNextWord;
   else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine",aCommandName))
     deleteDir = nsIEditor::eToBeginningOfLine;
   else if (!nsCRT::strcmp("cmd_deleteToEndOfLine",aCommandName))
     deleteDir = nsIEditor::eToEndOfLine;
 
-  return editor->DeleteSelection(deleteDir);
+  return editor->DeleteSelection(deleteDir, nsIEditor::eStrip);
 }
 
 NS_IMETHODIMP 
 nsDeleteCommand::DoCommandParams(const char *aCommandName,
                                  nsICommandParams *aParams,
                                  nsISupports *aCommandRefCon)
 {
   return DoCommand(aCommandName, aCommandRefCon);
--- a/editor/libeditor/html/TextEditorTest.cpp
+++ b/editor/libeditor/html/TextEditorTest.cpp
@@ -117,17 +117,17 @@ nsresult TextEditorTest::RunUnitTest(PRI
 
   return result;
 }
 
 nsresult TextEditorTest::InitDoc()
 {
   nsresult result = mEditor->SelectAll();
   TEST_RESULT(result);
-  result = mEditor->DeleteSelection(nsIEditor::eNext);
+  result = mEditor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
   TEST_RESULT(result);
   return result;
 }
 
 nsresult TextEditorTest::TestInsertBreak()
 {
   nsCOMPtr<nsISelection>selection;
   nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -201,17 +201,17 @@ NS_IMETHODIMP nsHTMLEditor::LoadHTML(con
   {
     bool isCollapsed;
     rv = selection->GetIsCollapsed(&isCollapsed);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Delete Selection, but only if it isn't collapsed, see bug #106269
     if (!isCollapsed) 
     {
-      rv = DeleteSelection(eNone);
+      rv = DeleteSelection(eNone, eStrip);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // Get the first range in the selection, for context:
     nsCOMPtr<nsIDOMRange> range;
     rv = selection->GetRangeAt(0, getter_AddRefs(range));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
@@ -346,17 +346,17 @@ nsHTMLEditor::DoInsertHTMLWithContext(co
   // the selection before collapsing the selection in the new destination)
   if (aDestNode)
   {
     if (aDeleteSelection)
     {
       // Use an auto tracker so that our drop point is correctly
       // positioned after the delete.
       nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
-      rv = DeleteSelection(eNone);
+      rv = DeleteSelection(eNone, eStrip);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     rv = selection->Collapse(targetNode, targetOffset);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // we need to recalculate various things based on potentially new offsets
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -611,17 +611,18 @@ nsHTMLEditRules::WillDoAction(nsISelecti
                             info->inString,
                             info->outString,
                             info->maxLength);
     case nsEditor::kOpLoadHTML:
       return WillLoadHTML(aSelection, aCancel);
     case nsEditor::kOpInsertBreak:
       return WillInsertBreak(aSelection, aCancel, aHandled);
     case nsEditor::kOpDeleteSelection:
-      return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
+      return WillDeleteSelection(aSelection, info->collapsedAction,
+                                 info->stripWrappers, aCancel, aHandled);
     case nsEditor::kOpMakeList:
       return WillMakeList(aSelection, info->blockType, info->entireList, info->bulletType, aCancel, aHandled);
     case nsEditor::kOpIndent:
       return WillIndent(aSelection, aCancel, aHandled);
     case nsEditor::kOpOutdent:
       return WillOutdent(aSelection, aCancel, aHandled);
     case nsEditor::kOpSetAbsolutePosition:
       return WillAbsolutePosition(aSelection, aCancel, aHandled);
@@ -1301,17 +1302,17 @@ nsHTMLEditRules::WillInsertText(nsEditor
   PRInt32 selOffset;
 
   // if the selection isn't collapsed, delete it.
   bool bCollapsed;
   res = aSelection->GetIsCollapsed(&bCollapsed);
   NS_ENSURE_SUCCESS(res, res);
   if (!bCollapsed)
   {
-    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone);
+    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
@@ -1509,17 +1510,17 @@ nsHTMLEditRules::WillInsertBreak(nsISele
   *aCancel = false;
   *aHandled = false;
 
   // if the selection isn't collapsed, delete it.
   bool bCollapsed;
   nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
   NS_ENSURE_SUCCESS(res, res);
   if (!bCollapsed) {
-    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone);
+    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore result of WillInsert()
@@ -1814,21 +1815,24 @@ nsHTMLEditRules::SplitMailCites(nsISelec
     }
     *aHandled = true;
   }
   return NS_OK;
 }
 
 
 nsresult
-nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, 
-                                     nsIEditor::EDirection aAction, 
-                                     bool *aCancel,
-                                     bool *aHandled)
-{
+nsHTMLEditRules::WillDeleteSelection(nsISelection* aSelection,
+                                     nsIEditor::EDirection aAction,
+                                     nsIEditor::EStripWrappers aStripWrappers,
+                                     bool* aCancel,
+                                     bool* aHandled)
+{
+  MOZ_ASSERT(aStripWrappers == nsIEditor::eStrip ||
+             aStripWrappers == nsIEditor::eNoStrip);
 
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = false;
 
   // remember that we did a selection deletion.  Used by CreateStyleForInsertText()
   mDidDeleteSelection = true;
@@ -1983,17 +1987,18 @@ nsHTMLEditRules::WillDeleteSelection(nsI
               (wsType==nsWSRunObject::eBreak)    ||
               nsHTMLEditUtils::IsHR(visNode) ) 
     {
       // short circuit for invisible breaks.  delete them and recurse.
       if (nsTextEditUtils::IsBreak(visNode) && !mHTMLEditor->IsVisBreak(visNode))
       {
         res = mHTMLEditor->DeleteNode(visNode);
         NS_ENSURE_SUCCESS(res, res);
-        return WillDeleteSelection(aSelection, aAction, aCancel, aHandled);
+        return WillDeleteSelection(aSelection, aAction, aStripWrappers,
+                                   aCancel, aHandled);
       }
       
       // special handling for backspace when positioned after <hr>
       if (aAction == nsIEditor::ePrevious && nsHTMLEditUtils::IsHR(visNode))
       {
         /*
           Only if the caret is positioned at the end-of-hr-line position,
           we want to delete the <hr>.
@@ -2287,24 +2292,27 @@ nsHTMLEditRules::WillDeleteSelection(nsI
     nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
     res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
                                             address_of(startNode), &startOffset, 
                                             address_of(endNode), &endOffset);
     NS_ENSURE_SUCCESS(res, res); 
   }
   
   {
-    // track end location of where we are deleting
-    nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(endNode), &endOffset);
+    // track location of where we are deleting
+    nsAutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
+                                     address_of(startNode), &startOffset);
+    nsAutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
+                                   address_of(endNode), &endOffset);
     // we are handling all ranged deletions directly now.
     *aHandled = true;
     
     if (endNode == startNode)
     {
-      res = mHTMLEditor->DeleteSelectionImpl(aAction);
+      res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
       NS_ENSURE_SUCCESS(res, res); 
     }
     else
     {
       // figure out mailcite ancestors
       nsCOMPtr<nsIDOMNode> endCiteNode, startCiteNode;
       res = GetTopEnclosingMailCite(startNode, address_of(startCiteNode), 
                                     IsPlaintextEditor());
@@ -2334,17 +2342,17 @@ nsHTMLEditRules::WillDeleteSelection(nsI
       if (IsBlockNode(endNode))
         rightParent = endNode;
       else
         rightParent = mHTMLEditor->GetBlockNodeParent(endNode);
         
       // are endpoint block parents the same?  use default deletion
       if (leftParent == rightParent) 
       {
-        res = mHTMLEditor->DeleteSelectionImpl(aAction);
+        res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
       }
       else
       {
         // deleting across blocks
         // are the blocks of same type?
         NS_ENSURE_STATE(leftParent && rightParent);
         
         // are the blocks siblings?
@@ -2355,30 +2363,30 @@ nsHTMLEditRules::WillDeleteSelection(nsI
 
         // MOOSE: this could conceivably screw up a table.. fix me.
         if (   (leftBlockParent == rightBlockParent)
             && (mHTMLEditor->NodesSameType(leftParent, rightParent))  )
         {
           if (nsHTMLEditUtils::IsParagraph(leftParent))
           {
             // first delete the selection
-            res = mHTMLEditor->DeleteSelectionImpl(aAction);
+            res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
             NS_ENSURE_SUCCESS(res, res);
             // then join para's, insert break
             res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
             NS_ENSURE_SUCCESS(res, res);
             // fix up selection
             res = aSelection->Collapse(selNode,selOffset);
             return res;
           }
           if (nsHTMLEditUtils::IsListItem(leftParent)
               || nsHTMLEditUtils::IsHeader(leftParent))
           {
             // first delete the selection
-            res = mHTMLEditor->DeleteSelectionImpl(aAction);
+            res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
             NS_ENSURE_SUCCESS(res, res);
             // join blocks
             res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
             NS_ENSURE_SUCCESS(res, res);
             // fix up selection
             res = aSelection->Collapse(selNode,selOffset);
             return res;
           }
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -147,18 +147,20 @@ protected:
                             const nsAString *inString,
                             nsAString       *outString,
                             PRInt32          aMaxLength);
   nsresult WillLoadHTML(nsISelection *aSelection, bool *aCancel);
   nsresult WillInsertBreak(nsISelection *aSelection, bool *aCancel, bool *aHandled);
   nsresult StandardBreakImpl(nsIDOMNode *aNode, PRInt32 aOffset, nsISelection *aSelection);
   nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult);
   nsresult SplitMailCites(nsISelection *aSelection, bool aPlaintext, bool *aHandled);
-  nsresult WillDeleteSelection(nsISelection *aSelection, nsIEditor::EDirection aAction, 
-                               bool *aCancel, bool *aHandled);
+  nsresult WillDeleteSelection(nsISelection* aSelection,
+                               nsIEditor::EDirection aAction,
+                               nsIEditor::EStripWrappers aStripWrappers,
+                               bool* aCancel, bool* aHandled);
   nsresult DidDeleteSelection(nsISelection *aSelection, 
                               nsIEditor::EDirection aDir, 
                               nsresult aResult);
   nsresult InsertBRIfNeeded(nsISelection *aSelection);
   nsresult GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection aAction, 
                                   nsCOMPtr<nsIDOMNode> *outSelNode, PRInt32 *outSelOffset);
   nsresult JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, bool *aCanceled);
   nsresult MoveBlock(nsIDOMNode *aLeft, nsIDOMNode *aRight, PRInt32 aLeftOffset, PRInt32 aRightOffset);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1752,16 +1752,25 @@ nsHTMLEditor::InsertElementAtSelection(n
   ruleInfo.insertElement = aElement;
   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   if (cancel || (NS_FAILED(res))) return res;
 
   if (!handled)
   {
     if (aDeleteSelection)
     {
+      if (!IsBlockNode(aElement)) {
+        // E.g., inserting an image.  In this case we don't need to delete any
+        // inline wrappers before we do the insertion.  Otherwise we let
+        // DeleteSelectionAndPrepareToCreateNode do the deletion for us, which
+        // calls DeleteSelection with aStripWrappers = eStrip.
+        res = DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
+        NS_ENSURE_SUCCESS(res, res);
+      }
+
       nsCOMPtr<nsIDOMNode> tempNode;
       PRInt32 tempOffset;
       nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
       NS_ENSURE_SUCCESS(result, result);
     }
 
     // If deleting, selection will be collapsed.
     // so if not, we collapse it
@@ -3449,16 +3458,76 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupp
     iter->Next();
   }
 
   return rv;
 }
 
 
 NS_IMETHODIMP
+nsHTMLEditor::DeleteSelectionImpl(EDirection aAction,
+                                  EStripWrappers aStripWrappers)
+{
+  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+
+  nsresult res = nsEditor::DeleteSelectionImpl(aAction, aStripWrappers);
+  NS_ENSURE_SUCCESS(res, res);
+
+  // If we weren't asked to strip any wrappers, we're done.
+  if (aStripWrappers == eNoStrip) {
+    return NS_OK;
+  }
+
+  nsRefPtr<nsTypedSelection> typedSel = GetTypedSelection();
+  // Just checking that the selection itself is collapsed doesn't seem to work
+  // right in the multi-range case
+  NS_ENSURE_STATE(typedSel);
+  NS_ENSURE_STATE(typedSel->GetAnchorFocusRange());
+  NS_ENSURE_STATE(typedSel->GetAnchorFocusRange()->Collapsed());
+
+  nsCOMPtr<nsIContent> content = do_QueryInterface(typedSel->GetAnchorNode());
+  NS_ENSURE_STATE(content);
+
+  // Don't strip wrappers if this is the only wrapper in the block.  Then we'll
+  // add a <br> later, so it won't be an empty wrapper in the end.
+  nsCOMPtr<nsIContent> blockParent = content;
+  while (!IsBlockNode(blockParent)) {
+    blockParent = blockParent->GetParent();
+  }
+  bool emptyBlockParent;
+  res = IsEmptyNode(blockParent, &emptyBlockParent);
+  NS_ENSURE_SUCCESS(res, res);
+  if (emptyBlockParent) {
+    return NS_OK;
+  }
+
+  if (content && !IsBlockNode(content) && !content->Length() &&
+      content->IsEditable() && content != content->GetEditingHost()) {
+    while (content->GetParent() && !IsBlockNode(content->GetParent()) &&
+           content->GetParent()->Length() == 1 &&
+           content->GetParent()->IsEditable() &&
+           content->GetParent() != content->GetEditingHost()) {
+      content = content->GetParent();
+    }
+    res = DeleteNode(content);
+    NS_ENSURE_SUCCESS(res, res);
+  }
+
+  return NS_OK;
+}
+
+
+nsresult
+nsHTMLEditor::DeleteNode(nsINode* aNode)
+{
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
+  return DeleteNode(node);
+}
+
+NS_IMETHODIMP
 nsHTMLEditor::DeleteNode(nsIDOMNode* aNode)
 {
   // do nothing if the node is read-only
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   if (!IsModifiableNode(aNode) && !IsMozEditorBogusNode(content)) {
     return NS_ERROR_FAILURE;
   }
 
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -322,16 +322,19 @@ public:
                                          const nsAString & aAttribute,
                                          bool aSuppressTransaction);
 
   /** join together any afjacent editable text nodes in the range */
   NS_IMETHOD CollapseAdjacentTextNodes(nsIDOMRange *aInRange);
 
   virtual bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
 
+  NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
+                                 EStripWrappers aStripWrappers);
+  nsresult DeleteNode(nsINode* aNode);
   NS_IMETHODIMP DeleteNode(nsIDOMNode * aNode);
   NS_IMETHODIMP DeleteText(nsIDOMCharacterData *aTextNode,
                            PRUint32             aOffset,
                            PRUint32             aLength);
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                             nsCOMPtr<nsIDOMNode> *aInOutNode, 
                             PRInt32 *aInOutOffset,
                             nsIDOMDocument *aDoc);
--- a/editor/libeditor/html/nsHTMLEditorLog.cpp
+++ b/editor/libeditor/html/nsHTMLEditorLog.cpp
@@ -140,31 +140,32 @@ nsHTMLEditorLog::RemoveInlineProperty(ns
 
     Flush();
   }
 
   return nsHTMLEditor::RemoveInlineProperty(aProperty, aAttribute);
 }
 
 NS_IMETHODIMP
-nsHTMLEditorLog::DeleteSelection(nsIEditor::EDirection aAction)
+nsHTMLEditorLog::DeleteSelection(nsIEditor::EDirection aAction,
+                                 nsIEditor::EStripWrappers aStripWrappers)
 {
   nsAutoHTMLEditorLogLock logLock(this);
 
   if (!mLocked && mFileStream)
   {
     PrintSelection();
     Write("GetCurrentEditor().deleteSelection(");
     WriteInt(aAction);
     Write(");\n");
 
     Flush();
   }
 
-  return nsHTMLEditor::DeleteSelection(aAction);
+  return nsHTMLEditor::DeleteSelection(aAction, aStripWrappers);
 }
 
 NS_IMETHODIMP
 nsHTMLEditorLog::InsertText(const nsAString& aStringToInsert)
 {
   nsAutoHTMLEditorLogLock logLock(this);
 
   if (!mLocked && mFileStream)
--- a/editor/libeditor/html/nsHTMLEditorLog.h
+++ b/editor/libeditor/html/nsHTMLEditorLog.h
@@ -68,17 +68,18 @@ public:
   virtual ~nsHTMLEditorLog();
 
   /* nsIHTMLEditor method implementations. */
   NS_IMETHOD SetInlineProperty(nsIAtom *aProperty, 
                             const nsAString & aAttribute, 
                             const nsAString & aValue);
   NS_IMETHOD SetParagraphFormat(const nsAString& aParagraphFormat);
   NS_IMETHOD RemoveInlineProperty(nsIAtom *aProperty, const nsAString& aAttribute);
-  NS_IMETHOD DeleteSelection(nsIEditor::EDirection aAction);
+  NS_IMETHOD DeleteSelection(nsIEditor::EDirection aAction,
+                             nsIEditor::EStripWrappers aStripWrappers);
   NS_IMETHOD InsertText(const nsAString& aStringToInsert);
   NS_IMETHOD InsertLineBreak();
   NS_IMETHOD Undo(PRUint32 aCount);
   NS_IMETHOD Redo(PRUint32 aCount);
   NS_IMETHOD BeginTransaction();
   NS_IMETHOD EndTransaction();
   NS_IMETHOD SelectAll();
   NS_IMETHOD BeginningOfDocument();
--- a/editor/libeditor/html/nsTableEditor.cpp
+++ b/editor/libeditor/html/nsTableEditor.cpp
@@ -744,17 +744,17 @@ nsHTMLEditor::DeleteTable2(nsIDOMElement
   NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
 
   // Select the table
   nsresult res = ClearSelection();
   if (NS_SUCCEEDED(res))
     res = AppendNodeToSelectionAsRange(aTable);
   NS_ENSURE_SUCCESS(res, res);
 
-  return DeleteSelection(nsIEditor::eNext);
+  return DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::DeleteTable()
 {
   nsCOMPtr<nsISelection> selection;
   nsCOMPtr<nsIDOMElement> table;
   nsresult res = GetCellContext(getter_AddRefs(selection),
--- a/editor/libeditor/html/tests/browserscope/lib/richtext2/currentStatus.js
+++ b/editor/libeditor/html/tests/browserscope/lib/richtext2/currentStatus.js
@@ -963,18 +963,16 @@ const knownFailures = {
     "D-Proposed-CHAR-5_SR-body": true,
     "D-Proposed-CHAR-5_SR-div": true,
     "D-Proposed-CHAR-6_SC-dM": true,
     "D-Proposed-CHAR-6_SC-body": true,
     "D-Proposed-CHAR-6_SC-div": true,
     "D-Proposed-CHAR-7_SC-dM": true,
     "D-Proposed-CHAR-7_SC-body": true,
     "D-Proposed-CHAR-7_SC-div": true,
-    "D-Proposed-B-1_SW-dM": true,
-    "D-Proposed-B-1_SW-body": true,
     "D-Proposed-B-1_SW-div": true,
     "D-Proposed-B-1_SL-dM": true,
     "D-Proposed-B-1_SL-body": true,
     "D-Proposed-B-1_SL-div": true,
     "D-Proposed-B-1_SR-dM": true,
     "D-Proposed-B-1_SR-body": true,
     "D-Proposed-B-1_SR-div": true,
     "D-Proposed-B.I-1_SM-dM": true,
--- a/editor/libeditor/html/tests/test_bug460740.html
+++ b/editor/libeditor/html/tests/test_bug460740.html
@@ -103,21 +103,21 @@ function checkBR(element) {
 }
 
 function runTests() {
   var count = getBlockCount();
   var nodes = document.querySelectorAll("#content [contenteditable]");
   for (var i = 0; i < nodes.length; i++) {
     var node = nodes[i];
     node.focus();
-    is(checkBR(node), 0, "This node should not have any <br> element yet.");
+    is(checkBR(node), 0, node.textContent.trim() + ": This node should not have any <br> element yet.");
     for (var j = 0; j < 3; j++) { // CARET_BEGIN|MIDDLE|END
       split(node, j);
-      ok(checkBR(node) > 0, "Pressing [Return] should add (at least) one <br> element.");
-      is(getBlockCount(), count, "Pressing [Return] should not change the number of non-<br> elements.");
+      ok(checkBR(node) > 0, node.textContent.trim() + " " + j + ": Pressing [Return] should add (at least) one <br> element.");
+      is(getBlockCount(), count, node.textContent.trim() + " " + j + ": Pressing [Return] should not change the number of non-<br> elements.");
       document.execCommand("Undo", false, null);
     }
   }
   SimpleTest.finish();
 }
 </script>
 </pre>
 </body>
--- a/editor/libeditor/html/tests/test_bug668599.html
+++ b/editor/libeditor/html/tests/test_bug668599.html
@@ -55,17 +55,17 @@ function runTests() {
   span.focus();
   synthesizeKey("VK_DELETE", {});
   is(span.textContent, "", "The <span> content should have been deleted.");
 
   // <span> in editable block => the <span> *element* should be deleted
   select(document.querySelector("#test2 span"));
   document.querySelector("#test2 [contenteditable]").focus();
   synthesizeKey("VK_DELETE", {});
-  todo_is(document.querySelector("#test2 span"), null,
+  is(document.querySelector("#test2 span"), null,
     "The <span> element should have been deleted.");
 
   // done
   SimpleTest.finish();
 }
 
 </script>
 </pre>
--- a/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -104,17 +104,17 @@ nsresult nsPlaintextEditor::InsertTextAt
     nsCOMPtr<nsIDOMNode> targetNode = aDestinationNode;
     PRInt32 targetOffset = aDestOffset;
 
     if (aDoDeleteSelection)
     {
       // Use an auto tracker so that our drop point is correctly
       // positioned after the delete.
       nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
-      res = DeleteSelection(eNone);
+      res = DeleteSelection(eNone, eStrip);
       NS_ENSURE_SUCCESS(res, res);
     }
 
     res = selection->Collapse(targetNode, targetOffset);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   return InsertText(aStringToInsert);
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -548,17 +548,17 @@ nsPlaintextEditor::InsertBR(nsCOMPtr<nsI
   nsCOMPtr<nsISelection> selection;
   nsresult res = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   bool bCollapsed;
   res = selection->GetIsCollapsed(&bCollapsed);
   NS_ENSURE_SUCCESS(res, res);
   if (!bCollapsed)
   {
-    res = DeleteSelection(nsIEditor::eNone);
+    res = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
     NS_ENSURE_SUCCESS(res, res);
   }
   nsCOMPtr<nsIDOMNode> selNode;
   PRInt32 selOffset;
   res = GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, res);
   
   res = CreateBR(selNode, selOffset, outBRNode);
@@ -734,18 +734,22 @@ nsPlaintextEditor::ExtendSelectionForDel
       default:       // avoid several compiler warnings
         result = NS_OK;
         break;
     }
   }
   return result;
 }
 
-NS_IMETHODIMP nsPlaintextEditor::DeleteSelection(nsIEditor::EDirection aAction)
+nsresult
+nsPlaintextEditor::DeleteSelection(EDirection aAction,
+                                   EStripWrappers aStripWrappers)
 {
+  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+
   if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
 
   // Protect the edit rules object from dying
   nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
 
   nsresult result;
 
   HandlingTrustedAction trusted(this, aAction != eNone);
@@ -780,22 +784,23 @@ NS_IMETHODIMP nsPlaintextEditor::DeleteS
     else
     { 
       aAction = eNone;
     }
   }
 
   nsTextRulesInfo ruleInfo(kOpDeleteSelection);
   ruleInfo.collapsedAction = aAction;
+  ruleInfo.stripWrappers = aStripWrappers;
   bool cancel, handled;
   result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   NS_ENSURE_SUCCESS(result, result);
   if (!cancel && !handled)
   {
-    result = DeleteSelectionImpl(aAction);
+    result = DeleteSelectionImpl(aAction, aStripWrappers);
   }
   if (!cancel)
   {
     // post-process 
     result = mRules->DidDoAction(selection, &ruleInfo, result);
   }
 
   return result;
@@ -1286,17 +1291,17 @@ nsPlaintextEditor::FireClipboardEvent(PR
   return !mDidPreDestroy;
 }
 
 NS_IMETHODIMP nsPlaintextEditor::Cut()
 {
   HandlingTrustedAction trusted(this);
 
   if (FireClipboardEvent(NS_CUT))
-    return DeleteSelection(eNone);
+    return DeleteSelection(eNone, eStrip);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPlaintextEditor::CanCut(bool *aCanCut)
 {
   NS_ENSURE_ARG_POINTER(aCanCut);
   *aCanCut = IsModifiable() && CanCutOrCopy();
   return NS_OK;
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -97,17 +97,18 @@ public:
                                          bool aSuppressTransaction);
 
   /** prepare the editor for use */
   NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot, nsISelectionController *aSelCon, PRUint32 aFlags);
   
   NS_IMETHOD GetDocumentIsEmpty(bool *aDocumentIsEmpty);
   NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable);
 
-  NS_IMETHOD DeleteSelection(EDirection aAction);
+  NS_IMETHOD DeleteSelection(EDirection aAction,
+                             EStripWrappers aStripWrappers);
 
   NS_IMETHOD SetDocumentCharacterSet(const nsACString & characterSet);
 
   NS_IMETHOD Undo(PRUint32 aCount);
   NS_IMETHOD Redo(PRUint32 aCount);
 
   NS_IMETHOD Cut();
   NS_IMETHOD CanCut(bool *aCanCut);
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -405,17 +405,17 @@ nsTextEditRules::WillInsertBreak(nsISele
     *aCancel = false;
 
     // if the selection isn't collapsed, delete it.
     bool bCollapsed;
     res = aSelection->GetIsCollapsed(&bCollapsed);
     NS_ENSURE_SUCCESS(res, res);
     if (!bCollapsed)
     {
-      res = mEditor->DeleteSelection(nsIEditor::eNone);
+      res = mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
       NS_ENSURE_SUCCESS(res, res);
     }
 
     res = WillInsert(aSelection, aCancel);
     NS_ENSURE_SUCCESS(res, res);
     // initialize out param
     // we want to ignore result of WillInsert()
     *aCancel = false;
@@ -633,17 +633,17 @@ nsTextEditRules::WillInsertText(nsEditor
   }
 
   // if the selection isn't collapsed, delete it.
   bool bCollapsed;
   res = aSelection->GetIsCollapsed(&bCollapsed);
   NS_ENSURE_SUCCESS(res, res);
   if (!bCollapsed)
   {
-    res = mEditor->DeleteSelection(nsIEditor::eNone);
+    res = mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
@@ -873,17 +873,17 @@ nsTextEditRules::WillDeleteSelection(nsI
     res = CheckBidiLevelForDeletion(aSelection, startNode, startOffset, aCollapsedAction, aCancel);
     NS_ENSURE_SUCCESS(res, res);
     if (*aCancel) return NS_OK;
 
     res = mEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction);
     NS_ENSURE_SUCCESS(res, res);
   }
 
-  res = mEditor->DeleteSelectionImpl(aCollapsedAction);
+  res = mEditor->DeleteSelectionImpl(aCollapsedAction, nsIEditor::eStrip);
   NS_ENSURE_SUCCESS(res, res);
 
   *aHandled = true;
   ASSERT_PASSWORD_LENGTHS_EQUAL()
   return NS_OK;
 }
 
 nsresult
--- a/editor/libeditor/text/nsTextEditRules.h
+++ b/editor/libeditor/text/nsTextEditRules.h
@@ -270,16 +270,17 @@ class nsTextRulesInfo : public nsRulesIn
  
   nsTextRulesInfo(nsEditor::OperationID aAction) :
     nsRulesInfo(aAction),
     inString(0),
     outString(0),
     outputFormat(0),
     maxLength(-1),
     collapsedAction(nsIEditor::eNext),
+    stripWrappers(nsIEditor::eStrip),
     bOrdered(false),
     entireList(false),
     bulletType(0),
     alignType(0),
     blockType(0),
     insertElement(0)
     {}
 
@@ -288,16 +289,17 @@ class nsTextRulesInfo : public nsRulesIn
   // kInsertText
   const nsAString *inString;
   nsAString *outString;
   const nsAString *outputFormat;
   PRInt32 maxLength;
   
   // kDeleteSelection
   nsIEditor::EDirection collapsedAction;
+  nsIEditor::EStripWrappers stripWrappers;
   
   // kMakeList
   bool bOrdered;
   bool entireList;
   const nsAString *bulletType;
 
   // kAlign
   const nsAString *alignType;
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -1372,17 +1372,17 @@ nsTextServicesDocument::DeleteSelection(
   }
 
   // Make sure mIterator always points to something valid!
 
   AdjustContentIterator();
 
   // Now delete the actual content!
 
-  result = editor->DeleteSelection(nsIEditor::ePrevious);
+  result = editor->DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
 
   if (NS_FAILED(result))
   {
     UNLOCK_DOC(this);
     return result;
   }
 
   // Now that we've actually deleted the selected content,
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -827,17 +827,17 @@ mozInlineSpellChecker::ReplaceWord(nsIDO
   {
     editor->BeginTransaction();
   
     nsCOMPtr<nsISelection> selection;
     res = editor->GetSelection(getter_AddRefs(selection));
     NS_ENSURE_SUCCESS(res, res);
     selection->RemoveAllRanges();
     selection->AddRange(range);
-    editor->DeleteSelection(nsIEditor::eNone);
+    editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
 
     nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryReferent(mEditor));
     textEditor->InsertText(newword);
 
     editor->EndTransaction();
   }
 
   return NS_OK;