bug 1034601 - Enable devtools/markupview tests with e10s; r=bgrins
authorPatrick Brosset <pbrosset@mozilla.com>
Wed, 16 Jul 2014 22:17:30 +0200
changeset 216513 4118687bbaeb0ba14a7375b83058aca82be8c017
parent 216512 dcad44d79eee4c4f09e694caa0c2ac313b03d350
child 216514 cadbfcd5e867b6a6c3608e9c779c2a3256326f85
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1034601
milestone33.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 1034601 - Enable devtools/markupview tests with e10s; r=bgrins
browser/devtools/inspector/breadcrumbs.js
browser/devtools/markupview/test/browser.ini
browser/devtools/markupview/test/browser_markupview_css_completion_style_attribute.js
browser/devtools/markupview/test/browser_markupview_highlight_hover_01.js
browser/devtools/markupview/test/browser_markupview_highlight_hover_03.js
browser/devtools/markupview/test/browser_markupview_html_edit_01.js
browser/devtools/markupview/test/browser_markupview_html_edit_02.js
browser/devtools/markupview/test/browser_markupview_html_edit_03.js
browser/devtools/markupview/test/browser_markupview_image_tooltip.js
browser/devtools/markupview/test/browser_markupview_mutation_01.js
browser/devtools/markupview/test/browser_markupview_mutation_02.js
browser/devtools/markupview/test/browser_markupview_navigation.js
browser/devtools/markupview/test/browser_markupview_node_not_displayed_01.js
browser/devtools/markupview/test/browser_markupview_node_not_displayed_02.js
browser/devtools/markupview/test/browser_markupview_pagesize_01.js
browser/devtools/markupview/test/browser_markupview_pagesize_02.js
browser/devtools/markupview/test/browser_markupview_search_01.js
browser/devtools/markupview/test/browser_markupview_tag_edit_02.js
browser/devtools/markupview/test/browser_markupview_tag_edit_03.js
browser/devtools/markupview/test/browser_markupview_tag_edit_04.js
browser/devtools/markupview/test/browser_markupview_tag_edit_08.js
browser/devtools/markupview/test/browser_markupview_textcontent_edit_01.js
browser/devtools/markupview/test/browser_markupview_toggle_01.js
browser/devtools/markupview/test/browser_markupview_toggle_02.js
browser/devtools/markupview/test/browser_markupview_toggle_03.js
browser/devtools/markupview/test/head.js
browser/devtools/markupview/test/helper_attributes_test_runner.js
browser/devtools/markupview/test/helper_outerhtml_test_runner.js
toolkit/devtools/server/actors/highlighter.js
--- a/browser/devtools/inspector/breadcrumbs.js
+++ b/browser/devtools/inspector/breadcrumbs.js
@@ -591,18 +591,18 @@ HTMLBreadcrumbs.prototype = {
    * if the selected node still has children.
    */
   ensureFirstChild: function BC_ensureFirstChild()
   {
     // If the last displayed node is the selected node
     if (this.currentIndex == this.nodeHierarchy.length - 1) {
       let node = this.nodeHierarchy[this.currentIndex].node;
       return this.getInterestingFirstNode(node).then(child => {
-        // If the node has a child
-        if (child) {
+        // If the node has a child and we've not been destroyed in the meantime
+        if (child && !this.isDestroyed) {
           // Show this child
           this.expand(child);
         }
       });
     }
 
     return resolveNextTick(true);
   },
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -1,10 +1,9 @@
 [DEFAULT]
-skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 subsuite = devtools
 support-files =
   doc_markup_edit.html
   doc_markup_flashing.html
   doc_markup_mutation.html
   doc_markup_navigation.html
   doc_markup_not_displayed.html
   doc_markup_pagesize_01.html
@@ -14,33 +13,38 @@ support-files =
   doc_markup_tooltip.png
   head.js
   helper_attributes_test_runner.js
   helper_outerhtml_test_runner.js
 
 [browser_markupview_copy_image_data.js]
 [browser_markupview_css_completion_style_attribute.js]
 [browser_markupview_highlight_hover_01.js]
+skip-if = e10s # Bug 985597 - The XUL-based highlighter isn't e10s compatible
 [browser_markupview_highlight_hover_02.js]
+skip-if = e10s # Bug 985597 - The XUL-based highlighter isn't e10s compatible
 [browser_markupview_highlight_hover_03.js]
+skip-if = e10s # Bug 985597 - The XUL-based highlighter isn't e10s compatible
 [browser_markupview_html_edit_01.js]
 [browser_markupview_html_edit_02.js]
 [browser_markupview_html_edit_03.js]
 [browser_markupview_image_tooltip.js]
 [browser_markupview_mutation_01.js]
 [browser_markupview_mutation_02.js]
 [browser_markupview_navigation.js]
 [browser_markupview_node_not_displayed_01.js]
 [browser_markupview_node_not_displayed_02.js]
 [browser_markupview_pagesize_01.js]
 [browser_markupview_pagesize_02.js]
+skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
 [browser_markupview_search_01.js]
 [browser_markupview_tag_edit_01.js]
 [browser_markupview_tag_edit_02.js]
 [browser_markupview_tag_edit_03.js]
+skip-if = e10s # Bug 1036421 - Tag editing isn't remote-safe
 [browser_markupview_tag_edit_04.js]
 [browser_markupview_tag_edit_05.js]
 [browser_markupview_tag_edit_06.js]
 [browser_markupview_tag_edit_07.js]
 [browser_markupview_tag_edit_08.js]
 [browser_markupview_textcontent_edit_01.js]
 [browser_markupview_toggle_01.js]
 [browser_markupview_toggle_02.js]
--- a/browser/devtools/markupview/test/browser_markupview_css_completion_style_attribute.js
+++ b/browser/devtools/markupview/test/browser_markupview_css_completion_style_attribute.js
@@ -64,25 +64,26 @@ const TEST_DATA = [
 ];
 
 let test = asyncTest(function*() {
   info("Opening the inspector on the test URL");
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   yield inspector.markup.expandAll();
 
-  let node = getContainerForRawNode("#node14", inspector).editor;
-  let attr = node.newAttr;
+  let nodeFront = yield getNodeFront("#node14", inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
+  let attr = container.editor.newAttr;
   attr.focus();
   EventUtils.sendKey("return", inspector.panelWin);
   let editor = inplaceEditor(attr);
 
   for (let i = 0; i < TEST_DATA.length; i ++) {
     yield enterData(i, editor, inspector);
-    checkData(i, editor, inspector);
+    yield checkData(i, editor, inspector);
   }
 
   while (inspector.markup.undo.canUndo()) {
     yield undoChange(inspector);
   }
 
   yield inspector.once("inspector-updated");
 });
@@ -117,28 +118,29 @@ function enterData(index, editor, inspec
       executeSoon(def.resolve);
     });
   }
   EventUtils.synthesizeKey(key, {}, inspector.panelWin);
 
   return def.promise;
 }
 
-function checkData(index, editor, inspector) {
+function* checkData(index, editor, inspector) {
   let [key, completion, selStart, selEnd, popupOpen] = TEST_DATA[index];
   info("Test data " + index + " entered. Checking state.");
 
   if (selEnd != -1) {
     is(editor.input.value, completion, "Completed value is correct");
     is(editor.input.selectionStart, selStart, "Selection start position is correct");
     is(editor.input.selectionEnd, selEnd, "Selection end position is correct");
     if (popupOpen) {
       ok(editor.popup.isOpen, "Popup is open");
     } else {
       ok(editor.popup._panel.state != "open" && editor.popup._panel.state != "showing",
         "Popup is closed");
     }
   } else {
-    let editor = getContainerForRawNode("#node14", inspector).editor;
+    let nodeFront = yield getNodeFront("#node14", inspector);
+    let editor = getContainerForNodeFront(nodeFront, inspector).editor;
     let attr = editor.attrs["style"].querySelector(".editable");
     is(attr.textContent, completion, "Correct value is persisted after pressing Enter");
   }
 }
--- a/browser/devtools/markupview/test/browser_markupview_highlight_hover_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_highlight_hover_01.js
@@ -8,21 +8,21 @@
 // by clicking on it leaves the highlighter visible for as long as the mouse is
 // over the node
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab("data:text/html,<p>It's going to be legen....</p>").then(openInspector);
   let p = getNode("p");
 
   info("hovering over the <p> line in the markup-view");
-  yield hoverContainer(p, inspector);
+  yield hoverContainer("p", inspector);
   ok(isHighlighterVisible(), "the highlighter is still visible");
 
   info("selecting the <p> line by clicking in the markup-view");
-  yield clickContainer(p, inspector);
+  yield clickContainer("p", inspector);
 
   p.textContent = "wait for it ....";
   info("wait and see if the highlighter stays visible even after the node was selected");
   yield waitForTheBrieflyShowBoxModelTimeout();
 
   let updated = inspector.once("inspector-updated");
   p.textContent = "dary!!!!";
   ok(isHighlighterVisible(), "the highlighter is still visible");
--- a/browser/devtools/markupview/test/browser_markupview_highlight_hover_03.js
+++ b/browser/devtools/markupview/test/browser_markupview_highlight_hover_03.js
@@ -24,31 +24,32 @@ let test = asyncTest(function*() {
   inspector.toolbox._highlighter.showBoxModel = function(nodeFront) {
     highlightedNode = nodeFront;
     return promise.resolve();
   };
   inspector.toolbox._highlighter.hideBoxModel = function() {
     return promise.resolve();
   };
 
-  function isHighlighting(node, desc) {
-    is(highlightedNode, getContainerForRawNode(node, inspector).node, desc);
+  function* isHighlighting(selector, desc) {
+    let nodeFront = yield getNodeFront(selector, inspector);
+    is(highlightedNode, nodeFront, desc);
   }
 
   info("Hover over <p#one> line in the markup-view");
   yield hoverContainer("#one", inspector);
-  isHighlighting(getNode("#one"), "<p#one> is highlighted");
+  yield isHighlighting("#one", "<p#one> is highlighted");
 
   info("Navigate to <p#two> with the keyboard");
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeKey("VK_DOWN", {});
   yield onUpdated;
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeKey("VK_DOWN", {});
   yield onUpdated;
-  isHighlighting(getNode("#two"), "<p#two> is highlighted");
+  yield isHighlighting("#two", "<p#two> is highlighted");
 
   info("Navigate back to <p#one> with the keyboard");
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeKey("VK_UP", {});
   yield onUpdated;
-  isHighlighting(getNode("#one"), "<p#one> is highlighted again");
+  yield isHighlighting("#one", "<p#one> is highlighted again");
 });
--- a/browser/devtools/markupview/test/browser_markupview_html_edit_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_html_edit_01.js
@@ -8,17 +8,17 @@
 
 loadHelperScript("helper_outerhtml_test_runner.js");
 
 const TEST_DATA = [
   {
     selector: "#one",
     oldHTML: '<div id="one">First <em>Div</em></div>',
     newHTML: '<div id="one">First Div</div>',
-    validate: function(pageNode, selectedNode) {
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront) {
       is(pageNode.textContent, "First Div", "New div has expected text content");
       ok(!getNode("#one em"), "No em remaining")
     }
   },
   {
     selector: "#removedChildren",
     oldHTML: '<div id="removedChildren">removedChild <i>Italic <b>Bold <u>Underline</u></b></i> Normal</div>',
     newHTML: '<div id="removedChildren">removedChild</div>'
@@ -27,41 +27,42 @@ const TEST_DATA = [
     selector: "#addedChildren",
     oldHTML: '<div id="addedChildren">addedChildren</div>',
     newHTML: '<div id="addedChildren">addedChildren <i>Italic <b>Bold <u>Underline</u></b></i> Normal</div>'
   },
   {
     selector: "#addedAttribute",
     oldHTML: '<div id="addedAttribute">addedAttribute</div>',
     newHTML: '<div id="addedAttribute" class="important" disabled checked>addedAttribute</div>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
       is(pageNode.outerHTML, '<div id="addedAttribute" class="important" disabled="" checked="">addedAttribute</div>',
             "Attributes have been added");
     }
   },
   {
     selector: "#changedTag",
     oldHTML: '<div id="changedTag">changedTag</div>',
     newHTML: '<p id="changedTag" class="important">changedTag</p>'
   },
   {
     selector: "#siblings",
     oldHTML: '<div id="siblings">siblings</div>',
     newHTML: '<div id="siblings-before-sibling">before sibling</div>' +
              '<div id="siblings">siblings (updated)</div>' +
              '<div id="siblings-after-sibling">after sibling</div>',
-    validate: function(pageNode, selectedNode) {
-      let beforeSiblingNode = getNode("#siblings-before-sibling");
-      let afterSiblingNode = getNode("#siblings-after-sibling");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      let beforeSibling = getNode("#siblings-before-sibling");
+      let beforeSiblingFront = yield getNodeFront("#siblings-before-sibling", inspector);
+      let afterSibling = getNode("#siblings-after-sibling");
 
-      is(beforeSiblingNode, selectedNode, "Sibling has been selected");
+      is(beforeSiblingFront, selectedNodeFront, "Sibling has been selected");
       is(pageNode.textContent, "siblings (updated)", "New div has expected text content");
-      is(beforeSiblingNode.textContent, "before sibling", "Sibling has been inserted");
-      is(afterSiblingNode.textContent, "after sibling", "Sibling has been inserted");
+      is(beforeSibling.textContent, "before sibling", "Sibling has been inserted");
+      is(afterSibling.textContent, "after sibling", "Sibling has been inserted");
     }
   }
 ];
 
 const TEST_URL = "data:text/html," +
   "<!DOCTYPE html>" +
   "<head><meta charset='utf-8' /></head>" +
   "<body>" +
--- a/browser/devtools/markupview/test/browser_markupview_html_edit_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_html_edit_02.js
@@ -8,74 +8,74 @@
 
 loadHelperScript("helper_outerhtml_test_runner.js");
 
 const TEST_DATA = [
   {
     selector: "#badMarkup1",
     oldHTML: '<div id="badMarkup1">badMarkup1</div>',
     newHTML: '<div id="badMarkup1">badMarkup1</div> hanging</div>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
 
       let textNode = pageNode.nextSibling;
 
       is(textNode.nodeName, "#text", "Sibling is a text element");
       is(textNode.data, " hanging", "New text node has expected text content");
     }
   },
   {
     selector: "#badMarkup2",
     oldHTML: '<div id="badMarkup2">badMarkup2</div>',
     newHTML: '<div id="badMarkup2">badMarkup2</div> hanging<div></div></div></div></body>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
 
       let textNode = pageNode.nextSibling;
 
       is(textNode.nodeName, "#text", "Sibling is a text element");
       is(textNode.data, " hanging", "New text node has expected text content");
     }
   },
   {
     selector: "#badMarkup3",
     oldHTML: '<div id="badMarkup3">badMarkup3</div>',
     newHTML: '<div id="badMarkup3">badMarkup3 <em>Emphasized <strong> and strong</div>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
 
       let em = getNode("#badMarkup3 em");
       let strong = getNode("#badMarkup3 strong");
 
       is(em.textContent, "Emphasized  and strong", "<em> was auto created");
       is(strong.textContent, " and strong", "<strong> was auto created");
     }
   },
   {
     selector: "#badMarkup4",
     oldHTML: '<div id="badMarkup4">badMarkup4</div>',
     newHTML: '<div id="badMarkup4">badMarkup4</p>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
 
       let div = getNode("#badMarkup4");
       let p = getNode("#badMarkup4 p");
 
       is(div.textContent, "badMarkup4", "textContent is correct");
       is(div.tagName, "DIV", "did not change to <p> tag");
       is(p.textContent, "", "The <p> tag has no children");
       is(p.tagName, "P", "Created an empty <p> tag");
     }
   },
   {
     selector: "#badMarkup5",
     oldHTML: '<p id="badMarkup5">badMarkup5</p>',
     newHTML: '<p id="badMarkup5">badMarkup5 <div>with a nested div</div></p>',
-    validate: function(pageNode, selectedNode) {
-      is(pageNode, selectedNode, "Original element is selected");
+    validate: function*(pageNode, pageNodeFront, selectedNodeFront, inspector) {
+      is(pageNodeFront, selectedNodeFront, "Original element is selected");
 
       let p = getNode("#badMarkup5");
       let nodiv = getNode("#badMarkup5 div");
       let div = getNode("#badMarkup5 ~ div");
 
       ok(!nodiv, "The invalid markup got created as a sibling");
       is(p.textContent, "badMarkup5 ", "The <p> tag does not take in the <div> content");
       is(p.tagName, "P", "Did not change to a <div> tag");
--- a/browser/devtools/markupview/test/browser_markupview_html_edit_03.js
+++ b/browser/devtools/markupview/test/browser_markupview_html_edit_03.js
@@ -41,17 +41,17 @@ let test = asyncTest(function*() {
   info("Checking (again) that editing the <html> element works like other nodes");
   yield testDocumentElement2(inspector);
 });
 
 function testEscapeCancels(inspector) {
   let def = promise.defer();
   let node = getNode(SELECTOR);
 
-  selectNode(node, inspector).then(() => {
+  selectNode(SELECTOR, inspector).then(() => {
     inspector.markup.htmlEditor.on("popupshown", function onPopupShown() {
       inspector.markup.htmlEditor.off("popupshown", onPopupShown);
 
       ok(inspector.markup.htmlEditor._visible, "HTML Editor is visible");
       is(node.outerHTML, OLD_HTML, "The node is starting with old HTML.");
 
       inspector.markup.htmlEditor.on("popuphidden", function onPopupHidden() {
         inspector.markup.htmlEditor.off("popuphidden", onPopupHidden);
@@ -96,85 +96,87 @@ function testF2Commits(inspector) {
   });
 
   inspector.markup._frame.contentDocument.documentElement.focus();
   EventUtils.sendKey("F2", inspector.markup._frame.contentWindow);
 
   return def.promise;
 }
 
-function testBody(inspector) {
+function* testBody(inspector) {
   let body = getNode("body");
   let bodyHTML = '<body id="updated"><p></p></body>';
-  let bodyFront = inspector.markup.walker.frontForRawNode(body);
+  let bodyFront = yield getNodeFront("body", inspector);
   let doc = content.document;
 
   let mutated = inspector.once("markupmutation");
   inspector.markup.updateNodeOuterHTML(bodyFront, bodyHTML, body.outerHTML);
 
-  return mutated.then(mutations => {
-    is(getNode("body").outerHTML, bodyHTML, "<body> HTML has been updated");
-    is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
-    return inspector.once("inspector-updated");
-  });
+  let mutations = yield mutated;
+
+  is(getNode("body").outerHTML, bodyHTML, "<body> HTML has been updated");
+  is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testHead(inspector) {
+function* testHead(inspector) {
   let head = getNode("head");
   let headHTML = '<head id="updated"><title>New Title</title><script>window.foo="bar";</script></head>';
-  let headFront = inspector.markup.walker.frontForRawNode(head);
+  let headFront = yield getNodeFront("head", inspector);
   let doc = content.document;
 
   let mutated = inspector.once("markupmutation");
   inspector.markup.updateNodeOuterHTML(headFront, headHTML, head.outerHTML);
 
-  return mutated.then(mutations => {
-    is(doc.title, "New Title", "New title has been added");
-    is(doc.defaultView.foo, undefined, "Script has not been executed");
-    is(doc.querySelector("head").outerHTML, headHTML, "<head> HTML has been updated");
-    is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
-    return inspector.once("inspector-updated");
-  });
+  let mutations = yield mutated;
+
+  is(doc.title, "New Title", "New title has been added");
+  is(doc.defaultView.foo, undefined, "Script has not been executed");
+  is(doc.querySelector("head").outerHTML, headHTML, "<head> HTML has been updated");
+  is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testDocumentElement(inspector) {
+function* testDocumentElement(inspector) {
   let doc = content.document;
   let docElement = doc.documentElement;
   let docElementHTML = '<html id="updated" foo="bar"><head><title>Updated from document element</title><script>window.foo="bar";</script></head><body><p>Hello</p></body></html>';
-  let docElementFront = inspector.markup.walker.frontForRawNode(docElement);
+  let docElementFront = yield inspector.markup.walker.documentElement();
 
   let mutated = inspector.once("markupmutation");
   inspector.markup.updateNodeOuterHTML(docElementFront, docElementHTML, docElement.outerHTML);
 
-  return mutated.then(mutations => {
-    is(doc.title, "Updated from document element", "New title has been added");
-    is(doc.defaultView.foo, undefined, "Script has not been executed");
-    is(doc.documentElement.id, "updated", "<html> ID has been updated");
-    is(doc.documentElement.className, "", "<html> class has been updated");
-    is(doc.documentElement.getAttribute("foo"), "bar", "<html> attribute has been updated");
-    is(doc.documentElement.outerHTML, docElementHTML, "<html> HTML has been updated");
-    is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
-    is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
-    is(doc.body.textContent, "Hello", "document.body.textContent has been updated");
-  });
+  let mutations = yield mutated;
+
+  is(doc.title, "Updated from document element", "New title has been added");
+  is(doc.defaultView.foo, undefined, "Script has not been executed");
+  is(doc.documentElement.id, "updated", "<html> ID has been updated");
+  is(doc.documentElement.className, "", "<html> class has been updated");
+  is(doc.documentElement.getAttribute("foo"), "bar", "<html> attribute has been updated");
+  is(doc.documentElement.outerHTML, docElementHTML, "<html> HTML has been updated");
+  is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
+  is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
+  is(doc.body.textContent, "Hello", "document.body.textContent has been updated");
 }
 
-function testDocumentElement2(inspector) {
+function* testDocumentElement2(inspector) {
   let doc = content.document;
   let docElement = doc.documentElement;
   let docElementHTML = '<html class="updated" id="somethingelse"><head><title>Updated again from document element</title><script>window.foo="bar";</script></head><body><p>Hello again</p></body></html>';
-  let docElementFront = inspector.markup.walker.frontForRawNode(docElement);
+  let docElementFront = yield inspector.markup.walker.documentElement();
 
   let mutated = inspector.once("markupmutation");
   inspector.markup.updateNodeOuterHTML(docElementFront, docElementHTML, docElement.outerHTML);
 
-  return mutated.then(mutations => {
-    is(doc.title, "Updated again from document element", "New title has been added");
-    is(doc.defaultView.foo, undefined, "Script has not been executed");
-    is(doc.documentElement.id, "somethingelse", "<html> ID has been updated");
-    is(doc.documentElement.className, "updated", "<html> class has been updated");
-    is(doc.documentElement.getAttribute("foo"), null, "<html> attribute has been removed");
-    is(doc.documentElement.outerHTML, docElementHTML, "<html> HTML has been updated");
-    is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
-    is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
-    is(doc.body.textContent, "Hello again", "document.body.textContent has been updated");
-  });
+  let mutations = yield mutated;
+
+  is(doc.title, "Updated again from document element", "New title has been added");
+  is(doc.defaultView.foo, undefined, "Script has not been executed");
+  is(doc.documentElement.id, "somethingelse", "<html> ID has been updated");
+  is(doc.documentElement.className, "updated", "<html> class has been updated");
+  is(doc.documentElement.getAttribute("foo"), null, "<html> attribute has been removed");
+  is(doc.documentElement.outerHTML, docElementHTML, "<html> HTML has been updated");
+  is(doc.querySelectorAll("head").length, 1, "no extra <head>s have been added");
+  is(doc.querySelectorAll("body").length, 1, "no extra <body>s have been added");
+  is(doc.body.textContent, "Hello again", "document.body.textContent has been updated");
 }
--- a/browser/devtools/markupview/test/browser_markupview_image_tooltip.js
+++ b/browser/devtools/markupview/test/browser_markupview_image_tooltip.js
@@ -27,17 +27,17 @@ let test = asyncTest(function*() {
   createPage();
 
   let {inspector} = yield openInspector();
 
   info("Selecting the first <img> tag");
   yield selectNode("img", inspector);
 
   for (let testNode of TEST_NODES) {
-    let target = getImageTooltipTarget(testNode, inspector);
+    let target = yield getImageTooltipTarget(testNode, inspector);
     yield assertTooltipShownOn(target, inspector);
     checkImageTooltip(testNode, inspector);
   }
 });
 
 function createPage() {
   info("Fill the page with the test content");
   content.document.body.innerHTML = PAGE_CONTENT;
@@ -50,35 +50,33 @@ function createPage() {
   context.moveTo(300, 0);
   context.lineTo(600, 600);
   context.lineTo(0, 600);
   context.closePath();
   context.fillStyle = "#ffc821";
   context.fill();
 }
 
-function getImageTooltipTarget({selector}, inspector) {
-  let node = getNode(selector);
-  let isImg = node.tagName.toLowerCase() === "img";
+function* getImageTooltipTarget({selector}, inspector) {
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let isImg = nodeFront.tagName.toLowerCase() === "img";
 
-  let container = getContainerForRawNode(node, inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
 
    let target = container.editor.tag;
    if (isImg) {
      target = container.editor.getAttributeElement("src");
    }
   return target;
 }
 
-function assertTooltipShownOn(element, {markup}) {
-  return Task.spawn(function*() {
-    info("Is the element a valid hover target");
-    let isValid = yield markup.tooltip.isValidHoverTarget(element);
-    ok(isValid, "The element is a valid hover target for the image tooltip");
-  });
+function* assertTooltipShownOn(element, {markup}) {
+  info("Is the element a valid hover target");
+  let isValid = yield markup.tooltip.isValidHoverTarget(element);
+  ok(isValid, "The element is a valid hover target for the image tooltip");
 }
 
 function checkImageTooltip({selector, size}, {markup}) {
   let images = markup.tooltip.panel.getElementsByTagName("image");
   is(images.length, 1, "Tooltip for [" + selector + "] contains an image");
 
   let label = markup.tooltip.panel.querySelector(".devtools-tooltip-caption");
   is(label.textContent, size, "Tooltip label for [" + selector + "] displays the right image size");
--- a/browser/devtools/markupview/test/browser_markupview_mutation_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_mutation_01.js
@@ -1,67 +1,110 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that various mutations to the dom update the markup view correctly.
-// The test for comparing the markup view to the real dom is a bit weird:
-// - Select the text in the markup view
-// - Parse that as innerHTML in a document we've created for the purpose.
-// - Remove extraneous whitespace in that tree
-// - Compare it to the real dom with isEqualNode.
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_mutation.html";
-// All the mutation types we want to test.
+
+// Mutation tests. Each entry in the array has the following properties:
+// - desc: for logging only
+// - test: a function supposed to mutate the DOM
+// - check: a function supposed to test that the mutation was handled
 const TEST_DATA = [
   {
     desc: "Adding an attribute",
     test: () => {
       let node1 = getNode("#node1");
       node1.setAttribute("newattr", "newattrval");
+    },
+    check: function*(inspector) {
+      let {editor} = yield getContainerForSelector("#node1", inspector);
+      ok([...editor.attrList.querySelectorAll(".attreditor")].some(attr => {
+        return attr.textContent.trim() === "newattr=\"newattrval\"";
+      }), "newattr attribute found");
     }
   },
   {
     desc: "Removing an attribute",
     test: () => {
       let node1 = getNode("#node1");
       node1.removeAttribute("newattr");
+    },
+    check: function*(inspector) {
+      // The markup-view is a little weird in that it doesn't remove the
+      // attribute but only hides it with display:none
+      let {editor} = yield getContainerForSelector("#node1", inspector);
+      ok([...editor.attrList.querySelectorAll(".attreditor")].some(attr => {
+        return attr.textContent.trim() === "newattr=\"newattrval\"" &&
+               attr.style.display === "none";
+      }), "newattr attribute removed");
     }
   },
   {
     desc: "Updating the text-content",
     test: () => {
       let node1 = getNode("#node1");
       node1.textContent = "newtext";
+    },
+    check: function*(inspector) {
+      let {children} = yield getContainerForSelector("#node1", inspector);
+      is(children.querySelector(".text").textContent.trim(), "newtext",
+        "The new textcontent was updated");
     }
   },
   {
     desc: "Updating the innerHTML",
     test: () => {
       let node2 = getNode("#node2");
       node2.innerHTML = "<div><span>foo</span></div>";
+    },
+    check: function*(inspector) {
+      let container = yield getContainerForSelector("#node2", inspector);
+
+      let openTags = container.children.querySelectorAll(".open .tag");
+      is(openTags.length, 2, "There are 2 tags in node2");
+      is(openTags[0].textContent.trim(), "div", "The first tag is a div");
+      is(openTags[1].textContent.trim(), "span", "The second tag is a span");
+
+      is(container.children.querySelector(".text").textContent.trim(), "foo",
+        "The span's textcontent is correct");
     }
   },
   {
     desc: "Removing child nodes",
     test: () => {
       let node4 = getNode("#node4");
       while (node4.firstChild) {
         node4.removeChild(node4.firstChild);
       }
+    },
+    check: function*(inspector) {
+      let {children} = yield getContainerForSelector("#node4", inspector);
+      is(children.innerHTML, "", "Children have been removed");
     }
   },
   {
     desc: "Appending a child to a different parent",
     test: () => {
       let node17 = getNode("#node17");
-      let node1 = getNode("#node2");
-      node1.appendChild(node17);
+      let node2 = getNode("#node2");
+      node2.appendChild(node17);
+    },
+    check: function*(inspector) {
+      let {children} = yield getContainerForSelector("#node16", inspector);
+      is(children.innerHTML, "", "Node17 has been removed from its node16 parent");
+
+      let container = yield getContainerForSelector("#node2", inspector);
+      let openTags = container.children.querySelectorAll(".open .tag");
+      is(openTags.length, 3, "There are now 3 tags in node2");
+      is(openTags[2].textContent.trim(), "p", "The third tag is node17");
     }
   },
   {
     desc: "Swapping a parent and child element, putting them in the same tree",
     // body
     //  node1
     //  node18
     //    node19
@@ -77,78 +120,51 @@ const TEST_DATA = [
     test: () => {
       let node18 = getNode("#node18");
       let node20 = getNode("#node20");
 
       let node1 = getNode("#node1");
 
       node1.appendChild(node20);
       node20.appendChild(node18);
+    },
+    check: function*(inspector) {
+      let {children} = yield getContainerForSelector("#node1", inspector);
+      is(children.childNodes.length, 2,
+        "Node1 now has 2 children (textnode and node20)");
+
+      let node20 = children.childNodes[1];
+      let node20Children = node20.querySelector(".children")
+      is(node20Children.childNodes.length, 2, "Node20 has 2 children (21 and 18)");
+
+      let node21 = node20Children.childNodes[0];
+      is(node21.querySelector(".children").textContent.trim(), "line21",
+        "Node21 only has a text node child");
+
+      let node18 = node20Children.childNodes[1];
+      is(node18.querySelector(".open .attreditor .attr-value").textContent.trim(),
+        "node18", "Node20's second child is indeed node18");
     }
   }
 ];
 
 let test = asyncTest(function*() {
-  info("Creating the helper tab for parsing");
-  let parseTab = yield addTab("data:text/html,<html></html>");
-  let parseDoc = content.document;
-
-  info("Creating the test tab");
-  let contentTab = yield addTab(TEST_URL);
-  let doc = content.document;
-  // Strip whitespace in the document for easier comparison
-  stripWhitespace(doc.documentElement);
-
-  let {inspector} = yield openInspector();
-  let markup = inspector.markup;
+  let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Expanding all markup-view nodes");
-  yield markup.expandAll();
+  yield inspector.markup.expandAll();
 
-  for (let step of TEST_DATA) {
-    info("Starting test: " + step.desc);
+  for (let {desc, test, check} of TEST_DATA) {
+    info("Starting test: " + desc);
 
-    info("Executing the test markup mutation, listening for inspector-updated before moving on");
-    let updated = inspector.once("inspector-updated");
-    step.test();
-    yield updated;
+    info("Executing the test markup mutation");
+    let onUpdated = inspector.once("inspector-updated");
+    let onMutation = inspector.once("markupmutation");
+    test();
+    yield onUpdated.then(onMutation);
 
     info("Expanding all markup-view nodes to make sure new nodes are imported");
-    yield markup.expandAll();
+    yield inspector.markup.expandAll();
 
-    info("Comparing the markup-view markup with the content document");
-    compareMarkup(parseDoc, inspector);
+    info("Checking the markup-view content");
+    yield check(inspector);
   }
 });
-
-function stripWhitespace(node) {
-  node.normalize();
-  let iter = node.ownerDocument.createNodeIterator(node,
-    NodeFilter.SHOW_TEXT + NodeFilter.SHOW_COMMENT, null);
-
-  while ((node = iter.nextNode())) {
-    node.nodeValue = node.nodeValue.replace(/\s+/g, '');
-    if (node.nodeType == Node.TEXT_NODE &&
-      !/[^\s]/.exec(node.nodeValue)) {
-      node.parentNode.removeChild(node);
-    }
-  }
-}
-
-function compareMarkup(parseDoc, inspector) {
-  // Grab the text from the markup panel...
-  let markupContainerEl = getContainerForRawNode("body", inspector).elt;
-  let sel = markupContainerEl.ownerDocument.defaultView.getSelection();
-  sel.selectAllChildren(markupContainerEl);
-
-  // Parse it
-  let parseNode = parseDoc.querySelector("body");
-  parseNode.outerHTML = sel;
-  parseNode = parseDoc.querySelector("body");
-
-  // Pull whitespace out of text and comment nodes, there will
-  // be minor unimportant differences.
-  stripWhitespace(parseNode);
-
-  // console.log(contentNode.innerHTML, parseNode.innerHTML);
-  ok(getNode("body").isEqualNode(parseNode),
-    "Markup panel matches what's in the content document.");
-}
--- a/browser/devtools/markupview/test/browser_markupview_mutation_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_mutation_02.js
@@ -3,89 +3,89 @@
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that markup-containers in the markup-view do flash when their
 // corresponding DOM nodes mutate
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_flashing.html";
+
 // The test data contains a list of mutations to test.
 // Each item is an object:
 // - desc: a description of the test step, for better logging
 // - mutate: a function that should make changes to the content DOM
-// - shouldFlash: a function that returns the element that should be the one flashing
+// - flashedNode: [optional] the css selector of the node that is expected to
+//   flash in the markup-view as a result of the mutation.
+//   If missing, the rootNode (".list") will be expected to flash
 const TEST_DATA = [{
   desc: "Adding a new node should flash the new node",
   mutate: (doc, rootNode) => {
     let newLi = doc.createElement("LI");
     newLi.textContent = "new list item";
     rootNode.appendChild(newLi);
   },
-  shouldFlash: rootNode => rootNode.lastElementChild
+  flashedNode: ".list li:nth-child(3)"
 }, {
   desc: "Removing a node should flash its parent",
   mutate: (doc, rootNode) => {
     rootNode.removeChild(rootNode.lastElementChild);
-  },
-  shouldFlash: rootNode => rootNode
+  }
 }, {
   desc: "Re-appending an existing node should only flash this node",
   mutate: (doc, rootNode) => {
     rootNode.appendChild(rootNode.firstElementChild);
   },
-  shouldFlash: rootNode => rootNode.lastElementChild
+  flashedNode: ".list .item:last-child"
 }, {
   desc: "Adding an attribute should flash the node",
   mutate: (doc, rootNode) => {
     rootNode.setAttribute("name-" + Date.now(), "value-" + Date.now());
-  },
-  shouldFlash: rootNode => rootNode
+  }
 }, {
   desc: "Editing an attribute should flash the node",
   mutate: (doc, rootNode) => {
     rootNode.setAttribute("class", "list value-" + Date.now());
-  },
-  shouldFlash: rootNode => rootNode
+  }
 }, {
   desc: "Removing an attribute should flash the node",
   mutate: (doc, rootNode) => {
     rootNode.removeAttribute("class");
-  },
-  shouldFlash: rootNode => rootNode
+  }
 }];
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Getting the <ul.list> root node to test mutations on");
   let rootNode = getNode(".list");
+  let rootNodeFront = yield getNodeFront(".list", inspector);
 
   info("Selecting the last element of the root node before starting");
-  yield selectNode(rootNode.lastElementChild, inspector);
+  yield selectNode(".list .item:nth-child(2)", inspector);
 
-  for (let {mutate, shouldFlash, desc} of TEST_DATA) {
+  for (let {mutate, flashedNode, desc} of TEST_DATA) {
     info("Starting test: " + desc);
 
     info("Mutating the DOM and listening for markupmutation event");
     let mutated = inspector.once("markupmutation");
     let updated = inspector.once("inspector-updated");
     mutate(content.document, rootNode);
     yield mutated;
 
     info("Asserting that the correct markup-container is flashing");
-    assertNodeFlashing(shouldFlash(rootNode), inspector);
+    let flashingNodeFront = rootNodeFront;
+    if (flashedNode) {
+      flashingNodeFront = yield getNodeFront(flashedNode, inspector);
+    }
+    yield assertNodeFlashing(flashingNodeFront, inspector);
 
     // Making sure the inspector has finished updating before moving on
     yield updated;
   }
 });
 
-function assertNodeFlashing(node, inspector) {
-  let container = getContainerForRawNode(node, inspector);
-
-  if (!container) {
-    ok(false, "Node not found");
-  } else {
-    ok(container.tagState.classList.contains("theme-bg-contrast"),
-      "Node is flashing");
-  }
+function* assertNodeFlashing(nodeFront, inspector) {
+  let container = getContainerForNodeFront(nodeFront, inspector);
+  ok(container, "Markup container for node found");
+  ok(container.tagState.classList.contains("theme-bg-contrast"),
+    "Markup container for node is flashing");
 }
--- a/browser/devtools/markupview/test/browser_markupview_navigation.js
+++ b/browser/devtools/markupview/test/browser_markupview_navigation.js
@@ -109,17 +109,17 @@ function pressKey(key) {
       break;
     case "home":
       EventUtils.synthesizeKey("VK_HOME", {});
       break;
   }
 }
 
 function checkSelectedNode(key, className, inspector) {
-  let node = inspector.selection.node;
+  let node = inspector.selection.nodeFront;
 
   if (className == "*comment*") {
     is(node.nodeType, Node.COMMENT_NODE, "Found a comment after pressing " + key);
   } else if (className == "*text*") {
     is(node.nodeType, Node.TEXT_NODE, "Found text after pressing " + key);
   } else if (className == "*doctype*") {
     is(node.nodeType, Node.DOCUMENT_TYPE_NODE, "Found the doctype after pressing " + key);
   } else {
--- a/browser/devtools/markupview/test/browser_markupview_node_not_displayed_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_node_not_displayed_01.js
@@ -21,13 +21,14 @@ const TEST_DATA = [
   {selector: "#visibility-hidden", isDisplayed: true}
 ];
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   for (let {selector, isDisplayed} of TEST_DATA) {
     info("Getting node " + selector);
-    let container = getContainerForRawNode(selector, inspector);
+    let nodeFront = yield getNodeFront(selector, inspector);
+    let container = getContainerForNodeFront(nodeFront, inspector);
     is(!container.elt.classList.contains("not-displayed"), isDisplayed,
       "The container for " + selector + " is marked as displayed " + isDisplayed);
   }
 });
--- a/browser/devtools/markupview/test/browser_markupview_node_not_displayed_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_node_not_displayed_02.js
@@ -93,40 +93,38 @@ let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   for (let data of TEST_DATA) {
     info("Running test case: " + data.desc);
     yield runTestData(inspector, data);
   }
 });
 
-function runTestData(inspector, {selector, before, changeStyle, after}) {
-  let def = promise.defer();
-
+function* runTestData(inspector, {selector, before, changeStyle, after}) {
   info("Getting the " + selector + " test node");
-  let container = getContainerForRawNode(selector, inspector);
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
   is(!container.elt.classList.contains("not-displayed"), before,
     "The container is marked as " + (before ? "shown" : "hidden"));
 
   info("Listening for the display-change event");
-  inspector.markup.walker.once("display-change", nodes => {
-    info("Verifying that the list of changed nodes include our container");
-
-    ok(nodes.length, "The display-change event was received with a nodes");
-    let foundContainer = false;
-    for (let node of nodes) {
-      if (inspector.markup.getContainer(node) === container) {
-        foundContainer = true;
-        break;
-      }
-    }
-    ok(foundContainer, "Container is part of the list of changed nodes");
-
-    is(!container.elt.classList.contains("not-displayed"), after,
-      "The container is marked as " + (after ? "shown" : "hidden"));
-    def.resolve();
-  });
+  let onDisplayChanged = promise.defer();
+  inspector.markup.walker.once("display-change", onDisplayChanged.resolve);
 
   info("Making style changes");
   changeStyle(content.document, getNode(selector));
+  let nodes = yield onDisplayChanged.promise;
 
-  return def.promise;
+  info("Verifying that the list of changed nodes include our container");
+
+  ok(nodes.length, "The display-change event was received with a nodes");
+  let foundContainer = false;
+  for (let node of nodes) {
+    if (getContainerForNodeFront(node, inspector) === container) {
+      foundContainer = true;
+      break;
+    }
+  }
+  ok(foundContainer, "Container is part of the list of changed nodes");
+
+  is(!container.elt.classList.contains("not-displayed"), after,
+    "The container is marked as " + (after ? "shown" : "hidden"));
 }
--- a/browser/devtools/markupview/test/browser_markupview_pagesize_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_pagesize_01.js
@@ -40,47 +40,47 @@ const TEST_DATA = [{
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Start iterating through the test data");
   for (let step of TEST_DATA) {
     info("Start test: " + step.desc);
 
     if (step.forceReload) {
-      forceReload(inspector);
+      yield forceReload(inspector);
     }
     info("Selecting the node that corresponds to " + step.selector);
     yield selectNode(step.selector, inspector);
 
     info("Checking that the right nodes are shwon");
-    assertChildren(step.expected, inspector);
+    yield assertChildren(step.expected, inspector);
   }
 
   info("Checking that clicking the more button loads everything");
-  clickShowMoreNodes(inspector);
+  yield clickShowMoreNodes(inspector);
   yield inspector.markup._waitForChildren();
-  assertChildren("abcdefghijklmnopqrstuvwxyz", inspector);
+  yield assertChildren("abcdefghijklmnopqrstuvwxyz", inspector);
 });
 
-function assertChildren(expected, inspector) {
-  let container = getContainerForRawNode("body", inspector);
+function* assertChildren(expected, inspector) {
+  let container = yield getContainerForSelector("body", inspector);
   let found = "";
   for (let child of container.children.children) {
     if (child.classList.contains("more-nodes")) {
       found += "*more*";
     } else {
       found += child.container.node.getAttribute("id");
     }
   }
   is(found, expected, "Got the expected children.");
 }
 
-function forceReload(inspector) {
-  let container = getContainerForRawNode("body", inspector);
+function* forceReload(inspector) {
+  let container = yield getContainerForSelector("body", inspector);
   container.childrenDirty = true;
 }
 
-function clickShowMoreNodes(inspector) {
-  let container = getContainerForRawNode("body", inspector);
+function* clickShowMoreNodes(inspector) {
+  let container = yield getContainerForSelector("body", inspector);
   let button = container.elt.querySelector("button");
   let win = button.ownerDocument.defaultView;
   EventUtils.sendMouseEvent({type: "click"}, button, win);
 }
--- a/browser/devtools/markupview/test/browser_markupview_pagesize_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_pagesize_02.js
@@ -20,27 +20,26 @@ let test = asyncTest(function*() {
   yield clickContainer("ul", inspector);
   info("Reloading the page with the UL node selected will expand its children");
   yield reloadPage(inspector);
   yield inspector.markup._waitForChildren();
 
   info("Click on the 'show all nodes' button in the UL's list of children");
   yield showAllNodes(inspector);
 
-  assertAllNodesAreVisible(inspector);
+  yield assertAllNodesAreVisible(inspector);
 });
 
-function showAllNodes(inspector) {
-  let container = getContainerForRawNode("ul", inspector);
+function* showAllNodes(inspector) {
+  let container = yield getContainerForSelector("ul", inspector);
   let button = container.elt.querySelector("button");
   ok(button, "All nodes button is here");
   let win = button.ownerDocument.defaultView;
 
   EventUtils.sendMouseEvent({type: "click"}, button, win);
-  return inspector.markup._waitForChildren();
+  yield inspector.markup._waitForChildren();
 }
 
-function assertAllNodesAreVisible(inspector) {
-  let ul = getNode("ul");
-  let container = getContainerForRawNode(ul, inspector);
+function* assertAllNodesAreVisible(inspector) {
+  let container = yield getContainerForSelector("ul", inspector);
   ok(!container.elt.querySelector("button"), "All nodes button isn't here anymore");
-  is(container.children.childNodes.length, ul.children.length);
+  is(container.children.childNodes.length, getNode("ul").children.length);
 }
--- a/browser/devtools/markupview/test/browser_markupview_search_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_search_01.js
@@ -8,34 +8,38 @@
 // selects the right nodes in the markup-view, even when those nodes are deeply
 // nested (and therefore not attached yet when the markup-view is initialized).
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_search.html";
 
 let test = asyncTest(function*() {
   let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
 
-  ok(!getContainerForRawNode("em", inspector),
-    "The <em> tag isn't present yet in the markup-view");
+  let container = yield getContainerForSelector("em", inspector);
+  ok(!container, "The <em> tag isn't present yet in the markup-view");
 
   // Searching for the innermost element first makes sure that the inspector
   // back-end is able to attach the resulting node to the tree it knows at the
   // moment. When the inspector is started, the <body> is the default selected
   // node, and only the parents up to the ROOT are known, and its direct children
   info("searching for the innermost child: <em>");
   let updated = inspector.once("inspector-updated");
   searchUsingSelectorSearch("em", inspector);
   yield updated;
 
-  ok(getContainerForRawNode("em", inspector),
-    "The <em> tag is now imported in the markup-view");
-  is(inspector.selection.node, getNode("em"),
+  container = yield getContainerForSelector("em", inspector);
+  ok(container, "The <em> tag is now imported in the markup-view");
+
+  let nodeFront = yield getNodeFront("em", inspector);
+  is(inspector.selection.nodeFront, nodeFront,
     "The <em> tag is the currently selected node");
 
   info("searching for other nodes too");
   for (let node of ["span", "li", "ul"]) {
     let updated = inspector.once("inspector-updated");
     searchUsingSelectorSearch(node, inspector);
     yield updated;
-    is(inspector.selection.node, getNode(node),
+
+    nodeFront = yield getNodeFront(node, inspector);
+    is(inspector.selection.nodeFront, nodeFront,
       "The <" + node + "> tag is the currently selected node");
   }
 });
--- a/browser/devtools/markupview/test/browser_markupview_tag_edit_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_tag_edit_02.js
@@ -8,39 +8,38 @@
 
 const TEST_URL = "data:text/html,<div id='test-div'>Test modifying my ID attribute</div>";
 
 let test = asyncTest(function*() {
   info("Opening the inspector on the test page");
   let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Selecting the test node");
-  let node = content.document.getElementById("test-div");
-  yield selectNode(node, inspector);
+  yield selectNode("#test-div", inspector);
 
   info("Verify attributes, only ID should be there for now");
-  assertAttributes(node, {
+  assertAttributes("#test-div", {
     id: "test-div"
   });
 
   info("Focus the ID attribute and change its content");
-  let editor = getContainerForRawNode(node, inspector).editor;
+  let {editor} = yield getContainerForSelector("#test-div", inspector);
   let attr = editor.attrs["id"].querySelector(".editable");
   let mutated = inspector.once("markupmutation");
   setEditableFieldValue(attr,
     attr.textContent + ' class="newclass" style="color:green"', inspector);
   yield mutated;
 
   info("Verify attributes, should have ID, class and style");
-  assertAttributes(node, {
+  assertAttributes("#test-div", {
     id: "test-div",
     class: "newclass",
     style: "color:green"
   });
 
   info("Trying to undo the change");
   yield undoChange(inspector);
-  assertAttributes(node, {
+  assertAttributes("#test-div", {
     id: "test-div"
   });
 
   yield inspector.once("inspector-updated");
 });
--- a/browser/devtools/markupview/test/browser_markupview_tag_edit_03.js
+++ b/browser/devtools/markupview/test/browser_markupview_tag_edit_03.js
@@ -9,31 +9,31 @@
 const TEST_URL = "data:text/html,<div id='retag-me'><div id='retag-me-2'></div></div>";
 
 let test = asyncTest(function*() {
   let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
 
   yield inspector.markup.expandAll();
 
   info("Selecting the test node");
-  let node = content.document.getElementById("retag-me");
+  let node = content.document.querySelector("#retag-me");
   let child = content.document.querySelector("#retag-me-2");
-  yield selectNode(node, inspector);
+  yield selectNode("#retag-me", inspector);
 
-  let container = getContainerForRawNode(node, inspector);
+  let container = yield getContainerForSelector("#retag-me", inspector);
   is(node.tagName, "DIV", "We've got #retag-me element, it's a DIV");
   ok(container.expanded, "It is expanded");
   is(child.parentNode, node, "Child #retag-me-2 is inside #retag-me");
 
   info("Changing the tagname");
   let mutated = inspector.once("markupmutation");
   let tagEditor = container.editor.tag;
   setEditableFieldValue(tagEditor, "p", inspector);
   yield mutated;
 
   info("Checking that the tagname change was done");
-  let node = content.document.getElementById("retag-me");
-  let container = getContainerForRawNode(node, inspector);
+  let node = content.document.querySelector("#retag-me");
+  let container = yield getContainerForSelector("#retag-me", inspector);
   is(node.tagName, "P", "We've got #retag-me, it should now be a P");
   ok(container.expanded, "It is still expanded");
   ok(container.selected, "It is still selected");
   is(child.parentNode, node, "Child #retag-me-2 is still inside #retag-me");
 });
--- a/browser/devtools/markupview/test/browser_markupview_tag_edit_04.js
+++ b/browser/devtools/markupview/test/browser_markupview_tag_edit_04.js
@@ -7,24 +7,24 @@
 // Tests that a node can be deleted from the markup-view with the delete key
 
 const TEST_URL = "data:text/html,<div id='delete-me'></div>";
 
 let test = asyncTest(function*() {
   let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Selecting the test node by clicking on it to make sure it receives focus");
-  let node = content.document.getElementById("delete-me");
-  yield clickContainer(node, inspector);
+  let node = content.document.querySelector("#delete-me");
+  yield clickContainer("#delete-me", inspector);
 
   info("Deleting the element with the keyboard");
   let mutated = inspector.once("markupmutation");
   EventUtils.sendKey("delete", inspector.panelWin);
   yield mutated;
 
   info("Checking that it's gone, baby gone!");
-  ok(!content.document.getElementById("delete-me"), "The test node does not exist");
+  ok(!content.document.querySelector("#delete-me"), "The test node does not exist");
 
   yield undoChange(inspector);
-  ok(content.document.getElementById("delete-me"), "The test node is back!");
+  ok(content.document.querySelector("#delete-me"), "The test node is back!");
 
   yield inspector.once("inspector-updated");
 });
--- a/browser/devtools/markupview/test/browser_markupview_tag_edit_08.js
+++ b/browser/devtools/markupview/test/browser_markupview_tag_edit_08.js
@@ -31,17 +31,17 @@ function* testCollapsedLongAttribute(ins
   yield onMutated;
 
   assertAttributes("#node24", {
     id: "node24",
     "class": "",
     "data-long": LONG_ATTRIBUTE
   });
 
-  let editor = getContainerForRawNode("#node24", inspector).editor;
+  let {editor} = yield getContainerForSelector("#node24", inspector);
   let attr = editor.attrs["data-long"].querySelector(".editable");
 
   // Check to make sure it has expanded after focus
   attr.focus();
   EventUtils.sendKey("return", inspector.panelWin);
   let input = inplaceEditor(attr).input;
   is (input.value, 'data-long="' + LONG_ATTRIBUTE + '"');
   EventUtils.sendKey("escape", inspector.panelWin);
@@ -64,17 +64,17 @@ function* testModifyInlineStyleWithQuote
   info("Modify inline style containing \"");
 
   assertAttributes("#node26", {
     id: "node26",
     style: 'background-image: url("moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F");'
   });
 
   let onMutated = inspector.once("markupmutation");
-  let editor = getContainerForRawNode("#node26", inspector).editor;
+  let {editor} = yield getContainerForSelector("#node26", inspector);
   let attr = editor.attrs["style"].querySelector(".editable");
 
   attr.focus();
   EventUtils.sendKey("return", inspector.panelWin);
 
   let input = inplaceEditor(attr).input;
   let value = input.value;
 
@@ -100,17 +100,17 @@ function* testEditingAttributeWithMixedQ
   info("Modify class containing \" and \'");
 
   assertAttributes("#node27", {
     "id": "node27",
     "class": 'Double " and single \''
   });
 
   let onMutated = inspector.once("markupmutation");
-  let editor = getContainerForRawNode("#node27", inspector).editor;
+  let {editor} = yield getContainerForSelector("#node27", inspector);
   let attr = editor.attrs["class"].querySelector(".editable");
 
   attr.focus();
   EventUtils.sendKey("return", inspector.panelWin);
 
   let input = inplaceEditor(attr).input;
   let value = input.value;
 
--- a/browser/devtools/markupview/test/browser_markupview_textcontent_edit_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_textcontent_edit_01.js
@@ -8,25 +8,38 @@
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_edit.html";
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Expanding all nodes");
   yield inspector.markup.expandAll();
+  yield waitForMultipleChildrenUpdates(inspector);
 
   let node = getNode(".node6").firstChild;
   is(node.nodeValue, "line6", "The test node's text content is correct");
 
   info("Changing the text content");
 
   info("Listening to the markupmutation event");
   let onMutated = inspector.once("markupmutation");
-  let editor = getContainerForRawNode(node, inspector).editor;
-  let field = editor.elt.querySelector("pre");
+  let container = yield getContainerForSelector(".node6", inspector);
+  let field = container.elt.querySelector("pre");
   setEditableFieldValue(field, "New text", inspector);
   yield onMutated;
 
   is(node.nodeValue, "New text", "Test test node's text content has changed");
 
   yield inspector.once("inspector-updated");
 });
+
+// The expand all operation of the markup-view calls itself recursively and
+// there's not one event we can wait for to know when it's done
+function* waitForMultipleChildrenUpdates(inspector) {
+  // As long as child updates are queued up while we wait for an update already
+  // wait again
+  if (inspector.markup._queuedChildUpdates &&
+      inspector.markup._queuedChildUpdates.size) {
+    yield waitForChildrenUpdated(inspector);
+    return yield waitForMultipleChildrenUpdates(inspector);
+  }
+}
--- a/browser/devtools/markupview/test/browser_markupview_toggle_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_toggle_01.js
@@ -7,39 +7,41 @@
 // Test toggling (expand/collapse) elements by clicking on twisties
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_toggle.html";
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Getting the container for the UL parent element");
-  let container = getContainerForRawNode("ul", inspector);
+  let container = yield getContainerForSelector("ul", inspector);
 
   info("Clicking on the UL parent expander, and waiting for children");
   let onChildren = waitForChildrenUpdated(inspector);
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeMouseAtCenter(container.expander, {},
     inspector.markup.doc.defaultView);
   yield onChildren;
   yield onUpdated;
 
   info("Checking that child LI elements have been created");
-  for (let li of content.document.querySelectorAll("li")) {
-    ok(getContainerForRawNode(li, inspector),
-      "A container for the child LI element was created");
+  for (let i = 0; i < content.document.querySelectorAll("li").length; i ++) {
+    let liContainer = yield getContainerForSelector(
+      "li:nth-child(" + (i + 1) + ")", inspector);
+    ok(liContainer, "A container for the child LI element was created");
   }
   ok(container.expanded, "Parent UL container is expanded");
 
   info("Clicking again on the UL expander");
   // No need to wait, this is a local, synchronous operation where nodes are
   // only hidden from the view, not destroyed
   EventUtils.synthesizeMouseAtCenter(container.expander, {},
     inspector.markup.doc.defaultView);
 
   info("Checking that child LI elements have been hidden");
-  for (let li of content.document.querySelectorAll("li")) {
-    let liContainer = getContainerForRawNode(li, inspector);
+  for (let i = 0; i < content.document.querySelectorAll("li").length; i ++) {
+    let liContainer = yield getContainerForSelector(
+      "li:nth-child(" + (i + 1) + ")", inspector);
     is(liContainer.elt.getClientRects().length, 0,
       "The container for the child LI element was hidden");
   }
   ok(!container.expanded, "Parent UL container is collapsed");
 });
--- a/browser/devtools/markupview/test/browser_markupview_toggle_02.js
+++ b/browser/devtools/markupview/test/browser_markupview_toggle_02.js
@@ -7,39 +7,41 @@
 // Test toggling (expand/collapse) elements by dbl-clicking on tag lines
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_toggle.html";
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Getting the container for the UL parent element");
-  let container = getContainerForRawNode("ul", inspector);
+  let container = yield getContainerForSelector("ul", inspector);
 
   info("Dbl-clicking on the UL parent expander, and waiting for children");
   let onChildren = waitForChildrenUpdated(inspector);
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeMouseAtCenter(container.tagLine, {clickCount: 2},
     inspector.markup.doc.defaultView);
   yield onChildren;
   yield onUpdated;
 
   info("Checking that child LI elements have been created");
-  for (let li of content.document.querySelectorAll("li")) {
-    ok(getContainerForRawNode(li, inspector),
-      "A container for the child LI element was created");
+  for (let i = 0; i < content.document.querySelectorAll("li").length; i ++) {
+    let liContainer = yield getContainerForSelector(
+      "li:nth-child(" + (i + 1) + ")", inspector);
+    ok(liContainer, "A container for the child LI element was created");
   }
   ok(container.expanded, "Parent UL container is expanded");
 
   info("Dbl-clicking again on the UL expander");
   // No need to wait, this is a local, synchronous operation where nodes are
   // only hidden from the view, not destroyed
   EventUtils.synthesizeMouseAtCenter(container.tagLine, {clickCount: 2},
     inspector.markup.doc.defaultView);
 
   info("Checking that child LI elements have been hidden");
-  for (let li of content.document.querySelectorAll("li")) {
-    let liContainer = getContainerForRawNode(li, inspector);
+  for (let i = 0; i < content.document.querySelectorAll("li").length; i ++) {
+    let liContainer = yield getContainerForSelector(
+      "li:nth-child(" + (i + 1) + ")", inspector);
     is(liContainer.elt.getClientRects().length, 0,
       "The container for the child LI element was hidden");
   }
   ok(!container.expanded, "Parent UL container is collapsed");
 });
--- a/browser/devtools/markupview/test/browser_markupview_toggle_03.js
+++ b/browser/devtools/markupview/test/browser_markupview_toggle_03.js
@@ -8,37 +8,40 @@
 // should expand all the descendants
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_toggle.html";
 
 let test = asyncTest(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Getting the container for the UL parent element");
-  let container = getContainerForRawNode("ul", inspector);
+  let container = yield getContainerForSelector("ul", inspector);
 
   info("Alt-clicking on the UL parent expander, and waiting for children");
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeMouseAtCenter(container.expander, {altKey: true},
     inspector.markup.doc.defaultView);
   yield onUpdated;
   yield waitForMultipleChildrenUpdates(inspector);
 
   info("Checking that all nodes exist and are expanded");
-  for (let node of content.document.querySelectorAll("ul, li, span, em")) {
-    let nodeContainer = getContainerForRawNode(node, inspector);
-    ok(nodeContainer, "Container for node " + node.tagName + " exists");
+  let nodeList = yield inspector.walker.querySelectorAll(
+    inspector.walker.rootNode, "ul, li, span, em");
+  let nodeFronts = yield nodeList.items();
+  for (let nodeFront of nodeFronts) {
+    let nodeContainer = getContainerForNodeFront(nodeFront, inspector);
+    ok(nodeContainer, "Container for node " + nodeFront.tagName + " exists");
     ok(nodeContainer.expanded,
-      "Container for node " + node.tagName + " is expanded");
+      "Container for node " + nodeFront.tagName + " is expanded");
   }
 });
 
 // The expand all operation of the markup-view calls itself recursively and
 // there's not one event we can wait for to know when it's done
 function* waitForMultipleChildrenUpdates(inspector) {
   // As long as child updates are queued up while we wait for an update already
   // wait again
   if (inspector.markup._queuedChildUpdates &&
       inspector.markup._queuedChildUpdates.size) {
     yield waitForChildrenUpdated(inspector);
     return yield waitForMultipleChildrenUpdates(inspector);
   }
-}
\ No newline at end of file
+}
--- a/browser/devtools/markupview/test/head.js
+++ b/browser/devtools/markupview/test/head.js
@@ -23,29 +23,27 @@ registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.inspector.htmlPanelOpen");
   Services.prefs.clearUserPref("devtools.inspector.sidebarOpen");
   Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
   Services.prefs.clearUserPref("devtools.dump.emit");
   Services.prefs.clearUserPref("devtools.markup.pagesize");
 });
 
 // Auto close the toolbox and close the test tabs when the test ends
-registerCleanupFunction(() => {
-  try {
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.closeToolbox(target);
-  } catch (ex) {
-    dump(ex);
-  }
+registerCleanupFunction(function*() {
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  yield gDevTools.closeToolbox(target);
+
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
 const TEST_URL_ROOT = "http://mochi.test:8888/browser/browser/devtools/markupview/test/";
+const CHROME_BASE = "chrome://mochitests/content/browser/browser/devtools/markupview/test/";
 
 /**
  * Define an async test based on a generator function
  */
 function asyncTest(generator) {
   return () => Task.spawn(generator).then(null, ok.bind(null, false)).then(finish);
 }
 
@@ -53,25 +51,29 @@ function asyncTest(generator) {
  * Add a new test tab in the browser and load the given url.
  * @param {String} url The url to be loaded in the new tab
  * @return a promise that resolves to the tab object when the url is loaded
  */
 function addTab(url) {
   info("Adding a new tab with URL: '" + url + "'");
   let def = promise.defer();
 
-  let tab = gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onload() {
-    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+  // Bug 921935 should bring waitForFocus() support to e10s, which would
+  // probably cover the case of the test losing focus when the page is loading.
+  // For now, we just make sure the window is focused.
+  window.focus();
+
+  let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
+  let linkedBrowser = tab.linkedBrowser;
+
+  linkedBrowser.addEventListener("load", function onload() {
+    linkedBrowser.removeEventListener("load", onload, true);
     info("URL '" + url + "' loading complete");
-    waitForFocus(() => {
-      def.resolve(tab);
-    }, content);
+    def.resolve(tab);
   }, true);
-  content.location = url;
 
   return def.promise;
 }
 
 /**
  * Some tests may need to import one or more of the test helper scripts.
  * A test helper script is simply a js file that contains common test code that
  * is either not common-enough to be in head.js, or that is located in a separate
@@ -119,80 +121,100 @@ function openInspector() {
 
   return def.promise;
 }
 
 /**
  * Simple DOM node accesor function that takes either a node or a string css
  * selector as argument and returns the corresponding node
  * @param {String|DOMNode} nodeOrSelector
- * @return {DOMNode}
+ * @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
+ * doesn't implement *all* of the DOMNode's properties
  */
 function getNode(nodeOrSelector) {
   info("Getting the node for '" + nodeOrSelector + "'");
   return typeof nodeOrSelector === "string" ?
     content.document.querySelector(nodeOrSelector) :
     nodeOrSelector;
 }
 
 /**
+ * Get the NodeFront for a given css selector, via the protocol
+ * @param {String} selector
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @return {Promise} Resolves to the NodeFront instance
+ */
+function getNodeFront(selector, {walker}) {
+  return walker.querySelector(walker.rootNode, selector);
+}
+
+/**
  * Highlight a node and set the inspector's current selection to the node or
  * the first match of the given css selector.
  * @param {String|DOMNode} nodeOrSelector
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise that resolves when the inspector is updated with the new
  * node
  */
 function selectAndHighlightNode(nodeOrSelector, inspector) {
   info("Highlighting and selecting the node " + nodeOrSelector);
 
   let node = getNode(nodeOrSelector);
   let updated = inspector.toolbox.once("highlighter-ready");
   inspector.selection.setNode(node, "test-highlight");
   return updated;
-
 }
 
 /**
- * Set the inspector's current selection to a node or to the first match of the
- * given css selector.
- * @param {String|DOMNode} nodeOrSelector
- * @param {InspectorPanel} inspector
- *        The instance of InspectorPanel currently loaded in the toolbox
- * @param {String} reason
- *        Defaults to "test" which instructs the inspector not to highlight the
- *        node upon selection
- * @return a promise that resolves when the inspector is updated with the new
- * node
+ * Set the inspector's current selection to the first match of the given css
+ * selector
+ * @param {String} selector
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @param {String} reason Defaults to "test" which instructs the inspector not
+ * to highlight the node upon selection
+ * @return {Promise} Resolves when the inspector is updated with the new node
  */
-function selectNode(nodeOrSelector, inspector, reason="test") {
-  info("Selecting the node " + nodeOrSelector);
+let selectNode = Task.async(function*(selector, inspector, reason="test") {
+  info("Selecting the node for '" + selector + "'");
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let updated = inspector.once("inspector-updated");
+  inspector.selection.setNodeFront(nodeFront, reason);
+  yield updated;
+});
 
-  let node = getNode(nodeOrSelector);
-  let updated = inspector.once("inspector-updated");
-  inspector.selection.setNode(node, reason);
-  return updated;
+/**
+ * Get the MarkupContainer object instance that corresponds to the given
+ * NodeFront
+ * @param {NodeFront} nodeFront
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @return {MarkupContainer}
+ */
+function getContainerForNodeFront(nodeFront, {markup}) {
+  return markup.getContainer(nodeFront);
 }
 
 /**
  * Get the MarkupContainer object instance that corresponds to the given
- * HTML node
- * @param {DOMNode|String} nodeOrSelector The DOM node for which the
- * container is required
+ * selector
+ * @param {String} selector
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * loaded in the toolbox
  * @return {MarkupContainer}
  */
-function getContainerForRawNode(nodeOrSelector, {markup}) {
-  let front = markup.walker.frontForRawNode(getNode(nodeOrSelector));
-  let container = markup.getContainer(front);
-  info("Markup-container object for " + nodeOrSelector + " " + container);
+let getContainerForSelector = Task.async(function*(selector, inspector) {
+  info("Getting the markup-container for node " + selector);
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
+  info("Found markup-container " + container);
   return container;
-}
+});
 
 /**
  * Using the markupview's _waitForChildren function, wait for all queued
  * children updates to be handled.
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * loaded in the toolbox
  * @return a promise that resolves when all queued children updates have been
  * handled
@@ -203,48 +225,56 @@ function waitForChildrenUpdated({markup}
   markup._waitForChildren().then(() => {
     executeSoon(def.resolve);
   });
   return def.promise;
 }
 
 /**
  * Simulate a mouse-over on the markup-container (a line in the markup-view)
- * that corresponds to the node or selector passed.
- * @param {String|DOMNode} nodeOrSelector
- * @param {InspectorPanel} inspector The instance of InspectorPanel currently loaded in the toolbox
- * @return a promise that resolves when the container is hovered and the higlighter
+ * that corresponds to the selector passed.
+ * @param {String} selector
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @return {Promise} Resolves when the container is hovered and the higlighter
  * is shown on the corresponding node
  */
-function hoverContainer(nodeOrSelector, inspector) {
-  info("Hovering over the markup-container for node " + nodeOrSelector);
+let hoverContainer = Task.async(function*(selector, inspector) {
+  info("Hovering over the markup-container for node " + selector);
+
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
+
   let highlit = inspector.toolbox.once("node-highlight");
-  let container = getContainerForRawNode(getNode(nodeOrSelector), inspector);
   EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
     inspector.markup.doc.defaultView);
   return highlit;
-}
+});
 
 /**
  * Simulate a click on the markup-container (a line in the markup-view)
- * that corresponds to the node or selector passed.
- * @param {String|DOMNode} nodeOrSelector
- * @param {InspectorPanel} inspector The instance of InspectorPanel currently loaded in the toolbox
- * @return a promise that resolves when the node has been selected.
+ * that corresponds to the selector passed.
+ * @param {String} selector
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @return {Promise} Resolves when the node has been selected.
  */
-function clickContainer(nodeOrSelector, inspector) {
-  info("Clicking on the markup-container for node " + nodeOrSelector);
+let clickContainer = Task.async(function*(selector, inspector) {
+  info("Clicking on the markup-container for node " + selector);
+
+  let nodeFront = yield getNodeFront(selector, inspector);
+  let container = getContainerForNodeFront(nodeFront, inspector);
+
   let updated = inspector.once("inspector-updated");
-  let container = getContainerForRawNode(getNode(nodeOrSelector), inspector);
   EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousedown"},
     inspector.markup.doc.defaultView);
   EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mouseup"},
     inspector.markup.doc.defaultView);
   return updated;
-}
+});
 
 /**
  * Checks if the highlighter is visible currently
  * @return {Boolean}
  */
 function isHighlighterVisible() {
   let highlighter = gBrowser.selectedBrowser.parentNode
                             .querySelector(".highlighter-container .box-model-root");
@@ -283,49 +313,49 @@ function setEditableFieldValue(field, va
   EventUtils.sendKey("return", inspector.panelWin);
   let input = inplaceEditor(field).input;
   ok(input, "Found editable field for setting value: " + value);
   input.value = value;
   EventUtils.sendKey("return", inspector.panelWin);
 }
 
 /**
- * Focus the new-attribute inplace-editor field of the nodeOrSelector's markup
- * container, and enters the given text, then wait for it to be applied and the
- * for the node to mutates (when new attribute(s) is(are) created)
- * @param {DOMNode|String} nodeOrSelector The node or node selector to edit.
+ * Focus the new-attribute inplace-editor field of a node's markup container
+ * and enters the given text, then wait for it to be applied and the for the
+ * node to mutates (when new attribute(s) is(are) created)
+ * @param {String} selector The selector for the node to edit.
  * @param {String} text The new attribute text to be entered (e.g. "id='test'")
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * loaded in the toolbox
  * @return a promise that resolves when the node has mutated
  */
-function addNewAttributes(nodeOrSelector, text, inspector) {
-  info("Entering text '" + text + "' in node '" + nodeOrSelector + "''s new attribute field");
+let addNewAttributes = Task.async(function*(selector, text, inspector) {
+  info("Entering text '" + text + "' in node '" + selector + "''s new attribute field");
 
-  let container = getContainerForRawNode(nodeOrSelector, inspector);
-  ok(container, "The container for '" + nodeOrSelector + "' was found");
+  let container = yield getContainerForSelector(selector, inspector);
+  ok(container, "The container for '" + selector + "' was found");
 
   info("Listening for the markupmutation event");
   let nodeMutated = inspector.once("markupmutation");
   setEditableFieldValue(container.editor.newAttr, text, inspector);
-  return nodeMutated;
-}
+  yield nodeMutated;
+});
 
 /**
  * Checks that a node has the given attributes
  *
- * @param {DOMNode|String} nodeOrSelector The node or node selector to check.
+ * @param {String} selector The node or node selector to check.
  * @param {Object} attrs An object containing the attributes to check.
  *        e.g. {id: "id1", class: "someclass"}
  *
  * Note that node.getAttribute() returns attribute values provided by the HTML
  * parser. The parser only provides unescaped entities so &amp; will return &.
  */
-function assertAttributes(nodeOrSelector, attrs) {
-  let node = getNode(nodeOrSelector);
+function assertAttributes(selector, attrs) {
+  let node = getNode(selector);
 
   is(node.attributes.length, Object.keys(attrs).length,
     "Node has the correct number of attributes.");
   for (let attr in attrs) {
     is(node.getAttribute(attr), attrs[attr],
       "Node has the correct " + attr + " attribute.");
   }
 }
--- a/browser/devtools/markupview/test/helper_attributes_test_runner.js
+++ b/browser/devtools/markupview/test/helper_attributes_test_runner.js
@@ -16,21 +16,20 @@
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * opened
  * @return a promise that resolves when the tests have run
  */
 function runAddAttributesTests(tests, nodeOrSelector, inspector) {
   info("Running " + tests.length + " add-attributes tests");
   return Task.spawn(function*() {
     info("Selecting the test node");
-    let div = getNode("div");
-    yield selectNode(div, inspector);
+    yield selectNode("div", inspector);
 
     for (let test of tests) {
-      yield runAddAttributesTest(test, div, inspector);
+      yield runAddAttributesTest(test, "div", inspector);
     }
 
     yield inspector.once("inspector-updated");
   });
 }
 
 /**
  * Run a single add-attribute test.
@@ -43,32 +42,32 @@ function runAddAttributesTests(tests, no
  *        used to check the attributes on the test element
  *        - validate {Function} optional extra function that will be called after
  *        the attributes have been added and which should be used to assert some
  *        more things this test runner might not be checking. The function will
  *        be called with the following arguments:
  *          - {DOMNode} The element being tested
  *          - {MarkupContainer} The corresponding container in the markup-view
  *          - {InspectorPanel} The instance of the InspectorPanel opened
- * @param {DOMNode|String} nodeOrSelector The node or node selector
- * corresponding to the test element
+ * @param {String} selector The node selector corresponding to the test element
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * opened
  */
-function* runAddAttributesTest(test, nodeOrSelector, inspector) {
-  let element = getNode(nodeOrSelector);
+function* runAddAttributesTest(test, selector, inspector) {
+  let element = getNode(selector);
 
   info("Starting add-attribute test: " + test.desc);
-  yield addNewAttributes(element, test.text, inspector);
+  yield addNewAttributes(selector, test.text, inspector);
 
   info("Assert that the attribute(s) has/have been applied correctly");
   assertAttributes(element, test.expectedAttributes);
 
   if (test.validate) {
-    test.validate(element, getContainerForRawNode(element, inspector), inspector);
+    let container = yield getContainerForSelector(selector, inspector);
+    test.validate(element, container, inspector);
   }
 
   info("Undo the change");
   yield undoChange(inspector);
 
   info("Assert that the attribute(s) has/have been removed correctly");
   assertAttributes(element, {});
 }
@@ -123,17 +122,17 @@ function* runEditAttributesTest(test, in
   info("Selecting the test node " + test.node);
   yield selectNode(test.node, inspector);
 
   info("Asserting that the node has the right attributes to start with");
   assertAttributes(test.node, test.originalAttributes);
 
   info("Editing attribute " + test.name + " with value " + test.value);
 
-  let container = getContainerForRawNode(test.node, inspector);
+  let container = yield getContainerForSelector(test.node, inspector);
   ok(container && container.editor, "The markup-container for " + test.node +
     " was found");
 
   info("Listening for the markupmutation event");
   let nodeMutated = inspector.once("markupmutation");
   let attr = container.editor.attrs[test.name].querySelector(".editable");
   setEditableFieldValue(attr, test.value, inspector);
   yield nodeMutated;
--- a/browser/devtools/markupview/test/helper_outerhtml_test_runner.js
+++ b/browser/devtools/markupview/test/helper_outerhtml_test_runner.js
@@ -37,16 +37,18 @@ function runEditOuterHTMLTests(tests, in
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * opened
  */
 function* runEditOuterHTMLTest(test, inspector) {
   info("Running an edit outerHTML test on '" + test.selector + "'");
   yield selectNode(test.selector, inspector);
   let oldNodeFront = inspector.selection.nodeFront;
 
+  let onUpdated = inspector.once("inspector-updated");
+
   info("Listening for the markupmutation event");
   // This event fires once the outerHTML is set, with a target as the parent node and a type of "childList".
   let mutated = inspector.once("markupmutation");
   info("Editing the outerHTML");
   inspector.markup.updateNodeOuterHTML(inspector.selection.nodeFront, test.newHTML, test.oldHTML);
   let mutations = yield mutated;
   ok(true, "The markupmutation event has fired, mutation done");
 
@@ -55,27 +57,27 @@ function* runEditOuterHTMLTest(test, ins
   let mutation = mutations[0];
   let isFromOuterHTML = mutation.removed.some(n => n === oldNodeFront);
 
   ok(isFromOuterHTML, "The node is in the 'removed' list of the mutation");
   is(mutation.type, "childList", "Mutation is a childList after updating outerHTML");
   is(mutation.target, nodeFront, "Parent node is selected immediately after setting outerHTML");
 
   // Wait for node to be reselected after outerHTML has been set
-  yield inspector.selection.once("new-node");
+  yield inspector.selection.once("new-node-front");
 
   // Typically selectedNode will === pageNode, but if a new element has been injected in front
   // of it, this will not be the case.  If this happens.
-  let selectedNode = inspector.selection.node;
-  let nodeFront = inspector.selection.nodeFront;
+  let selectedNodeFront = inspector.selection.nodeFront;
+  let pageNodeFront = yield inspector.walker.querySelector(inspector.walker.rootNode, test.selector);
   let pageNode = getNode(test.selector);
 
   if (test.validate) {
-    test.validate(pageNode, selectedNode);
+    yield test.validate(pageNode, pageNodeFront, selectedNodeFront, inspector);
   } else {
-    is(pageNode, selectedNode, "Original node (grabbed by selector) is selected");
+    is(pageNodeFront, selectedNodeFront, "Original node (grabbed by selector) is selected");
     is(pageNode.outerHTML, test.newHTML, "Outer HTML has been updated");
   }
 
   // Wait for the inspector to be fully updated to avoid causing errors by
   // abruptly closing hanging requests when the test ends
-  yield inspector.once("inspector-updated");
+  yield onUpdated;
 }
--- a/toolkit/devtools/server/actors/highlighter.js
+++ b/toolkit/devtools/server/actors/highlighter.js
@@ -89,18 +89,20 @@ let HighlighterActor = exports.Highlight
     }
   },
 
   get conn() this._inspector && this._inspector.conn,
 
   destroy: function() {
     protocol.Actor.prototype.destroy.call(this);
     if (this._boxModelHighlighter) {
-      this._boxModelHighlighter.off("ready", this._highlighterReady);
-      this._boxModelHighlighter.off("hide", this._highlighterHidden);
+      if (supportXULBasedHighlighter(this._tabActor)) {
+        this._boxModelHighlighter.off("ready", this._highlighterReady);
+        this._boxModelHighlighter.off("hide", this._highlighterHidden);
+      }
       this._boxModelHighlighter.destroy();
       this._boxModelHighlighter = null;
     }
     this._autohide = null;
     this._inspector = null;
     this._walker = null;
     this._tabActor = null;
   },