More work
authorDave Camp <dcamp@mozilla.com>
Fri, 28 Jun 2013 16:36:02 -0700
changeset 13 d178fa3c570108d79814471bb17c5f5e2a3bed57
parent 12 8c3895ba691621a5462cfbdbea09c516637d4a5f
child 14 d8075e02936f0f83b20c47a5399f97624f4a6813
push id14
push userdcamp@campd.org
push dateFri, 28 Jun 2013 23:36:07 +0000
More work
android-browser.diff
android-crap.diff
inspector-delete-node.diff
inspector-remote-delete-node.diff
series
rename from android-crap.diff
rename to android-browser.diff
--- a/inspector-delete-node.diff
+++ b/inspector-delete-node.diff
@@ -1,28 +1,32 @@
 # HG changeset patch
 # User Dave Camp <dcamp@mozilla.com>
 # Date 1371477173 25200
 #      Mon Jun 17 06:52:53 2013 -0700
 # Node ID 877aba69dfd4ad1f638be4691802b721d6ee54c0
-# Parent  2ccc31df1f64ef58ad9db4f76a2a5caa5507d141
+# Parent 0346910d331ca63edf112851e7efe2213c436bf3
 imported patch inspector-delete-node.diff
 
 diff --git a/toolkit/devtools/server/actors/inspector.js b/toolkit/devtools/server/actors/inspector.js
 --- a/toolkit/devtools/server/actors/inspector.js
 +++ b/toolkit/devtools/server/actors/inspector.js
-@@ -1376,16 +1376,48 @@ var WalkerActor = protocol.ActorClass({
-     request: {
+@@ -1377,16 +1377,56 @@ var WalkerActor = protocol.ActorClass({
        node: Arg(0, "domnode")
      },
      response: {
        value: RetVal("longstring")
      }
    }),
  
+   /**
++   * Removes a node from its parent node.
++   *   
++   * @returns The node's nextSibling before it was removed.
++   */
 +  removeNode: method(function(node) {
 +    if ((node.rawNode.ownerDocument &&
 +         node.rawNode.ownerDocument.documentElement === this.rawNode) ||
 +         node.rawNode.nodeType === Ci.nsIDOMNode.DOCUMENT_NODE) {
 +      throw Error("Cannot remove document or document elements.");
 +    }
 +    let nextSibling = this.nextSibling(node);
 +    if (node.rawNode.parentNode) {
@@ -34,27 +38,282 @@ diff --git a/toolkit/devtools/server/act
 +    request: {
 +      node: Arg(0, "domnode")
 +    },
 +    response: {
 +      nextSibling: RetVal("domnode", { optional: true })
 +    }
 +  }),
 +
++  /**
++   * Insert a node into the DOM.
++   */
 +  insertBefore: method(function(node, parent, sibling) {
 +    parent.rawNode.insertBefore(node.rawNode, sibling ? sibling.rawNode : null);
 +  }, {
 +    request: {
 +      node: Arg(0, "domnode"),
 +      parent: Arg(1, "domnode"),
 +      sibling: Arg(2, "domnode", { optional: true })
 +    },
 +    response: {}
 +  }),
 +
-   /**
++  /**
     * Get any pending mutation records.  Must be called by the client after
     * the `new-mutations` notification is received.  Returns an array of
     * mutation records.
     *
     * Mutation records have a basic structure:
     *
     * {
+    *   type: attributes|characterData|childList,
+diff --git a/toolkit/devtools/server/tests/mochitest/Makefile.in b/toolkit/devtools/server/tests/mochitest/Makefile.in
+--- a/toolkit/devtools/server/tests/mochitest/Makefile.in
++++ b/toolkit/devtools/server/tests/mochitest/Makefile.in
+@@ -11,21 +11,23 @@ relativesrcdir	= @relativesrcdir@
+ 
+ include $(DEPTH)/config/autoconf.mk
+ 
+ MOCHITEST_CHROME_FILES	= \
+ 	inspector-helpers.js \
+ 	inspector-traversal-data.html \
+ 	test_inspector-changeattrs.html \
+ 	test_inspector-changevalue.html \
++	test_inspector-insert.html \
+ 	test_inspector-mutations-attr.html \
+ 	test_inspector-mutations-childlist.html \
+ 	test_inspector-mutations-frameload.html \
+ 	test_inspector-mutations-value.html \
+ 	test_inspector-release.html \
++	test_inspector-remove.html \
+ 	test_inspector-retain.html \
+ 	test_inspector-pseudoclass-lock.html \
+ 	test_inspector-traversal.html \
+ 	test_unsafeDereference.html \
+ 	nonchrome_unsafeDereference.html \
+ 	$(NULL)
+ 
+ include $(topsrcdir)/config/rules.mk
+diff --git a/toolkit/devtools/server/tests/mochitest/inspector-helpers.js b/toolkit/devtools/server/tests/mochitest/inspector-helpers.js
+--- a/toolkit/devtools/server/tests/mochitest/inspector-helpers.js
++++ b/toolkit/devtools/server/tests/mochitest/inspector-helpers.js
+@@ -150,16 +150,18 @@ function ownershipTreeSize(tree) {
+   return size;
+ }
+ 
+ function assertOwnershipTrees(walker) {
+   let serverTree = serverOwnershipTree(walker);
+   let clientTree = clientOwnershipTree(walker);
+   is(JSON.stringify(clientTree, null, ' '), JSON.stringify(serverTree, null, ' '), "Server and client ownership trees should match.");
+ 
++  dump("ownership tree: " + JSON.stringify(clientTree, null, ' ') + "\n");
++
+   return ownershipTreeSize(clientTree.root);
+ }
+ 
+ // Verify that an actorID is inaccessible both from the client library and the server.
+ function checkMissing(client, actorID) {
+   let deferred = Promise.defer();
+   let front = client.getActor(actorID);
+   ok(!front, "Front shouldn't be accessible from the client for actorID: " + actorID);
+diff --git a/toolkit/devtools/server/tests/mochitest/test_inspector-insert.html b/toolkit/devtools/server/tests/mochitest/test_inspector-insert.html
+new file mode 100644
+--- /dev/null
++++ b/toolkit/devtools/server/tests/mochitest/test_inspector-insert.html
+@@ -0,0 +1,96 @@
++<!DOCTYPE HTML>
++<html>
++<!--
++https://bugzilla.mozilla.org/show_bug.cgi?id=
++-->
++<head>
++  <meta charset="utf-8">
++  <title>Test for Bug </title>
++
++  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
++  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
++  <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
++  <script type="application/javascript;version=1.8">
++Components.utils.import("resource://gre/modules/devtools/Loader.jsm");
++
++const Promise = devtools.require("sdk/core/promise");
++const inspector = devtools.require("devtools/server/actors/inspector");
++
++window.onload = function() {
++  SimpleTest.waitForExplicitFinish();
++  runNextTest();
++}
++
++var gWalker = null;
++var gClient = null;
++
++function assertOwnership() {
++  return assertOwnershipTrees(gWalker);
++}
++
++addTest(function setup() {
++  let url = document.getElementById("inspectorContent").href;
++  attachURL(url, function(err, client, tab, doc) {
++    gInspectee = doc;
++    let {InspectorFront} = devtools.require("devtools/server/actors/inspector");
++    let inspector = InspectorFront(client, tab);
++    promiseDone(inspector.getWalker().then(walker => {
++      ok(walker, "getWalker() should return an actor.");
++      gClient = client;
++      gWalker = walker;
++    }).then(runNextTest));
++  });
++});
++
++addTest(function testRearrange() {
++  let longlist = null;
++  let nodeA = null;
++  let nextNode = null;
++
++  promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(listFront => {
++    longlist = listFront;
++  }).then(() => {
++    return gWalker.children(longlist);
++  }).then(response => {
++    nodeA = response.nodes[0];
++    is(nodeA.id, "a", "Got the expected node.");
++    // Move nodeA to the end of the list.
++    return gWalker.insertBefore(nodeA, longlist, null);
++  }).then(() => {
++    ok(!gInspectee.querySelector("#a").nextSibling, "a should now be at the end of the list.");
++    return gWalker.children(longlist);
++  }).then(response => {
++    is(nodeA, response.nodes[response.nodes.length - 1], "a should now be the last returned child.");
++    // Now move it to the middle of the list.
++    nextNode = response.nodes[13];
++    return gWalker.insertBefore(nodeA, longlist, nextNode);
++  }).then(response => {
++    let sibling = inspector._documentWalker(gInspectee.querySelector("#a")).nextSibling();
++    is(sibling, nextNode.rawNode(), "Node should match the expected next node.");
++    return gWalker.children(longlist);
++  }).then(response => {
++    is(nodeA, response.nodes[13], "a should be where we expect it.");
++    is(nextNode, response.nodes[14], "next node should be where we expect it.");
++  }).then(runNextTest));
++});
++
++addTest(function cleanup() {
++  delete gWalker;
++  delete gClient;
++  runNextTest();
++});
++
++
++  </script>
++</head>
++<body>
++<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
++<a id="inspectorContent" target="_blank" href="inspector-traversal-data.html">Test Document</a>
++<p id="display"></p>
++<div id="content" style="display: none">
++
++</div>
++<pre id="test">
++</pre>
++</body>
++</html>
+diff --git a/toolkit/devtools/server/tests/mochitest/test_inspector-remove.html b/toolkit/devtools/server/tests/mochitest/test_inspector-remove.html
+new file mode 100644
+--- /dev/null
++++ b/toolkit/devtools/server/tests/mochitest/test_inspector-remove.html
+@@ -0,0 +1,96 @@
++<!DOCTYPE HTML>
++<html>
++<!--
++https://bugzilla.mozilla.org/show_bug.cgi?id=
++-->
++<head>
++  <meta charset="utf-8">
++  <title>Test for Bug </title>
++
++  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
++  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
++  <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
++  <script type="application/javascript;version=1.8">
++Components.utils.import("resource://gre/modules/devtools/Loader.jsm");
++
++const Promise = devtools.require("sdk/core/promise");
++const inspector = devtools.require("devtools/server/actors/inspector");
++
++window.onload = function() {
++  SimpleTest.waitForExplicitFinish();
++  runNextTest();
++}
++
++var gWalker = null;
++var gClient = null;
++
++function assertOwnership() {
++  return assertOwnershipTrees(gWalker);
++}
++
++addTest(function setup() {
++  let url = document.getElementById("inspectorContent").href;
++  attachURL(url, function(err, client, tab, doc) {
++    gInspectee = doc;
++    let {InspectorFront} = devtools.require("devtools/server/actors/inspector");
++    let inspector = InspectorFront(client, tab);
++    promiseDone(inspector.getWalker().then(walker => {
++      ok(walker, "getWalker() should return an actor.");
++      gClient = client;
++      gWalker = walker;
++    }).then(runNextTest));
++  });
++});
++
++addTest(function testRemoveSubtree() {
++  let originalOwnershipSize = 0;
++  let longlist = null;
++  let longlistID = null;
++
++  let nextSibling = gInspectee.querySelector("#longlist").nextSibling;
++  // Duplicate the walker logic to skip blank nodes...
++  while (nextSibling && nextSibling.nodeType === Components.interfaces.nsIDOMNode.TEXT_NODE && !/[^\s]/.exec(nextSibling.nodeValue)) {
++    nextSibling = nextSibling.nextSibling;
++  }
++
++  promiseDone(gWalker.querySelector(gWalker.rootNode, "#longlist").then(listFront => {
++    longlist = listFront;
++    longlistID = longlist.actorID;
++  }).then(() => {
++    return gWalker.children(longlist);
++  }).then((items)=> {
++    originalOwnershipSize = assertOwnership();
++    ok(originalOwnershipSize > 26, "Should have at least 26 items in our ownership tree");
++    return gWalker.removeNode(longlist);
++  }).then(nextSiblingFront => {
++    is(nextSiblingFront.rawNode(), nextSibling, "Should have returned the next sibling.");
++    return waitForMutation(gWalker, isChildList);
++  }).then(() => {
++    // Our ownership size should now be 26 fewer (we forgot about #longlist + 26 children, but learned about #longlist's next sibling)
++    let newOwnershipSize = assertOwnership();
++    is(newOwnershipSize, originalOwnershipSize - 26, "Ownership tree should have dropped by 27 nodes");
++    // Now verify that some nodes have gone away
++    return checkMissing(gClient, longlistID);
++  }).then(runNextTest));
++});
++
++addTest(function cleanup() {
++  delete gWalker;
++  delete gClient;
++  runNextTest();
++});
++
++
++  </script>
++</head>
++<body>
++<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
++<a id="inspectorContent" target="_blank" href="inspector-traversal-data.html">Test Document</a>
++<p id="display"></p>
++<div id="content" style="display: none">
++
++</div>
++<pre id="test">
++</pre>
++</body>
++</html>
--- a/inspector-remote-delete-node.diff
+++ b/inspector-remote-delete-node.diff
@@ -1,20 +1,20 @@
 # HG changeset patch
 # User Dave Camp <dcamp@mozilla.com>
 # Date 1371477175 25200
 #      Mon Jun 17 06:52:55 2013 -0700
 # Node ID d226c8a4645c57624d721ab57c3b8fb1c98d8822
-# Parent  00aba1b028d43fb8dc1604f6fa3c1df3243feae0
+# Parent 39dfcd31bc12451e6ba0c7eab89fc34e28682c59
 imported patch inspector-remote-delete-node.diff
 
 diff --git a/browser/devtools/inspector/inspector-panel.js b/browser/devtools/inspector/inspector-panel.js
 --- a/browser/devtools/inspector/inspector-panel.js
 +++ b/browser/devtools/inspector/inspector-panel.js
-@@ -681,18 +681,17 @@ InspectorPanel.prototype = {
+@@ -685,18 +685,17 @@ InspectorPanel.prototype = {
      }
  
      // If the markup panel is active, use the markup panel to delete
      // the node, making this an undoable action.
      if (this.markup) {
        this.markup.deleteNode(this.selection.nodeFront);
      } else {
        // remove the node from content
@@ -94,17 +94,17 @@ diff --git a/browser/devtools/markupview
 +      this.undo.do(() => {
 +        if (container.selected) {
 +          this.navigate(this._containers.get(parent));
 +        }
 +        this.walker.removeNode(aNode).then(nextSibling => {
 +          sibling = nextSibling;
 +        });
 +      }, () => {
-+        this.walker.insertBefore(aNode, parent);
++        this.walker.insertBefore(aNode, parent, sibling);
 +      });
 +    }).then(null, console.error);
    },
  
    /**
     * If an editable item is focused, select its container.
     */
    _onFocus: function MC__onFocus(aEvent) {
--- a/series
+++ b/series
@@ -1,14 +1,14 @@
+android-browser.diff
+inspector-delete-node.diff
 remote-markup.diff
 remote-edit-attributes.diff
 remote-edit-value.diff
 inspector-panel-default-node.diff
 copy-html.diff
 search-box-remote.diff
-inspector-delete-node.diff
 warning-fixes.diff
 inspector-remote-delete-node.diff
 style-actor.diff
-android-crap.diff
 window-targets.diff
 inspector-retain-root.diff #+obsolete
 protocol-clientserver-marshallers.diff #+experimental