Bug 1465875 part 1. Eliminate pointless QIs to nsIDOMNSEditableElement. r=qdot
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 01 Jun 2018 22:35:22 -0400
changeset 421073 3ef0eb8cbf3bade62d66cc607bcc28c043188100
parent 421072 d50a8eb8c327a69f4f25108b62cfa2f3230a18ba
child 421074 7c9969cf727a3885d25453de55101f56134a4a49
push id64789
push userapavel@mozilla.com
push dateSun, 03 Jun 2018 04:27:54 +0000
treeherderautoland@15b13a9f6e91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1465875
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465875 part 1. Eliminate pointless QIs to nsIDOMNSEditableElement. r=qdot We expose the relevant APIs on textarea and input elements anyway (chromeonly). The QIs will throw on a non-input or non-textarea element, but none of these consumers expect that to happen.
accessible/tests/mochitest/events/test_textattrchange.html
browser/base/content/nsContextMenu.js
dom/tests/mochitest/chrome/queryCaretRectUnix.html
dom/tests/mochitest/chrome/queryCaretRectWin.html
editor/libeditor/tests/test_bug1053048.html
editor/libeditor/tests/test_bug1230473.html
editor/libeditor/tests/test_bug471319.html
editor/libeditor/tests/test_bug602130.html
editor/libeditor/tests/test_bug830600.html
editor/libeditor/tests/test_composition_event_created_in_chrome.html
editor/spellchecker/tests/test_bug1200533.html
editor/spellchecker/tests/test_bug1204147.html
editor/spellchecker/tests/test_bug1205983.html
editor/spellchecker/tests/test_bug1209414.html
editor/spellchecker/tests/test_bug678842.html
editor/spellchecker/tests/test_bug697981.html
editor/spellchecker/tests/test_bug717433.html
layout/base/tests/bug585922-ref.html
layout/base/tests/bug585922.html
layout/base/tests/chrome/test_bug504311.xul
layout/forms/test/bug477700_subframe.html
layout/forms/test/test_bug595310.html
layout/generic/test/test_selection_preventDefault.html
mobile/android/modules/ActionBarHandler.jsm
mobile/android/modules/FormAssistant.jsm
mobile/android/tests/browser/robocop/robocop_input.html
toolkit/content/widgets/menulist.xml
toolkit/content/widgets/textbox.xml
toolkit/modules/InlineSpellCheckerContent.jsm
widget/tests/window_composition_text_querycontent.xul
--- a/accessible/tests/mochitest/events/test_textattrchange.html
+++ b/accessible/tests/mochitest/events/test_textattrchange.html
@@ -19,30 +19,27 @@
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
 
-    const nsIDOMNSEditableElement =
-      Ci.nsIDOMNSEditableElement;
-
     ChromeUtils.import("resource://gre/modules/InlineSpellChecker.jsm");
 
     function spelledTextInvoker(aID) {
       this.DOMNode = getNode(aID);
 
       this.eventSeq = [
         new invokerChecker(EVENT_TEXT_ATTRIBUTE_CHANGED, this.DOMNode)
       ];
 
       this.invoke = function spelledTextInvoker_invoke() {
-        var editor = this.DOMNode.QueryInterface(nsIDOMNSEditableElement).editor;
+        var editor = this.DOMNode.editor;
         var spellChecker = new InlineSpellChecker(editor);
         spellChecker.enabled = true;
 
         // var spellchecker = editor.getInlineSpellChecker(true);
         // spellchecker.enableRealTimeSpell = true;
 
         this.DOMNode.value = "valid text inalid tixt";
       };
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -248,17 +248,17 @@ nsContextMenu.prototype = {
     this.inWebExtBrowser   = !!this.webExtBrowserType;
     this.inTabBrowser      = this.browser.ownerGlobal.gBrowser ?
       !!this.browser.ownerGlobal.gBrowser.getTabForBrowser(this.browser) : false;
 
     if (context.shouldInitInlineSpellCheckerUINoChildren) {
       if (this.isRemote) {
         InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
       } else {
-        InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
+        InlineSpellCheckerUI.init(this.target.editor);
         InlineSpellCheckerUI.initFromEvent(document.popupRangeParent,
                                            document.popupRangeOffset);
       }
     }
 
     if (context.shouldInitInlineSpellCheckerUIWithChildren) {
       if (this.isRemote) {
         InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
--- a/dom/tests/mochitest/chrome/queryCaretRectUnix.html
+++ b/dom/tests/mochitest/chrome/queryCaretRectUnix.html
@@ -59,21 +59,18 @@
       var e = document.createElement("div");
       e.setAttribute("id", "div-ver");
       e.style.left = (idx*20) + "px";
       document.getElementById("container").appendChild(e);
     }
   }
 
   function getSelection(aElement) {
-    if (aElement instanceof Ci.nsIDOMNSEditableElement) {
-      return aElement.QueryInterface(Ci.nsIDOMNSEditableElement)
-                     .editor.selection;
-    }
-    return null;
+    // aElement is known to be a textarea here.
+    return aElement.editor.selection;
   }
 
   function testCaretPosition(aDomWinUtils, aOffset, aRectDims) {
     let rect = aDomWinUtils.sendQueryContentEvent(
                  aDomWinUtils.QUERY_CARET_RECT,
                  aOffset, 0, 0, 0,
                  aDomWinUtils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
     ok(rect, "rect returned");
--- a/dom/tests/mochitest/chrome/queryCaretRectWin.html
+++ b/dom/tests/mochitest/chrome/queryCaretRectWin.html
@@ -68,21 +68,18 @@
       var e = document.createElement("div");
       e.setAttribute("id", "div-ver");
       e.style.left = (idx*20) + "px";
       document.getElementById("container").appendChild(e);
     }
   }
 
   function getSelection(aElement) {
-    if (aElement instanceof Ci.nsIDOMNSEditableElement) {
-      return aElement.QueryInterface(Ci.nsIDOMNSEditableElement)
-                     .editor.selection;
-    }
-    return null;
+    // aElement is know to be a textarea.
+    return aElement.editor.selection;
   }
 
   function testCaretPosition(aDomWinUtils, aOffset, aRectDims) {
     let rect = aDomWinUtils.sendQueryContentEvent(
                  aDomWinUtils.QUERY_CARET_RECT,
                  aOffset, 0, 0, 0,
                  aDomWinUtils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
     ok(rect, "rect returned");
--- a/editor/libeditor/tests/test_bug1053048.html
+++ b/editor/libeditor/tests/test_bug1053048.html
@@ -11,24 +11,23 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" href="/tests/SimpleTest/test.css">
   <script type="application/javascript">
 
   /** Test for Bug 1053048 **/
   SimpleTest.waitForExplicitFinish();
   SimpleTest.waitForFocus(runTests);
 
   const nsISelectionListener = SpecialPowers.Ci.nsISelectionListener;
-  const nsIDOMNSEditableElement = SpecialPowers.Ci.nsIDOMNSEditableElement;
 
   function runTests()
   {
     var textarea = SpecialPowers.wrap(document.getElementById("textarea"));
     textarea.focus();
 
-    var editor = textarea.QueryInterface(nsIDOMNSEditableElement).editor;
+    var editor = textarea.editor;
     var selectionPrivate = editor.selection;
 
     var selectionListener = {
       count: 0,
       notifySelectionChanged: function (aDocument, aSelection, aReason)
       {
         ok(true, "selectionStart: " + textarea.selectionStart);
         ok(true, "selectionEnd: " + textarea.selectionEnd);
--- a/editor/libeditor/tests/test_bug1230473.html
+++ b/editor/libeditor/tests/test_bug1230473.html
@@ -27,17 +27,16 @@ SimpleTest.waitForFocus(()=>{
     function isNSEditableElement() {
       return aEditor.tagName.toLowerCase() == "input" || aEditor.tagName.toLowerCase() == "textarea";
     }
     function value() {
       return isNSEditableElement() ? aEditor.value : aEditor.textContent;
     }
     function isComposing() {
       return isNSEditableElement() ?  SpecialPowers.wrap(aEditor)
-                                                   .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
                                                    .editor
                                                    .composing :
                                       SpecialPowers.wrap(window)
                                                    .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
                                                    .getInterface(SpecialPowers.Ci.nsIWebNavigation)
                                                    .QueryInterface(SpecialPowers.Ci.nsIDocShell)
                                                    .editor
                                                    .composing;
--- a/editor/libeditor/tests/test_bug471319.html
+++ b/editor/libeditor/tests/test_bug471319.html
@@ -27,28 +27,26 @@ https://bugzilla.mozilla.org/show_bug.cg
       SimpleTest.waitForExplicitFinish();
 
       function doTest() {
         let t1 = SpecialPowers.wrap($("t1"));
         let editor = null;
 
         // Test 1: Undo on an empty editor - the editor should not forget about
         // the bogus node
-        t1.QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
         t1Editor = t1.editor;
 
         // Did the editor recognize the new bogus node?
         t1Editor.undo(1);
         ok(!t1.value, "<br> still recognized as bogus node on undo");
 
 
         // Test 2: Redo on an empty editor - the editor should not forget about
         // the bogus node
         let t2 = SpecialPowers.wrap($("t2"));
-        t2.QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
         t2Editor = t2.editor;
 
         // Did the editor recognize the new bogus node?
         t2Editor.redo(1);
         ok(!t2.value, "<br> still recognized as bogus node on redo");
 
 
         // Test 3: Undoing a batched transaction where both end points of the
--- a/editor/libeditor/tests/test_bug602130.html
+++ b/editor/libeditor/tests/test_bug602130.html
@@ -18,17 +18,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 
 /** Test for Bug 602130 **/
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var i = document.createElement("input");
   document.body.appendChild(i);
-  SpecialPowers.wrap(i).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
   i.select();
   i.focus();
   is(SpecialPowers.wrap(i).editor.transactionManager.numberOfUndoItems, 0,
      "The number of undo items should be 0 after initing the editor");
   i.style.display = "none";
   document.offsetWidth;
   i.style.display = "";
   document.offsetWidth;
--- a/editor/libeditor/tests/test_bug830600.html
+++ b/editor/libeditor/tests/test_bug830600.html
@@ -23,17 +23,16 @@ https://bugzilla.mozilla.org/show_bug.cg
     <script type="application/javascript">
 
       /** Test for Bug 830600 **/
       SimpleTest.waitForExplicitFinish();
       SimpleTest.waitForFocus(function() {
         const Ci = SpecialPowers.Ci;
         function test(str, expected, callback) {
           var t = document.getElementById("t1");
-          SpecialPowers.wrap(t).QueryInterface(Ci.nsIDOMNSEditableElement);
           t.focus();
           t.value = "";
           var editor = SpecialPowers.wrap(t).editor;
           editor.QueryInterface(Ci.nsIPlaintextEditor);
           var origNewlineHandling = editor.newlineHandling;
           editor.newlineHandling = Ci.nsIPlaintextEditor.eNewlinesStripSurroundingWhitespace
           SimpleTest.waitForClipboard(str,
             function() {
--- a/editor/libeditor/tests/test_composition_event_created_in_chrome.html
+++ b/editor/libeditor/tests/test_composition_event_created_in_chrome.html
@@ -17,18 +17,17 @@
 // In nsEditorEventListener, when listening event is not created with proper
 // event interface, it asserts the fact.
 SimpleTest.waitForExplicitFinish();
 
 var gInputElement = document.getElementById("input");
 
 function getEditor(aInputElement)
 {
-  var editableElement = SpecialPowers.wrap(aInputElement).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
-  ok(editableElement, "The input element doesn't have nsIDOMNSEditableElement interface");
+  var editableElement = SpecialPowers.wrap(aInputElement);
   ok(editableElement.editor, "There is no editor for the input element");
   return editableElement.editor;
 }
 
 var gEditor;
 
 function testNotGenerateCompositionByCreatedEvents(aEventInterface)
 {
--- a/editor/spellchecker/tests/test_bug1200533.html
+++ b/editor/spellchecker/tests/test_bug1200533.html
@@ -92,17 +92,17 @@ var loadListener = function(evt) {
 
   SpecialPowers.pushPrefEnv({set: [["spellchecker.dictionary", tests[loadCount][1]]]},
                             function() { continueTest(evt) });
 }
 
 function continueTest(evt) {
   var doc = evt.target.contentDocument;
   var elem = doc.getElementById(tests[loadCount][0]);
-  var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  var editor = SpecialPowers.wrap(elem).editor;
   editor.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor.getInlineSpellChecker(true);
 
   SpecialPowers.Cu.import(
     "resource://testing-common/AsyncSpellCheckTestHelper.jsm")
   .onSpellCheck(elem, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
--- a/editor/spellchecker/tests/test_bug1204147.html
+++ b/editor/spellchecker/tests/test_bug1204147.html
@@ -58,17 +58,17 @@ var loadListener = function(evt) {
   var doc = evt.target.contentDocument;
   var elem;
   if (firstLoad) {
     elem = doc.getElementById('en-GB');
   } else {
     elem = doc.getElementById('en-US');
   }
 
-  var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  var editor = SpecialPowers.wrap(elem).editor;
   editor.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor.getInlineSpellChecker(true);
 
   SpecialPowers.Cu.import(
     "resource://testing-common/AsyncSpellCheckTestHelper.jsm")
   .onSpellCheck(elem, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
--- a/editor/spellchecker/tests/test_bug1205983.html
+++ b/editor/spellchecker/tests/test_bug1205983.html
@@ -82,17 +82,16 @@ function deFocus() {
     document.getElementById('en-US').focus();
   });
 }
 
 function enFocus() {
   var elem_en = document.getElementById('en-US');
   var editor_en =
     SpecialPowers.wrap(elem_en)
-                 .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
                  .editor;
   editor_en.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor_en.getInlineSpellChecker(true);
 
   onSpellCheck(elem_en, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
       currentDictonary = spellchecker.GetCurrentDictionary();
--- a/editor/spellchecker/tests/test_bug1209414.html
+++ b/editor/spellchecker/tests/test_bug1209414.html
@@ -89,18 +89,17 @@ SimpleTest.waitForFocus(function() {
   });
   is(script.sendSyncMessage("contextMenu-not-null")[0][0], true,
      "Got context menu XUL");
   is(script.sendSyncMessage("de_DE-exists")[0][0], true,
      "true expected (de_DE directory should exist)");
   script.addMessageListener("popupshown", handlePopup);
 
   elem_de = document.getElementById('de-DE');
-  editor_de = SpecialPowers.wrap(elem_de)
-                           .QueryInterface(Ci.nsIDOMNSEditableElement).editor;
+  editor_de = SpecialPowers.wrap(elem_de).editor;
   editor_de.setSpellcheckUserOverride(true);
 
   onSpellCheck(elem_de, function () {
     var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
       var currentDictonary = spellchecker.GetCurrentDictionary();
     } catch(e) {}
--- a/editor/spellchecker/tests/test_bug678842.html
+++ b/editor/spellchecker/tests/test_bug678842.html
@@ -51,17 +51,17 @@ var loadListener = function(evt) {
       addMessageListener("destroy", () => hunspell.removeDirectory(en_GB));
     });
     is(script.sendSyncMessage("en_GB-exists")[0][0], true,
        "true expected (en-GB directory should exist)");
   }
 
   var doc = evt.target.contentDocument;
   var elem = doc.getElementById('textarea');
-  var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  var editor = SpecialPowers.wrap(elem).editor;
   editor.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor.getInlineSpellChecker(true);
 
   SpecialPowers.Cu.import(
     "resource://testing-common/AsyncSpellCheckTestHelper.jsm")
   .onSpellCheck(elem, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
--- a/editor/spellchecker/tests/test_bug697981.html
+++ b/editor/spellchecker/tests/test_bug697981.html
@@ -58,17 +58,17 @@ SimpleTest.waitForFocus(function() {
   is(script.sendSyncMessage("de_DE-exists")[0][0], true,
      "true expected (de_DE directory should exist)");
 
   document.getElementById('de-DE').focus();
 });
 
 function deFocus() {
   elem_de = document.getElementById('de-DE');
-  editor_de = SpecialPowers.wrap(elem_de).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  editor_de = SpecialPowers.wrap(elem_de).editor;
   editor_de.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
 
   onSpellCheck(elem_de, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
       var currentDictonary = spellchecker.GetCurrentDictionary();
     } catch(e) {}
@@ -79,17 +79,17 @@ function deFocus() {
 
     // Now focus the other textarea, which requires English spelling.
     document.getElementById('en-US').focus();
   });
 }
 
 function enFocus() {
   var elem_en = document.getElementById('en-US');
-  var editor_en = SpecialPowers.wrap(elem_en).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  var editor_en = SpecialPowers.wrap(elem_en).editor;
   editor_en.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor_en.getInlineSpellChecker(true);
 
   onSpellCheck(elem_en, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
       currentDictonary = spellchecker.GetCurrentDictionary();
     } catch(e) {}
--- a/editor/spellchecker/tests/test_bug717433.html
+++ b/editor/spellchecker/tests/test_bug717433.html
@@ -53,17 +53,17 @@ var loadListener = function(evt) {
       addMessageListener("destroy", () => hunspell.removeDirectory(en_GB));
     });
     is(script.sendSyncMessage("en_GB-exists")[0][0], true,
        "true expected (en-GB directory should exist)");
   }
 
   var doc = evt.target.contentDocument;
   var elem = doc.getElementById('textarea');
-  var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+  var editor = SpecialPowers.wrap(elem).editor;
   editor.setSpellcheckUserOverride(true);
   var inlineSpellChecker = editor.getInlineSpellChecker(true);
 
   SpecialPowers.Cu.import(
     "resource://testing-common/AsyncSpellCheckTestHelper.jsm")
   .onSpellCheck(elem, function () {
     var spellchecker = inlineSpellChecker.spellChecker;
     try {
--- a/layout/base/tests/bug585922-ref.html
+++ b/layout/base/tests/bug585922-ref.html
@@ -5,17 +5,17 @@
   </head>
   <body onload="doTest()">
     <input type=text style="-moz-appearance: none">
     <script>
       function doTest() {
         var d = document.querySelector("input");
         d.value = "b";
         d.focus();
-        var editor = SpecialPowers.wrap(d).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+        var editor = SpecialPowers.wrap(d).editor;
         var sel = editor.selection;
         var t = editor.rootElement.firstChild;
         sel.collapse(t, 1); // put the caret at the end of the textbox
         document.documentElement.removeAttribute("class");
       }
     </script>
   </body>
 </html>
--- a/layout/base/tests/bug585922.html
+++ b/layout/base/tests/bug585922.html
@@ -10,17 +10,17 @@
         function enableCaret(aEnable) {
           var selCon = editor.selectionController;
           selCon.setCaretEnabled(aEnable);
         }
 
         var d = document.querySelector("input");
         d.value = "a";
         d.focus();
-        var editor = SpecialPowers.wrap(d).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+        var editor = SpecialPowers.wrap(d).editor;
         var sel = editor.selection;
         var t = editor.rootElement.firstChild;
         sel.collapse(t, 1); // put the caret at the end of the div
         setTimeout(function() {
           enableCaret(false);enableCaret(true);// force a caret display
           enableCaret(false); // hide the caret
           t.replaceData(0, 1, "b"); // replace the text node data
           // at this point, the selection is collapsed to offset 0
--- a/layout/base/tests/chrome/test_bug504311.xul
+++ b/layout/base/tests/chrome/test_bug504311.xul
@@ -18,17 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
 function doTest()
 {
   var tb = document.getElementById("tb01");
   var inputField = tb.inputField;
-  var editor = inputField.QueryInterface(Ci.nsIDOMNSEditableElement).editor;
+  var editor = inputField.editor;
   editor = editor.QueryInterface(Ci.nsIPlaintextEditor);
   editor.wrapWidth = -1;
 
   ok(true, "Didn't crash");
   SimpleTest.finish();
 }
 ]]></script>
 <textbox id="tb01" multiline="true"/>
--- a/layout/forms/test/bug477700_subframe.html
+++ b/layout/forms/test/bug477700_subframe.html
@@ -14,21 +14,21 @@
       window.addEventListener("message",
         function(evt) {
           doIs(evt.data, "start", "Unexpected message");
           $("target").focus();
           sendString("Test");
           var t = $("target");
           doIs(t.value, "Test", "Typing should work");
           (function() {
-            SpecialPowers.wrap(t).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor.undo(1);
+            SpecialPowers.wrap(t).editor.undo(1);
           })()
           doIs(t.value, "", "Undo should work");
           (function() {
-            SpecialPowers.wrap(t).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor.redo(1);
+            SpecialPowers.wrap(t).editor.redo(1);
           })()
           doIs(t.value, "Test", "Redo should work");
           window.parent.postMessage("f", "*");
         },
         "false");
       
     </script>
   </head>
--- a/layout/forms/test/test_bug595310.html
+++ b/layout/forms/test/test_bug595310.html
@@ -38,17 +38,16 @@ addLoadEvent(function() {
   // Note: one call would have been enough actually but I didn't want to favour
   // one element... ;)
   i.getBoundingClientRect();
   t.getBoundingClientRect();
 
   function synthesizeDropText(aElement, aText)
   {
     var editor = SpecialPowers.wrap(aElement)
-                              .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
                               .editor
                               .QueryInterface(SpecialPowers.Ci.nsIPlaintextEditor);
 
     editor.insertText(aText);
   }
 
   // We insert "bar" and we should only see "bar" now.
   synthesizeDropText(i, "bar");
--- a/layout/generic/test/test_selection_preventDefault.html
+++ b/layout/generic/test/test_selection_preventDefault.html
@@ -35,20 +35,17 @@ dddddd dddddd dddddd
 
 var fixedDiv1 = document.getElementById("fixedDiv1");
 var input = document.getElementById("input");
 
 function test()
 {
   function getSelectionForEditor(aEditorElement)
   {
-    const nsIDOMNSEditableElement =
-      SpecialPowers.Ci.nsIDOMNSEditableElement;
-    return SpecialPowers.wrap(aEditorElement)
-             .QueryInterface(nsIDOMNSEditableElement).editor.selection;
+    return SpecialPowers.wrap(aEditorElement).editor.selection;
   }
 
   function clear()
   {
     var sel = window.getSelection();
     if (sel.rangeCount > 0)
       sel.collapseToEnd();
     sel = getSelectionForEditor(input);
--- a/mobile/android/modules/ActionBarHandler.jsm
+++ b/mobile/android/modules/ActionBarHandler.jsm
@@ -752,43 +752,52 @@ var ActionBarHandler = {
       return selection.toStringWithFormat("text/plain", flags, 0);
     }
 
     // Return explicitly selected text.
     return selection.toString();
   },
 
   /**
+   * Tests whether a given element is editable.
+   */
+  _isElementEditable: function(element) {
+    let elementClass = ChromeUtils.getClassName(element);
+    return elementClass === "HTMLInputElement" ||
+           elementClass === "HTMLTextAreaElement";
+  },
+
+  /**
    * Provides the Selection for either an editor, or from the
    * default window.
    */
   _getSelection: function(element = this._targetElement, win = this._contentWindow) {
-    return (element instanceof Ci.nsIDOMNSEditableElement) ?
+    return this._isElementEditable(element) ?
       this._getEditor(element).selection :
       win.getSelection();
   },
 
   /**
    * Returns an nsEditor or nsHTMLEditor.
    */
   _getEditor: function(element = this._targetElement, win = this._contentWindow) {
-    if (element instanceof Ci.nsIDOMNSEditableElement) {
-      return element.QueryInterface(Ci.nsIDOMNSEditableElement).editor;
+    if (this._isElementEditable(element)) {
+      return element.editor;
     }
 
     return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).
                QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIEditingSession).
                getEditorForWindow(win);
   },
 
   /**
    * Returns a selection controller.
    */
   _getSelectionController: function(element = this._targetElement, win = this._contentWindow) {
-    if (element instanceof Ci.nsIDOMNSEditableElement) {
+    if (this._isElementEditable(element)) {
       return this._getEditor(element, win).selectionController;
     }
 
     return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).
                QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).
                QueryInterface(Ci.nsISelectionController);
   },
 
--- a/mobile/android/modules/FormAssistant.jsm
+++ b/mobile/android/modules/FormAssistant.jsm
@@ -25,28 +25,27 @@ var FormAssistant = {
 
   init: function() {
     Services.obs.addObserver(this, "PanZoom:StateChange");
   },
 
   _onPopupResponse: function(currentElement, message) {
     switch (message.action) {
       case "autocomplete": {
-        let editableElement = currentElement.QueryInterface(Ci.nsIDOMNSEditableElement);
         this._doingAutocomplete = true;
 
         // If we have an active composition string, commit it before sending
         // the autocomplete event with the text that will replace it.
         try {
-          if (editableElement.editor.composing) {
-            editableElement.editor.forceCompositionEnd();
+          if (currentElement.editor.composing) {
+            currentElement.editor.forceCompositionEnd();
           }
         } catch (e) {}
 
-        editableElement.setUserInput(message.value);
+        currentElement.setUserInput(message.value);
 
         let event = currentElement.ownerDocument.createEvent("Events");
         event.initEvent("DOMAutoComplete", true, true);
         currentElement.dispatchEvent(event);
 
         this._doingAutocomplete = false;
         break;
       }
--- a/mobile/android/tests/browser/robocop/robocop_input.html
+++ b/mobile/android/tests/browser/robocop/robocop_input.html
@@ -99,33 +99,31 @@
           return parent;
         }
         return editor.document;
       }
 
       let test = {
         focus_input: function(value) {
           getEditor = function() {
-            return SpecialPowers.wrap(input).QueryInterface(
-                SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+            return SpecialPowers.wrap(input).editor;
           };
           setValue = function(val) {
             input.value = val;
           };
           setSelection = function(pos) {
             input.setSelectionRange(pos, pos);
           };
           setValue(value);
           input.focus();
         },
 
         focus_text_area: function(value) {
           getEditor = function() {
-            return SpecialPowers.wrap(textArea).QueryInterface(
-                SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
+            return SpecialPowers.wrap(textArea).editor;
           };
           setValue = function(val) {
             textArea.value = val;
           };
           setSelection = function(pos) {
             textArea.setSelectionRange(pos, pos);
           };
           setValue(value);
--- a/toolkit/content/widgets/menulist.xml
+++ b/toolkit/content/widgets/menulist.xml
@@ -479,18 +479,17 @@
       </property>
       <property name="disableautoselect"
                 onset="if (val) this.setAttribute('disableautoselect','true');
                        else this.removeAttribute('disableautoselect'); return val;"
                 onget="return this.hasAttribute('disableautoselect');"/>
 
       <property name="editor" readonly="true">
         <getter><![CDATA[
-          const nsIDOMNSEditableElement = Ci.nsIDOMNSEditableElement;
-          return this.inputField.QueryInterface(nsIDOMNSEditableElement).editor;
+          return this.inputField.editor;
         ]]></getter>
       </property>
 
       <property name="readOnly"   onset="this.inputField.readOnly = val;
                                          if (val) this.setAttribute('readonly', 'true');
                                          else this.removeAttribute('readonly'); return val;"
                                   onget="return this.inputField.readOnly;"/>
 
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -86,18 +86,17 @@
       <property name="clickSelectsAll"
                 onget="return this.getAttribute('clickSelectsAll') == 'true';"
                 onset="if (val) this.setAttribute('clickSelectsAll', 'true');
                        else this.removeAttribute('clickSelectsAll'); return val;" />
 
       <property name="editor" readonly="true">
         <getter><![CDATA[
           if (!this.mEditor) {
-            const nsIDOMNSEditableElement = Ci.nsIDOMNSEditableElement;
-            this.mEditor = this.inputField.QueryInterface(nsIDOMNSEditableElement).editor;
+            this.mEditor = this.inputField.editor;
           }
           return this.mEditor;
         ]]></getter>
       </property>
 
       <method name="reset">
         <body><![CDATA[
           this.value = this.defaultValue;
--- a/toolkit/modules/InlineSpellCheckerContent.jsm
+++ b/toolkit/modules/InlineSpellCheckerContent.jsm
@@ -25,17 +25,17 @@ var InlineSpellCheckerContent = {
                               .getInterface(Ci.nsIWebNavigation)
                               .QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIEditingSession);
       spellChecker = this._spellChecker =
         new InlineSpellChecker(editingSession.getEditorForWindow(win));
     } else {
       // Use the element's editor.
       spellChecker = this._spellChecker =
-        new InlineSpellChecker(event.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
+        new InlineSpellChecker(event.target.editor);
     }
 
     this._spellChecker.initFromEvent(event.rangeParent, event.rangeOffset);
 
     this._addMessageListeners();
 
     if (!spellChecker.canSpellCheck) {
       return { canSpellCheck: false,
--- a/widget/tests/window_composition_text_querycontent.xul
+++ b/widget/tests/window_composition_text_querycontent.xul
@@ -110,33 +110,32 @@ var iframe = document.getElementById("if
 var iframe2 = document.getElementById("iframe2");
 var iframe3 = document.getElementById("iframe3");
 var contenteditable;
 var windowOfContenteditable;
 var input = document.getElementById("input");
 var textareaInFrame;
 
 const nsITextInputProcessorCallback = Ci.nsITextInputProcessorCallback;
-const nsIDOMNSEditableElement = Ci.nsIDOMNSEditableElement;
 const nsIInterfaceRequestor = Ci.nsIInterfaceRequestor;
 const nsIWebNavigation = Ci.nsIWebNavigation;
 const nsIDocShell = Ci.nsIDocShell;
 
 function hitEventLoop(aFunc, aTimes)
 {
   if (--aTimes) {
     setTimeout(hitEventLoop, 0, aFunc, aTimes);
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
 function getEditor(aNode)
 {
-  return aNode.QueryInterface(nsIDOMNSEditableElement).editor;
+  return aNode.editor;
 }
 
 function getHTMLEditorIMESupport(aWindow)
 {
   return aWindow.QueryInterface(nsIInterfaceRequestor).
                  getInterface(nsIWebNavigation).
                  QueryInterface(nsIDocShell).
                  editor;