Bug 1519953, replace calls to retrieve boxobject position and size with getBoundingClientRect, r=gijs
authorNeil Deakin <neil@mozilla.com>
Fri, 01 Mar 2019 12:26:45 -0500
changeset 519980 aa8dea3c0f43
parent 519979 1178c5fddda7
child 519981 bc5daa250f8a
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs
bugs1519953
milestone67.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 1519953, replace calls to retrieve boxobject position and size with getBoundingClientRect, r=gijs
accessible/tests/mochitest/events.js
accessible/tests/mochitest/events/test_label.xul
accessible/tests/mochitest/hittest/test_zoom_tree.xul
browser/base/content/browser-sidebar.js
browser/base/content/sanitizeDialog.js
browser/base/content/tabbrowser.xml
browser/base/content/test/general/browser_tab_dragdrop2_frame1.xul
browser/base/content/test/permissions/browser_temporary_permissions.js
browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
browser/base/content/test/popupNotifications/browser_popupNotification.js
browser/base/content/test/popupNotifications/browser_popupNotification_2.js
browser/base/content/test/popupNotifications/browser_popupNotification_3.js
browser/base/content/test/popupNotifications/browser_popupNotification_no_anchors.js
browser/base/content/test/popupNotifications/head.js
browser/base/content/utilityOverlay.js
browser/components/customizableui/PanelMultiView.jsm
browser/components/extensions/ExtensionPopups.jsm
browser/components/places/content/bookmarkProperties.js
browser/components/places/content/menu.xml
browser/components/places/content/places-tree.js
devtools/client/shared/widgets/VariablesView.jsm
dom/tests/mochitest/chrome/test_bug1224790-1.xul
dom/tests/mochitest/chrome/test_bug1224790-2.xul
layout/base/crashtests/526378-1.xul
layout/xul/crashtests/399013.xul
layout/xul/test/test_bug393970.xul
layout/xul/test/test_splitter.xul
toolkit/content/tests/chrome/test_arrowpanel.xul
toolkit/content/tests/chrome/test_bug624329.xul
toolkit/content/tests/chrome/test_mousescroll.xul
toolkit/content/tests/chrome/test_popupremoving.xul
toolkit/content/tests/chrome/test_popupremoving_frame.xul
toolkit/content/tests/chrome/test_position.xul
toolkit/content/tests/widgets/tree_shared.js
toolkit/content/widgets/notificationbox.js
toolkit/content/widgets/popup.xml
toolkit/content/widgets/scrollbox.xml
toolkit/content/widgets/tree.js
toolkit/modules/PopupNotifications.jsm
toolkit/mozapps/extensions/content/extensions.js
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -1099,17 +1099,17 @@ function synthClick(aNodeOrID, aCheckerO
       targetAcc.scrollTo(SCROLL_TYPE_ANYWHERE);
     }
 
     var x = 1, y = 1;
     if (aArgs && ("where" in aArgs) && aArgs.where == "right") {
       if (isHTMLElement(targetNode)) {
         x = targetNode.offsetWidth - 1;
       } else if (isXULElement(targetNode)) {
-        x = targetNode.boxObject.width - 1;
+        x = targetNode.getBoundingClientRect().width - 1;
       }
     }
     synthesizeMouse(targetNode, x, y, aArgs ? aArgs : {});
   };
 
   this.finalCheck = function synthClick_finalCheck() {
     // Scroll top window back.
     window.top.scrollTo(0, 0);
--- a/accessible/tests/mochitest/events/test_label.xul
+++ b/accessible/tests/mochitest/events/test_label.xul
@@ -80,17 +80,17 @@
     }
 
     /**
      * Change @crop attribute.
      */
     function setCrop(aID, aCropValue, aRemovedText, aInsertedText)
     {
       this.labelNode = getNode(aID);
-      this.width = this.labelNode.boxObject.width;
+      this.width = this.labelNode.getBoundingClientRect().width;
       this.charWidth = this.width / this.labelNode.value.length;
 
       this.eventSeq = [
         new textChangeChecker(this.labelNode, 0, -1, aRemovedText, false),
         new textChangeChecker(this.labelNode, 0, -1, aInsertedText, true)
       ];
 
       this.invoke = function setCrop_invoke()
--- a/accessible/tests/mochitest/hittest/test_zoom_tree.xul
+++ b/accessible/tests/mochitest/hittest/test_zoom_tree.xul
@@ -33,25 +33,25 @@
       var tree = tabDocument.getElementById("tree");
       var treecols = tabDocument.getElementById("treecols");
       var treecol1 = tabDocument.getElementById("treecol1");
 
       // tree columns
       hitTest(tree, treecols, treecol1);
 
       // tree rows and cells
-      var treeBodyBoxObj = tree.treeBody.boxObject;
+      var treeRect = tree.treeBody.getBoundingClientRect();
       var rect = tree.getCoordsForCellItem(1, tree.columns[0], "cell");
 
       var treeAcc = getAccessible(tree, [nsIAccessibleTable]);
       var cellAcc = treeAcc.getCellAt(1, 0);
       var rowAcc = cellAcc.parent;
 
-      var cssX = rect.x + treeBodyBoxObj.x;
-      var cssY = rect.y + treeBodyBoxObj.y;
+      var cssX = rect.x + treeRect.x;
+      var cssY = rect.y + treeRect.y;
       var [x, y] = CSSToDevicePixels(tabWindow, cssX, cssY);
 
       testChildAtPoint(treeAcc, x, y, rowAcc, cellAcc);
       testChildAtPoint(rowAcc, x, y, cellAcc, cellAcc);
 
       // do zoom
       zoomDocument(tabDocument, 1.5);
 
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -240,17 +240,17 @@ var SidebarUI = {
     }
 
     // dynamically generated sidebars will fail this check, but we still
     // consider it adopted.
     if (!this.sidebars.has(commandID)) {
       return true;
     }
 
-    this._box.setAttribute("width", sourceUI._box.boxObject.width);
+    this._box.setAttribute("width", sourceUI._box.getBoundingClientRect().width);
     this.showInitially(commandID);
 
     return true;
   },
 
   windowPrivacyMatches(w1, w2) {
     return PrivateBrowsingUtils.isWindowPrivate(w1) === PrivateBrowsingUtils.isWindowPrivate(w2);
   },
--- a/browser/base/content/sanitizeDialog.js
+++ b/browser/base/content/sanitizeDialog.js
@@ -72,25 +72,25 @@ var gSanitizePromptDialog = {
 
     var warningBox = this.warningBox;
 
     // If clearing everything
     if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) {
       this.prepareWarning();
       if (warningBox.hidden) {
         warningBox.hidden = false;
-        window.resizeBy(0, warningBox.boxObject.height);
+        window.resizeBy(0, warningBox.getBoundingClientRect().height);
       }
       document.l10n.setAttributes(document.documentElement, "dialog-title-everything");
       return;
     }
 
     // If clearing a specific time range
     if (!warningBox.hidden) {
-      window.resizeBy(0, -warningBox.boxObject.height);
+      window.resizeBy(0, -warningBox.getBoundingClientRect().height);
       warningBox.hidden = true;
     }
     document.l10n.setAttributes(document.documentElement, "dialog-title");
   },
 
   sanitize() {
     // Update pref values before handing off to the sanitizer (bug 453440)
     this.updatePrefs();
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -632,17 +632,17 @@
           let rightTab = tabs[tabs.length - 1];
           let rightMovingTabScreenX = movingTabs[movingTabs.length - 1].screenX;
           let leftMovingTabScreenX = movingTabs[0].screenX;
           let translateX = screenX - draggedTab._dragData.screenX;
           if (!pinned) {
             translateX += this.arrowScrollbox.scrollbox.scrollLeft - draggedTab._dragData.scrollX;
           }
           let leftBound = leftTab.screenX - leftMovingTabScreenX;
-          let rightBound = (rightTab.screenX + rightTab.boxObject.width) -
+          let rightBound = (rightTab.screenX + rightTab.getBoundingClientRect().width) -
                            (rightMovingTabScreenX + tabWidth);
           translateX = Math.min(Math.max(translateX, leftBound), rightBound);
 
           for (let tab of movingTabs) {
             tab.style.transform = "translateX(" + translateX + "px)";
           }
 
           draggedTab._dragData.translateX = translateX;
@@ -791,17 +791,17 @@
             let movingTabOldIndex = movingTab._tPos;
 
             if (movingTabOldIndex == movingTabNewIndex) {
               // movingTab is already at the right position
               // and thus don't need to be animated.
               return;
             }
 
-            let movingTabWidth = movingTab.boxObject.width;
+            let movingTabWidth = movingTab.getBoundingClientRect().width;
             let shift = (movingTabNewIndex - movingTabOldIndex) * movingTabWidth;
 
             movingTab.groupingTabsData.animate = true;
             movingTab.setAttribute("tab-grouping", "true");
 
             movingTab.groupingTabsData.translateX = shift;
 
             let onTransitionEnd = transitionendEvent => {
@@ -991,38 +991,38 @@
       </method>
 
       <method name="_getDragTargetTab">
         <parameter name="event"/>
         <parameter name="isLink"/>
         <body><![CDATA[
           let tab = event.target.localName == "tab" ? event.target : null;
           if (tab && isLink) {
-            let boxObject = tab.boxObject;
-            if (event.screenX < tab.screenX + boxObject.width * .25 ||
-                event.screenX > tab.screenX + boxObject.width * .75)
+            let {width} = tab.getBoundingClientRect();
+            if (event.screenX < tab.screenX + width * .25 ||
+                event.screenX > tab.screenX + width * .75)
               return null;
           }
           return tab;
         ]]></body>
       </method>
 
       <method name="_getDropIndex">
         <parameter name="event"/>
         <parameter name="isLink"/>
         <body><![CDATA[
           var tabs = this.children;
           var tab = this._getDragTargetTab(event, isLink);
           if (!RTL_UI) {
             for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
-              if (event.screenX < tabs[i].screenX + tabs[i].boxObject.width / 2)
+              if (event.screenX < tabs[i].screenX + tabs[i].getBoundingClientRect().width / 2)
                 return i;
           } else {
             for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
-              if (event.screenX > tabs[i].screenX + tabs[i].boxObject.width / 2)
+              if (event.screenX > tabs[i].screenX + tabs[i].getBoundingClientRect().width / 2)
                 return i;
           }
           return tabs.length;
         ]]></body>
       </method>
 
       <method name="_getDropEffectForTabDrag">
         <parameter name="event"/>
--- a/browser/base/content/test/general/browser_tab_dragdrop2_frame1.xul
+++ b/browser/base/content/test/general/browser_tab_dragdrop2_frame1.xul
@@ -63,17 +63,17 @@ function nextTest()
   SimpleTest.waitForFocus(() => currentTest.test(panel));
   return i;
 }
 
 function popupShown(event)
 {
   var panel = event.target;
   if (waitSteps > 0 && navigator.platform.includes("Linux") &&
-      panel.boxObject.screenY == 210) {
+      panel.screenY == 210) {
     waitSteps--;
     setTimeout(popupShown, 10, event);
     return;
   }
   ++i;
 
   currentTest.result(currentTest.testname + " ", panel);
   panel.hidePopup();
--- a/browser/base/content/test/permissions/browser_temporary_permissions.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions.js
@@ -19,21 +19,21 @@ add_task(async function testTempPermissi
 
     Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
     let geoIcon = document.querySelector(".blocked-permission-icon[data-permission-id=geo]");
 
-    Assert.notEqual(geoIcon.boxObject.width, 0, "geo anchor should be visible");
+    Assert.notEqual(geoIcon.getBoundingClientRect().width, 0, "geo anchor should be visible");
 
     SitePermissions.remove(uri, id, browser);
 
-    Assert.equal(geoIcon.boxObject.width, 0, "geo anchor should not be visible");
+    Assert.equal(geoIcon.getBoundingClientRect().width, 0, "geo anchor should not be visible");
   });
 });
 
 // Test that temp blocked permissions requested by subframes (with a different URI) affect the whole page.
 add_task(async function testTempPermissionSubframes() {
   let uri = NetUtil.newURI(ORIGIN);
   let id = "geo";
 
--- a/browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
@@ -48,19 +48,19 @@ add_task(async function testTempPermissi
 
   Assert.deepEqual(SitePermissions.get(uri, id, tab1.linkedBrowser), {
     state: SitePermissions.UNKNOWN,
     scope: SitePermissions.SCOPE_PERSISTENT,
   });
 
   let geoIcon = document.querySelector(".blocked-permission-icon[data-permission-id=geo]");
 
-  Assert.notEqual(geoIcon.boxObject.width, 0, "geo anchor should be visible");
+  Assert.notEqual(geoIcon.getBoundingClientRect().width, 0, "geo anchor should be visible");
 
   await BrowserTestUtils.switchTab(gBrowser, tab1);
 
-  Assert.equal(geoIcon.boxObject.width, 0, "geo anchor should not be visible");
+  Assert.equal(geoIcon.getBoundingClientRect().width, 0, "geo anchor should not be visible");
 
   SitePermissions.remove(uri, id, tab2.linkedBrowser);
   BrowserTestUtils.removeTab(tab1);
   BrowserTestUtils.removeTab(tab2);
 });
 
--- a/browser/base/content/test/popupNotifications/browser_popupNotification.js
+++ b/browser/base/content/test/popupNotifications/browser_popupNotification.js
@@ -257,17 +257,17 @@ var tests = [
       this.notifyObj2.id += "-2";
       this.notifyObj2.anchorID = "addons-notification-icon";
       // Second showNotification() overrides the first
       this.secondNotification = showNotification(this.notifyObj2);
     },
     onShown(popup) {
       // This also checks that only one element is shown.
       checkPopup(popup, this.notifyObj2);
-      is(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      is(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
          "geo anchor shouldn't be visible");
       dismissNotification(popup);
     },
     onHidden(popup) {
       // Remove the notifications
       this.firstNotification.remove();
       this.secondNotification.remove();
       ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
--- a/browser/base/content/test/popupNotifications/browser_popupNotification_2.js
+++ b/browser/base/content/test/popupNotifications/browser_popupNotification_2.js
@@ -34,26 +34,26 @@ var tests = [
     run() {
       this.notifyObj = new BasicNotification(this.id);
       this.notifyObj.id = "geolocation";
       this.notifyObj.anchorID = "geo-notification-icon";
       this.notification = showNotification(this.notifyObj);
     },
     onShown(popup) {
       checkPopup(popup, this.notifyObj);
-      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
             "geo anchor should be visible");
       dismissNotification(popup);
     },
     onHidden(popup) {
       let icon = document.getElementById("geo-notification-icon");
-      isnot(icon.boxObject.width, 0,
+      isnot(icon.getBoundingClientRect().width, 0,
             "geo anchor should be visible after dismissal");
       this.notification.remove();
-      is(icon.boxObject.width, 0,
+      is(icon.getBoundingClientRect().width, 0,
          "geo anchor should not be visible after removal");
     },
   },
 
   // Test that persistence allows the notification to persist across reloads
   { id: "Test#3",
     async run() {
       this.oldSelectedTab = gBrowser.selectedTab;
@@ -173,31 +173,31 @@ var tests = [
   { id: "Test#7",
     async run() {
       let notifyObj = new BasicNotification(this.id);
       notifyObj.anchorID = "geo-notification-icon";
       notifyObj.addOptions({neverShow: true});
       let promiseTopic = TestUtils.topicObserved("PopupNotifications-updateNotShowing");
       showNotification(notifyObj);
       await promiseTopic;
-      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
             "geo anchor should be visible");
       goNext();
     },
   },
   // Test that autoplay media icon is shown
   { id: "Test#8",
     async run() {
       let notifyObj = new BasicNotification(this.id);
       notifyObj.anchorID = "autoplay-media-notification-icon";
       notifyObj.addOptions({neverShow: true});
       let promiseTopic = TestUtils.topicObserved("PopupNotifications-updateNotShowing");
       showNotification(notifyObj);
       await promiseTopic;
-      isnot(document.getElementById("autoplay-media-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("autoplay-media-notification-icon").getBoundingClientRect().width, 0,
             "autoplay media icon should be visible");
       goNext();
     },
   },
   // Test notification close button
   { id: "Test#9",
     run() {
       this.notifyObj = new BasicNotification(this.id);
--- a/browser/base/content/test/popupNotifications/browser_popupNotification_3.js
+++ b/browser/base/content/test/popupNotifications/browser_popupNotification_3.js
@@ -43,20 +43,20 @@ var tests = [
       this.notifyObj2.id += "_2";
       this.notifyObj2.anchorID = "geo-notification-icon";
       this.notification2 = showNotification(this.notifyObj2);
     },
     onShown(popup) {
       checkPopup(popup, this.notifyObj2);
 
       // check notifyObj1 anchor icon is showing
-      isnot(document.getElementById("default-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("default-notification-icon").getBoundingClientRect().width, 0,
             "default anchor should be visible");
       // check notifyObj2 anchor icon is showing
-      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
             "geo anchor should be visible");
 
       dismissNotification(popup);
     },
     onHidden(popup) {
       this.notification1.remove();
       ok(this.notifyObj1.removedCallbackTriggered, "removed callback triggered");
 
@@ -80,20 +80,20 @@ var tests = [
       this.notifyObjNew = new BasicNotification(this.id);
       this.notifyObjNew.anchorID = "geo-notification-icon";
       this.notificationNew = showNotification(this.notifyObjNew);
     },
     onShown(popup) {
       checkPopup(popup, this.notifyObjNew);
 
       // check notifyObjOld anchor icon is removed
-      is(document.getElementById("default-notification-icon").boxObject.width, 0,
+      is(document.getElementById("default-notification-icon").getBoundingClientRect().width, 0,
          "default anchor shouldn't be visible");
       // check notifyObjNew anchor icon is showing
-      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
             "geo anchor should be visible");
 
       dismissNotification(popup);
     },
     onHidden(popup) {
       this.notificationNew.remove();
       gBrowser.removeTab(gBrowser.selectedTab);
 
--- a/browser/base/content/test/popupNotifications/browser_popupNotification_no_anchors.js
+++ b/browser/base/content/test/popupNotifications/browser_popupNotification_no_anchors.js
@@ -20,17 +20,17 @@ var tests = [
       await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
       this.notifyObj = new BasicNotification(this.id);
       this.notifyObj.anchorID = "geo-notification-icon";
       this.notification = showNotification(this.notifyObj);
     },
     onShown(popup) {
       checkPopup(popup, this.notifyObj);
-      is(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      is(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
          "geo anchor shouldn't be visible");
       is(popup.anchorNode.id, "identity-icon",
          "notification anchored to identity icon");
       dismissNotification(popup);
     },
     onHidden(popup) {
       this.notification.remove();
       gBrowser.removeTab(gBrowser.selectedTab);
@@ -50,17 +50,17 @@ var tests = [
         persistence: 1,
       });
       this.notification = showNotification(this.notifyObj);
     },
     async onShown(popup) {
       await promiseTabLoadEvent(gBrowser.selectedTab, "about:blank");
 
       checkPopup(popup, this.notifyObj);
-      is(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      is(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
          "geo anchor shouldn't be visible");
       is(popup.anchorNode.id, "identity-icon",
          "notification anchored to identity icon");
       dismissNotification(popup);
     },
     onHidden(popup) {
       this.notification.remove();
       gBrowser.removeTab(gBrowser.selectedTab);
@@ -77,22 +77,22 @@ var tests = [
       this.notifyObj = new BasicNotification(this.id);
       this.notifyObj.anchorID = "geo-notification-icon";
       this.notifyObj.addOptions({
         dismissed: true,
         persistence: 1,
       });
       this.notification = showNotification(this.notifyObj);
 
-      is(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      is(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
          "geo anchor shouldn't be visible");
 
       await promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
 
-      isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
+      isnot(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
             "geo anchor should be visible");
 
       EventUtils.synthesizeMouse(document.getElementById("geo-notification-icon"), 2, 2, {});
     },
     onShown(popup) {
       checkPopup(popup, this.notifyObj);
       dismissNotification(popup);
     },
@@ -118,17 +118,17 @@ var tests = [
         checkPopup(PopupNotifications.panel, this.notifyObj);
 
         // Typing in the location bar should hide the notification.
         let hidden = waitForNotificationPanelHidden();
         gURLBar.select();
         EventUtils.sendString("*");
         await hidden;
 
-        is(document.getElementById("geo-notification-icon").boxObject.width, 0,
+        is(document.getElementById("geo-notification-icon").getBoundingClientRect().width, 0,
            "geo anchor shouldn't be visible");
 
         // Moving focus to the next control should show the notifications again,
         // anchored to the identity icon. We clear the URL bar before moving the
         // focus so that the awesomebar popup doesn't get in the way.
         shown = waitForNotificationPanel();
         EventUtils.synthesizeKey("KEY_Backspace");
         EventUtils.synthesizeKey("KEY_Tab");
--- a/browser/base/content/test/popupNotifications/head.js
+++ b/browser/base/content/test/popupNotifications/head.js
@@ -180,17 +180,17 @@ function checkPopup(popup, notifyObj) {
 
   let notifications = popup.childNodes;
   is(notifications.length, 1, "one notification displayed");
   let notification = notifications[0];
   if (!notification)
     return;
   let icon = notification.querySelector(".popup-notification-icon");
   if (notifyObj.id == "geolocation") {
-    isnot(icon.boxObject.width, 0, "icon for geo displayed");
+    isnot(icon.getBoundingClientRect().width, 0, "icon for geo displayed");
     ok(popup.anchorNode.classList.contains("notification-anchor-icon"),
        "notification anchored to icon");
   }
 
   let description = notifyObj.message.split("<>");
   let text = {};
   text.start = description[0];
   text.end = description[1];
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -962,18 +962,18 @@ function buildHelpMenu() {
 }
 
 function isElementVisible(aElement) {
   if (!aElement)
     return false;
 
   // If aElement or a direct or indirect parent is hidden or collapsed,
   // height, width or both will be 0.
-  var bo = aElement.boxObject;
-  return (bo.height > 0 && bo.width > 0);
+  var rect = aElement.getBoundingClientRect();
+  return (rect.height > 0 && rect.width > 0);
 }
 
 function makeURLAbsolute(aBase, aUrl) {
   // Note:  makeURI() will throw if aUri is not a valid URI
   return makeURI(aUrl, null, makeURI(aBase)).spec;
 }
 
 /**
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -1053,33 +1053,33 @@ var PanelMultiView = class extends Assoc
   }
 
   _calculateMaxHeight() {
     // While opening the panel, we have to limit the maximum height of any
     // view based on the space that will be available. We cannot just use
     // window.screen.availTop and availHeight because these may return an
     // incorrect value when the window spans multiple screens.
     let anchor = this._panel.anchorNode;
-    let anchorBox = anchor.boxObject;
+    let anchorRect = anchor.getBoundingClientRect();
 
     let screen = this._screenManager.screenForRect(anchor.screenX,
                                                    anchor.screenY,
-                                                   anchorBox.width,
-                                                   anchorBox.height);
+                                                   anchorRect.width,
+                                                   anchorRect.height);
     let availTop = {}, availHeight = {};
     screen.GetAvailRect({}, availTop, {}, availHeight);
     let cssAvailTop = availTop.value / screen.defaultCSSScaleFactor;
 
     // The distance from the anchor to the available margin of the screen is
     // based on whether the panel will open towards the top or the bottom.
     let maxHeight;
     if (this._panel.alignmentPosition.startsWith("before_")) {
       maxHeight = anchor.screenY - cssAvailTop;
     } else {
-      let anchorScreenBottom = anchor.screenY + anchorBox.height;
+      let anchorScreenBottom = anchor.screenY + anchorRect.height;
       let cssAvailHeight = availHeight.value / screen.defaultCSSScaleFactor;
       maxHeight = cssAvailTop + cssAvailHeight - anchorScreenBottom;
     }
 
     // To go from the maximum height of the panel to the maximum height of
     // the view stack, we need to subtract the height of the arrow and the
     // height of the opposite margin, but we cannot get their actual values
     // because the panel is not visible yet. However, we know that this is
--- a/browser/components/extensions/ExtensionPopups.jsm
+++ b/browser/components/extensions/ExtensionPopups.jsm
@@ -544,17 +544,17 @@ class ViewPopup extends BasePopup {
       // menu panel. Use that to calculate the how much the sub-view may grow.
       let popupRect = panel.getBoundingClientRect();
       let screenBottom = win.screen.availTop + win.screen.availHeight;
       let popupBottom = win.mozInnerScreenY + popupRect.bottom;
       let popupTop = win.mozInnerScreenY + popupRect.top;
 
       // Store the initial height of the view, so that we never resize menu panel
       // sub-views smaller than the initial height of the menu.
-      this.viewHeight = viewNode.boxObject.height;
+      this.viewHeight = viewNode.getBoundingClientRect().height;
 
       this.extraHeight = {
         bottom: Math.max(0, screenBottom - popupBottom),
         top:  Math.max(0, popupTop - win.screen.availTop),
       };
     });
 
     // Create a new browser in the real popup.
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -259,17 +259,17 @@ var BookmarkPropertiesPanel = {
         let wasCollapsed = mutation.oldValue === "true";
         if (collapsed == wasCollapsed)
           continue;
 
         if (collapsed) {
           this._height -= elementsHeight.get(id);
           elementsHeight.delete(id);
         } else {
-          elementsHeight.set(id, target.boxObject.height);
+          elementsHeight.set(id, target.getBoundingClientRect().height);
           this._height += elementsHeight.get(id);
         }
         window.resizeTo(window.outerWidth, this._height);
       }
     });
 
     this._mutationObserver.observe(document,
                                    { subtree: true,
@@ -333,17 +333,17 @@ var BookmarkPropertiesPanel = {
             target.id == "editBMPanel_keywordField") {
           // Check uri fields to enable accept button if input is valid
           document.documentElement
                   .getButton("accept").disabled = !this._inputIsValid();
         }
         break;
       case "resize":
         for (let [id, oldHeight] of elementsHeight) {
-          let newHeight = document.getElementById(id).boxObject.height;
+          let newHeight = document.getElementById(id).getBoundingClientRect().height;
           this._height += -oldHeight + newHeight;
           elementsHeight.set(id, newHeight);
         }
         break;
     }
   },
 
   // nsISupports
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -79,21 +79,25 @@
 
             // The element we are dragging over
             let elt = aEvent.target;
             if (elt.localName == "menupopup")
               elt = elt.parentNode;
 
             // Calculate positions taking care of arrowscrollbox
             let scrollbox = this._scrollBox;
-            let eventY = aEvent.layerY + (scrollbox.boxObject.y - this.boxObject.y);
-            let scrollboxOffset = scrollbox.scrollBoxObject.y -
-                                  (scrollbox.boxObject.y - this.boxObject.y);
-            let eltY = elt.boxObject.y - scrollboxOffset;
-            let eltHeight = elt.boxObject.height;
+
+            let thisY = this.getBoundingClientRect().y;
+            let scrollboxY = scrollbox.getBoundingClientRect().y;
+            let innerScrollboxY = scrollbox.scrollbox.getBoundingClientRect().y;
+
+            let eventY = aEvent.layerY + (scrollboxY - thisY);
+            let scrollboxOffset = innerScrollboxY - (scrollboxY - thisY);
+            let {y: eltY, height: eltHeight} = elt.getBoundingClientRect();
+            eltY -= scrollboxOffset;
 
             if (!elt._placesNode) {
               // If we are dragging over a non places node drop at the end.
               dropPoint.ip = new PlacesInsertionPoint({
                 parentId: PlacesUtils.getConcreteItemId(resultNode),
                 parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
               });
               // We can set folderElt if we are dropping over a static menu that
@@ -429,31 +433,31 @@
         if (dropPoint.folderElt || this._hideDropIndicator(event)) {
           this._indicatorBar.hidden = true;
           event.preventDefault();
           event.stopPropagation();
           return;
         }
 
         // We should display the drop indicator relative to the arrowscrollbox.
-        let scrollbox = this._scrollBox.scrollBoxObject;
+        let scrollRect = this._scrollBox.scrollbox.getBoundingClientRect();
         let newMarginTop = 0;
         if (scrollDir == 0) {
           let elt = this.firstElementChild;
           while (elt && event.screenY > elt.screenY +
-                                        elt.boxObject.height / 2)
+                                        elt.getBoundingClientRect().height / 2)
             elt = elt.nextElementSibling;
           newMarginTop = elt ? elt.screenY - this._scrollBox.screenY :
-                               scrollbox.height;
+                               scrollRect.height;
         } else if (scrollDir == 1) {
-          newMarginTop = scrollbox.height;
+          newMarginTop = scrollRect.height;
         }
 
         // Set the new marginTop based on arrowscrollbox.
-        newMarginTop += scrollbox.y - this._scrollBox.boxObject.y;
+        newMarginTop += scrollRect.y - this._scrollBox.getBoundingClientRect().y;
         this._indicatorBar.firstElementChild.style.marginTop = newMarginTop + "px";
         this._indicatorBar.hidden = false;
 
         event.preventDefault();
         event.stopPropagation();
       ]]></handler>
 
       <handler event="dragexit"><![CDATA[
--- a/browser/components/places/content/places-tree.js
+++ b/browser/components/places/content/places-tree.js
@@ -76,17 +76,17 @@
           this.view.nodeForTreeIndex(cell.row) :
           this.result.root;
         // cache the dropTarget for the view
         PlacesControllerDragHelper.currentDropTarget = node;
 
         // We have to calculate the orientation since view.canDrop will use
         // it and we want to be consistent with the dropfeedback.
         let rowHeight = this.rowHeight;
-        let eventY = event.clientY - this.treeBody.boxObject.y -
+        let eventY = event.clientY - this.treeBody.getBoundingClientRect().y -
           rowHeight * (cell.row - this.getFirstVisibleRow());
 
         let orientation = Ci.nsITreeView.DROP_BEFORE;
 
         if (cell.row == -1) {
           // If the row is not valid we try to insert inside the resultNode.
           orientation = Ci.nsITreeView.DROP_ON;
         } else if (PlacesUtils.nodeIsContainer(node) &&
--- a/devtools/client/shared/widgets/VariablesView.jsm
+++ b/devtools/client/shared/widgets/VariablesView.jsm
@@ -967,24 +967,16 @@ VariablesView.prototype = {
       this._parent.removeAttribute("actions-first");
     }
   },
 
   /**
    * Gets the parent node holding this view.
    * @return Node
    */
-  get boxObject() {
-    return this._list.boxObject;
-  },
-
-  /**
-   * Gets the parent node holding this view.
-   * @return Node
-   */
   get parentNode() {
     return this._parent;
   },
 
   /**
    * Gets the owner document holding this view.
    * @return nsIHTMLDocument
    */
--- a/dom/tests/mochitest/chrome/test_bug1224790-1.xul
+++ b/dom/tests/mochitest/chrome/test_bug1224790-1.xul
@@ -32,18 +32,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   var timer = null;
   function gotFocus() {
     var button = document.getElementById('button');
     synthesizeMouseAtCenter(button, { type: 'mousemove' }, window);
     function click() {
       // The bug is not reproducible with synthesizeMouseAtCenter.
       // Need to emulate native mouse event.
-      synthesizeNativeOSXClick(button.screenX + button.boxObject.width / 2,
-                               button.screenY + button.boxObject.height / 2);
+      synthesizeNativeOSXClick(button.screenX + button.getBoundingClientRect().width / 2,
+                               button.screenY + button.getBoundingClientRect().height / 2);
     }
     click();
     // On debug build, it's possible that the click event handler is not
     // triggered by the first click in case the click is dispatched too early
     // before Firefox gets ready for input.
     // Click the button again after 1 sec when we don't get click event.
     timer = setTimeout(click, 1000);
   }
--- a/dom/tests/mochitest/chrome/test_bug1224790-2.xul
+++ b/dom/tests/mochitest/chrome/test_bug1224790-2.xul
@@ -33,18 +33,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   var timer = null;
   function gotFocus() {
     var button = document.getElementById('button');
     synthesizeMouseAtCenter(button, { type: 'mousemove' }, window);
     function click() {
       // The bug is not reproducible with synthesizeMouseAtCenter.
       // Need to emulate native mouse event.
-      synthesizeNativeOSXClick(button.screenX + button.boxObject.width / 2,
-                               button.screenY + button.boxObject.height / 2);
+      synthesizeNativeOSXClick(button.screenX + button.getBoundingClientRect().width / 2,
+                               button.screenY + button.getBoundingClientRect().height / 2);
     }
     click();
     // On debug build, it's possible that the click event handler is not
     // triggered by the first click in case the click is dispatched too early
     // before Firefox gets ready for input.
     // Click the button again after 1 sec when we don't get click event.
     timer = setTimeout(click, 1000);
   }
--- a/layout/base/crashtests/526378-1.xul
+++ b/layout/base/crashtests/526378-1.xul
@@ -8,17 +8,17 @@
 
 function boom()
 {
   var x = document.getElementById("x");
   
   x.appendChild(document.createTextNode("A"));
   x.appendChild(document.createTextNode("\u202B" + "C"));
 
-  document.getBoxObjectFor(document.documentElement).height; // flush layout
+  document.documentElement.clientHeight; // flush layout
 
   x.normalize();
   x.appendChild(document.createTextNode("D"));
 }
 
 window.addEventListener("load", boom, false);
 
 ]]>
--- a/layout/xul/crashtests/399013.xul
+++ b/layout/xul/crashtests/399013.xul
@@ -1,31 +1,31 @@
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<menulist id="b" style="display: -moz-groupbox;">
-<panel id="c" style=" position: absolute;">
-<popup onunderflow="document.getElementById('c').removeAttribute('style')"/>
-</panel>
-<menupopup id="a" style="display: -moz-stack;">
-<menulist/>
-</menupopup>
-<panel style="display: -moz-deck;" onoverflow="document.getElementById('b').removeAttribute('style')">
-<popup style="display: -moz-deck;"/>
-</panel>
-</menulist>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<menulist id="b" style="display: -moz-groupbox;">
+<panel id="c" style=" position: absolute;">
+<popup onunderflow="document.getElementById('c').removeAttribute('style')"/>
+</panel>
+<menupopup id="a" style="display: -moz-stack;">
+<menulist/>
+</menupopup>
+<panel style="display: -moz-deck;" onoverflow="document.getElementById('b').removeAttribute('style')">
+<popup style="display: -moz-deck;"/>
+</panel>
+</menulist>
 
 <script id="script" xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
 function doe() {
 document.getElementById('c').removeAttribute('style');
-document.documentElement.boxObject.height;
+document.documentElement.clientHeight;
 document.getElementById('b').removeAttribute('style');
 document.getElementById('a').setAttribute('selected', 'true');
 document.getElementById('a').setAttribute('style', 'position: fixed;');
-document.documentElement.boxObject.height;
+document.documentElement.clientHeight;
 document.getElementById('a').removeAttribute('style');
 }
 
 function doe2() {
 window.location.reload();
 }
 setTimeout(doe2, 200);
 setTimeout(doe,100);
 ]]></script>
-</window>
\ No newline at end of file
+</window>
--- a/layout/xul/test/test_bug393970.xul
+++ b/layout/xul/test/test_bug393970.xul
@@ -70,22 +70,30 @@ https://bugzilla.mozilla.org/show_bug.cg
       }
 
       $("rows2").setAttribute("style", tests[currentTest]);
       setTimeout(checkPositions, 0, tests[currentTest]);
     }
 
     function checkPositions(variant) {
       for (var col = 1; col <= 3; col++) {
-        is($('cell1' + col).boxObject.x, $('cell2' + col).boxObject.x, "Cells (1," + col + ") and (2," + col + ") line up horizontally (with " + variant + ")");
-        is($('cell2' + col).boxObject.x, $('cell3' + col).boxObject.x, "Cells (2," + col + ") and (3," + col + ") line up horizontally (with " + variant + ")");
+        is(Math.round($('cell1' + col).getBoundingClientRect().x),
+           Math.round($('cell2' + col).getBoundingClientRect().x),
+           "Cells (1," + col + ") and (2," + col + ") line up horizontally (with " + variant + ")");
+        is(Math.round($('cell2' + col).getBoundingClientRect().x),
+           Math.round($('cell3' + col).getBoundingClientRect().x),
+           "Cells (2," + col + ") and (3," + col + ") line up horizontally (with " + variant + ")");
       }
       for (var row = 1; row <= 3; row++) {
-        is($('cell' + row + '1').boxObject.y, $('cell' + row + '2').boxObject.y, "Cells (" + row + ",1) and (" + row + ",2) line up vertically (with " + variant + ")");
-        is($('cell' + row + '2').boxObject.y, $('cell' + row + '3').boxObject.y, "Cells (" + row + ",2) and (" + row + ",3) line up vertically (with " + variant + ")");
+        is(Math.round($('cell' + row + '1').getBoundingClientRect().y),
+           Math.round($('cell' + row + '2').getBoundingClientRect().y),
+           "Cells (" + row + ",1) and (" + row + ",2) line up vertically (with " + variant + ")");
+        is(Math.round($('cell' + row + '2').getBoundingClientRect().y),
+           Math.round($('cell' + row + '3').getBoundingClientRect().y),
+           "Cells (" + row + ",2) and (" + row + ",3) line up vertically (with " + variant + ")");
       }
       runNextTest();
     }
  
     addLoadEvent(runNextTest);
     SimpleTest.waitForExplicitFinish()
    ]]></script>
 </window>
--- a/layout/xul/test/test_splitter.xul
+++ b/layout/xul/test/test_splitter.xul
@@ -15,17 +15,17 @@ XUL <splitter> collapsing tests
   <body xmlns="http://www.w3.org/1999/xhtml">
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
     SimpleTest.waitForExplicitFinish();
 
     function dragSplitter(offsetX, callback) {
-      var splitterWidth = splitter.boxObject.width;
+      var splitterWidth = splitter.getBoundingClientRect().width;
       synthesizeMouse(splitter, splitterWidth / 2, 2, {type: "mousedown"});
       synthesizeMouse(splitter, splitterWidth / 2, 1, {type: "mousemove"});
       SimpleTest.executeSoon(function() {
         SimpleTest.is(splitter.getAttribute("state"), "dragging", "The splitter should be dragged");
         synthesizeMouse(splitter, offsetX, 1, {type: "mousemove"});
         synthesizeMouse(splitter, offsetX, 1, {type: "mouseup"});
         SimpleTest.executeSoon(callback);
       });
@@ -36,17 +36,17 @@ XUL <splitter> collapsing tests
       SimpleTest.is(splitter.getAttribute("substate"), where, "The splitter should be collapsed " + where);
     }
 
     function shouldNotBeCollapsed() {
       SimpleTest.is(splitter.getAttribute("state"), "", "The splitter should not be collapsed");
     }
 
     function runPass(rightCollapsed, leftCollapsed, callback) {
-      var containerWidth = container.boxObject.width;
+      var containerWidth = container.getBoundingClientRect().width;
       var isRTL = getComputedStyle(splitter, null).direction == "rtl";
       dragSplitter(containerWidth, function() {
         if (rightCollapsed) {
           shouldBeCollapsed(isRTL ? "before" : "after");
         } else {
           shouldNotBeCollapsed();
         }
         dragSplitter(-containerWidth * 2, function() {
--- a/toolkit/content/tests/chrome/test_arrowpanel.xul
+++ b/toolkit/content/tests/chrome/test_arrowpanel.xul
@@ -232,21 +232,17 @@ function checkPanelPosition(panel)
   if (isRTL) {
     var flipLeftRight = val => val == "left" ? "right" : "left";
     expectedAnchorEdge = expectedAnchorEdge.replace(/(left|right)/, flipLeftRight);
     expectedSide = expectedSide.replace(/(left|right)/, flipLeftRight);
   }
 
   var panelRect = panel.getBoundingClientRect();
   var anchorRect = anchor.getBoundingClientRect();
-  var contentBO = panel.firstChild.boxObject;
-  var contentRect = { top: contentBO.y,
-                      left: contentBO.x,
-                      bottom: contentBO.y + contentBO.height,
-                      right: contentBO.x + contentBO.width };
+  var contentRect = panel.firstChild.getBoundingClientRect();
   switch (expectedSide) {
     case "top":
       ok(contentRect.top > vwinpos + anchorRect.bottom * zoomFactor + 5, "panel content is below");
       break;
     case "bottom":
       ok(contentRect.bottom < vwinpos + anchorRect.top * zoomFactor - 5, "panel content is above");
       break;
     case "left":
--- a/toolkit/content/tests/chrome/test_bug624329.xul
+++ b/toolkit/content/tests/chrome/test_bug624329.xul
@@ -116,17 +116,17 @@ function openContextMenu() {
              "menu top " + y + " should be below click point " + mouseY);
         }
         
         ok(y <= mouseY + 20,
            "menu top " + y + " should not be too far below click point " + mouseY);
 
         ok(x < mouseX,
            "menu left " + x + " should be left of click point " + mouseX);
-        var right = x + menu.boxObject.width;
+        var right = x + menu.getBoundingClientRect().width;
 
         if (platformIsMac) {
           // Rather than be constrained by the right hand screen edge, OSX menus flip
           // horizontally and appear to the left of the mouse pointer
           ok(right < mouseX,
              "menu right " + right + " should be left of click point " + mouseX);
         }
         else {
--- a/toolkit/content/tests/chrome/test_mousescroll.xul
+++ b/toolkit/content/tests/chrome/test_mousescroll.xul
@@ -256,18 +256,18 @@ function* testArrowScrollbox(id)
              " delta " + aDelta + " lineOrPageDelta " + lineOrPageDelta +
              " aDeltaMode " + aDeltaMode);
       }
     }
   }
 
   var scrolledWidth = scrollbox.scrollWidth;
   var scrolledHeight = scrollbox.scrollHeight;
-  var scrollMaxX = scrolledWidth - scrollbox.boxObject.width;
-  var scrollMaxY = scrolledHeight - scrollbox.boxObject.height;
+  var scrollMaxX = scrolledWidth - scrollbox.getBoundingClientRect().width;
+  var scrollMaxY = scrolledHeight - scrollbox.getBoundingClientRect().height;
   var scrollMax = orient == "horizontal" ? scrollMaxX : scrollMaxY;
 
   for (let i = 0; i < deltaModes.length; i++) {
     yield* helper(50, -1000, deltaModes[i], 0);
     yield* helper(50,  1000, deltaModes[i], scrollMax);
   }
 }
 
--- a/toolkit/content/tests/chrome/test_popupremoving.xul
+++ b/toolkit/content/tests/chrome/test_popupremoving.xul
@@ -113,17 +113,17 @@ function modified(event)
 {
   // use this mutation listener to hide the third popup, destroying its frame.
   // It gets triggered when the open attribute is cleared on the fourth menu.
 
   if (event.target == gTriggerMutation &&
       event.attrName == "open") {
     gChangeMutation.hidden = true;
     // force a layout flush
-    document.documentElement.boxObject.width;
+    document.documentElement.clientWidth;
     gTriggerMutation = null;
     gChangeMutation = null;
   }
 }
 
 function removePopups()
 {
   var menu2 = $(gKey + "menu2");
--- a/toolkit/content/tests/chrome/test_popupremoving_frame.xul
+++ b/toolkit/content/tests/chrome/test_popupremoving_frame.xul
@@ -52,17 +52,17 @@ function modified(event)
   if (event.target.id == "separatemenu3")
     tohide = framedoc.getElementById("separatemenu2");
   else if (event.target.id == "nestedmenu3")
     tohide = framedoc.getElementById("nestedmenu2");
 
   if (tohide) {
     tohide.hidden = true;
     // force a layout flush
-    $("frame").contentDocument.documentElement.boxObject.width;
+    $("frame").contentDocument.documentElement.clientWidth;
   }
 
   is(event.target, gMenus.shift(), event.target.id + " hidden");
   if (gMenus.length == 0)
     SimpleTest.finish();
 }
 
 ]]>
--- a/toolkit/content/tests/chrome/test_position.xul
+++ b/toolkit/content/tests/chrome/test_position.xul
@@ -57,18 +57,18 @@
 
 <script>
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest()
 {
-  var winwidth = document.documentElement.boxObject.width;
-  var innerscroll = $("innerscroll").boxObject.width;
+  var winwidth = document.documentElement.getBoundingClientRect().width;
+  var innerscroll = $("innerscroll").getBoundingClientRect().width;
 
   var box1 = $("box1");
   checkPosition("box1", box1, 0, 0, winwidth, 46);
 
   var box2 = $("box2");
   checkPosition("box2", box2, 2, 46, winwidth, 96);
 
   // height is height(box1) = 46 + margin-top(box3) = 1 + margin-top(button1) = 5
--- a/toolkit/content/tests/widgets/tree_shared.js
+++ b/toolkit/content/tests/widgets/tree_shared.js
@@ -1008,17 +1008,17 @@ function testtag_tree_wheel(aTree) {
 function synthesizeColumnDrag(aTree, aMouseDownColumnNumber, aMouseUpColumnNumber, aAfter) {
   var columns = getSortedColumnArray(aTree);
 
   var down = columns[aMouseDownColumnNumber].element;
   var up   = columns[aMouseUpColumnNumber].element;
 
   // Target the initial mousedown in the middle of the column header so we
   // avoid the extra hit test space given to the splitter
-  var columnWidth = down.boxObject.width;
+  var columnWidth = down.getBoundingClientRect().width;
   var splitterHitWidth = columnWidth / 2;
   synthesizeMouse(down, splitterHitWidth, 3, { type: "mousedown"});
 
   var offsetX = 0;
   if (aAfter) {
     offsetX = columnWidth;
   }
 
--- a/toolkit/content/widgets/notificationbox.js
+++ b/toolkit/content/widgets/notificationbox.js
@@ -240,17 +240,17 @@ MozElements.NotificationBox = class Noti
       else if (Date.now() > notification.timeout)
         this.removeNotification(notification);
     }
   }
 
   _showNotification(aNotification, aSlideIn, aSkipAnimation) {
     this._finishAnimation();
 
-    var height = aNotification.boxObject.height;
+    var height = aNotification.getBoundingClientRect().height;
     var skipAnimation = aSkipAnimation || height == 0 ||
       !this._allowAnimation;
     aNotification.classList.toggle("animated", !skipAnimation);
 
     if (aSlideIn) {
       this.currentNotification = aNotification;
       aNotification.style.removeProperty("position");
       aNotification.style.removeProperty("top");
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -1,16 +1,13 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<!-- This files relies on these specific Chrome/XBL globals -->
-<!-- globals PopupBoxObject -->
-
 <bindings id="popupBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="popup">
     <content>
       <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
@@ -155,20 +152,22 @@
     <handlers>
       <handler event="popupshowing" phase="target">
         <![CDATA[
           var array = [];
           var width = 0;
           for (var menuitem = this.firstElementChild; menuitem; menuitem = menuitem.nextElementSibling) {
             if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) {
               var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel");
-              if (accel && accel.boxObject) {
+              if (accel) {
                 array.push(accel);
-                if (accel.boxObject.width > width)
-                  width = accel.boxObject.width;
+                let accelWidth = accel.getBoundingClientRect().width;
+                if (accelWidth > width) {
+                  width = accelWidth;
+                }
               }
             }
           }
           for (var i = 0; i < array.length; i++)
             array[i].width = width;
         ]]>
       </handler>
     </handlers>
--- a/toolkit/content/widgets/scrollbox.xml
+++ b/toolkit/content/widgets/scrollbox.xml
@@ -138,22 +138,16 @@
           return this.getAttribute("smoothscroll") == "true";
         ]]></getter>
         <setter><![CDATA[
           this.setAttribute("smoothscroll", !!val);
           return val;
         ]]></setter>
       </property>
 
-      <property name="scrollBoxObject" readonly="true">
-        <getter><![CDATA[
-          return this.scrollbox.boxObject;
-        ]]></getter>
-      </property>
-
       <property name="scrollClientRect" readonly="true">
         <getter><![CDATA[
           return this.scrollbox.getBoundingClientRect();
         ]]></getter>
       </property>
 
       <property name="scrollClientSize" readonly="true">
         <getter><![CDATA[
--- a/toolkit/content/widgets/tree.js
+++ b/toolkit/content/widgets/tree.js
@@ -269,17 +269,17 @@
         if (event.button != 0) { return; }
         if (this.parentNode.parentNode.enableColumnDrag) {
           var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
           var cols = this.parentNode.getElementsByTagNameNS(xulns, "treecol");
 
           // only start column drag operation if there are at least 2 visible columns
           var visible = 0;
           for (var i = 0; i < cols.length; ++i)
-            if (cols[i].boxObject.width > 0) ++visible;
+            if (cols[i].getBoundingClientRect().width > 0) ++visible;
 
           if (visible > 1) {
             window.addEventListener("mousemove", this._onDragMouseMove, true);
             window.addEventListener("mouseup", this._onDragMouseUp, true);
             document.treecolDragging = this;
             this.mDragGesturing = true;
             this.mStartDragX = event.clientX;
             this.mStartDragY = event.clientY;
@@ -332,18 +332,21 @@
         return "1";
 
       return "" + (val == "0" ? 0 : parseInt(val));
     }
 
     get _previousVisibleColumn() {
       var sib = this.boxObject.previousSibling;
       while (sib) {
-        if (sib.localName == "treecol" && sib.boxObject.width > 0 && sib.parentNode == this.parentNode)
+        if (sib.localName == "treecol" &&
+            sib.getBoundingClientRect().width > 0 &&
+            sib.parentNode == this.parentNode) {
           return sib;
+        }
         sib = sib.boxObject.previousSibling;
       }
       return null;
     }
 
     _onDragMouseMove(aEvent) {
       var col = document.treecolDragging;
       if (!col) return;
@@ -1013,21 +1016,21 @@
       var columns = [];
       var col = this.columns.getFirstColumn();
       while (col) {
         columns.push(col);
         col = col.getNext();
       }
       if (isRTL)
         columns.reverse();
-      var currentX = this.boxObject.x;
+      var currentX = this.getBoundingClientRect().x;
       var adjustedX = aX + this.horizontalPosition;
       for (var i = 0; i < columns.length; ++i) {
         col = columns[i];
-        var cw = col.element.boxObject.width;
+        var cw = col.element.getBoundingClientRect().width;
         if (cw > 0) {
           currentX += cw;
           if (currentX - (cw * aThresh) > adjustedX)
             return col.element;
         }
       }
 
       if (aPos)
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -977,33 +977,39 @@ PopupNotifications.prototype = {
       return !dismiss;
     });
     if (!notificationsToShow.length)
       return;
     let notificationIds = notificationsToShow.map(n => n.id);
 
     this._refreshPanel(notificationsToShow);
 
+    function isNullOrHidden(elem) {
+      if (!elem) {
+        return true;
+      }
+
+      let anchorRect = elem.getBoundingClientRect();
+      return (anchorRect.width == 0 && anchorRect.height == 0);
+    }
+
     // If the anchor element is hidden or null, fall back to the identity icon.
-    if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                           anchorElement.boxObject.width == 0)) {
+    if (isNullOrHidden(anchorElement)) {
       anchorElement = this.window.document.getElementById("identity-icon");
 
       // If the identity icon is not available in this window, or maybe the
       // entire location bar is hidden for any reason, use the tab as the
       // anchor. We only ever show notifications for the current browser, so we
       // can just use the current tab.
-      if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                             anchorElement.boxObject.width == 0)) {
+      if (isNullOrHidden(anchorElement)) {
         anchorElement = this.tabbrowser.selectedTab;
 
         // If we're in an entirely chromeless environment, set the anchorElement
         // to null and let openPopup show the notification at (0,0) later.
-        if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                               anchorElement.boxObject.width == 0)) {
+        if (isNullOrHidden(anchorElement)) {
           anchorElement = null;
         }
       }
     }
 
     if (this.isPanelOpen && this._currentAnchorElement == anchorElement) {
       notificationsToShow.forEach(function(n) {
         this._fireCallback(n, NOTIFICATION_EVENT_SHOWN);
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3300,23 +3300,23 @@ var gDetailView = {
       aCallback();
   },
 
   scrollToPreferencesRows() {
     // We find this row, rather than remembering it from above,
     // in case it has been changed by the observers.
     let firstRow = gDetailView.node.querySelector('setting[first-row="true"]');
     if (firstRow) {
-      let top = firstRow.boxObject.y;
+      let top = firstRow.getBoundingClientRect().y;
       top -= parseInt(window.getComputedStyle(firstRow).getPropertyValue("margin-top"));
 
-      let detailViewBoxObject = gDetailView.node.boxObject;
-      top -= detailViewBoxObject.y;
-
-      detailViewBoxObject.scrollTo(0, top);
+      let detailView = gDetailView.node;
+      top -= detailView.getBoundingClientRect().y;
+
+      detailView.scrollTo(0, top);
     }
   },
 
   async createOptionsBrowser(parentNode) {
     const containerId = "addon-options-prompts-stack";
 
     let stack = document.getElementById(containerId);