Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 11 Mar 2013 13:50:48 -0400
changeset 124383 7433bc4545c9930cb609bf86f8f4be04c0265dec
parent 124382 7b3da1dae19ae2fa087cfaa3e18dbbb6cda66d84 (current diff)
parent 124332 dfeacbbb793d3617edd3ef430e99bd7c56176476 (diff)
child 124384 619f2df16dfe4bae1d669d99c340390ede755306
child 124389 e7f298d7b17b5945406238edc961ca396de5b028
push id24417
push userryanvm@gmail.com
push dateMon, 11 Mar 2013 23:58:07 +0000
treeherdermozilla-central@7433bc4545c9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone22.0a1
first release with
nightly linux32
7433bc4545c9 / 22.0a1 / 20130312031046 / files
nightly linux64
7433bc4545c9 / 22.0a1 / 20130312031046 / files
nightly mac
7433bc4545c9 / 22.0a1 / 20130312031046 / files
nightly win32
7433bc4545c9 / 22.0a1 / 20130312031046 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Merge m-c to inbound.
browser/devtools/debugger/test/browser_dbg_script-switching.js
browser/devtools/shared/VariablesView.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1065,18 +1065,18 @@ pref("devtools.debugger.remote-autoconne
 pref("devtools.debugger.remote-connection-retries", 3);
 pref("devtools.debugger.remote-timeout", 20000);
 
 // The default Debugger UI settings
 pref("devtools.debugger.ui.win-x", 0);
 pref("devtools.debugger.ui.win-y", 0);
 pref("devtools.debugger.ui.win-width", 900);
 pref("devtools.debugger.ui.win-height", 400);
-pref("devtools.debugger.ui.stackframes-width", 200);
-pref("devtools.debugger.ui.variables-width", 300);
+pref("devtools.debugger.ui.panes-sources-width", 200);
+pref("devtools.debugger.ui.panes-instruments-width", 300);
 pref("devtools.debugger.ui.pause-on-exceptions", false);
 pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
 
 // Enable the Profiler
 pref("devtools.profiler.enabled", true);
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -28,53 +28,57 @@ const VARIABLES_VIEW_NON_SORTABLE = [
 ];
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 Cu.import("resource:///modules/source-editor.jsm");
 Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
+Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm");
+Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
 Cu.import("resource:///modules/devtools/VariablesView.jsm");
+Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this,
   "Reflect", "resource://gre/modules/reflect.jsm");
 
 /**
  * Object defining the debugger controller components.
  */
 let DebuggerController = {
   /**
    * Initializes the debugger controller.
    */
   initialize: function DC_initialize() {
     dumpn("Initializing the DebuggerController");
+
     this._startupDebugger = this._startupDebugger.bind(this);
     this._shutdownDebugger = this._shutdownDebugger.bind(this);
     this._onTabNavigated = this._onTabNavigated.bind(this);
     this._onTabDetached = this._onTabDetached.bind(this);
 
-    window.addEventListener("load", this._startupDebugger, true);
+    window.addEventListener("DOMContentLoaded", this._startupDebugger, true);
     window.addEventListener("unload", this._shutdownDebugger, true);
   },
 
   /**
    * Initializes the view and connects a debugger client to the server.
    */
   _startupDebugger: function DC__startupDebugger() {
     if (this._isInitialized) {
       return;
     }
     this._isInitialized = true;
-    window.removeEventListener("load", this._startupDebugger, true);
+    window.removeEventListener("DOMContentLoaded", this._startupDebugger, true);
 
     DebuggerView.initialize(function() {
       DebuggerView._isInitialized = true;
 
-      window.dispatchEvent("Debugger:Loaded");
+      window.dispatchEvent(document, "Debugger:Loaded");
       this._connect();
     }.bind(this));
   },
 
   /**
    * Destroys the view and disconnects the debugger client from the server.
    */
   _shutdownDebugger: function DC__shutdownDebugger() {
@@ -86,17 +90,17 @@ let DebuggerController = {
 
     DebuggerView.destroy(function() {
       DebuggerView._isDestroyed = true;
       this.SourceScripts.disconnect();
       this.StackFrames.disconnect();
       this.ThreadState.disconnect();
 
       this._disconnect();
-      window.dispatchEvent("Debugger:Unloaded");
+      window.dispatchEvent(document, "Debugger:Unloaded");
       window._isChromeDebugger && this._quitApp();
     }.bind(this));
   },
 
   /**
    * Prepares the hostname and port number for a remote debugger connection
    * and handles connection retries and timeouts.
    * XXX: remove all this (bug 823577)
@@ -157,17 +161,17 @@ let DebuggerController = {
   },
 
   /**
    * Initializes a debugger client and connects it to the debugger server,
    * wiring event handlers as necessary.
    */
   _connect: function DC__connect() {
     function callback() {
-      window.dispatchEvent("Debugger:Connected");
+      window.dispatchEvent(document, "Debugger:Connected");
     }
 
     if (!window._isChromeDebugger) {
       let client = this.client = this._target.client;
       this._target.on("close", this._onTabDetached);
       this._target.on("navigate", this._onTabNavigated);
       this._target.on("will-navigate", this._onTabNavigated);
 
@@ -325,30 +329,16 @@ let DebuggerController = {
 
     Services.obs.notifyObservers(canceled, "quit-application-requested", null);
 
     // Somebody canceled our quit request.
     if (canceled.data) {
       return;
     }
     Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
-  },
-
-  /**
-   * Convenience method, dispatching a custom event.
-   *
-   * @param string aType
-   *        The name of the event.
-   * @param any aDetail
-   *        The data passed when initializing the event.
-   */
-  dispatchEvent: function DC_dispatchEvent(aType, aDetail) {
-    let evt = document.createEvent("CustomEvent");
-    evt.initCustomEvent(aType, true, false, aDetail);
-    document.documentElement.dispatchEvent(evt);
   }
 };
 
 /**
  * ThreadState keeps the UI up to date with the state of the
  * thread (paused/attached/etc.).
  */
 function ThreadState() {
@@ -360,53 +350,50 @@ ThreadState.prototype = {
 
   /**
    * Connect to the current thread client.
    */
   connect: function TS_connect() {
     dumpn("ThreadState is connecting...");
     this.activeThread.addListener("paused", this._update);
     this.activeThread.addListener("resumed", this._update);
-    this.activeThread.addListener("detached", this._update);
     this.activeThread.pauseOnExceptions(Prefs.pauseOnExceptions);
     this._handleTabNavigation();
   },
 
   /**
    * Disconnect from the client.
    */
   disconnect: function TS_disconnect() {
     if (!this.activeThread) {
       return;
     }
     dumpn("ThreadState is disconnecting...");
     this.activeThread.removeListener("paused", this._update);
     this.activeThread.removeListener("resumed", this._update);
-    this.activeThread.removeListener("detached", this._update);
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
   _handleTabNavigation: function TS__handleTabNavigation() {
     if (!this.activeThread) {
       return;
     }
     dumpn("Handling tab navigation in the ThreadState");
-    this._update(this.activeThread.state);
+    this._update();
   },
 
   /**
    * Update the UI after a thread state change.
    */
   _update: function TS__update(aEvent) {
     DebuggerView.Toolbar.toggleResumeButtonState(this.activeThread.state);
 
-    if (DebuggerController._target &&
-        (aEvent == "paused" || aEvent == "resumed")) {
+    if (DebuggerController._target && (aEvent == "paused" || aEvent == "resumed")) {
       DebuggerController._target.emit("thread-" + aEvent);
     }
   }
 };
 
 /**
  * Keeps the stack frame list up-to-date, using the thread client's
  * stack frame cache.
@@ -568,16 +555,19 @@ StackFrames.prototype = {
       }
       // If the watch expressions were evaluated successfully, attach
       // the results to the topmost frame.
       let topmostFrame = this.activeThread.cachedFrames[0];
       topmostFrame.watchExpressionsEvaluation = this.currentEvaluation.return;
     }
 
 
+    // Make sure the debugger view panes are visible.
+    DebuggerView.showInstrumentsPane();
+
     // Make sure all the previous stackframes are removed before re-adding them.
     DebuggerView.StackFrames.empty();
 
     for (let frame of this.activeThread.cachedFrames) {
       this._addFrame(frame);
     }
     if (this.currentFrame == null) {
       this.selectFrame(0);
@@ -607,20 +597,20 @@ StackFrames.prototype = {
    * Called soon after the thread client's framescleared notification.
    */
   _afterFramesCleared: function SF__afterFramesCleared() {
     // Ignore useless notifications.
     if (this.activeThread.cachedFrames.length) {
       return;
     }
     DebuggerView.StackFrames.empty();
+    DebuggerView.Sources.unhighlightBreakpoint();
+    DebuggerView.WatchExpressions.toggleContents(true);
     DebuggerView.Variables.empty(0);
-    DebuggerView.Breakpoints.unhighlightBreakpoint();
-    DebuggerView.WatchExpressions.toggleContents(true);
-    window.dispatchEvent("Debugger:AfterFramesCleared");
+    window.dispatchEvent(document, "Debugger:AfterFramesCleared");
   },
 
   /**
    * Marks the stack frame at the specified depth as selected and updates the
    * properties view with the stack frame's data.
    *
    * @param number aDepth
    *        The depth of the frame in the stack.
@@ -638,17 +628,17 @@ StackFrames.prototype = {
       return;
     }
 
     // Move the editor's caret to the proper url and line.
     DebuggerView.updateEditor(url, line);
     // Highlight the stack frame at the specified depth.
     DebuggerView.StackFrames.highlightFrame(aDepth);
     // Highlight the breakpoint at the specified url and line if it exists.
-    DebuggerView.Breakpoints.highlightBreakpoint(url, line);
+    DebuggerView.Sources.highlightBreakpoint(url, line);
     // Don't display the watch expressions textbox inputs in the pane.
     DebuggerView.WatchExpressions.toggleContents(false);
     // Start recording any added variables or properties in any scope.
     DebuggerView.Variables.createHierarchy();
     // Clear existing scopes and create each one dynamically.
     DebuggerView.Variables.empty();
 
     // If watch expressions evaluation results are available, create a scope
@@ -667,35 +657,35 @@ StackFrames.prototype = {
       // The evaluation hasn't thrown, so display the returned results and
       // always expand the watch expressions scope by default.
       this._fetchWatchExpressions(scope, watchExpressionsEvaluation);
       scope.expand();
     }
 
     do {
       // Create a scope to contain all the inspected variables.
-      let label = this._getScopeLabel(environment);
+      let label = StackFrameUtils.getScopeLabel(environment);
       let scope = DebuggerView.Variables.addScope(label);
 
       // Handle additions to the innermost scope.
       if (environment == frame.environment) {
         this._insertScopeFrameReferences(scope, frame);
         this._addScopeExpander(scope, environment);
         // Always expand the innermost scope by default.
         scope.expand();
       }
       // Lazily add nodes for every other environment scope.
       else {
         this._addScopeExpander(scope, environment);
         this.autoScopeExpand && scope.expand();
       }
-    } while (environment = environment.parent);
+    } while ((environment = environment.parent));
 
     // Signal that variables have been fetched.
-    window.dispatchEvent("Debugger:FetchedVariables");
+    window.dispatchEvent(document, "Debugger:FetchedVariables");
     DebuggerView.Variables.commitHierarchy();
   },
 
   /**
    * Adds an 'onexpand' callback for a scope, lazily handling
    * the addition of new variables.
    *
    * @param Scope aScope
@@ -750,33 +740,33 @@ StackFrames.prototype = {
     if (aScope._fetched) {
       return;
     }
     aScope._fetched = true;
 
     // Add nodes for every watch expression in scope.
     this.activeThread.pauseGrip(aExp).getPrototypeAndProperties(function(aResponse) {
       let ownProperties = aResponse.ownProperties;
-      let totalExpressions = DebuggerView.WatchExpressions.totalItems;
+      let totalExpressions = DebuggerView.WatchExpressions.itemCount;
 
       for (let i = 0; i < totalExpressions; i++) {
         let name = DebuggerView.WatchExpressions.getExpression(i);
         let expVal = ownProperties[i].value;
         let expRef = aScope.addVar(name, ownProperties[i]);
         this._addVarExpander(expRef, expVal);
 
         // Revert some of the custom watch expressions scope presentation flags.
         expRef.switch = null;
         expRef.delete = null;
         expRef.descriptorTooltip = true;
         expRef.separatorStr = L10N.getStr("variablesSeparatorLabel");
       }
 
       // Signal that watch expressions have been fetched.
-      window.dispatchEvent("Debugger:FetchedWatchExpressions");
+      window.dispatchEvent(document, "Debugger:FetchedWatchExpressions");
       DebuggerView.Variables.commitHierarchy();
     }.bind(this));
   },
 
   /**
    * Adds variables to a scope in the view. Triggered when a scope is
    * expanded or is hovered. It does not expand the scope.
    *
@@ -794,17 +784,17 @@ StackFrames.prototype = {
     switch (env.type) {
       case "with":
       case "object":
         // Add nodes for every variable in scope.
         this.activeThread.pauseGrip(env.object).getPrototypeAndProperties(function(aResponse) {
           this._insertScopeVariables(aResponse.ownProperties, aScope);
 
           // Signal that variables have been fetched.
-          window.dispatchEvent("Debugger:FetchedVariables");
+          window.dispatchEvent(document, "Debugger:FetchedVariables");
           DebuggerView.Variables.commitHierarchy();
         }.bind(this));
         break;
       case "block":
       case "function":
         // Add nodes for every argument and every other variable in scope.
         this._insertScopeArguments(env.bindings.arguments, aScope);
         this._insertScopeVariables(env.bindings.variables, aScope);
@@ -921,69 +911,34 @@ StackFrames.prototype = {
         // Expansion handlers must be set after the properties are added.
         this._addVarExpander(aVar.get("__proto__"), prototype);
       }
 
       // Mark the variable as having retrieved all its properties.
       aVar._retrieved = true;
 
       // Signal that properties have been fetched.
-      window.dispatchEvent("Debugger:FetchedProperties");
+      window.dispatchEvent(document, "Debugger:FetchedProperties");
       DebuggerView.Variables.commitHierarchy();
     }.bind(this));
   },
 
   /**
-   * Constructs a scope label based on its environment.
-   *
-   * @param object aEnv
-   *        The scope's environment.
-   * @return string
-   *         The scope's label.
-   */
-  _getScopeLabel: function SV__getScopeLabel(aEnv) {
-    let name = "";
-
-    // Name the outermost scope Global.
-    if (!aEnv.parent) {
-      name = L10N.getStr("globalScopeLabel");
-    }
-    // Otherwise construct the scope name.
-    else {
-      name = aEnv.type.charAt(0).toUpperCase() + aEnv.type.slice(1);
-    }
-
-    let label = L10N.getFormatStr("scopeLabel", [name]);
-    switch (aEnv.type) {
-      case "with":
-      case "object":
-        label += " [" + aEnv.object.class + "]";
-        break;
-      case "function":
-        let f = aEnv.function;
-        label += " [" + (f.name || f.userDisplayName || f.displayName ||
-                         "(anonymous)") + "]";
-        break;
-    }
-    return label;
-  },
-
-  /**
    * Adds the specified stack frame to the list.
    *
    * @param object aFrame
    *        The new frame to add.
    */
   _addFrame: function SF__addFrame(aFrame) {
     let depth = aFrame.depth;
     let { url, line } = aFrame.where;
+    let frameLocation = SourceUtils.convertToUnicode(window.unescape(url));
+    let frameTitle = StackFrameUtils.getFrameTitle(aFrame);
 
-    let startText = StackFrameUtils.getFrameTitle(aFrame);
-    let endText = SourceUtils.getSourceLabel(url) + ":" + line;
-    DebuggerView.StackFrames.addFrame(startText, endText, depth);
+    DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth);
   },
 
   /**
    * Loads more stack frames from the debugger server cache.
    */
   addMoreFrames: function SF_addMoreFrames() {
     this.activeThread.fillFrames(
       this.activeThread.cachedFrames.length + CALL_STACK_PAGE_SIZE);
@@ -1057,16 +1012,17 @@ function SourceScripts() {
   this._onNewSource = this._onNewSource.bind(this);
   this._onNewGlobal = this._onNewGlobal.bind(this);
   this._onSourcesAdded = this._onSourcesAdded.bind(this);
 }
 
 SourceScripts.prototype = {
   get activeThread() DebuggerController.activeThread,
   get debuggerClient() DebuggerController.client,
+  _newSourceTimeout: null,
 
   /**
    * Connect to the current thread client.
    */
   connect: function SS_connect() {
     dumpn("SourceScripts is connecting...");
     this.debuggerClient.addListener("newGlobal", this._onNewGlobal);
     this.activeThread.addListener("newSource", this._onNewSource);
@@ -1097,37 +1053,40 @@ SourceScripts.prototype = {
     window.clearTimeout(this._newSourceTimeout);
 
     // Retrieve the list of script sources known to the server from before
     // the client was ready to handle "newScript" notifications.
     this.activeThread.getSources(this._onSourcesAdded);
   },
 
   /**
+   * Handler for the debugger client's unsolicited newGlobal notification.
+   */
+  _onNewGlobal: function SS__onNewGlobal(aNotification, aPacket) {
+    // TODO: bug 806775, update the globals list using aPacket.hostAnnotations
+    // from bug 801084.
+  },
+
+  /**
    * Handler for the debugger client's unsolicited newScript notification.
    */
   _onNewSource: function SS__onNewSource(aNotification, aPacket) {
     // Ignore bogus scripts, e.g. generated from 'clientEvaluate' packets.
-    if (NEW_SOURCE_IGNORED_URLS.indexOf(aPacket.url) != -1) {
+    if (NEW_SOURCE_IGNORED_URLS.indexOf(aPacket.source.url) != -1) {
       return;
     }
 
     // Add the source in the debugger view sources container.
-    this._addSource({
-      url: aPacket.source.url,
-      source: aPacket.source
-    }, {
-      forced: true
-    });
+    DebuggerView.Sources.addSource(aPacket.source, { staged: false });
 
     let container = DebuggerView.Sources;
     let preferredValue = container.preferredValue;
 
     // Select this source if it's the preferred one.
-    if (aPacket.url == preferredValue) {
+    if (aPacket.source.url == preferredValue) {
       container.selectedValue = preferredValue;
     }
     // ..or the first entry if there's none selected yet after a while
     else {
       window.clearTimeout(this._newSourceTimeout);
       this._newSourceTimeout = window.setTimeout(function() {
         // If after a certain delay the preferred source still wasn't received,
         // just give up on waiting and display the first entry.
@@ -1138,127 +1097,95 @@ SourceScripts.prototype = {
     }
 
     // If there are any stored breakpoints for this source, display them again,
     // both in the editor and the breakpoints pane.
     DebuggerController.Breakpoints.updateEditorBreakpoints();
     DebuggerController.Breakpoints.updatePaneBreakpoints();
 
     // Signal that a new script has been added.
-    window.dispatchEvent("Debugger:AfterNewScript");
-  },
-
-  /**
-   * Handler for the debugger client's unsolicited newGlobal notification.
-   */
-  _onNewGlobal: function SS__onNewGlobal(aNotification, aPacket) {
-    // TODO: bug 806775, update the globals list using aPacket.hostAnnotations
-    // from bug 801084.
+    window.dispatchEvent(document, "Debugger:AfterNewSource");
   },
 
   /**
    * Callback for the debugger's active thread getSources() method.
    */
   _onSourcesAdded: function SS__onSourcesAdded(aResponse) {
     if (aResponse.error) {
-      Cu.reportError(new Error("Error getting sources: " + aResponse.error));
+      Cu.reportError("Error getting sources: " + aResponse.error);
       return;
     }
 
     // Add all the sources in the debugger view sources container.
     for (let source of aResponse.sources) {
       // Ignore bogus scripts, e.g. generated from 'clientEvaluate' packets.
       if (NEW_SOURCE_IGNORED_URLS.indexOf(source.url) != -1) {
         continue;
       }
-      this._addSource({
-        url: source.url,
-        source: source
-      });
+      DebuggerView.Sources.addSource(source, { staged: true });
     }
 
     let container = DebuggerView.Sources;
     let preferredValue = container.preferredValue;
 
     // Flushes all the prepared sources into the sources container.
-    container.commit();
+    container.commit({ sorted: true });
 
     // Select the preferred source if it exists and was part of the response.
     if (container.containsValue(preferredValue)) {
       container.selectedValue = preferredValue;
     }
     // ..or the first entry if there's no one selected yet.
     else if (!container.selectedValue) {
       container.selectedIndex = 0;
     }
 
     // If there are any stored breakpoints for the sources, display them again,
     // both in the editor and the breakpoints pane.
     DebuggerController.Breakpoints.updateEditorBreakpoints();
     DebuggerController.Breakpoints.updatePaneBreakpoints();
 
     // Signal that scripts have been added.
-    window.dispatchEvent("Debugger:AfterSourcesAdded");
-  },
-
-  /**
-   * Add the specified source to the debugger view sources list.
-   *
-   * @param object aSource
-   *        The source object coming from the active thread.
-   * @param object aOptions [optional]
-   *        Additional options for adding the source. Supported options:
-   *        - forced: force the source to be immediately added
-   */
-  _addSource: function SS__addSource(aSource, aOptions = {}) {
-    let url = aSource.url;
-    let label = SourceUtils.getSourceLabel(url);
-
-    DebuggerView.Sources.push(label, url, {
-      forced: aOptions.forced,
-      tooltip: url,
-      attachment: aSource
-    });
+    window.dispatchEvent(document, "Debugger:AfterSourcesAdded");
   },
 
   /**
    * Gets a specified source's text.
    *
    * @param object aSource
    *        The source object coming from the active thread.
    * @param function aCallback
    *        Function called after the source text has been loaded.
    * @param function aOnTimeout
    *        Function called when the source text takes too long to fetch.
    */
   getText: function SS_getText(aSource, aCallback, aOnTimeout) {
     // If already loaded, return the source text immediately.
     if (aSource.loaded) {
-      aCallback(aSource.source.url, aSource.text);
+      aCallback(aSource.url, aSource.text);
       return;
     }
 
     // If the source text takes too long to fetch, invoke a timeout to
     // avoid blocking any operations.
     if (aOnTimeout) {
       var fetchTimeout = window.setTimeout(aOnTimeout, FETCH_SOURCE_RESPONSE_DELAY);
     }
 
     // Get the source text from the active thread.
-    this.activeThread.source(aSource.source).source(function(aResponse) {
+    this.activeThread.source(aSource).source(function(aResponse) {
       window.clearTimeout(fetchTimeout);
 
       if (aResponse.error) {
-        Cu.reportError("Error loading " + aSource.source.url + "\n" + aResponse.error);
-        aCallback(aSource.source.url, "");
-        return;
+        Cu.reportError("Error loading: " + aSource.url + "\n" + aResponse.error);
+        return void aCallback(aSource.url, "");
       }
       aSource.loaded = true;
       aSource.text = aResponse.source;
-      aCallback(aSource.source.url, aResponse.source);
+      aCallback(aSource.url, aResponse.source);
     });
   }
 };
 
 /**
  * Handles all the breakpoints in the current debugger.
  */
 function Breakpoints() {
@@ -1456,20 +1383,19 @@ Breakpoints.prototype = {
       }
 
       // Remember the breakpoint client in the store.
       this.store[aBreakpointClient.actor] = aBreakpointClient;
 
       // Attach any specified conditional expression to the breakpoint client.
       aBreakpointClient.conditionalExpression = aFlags.conditionalExpression;
 
-      // Preserve some information about the breakpoint's source url and line
-      // to display in the breakpoints pane.
-      aBreakpointClient.lineText = DebuggerView.getEditorLine(line - 1);
-      aBreakpointClient.lineInfo = SourceUtils.getSourceLabel(url) + ":" + line;
+      // Preserve information about the breakpoint's line text, to display it in
+      // the sources pane without requiring fetching the source.
+      aBreakpointClient.lineText = DebuggerView.getEditorLine(line - 1).trim();
 
       // Show the breakpoint in the editor and breakpoints pane.
       this._showBreakpoint(aBreakpointClient, aFlags);
 
       // We're done here.
       aCallback && aCallback(aBreakpointClient, aResponse.error);
     }.bind(this));
   },
@@ -1525,26 +1451,27 @@ Breakpoints.prototype = {
       if (url == currentSourceUrl) {
         this._skipEditorBreakpointCallbacks = true;
         this.editor.addBreakpoint(line - 1);
         this._skipEditorBreakpointCallbacks = false;
       }
     }
     // Update the breakpoints pane if required.
     if (!aFlags.noPaneUpdate) {
-      let { lineText, lineInfo, actor } = aBreakpointClient;
-      let conditionalFlag = aBreakpointClient.conditionalExpression !== undefined;
-      let openPopupFlag = aFlags.openPopup;
-
-      DebuggerView.Breakpoints.addBreakpoint(
-        url, line, actor, lineInfo, lineText, conditionalFlag, openPopupFlag);
+      DebuggerView.Sources.addBreakpoint({
+        sourceLocation: url,
+        lineNumber: line,
+        lineText: aBreakpointClient.lineText,
+        actor: aBreakpointClient.actor,
+        openPopupFlag: aFlags.openPopup
+      });
     }
     // Highlight the breakpoint in the pane if required.
     if (!aFlags.noPaneHighlight) {
-      DebuggerView.Breakpoints.highlightBreakpoint(url, line);
+      DebuggerView.Sources.highlightBreakpoint(url, line, aFlags);
     }
   },
 
   /**
    * Update the editor and breakpoints pane to hide a specified breakpoint.
    *
    * @param object aBreakpointClient
    *        The BreakpointActor client object to hide.
@@ -1560,17 +1487,17 @@ Breakpoints.prototype = {
       if (url == currentSourceUrl) {
         this._skipEditorBreakpointCallbacks = true;
         this.editor.removeBreakpoint(line - 1);
         this._skipEditorBreakpointCallbacks = false;
       }
     }
     // Update the breakpoints pane if required.
     if (!aFlags.noPaneUpdate) {
-      DebuggerView.Breakpoints.removeBreakpoint(url, line);
+      DebuggerView.Sources.removeBreakpoint(url, line);
     }
   },
 
   /**
    * Get the breakpoint object at the given location.
    *
    * @param string aUrl
    *        The URL of where the breakpoint is.
@@ -1668,18 +1595,18 @@ let Prefs = {
     });
   }
 };
 
 Prefs.map("Int", "windowX", "devtools.debugger.ui.win-x");
 Prefs.map("Int", "windowY", "devtools.debugger.ui.win-y");
 Prefs.map("Int", "windowWidth", "devtools.debugger.ui.win-width");
 Prefs.map("Int", "windowHeight", "devtools.debugger.ui.win-height");
-Prefs.map("Int", "stackframesWidth", "devtools.debugger.ui.stackframes-width");
-Prefs.map("Int", "variablesWidth", "devtools.debugger.ui.variables-width");
+Prefs.map("Int", "sourcesWidth", "devtools.debugger.ui.panes-sources-width");
+Prefs.map("Int", "instrumentsWidth", "devtools.debugger.ui.panes-instruments-width");
 Prefs.map("Bool", "pauseOnExceptions", "devtools.debugger.ui.pause-on-exceptions");
 Prefs.map("Bool", "panesVisibleOnStartup", "devtools.debugger.ui.panes-visible-on-startup");
 Prefs.map("Bool", "variablesSortingEnabled", "devtools.debugger.ui.variables-sorting-enabled");
 Prefs.map("Bool", "variablesOnlyEnumVisible", "devtools.debugger.ui.variables-only-enum-visible");
 Prefs.map("Bool", "variablesSearchboxVisible", "devtools.debugger.ui.variables-searchbox-visible");
 Prefs.map("Char", "remoteHost", "devtools.debugger.remote-host");
 Prefs.map("Int", "remotePort", "devtools.debugger.remote-port");
 Prefs.map("Bool", "remoteAutoConnect", "devtools.debugger.remote-autoconnect");
@@ -1714,16 +1641,25 @@ DebuggerController.ThreadState = new Thr
 DebuggerController.StackFrames = new StackFrames();
 DebuggerController.SourceScripts = new SourceScripts();
 DebuggerController.Breakpoints = new Breakpoints();
 
 /**
  * Export some properties to the global scope for easier access.
  */
 Object.defineProperties(window, {
+  "create": {
+    get: function() ViewHelpers.create,
+  },
+  "dispatchEvent": {
+    get: function() ViewHelpers.dispatchEvent,
+  },
+  "editor": {
+    get: function() DebuggerView.editor
+  },
   "gClient": {
     get: function() DebuggerController.client
   },
   "gTabClient": {
     get: function() DebuggerController.tabClient
   },
   "gThreadClient": {
     get: function() DebuggerController.activeThread
@@ -1737,22 +1673,16 @@ Object.defineProperties(window, {
   "gSourceScripts": {
     get: function() DebuggerController.SourceScripts
   },
   "gBreakpoints": {
     get: function() DebuggerController.Breakpoints
   },
   "gCallStackPageSize": {
     get: function() CALL_STACK_PAGE_SIZE,
-  },
-  "dispatchEvent": {
-    get: function() DebuggerController.dispatchEvent,
-  },
-  "editor": {
-    get: function() DebuggerView.editor
   }
 });
 
 /**
  * Helper method for debugging.
  * @param string
  */
 function dumpn(str) {
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -1,335 +1,269 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 /**
- * Functions handling the stackframes UI.
+ * Functions handling the sources UI.
  */
-function StackFramesView() {
-  dumpn("StackFramesView was instantiated");
-  MenuContainer.call(this);
-  this._onClick = this._onClick.bind(this);
-  this._onScroll = this._onScroll.bind(this);
+function SourcesView() {
+  dumpn("SourcesView was instantiated");
+
+  this._breakpointsCache = new Map(); // Can't use a WeakMap because keys are strings.
+  this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
+  this._onEditorLoad = this._onEditorLoad.bind(this);
+  this._onEditorUnload = this._onEditorUnload.bind(this);
+  this._onEditorSelection = this._onEditorSelection.bind(this);
+  this._onEditorContextMenu = this._onEditorContextMenu.bind(this);
+  this._onSourceMouseDown = this._onSourceMouseDown.bind(this);
+  this._onSourceSelect = this._onSourceSelect.bind(this);
+  this._onSourceClick = this._onSourceClick.bind(this);
+  this._onBreakpointClick = this._onBreakpointClick.bind(this);
+  this._onBreakpointCheckboxClick = this._onBreakpointCheckboxClick.bind(this);
+  this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
+  this._onConditionalPopupShown = this._onConditionalPopupShown.bind(this);
+  this._onConditionalPopupHiding = this._onConditionalPopupHiding.bind(this);
+  this._onConditionalTextboxInput = this._onConditionalTextboxInput.bind(this);
+  this._onConditionalTextboxKeyPress = this._onConditionalTextboxKeyPress.bind(this);
 }
 
-create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
+create({ constructor: SourcesView, proto: MenuContainer.prototype }, {
   /**
    * Initialization function, called when the debugger is started.
    */
-  initialize: function DVSF_initialize() {
-    dumpn("Initializing the StackFramesView");
-    this._container = new StackList(document.getElementById("stackframes"));
-    this._container.emptyText = L10N.getStr("emptyStackText");
+  initialize: function DVS_initialize() {
+    dumpn("Initializing the SourcesView");
+
+    this.node = new SideMenuWidget(document.getElementById("sources"));
+    this.emptyText = L10N.getStr("noSourcesText");
+    this.unavailableText = L10N.getStr("noMatchingSourcesText");
+
+    this._commandset = document.getElementById("debuggerCommands");
+    this._popupset = document.getElementById("debuggerPopupset");
+    this._cmPopup = document.getElementById("sourceEditorContextMenu");
+    this._cbPanel = document.getElementById("conditional-breakpoint-panel");
+    this._cbTextbox = document.getElementById("conditional-breakpoint-panel-textbox");
 
-    this._container.addEventListener("click", this._onClick, false);
-    this._container.addEventListener("scroll", this._onScroll, true);
-    window.addEventListener("resize", this._onScroll, true);
+    window.addEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
+    window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
+    this.node.addEventListener("mousedown", this._onSourceMouseDown, false);
+    this.node.addEventListener("select", this._onSourceSelect, false);
+    this.node.addEventListener("click", this._onSourceClick, false);
+    this._cbPanel.addEventListener("popupshowing", this._onConditionalPopupShowing, false);
+    this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
+    this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
+    this._cbTextbox.addEventListener("input", this._onConditionalTextboxInput, false);
+    this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
 
-    this._cache = new Map();
+    // Show an empty label by default.
+    this.empty();
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
-  destroy: function DVSF_destroy() {
-    dumpn("Destroying the StackFramesView");
-    this._container.removeEventListener("click", this._onClick, false);
-    this._container.removeEventListener("scroll", this._onScroll, true);
-    window.removeEventListener("resize", this._onScroll, true);
+  destroy: function DVS_destroy() {
+    dumpn("Destroying the SourcesView");
+
+    window.removeEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
+    window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
+    this.node.removeEventListener("mousedown", this._onSourceMouseDown, false);
+    this.node.removeEventListener("select", this._onSourceSelect, false);
+    this.node.removeEventListener("click", this._onSourceClick, false);
+    this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShowing, false);
+    this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
+    this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
+    this._cbTextbox.removeEventListener("input", this._onConditionalTextboxInput, false);
+    this._cbTextbox.removeEventListener("keypress", this._onConditionalTextboxKeyPress, false);
   },
 
   /**
-   * Adds a frame in this stackframes container.
-   *
-   * @param string aFrameName
-   *        Name to be displayed in the list.
-   * @param string aFrameDetails
-   *        Details to be displayed in the list.
-   * @param number aDepth
-   *        The frame depth specified by the debugger.
+   * Sets the preferred location to be selected in this sources container.
+   * @param string aSourceLocation
    */
-  addFrame: function DVSF_addFrame(aFrameName, aFrameDetails, aDepth) {
-    // Stackframes are UI elements which benefit from visible panes.
-    DebuggerView.showPanesSoon();
-
-    // Append a stackframe item to this container.
-    let stackframeItem = this.push(aFrameName, aFrameDetails, {
-      forced: true,
-      unsorted: true,
-      relaxed: true,
-      attachment: {
-        depth: aDepth
-      }
-    });
-
-    // Check if stackframe was already appended.
-    if (!stackframeItem) {
-      return;
-    }
+  set preferredSource(aSourceLocation) {
+    this._preferredValue = aSourceLocation;
 
-    let element = stackframeItem.target;
-    element.id = "stackframe-" + aDepth;
-    element.className = "dbg-stackframe list-item";
-    element.labelNode.className = "dbg-stackframe-name plain";
-    element.valueNode.className = "dbg-stackframe-details plain";
-
-    this._cache.set(aDepth, stackframeItem);
-  },
-
-  /**
-   * Highlights a frame in this stackframes container.
-   *
-   * @param number aDepth
-   *        The frame depth specified by the debugger controller.
-   */
-  highlightFrame: function DVSF_highlightFrame(aDepth) {
-    this._container.selectedItem = this._cache.get(aDepth).target;
-  },
-
-  /**
-   * Specifies if the active thread has more frames that need to be loaded.
-   */
-  dirty: false,
-
-  /**
-   * The click listener for the stackframes container.
-   */
-  _onClick: function DVSF__onClick(e) {
-    let item = this.getItemForElement(e.target);
-    if (item) {
-      // The container is not empty and we clicked on an actual item.
-      DebuggerController.StackFrames.selectFrame(item.attachment.depth);
+    // Selects the element with the specified value in this sources container,
+    // if already inserted.
+    if (this.containsValue(aSourceLocation)) {
+      this.selectedValue = aSourceLocation;
     }
   },
 
   /**
-   * The scroll listener for the stackframes container.
+   * Adds a source to this sources container.
+   *
+   * @param object aSource
+   *        The source object coming from the active thread.
+   * @param object aOptions [optional]
+   *        Additional options for adding the source. Supported options:
+   *        - forced: force the source to be immediately added
    */
-  _onScroll: function DVSF__onScroll() {
-    // Update the stackframes container only if we have to.
-    if (this.dirty) {
-      let list = this._container._list;
-
-      // If the stackframes container was scrolled past 95% of the height,
-      // load more content.
-      if (list.scrollTop >= (list.scrollHeight - list.clientHeight) * 0.95) {
-        DebuggerController.StackFrames.addMoreFrames();
-        this.dirty = false;
-      }
-    }
-  },
-
-  _cache: null
-});
-
-/**
- * Utility functions for handling stackframes.
- */
-let StackFrameUtils = {
-  /**
-   * Create a textual representation for the specified stack frame
-   * to display in the stack frame container.
-   *
-   * @param object aFrame
-   *        The stack frame to label.
-   */
-  getFrameTitle: function SFU_getFrameTitle(aFrame) {
-    if (aFrame.type == "call") {
-      let c = aFrame.callee;
-      return (c.name || c.userDisplayName || c.displayName || "(anonymous)");
-    }
-    return "(" + aFrame.type + ")";
-  }
-};
+  addSource: function DVS_addSource(aSource, aOptions = {}) {
+    let url = aSource.url;
+    let label = SourceUtils.getSourceLabel(url);
+    let group = SourceUtils.getSourceGroup(url);
 
-/**
- * Functions handling the breakpoints UI.
- */
-function BreakpointsView() {
-  dumpn("BreakpointsView was instantiated");
-  MenuContainer.call(this);
-  this._createItemView = this._createItemView.bind(this);
-  this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
-  this._onEditorLoad = this._onEditorLoad.bind(this);
-  this._onEditorUnload = this._onEditorUnload.bind(this);
-  this._onEditorSelection = this._onEditorSelection.bind(this);
-  this._onEditorContextMenu = this._onEditorContextMenu.bind(this);
-  this._onEditorContextMenuPopupHidden = this._onEditorContextMenuPopupHidden.bind(this);
-  this._onBreakpointClick = this._onBreakpointClick.bind(this);
-  this._onCheckboxClick = this._onCheckboxClick.bind(this);
-  this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
-  this._onConditionalPopupShown = this._onConditionalPopupShown.bind(this);
-  this._onConditionalPopupHiding = this._onConditionalPopupHiding.bind(this);
-  this._onConditionalTextboxKeyPress = this._onConditionalTextboxKeyPress.bind(this);
-}
-
-create({ constructor: BreakpointsView, proto: MenuContainer.prototype }, {
-  /**
-   * Initialization function, called when the debugger is started.
-   */
-  initialize: function DVB_initialize() {
-    dumpn("Initializing the BreakpointsView");
-    this._container = new StackList(document.getElementById("breakpoints"));
-    this._commandset = document.getElementById("debuggerCommands");
-    this._popupset = document.getElementById("debuggerPopupset");
-    this._cmPopup = document.getElementById("sourceEditorContextMenu");
-    this._cbPanel = document.getElementById("conditional-breakpoint-panel");
-    this._cbTextbox = document.getElementById("conditional-breakpoint-textbox");
-
-    this._container.emptyText = L10N.getStr("emptyBreakpointsText");
-    this._container.itemFactory = this._createItemView;
-    this._container.uniquenessQualifier = 2;
-
-    window.addEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
-    window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
-    this._container.addEventListener("click", this._onBreakpointClick, false);
-    this._cmPopup.addEventListener("popuphidden", this._onEditorContextMenuPopupHidden, false);
-    this._cbPanel.addEventListener("popupshowing", this._onConditionalPopupShowing, false);
-    this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
-    this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
-    this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
-
-    this._cache = new Map();
+    // Append a source item to this container.
+    let sourceItem = this.push([label, url, group], {
+      staged: aOptions.staged, /* stage the item to be appended later? */
+      attachment: {
+        source: aSource
+      }
+    });
   },
 
   /**
-   * Destruction function, called when the debugger is closed.
-   */
-  destroy: function DVB_destroy() {
-    dumpn("Destroying the BreakpointsView");
-    window.removeEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
-    window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
-    this._container.removeEventListener("click", this._onBreakpointClick, false);
-    this._cmPopup.removeEventListener("popuphidden", this._onEditorContextMenuPopupHidden, false);
-    this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShowing, false);
-    this._cbPanel.removeEventListener("popupshown", this._onConditionalPopupShown, false);
-    this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
-    this._cbTextbox.removeEventListener("keypress", this._onConditionalTextboxKeyPress, false);
-
-    this._cbPanel.hidePopup();
-  },
-
-  /**
-   * Adds a breakpoint in this breakpoints container.
+   * Adds a breakpoint to this sources container.
    *
-   * @param string aSourceLocation
-   *        The breakpoint source location specified by the debugger controller.
-   * @param number aLineNumber
-   *        The breakpoint line number specified by the debugger controller.
-   * @param string aActor
-   *        A breakpoint identifier specified by the debugger controller.
-   * @param string aLineInfo
-   *        Line information (parent source etc.) to be displayed in the list.
-   * @param string aLineText
-   *        Line text to be displayed in the list.
-   * @param boolean aConditionalFlag [optional]
-   *        A flag specifying if this is a conditional breakpoint.
-   * @param boolean aOpenPopupFlag [optional]
-   *        A flag specifying if the expression popup should be shown.
+   * @param object aOptions
+   *        Several options or flags supported by this operation:
+   *          - string sourceLocation
+   *            The breakpoint's source location.
+   *          - number lineNumber
+   *            The breakpoint's line number to be displayed.
+   *          - string lineText
+   *            The breakpoint's line text to be displayed.
+   *          - string actor
+   *            A breakpoint identifier specified by the debugger controller.
+   *          - boolean openPopupFlag [optional]
+   *            A flag specifying if the expression popup should be shown.
    */
-  addBreakpoint: function DVB_addBreakpoint(aSourceLocation, aLineNumber,
-                                            aActor, aLineInfo, aLineText,
-                                            aConditionalFlag, aOpenPopupFlag) {
-    // Append a breakpoint item to this container.
-    let breakpointItem = this.push(aLineInfo.trim(), aLineText.trim(), {
-      forced: true,
-      attachment: {
-        enabled: true,
-        sourceLocation: aSourceLocation,
-        lineNumber: aLineNumber,
-        isConditional: aConditionalFlag
-      }
-    });
+  addBreakpoint: function DVS_addBreakpoint(aOptions) {
+    let { sourceLocation: url, lineNumber: line } = aOptions;
 
-    // Check if breakpoint was already appended.
-    if (!breakpointItem) {
-      this.enableBreakpoint(aSourceLocation, aLineNumber, { id: aActor });
+    // Make sure we're not duplicating anything. If a breakpoint at the
+    // specified source location and line number already exists, just enable it.
+    if (this.getBreakpoint(url, line)) {
+      this.enableBreakpoint(url, line, { id: aOptions.actor });
       return;
     }
 
-    let element = breakpointItem.target;
-    element.id = "breakpoint-" + aActor;
-    element.className = "dbg-breakpoint list-item";
-    element.infoNode.className = "dbg-breakpoint-info plain";
-    element.textNode.className = "dbg-breakpoint-text plain";
-    element.setAttribute("contextmenu", this._createContextMenu(element));
+    // Get the source item to which the breakpoint should be attached.
+    let sourceItem = this.getItemByValue(url);
+
+    // Create the element node and menu popup for the breakpoint item.
+    let breakpointView = this._createBreakpointView.call(this, aOptions);
+    let contextMenu = this._createContextMenu.call(this, aOptions);
 
-    breakpointItem.finalize = this._onBreakpointRemoved;
-    this._cache.set(this._key(aSourceLocation, aLineNumber), breakpointItem);
+    // Append a breakpoint child item to the corresponding source item.
+    let breakpointItem = sourceItem.append(breakpointView.container, {
+      attachment: Object.create(aOptions, {
+        view: { value: breakpointView },
+        popup: { value: contextMenu }
+      }),
+      attributes: [
+        ["contextmenu", contextMenu.menupopupId]
+      ],
+      // Make sure that when the breakpoint item is removed, the corresponding
+      // menupopup and commandset are also destroyed.
+      finalize: this._onBreakpointRemoved
+    });
 
-    // If this is a conditional breakpoint, display the panes and a panel
-    // to input the corresponding conditional expression.
-    if (aConditionalFlag && aOpenPopupFlag) {
-      this.highlightBreakpoint(aSourceLocation, aLineNumber, { openPopup: true });
+    this._breakpointsCache.set(this._getBreakpointKey(url, line), breakpointItem);
+
+    // If this is a conditional breakpoint, display a panel to input the
+    // corresponding conditional expression.
+    if (aOptions.openPopupFlag) {
+      this.highlightBreakpoint(url, line, { openPopup: true });
     }
   },
 
   /**
-   * Removes a breakpoint from this breakpoints container.
+   * Removes a breakpoint from this sources container.
    *
    * @param string aSourceLocation
    *        The breakpoint source location.
    * @param number aLineNumber
    *        The breakpoint line number.
    */
-  removeBreakpoint: function DVB_removeBreakpoint(aSourceLocation, aLineNumber) {
+  removeBreakpoint: function DVS_removeBreakpoint(aSourceLocation, aLineNumber) {
+    // When a parent source item is removed, all the child breakpoint items are
+    // also automagically removed.
+    let sourceItem = this.getItemByValue(aSourceLocation);
+    if (!sourceItem) {
+      return;
+    }
     let breakpointItem = this.getBreakpoint(aSourceLocation, aLineNumber);
-    if (breakpointItem) {
-      this.remove(breakpointItem);
-      this._cache.delete(this._key(aSourceLocation, aLineNumber));
+    if (!breakpointItem) {
+      return;
+    }
+
+    sourceItem.remove(breakpointItem);
+
+    if (this._selectedBreakpoint == breakpointItem) {
+      this._selectedBreakpoint = null;
     }
   },
 
   /**
+   * Returns the breakpoint at the specified source location and line number.
+   *
+   * @param string aSourceLocation
+   *        The breakpoint source location.
+   * @param number aLineNumber
+   *        The breakpoint line number.
+   * @return MenuItem
+   *         The corresponding breakpoint item if found, null otherwise.
+   */
+  getBreakpoint: function DVS_getBreakpoint(aSourceLocation, aLineNumber) {
+    let breakpointKey = this._getBreakpointKey(aSourceLocation, aLineNumber);
+    return this._breakpointsCache.get(breakpointKey);
+  },
+
+  /**
    * Enables a breakpoint.
    *
    * @param string aSourceLocation
    *        The breakpoint source location.
    * @param number aLineNumber
    *        The breakpoint line number.
    * @param object aOptions [optional]
    *        Additional options or flags supported by this operation:
    *          - silent: pass true to not update the checkbox checked state;
    *                    this is usually necessary when the checked state will
    *                    be updated automatically (e.g: on a checkbox click).
-   *          - callback: function to invoke once the breakpoint is disabled
+   *          - callback: function to invoke once the breakpoint is enabled
    *          - id: a new id to be applied to the corresponding element node
    * @return boolean
    *         True if breakpoint existed and was enabled, false otherwise.
    */
   enableBreakpoint:
-  function DVB_enableBreakpoint(aSourceLocation, aLineNumber, aOptions = {}) {
+  function DVS_enableBreakpoint(aSourceLocation, aLineNumber, aOptions = {}) {
     let breakpointItem = this.getBreakpoint(aSourceLocation, aLineNumber);
-    if (breakpointItem) {
-      // Set a new id to the corresponding breakpoint element if required.
-      if (aOptions.id) {
-        breakpointItem.target.id = "breakpoint-" + aOptions.id;
-      }
+    if (!breakpointItem) {
+      return false;
+    }
+
+    // Set a new id to the corresponding breakpoint element if required.
+    if (aOptions.id) {
+      breakpointItem.attachment.view.container.id = "breakpoint-" + aOptions.id;
+    }
 
-      // Update the checkbox state if necessary.
-      if (!aOptions.silent) {
-        breakpointItem.target.checkbox.setAttribute("checked", "true");
-      }
+    // Update the checkbox state if necessary.
+    if (!aOptions.silent) {
+      breakpointItem.attachment.view.checkbox.setAttribute("checked", "true");
+    }
 
-      let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
-      let breakpointLocation = { url: url, line: line };
-      DebuggerController.Breakpoints.addBreakpoint(breakpointLocation, aOptions.callback, {
-        noPaneUpdate: true
-      });
+    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+    let breakpointLocation = { url: url, line: line };
+    DebuggerController.Breakpoints.addBreakpoint(breakpointLocation, aOptions.callback, {
+      noPaneUpdate: true,
+      noPaneHighlight: true,
+      conditionalExpression: breakpointItem.attachment.conditionalExpression
+    });
 
-      // Breakpoint is now enabled.
-      breakpointItem.attachment.enabled = true;
-      return true;
-    }
-    return false;
+    // Breakpoint is now enabled.
+    breakpointItem.attachment.disabled = false;
+    return true;
   },
 
   /**
    * Disables a breakpoint.
    *
    * @param string aSourceLocation
    *        The breakpoint source location.
    * @param number aLineNumber
@@ -339,321 +273,471 @@ create({ constructor: BreakpointsView, p
    *          - silent: pass true to not update the checkbox checked state;
    *                    this is usually necessary when the checked state will
    *                    be updated automatically (e.g: on a checkbox click).
    *          - callback: function to invoke once the breakpoint is disabled
    * @return boolean
    *         True if breakpoint existed and was disabled, false otherwise.
    */
   disableBreakpoint:
-  function DVB_disableBreakpoint(aSourceLocation, aLineNumber, aOptions = {}) {
+  function DVS_disableBreakpoint(aSourceLocation, aLineNumber, aOptions = {}) {
     let breakpointItem = this.getBreakpoint(aSourceLocation, aLineNumber);
-    if (breakpointItem) {
-      // Update the checkbox state if necessary.
-      if (!aOptions.silent) {
-        breakpointItem.target.checkbox.removeAttribute("checked");
-      }
+    if (!breakpointItem) {
+      return false;
+    }
+
+    // Update the checkbox state if necessary.
+    if (!aOptions.silent) {
+      breakpointItem.attachment.view.checkbox.removeAttribute("checked");
+    }
 
-      let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
-      let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
-      DebuggerController.Breakpoints.removeBreakpoint(breakpointClient, aOptions.callback, {
-        noPaneUpdate: true
-      });
+    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+    let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
+    DebuggerController.Breakpoints.removeBreakpoint(breakpointClient, aOptions.callback, {
+      noPaneUpdate: true
+    });
 
-      // Breakpoint is now disabled.
-      breakpointItem.attachment.enabled = false;
-      return true;
-    }
-    return false;
+    // Remember the conditional expression for when the breakpoint is enabled.
+    breakpointItem.attachment.conditionalExpression = breakpointClient.conditionalExpression;
+
+    // Breakpoint is now disabled.
+    breakpointItem.attachment.disabled = true;
+    return true;
   },
 
   /**
-   * Highlights a breakpoint in this breakpoints container.
+   * Highlights a breakpoint in this sources container.
    *
    * @param string aSourceLocation
    *        The breakpoint source location.
    * @param number aLineNumber
    *        The breakpoint line number.
    * @param object aFlags [optional]
    *        An object containing some of the following boolean properties:
    *          - updateEditor: true if editor updates should be allowed
    *          - openPopup: true if the expression popup should be shown
    */
   highlightBreakpoint:
-  function DVB_highlightBreakpoint(aSourceLocation, aLineNumber, aFlags = {}) {
+  function DVS_highlightBreakpoint(aSourceLocation, aLineNumber, aFlags = {}) {
     let breakpointItem = this.getBreakpoint(aSourceLocation, aLineNumber);
-    if (breakpointItem) {
-      // Update the editor source location and line number if necessary.
-      if (aFlags.updateEditor) {
-        DebuggerView.updateEditor(aSourceLocation, aLineNumber, { noDebug: true });
-      }
+    if (!breakpointItem) {
+      return;
+    }
 
-      // If the breakpoint requires a new conditional expression, display
-      // the panes and the panel to input the corresponding expression.
-      if (aFlags.openPopup && breakpointItem.attachment.isConditional) {
-        let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
-        let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
+    // Breakpoint is now selected.
+    this._selectBreakpoint(breakpointItem);
 
-        // The conditional expression popup can only be shown with visible panes.
-        DebuggerView.showPanesSoon(function() {
-          // Verify if the breakpoint wasn't removed before the panes were shown.
-          if (this.getBreakpoint(aSourceLocation, aLineNumber)) {
-            this._cbTextbox.value = breakpointClient.conditionalExpression || "";
-            this._cbPanel.openPopup(breakpointItem.target,
-              BREAKPOINT_CONDITIONAL_POPUP_POSITION,
-              BREAKPOINT_CONDITIONAL_POPUP_OFFSET);
-          }
-        }.bind(this));
-      } else {
-        this._cbPanel.hidePopup();
-      }
+    // Update the editor source location and line number if necessary.
+    if (aFlags.updateEditor) {
+      DebuggerView.updateEditor(aSourceLocation, aLineNumber, { noDebug: true });
+    }
 
-      // Breakpoint is now highlighted.
-      this._container.selectedItem = breakpointItem.target;
-    }
-    // Can't find a breakpoint at the requested source location and line number.
-    else {
-      this._container.selectedIndex = -1;
-      this._cbPanel.hidePopup();
+    // If the breakpoint requires a new conditional expression, display
+    // the panel to input the corresponding expression.
+    if (aFlags.openPopup) {
+      this._openConditionalPopup();
+    } else {
+      this._hideConditionalPopup();
     }
   },
 
   /**
-   * Unhighlights the current breakpoint in this breakpoints container.
+   * Unhighlights the current breakpoint in this sources container.
    */
-  unhighlightBreakpoint: function DVB_highlightBreakpoint() {
-    this.highlightBreakpoint(null);
+  unhighlightBreakpoint: function DVS_unhighlightBreakpoint() {
+    this._unselectBreakpoint();
+    this._hideConditionalPopup();
   },
 
   /**
-   * Checks whether a breakpoint with the specified source location and
-   * line number exists in this container, and returns the corresponding item
-   * if true, null otherwise.
-   *
-   * @param string aSourceLocation
-   *        The breakpoint source location.
-   * @param number aLineNumber
-   *        The breakpoint line number.
+   * Gets the currently selected breakpoint item.
    * @return object
-   *         The corresponding item.
    */
-  getBreakpoint: function DVB_getBreakpoint(aSourceLocation, aLineNumber) {
-    return this._cache.get(this._key(aSourceLocation, aLineNumber));
-  },
+  get selectedBreakpoint() this._selectedBreakpoint,
 
   /**
    * Gets the currently selected breakpoint client.
    * @return object
    */
   get selectedClient() {
-    let selectedItem = this.selectedItem;
-    if (selectedItem) {
-      let { sourceLocation: url, lineNumber: line } = selectedItem.attachment;
+    let breakpointItem = this._selectedBreakpoint;
+    if (breakpointItem) {
+      let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
       return DebuggerController.Breakpoints.getBreakpoint(url, line);
     }
     return null;
   },
 
   /**
-   * Customization function for creating an item's UI.
+   * Marks a breakpoint as selected in this sources container.
    *
-   * @param nsIDOMNode aElementNode
-   *        The element associated with the displayed item.
-   * @param string aInfo
-   *        The breakpoint's line info.
-   * @param string aText
-   *        The breakpoint's line text.
-   * @param any aAttachment [optional]
-   *        Some attached primitive/object.
+   * @param MenuItem aItem
+   *        The breakpoint item to select.
+   */
+  _selectBreakpoint: function DVS__selectBreakpoint(aItem) {
+    if (this._selectedBreakpoint == aItem) {
+      return;
+    }
+    this._unselectBreakpoint();
+    this._selectedBreakpoint = aItem;
+    this._selectedBreakpoint.markSelected();
+
+    // Ensure the currently selected breakpoint is visible.
+    this.node.ensureElementIsVisible(aItem.target);
+  },
+
+  /**
+   * Marks the current breakpoint as unselected in this sources container.
+   */
+  _unselectBreakpoint: function DVS__unselectBreakpoint() {
+    if (this._selectedBreakpoint) {
+      this._selectedBreakpoint.markDeselected();
+      this._selectedBreakpoint = null;
+    }
+  },
+
+  /**
+   * Opens a conditional breakpoint's expression input popup.
    */
-  _createItemView: function DVB__createItemView(aElementNode, aInfo, aText, aAttachment) {
+  _openConditionalPopup: function DVS__openConditionalPopup() {
+    let selectedBreakpoint = this.selectedBreakpoint;
+    let selectedClient = this.selectedClient;
+
+    if (selectedClient.conditionalExpression === undefined) {
+      this._cbTextbox.value = selectedClient.conditionalExpression = "";
+    } else {
+      this._cbTextbox.value = selectedClient.conditionalExpression;
+    }
+
+    this._cbPanel.hidden = false;
+    this._cbPanel.openPopup(this.selectedBreakpoint.attachment.view.lineNumber,
+      BREAKPOINT_CONDITIONAL_POPUP_POSITION,
+      BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X,
+      BREAKPOINT_CONDITIONAL_POPUP_OFFSET_Y);
+  },
+
+  /**
+   * Hides a conditional breakpoint's expression input popup.
+   */
+  _hideConditionalPopup: function DVS__hideConditionalPopup() {
+    this._cbPanel.hidden = true;
+    this._cbPanel.hidePopup();
+  },
+
+  /**
+   * Customization function for creating a breakpoint item's UI.
+   *
+   * @param object aOptions
+   *        Additional options or flags supported by this operation:
+   *          - number lineNumber
+   *            The line number specified by the debugger controller.
+   *          - string lineText
+   *            The line text to be displayed.
+   * @return object
+   *         An object containing the breakpoint container, checkbox,
+   *         line number and line text nodes.
+   */
+  _createBreakpointView: function DVS_createBreakpointView(aOptions) {
+    let { lineNumber, lineText } = aOptions;
+
     let checkbox = document.createElement("checkbox");
     checkbox.setAttribute("checked", "true");
-    checkbox.addEventListener("click", this._onCheckboxClick, false);
 
-    let lineInfo = document.createElement("label");
-    lineInfo.setAttribute("value", aInfo);
-    lineInfo.setAttribute("crop", "end");
+    let lineNumberNode = document.createElement("label");
+    lineNumberNode.className = "plain dbg-breakpoint-line";
+    lineNumberNode.setAttribute("value", lineNumber);
 
-    let lineText = document.createElement("label");
-    lineText.setAttribute("value", aText);
-    lineText.setAttribute("crop", "end");
-    lineText.setAttribute("tooltiptext",
-      aText.substr(0, BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH));
+    let lineTextNode = document.createElement("label");
+    lineTextNode.className = "plain dbg-breakpoint-text";
+    lineTextNode.setAttribute("value", lineText);
+    lineTextNode.setAttribute("crop", "end");
+    lineTextNode.setAttribute("flex", "1");
+    lineTextNode.setAttribute("tooltiptext",
+      lineText.substr(0, BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH));
 
-    let state = document.createElement("vbox");
-    state.className = "state";
-    state.setAttribute("pack", "center");
-    state.appendChild(checkbox);
+    let container = document.createElement("hbox");
+    container.id = "breakpoint-" + aOptions.actor;
+    container.className = "dbg-breakpoint side-menu-widget-item-other";
+    container.setAttribute("align", "center");
+    container.setAttribute("flex", "1");
+
+    container.addEventListener("click", this._onBreakpointClick, false);
+    checkbox.addEventListener("click", this._onBreakpointCheckboxClick, false);
 
-    let content = document.createElement("vbox");
-    content.className = "content";
-    content.setAttribute("flex", "1");
-    content.appendChild(lineInfo);
-    content.appendChild(lineText);
+    container.appendChild(checkbox);
+    container.appendChild(lineNumberNode);
+    container.appendChild(lineTextNode);
 
-    aElementNode.appendChild(state);
-    aElementNode.appendChild(content);
-
-    aElementNode.checkbox = checkbox;
-    aElementNode.infoNode = lineInfo;
-    aElementNode.textNode = lineText;
+    return {
+      container: container,
+      checkbox: checkbox,
+      lineNumber: lineNumberNode,
+      lineText: lineTextNode
+    };
   },
 
   /**
    * Creates a context menu for a breakpoint element.
    *
-   * @param nsIDOMNode aElementNode
-   *        The element associated with the displayed breakpoint item.
-   * @return string
-   *         The newly created menupopup id.
+   * @param aOptions
+   *        Additional options or flags supported by this operation:
+   *          - string actor
+   *            A breakpoint identifier specified by the debugger controller.
+   * @return object
+   *         An object containing the breakpoint commandset and menu popup ids.
    */
-  _createContextMenu: function DVB__createContextMenu(aElementNode) {
-    let breakpointId = aElementNode.id;
-    let commandsetId = "breakpointCommandset-" + breakpointId;
-    let menupopupId = "breakpointMenupopup-" + breakpointId;
+  _createContextMenu: function DVS__createContextMenu(aOptions) {
+    let commandsetId = "bp-cSet-" + aOptions.actor;
+    let menupopupId = "bp-mPop-" + aOptions.actor;
 
     let commandset = document.createElement("commandset");
     let menupopup = document.createElement("menupopup");
-    commandset.setAttribute("id", commandsetId);
-    menupopup.setAttribute("id", menupopupId);
+    commandset.id = commandsetId;
+    menupopup.id = menupopupId;
 
-    createMenuItem.call(this, "deleteAll");
+    createMenuItem.call(this, "enableSelf", true);
+    createMenuItem.call(this, "disableSelf");
+    createMenuItem.call(this, "deleteSelf");
     createMenuSeparator();
-    createMenuItem.call(this, "enableAll");
-    createMenuItem.call(this, "disableAll");
+    createMenuItem.call(this, "setConditional");
     createMenuSeparator();
     createMenuItem.call(this, "enableOthers");
     createMenuItem.call(this, "disableOthers");
     createMenuItem.call(this, "deleteOthers");
     createMenuSeparator();
-    createMenuItem.call(this, "setConditional");
+    createMenuItem.call(this, "enableAll");
+    createMenuItem.call(this, "disableAll");
     createMenuSeparator();
-    createMenuItem.call(this, "enableSelf", true);
-    createMenuItem.call(this, "disableSelf");
-    createMenuItem.call(this, "deleteSelf");
+    createMenuItem.call(this, "deleteAll");
 
     this._popupset.appendChild(menupopup);
     this._commandset.appendChild(commandset);
 
-    aElementNode.commandset = commandset;
-    aElementNode.menupopup = menupopup;
-    return menupopupId;
+    return {
+      commandsetId: commandsetId,
+      menupopupId: menupopupId
+    };
 
     /**
      * Creates a menu item specified by a name with the appropriate attributes
      * (label and handler).
      *
      * @param string aName
      *        A global identifier for the menu item.
      * @param boolean aHiddenFlag
      *        True if this menuitem should be hidden.
      */
     function createMenuItem(aName, aHiddenFlag) {
       let menuitem = document.createElement("menuitem");
       let command = document.createElement("command");
 
-      let prefix = "bp-cMenu-";
-      let commandId = prefix + aName + "-" + breakpointId + "-command";
-      let menuitemId = prefix + aName + "-" + breakpointId + "-menuitem";
+      let prefix = "bp-cMenu-"; // "breakpoints context menu"
+      let commandId = prefix + aName + "-" + aOptions.actor + "-command";
+      let menuitemId = prefix + aName + "-" + aOptions.actor + "-menuitem";
 
       let label = L10N.getStr("breakpointMenuItem." + aName);
       let func = this["_on" + aName.charAt(0).toUpperCase() + aName.slice(1)];
 
-      command.setAttribute("id", commandId);
+      command.id = commandId;
       command.setAttribute("label", label);
-      command.addEventListener("command", func.bind(this, aElementNode), false);
+      command.addEventListener("command", func.bind(this, aOptions), false);
 
-      menuitem.setAttribute("id", menuitemId);
+      menuitem.id = menuitemId;
+      menuitem.setAttribute("command", commandId);
       menuitem.setAttribute("command", commandId);
       menuitem.setAttribute("hidden", aHiddenFlag);
 
       commandset.appendChild(command);
       menupopup.appendChild(menuitem);
-      aElementNode[aName] = { menuitem: menuitem, command: command };
     }
 
     /**
      * Creates a simple menu separator element and appends it to the current
      * menupopup hierarchy.
      */
     function createMenuSeparator() {
       let menuseparator = document.createElement("menuseparator");
       menupopup.appendChild(menuseparator);
     }
   },
 
   /**
-   * Destroys a context menu for a breakpoint.
+   * Destroys the context menu for a breakpoint.
    *
-   * @param nsIDOMNode aElementNode
-   *        The element associated with the displayed breakpoint item.
+   * @param object aContextMenu
+   *        An object containing the breakpoint commandset and menu popup ids.
    */
-  _destroyContextMenu: function DVB__destroyContextMenu(aElementNode) {
-    let commandset = aElementNode.commandset;
-    let menupopup = aElementNode.menupopup;
+  _destroyContextMenu: function DVS__destroyContextMenu(aContextMenu) {
+    dumpn("Destroying context menu: " +
+      aContextMenu.commandsetId + " & " + aContextMenu.menupopupId);
 
+    let commandset = document.getElementById(aContextMenu.commandsetId);
+    let menupopup = document.getElementById(aContextMenu.menupopupId);
     commandset.parentNode.removeChild(commandset);
     menupopup.parentNode.removeChild(menupopup);
   },
 
   /**
    * Function called each time a breakpoint item is removed.
+   *
+   * @param MenuItem aItem
+   *        The corresponding menu item.
    */
-  _onBreakpointRemoved: function DVB__onBreakpointRemoved(aItem) {
-    this._destroyContextMenu(aItem.target);
+  _onBreakpointRemoved: function DVS__onBreakpointRemoved(aItem) {
+    dumpn("Finalizing breakpoint item: " + aItem);
+
+    let { sourceLocation: url, lineNumber: line, popup } = aItem.attachment;
+    this._destroyContextMenu(popup);
+    this._breakpointsCache.delete(this._getBreakpointKey(url, line));
   },
 
   /**
    * The load listener for the source editor.
    */
-  _onEditorLoad: function DVB__onEditorLoad({ detail: editor }) {
+  _onEditorLoad: function DVS__onEditorLoad({ detail: editor }) {
     editor.addEventListener("Selection", this._onEditorSelection, false);
     editor.addEventListener("ContextMenu", this._onEditorContextMenu, false);
   },
 
   /**
    * The unload listener for the source editor.
    */
-  _onEditorUnload: function DVB__onEditorUnload({ detail: editor }) {
+  _onEditorUnload: function DVS__onEditorUnload({ detail: editor }) {
     editor.removeEventListener("Selection", this._onEditorSelection, false);
     editor.removeEventListener("ContextMenu", this._onEditorContextMenu, false);
   },
 
   /**
    * The selection listener for the source editor.
    */
-  _onEditorSelection: function DVB__onEditorSelection(e) {
+  _onEditorSelection: function DVS__onEditorSelection(e) {
     let { start, end } = e.newValue;
 
-    let sourceLocation = DebuggerView.Sources.selectedValue;
+    let sourceLocation = this.selectedValue;
     let lineStart = DebuggerView.editor.getLineAtOffset(start) + 1;
     let lineEnd = DebuggerView.editor.getLineAtOffset(end) + 1;
 
     if (this.getBreakpoint(sourceLocation, lineStart) && lineStart == lineEnd) {
       this.highlightBreakpoint(sourceLocation, lineStart);
     } else {
       this.unhighlightBreakpoint();
     }
   },
 
   /**
    * The context menu listener for the source editor.
    */
-  _onEditorContextMenu: function DVB__onEditorContextMenu({ x, y }) {
+  _onEditorContextMenu: function DVS__onEditorContextMenu({ x, y }) {
     let offset = DebuggerView.editor.getOffsetAtLocation(x, y);
     let line = DebuggerView.editor.getLineAtOffset(offset);
     this._editorContextMenuLineNumber = line;
   },
 
   /**
-   * The context menu popup hidden listener for the source editor.
+   * The mouse down listener for the sources container.
+   */
+  _onSourceMouseDown: function DVS__onSourceMouseDown(e) {
+    let item = this.getItemForElement(e.target);
+    if (item) {
+      // The container is not empty and we clicked on an actual item.
+      this.selectedItem = item;
+    }
+  },
+
+  /**
+   * The select listener for the sources container.
+   */
+  _onSourceSelect: function DVS__onSourceSelect() {
+    if (!this.refresh()) {
+      return;
+    }
+
+    let selectedSource = this.selectedItem.attachment.source;
+    if (DebuggerView.editorSource != selectedSource) {
+      DebuggerView.editorSource = selectedSource;
+    }
+  },
+
+  /**
+   * The click listener for the sources container.
+   */
+  _onSourceClick: function DVS__onSourceClick() {
+    // Use this container as a filtering target.
+    DebuggerView.Filtering.target = this;
+  },
+
+  /**
+   * The click listener for a breakpoint container.
+   */
+  _onBreakpointClick: function DVS__onBreakpointClick(e) {
+    let sourceItem = this.getItemForElement(e.target);
+    let breakpointItem = this.getItemForElement.call(sourceItem, e.target);
+    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+    let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
+    let conditionalExpression = (breakpointClient || {}).conditionalExpression;
+
+    this.highlightBreakpoint(url, line, {
+      updateEditor: true,
+      openPopup: conditionalExpression !== undefined && e.button == 0
+    });
+  },
+
+  /**
+   * The click listener for a breakpoint checkbox.
    */
-  _onEditorContextMenuPopupHidden: function DVB__onEditorContextMenuPopupHidden() {
-    this._editorContextMenuLineNumber = -1;
+  _onBreakpointCheckboxClick: function DVS__onBreakpointCheckboxClick(e) {
+    let sourceItem = this.getItemForElement(e.target);
+    let breakpointItem = this.getItemForElement.call(sourceItem, e.target);
+    let { sourceLocation: url, lineNumber: line, disabled } = breakpointItem.attachment;
+
+    this[disabled ? "enableBreakpoint" : "disableBreakpoint"](url, line, {
+      silent: true
+    });
+
+    // Don't update the editor location (propagate into DVS__onBreakpointClick).
+    e.preventDefault();
+    e.stopPropagation();
+  },
+
+  /**
+   * The popup showing listener for the breakpoints conditional expression panel.
+   */
+  _onConditionalPopupShowing: function DVS__onConditionalPopupShowing() {
+    this._conditionalPopupVisible = true;
+  },
+
+  /**
+   * The popup shown listener for the breakpoints conditional expression panel.
+   */
+  _onConditionalPopupShown: function DVS__onConditionalPopupShown() {
+    this._cbTextbox.focus();
+    this._cbTextbox.select();
+  },
+
+  /**
+   * The popup hiding listener for the breakpoints conditional expression panel.
+   */
+  _onConditionalPopupHiding: function DVS__onConditionalPopupHiding() {
+    this._conditionalPopupVisible = false;
+  },
+
+  /**
+   * The input listener for the breakpoints conditional expression textbox.
+   */
+  _onConditionalTextboxInput: function DVS__onConditionalTextboxInput() {
+    this.selectedClient.conditionalExpression = this._cbTextbox.value;
+  },
+
+  /**
+   * The keypress listener for the breakpoints conditional expression textbox.
+   */
+  _onConditionalTextboxKeyPress: function DVS__onConditionalTextboxKeyPress(e) {
+    if (e.keyCode == e.DOM_VK_RETURN || e.keyCode == e.DOM_VK_ENTER) {
+      this._hideConditionalPopup();
+    }
   },
 
   /**
    * Called when the add breakpoint key sequence was pressed.
    */
   _onCmdAddBreakpoint: function BP__onCmdAddBreakpoint() {
     // If this command was executed via the context menu, add the breakpoint
     // on the currently hovered line in the source editor.
@@ -664,19 +748,18 @@ create({ constructor: BreakpointsView, p
     this._editorContextMenuLineNumber = -1;
 
     let url = DebuggerView.Sources.selectedValue;
     let line = DebuggerView.editor.getCaretPosition().line + 1;
     let breakpointItem = this.getBreakpoint(url, line);
 
     // If a breakpoint already existed, remove it now.
     if (breakpointItem) {
-      let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line)
+      let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
       DebuggerController.Breakpoints.removeBreakpoint(breakpointClient);
-      DebuggerView.Breakpoints.unhighlightBreakpoint();
     }
     // No breakpoint existed at the required location, add one now.
     else {
       let breakpointLocation = { url: url, line: line };
       DebuggerController.Breakpoints.addBreakpoint(breakpointLocation);
     }
   },
 
@@ -693,336 +776,516 @@ create({ constructor: BreakpointsView, p
     this._editorContextMenuLineNumber = -1;
 
     let url =  DebuggerView.Sources.selectedValue;
     let line = DebuggerView.editor.getCaretPosition().line + 1;
     let breakpointItem = this.getBreakpoint(url, line);
 
     // If a breakpoint already existed or wasn't a conditional, morph it now.
     if (breakpointItem) {
-      breakpointItem.attachment.isConditional = true;
-      this.selectedClient.conditionalExpression = "";
+      let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
       this.highlightBreakpoint(url, line, { openPopup: true });
     }
     // No breakpoint existed at the required location, add one now.
     else {
       DebuggerController.Breakpoints.addBreakpoint({ url: url, line: line }, null, {
         conditionalExpression: "",
         openPopup: true
       });
     }
   },
 
   /**
-   * The popup showing listener for the breakpoints conditional expression panel.
-   */
-  _onConditionalPopupShowing: function DVB__onConditionalPopupShowing() {
-    this._popupShown = true;
-  },
-
-  /**
-   * The popup shown listener for the breakpoints conditional expression panel.
-   */
-  _onConditionalPopupShown: function DVB__onConditionalPopupShown() {
-    this._cbTextbox.focus();
-    this._cbTextbox.select();
-  },
-
-  /**
-   * The popup hiding listener for the breakpoints conditional expression panel.
-   */
-  _onConditionalPopupHiding: function DVB__onConditionalPopupHiding() {
-    this._popupShown = false;
-    this.selectedClient.conditionalExpression = this._cbTextbox.value;
-  },
-
-  /**
-   * The keypress listener for the breakpoints conditional expression textbox.
-   */
-  _onConditionalTextboxKeyPress: function DVB__onConditionalTextboxKeyPress(e) {
-    if (e.keyCode == e.DOM_VK_RETURN || e.keyCode == e.DOM_VK_ENTER) {
-      this._cbPanel.hidePopup();
-    }
-  },
-
-  /**
-   * The click listener for the breakpoints container.
-   */
-  _onBreakpointClick: function DVB__onBreakpointClick(e) {
-    let breakpointItem = this.getItemForElement(e.target);
-    if (!breakpointItem) {
-      // The container is empty or we didn't click on an actual item.
-      return;
-    }
-    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
-    this.highlightBreakpoint(url, line, { updateEditor: true, openPopup: e.button == 0 });
-  },
-
-  /**
-   * The click listener for a breakpoint checkbox.
-   */
-  _onCheckboxClick: function DVB__onCheckboxClick(e) {
-    let breakpointItem = this.getItemForElement(e.target);
-    if (!breakpointItem) {
-      // The container is empty or we didn't click on an actual item.
-      return;
-    }
-    let { sourceLocation: url, lineNumber: line, enabled } = breakpointItem.attachment;
-    this[enabled ? "disableBreakpoint" : "enableBreakpoint"](url, line, { silent: true });
-
-    // Don't update the editor location.
-    e.preventDefault();
-    e.stopPropagation();
-  },
-
-  /**
    * Listener handling the "setConditional" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onSetConditional: function DVB__onSetConditional(aTarget) {
-    if (!aTarget) {
-      return;
-    }
-    let breakpointItem = this.getItemForElement(aTarget);
-    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
-
-    breakpointItem.attachment.isConditional = true;
+  _onSetConditional: function DVS__onSetConditional(aDetails) {
+    let { sourceLocation: url, lineNumber: line, actor } = aDetails;
+    let breakpointItem = this.getBreakpoint(url, line);
     this.highlightBreakpoint(url, line, { openPopup: true });
   },
 
   /**
    * Listener handling the "enableSelf" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onEnableSelf: function DVB__onEnableSelf(aTarget) {
-    if (!aTarget) {
-      return;
-    }
-    let breakpointItem = this.getItemForElement(aTarget);
-    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+  _onEnableSelf: function DVS__onEnableSelf(aDetails) {
+    let { sourceLocation: url, lineNumber: line, actor } = aDetails;
 
     if (this.enableBreakpoint(url, line)) {
-      aTarget.enableSelf.menuitem.setAttribute("hidden", "true");
-      aTarget.disableSelf.menuitem.removeAttribute("hidden");
+      let prefix = "bp-cMenu-"; // "breakpoints context menu"
+      let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
+      let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
+      document.getElementById(enableSelfId).setAttribute("hidden", "true");
+      document.getElementById(disableSelfId).removeAttribute("hidden");
     }
   },
 
   /**
    * Listener handling the "disableSelf" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onDisableSelf: function DVB__onDisableSelf(aTarget) {
-    if (!aTarget) {
-      return;
-    }
-    let breakpointItem = this.getItemForElement(aTarget);
-    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+  _onDisableSelf: function DVS__onDisableSelf(aDetails) {
+    let { sourceLocation: url, lineNumber: line, actor } = aDetails;
 
     if (this.disableBreakpoint(url, line)) {
-      aTarget.enableSelf.menuitem.removeAttribute("hidden");
-      aTarget.disableSelf.menuitem.setAttribute("hidden", "true");
+      let prefix = "bp-cMenu-"; // "breakpoints context menu"
+      let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
+      let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
+      document.getElementById(enableSelfId).removeAttribute("hidden");
+      document.getElementById(disableSelfId).setAttribute("hidden", "true");
     }
   },
 
   /**
    * Listener handling the "deleteSelf" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onDeleteSelf: function DVB__onDeleteSelf(aTarget) {
-    if (!aTarget) {
-      return;
-    }
-    let breakpointItem = this.getItemForElement(aTarget);
-    let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+  _onDeleteSelf: function DVS__onDeleteSelf(aDetails) {
+    let { sourceLocation: url, lineNumber: line } = aDetails;
     let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
 
     this.removeBreakpoint(url, line);
     DebuggerController.Breakpoints.removeBreakpoint(breakpointClient);
   },
 
   /**
    * Listener handling the "enableOthers" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onEnableOthers: function DVB__onEnableOthers(aTarget) {
-    for (let item in this) {
-      if (item.target != aTarget) {
-        this._onEnableSelf(item.target);
+  _onEnableOthers: function DVS__onEnableOthers(aDetails) {
+    for (let [, item] of this._breakpointsCache) {
+      if (item.attachment.actor != aDetails.actor) {
+        this._onEnableSelf(item.attachment);
       }
     }
   },
 
   /**
    * Listener handling the "disableOthers" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onDisableOthers: function DVB__onDisableOthers(aTarget) {
-    for (let item in this) {
-      if (item.target != aTarget) {
-        this._onDisableSelf(item.target);
+  _onDisableOthers: function DVS__onDisableOthers(aDetails) {
+    for (let [, item] of this._breakpointsCache) {
+      if (item.attachment.actor != aDetails.actor) {
+        this._onDisableSelf(item.attachment);
       }
     }
   },
 
   /**
    * Listener handling the "deleteOthers" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onDeleteOthers: function DVB__onDeleteOthers(aTarget) {
-    for (let item in this) {
-      if (item.target != aTarget) {
-        this._onDeleteSelf(item.target);
+  _onDeleteOthers: function DVS__onDeleteOthers(aDetails) {
+    for (let [, item] of this._breakpointsCache) {
+      if (item.attachment.actor != aDetails.actor) {
+        this._onDeleteSelf(item.attachment);
       }
     }
   },
 
   /**
    * Listener handling the "enableAll" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onEnableAll: function DVB__onEnableAll(aTarget) {
-    this._onEnableOthers(aTarget);
-    this._onEnableSelf(aTarget);
+  _onEnableAll: function DVS__onEnableAll(aDetails) {
+    this._onEnableOthers(aDetails);
+    this._onEnableSelf(aDetails);
   },
 
   /**
    * Listener handling the "disableAll" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
    */
-  _onDisableAll: function DVB__onDisableAll(aTarget) {
-    this._onDisableOthers(aTarget);
-    this._onDisableSelf(aTarget);
+  _onDisableAll: function DVS__onDisableAll(aDetails) {
+    this._onDisableOthers(aDetails);
+    this._onDisableSelf(aDetails);
   },
 
   /**
    * Listener handling the "deleteAll" menuitem command.
    *
-   * @param object aTarget
-   *        The corresponding breakpoint element node.
+   * @param object aDetails
+   *        The breakpoint details (sourceLocation, lineNumber etc.).
+   */
+  _onDeleteAll: function DVS__onDeleteAll(aDetails) {
+    this._onDeleteOthers(aDetails);
+    this._onDeleteSelf(aDetails);
+  },
+
+  /**
+   * Gets an identifier for a breakpoint's details in the current cache.
+   *
+   * @param string aSourceLocation
+   *        The breakpoint source location.
+   * @param number aLineNumber
+   *        The breakpoint line number.
+   * @return string
+   *         The breakpoint identifier.
+   */
+  _getBreakpointKey: function DVS__getBreakpointKey(aSourceLocation, aLineNumber) {
+    return [aSourceLocation, aLineNumber].join();
+  },
+
+  _breakpointsCache: null,
+  _commandset: null,
+  _popupset: null,
+  _cmPopup: null,
+  _cbPanel: null,
+  _cbTextbox: null,
+  _selectedBreakpoint: null,
+  _editorContextMenuLineNumber: -1,
+  _conditionalPopupVisible: false
+});
+
+/**
+ * Utility functions for handling sources.
+ */
+let SourceUtils = {
+  _labelsCache: new Map(),
+  _groupsCache: new Map(),
+
+  /**
+   * Clears the labels cache, populated by methods like
+   * SourceUtils.getSourceLabel or Source Utils.getSourceGroup.
+   * This should be done every time the content location changes.
+   */
+  clearCache: function SU_clearCache() {
+    this._labelsCache = new Map();
+    this._groupsCache = new Map();
+  },
+
+  /**
+   * Gets a unique, simplified label from a source url.
+   *
+   * @param string aUrl
+   *        The source url.
+   * @param number aLength [optional]
+   *        The expected source url length.
+   * @param number aSection [optional]
+   *        The section to trim. Supported values: "start", "center", "end"
+   * @return string
+   *         The simplified label.
    */
-  _onDeleteAll: function DVB__onDeleteAll(aTarget) {
-    this._onDeleteOthers(aTarget);
-    this._onDeleteSelf(aTarget);
+  getSourceLabel: function SU_getSourceLabel(aUrl, aLength, aSection) {
+    aLength = aLength || SOURCE_URL_DEFAULT_MAX_LENGTH;
+    aSection = aSection || "end";
+    let id = [aUrl, aLength, aSection].join();
+    let cachedLabel = this._labelsCache.get(id);
+    if (cachedLabel) {
+      return cachedLabel;
+    }
+
+    let sourceLabel = this.trimUrlLength(this.trimUrl(aUrl), aLength, aSection);
+    let unicodeLabel = this.convertToUnicode(window.unescape(sourceLabel));
+    this._labelsCache.set(id, unicodeLabel);
+    return unicodeLabel;
+  },
+
+  /**
+   * Gets as much information as possible about the hostname and directory paths
+   * of an url to create a short url group identifier.
+   *
+   * @param string aUrl
+   *        The source url.
+   * @return string
+   *         The simplified group.
+   */
+  getSourceGroup: function SU_getSourceGroup(aUrl) {
+    let cachedGroup = this._groupsCache.get(aUrl);
+    if (cachedGroup) {
+      return cachedGroup;
+    }
+
+    try {
+      // Use an nsIURL to parse all the url path parts.
+      var uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
+    } catch (e) {
+      // This doesn't look like a url, or nsIURL can't handle it.
+      return "";
+    }
+
+    let { scheme, hostPort, directory, fileName } = uri;
+    let lastDir = directory.split("/").reverse()[1];
+    let group = [];
+
+    // Only show interesting schemes, http is implicit.
+    if (scheme != "http") {
+      group.push(scheme);
+    }
+    // Hostnames don't always exist for files or some resource urls.
+    // e.g. file://foo/bar.js or resource:///foo/bar.js don't have a host.
+    if (hostPort) {
+      // If the hostname is a dot-separated identifier, show the first 2 parts.
+      group.push(hostPort.split(".").slice(0, 2).join("."));
+    }
+    // Append the last directory if the path leads to an actual file.
+    // e.g. http://foo.org/bar/ should only show "foo.org", not "foo.org bar"
+    if (fileName) {
+      group.push(lastDir);
+    }
+
+    let groupLabel = group.join(" ");
+    let unicodeLabel = this.convertToUnicode(window.unescape(groupLabel));
+    this._groupsCache.set(aUrl, unicodeLabel)
+    return unicodeLabel;
   },
 
   /**
-   * Gets an identifier for a breakpoint item in the current cache.
+   * Trims the url by shortening it if it exceeds a certain length, adding an
+   * ellipsis at the end.
+   *
+   * @param string aUrl
+   *        The source url.
+   * @param number aLength [optional]
+   *        The expected source url length.
+   * @param number aSection [optional]
+   *        The section to trim. Supported values: "start", "center", "end"
    * @return string
+   *         The shortened url.
    */
-  _key: function DVB__key(aSourceLocation, aLineNumber) {
-    return aSourceLocation + aLineNumber;
+  trimUrlLength: function SU_trimUrlLength(aUrl, aLength, aSection) {
+    aLength = aLength || SOURCE_URL_DEFAULT_MAX_LENGTH;
+    aSection = aSection || "end";
+
+    if (aUrl.length > aLength) {
+      switch (aSection) {
+        case "start":
+          return L10N.ellipsis + aUrl.slice(-aLength);
+          break;
+        case "center":
+          return aUrl.substr(0, aLength / 2 - 1) + L10N.ellipsis + aUrl.slice(-aLength / 2 + 1);
+          break;
+        case "end":
+          return aUrl.substr(0, aLength) + L10N.ellipsis;
+          break;
+      }
+    }
+    return aUrl;
+  },
+
+  /**
+   * Trims the query part or reference identifier of a url string, if necessary.
+   *
+   * @param string aUrl
+   *        The source url.
+   * @return string
+   *         The shortened url.
+   */
+  trimUrlQuery: function SU_trimUrlQuery(aUrl) {
+    let length = aUrl.length;
+    let q1 = aUrl.indexOf('?');
+    let q2 = aUrl.indexOf('&');
+    let q3 = aUrl.indexOf('#');
+    let q = Math.min(q1 != -1 ? q1 : length,
+                     q2 != -1 ? q2 : length,
+                     q3 != -1 ? q3 : length);
+
+    return aUrl.slice(0, q);
   },
 
-  _popupset: null,
-  _commandset: null,
-  _cmPopup: null,
-  _cbPanel: null,
-  _cbTextbox: null,
-  _popupShown: false,
-  _cache: null,
-  _editorContextMenuLineNumber: -1
-});
+  /**
+   * Trims as much as possible from a url, while keeping the label unique
+   * in the sources container.
+   *
+   * @param string | nsIURL aUrl
+   *        The source url.
+   * @param string aLabel [optional]
+   *        The resulting label at each step.
+   * @param number aSeq [optional]
+   *        The current iteration step.
+   * @return string
+   *         The resulting label at the final step.
+   */
+  trimUrl: function SU_trimUrl(aUrl, aLabel, aSeq) {
+    if (!(aUrl instanceof Ci.nsIURL)) {
+      try {
+        // Use an nsIURL to parse all the url path parts.
+        aUrl = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
+      } catch (e) {
+        // This doesn't look like a url, or nsIURL can't handle it.
+        return aUrl;
+      }
+    }
+    if (!aSeq) {
+      let name = aUrl.fileName;
+      if (name) {
+        // This is a regular file url, get only the file name (contains the
+        // base name and extension if available).
+
+        // If this url contains an invalid query, unfortunately nsIURL thinks
+        // it's part of the file extension. It must be removed.
+        aLabel = aUrl.fileName.replace(/\&.*/, "");
+      } else {
+        // This is not a file url, hence there is no base name, nor extension.
+        // Proceed using other available information.
+        aLabel = "";
+      }
+      aSeq = 1;
+    }
+
+    // If we have a label and it doesn't only contain a query...
+    if (aLabel && aLabel.indexOf("?") != 0) {
+      // A page may contain multiple requests to the same url but with different
+      // queries. It is *not* redundant to show each one.
+      if (!DebuggerView.Sources.containsLabel(aLabel)) {
+        return aLabel;
+      }
+    }
+
+    // Append the url query.
+    if (aSeq == 1) {
+      let query = aUrl.query;
+      if (query) {
+        return this.trimUrl(aUrl, aLabel + "?" + query, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Append the url reference.
+    if (aSeq == 2) {
+      let ref = aUrl.ref;
+      if (ref) {
+        return this.trimUrl(aUrl, aLabel + "#" + aUrl.ref, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Prepend the url directory.
+    if (aSeq == 3) {
+      let dir = aUrl.directory;
+      if (dir) {
+        return this.trimUrl(aUrl, dir.replace(/^\//, "") + aLabel, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Prepend the hostname and port number.
+    if (aSeq == 4) {
+      let host = aUrl.hostPort;
+      if (host) {
+        return this.trimUrl(aUrl, host + "/" + aLabel, aSeq + 1);
+      }
+      aSeq++;
+    }
+    // Use the whole url spec but ignoring the reference.
+    if (aSeq == 5) {
+      return this.trimUrl(aUrl, aUrl.specIgnoringRef, aSeq + 1);
+    }
+    // Give up.
+    return aUrl.spec;
+  },
+
+  /**
+   * Convert a given string, encoded in a given character set, to unicode.
+   *
+   * @param string aString
+   *        A string.
+   * @param string aCharset [optional]
+   *        A character set.
+   * @return string
+   *         A unicode string.
+   */
+  convertToUnicode: function SU_convertToUnicode(aString, aCharset) {
+    // Decoding primitives.
+    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+        .createInstance(Ci.nsIScriptableUnicodeConverter);
+
+    try {
+      if (aCharset) {
+        converter.charset = aCharset;
+      }
+      return converter.ConvertToUnicode(aString);
+    } catch(e) {
+      return aString;
+    }
+  }
+};
 
 /**
  * Functions handling the watch expressions UI.
  */
 function WatchExpressionsView() {
   dumpn("WatchExpressionsView was instantiated");
-  MenuContainer.call(this);
+
+  this._cache = []; // Array instead of a map because indices are important.
   this.switchExpression = this.switchExpression.bind(this);
   this.deleteExpression = this.deleteExpression.bind(this);
   this._createItemView = this._createItemView.bind(this);
   this._onClick = this._onClick.bind(this);
   this._onClose = this._onClose.bind(this);
   this._onBlur = this._onBlur.bind(this);
   this._onKeyPress = this._onKeyPress.bind(this);
 }
 
 create({ constructor: WatchExpressionsView, proto: MenuContainer.prototype }, {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVWE_initialize() {
     dumpn("Initializing the WatchExpressionsView");
-    this._container = new StackList(document.getElementById("expressions"));
+
+    this.node = new ListWidget(document.getElementById("expressions"));
     this._variables = document.getElementById("variables");
 
-    this._container.setAttribute("context", "debuggerWatchExpressionsContextMenu");
-    this._container.permaText = L10N.getStr("addWatchExpressionText");
-    this._container.itemFactory = this._createItemView;
-    this._container.addEventListener("click", this._onClick, false);
-
-    this._cache = [];
+    this.node.permaText = L10N.getStr("addWatchExpressionText");
+    this.node.itemFactory = this._createItemView;
+    this.node.setAttribute("context", "debuggerWatchExpressionsContextMenu");
+    this.node.addEventListener("click", this._onClick, false);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVWE_destroy() {
     dumpn("Destroying the WatchExpressionsView");
-    this._container.removeEventListener("click", this._onClick, false);
+
+    this.node.removeEventListener("click", this._onClick, false);
   },
 
   /**
    * Adds a watch expression in this container.
    *
    * @param string aExpression [optional]
    *        An optional initial watch expression text.
    */
   addExpression: function DVWE_addExpression(aExpression = "") {
     // Watch expressions are UI elements which benefit from visible panes.
-    DebuggerView.showPanesSoon();
+    DebuggerView.showInstrumentsPane();
 
     // Append a watch expression item to this container.
-    let expressionItem = this.push("", aExpression, {
-      forced: { atIndex: 0 },
-      unsorted: true,
-      relaxed: true,
+    let expressionItem = this.push([, aExpression], {
+      index: 0, /* specifies on which position should the item be appended */
+      relaxed: true, /* this container should allow dupes & degenerates */
       attachment: {
+        initialExpression: aExpression,
         currentExpression: "",
-        initialExpression: aExpression,
         id: this._generateId()
       }
     });
 
-    // Check if watch expression was already appended.
-    if (!expressionItem) {
-      return;
-    }
-
-    let element = expressionItem.target;
-    element.id = "expression-" + expressionItem.attachment.id;
-    element.className = "dbg-expression list-item";
-    element.arrowNode.className = "dbg-expression-arrow";
-    element.inputNode.className = "dbg-expression-input plain";
-    element.closeNode.className = "dbg-expression-delete plain devtools-closebutton";
-
-    // Automatically focus the new watch expression input and
-    // scroll the variables view to top.
-    element.inputNode.value = aExpression;
-    element.inputNode.select();
-    element.inputNode.focus();
+    // Automatically focus the new watch expression input.
+    expressionItem.attachment.inputNode.select();
+    expressionItem.attachment.inputNode.focus();
     this._variables.scrollTop = 0;
 
     this._cache.splice(0, 0, expressionItem);
   },
 
   /**
    * Removes the watch expression with the specified index from this container.
    *
@@ -1031,42 +1294,46 @@ create({ constructor: WatchExpressionsVi
    */
   removeExpressionAt: function DVWE_removeExpressionAt(aIndex) {
     this.remove(this._cache[aIndex]);
     this._cache.splice(aIndex, 1);
   },
 
   /**
    * Changes the watch expression corresponding to the specified variable item.
+   * This function is called whenever a watch expression's code is edited in
+   * the variables view container.
    *
    * @param Variable aVar
    *        The variable representing the watch expression evaluation.
    * @param string aExpression
    *        The new watch expression text.
    */
   switchExpression: function DVWE_switchExpression(aVar, aExpression) {
     let expressionItem =
       [i for (i of this._cache) if (i.attachment.currentExpression == aVar.name)][0];
 
-    // Remove the watch expression if it's going to be a duplicate.
+    // Remove the watch expression if it's going to be empty or a duplicate.
     if (!aExpression || this.getExpressions().indexOf(aExpression) != -1) {
       this.deleteExpression(aVar);
       return;
     }
 
     // Save the watch expression code string.
     expressionItem.attachment.currentExpression = aExpression;
-    expressionItem.target.inputNode.value = aExpression;
+    expressionItem.attachment.inputNode.value = aExpression;
 
     // Synchronize with the controller's watch expressions store.
     DebuggerController.StackFrames.syncWatchExpressions();
   },
 
   /**
    * Removes the watch expression corresponding to the specified variable item.
+   * This function is called whenever a watch expression's value is edited in
+   * the variables view container.
    *
    * @param Variable aVar
    *        The variable representing the watch expression evaluation.
    */
   deleteExpression: function DVWE_deleteExpression(aVar) {
     let expressionItem =
       [i for (i of this._cache) if (i.attachment.currentExpression == aVar.name)][0];
 
@@ -1099,37 +1366,45 @@ create({ constructor: WatchExpressionsVi
     return [item.attachment.currentExpression for (item of this._cache)];
   },
 
   /**
    * Customization function for creating an item's UI.
    *
    * @param nsIDOMNode aElementNode
    *        The element associated with the displayed item.
-   * @param string aExpression
-   *        The initial watch expression text.
+   * @param any aAttachment
+   *        Some attached primitive/object.
    */
-  _createItemView: function DVWE__createItemView(aElementNode, aExpression) {
+  _createItemView: function DVWE__createItemView(aElementNode, aAttachment) {
     let arrowNode = document.createElement("box");
-    let inputNode = document.createElement("textbox");
-    let closeNode = document.createElement("toolbarbutton");
+    arrowNode.className = "dbg-expression-arrow";
 
-    inputNode.setAttribute("value", aExpression);
+    let inputNode = document.createElement("textbox");
+    inputNode.className = "plain dbg-expression-input";
+    inputNode.setAttribute("value", aAttachment.initialExpression);
     inputNode.setAttribute("flex", "1");
 
+    let closeNode = document.createElement("toolbarbutton");
+    closeNode.className = "plain variables-view-delete";
+
     closeNode.addEventListener("click", this._onClose, false);
     inputNode.addEventListener("blur", this._onBlur, false);
     inputNode.addEventListener("keypress", this._onKeyPress, false);
 
+    aElementNode.id = "expression-" + aAttachment.id;
+    aElementNode.className = "dbg-expression title";
+
     aElementNode.appendChild(arrowNode);
     aElementNode.appendChild(inputNode);
     aElementNode.appendChild(closeNode);
-    aElementNode.arrowNode = arrowNode;
-    aElementNode.inputNode = inputNode;
-    aElementNode.closeNode = closeNode;
+
+    aAttachment.arrowNode = arrowNode;
+    aAttachment.inputNode = inputNode;
+    aAttachment.closeNode = closeNode;
   },
 
   /**
    * Called when the add watch expression key sequence was pressed.
    */
   _onCmdAddExpression: function BP__onCmdAddExpression(aText) {
     // Only add a new expression if there's no pending input.
     if (this.getExpressions().indexOf("") == -1) {
@@ -1138,17 +1413,17 @@ create({ constructor: WatchExpressionsVi
   },
 
   /**
    * Called when the remove all watch expressions key sequence was pressed.
    */
   _onCmdRemoveAllExpressions: function BP__onCmdRemoveAllExpressions() {
     // Empty the view of all the watch expressions and clear the cache.
     this.empty();
-    this._cache = [];
+    this._cache.length = 0;
 
     // Synchronize with the controller's watch expressions store.
     DebuggerController.StackFrames.syncWatchExpressions();
   },
 
   /**
    * The click listener for this container.
    */
@@ -1169,16 +1444,17 @@ create({ constructor: WatchExpressionsVi
    */
   _onClose: function DVWE__onClose(e) {
     let expressionItem = this.getItemForElement(e.target);
     this.removeExpressionAt(this._cache.indexOf(expressionItem));
 
     // Synchronize with the controller's watch expressions store.
     DebuggerController.StackFrames.syncWatchExpressions();
 
+    // Prevent clicking the expression element itself.
     e.preventDefault();
     e.stopPropagation();
   },
 
   /**
    * The blur listener for a watch expression's textbox.
    */
   _onBlur: function DVWE__onBlur({ target: textbox }) {
@@ -1231,17 +1507,18 @@ create({ constructor: WatchExpressionsVi
   _cache: null
 });
 
 /**
  * Functions handling the global search UI.
  */
 function GlobalSearchView() {
   dumpn("GlobalSearchView was instantiated");
-  MenuContainer.call(this);
+
+  this._cache = new Map();
   this._startSearch = this._startSearch.bind(this);
   this._onFetchSourceFinished = this._onFetchSourceFinished.bind(this);
   this._onFetchSourceTimeout = this._onFetchSourceTimeout.bind(this);
   this._onFetchSourcesFinished = this._onFetchSourcesFinished.bind(this);
   this._createItemView = this._createItemView.bind(this);
   this._onScroll = this._onScroll.bind(this);
   this._onHeaderClick = this._onHeaderClick.bind(this);
   this._onLineClick = this._onLineClick.bind(this);
@@ -1249,64 +1526,66 @@ function GlobalSearchView() {
 }
 
 create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVGS_initialize() {
     dumpn("Initializing the GlobalSearchView");
-    this._container = new StackList(document.getElementById("globalsearch"));
-    this._splitter = document.getElementById("globalsearch-splitter");
+
+    this.node = new ListWidget(document.getElementById("globalsearch"));
+    this._splitter = document.querySelector("#globalsearch + .devtools-horizontal-splitter");
 
-    this._container.emptyText = L10N.getStr("noMatchingStringsText");
-    this._container.itemFactory = this._createItemView;
-    this._container.addEventListener("scroll", this._onScroll, false);
-
-    this._cache = new Map();
+    this.node.emptyText = L10N.getStr("noMatchingStringsText");
+    this.node.itemFactory = this._createItemView;
+    this.node.addEventListener("scroll", this._onScroll, false);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVGS_destroy() {
     dumpn("Destroying the GlobalSearchView");
-    this._container.removeEventListener("scroll", this._onScroll, false);
+
+    this.node.removeEventListener("scroll", this._onScroll, false);
   },
 
   /**
    * Gets the visibility state of the global search container.
    * @return boolean
    */
-  get hidden() this._container.getAttribute("hidden") == "true",
+  get hidden()
+    this.node.getAttribute("hidden") == "true" ||
+    this._splitter.getAttribute("hidden") == "true",
 
   /**
    * Sets the results container hidden or visible. It's hidden by default.
    * @param boolean aFlag
    */
   set hidden(aFlag) {
-    this._container.setAttribute("hidden", aFlag);
+    this.node.setAttribute("hidden", aFlag);
     this._splitter.setAttribute("hidden", aFlag);
   },
 
   /**
-   * Removes all items from this container and hides it.
+   * Hides and removes all items from this search container.
    */
   clearView: function DVGS_clearView() {
     this.hidden = true;
     this.empty();
-    window.dispatchEvent("Debugger:GlobalSearch:ViewCleared");
+    window.dispatchEvent(document, "Debugger:GlobalSearch:ViewCleared");
   },
 
   /**
    * Clears all the fetched sources from cache.
    */
   clearCache: function DVGS_clearCache() {
     this._cache = new Map();
-    window.dispatchEvent("Debugger:GlobalSearch:CacheCleared");
+    window.dispatchEvent(document, "Debugger:GlobalSearch:CacheCleared");
   },
 
   /**
    * Focuses the next found match in the source editor.
    */
   focusNextMatch: function DVGS_focusNextMatch() {
     let totalLineResults = LineResults.size();
     if (!totalLineResults) {
@@ -1409,17 +1688,17 @@ create({ constructor: GlobalSearchView, 
     }
 
     // Fetch each new source.
     for (let location of aLocations) {
       if (this._cache.has(location)) {
         continue;
       }
       let sourceItem = DebuggerView.Sources.getItemByValue(location);
-      let sourceObject = sourceItem.attachment;
+      let sourceObject = sourceItem.attachment.source;
       DebuggerController.SourceScripts.getText(sourceObject, onFetch, onTimeout);
     }
   },
 
   /**
    * Called when a source has been fetched.
    *
    * @param string aLocation
@@ -1469,17 +1748,17 @@ create({ constructor: GlobalSearchView, 
    */
   _performGlobalSearch: function DVGS__performGlobalSearch() {
     // Get the currently searched token from the filtering input.
     let token = this._searchedToken;
 
     // Make sure we're actually searching for something.
     if (!token) {
       this.clearView();
-      window.dispatchEvent("Debugger:GlobalSearch:TokenEmpty");
+      window.dispatchEvent(document, "Debugger:GlobalSearch:TokenEmpty");
       return;
     }
 
     // Search is not case sensitive, prepare the actual searched token.
     let lowerCaseToken = token.toLowerCase();
     let tokenLength = token.length;
 
     // Prepare the results map, containing search details for each line.
@@ -1535,19 +1814,19 @@ create({ constructor: GlobalSearchView, 
     // Empty this container to rebuild the search results.
     this.empty();
 
     // Signal if there are any matches, and the rebuild the results.
     if (globalResults.itemCount) {
       this.hidden = false;
       this._currentlyFocusedMatch = -1;
       this._createGlobalResultsUI(globalResults);
-      window.dispatchEvent("Debugger:GlobalSearch:MatchFound");
+      window.dispatchEvent(document, "Debugger:GlobalSearch:MatchFound");
     } else {
-      window.dispatchEvent("Debugger:GlobalSearch:MatchNotFound");
+      window.dispatchEvent(document, "Debugger:GlobalSearch:MatchNotFound");
     }
   },
 
   /**
    * Creates global search results entries and adds them to this container.
    *
    * @param GlobalResults aGlobalResults
    *        An object containing all source results, grouped by source location.
@@ -1576,41 +1855,40 @@ create({ constructor: GlobalSearchView, 
    * @param SourceResults aSourceResults
    *        An object containing all the matched lines for a specific source.
    * @param boolean aExpandFlag
    *        True to expand the source results.
    */
   _createSourceResultsUI:
   function DVGS__createSourceResultsUI(aLocation, aSourceResults, aExpandFlag) {
     // Append a source results item to this container.
-    let sourceResultsItem = this.push(aLocation, aSourceResults.matchCount, {
-      forced: true,
-      unsorted: true,
-      relaxed: true,
+    let sourceResultsItem = this.push([aLocation, aSourceResults.matchCount], {
+      index: -1, /* specifies on which position should the item be appended */
+      relaxed: true, /* this container should allow dupes & degenerates */
       attachment: {
         sourceResults: aSourceResults,
         expandFlag: aExpandFlag
       }
     });
   },
 
   /**
    * Customization function for creating an item's UI.
    *
    * @param nsIDOMNode aElementNode
    *        The element associated with the displayed item.
+   * @param any aAttachment
+   *        Some attached primitive/object.
    * @param string aLocation
    *        The source result's location.
    * @param string aMatchCount
    *        The source result's match count.
-   * @param any aAttachment [optional]
-   *        Some attached primitive/object.
    */
   _createItemView:
-  function DVGS__createItemView(aElementNode, aLocation, aMatchCount, aAttachment) {
+  function DVGS__createItemView(aElementNode, aAttachment, aLocation, aMatchCount) {
     let { sourceResults, expandFlag } = aAttachment;
 
     sourceResults.createView(aElementNode, aLocation, aMatchCount, expandFlag, {
       onHeaderClick: this._onHeaderClick,
       onLineClick: this._onLineClick,
       onMatchClick: this._onMatchClick
     });
   },
@@ -1675,60 +1953,49 @@ create({ constructor: GlobalSearchView, 
    */
   _expandResultsIfNeeded: function DVGS__expandResultsIfNeeded(aTarget) {
     let sourceResultsItem = SourceResults.getItemForElement(aTarget);
     if (sourceResultsItem.instance.toggled ||
         sourceResultsItem.instance.expanded) {
       return;
     }
     let { top, height } = aTarget.getBoundingClientRect();
-    let { clientHeight } = this._container._parent;
+    let { clientHeight } = this.node._parent;
 
     if (top - height <= clientHeight || this._forceExpandResults) {
       sourceResultsItem.instance.expand();
     }
   },
 
   /**
-   * Scrolls a match into view.
+   * Scrolls a match into view if not already visible.
    *
    * @param nsIDOMNode aMatch
    *        The match to scroll into view.
    */
   _scrollMatchIntoViewIfNeeded:  function DVGS__scrollMatchIntoViewIfNeeded(aMatch) {
-    let { top, height } = aMatch.getBoundingClientRect();
-    let { clientHeight } = this._container._parent;
-
-    let style = window.getComputedStyle(aMatch);
-    let topBorderSize = window.parseInt(style.getPropertyValue("border-top-width"));
-    let bottomBorderSize = window.parseInt(style.getPropertyValue("border-bottom-width"));
-
-    let marginY = top - (height + topBorderSize + bottomBorderSize) * 2;
-    if (marginY <= 0) {
-      this._container._parent.scrollTop += marginY;
-    }
-    if (marginY + height > clientHeight) {
-      this._container._parent.scrollTop += height - (clientHeight - marginY);
-    }
+    let boxObject = this.node._parent.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+    boxObject.ensureElementIsVisible(aMatch);
   },
 
   /**
    * Starts a bounce animation for a match.
    *
    * @param nsIDOMNode aMatch
    *        The match to start a bounce animation for.
    */
   _bounceMatch: function DVGS__bounceMatch(aMatch) {
     Services.tm.currentThread.dispatch({ run: function() {
       aMatch.addEventListener("transitionend", function onEvent() {
         aMatch.removeEventListener("transitionend", onEvent);
         aMatch.removeAttribute("focused");
       });
       aMatch.setAttribute("focused", "");
     }}, 0);
+    aMatch.setAttribute("focusing", "");
   },
 
   _splitter: null,
   _currentlyFocusedMatch: -1,
   _forceExpandResults: false,
   _searchTimeout: null,
   _searchFunction: null,
   _searchedToken: "",
@@ -1791,35 +2058,27 @@ SourceResults.prototype = {
 
   /**
    * The number of matches in this store. One line may have multiple matches.
    */
   matchCount: -1,
 
   /**
    * Expands the element, showing all the added details.
-   *
-   * @param boolean aSkipAnimationFlag
-   *        Pass true to not show an opening animation.
    */
-  expand: function SR_expand(aSkipAnimationFlag) {
-    this._target.resultsContainer.setAttribute("open", "");
+  expand: function SR_expand() {
+    this._target.resultsContainer.removeAttribute("hidden")
     this._target.arrow.setAttribute("open", "");
-
-    if (!aSkipAnimationFlag) {
-      this._target.resultsContainer.setAttribute("animated", "");
-    }
   },
 
   /**
    * Collapses the element, hiding all the added details.
    */
   collapse: function SR_collapse() {
-    this._target.resultsContainer.removeAttribute("animated");
-    this._target.resultsContainer.removeAttribute("open");
+    this._target.resultsContainer.setAttribute("hidden", "true");
     this._target.arrow.removeAttribute("open");
   },
 
   /**
    * Toggles between the element collapse/expand state.
    */
   toggle: function SR_toggle(e) {
     if (e instanceof Event) {
@@ -1832,17 +2091,19 @@ SourceResults.prototype = {
    * Relaxes the auto-expand rules to always show as many results as possible.
    */
   alwaysExpand: true,
 
   /**
    * Gets this element's expanded state.
    * @return boolean
    */
-  get expanded() this._target.resultsContainer.hasAttribute("open"),
+  get expanded()
+    this._target.resultsContainer.getAttribute("hidden") != "true" &&
+    this._target.arrow.hasAttribute("open"),
 
   /**
    * Sets this element's expanded state.
    * @param boolean aFlag
    */
   set expanded(aFlag) this[aFlag ? "expand" : "collapse"](),
 
   /**
@@ -1876,33 +2137,34 @@ SourceResults.prototype = {
   createView:
   function SR_createView(aElementNode, aLocation, aMatchCount, aExpandFlag, aCallbacks) {
     this._target = aElementNode;
 
     let arrow = document.createElement("box");
     arrow.className = "arrow";
 
     let locationNode = document.createElement("label");
-    locationNode.className = "plain location";
+    locationNode.className = "plain dbg-results-header-location";
     locationNode.setAttribute("value", SourceUtils.trimUrlLength(aLocation));
 
     let matchCountNode = document.createElement("label");
-    matchCountNode.className = "plain match-count";
+    matchCountNode.className = "plain dbg-results-header-match-count";
     matchCountNode.setAttribute("value", "(" + aMatchCount + ")");
 
     let resultsHeader = document.createElement("hbox");
     resultsHeader.className = "dbg-results-header";
     resultsHeader.setAttribute("align", "center")
     resultsHeader.appendChild(arrow);
     resultsHeader.appendChild(locationNode);
     resultsHeader.appendChild(matchCountNode);
     resultsHeader.addEventListener("click", aCallbacks.onHeaderClick, false);
 
     let resultsContainer = document.createElement("vbox");
     resultsContainer.className = "dbg-results-container";
+    resultsContainer.setAttribute("hidden", "true");
 
     for (let [lineNumber, lineResults] of this._store) {
       lineResults.createView(resultsContainer, lineNumber, aCallbacks)
     }
 
     aElementNode.arrow = arrow;
     aElementNode.resultsHeader = resultsHeader;
     aElementNode.resultsContainer = resultsContainer;
@@ -1983,28 +2245,28 @@ LineResults.prototype = {
     this._target = aContainer;
 
     let lineNumberNode = document.createElement("label");
     let lineContentsNode = document.createElement("hbox");
     let lineString = "";
     let lineLength = 0;
     let firstMatch = null;
 
-    lineNumberNode.className = "plain line-number";
+    lineNumberNode.className = "plain dbg-results-line-number";
     lineNumberNode.setAttribute("value", aLineNumber + 1);
-    lineContentsNode.className = "line-contents";
+    lineContentsNode.className = "light list-widget-item dbg-results-line-contents";
     lineContentsNode.setAttribute("flex", "1");
 
     for (let chunk of this._store) {
       let { string, range, match } = chunk;
       lineString = string.substr(0, GLOBAL_SEARCH_LINE_MAX_LENGTH - lineLength);
       lineLength += string.length;
 
       let label = document.createElement("label");
-      label.className = "plain string";
+      label.className = "plain dbg-results-line-contents-string";
       label.setAttribute("value", lineString);
       label.setAttribute("match", match);
       lineContentsNode.appendChild(label);
 
       if (match) {
         this._entangleMatch(aLineNumber, label, chunk);
         label.addEventListener("click", aCallbacks.onMatchClick, false);
         firstMatch = firstMatch || label;
@@ -2050,17 +2312,17 @@ LineResults.prototype = {
     });
   },
 
   /**
    * An nsIDOMNode label with an ellipsis value.
    */
   _ellipsis: (function() {
     let label = document.createElement("label");
-    label.className = "plain string";
+    label.className = "plain dbg-results-line-contents-string";
     label.setAttribute("value", L10N.ellipsis);
     return label;
   })(),
 
   _store: null,
   _target: null
 };
 
@@ -2098,23 +2360,26 @@ LineResults.getItemForElement = function
  */
 SourceResults.getElementAtIndex =
 LineResults.getElementAtIndex = function DVGS_getElementAtIndex(aIndex) {
   for (let [element, item] of this._itemsByElement) {
     if (!item.nonenumerable && !aIndex--) {
       return element;
     }
   }
+  return null;
 };
 
 /**
  * Gets the index of an item associated with the specified element.
  *
+ * @param nsIDOMNode aElement
+ *        The element to get the index for.
  * @return number
- *         The index of the matched item, or -1 if nothing is found.
+ *         The index of the matched element, or -1 if nothing is found.
  */
 SourceResults.indexOfElement =
 LineResults.indexOfElement = function DVGS_indexOFElement(aElement) {
   let count = 0;
   for (let [element, item] of this._itemsByElement) {
     if (element == aElement) {
       return count;
     }
@@ -2140,12 +2405,11 @@ LineResults.size = function DVGS_size() 
     }
   }
   return count;
 };
 
 /**
  * Preliminary setup for the DebuggerView object.
  */
-DebuggerView.StackFrames = new StackFramesView();
-DebuggerView.Breakpoints = new BreakpointsView();
+DebuggerView.Sources = new SourcesView();
 DebuggerView.WatchExpressions = new WatchExpressionsView();
 DebuggerView.GlobalSearch = new GlobalSearchView();
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -6,48 +6,49 @@
 "use strict";
 
 /**
  * Functions handling the toolbar view: close button, expand/collapse button,
  * pause/resume and stepping buttons etc.
  */
 function ToolbarView() {
   dumpn("ToolbarView was instantiated");
+
   this._onTogglePanesPressed = this._onTogglePanesPressed.bind(this);
   this._onResumePressed = this._onResumePressed.bind(this);
   this._onStepOverPressed = this._onStepOverPressed.bind(this);
   this._onStepInPressed = this._onStepInPressed.bind(this);
   this._onStepOutPressed = this._onStepOutPressed.bind(this);
 }
 
 ToolbarView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVT_initialize() {
     dumpn("Initializing the ToolbarView");
-    this._togglePanesButton = document.getElementById("toggle-panes");
+
+    this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
     this._resumeButton = document.getElementById("resume");
     this._stepOverButton = document.getElementById("step-over");
     this._stepInButton = document.getElementById("step-in");
     this._stepOutButton = document.getElementById("step-out");
     this._chromeGlobals = document.getElementById("chrome-globals");
-    this._scripts = document.getElementById("sources");
 
     let resumeKey = LayoutHelpers.prettyKey(document.getElementById("resumeKey"), true);
     let stepOverKey = LayoutHelpers.prettyKey(document.getElementById("stepOverKey"), true);
     let stepInKey = LayoutHelpers.prettyKey(document.getElementById("stepInKey"), true);
     let stepOutKey = LayoutHelpers.prettyKey(document.getElementById("stepOutKey"), true);
     this._resumeTooltip = L10N.getFormatStr("resumeButtonTooltip", [resumeKey]);
     this._pauseTooltip = L10N.getFormatStr("pauseButtonTooltip", [resumeKey]);
     this._stepOverTooltip = L10N.getFormatStr("stepOverTooltip", [stepOverKey]);
     this._stepInTooltip = L10N.getFormatStr("stepInTooltip", [stepInKey]);
     this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", [stepOutKey]);
 
-    this._togglePanesButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
+    this._instrumentsPaneToggleButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
     this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
     this._stepOverButton.addEventListener("mousedown", this._onStepOverPressed, false);
     this._stepInButton.addEventListener("mousedown", this._onStepInPressed, false);
     this._stepOutButton.addEventListener("mousedown", this._onStepOutPressed, false);
 
     this._stepOverButton.setAttribute("tooltiptext", this._stepOverTooltip);
     this._stepInButton.setAttribute("tooltiptext", this._stepInTooltip);
     this._stepOutButton.setAttribute("tooltiptext", this._stepOutTooltip);
@@ -56,17 +57,18 @@ ToolbarView.prototype = {
     // this.toggleChromeGlobalsContainer(window._isChromeDebugger);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVT_destroy() {
     dumpn("Destroying the ToolbarView");
-    this._togglePanesButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
+
+    this._instrumentsPaneToggleButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
     this._resumeButton.removeEventListener("mousedown", this._onResumePressed, false);
     this._stepOverButton.removeEventListener("mousedown", this._onStepOverPressed, false);
     this._stepInButton.removeEventListener("mousedown", this._onStepInPressed, false);
     this._stepOutButton.removeEventListener("mousedown", this._onStepOutPressed, false);
   },
 
   /**
    * Sets the resume button state based on the debugger active thread.
@@ -93,31 +95,21 @@ ToolbarView.prototype = {
    * @param boolean aVisibleFlag
    *        Specifies the intended visibility.
    */
   toggleChromeGlobalsContainer: function DVT_toggleChromeGlobalsContainer(aVisibleFlag) {
     this._chromeGlobals.setAttribute("hidden", !aVisibleFlag);
   },
 
   /**
-   * Sets the sources container hidden or visible. It's visible by default.
-   *
-   * @param boolean aVisibleFlag
-   *        Specifies the intended visibility.
-   */
-  toggleSourcesContainer: function DVT_toggleSourcesContainer(aVisibleFlag) {
-    this._sources.setAttribute("hidden", !aVisibleFlag);
-  },
-
-  /**
    * Listener handling the toggle button click event.
    */
   _onTogglePanesPressed: function DVT__onTogglePanesPressed() {
-    DebuggerView.togglePanes({
-      visible: DebuggerView.panesHidden,
+    DebuggerView.toggleInstrumentsPane({
+      visible: DebuggerView.instrumentsPaneHidden,
       animated: true,
       delayed: true
     });
   },
 
   /**
    * Listener handling the pause/resume button click event.
    */
@@ -151,47 +143,48 @@ ToolbarView.prototype = {
    * Listener handling the step out button click event.
    */
   _onStepOutPressed: function DVT__onStepOutPressed() {
     if (DebuggerController.activeThread.paused) {
       DebuggerController.activeThread.stepOut();
     }
   },
 
-  _togglePanesButton: null,
+  _instrumentsPaneToggleButton: null,
   _resumeButton: null,
   _stepOverButton: null,
   _stepInButton: null,
   _stepOutButton: null,
   _chromeGlobals: null,
-  _sources: null,
   _resumeTooltip: "",
   _pauseTooltip: "",
   _stepOverTooltip: "",
   _stepInTooltip: "",
   _stepOutTooltip: ""
 };
 
 /**
  * Functions handling the options UI.
  */
 function OptionsView() {
   dumpn("OptionsView was instantiated");
+
   this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
   this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
   this._toggleShowVariablesOnlyEnum = this._toggleShowVariablesOnlyEnum.bind(this);
   this._toggleShowVariablesFilterBox = this._toggleShowVariablesFilterBox.bind(this);
 }
 
 OptionsView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVO_initialize() {
     dumpn("Initializing the OptionsView");
+
     this._button = document.getElementById("debugger-options");
     this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
     this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
     this._showVariablesOnlyEnumItem = document.getElementById("show-vars-only-enum");
     this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
 
     this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
     this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
@@ -260,311 +253,439 @@ OptionsView.prototype = {
   _showVariablesFilterBoxItem: null
 };
 
 /**
  * Functions handling the chrome globals UI.
  */
 function ChromeGlobalsView() {
   dumpn("ChromeGlobalsView was instantiated");
-  MenuContainer.call(this);
+
   this._onSelect = this._onSelect.bind(this);
   this._onClick = this._onClick.bind(this);
 }
 
 create({ constructor: ChromeGlobalsView, proto: MenuContainer.prototype }, {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVCG_initialize() {
     dumpn("Initializing the ChromeGlobalsView");
-    this._container = document.getElementById("chrome-globals");
-    this._emptyLabel = L10N.getStr("noGlobalsText");
-    this._unavailableLabel = L10N.getStr("noMatchingGlobalsText");
+
+    this.node = document.getElementById("chrome-globals");
+    this.emptyText = L10N.getStr("noGlobalsText");
+    this.unavailableText = L10N.getStr("noMatchingGlobalsText");
 
-    this._container.addEventListener("select", this._onSelect, false);
-    this._container.addEventListener("click", this._onClick, false);
+    this.node.addEventListener("select", this._onSelect, false);
+    this.node.addEventListener("click", this._onClick, false);
 
+    // Show an empty label by default.
     this.empty();
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVT_destroy() {
     dumpn("Destroying the ChromeGlobalsView");
-    this._container.removeEventListener("select", this._onSelect, false);
-    this._container.removeEventListener("click", this._onClick, false);
+
+    this.node.removeEventListener("select", this._onSelect, false);
+    this.node.removeEventListener("click", this._onClick, false);
   },
 
   /**
    * The select listener for the chrome globals container.
    */
   _onSelect: function DVCG__onSelect() {
     if (!this.refresh()) {
       return;
     }
-    // TODO: Do something useful for chrome debugging.
+    // TODO: bug 806775, do something useful for chrome debugging.
   },
 
   /**
    * The click listener for the chrome globals container.
    */
   _onClick: function DVCG__onClick() {
-    DebuggerView.Filtering.target = this;
-  }
-});
-
-/**
- * Functions handling the sources UI.
- */
-function SourcesView() {
-  dumpn("SourcesView was instantiated");
-  MenuContainer.call(this);
-  this._onSelect = this._onSelect.bind(this);
-  this._onClick = this._onClick.bind(this);
-}
-
-create({ constructor: SourcesView, proto: MenuContainer.prototype }, {
-  /**
-   * Initialization function, called when the debugger is started.
-   */
-  initialize: function DVS_initialize() {
-    dumpn("Initializing the SourcesView");
-    this._container = document.getElementById("sources");
-    this._emptyLabel = L10N.getStr("noScriptsText");
-    this._unavailableLabel = L10N.getStr("noMatchingScriptsText");
-
-    this._container.addEventListener("select", this._onSelect, false);
-    this._container.addEventListener("click", this._onClick, false);
-
-    this.empty();
-  },
-
-  /**
-   * Destruction function, called when the debugger is closed.
-   */
-  destroy: function DVS_destroy() {
-    dumpn("Destroying the SourcesView");
-    this._container.removeEventListener("select", this._onSelect, false);
-    this._container.removeEventListener("click", this._onClick, false);
-  },
-
-  /**
-   * Sets the preferred source url to be displayed in this container.
-   * @param string aValue
-   */
-  set preferredSource(aValue) {
-    this._preferredValue = aValue;
-
-    // Selects the element with the specified value in this container,
-    // if already inserted.
-    if (this.containsValue(aValue)) {
-      this.selectedValue = aValue;
-    }
-  },
-
-  /**
-   * The select listener for the sources container.
-   */
-  _onSelect: function DVS__onSelect() {
-    if (!this.refresh()) {
-      return;
-    }
-    DebuggerView.setEditorSource(this.selectedItem.attachment);
-  },
-
-  /**
-   * The click listener for the sources container.
-   */
-  _onClick: function DVS__onClick() {
+    // Use this container as a filtering target.
     DebuggerView.Filtering.target = this;
   }
 });
 
 /**
- * Utility functions for handling sources.
+ * Functions handling the stackframes UI.
  */
-let SourceUtils = {
-  _labelsCache: new Map(),
+function StackFramesView() {
+  dumpn("StackFramesView was instantiated");
 
+  this._framesCache = new Map(); // Can't use a WeakMap because keys are numbers.
+  this._onStackframeRemoved = this._onStackframeRemoved.bind(this);
+  this._onClick = this._onClick.bind(this);
+  this._onScroll = this._onScroll.bind(this);
+  this._afterScroll = this._afterScroll.bind(this);
+  this._selectFrame = this._selectFrame.bind(this);
+}
+
+create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
   /**
-   * Gets a unique, simplified label from a source url.
-   *
-   * @param string aUrl
-   *        The source url.
-   * @return string
-   *         The simplified label.
+   * Initialization function, called when the debugger is started.
    */
-  getSourceLabel: function SU_getSourceLabel(aUrl) {
-    if (!this._labelsCache.has(aUrl)) {
-      this._labelsCache.set(aUrl, this.trimUrlLength(this.trimUrl(aUrl)));
-    }
-    return this._labelsCache.get(aUrl);
+  initialize: function DVSF_initialize() {
+    dumpn("Initializing the StackFramesView");
+
+    let commandset = this._commandset = document.createElement("commandset");
+    let menupopup = this._menupopup = document.createElement("menupopup");
+    commandset.id = "stackframesCommandset";
+    menupopup.id = "stackframesMenupopup";
+
+    document.getElementById("debuggerPopupset").appendChild(menupopup);
+    document.getElementById("debuggerCommands").appendChild(commandset);
+
+    this.node = new BreadcrumbsWidget(document.getElementById("stackframes"));
+    this.node.addEventListener("mousedown", this._onClick, false);
+    this.node.addEventListener("scroll", this._onScroll, true);
+    window.addEventListener("resize", this._onScroll, true);
   },
 
   /**
-   * Clears the labels cache, populated by SourceUtils.getSourceLabel.
-   * This should be done every time the content location changes.
+   * Destruction function, called when the debugger is closed.
    */
-  clearLabelsCache: function SU_clearLabelsCache() {
-    this._labelsCache = new Map();
+  destroy: function DVSF_destroy() {
+    dumpn("Destroying the StackFramesView");
+
+    this.node.removeEventListener("mousedown", this._onClick, false);
+    this.node.removeEventListener("scroll", this._onScroll, true);
+    window.removeEventListener("resize", this._onScroll, true);
   },
 
   /**
-   * Trims the url by shortening it if it exceeds a certain length, adding an
-   * ellipsis at the end.
+   * Adds a frame in this stackframes container.
    *
-   * @param string aUrl
-   *        The source url.
-   * @param number aMaxLength [optional]
-   *        The max source url length.
-   * @return string
-   *         The shortened url.
+   * @param string aFrameTitle
+   *        The frame title to be displayed in the list.
+   * @param string aSourceLocation
+   *        The source location to be displayed in the list.
+   * @param string aLineNumber
+   *        The line number to be displayed in the list.
+   * @param number aDepth
+   *        The frame depth specified by the debugger.
    */
-  trimUrlLength: function SU_trimUrlLength(aUrl, aMaxLength = SOURCE_URL_MAX_LENGTH) {
-    if (aUrl.length > aMaxLength) {
-      return aUrl.substring(0, aMaxLength) + L10N.ellipsis;
-    }
-    return aUrl;
+  addFrame: function DVSF_addFrame(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
+    // Create the element node and menu entry for the stack frame item.
+    let frameView = this._createFrameView.apply(this, arguments);
+    let menuEntry = this._createMenuEntry.apply(this, arguments);
+
+    // Append a stack frame item to this container.
+    let stackframeItem = this.push(frameView, {
+      index: 0, /* specifies on which position should the item be appended */
+      relaxed: true, /* this container should allow dupes & degenerates */
+      attachment: {
+        popup: menuEntry,
+        depth: aDepth
+      },
+      attributes: [
+        ["contextmenu", "stackframesMenupopup"],
+        ["tooltiptext", aSourceLocation]
+      ],
+      // Make sure that when the stack frame item is removed, the corresponding
+      // menuitem and command are also destroyed.
+      finalize: this._onStackframeRemoved
+    });
+
+    this._framesCache.set(aDepth, stackframeItem);
   },
 
   /**
-   * Trims the query part or reference identifier of a url string, if necessary.
+   * Highlights a frame in this stackframes container.
    *
-   * @param string aUrl
-   *        The source url.
-   * @return string
-   *         The shortened url.
+   * @param number aDepth
+   *        The frame depth specified by the debugger controller.
+   */
+  highlightFrame: function DVSF_highlightFrame(aDepth) {
+    let selectedItem = this.selectedItem = this._framesCache.get(aDepth);
+
+    for (let item in this) {
+      if (item != selectedItem) {
+        item.attachment.popup.menuitem.removeAttribute("checked");
+      } else {
+        item.attachment.popup.menuitem.setAttribute("checked", "");
+      }
+    }
+  },
+
+  /**
+   * Specifies if the active thread has more frames that need to be loaded.
    */
-  trimUrlQuery: function SU_trimUrlQuery(aUrl) {
-    let length = aUrl.length;
-    let q1 = aUrl.indexOf('?');
-    let q2 = aUrl.indexOf('&');
-    let q3 = aUrl.indexOf('#');
-    let q = Math.min(q1 != -1 ? q1 : length,
-                     q2 != -1 ? q2 : length,
-                     q3 != -1 ? q3 : length);
+  dirty: false,
 
-    return aUrl.slice(0, q);
+  /**
+   * Customization function for creating an item's UI.
+   *
+   * @param string aFrameTitle
+   *        The frame title to be displayed in the list.
+   * @param string aSourceLocation
+   *        The source location to be displayed in the list.
+   * @param string aLineNumber
+   *        The line number to be displayed in the list.
+   * @param number aDepth
+   *        The frame depth specified by the debugger.
+   * @return nsIDOMNode
+   *         The stack frame view.
+   */
+  _createFrameView:
+  function DVSF__createFrameView(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
+    let frameDetails = SourceUtils.getSourceLabel(aSourceLocation,
+      STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
+      STACK_FRAMES_SOURCE_URL_TRIM_SECTION) +
+      SEARCH_LINE_FLAG + aLineNumber;
+
+    let frameTitleNode = document.createElement("label");
+    frameTitleNode.className = "plain dbg-stackframe-title breadcrumbs-widget-item-tag";
+    frameTitleNode.setAttribute("value", aFrameTitle);
+
+    let frameDetailsNode = document.createElement("label");
+    frameDetailsNode.className = "plain dbg-stackframe-details breadcrumbs-widget-item-id";
+    frameDetailsNode.setAttribute("value", frameDetails);
+
+    let container = document.createElement("hbox");
+    container.id = "stackframe-" + aDepth;
+    container.className = "dbg-stackframe";
+
+    container.appendChild(frameTitleNode);
+    container.appendChild(frameDetailsNode);
+
+    return container;
   },
 
   /**
-   * Trims as much as possible from a url, while keeping the result unique
-   * in the sources container.
+   * Customization function for populating an item's context menu.
    *
-   * @param string | nsIURL aUrl
-   *        The script url.
-   * @param string aLabel [optional]
-   *        The resulting label at each step.
-   * @param number aSeq [optional]
-   *        The current iteration step.
-   * @return string
-   *         The resulting label at the final step.
+   * @param string aFrameTitle
+   *        The frame title to be displayed in the list.
+   * @param string aSourceLocation
+   *        The source location to be displayed in the list.
+   * @param string aLineNumber
+   *        The line number to be displayed in the list.
+   * @param number aDepth
+   *        The frame depth specified by the debugger.
+   * @return object
+   *         An object containing the stack frame command and menu item.
+   */
+  _createMenuEntry:
+  function DVSF__createMenuEntry(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
+    let frameDescription = SourceUtils.getSourceLabel(aSourceLocation,
+      STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH,
+      STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION) +
+      SEARCH_LINE_FLAG + aLineNumber;
+
+    let prefix = "sf-cMenu-"; // "stackframes context menu"
+    let commandId = prefix + aDepth + "-" + "-command";
+    let menuitemId = prefix + aDepth + "-" + "-menuitem";
+
+    let command = document.createElement("command");
+    command.id = commandId;
+    command.addEventListener("command", this._selectFrame.bind(this, aDepth), false);
+
+    let menuitem = document.createElement("menuitem");
+    menuitem.id = menuitemId;
+    menuitem.className = "dbg-stackframe-menuitem";
+    menuitem.setAttribute("type", "checkbox");
+    menuitem.setAttribute("command", commandId);
+    menuitem.setAttribute("tooltiptext", aSourceLocation);
+
+    let labelNode = document.createElement("label");
+    labelNode.className = "plain dbg-stackframe-menuitem-title";
+    labelNode.setAttribute("value", aFrameTitle);
+    labelNode.setAttribute("flex", "1");
+
+    let descriptionNode = document.createElement("label");
+    descriptionNode.className = "plain dbg-stackframe-menuitem-details";
+    descriptionNode.setAttribute("value", frameDescription);
+
+    menuitem.appendChild(labelNode);
+    menuitem.appendChild(descriptionNode);
+
+    this._commandset.appendChild(command);
+    this._menupopup.appendChild(menuitem);
+
+    return {
+      command: command,
+      menuitem: menuitem
+    };
+  },
+
+  /**
+   * Destroys a context menu item for a stack frame.
+   *
+   * @param object aMenuEntry
+   *        An object containing the stack frame command and menu item.
+   */
+  _destroyMenuEntry: function DVSF__destroyMenuEntry(aMenuEntry) {
+    dumpn("Destroying context menu: " +
+      aMenuEntry.command.id + " & " + aMenuEntry.menuitem.id);
+
+    let command = aMenuEntry.command;
+    let menuitem = aMenuEntry.menuitem;
+    command.parentNode.removeChild(command);
+    menuitem.parentNode.removeChild(menuitem);
+  },
+
+  /**
+   * Function called each time a stack frame item is removed.
+   *
+   * @param MenuItem aItem
+   *        The corresponding menu item.
+   */
+  _onStackframeRemoved: function DVSF__onStackframeRemoved(aItem) {
+    dumpn("Finalizing stackframe item: " + aItem);
+
+    let { popup, depth } = aItem.attachment;
+    this._destroyMenuEntry(popup);
+    this._framesCache.delete(depth);
+  },
+
+  /**
+   * The click listener for the stackframes container.
    */
-  trimUrl: function SU_trimUrl(aUrl, aLabel, aSeq) {
-    if (!(aUrl instanceof Ci.nsIURL)) {
-      try {
-        // Use an nsIURL to parse all the url path parts.
-        aUrl = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
-      } catch (e) {
-        // This doesn't look like a url, or nsIURL can't handle it.
-        return aUrl;
-      }
+  _onClick: function DVSF__onClick(e) {
+    if (e && e.button != 0) {
+      // Only allow left-click to trigger this event.
+      return;
+    }
+    let item = this.getItemForElement(e.target);
+    if (item) {
+      // The container is not empty and we clicked on an actual item.
+      this._selectFrame(item.attachment.depth);
+    }
+  },
+
+  /**
+   * The scroll listener for the stackframes container.
+   */
+  _onScroll: function DVSF__onScroll() {
+    // Update the stackframes container only if we have to.
+    if (!this.dirty) {
+      return;
+    }
+    window.clearTimeout(this._scrollTimeout);
+    this._scrollTimeout = window.setTimeout(this._afterScroll, STACK_FRAMES_SCROLL_DELAY);
+  },
+
+  /**
+   * Requests the addition of more frames from the controller.
+   */
+  _afterScroll: function DVSF__afterScroll() {
+    let list = this.node._list;
+    let scrollPosition = list.scrollPosition;
+    let scrollWidth = list.scrollWidth;
+
+    // If the stackframes container scrolled almost to the end, with only
+    // 1/10 of a breadcrumb remaining, load more content.
+    if (scrollPosition - scrollWidth / 10 < 1) {
+      list.ensureElementIsVisible(this.getItemAtIndex(CALL_STACK_PAGE_SIZE - 1).target);
+      this.dirty = false;
+
+      // Loads more stack frames from the debugger server cache.
+      DebuggerController.StackFrames.addMoreFrames();
     }
-    if (!aSeq) {
-      let name = aUrl.fileName;
-      if (name) {
-        // This is a regular file url, get only the file name (contains the
-        // base name and extension if available).
+  },
+
+  /**
+   * Requests selection of a frame from the controller.
+   *
+   * @param number aDepth
+   *        The depth of the frame in the stack.
+   */
+  _selectFrame: function DVSF__selectFrame(aDepth) {
+    DebuggerController.StackFrames.selectFrame(aDepth);
+  },
+
+  _framesCache: null,
+  _commandset: null,
+  _menupopup: null,
+  _scrollTimeout: null
+});
 
-        // If this url contains an invalid query, unfortunately nsIURL thinks
-        // it's part of the file extension. It must be removed.
-        aLabel = aUrl.fileName.replace(/\&.*/, "");
-      } else {
-        // This is not a file url, hence there is no base name, nor extension.
-        // Proceed using other available information.
-        aLabel = "";
-      }
-      aSeq = 1;
+/**
+ * Utility functions for handling stackframes.
+ */
+let StackFrameUtils = {
+  /**
+   * Create a textual representation for the specified stack frame
+   * to display in the stackframes container.
+   *
+   * @param object aFrame
+   *        The stack frame to label.
+   */
+  getFrameTitle: function SFU_getFrameTitle(aFrame) {
+    if (aFrame.type == "call") {
+      let c = aFrame.callee;
+      return (c.name || c.userDisplayName || c.displayName || "(anonymous)");
+    }
+    return "(" + aFrame.type + ")";
+  },
+
+  /**
+   * Constructs a scope label based on its environment.
+   *
+   * @param object aEnv
+   *        The scope's environment.
+   * @return string
+   *         The scope's label.
+   */
+  getScopeLabel: function SFU_getScopeLabel(aEnv) {
+    let name = "";
+
+    // Name the outermost scope Global.
+    if (!aEnv.parent) {
+      name = L10N.getStr("globalScopeLabel");
+    }
+    // Otherwise construct the scope name.
+    else {
+      name = aEnv.type.charAt(0).toUpperCase() + aEnv.type.slice(1);
     }
 
-    // If we have a label and it doesn't start with a query...
-    if (aLabel && aLabel.indexOf("?") != 0) {
-      if (DebuggerView.Sources.containsTrimmedValue(aUrl.spec)) {
-        // A page may contain multiple requests to the same url but with different
-        // queries. It would be redundant to show each one.
-        return aLabel;
-      }
-      if (!DebuggerView.Sources.containsLabel(aLabel)) {
-        // We found the shortest unique label for the url.
-        return aLabel;
-      }
-    }
-
-    // Append the url query.
-    if (aSeq == 1) {
-      let query = aUrl.query;
-      if (query) {
-        return this.trimUrl(aUrl, aLabel + "?" + query, aSeq + 1);
-      }
-      aSeq++;
+    let label = L10N.getFormatStr("scopeLabel", [name]);
+    switch (aEnv.type) {
+      case "with":
+      case "object":
+        label += " [" + aEnv.object.class + "]";
+        break;
+      case "function":
+        let f = aEnv.function;
+        label += " [" +
+          (f.name || f.userDisplayName || f.displayName || "(anonymous)") +
+        "]";
+        break;
     }
-    // Append the url reference.
-    if (aSeq == 2) {
-      let ref = aUrl.ref;
-      if (ref) {
-        return this.trimUrl(aUrl, aLabel + "#" + aUrl.ref, aSeq + 1);
-      }
-      aSeq++;
-    }
-    // Prepend the url directory.
-    if (aSeq == 3) {
-      let dir = aUrl.directory;
-      if (dir) {
-        return this.trimUrl(aUrl, dir.replace(/^\//, "") + aLabel, aSeq + 1);
-      }
-      aSeq++;
-    }
-    // Prepend the hostname and port number.
-    if (aSeq == 4) {
-      let host = aUrl.hostPort;
-      if (host) {
-        return this.trimUrl(aUrl, host + "/" + aLabel, aSeq + 1);
-      }
-      aSeq++;
-    }
-    // Use the whole url spec but ignoring the reference.
-    if (aSeq == 5) {
-      return this.trimUrl(aUrl, aUrl.specIgnoringRef, aSeq + 1);
-    }
-    // Give up.
-    return aUrl.spec;
+    return label;
   }
 };
 
 /**
  * Functions handling the filtering UI.
  */
 function FilterView() {
   dumpn("FilterView was instantiated");
+
   this._onClick = this._onClick.bind(this);
   this._onSearch = this._onSearch.bind(this);
   this._onKeyPress = this._onKeyPress.bind(this);
   this._onBlur = this._onBlur.bind(this);
 }
 
 FilterView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVF_initialize() {
     dumpn("Initializing the FilterView");
+
     this._searchbox = document.getElementById("searchbox");
-    this._searchboxPanel = document.getElementById("searchbox-panel");
+    this._searchboxHelpPanel = document.getElementById("searchbox-help-panel");
     this._globalOperatorButton = document.getElementById("global-operator-button");
     this._globalOperatorLabel = document.getElementById("global-operator-label");
     this._tokenOperatorButton = document.getElementById("token-operator-button");
     this._tokenOperatorLabel = document.getElementById("token-operator-label");
     this._lineOperatorButton = document.getElementById("line-operator-button");
     this._lineOperatorLabel = document.getElementById("line-operator-label");
     this._variableOperatorButton = document.getElementById("variable-operator-button");
     this._variableOperatorLabel = document.getElementById("variable-operator-label");
@@ -603,16 +724,17 @@ FilterView.prototype = {
     // }
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVF_destroy() {
     dumpn("Destroying the FilterView");
+
     this._searchbox.removeEventListener("click", this._onClick, false);
     this._searchbox.removeEventListener("select", this._onSearch, false);
     this._searchbox.removeEventListener("input", this._onSearch, false);
     this._searchbox.removeEventListener("keypress", this._onKeyPress, false);
     this._searchbox.removeEventListener("blur", this._onBlur, false);
   },
 
   /**
@@ -701,31 +823,33 @@ FilterView.prototype = {
    */
   get searchedToken() this.searchboxInfo[2],
 
   /**
    * Clears the text from the searchbox and resets any changed view.
    */
   clearSearch: function DVF_clearSearch() {
     this._searchbox.value = "";
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Performs a file search if necessary.
    *
    * @param string aFile
    *        The source location to search for.
    */
   _performFileSearch: function DVF__performFileSearch(aFile) {
     // Don't search for files if the input hasn't changed.
     if (this._prevSearchedFile == aFile) {
       return;
     }
 
+    // This is the target container to be currently filtered. Clicking on a
+    // container generally means it should become a target.
     let view = this._target;
 
     // If we're not searching for a file anymore, unhide all the items.
     if (!aFile) {
       for (let item in view) {
         item.target.hidden = false;
       }
       view.refresh();
@@ -758,16 +882,23 @@ FilterView.prototype = {
       // If no matches were found, display the appropriate info.
       if (!found) {
         view.setUnavailable();
       }
     }
     // Synchronize with the view's filtered sources container.
     DebuggerView.FilteredSources.syncFileSearch();
 
+    // Hide all the groups with no visible children.
+    view.node.hideEmptyGroups();
+
+    // Ensure the currently selected item is visible.
+    view.node.ensureSelectionIsVisible(true);
+
+    // Remember the previously searched file to avoid redundant filtering.
     this._prevSearchedFile = aFile;
   },
 
   /**
    * Performs a line search if necessary.
    * (Jump to lines in the currently visible source).
    *
    * @param number aLine
@@ -777,16 +908,18 @@ FilterView.prototype = {
     // Don't search for lines if the input hasn't changed.
     if (this._prevSearchedLine != aLine && aLine) {
       DebuggerView.editor.setCaretPosition(aLine - 1);
     }
     // Can't search for lines and tokens at the same time.
     if (this._prevSearchedToken && !aLine) {
       this._target.refresh();
     }
+
+    // Remember the previously searched line to avoid redundant filtering.
     this._prevSearchedLine = aLine;
   },
 
   /**
    * Performs a token search if necessary.
    * (Search for tokens in the currently visible source).
    *
    * @param string aToken
@@ -800,31 +933,33 @@ FilterView.prototype = {
       if (offset > -1) {
         editor.setSelection(offset, offset + aToken.length)
       }
     }
     // Can't search for tokens and lines at the same time.
     if (this._prevSearchedLine && !aToken) {
       this._target.refresh();
     }
+
+    // Remember the previously searched token to avoid redundant filtering.
     this._prevSearchedToken = aToken;
   },
 
   /**
    * The click listener for the search container.
    */
   _onClick: function DVF__onClick() {
-    this._searchboxPanel.openPopup(this._searchbox);
+    this._searchboxHelpPanel.openPopup(this._searchbox);
   },
 
   /**
    * The search listener for the search container.
    */
   _onSearch: function DVF__onScriptsSearch() {
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
     let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
 
     // If this is a global search, schedule it for when the user stops typing,
     // or hide the corresponding pane otherwise.
     if (isGlobal) {
       DebuggerView.GlobalSearch.scheduleSearch(token);
       this._prevSearchedToken = token;
       return;
@@ -868,17 +1003,17 @@ FilterView.prototype = {
     // Meta+G and Ctrl+N focus next matches.
     if ((e.char == "g" && e.metaKey) || e.char == "n" && e.ctrlKey) {
       action = 0;
     }
     // Meta+Shift+G and Ctrl+P focus previous matches.
     else if ((e.char == "G" && e.metaKey) || e.char == "p" && e.ctrlKey) {
       action = 1;
     }
-    // Return, enter down and up keys focus next or previous matches, while
+    // Return, enter, down and up keys focus next or previous matches, while
     // the escape key switches focus from the search container.
     else switch (e.keyCode) {
       case e.DOM_VK_RETURN:
       case e.DOM_VK_ENTER:
         isReturnKey = true;
         // fall through
       case e.DOM_VK_DOWN:
         action = 0;
@@ -958,17 +1093,17 @@ FilterView.prototype = {
   },
 
   /**
    * The blur listener for the search container.
    */
   _onBlur: function DVF__onBlur() {
     DebuggerView.GlobalSearch.clearView();
     DebuggerView.Variables.performSearch(null);
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Called when a filtering key sequence was pressed.
    *
    * @param string aOperator
    *        The operator to use for filtering.
    */
@@ -977,62 +1112,62 @@ FilterView.prototype = {
     this._searchbox.value = aOperator;
   },
 
   /**
    * Called when the source location filter key sequence was pressed.
    */
   _doFileSearch: function DVF__doFileSearch() {
     this._doSearch();
-    this._searchboxPanel.openPopup(this._searchbox);
+    this._searchboxHelpPanel.openPopup(this._searchbox);
   },
 
   /**
    * Called when the global search filter key sequence was pressed.
    */
   _doGlobalSearch: function DVF__doGlobalSearch() {
     this._doSearch(SEARCH_GLOBAL_FLAG);
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Called when the source token filter key sequence was pressed.
    */
   _doTokenSearch: function DVF__doTokenSearch() {
     this._doSearch(SEARCH_TOKEN_FLAG);
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Called when the source line filter key sequence was pressed.
    */
   _doLineSearch: function DVF__doLineSearch() {
     this._doSearch(SEARCH_LINE_FLAG);
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Called when the variable search filter key sequence was pressed.
    */
   _doVariableSearch: function DVF__doVariableSearch() {
     DebuggerView.Variables.performSearch("");
     this._doSearch(SEARCH_VARIABLE_FLAG);
-    this._searchboxPanel.hidePopup();
+    this._searchboxHelpPanel.hidePopup();
   },
 
   /**
    * Called when the variables focus key sequence was pressed.
    */
   _doVariablesFocus: function DVG__doVariablesFocus() {
-    DebuggerView.showPanesSoon();
+    DebuggerView.showInstrumentsPane();
     DebuggerView.Variables.focusFirstVisibleNode();
   },
 
   _searchbox: null,
-  _searchboxPanel: null,
+  _searchboxHelpPanel: null,
   _globalOperatorButton: null,
   _globalOperatorLabel: null,
   _tokenOperatorButton: null,
   _tokenOperatorLabel: null,
   _lineOperatorButton: null,
   _lineOperatorLabel: null,
   _variableOperatorButton: null,
   _variableOperatorLabel: null,
@@ -1046,60 +1181,54 @@ FilterView.prototype = {
   _prevSearchedLine: 0,
   _prevSearchedToken: ""
 };
 
 /**
  * Functions handling the filtered sources UI.
  */
 function FilteredSourcesView() {
-  MenuContainer.call(this);
+  dumpn("FilteredSourcesView was instantiated");
+
   this._onClick = this._onClick.bind(this);
 }
 
 create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVFS_initialize() {
     dumpn("Initializing the FilteredSourcesView");
 
-    let panel = this._panel = document.createElement("panel");
-    panel.id = "filtered-sources-panel";
-    panel.setAttribute("noautofocus", "true");
-    panel.setAttribute("level", "top");
-    panel.setAttribute("position", FILTERED_SOURCES_POPUP_POSITION);
-    document.documentElement.appendChild(panel);
+    this.node = new ListWidget(document.getElementById("filtered-sources-panel"));
+    this._searchbox = document.getElementById("searchbox");
 
-    this._searchbox = document.getElementById("searchbox");
-    this._container = new StackList(panel);
-
-    this._container.itemFactory = this._createItemView;
-    this._container.itemType = "vbox";
-    this._container.addEventListener("click", this._onClick, false);
+    this.node.itemFactory = this._createItemView;
+    this.node.itemType = "vbox";
+    this.node.addEventListener("click", this._onClick, false);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVFS_destroy() {
     dumpn("Destroying the FilteredSourcesView");
-    document.documentElement.removeChild(this._panel);
-    this._container.removeEventListener("click", this._onClick, false);
+
+    this.node.removeEventListener("click", this._onClick, false);
   },
 
   /**
    * Sets the files container hidden or visible. It's hidden by default.
    * @param boolean aFlag
    */
   set hidden(aFlag) {
     if (aFlag) {
-      this._container._parent.hidePopup();
+      this.node._parent.hidePopup();
     } else {
-      this._container._parent.openPopup(this._searchbox);
+      this.node._parent.openPopup(this._searchbox);
     }
   },
 
   /**
    * Updates the list of sources displayed in this container.
    */
   syncFileSearch: function DVFS_syncFileSearch() {
     this.empty();
@@ -1115,66 +1244,59 @@ create({ constructor: FilteredSourcesVie
     // Get the currently visible items in the sources container.
     let visibleItems = DebuggerView.Sources.visibleItems;
     let displayedItems = visibleItems.slice(0, FILTERED_SOURCES_MAX_RESULTS);
 
     for (let item of displayedItems) {
       // Append a location item item to this container.
       let trimmedLabel = SourceUtils.trimUrlLength(item.label);
       let trimmedValue = SourceUtils.trimUrlLength(item.value);
-
-      let locationItem = this.push(trimmedLabel, trimmedValue, {
-        forced: true,
-        relaxed: true,
-        unsorted: true,
+      let locationItem = this.push([trimmedLabel, trimmedValue], {
+        relaxed: true, /* this container should allow dupes & degenerates */
         attachment: {
           fullLabel: item.label,
           fullValue: item.value
         }
       });
-
-      let element = locationItem.target;
-      element.className = "dbg-source-item list-item";
-      element.labelNode.className = "dbg-source-item-name plain";
-      element.valueNode.className = "dbg-source-item-details plain";
     }
 
     this._updateSelection(this.getItemAtIndex(0));
     this.hidden = false;
   },
 
   /**
    * Focuses the next found match in this container.
    */
   focusNext: function DVFS_focusNext() {
     let nextIndex = this.selectedIndex + 1;
-    if (nextIndex >= this.totalItems) {
+    if (nextIndex >= this.itemCount) {
       nextIndex = 0;
     }
     this._updateSelection(this.getItemAtIndex(nextIndex));
   },
 
   /**
    * Focuses the previously found match in this container.
    */
   focusPrev: function DVFS_focusPrev() {
     let prevIndex = this.selectedIndex - 1;
     if (prevIndex < 0) {
-      prevIndex = this.totalItems - 1;
+      prevIndex = this.itemCount - 1;
     }
     this._updateSelection(this.getItemAtIndex(prevIndex));
   },
 
   /**
    * The click listener for this container.
    */
   _onClick: function DVFS__onClick(e) {
     let locationItem = this.getItemForElement(e.target);
     if (locationItem) {
       this._updateSelection(locationItem);
+      DebuggerView.Filtering.clearSearch();
     }
   },
 
   /**
    * Updates the selected item in this container and other views.
    *
    * @param MenuItem aItem
    *        The item associated with the element to select.
@@ -1182,40 +1304,44 @@ create({ constructor: FilteredSourcesVie
   _updateSelection: function DVFS__updateSelection(aItem) {
     this.selectedItem = aItem;
     DebuggerView.Filtering._target.selectedValue = aItem.attachment.fullValue;
   },
 
   /**
    * Customization function for creating an item's UI.
    *
+   * @param nsIDOMNode aElementNode
+   *        The element associated with the displayed item.
+   * @param any aAttachment
+   *        Some attached primitive/object.
    * @param string aLabel
    *        The item's label.
    * @param string aValue
    *        The item's value.
    */
-  _createItemView: function DVFS__createItemView(aElementNode, aLabel, aValue) {
+  _createItemView:
+  function DVFS__createItemView(aElementNode, aAttachment, aLabel, aValue) {
     let labelNode = document.createElement("label");
-    let valueNode = document.createElement("label");
+    labelNode.className = "plain dbg-source-item-name";
+    labelNode.setAttribute("value", aLabel);
 
-    labelNode.setAttribute("value", aLabel);
+    let valueNode = document.createElement("label");
     valueNode.setAttribute("value", aValue);
+    valueNode.className = "plain dbg-source-item-details";
 
+    aElementNode.className = "light dbg-source-item";
     aElementNode.appendChild(labelNode);
     aElementNode.appendChild(valueNode);
-
-    aElementNode.labelNode = labelNode;
-    aElementNode.valueNode = valueNode;
   },
 
-  _panel: null,
   _searchbox: null
 });
 
 /**
  * Preliminary setup for the DebuggerView object.
  */
 DebuggerView.Toolbar = new ToolbarView();
 DebuggerView.Options = new OptionsView();
-DebuggerView.ChromeGlobals = new ChromeGlobalsView();
-DebuggerView.Sources = new SourcesView();
 DebuggerView.Filtering = new FilterView();
 DebuggerView.FilteredSources = new FilteredSourcesView();
+DebuggerView.ChromeGlobals = new ChromeGlobalsView();
+DebuggerView.StackFrames = new StackFramesView();
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -1,22 +1,27 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
-const SOURCE_URL_MAX_LENGTH = 64; // chars
+const SOURCE_URL_DEFAULT_MAX_LENGTH = 64; // chars
 const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 1048576; // 1 MB in bytes
+const STACK_FRAMES_SOURCE_URL_MAX_LENGTH = 15; // chars
+const STACK_FRAMES_SOURCE_URL_TRIM_SECTION = "center";
+const STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH = 32; // chars
+const STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION = "center";
+const STACK_FRAMES_SCROLL_DELAY = 100; // ms
 const PANES_APPEARANCE_DELAY = 50; // ms
 const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
-const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "after_start";
-const BREAKPOINT_CONDITIONAL_POPUP_OFFSET = 50; // px
-const FILTERED_SOURCES_POPUP_POSITION = "before_start";
+const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "before_start";
+const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X = 7; // px
+const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_Y = -3; // px
 const FILTERED_SOURCES_MAX_RESULTS = 10;
 const GLOBAL_SEARCH_EXPAND_MAX_RESULTS = 50;
 const GLOBAL_SEARCH_LINE_MAX_LENGTH = 300; // chars
 const GLOBAL_SEARCH_ACTION_MAX_DELAY = 1500; // ms
 const SEARCH_GLOBAL_FLAG = "!";
 const SEARCH_TOKEN_FLAG = "#";
 const SEARCH_LINE_FLAG = ":";
 const SEARCH_VARIABLE_FLAG = "*";
@@ -34,22 +39,21 @@ let DebuggerView = {
   initialize: function DV_initialize(aCallback) {
     dumpn("Initializing the DebuggerView");
 
     this._initializeWindow();
     this._initializePanes();
 
     this.Toolbar.initialize();
     this.Options.initialize();
-    this.ChromeGlobals.initialize();
-    this.Sources.initialize();
     this.Filtering.initialize();
     this.FilteredSources.initialize();
+    this.ChromeGlobals.initialize();
     this.StackFrames.initialize();
-    this.Breakpoints.initialize();
+    this.Sources.initialize();
     this.WatchExpressions.initialize();
     this.GlobalSearch.initialize();
 
     this.Variables = new VariablesView(document.getElementById("variables"));
     this.Variables.searchPlaceholder = L10N.getStr("emptyVariablesFilterText");
     this.Variables.emptyText = L10N.getStr("emptyVariablesText");
     this.Variables.onlyEnumVisible = Prefs.variablesOnlyEnumVisible;
     this.Variables.searchEnabled = Prefs.variablesSearchboxVisible;
@@ -65,22 +69,21 @@ let DebuggerView = {
    * @param function aCallback
    *        Called after the view finishes destroying.
    */
   destroy: function DV_destroy(aCallback) {
     dumpn("Destroying the DebuggerView");
 
     this.Toolbar.destroy();
     this.Options.destroy();
-    this.ChromeGlobals.destroy();
-    this.Sources.destroy();
     this.Filtering.destroy();
     this.FilteredSources.destroy();
+    this.ChromeGlobals.destroy();
     this.StackFrames.destroy();
-    this.Breakpoints.destroy();
+    this.Sources.destroy();
     this.WatchExpressions.destroy();
     this.GlobalSearch.destroy();
 
     this._destroyWindow();
     this._destroyPanes();
     this._destroyEditor();
     aCallback();
   },
@@ -104,57 +107,57 @@ let DebuggerView = {
         document.title = L10N.getStr("chromeDebuggerWindowTitle");
       }
     }
   },
 
   /**
    * Destroys the UI for the window.
    */
-  _destroyWindow: function DV__initializeWindow() {
+  _destroyWindow: function DV__destroyWindow() {
     dumpn("Destroying the DebuggerView window");
 
     if (window._isRemoteDebugger || window._isChromeDebugger) {
       Prefs.windowX = window.screenX;
       Prefs.windowY = window.screenY;
       Prefs.windowWidth = window.outerWidth;
       Prefs.windowHeight = window.outerHeight;
     }
   },
 
   /**
    * Initializes the UI for all the displayed panes.
    */
   _initializePanes: function DV__initializePanes() {
     dumpn("Initializing the DebuggerView panes");
 
-    this._togglePanesButton = document.getElementById("toggle-panes");
-    this._stackframesAndBreakpoints = document.getElementById("stackframes+breakpoints");
-    this._variablesAndExpressions = document.getElementById("variables+expressions");
+    this._sourcesPane = document.getElementById("sources-pane");
+    this._instrumentsPane = document.getElementById("instruments-pane");
+    this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
 
-    this._stackframesAndBreakpoints.setAttribute("width", Prefs.stackframesWidth);
-    this._variablesAndExpressions.setAttribute("width", Prefs.variablesWidth);
-    this.togglePanes({
-      visible: Prefs.panesVisibleOnStartup,
-      animated: false
-    });
+    this._collapsePaneString = L10N.getStr("collapsePanes");
+    this._expandPaneString = L10N.getStr("expandPanes");
+
+    this._sourcesPane.setAttribute("width", Prefs.sourcesWidth);
+    this._instrumentsPane.setAttribute("width", Prefs.instrumentsWidth);
+    this.toggleInstrumentsPane({ visible: Prefs.panesVisibleOnStartup });
   },
 
   /**
    * Destroys the UI for all the displayed panes.
    */
-  _destroyPanes: function DV__initializePanes() {
+  _destroyPanes: function DV__destroyPanes() {
     dumpn("Destroying the DebuggerView panes");
 
-    Prefs.stackframesWidth = this._stackframesAndBreakpoints.getAttribute("width");
-    Prefs.variablesWidth = this._variablesAndExpressions.getAttribute("width");
+    Prefs.sourcesWidth = this._sourcesPane.getAttribute("width");
+    Prefs.instrumentsWidth = this._instrumentsPane.getAttribute("width");
 
-    this._togglePanesButton = null;
-    this._stackframesAndBreakpoints = null;
-    this._variablesAndExpressions = null;
+    this._sourcesPane = null;
+    this._instrumentsPane = null;
+    this._instrumentsPaneToggleButton = null;
   },
 
   /**
    * Initializes the SourceEditor instance.
    *
    * @param function aCallback
    *        Called after the editor finishes initializing.
    */
@@ -167,64 +170,57 @@ let DebuggerView = {
       readOnly: true,
       showLineNumbers: true,
       showAnnotationRuler: true,
       showOverviewRuler: true
     };
 
     this.editor = new SourceEditor();
     this.editor.init(placeholder, config, function() {
+      this._loadingText = L10N.getStr("loadingText");
       this._onEditorLoad();
       aCallback();
     }.bind(this));
   },
 
   /**
    * The load event handler for the source editor, also executing any necessary
    * post-load operations.
    */
   _onEditorLoad: function DV__onEditorLoad() {
     dumpn("Finished loading the DebuggerView editor");
 
     DebuggerController.Breakpoints.initialize();
-    window.dispatchEvent("Debugger:EditorLoaded", this.editor);
+    window.dispatchEvent(document, "Debugger:EditorLoaded", this.editor);
     this.editor.focus();
   },
 
   /**
    * Destroys the SourceEditor instance and also executes any necessary
    * post-unload operations.
    */
   _destroyEditor: function DV__destroyEditor() {
     dumpn("Destroying the DebuggerView editor");
 
     DebuggerController.Breakpoints.destroy();
-    window.dispatchEvent("Debugger:EditorUnloaded", this.editor);
-    this.editor = null;
+    window.dispatchEvent(document, "Debugger:EditorUnloaded", this.editor);
   },
 
   /**
    * Sets the proper editor mode (JS or HTML) according to the specified
-   * content type, or by determining the type from the url.
+   * content type, or by determining the type from the url or text content.
    *
    * @param string aUrl
-   *        The script url.
+   *        The source url.
    * @param string aContentType [optional]
-   *        The script content type.
+   *        The source content type.
    * @param string aTextContent [optional]
-   *        The script text content.
+   *        The source text content.
    */
-  setEditorMode:
-  function DV_setEditorMode(aUrl, aContentType = "", aTextContent = "") {
-    if (!this.editor) {
-      return;
-    }
-    dumpn("Setting the DebuggerView editor mode: " + aUrl +
-          ", content type: " + aContentType);
-
+  setEditorMode: function DV_setEditorMode(aUrl, aContentType = "", aTextContent = "") {
     if (aContentType) {
       if (/javascript/.test(aContentType)) {
         this.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
       } else {
         this.editor.setMode(SourceEditor.MODES.HTML);
       }
     } else if (aTextContent.match(/^\s*</)) {
       // Use HTML mode for files in which the first non whitespace character is
@@ -236,96 +232,105 @@ let DebuggerView = {
         this.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
       } else {
         this.editor.setMode(SourceEditor.MODES.TEXT);
       }
     }
   },
 
   /**
-   * Load the editor with the specified source text.
+   * Sets the currently displayed source text in the editor.
+   *
+   * To update the source editor's current caret and debug location based on
+   * a requested url and line, use the DebuggerView.updateEditor method.
    *
    * @param object aSource
    *        The source object coming from the active thread.
-   * @param object aOptions [optional]
-   *        Additional options for showing the source. Supported options:
-   *        - caretLine: place the caret position at the given line number
-   *        - debugLine: place the debug location at the given line number
-   *        - callback: function called when the source is shown
    */
-  setEditorSource: function DV_setEditorSource(aSource, aOptions = {}) {
-    if (!this.editor) {
+  set editorSource(aSource) {
+    if (!this._isInitialized || this._isDestroyed || this._editorSource == aSource) {
       return;
     }
 
-    dumpn("Setting the DebuggerView editor source: " + aSource.source.url +
-          ", loaded: " + aSource.loaded +
-          ", options: " + aOptions.toSource());
+    dumpn("Setting the DebuggerView editor source: " + aSource.url +
+          ", loaded: " + aSource.loaded);
+
+    this.editor.setMode(SourceEditor.MODES.TEXT);
+    this.editor.setText(L10N.getStr("loadingText"));
+    this.editor.resetUndo();
+    this._editorSource = aSource;
 
     // If the source is not loaded, display a placeholder text.
     if (!aSource.loaded) {
-      this.editor.setMode(SourceEditor.MODES.TEXT);
-      this.editor.setText(L10N.getStr("loadingText"));
-      this.editor.resetUndo();
-
-      // Get the source text from the active thread.
-      DebuggerController.SourceScripts.getText(aSource, function(aUrl, aText) {
-        this.setEditorSource(aSource, aOptions);
-      }.bind(this));
+      DebuggerController.SourceScripts.getText(aSource, set.bind(this, aSource));
     }
     // If the source is already loaded, display it immediately.
     else {
+      set.call(this, aSource);
+    }
+
+    // Updates the source editor's displayed text.
+    // @param object aSource
+    function set(aSource) {
+      // Avoid setting an unexpected source. This may happen when fast switching
+      // between sources that haven't been fetched yet.
       if (this._editorSource != aSource) {
-        // Avoid setting the editor mode for very large files.
-        if (aSource.text.length < SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
-          this.setEditorMode(aSource.source.url, aSource.contentType, aSource.text);
-        } else {
-          this.editor.setMode(SourceEditor.MODES.TEXT);
-        }
-        this.editor.setText(aSource.text);
-        this.editor.resetUndo();
+        return;
       }
-      this._editorSource = aSource;
+
+      // Avoid setting the editor mode for very large files.
+      if (aSource.text.length < SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
+        this.setEditorMode(aSource.url, aSource.contentType, aSource.text);
+      } else {
+        this.editor.setMode(SourceEditor.MODES.TEXT);
+      }
+      this.editor.setText(aSource.text);
+      this.editor.resetUndo();
+
+      // Update the editor's current caret and debug locations given by the
+      // currently active frame in the stack, if there's one available.
       this.updateEditor();
 
-      DebuggerView.Sources.selectedValue = aSource.source.url;
+      // Synchronize any other components with the currently displayed source.
+      DebuggerView.Sources.selectedValue = aSource.url;
       DebuggerController.Breakpoints.updateEditorBreakpoints();
 
-      // Handle any additional options for showing the source.
-      if (aOptions.caretLine) {
-        editor.setCaretPosition(aOptions.caretLine - 1);
-      }
-      if (aOptions.debugLine) {
-        editor.setDebugLocation(aOptions.debugLine - 1);
-      }
-      if (aOptions.callback) {
-        aOptions.callback(aSource);
-      }
       // Notify that we've shown a source file.
-      window.dispatchEvent("Debugger:SourceShown", aSource);
+      window.dispatchEvent(document, "Debugger:SourceShown", aSource);
     }
   },
 
   /**
+   * Gets the currently displayed source text in the editor.
+   *
+   * @return object
+   *         The source object coming from the active thread.
+   */
+  get editorSource() this._editorSource,
+
+  /**
    * Update the source editor's current caret and debug location based on
    * a requested url and line. If unspecified, they default to the location
    * given by the currently active frame in the stack.
    *
    * @param string aUrl [optional]
    *        The target source url.
    * @param number aLine [optional]
    *        The target line number in the source.
    * @param object aFlags [optional]
-   *        An object containing some of the following boolean properties:
+   *        Additional options for showing the source. Supported options:
+   *          - charOffset: character offset for the caret or debug location
+   *          - lineOffset: line offset for the caret or debug location
+   *          - columnOffset: column offset for the caret or debug location
    *          - noSwitch: don't switch to the source if not currently selected
    *          - noCaret: don't set the caret location at the specified line
    *          - noDebug: don't set the debug location at the specified line
    */
   updateEditor: function DV_updateEditor(aUrl, aLine, aFlags = {}) {
-    if (!this.editor) {
+    if (!this._isInitialized || this._isDestroyed) {
       return;
     }
     // If the location is not specified, default to the location given by
     // the currently active frame in the stack.
     if (!aUrl && !aLine) {
       let cachedFrames = DebuggerController.activeThread.cachedFrames;
       let currentFrame = DebuggerController.StackFrames.currentFrame;
       let frame = cachedFrames[currentFrame];
@@ -336,36 +341,45 @@ let DebuggerView = {
       return;
     }
 
     dumpn("Updating the DebuggerView editor: " + aUrl + " @ " + aLine +
           ", flags: " + aFlags.toSource());
 
     // If the currently displayed source is the requested one, update.
     if (this.Sources.selectedValue == aUrl) {
-      updateLine(aLine);
+      set(aLine);
     }
     // If the requested source exists, display it and update.
     else if (this.Sources.containsValue(aUrl) && !aFlags.noSwitch) {
       this.Sources.selectedValue = aUrl;
-      updateLine(aLine);
+      set(aLine);
     }
     // Dumb request, invalidate the caret position and debug location.
     else {
-      updateLine(0);
+      set(0);
     }
 
     // Updates the source editor's caret position and debug location.
     // @param number a Line
-    function updateLine(aLine) {
+    function set(aLine) {
+      let editor = DebuggerView.editor;
+
+      // Handle any additional options for showing the source.
+      if (aFlags.charOffset) {
+        aLine += editor.getLineAtOffset(aFlags.charOffset);
+      }
+      if (aFlags.lineOffset) {
+        aLine += aFlags.lineOffset;
+      }
       if (!aFlags.noCaret) {
-        DebuggerView.editor.setCaretPosition(aLine - 1);
+        editor.setCaretPosition(aLine - 1);
       }
       if (!aFlags.noDebug) {
-        DebuggerView.editor.setDebugLocation(aLine - 1);
+        editor.setDebugLocation(aLine - 1);
       }
     }
   },
 
   /**
    * Gets the text in the source editor's specified line.
    *
    * @param number aLine [optional]
@@ -377,53 +391,52 @@ let DebuggerView = {
   getEditorLine: function SS_getEditorLine(aLine) {
     let line = aLine || this.editor.getCaretPosition().line;
     let start = this.editor.getLineStart(line);
     let end = this.editor.getLineEnd(line);
     return this.editor.getText(start, end);
   },
 
   /**
-   * Gets the visibility state of the panes.
+   * Gets the visibility state of the instruments pane.
    * @return boolean
    */
-  get panesHidden()
-    this._togglePanesButton.hasAttribute("panesHidden"),
+  get instrumentsPaneHidden()
+    this._instrumentsPaneToggleButton.hasAttribute("toggled"),
 
   /**
-   * Sets all the panes hidden or visible.
+   * Sets the instruments pane hidden or visible.
    *
    * @param object aFlags [optional]
    *        An object containing some of the following boolean properties:
    *        - visible: true if the pane should be shown, false for hidden
    *        - animated: true to display an animation on toggle
    *        - delayed: true to wait a few cycles before toggle
-   *        - callback: a function to invoke when the panes toggle finishes
+   *        - callback: a function to invoke when the toggle finishes
    */
-  togglePanes: function DV__togglePanes(aFlags = {}) {
+  toggleInstrumentsPane: function DV__toggleInstrumentsPane(aFlags = {}) {
     // Avoid useless toggles.
-    if (aFlags.visible == !this.panesHidden) {
+    if (aFlags.visible == !this.instrumentsPaneHidden) {
       if (aFlags.callback) aFlags.callback();
       return;
     }
 
-    // Computes and sets the panes margins in order to hide or show them.
+    // Computes and sets the pane margins in order to hide or show it.
     function set() {
       if (aFlags.visible) {
-        this._stackframesAndBreakpoints.style.marginLeft = "0";
-        this._variablesAndExpressions.style.marginRight = "0";
-        this._togglePanesButton.removeAttribute("panesHidden");
-        this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
+        this._instrumentsPane.style.marginLeft = "0";
+        this._instrumentsPane.style.marginRight = "0";
+        this._instrumentsPaneToggleButton.removeAttribute("toggled");
+        this._instrumentsPaneToggleButton.setAttribute("tooltiptext", this._collapsePaneString);
       } else {
-        let marginL = ~~(this._stackframesAndBreakpoints.getAttribute("width")) + 1;
-        let marginR = ~~(this._variablesAndExpressions.getAttribute("width")) + 1;
-        this._stackframesAndBreakpoints.style.marginLeft = -marginL + "px";
-        this._variablesAndExpressions.style.marginRight = -marginR + "px";
-        this._togglePanesButton.setAttribute("panesHidden", "true");
-        this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
+        let margin = ~~(this._instrumentsPane.getAttribute("width")) + 1;
+        this._instrumentsPane.style.marginLeft = -margin + "px";
+        this._instrumentsPane.style.marginRight = -margin + "px";
+        this._instrumentsPaneToggleButton.setAttribute("toggled", "true");
+        this._instrumentsPaneToggleButton.setAttribute("tooltiptext", this._expandPaneString);
       }
 
       if (aFlags.animated) {
         // Displaying the panes may have the effect of triggering scrollbars to
         // appear in the source editor, which would render the currently
         // highlighted line to appear behind them in some cases.
         window.addEventListener("transitionend", function onEvent() {
           window.removeEventListener("transitionend", onEvent, false);
@@ -434,781 +447,134 @@ let DebuggerView = {
         }, false);
       } else {
         // Invoke the callback immediately since there's no transition.
         if (aFlags.callback) aFlags.callback();
       }
     }
 
     if (aFlags.animated) {
-      this._stackframesAndBreakpoints.setAttribute("animated", "");
-      this._variablesAndExpressions.setAttribute("animated", "");
+      this._instrumentsPane.setAttribute("animated", "");
     } else {
-      this._stackframesAndBreakpoints.removeAttribute("animated");
-      this._variablesAndExpressions.removeAttribute("animated");
+      this._instrumentsPane.removeAttribute("animated");
     }
 
     if (aFlags.delayed) {
       window.setTimeout(set.bind(this), PANES_APPEARANCE_DELAY);
     } else {
       set.call(this);
     }
   },
 
   /**
-   * Sets all the panes visible after a short period of time.
+   * Sets the instruments pane visible after a short period of time.
    *
    * @param function aCallback
-   *        A function to invoke when the panes toggle finishes.
+   *        A function to invoke when the toggle finishes.
    */
-  showPanesSoon: function DV__showPanesSoon(aCallback) {
-    // Try to keep animations as smooth as possible, so wait a few cycles.
-    window.setTimeout(function() {
-      DebuggerView.togglePanes({
-        visible: true,
-        animated: true,
-        delayed: true,
-        callback: aCallback
-      });
-    }, PANES_APPEARANCE_DELAY);
+  showInstrumentsPane: function DV__showInstrumentsPane(aCallback) {
+    DebuggerView.toggleInstrumentsPane({
+      visible: true,
+      animated: true,
+      delayed: true,
+      callback: aCallback
+    });
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
   _handleTabNavigation: function DV__handleTabNavigation() {
     dumpn("Handling tab navigation in the DebuggerView");
 
-    this.ChromeGlobals.empty();
-    this.Sources.empty();
     this.Filtering.clearSearch();
     this.GlobalSearch.clearView();
     this.GlobalSearch.clearCache();
+    this.ChromeGlobals.empty();
     this.StackFrames.empty();
-    this.Breakpoints.empty();
-    this.Breakpoints.unhighlightBreakpoint();
+    this.Sources.empty();
     this.Variables.empty();
-    SourceUtils.clearLabelsCache();
+    SourceUtils.clearCache();
 
     if (this.editor) {
       this.editor.setText("");
       this.editor.focus();
       this._editorSource = null;
     }
   },
 
   Toolbar: null,
   Options: null,
+  Filtering: null,
+  FilteredSources: null,
   ChromeGlobals: null,
+  StackFrames: null,
   Sources: null,
-  Filtering: null,
-  StackFrames: null,
-  Breakpoints: null,
+  WatchExpressions: null,
   GlobalSearch: null,
   Variables: null,
   _editor: null,
   _editorSource: null,
-  _togglePanesButton: null,
-  _stackframesAndBreakpoints: null,
-  _variablesAndExpressions: null,
+  _loadingText: "",
+  _sourcesPane: null,
+  _instrumentsPane: null,
+  _instrumentsPaneToggleButton: null,
+  _collapsePaneString: "",
+  _expandPaneString: "",
   _isInitialized: false,
   _isDestroyed: false
 };
 
 /**
- * A generic item used to describe elements present in views like the
- * ChromeGlobals, Sources, Stackframes, Breakpoints etc.
- *
- * @param string aLabel
- *        The label displayed in the container.
- * @param string aValue
- *        The actual internal value of the item.
- * @param string aDescription [optional]
- *        An optional description of the item.
- * @param any aAttachment [optional]
- *        Some attached primitive/object.
- */
-function MenuItem(aLabel, aValue, aDescription, aAttachment) {
-  this._label = aLabel + "";
-  this._value = aValue + "";
-  this._description = aDescription + "";
-  this.attachment = aAttachment;
-}
-
-MenuItem.prototype = {
-  /**
-   * Gets the label set for this item.
-   * @return string
-   */
-  get label() this._label,
-
-  /**
-   * Gets the value set for this item.
-   * @return string
-   */
-  get value() this._value,
-
-  /**
-   * Gets the description set for this item.
-   * @return string
-   */
-  get description() this._description,
-
-  /**
-   * Gets the element associated with this item.
-   * @return nsIDOMNode
-   */
-  get target() this._target,
-
-  _label: "",
-  _value: "",
-  _description: "",
-  _target: null,
-  finalize: null,
-  attachment: null
-};
-
-/**
- * A generic items container, used for displaying views like the
- * ChromeGlobals, Sources, Stackframes, Breakpoints etc.
- * Iterable via "for (let item in menuContainer) { }".
- *
- * Language:
- *   - An "item" is an instance (or compatible iterface) of a MenuItem.
- *   - An "element" or "node" is a nsIDOMNode.
- *
- * The container node supplied to all instances of this constructor can either
- * be a <menulist> element, or any other object interfacing the following
- * methods:
- *   - function:nsIDOMNode appendItem(aLabel:string, aValue:string)
- *   - function:nsIDOMNode insertItemAt(aIndex:number, aLabel:string, aValue:string)
- *   - function:nsIDOMNode getItemAtIndex(aIndex:number)
- *   - function removeChild(aChild:nsIDOMNode)
- *   - function removeAllItems()
- *   - get:number itemCount()
- *   - get:number selectedIndex()
- *   - set selectedIndex(aIndex:number)
- *   - get:nsIDOMNode selectedItem()
- *   - set selectedItem(aChild:nsIDOMNode)
- *   - function getAttribute(aName:string)
- *   - function setAttribute(aName:string, aValue:string)
- *   - function removeAttribute(aName:string)
- *   - function addEventListener(aName:string, aCallback:function, aBubbleFlag:boolean)
- *   - function removeEventListener(aName:string, aCallback:function, aBubbleFlag:boolean)
+ * A stacked list of items, compatible with MenuContainer instances, used for
+ * displaying views like the watch expressions, filtering or search results etc.
  *
- * @param nsIDOMNode aContainerNode [optional]
- *        The element associated with the displayed container. Although required,
- *        derived objects may set this value later, upon debugger initialization.
- */
-function MenuContainer(aContainerNode) {
-  this._container = aContainerNode;
-  this._stagedItems = [];
-  this._itemsByLabel = new Map();
-  this._itemsByValue = new Map();
-  this._itemsByElement = new Map();
-}
-
-MenuContainer.prototype = {
-  /**
-   * Prepares an item to be added to this container. This allows for a large
-   * number of items to be batched up before being alphabetically sorted and
-   * added in this menu.
-   *
-   * If the "forced" flag is true, the item will be immediately inserted at the
-   * correct position in this container, so that all the items remain sorted.
-   * This can (possibly) be much slower than batching up multiple items.
-   *
-   * By default, this container assumes that all the items should be displayed
-   * sorted by their label. This can be overridden with the "unsorted" flag.
-   *
-   * Furthermore, this container makes sure that all the items are unique
-   * (two items with the same label or value are not allowed) and non-degenerate
-   * (items with "undefined" or "null" labels/values). This can, as well, be
-   * overridden via the "relaxed" flag.
-   *
-   * @param string aLabel
-   *        The label displayed in the container.
-   * @param string aValue
-   *        The actual internal value of the item.
-   * @param object aOptions [optional]
-   *        Additional options or flags supported by this operation:
-   *          - forced: true to force the item to be immediately appended
-   *          - unsorted: true if the items should not always remain sorted
-   *          - relaxed: true if this container should allow dupes & degenerates
-   *          - description: an optional description of the item
-   *          - tooltip: an optional tooltip for the item
-   *          - attachment: some attached primitive/object
-   * @return MenuItem
-   *         The item associated with the displayed element if a forced push,
-   *         undefined if the item was staged for a later commit.
-   */
-  push: function DVMC_push(aLabel, aValue, aOptions = {}) {
-    let item = new MenuItem(
-      aLabel, aValue, aOptions.description, aOptions.attachment);
-
-    // Batch the item to be added later.
-    if (!aOptions.forced) {
-      this._stagedItems.push({ item: item, options: aOptions });
-    }
-    // Immediately insert the item at the specified index.
-    else if (aOptions.forced && aOptions.forced.atIndex !== undefined) {
-      return this._insertItemAt(aOptions.forced.atIndex, item, aOptions);
-    }
-    // Find the target position in this container and insert the item there.
-    else if (!aOptions.unsorted) {
-      return this._insertItemAt(this._findExpectedIndex(aLabel), item, aOptions);
-    }
-    // Just append the item in this container.
-    else {
-      return this._appendItem(item, aOptions);
-    }
-  },
-
-  /**
-   * Flushes all the prepared items into this container.
-   *
-   * @param object aOptions [optional]
-   *        Additional options or flags supported by this operation:
-   *          - unsorted: true if the items should not be sorted beforehand
-   */
-  commit: function DVMC_commit(aOptions = {}) {
-    let stagedItems = this._stagedItems;
-
-    // By default, sort the items before adding them to this container.
-    if (!aOptions.unsorted) {
-      stagedItems.sort(function(a, b) a.item.label.toLowerCase() >
-                                      b.item.label.toLowerCase());
-    }
-    // Append the prepared items to this container.
-    for (let { item, options } of stagedItems) {
-      this._appendItem(item, options);
-    }
-    // Recreate the temporary items list for ulterior pushes.
-    this._stagedItems = [];
-  },
-
-  /**
-   * Updates this container to reflect the information provided by the
-   * currently selected item.
-   *
-   * @return boolean
-   *         True if a selected item was available, false otherwise.
-   */
-  refresh: function DVMC_refresh() {
-    let selectedValue = this.selectedValue;
-    if (!selectedValue) {
-      return false;
-    }
-
-    let entangledLabel = this.getItemByValue(selectedValue).label;
-
-    this._container.setAttribute("label", entangledLabel);
-    this._container.setAttribute("tooltiptext", selectedValue);
-    return true;
-  },
-
-  /**
-   * Immediately removes the specified item from this container.
-   *
-   * @param MenuItem aItem
-   *        The item associated with the element to remove.
-   */
-  remove: function DVMC__remove(aItem) {
-    this._container.removeChild(aItem.target);
-    this._untangleItem(aItem);
-  },
-
-  /**
-   * Removes all items from this container.
-   */
-  empty: function DVMC_empty() {
-    this._preferredValue = this.selectedValue;
-    this._container.selectedIndex = -1;
-    this._container.setAttribute("label", this._emptyLabel);
-    this._container.removeAttribute("tooltiptext");
-    this._container.removeAllItems();
-
-    for (let [, item] of this._itemsByElement) {
-      this._untangleItem(item);
-    }
-
-    this._itemsByLabel = new Map();
-    this._itemsByValue = new Map();
-    this._itemsByElement = new Map();
-    this._stagedItems = [];
-  },
-
-  /**
-   * Toggles all the items in this container hidden or visible.
-   *
-   * @param boolean aVisibleFlag
-   *        Specifies the intended visibility.
-   */
-  toggleContents: function DVMC_toggleContents(aVisibleFlag) {
-    for (let [, item] of this._itemsByElement) {
-      item.target.hidden = !aVisibleFlag;
-    }
-  },
-
-  /**
-   * Does not remove any item in this container. Instead, it overrides the
-   * current label to signal that it is unavailable and removes the tooltip.
-   */
-  setUnavailable: function DVMC_setUnavailable() {
-    this._container.setAttribute("label", this._unavailableLabel);
-    this._container.removeAttribute("tooltiptext");
-  },
-
-  /**
-   * Checks whether an item with the specified label is among the elements
-   * shown in this container.
-   *
-   * @param string aLabel
-   *        The item's label.
-   * @return boolean
-   *         True if the label is known, false otherwise.
-   */
-  containsLabel: function DVMC_containsLabel(aLabel) {
-    return this._itemsByLabel.has(aLabel) ||
-           this._stagedItems.some(function({item}) item.label == aLabel);
-  },
-
-  /**
-   * Checks whether an item with the specified value is among the elements
-   * shown in this container.
-   *
-   * @param string aValue
-   *        The item's value.
-   * @return boolean
-   *         True if the value is known, false otherwise.
-   */
-  containsValue: function DVMC_containsValue(aValue) {
-    return this._itemsByValue.has(aValue) ||
-           this._stagedItems.some(function({item}) item.value == aValue);
-  },
-
-  /**
-   * Checks whether an item with the specified trimmed value is among the
-   * elements shown in this container.
-   *
-   * @param string aValue
-   *        The item's value.
-   * @param function aTrim [optional]
-   *        A custom trimming function.
-   * @return boolean
-   *         True if the trimmed value is known, false otherwise.
-   */
-  containsTrimmedValue:
-  function DVMC_containsTrimmedValue(aValue,
-                                     aTrim = SourceUtils.trimUrlQuery) {
-    let trimmedValue = aTrim(aValue);
-
-    for (let [value] of this._itemsByValue) {
-      if (aTrim(value) == trimmedValue) {
-        return true;
-      }
-    }
-    return this._stagedItems.some(function({item}) aTrim(item.value) == trimmedValue);
-  },
-
-  /**
-   * Gets the preferred selected value to be displayed in this container.
-   * @return string
-   */
-  get preferredValue() this._preferredValue,
-
-  /**
-   * Retrieves the selected element's index in this container.
-   * @return number
-   */
-  get selectedIndex() this._container.selectedIndex,
-
-  /**
-   * Retrieves the item associated with the selected element.
-   * @return MenuItem
-   */
-  get selectedItem()
-    this._container.selectedItem ?
-    this._itemsByElement.get(this._container.selectedItem) : null,
-
-  /**
-   * Retrieves the label of the selected element.
-   * @return string
-   */
-  get selectedLabel()
-    this._container.selectedItem ?
-    this._itemsByElement.get(this._container.selectedItem).label : null,
-
-  /**
-   * Retrieves the value of the selected element.
-   * @return string
-   */
-  get selectedValue()
-    this._container.selectedItem ?
-    this._itemsByElement.get(this._container.selectedItem).value : null,
-
-  /**
-   * Selects the element at the specified index in this container.
-   * @param number aIndex
-   */
-  set selectedIndex(aIndex) this._container.selectedIndex = aIndex,
-
-  /**
-   * Selects the element with the entangled item in this container.
-   * @param MenuItem aItem
-   */
-  set selectedItem(aItem) this._container.selectedItem = aItem.target,
-
-  /**
-   * Selects the element with the specified label in this container.
-   * @param string aLabel
-   */
-  set selectedLabel(aLabel) {
-    let item = this._itemsByLabel.get(aLabel);
-    if (item) {
-      this._container.selectedItem = item.target;
-    }
-  },
-
-  /**
-   * Selects the element with the specified value in this container.
-   * @param string aValue
-   */
-  set selectedValue(aValue) {
-    let item = this._itemsByValue.get(aValue);
-    if (item) {
-      this._container.selectedItem = item.target;
-    }
-  },
-
-  /**
-   * Gets the item in the container having the specified index.
-   *
-   * @param number aIndex
-   *        The index used to identify the element.
-   * @return MenuItem
-   *         The matched item, or null if nothing is found.
-   */
-  getItemAtIndex: function DVMC_getItemAtIndex(aIndex) {
-    return this.getItemForElement(this._container.getItemAtIndex(aIndex));
-  },
-
-  /**
-   * Gets the item in the container having the specified label.
-   *
-   * @param string aLabel
-   *        The label used to identify the element.
-   * @return MenuItem
-   *         The matched item, or null if nothing is found.
-   */
-  getItemByLabel: function DVMC_getItemByLabel(aLabel) {
-    return this._itemsByLabel.get(aLabel);
-  },
-
-  /**
-   * Gets the item in the container having the specified value.
-   *
-   * @param string aValue
-   *        The value used to identify the element.
-   * @return MenuItem
-   *         The matched item, or null if nothing is found.
-   */
-  getItemByValue: function DVMC_getItemByValue(aValue) {
-    return this._itemsByValue.get(aValue);
-  },
-
-  /**
-   * Gets the item in the container associated with the specified element.
-   *
-   * @param nsIDOMNode aElement
-   *        The element used to identify the item.
-   * @return MenuItem
-   *         The matched item, or null if nothing is found.
-   */
-  getItemForElement: function DVMC_getItemForElement(aElement) {
-    while (aElement) {
-      let item = this._itemsByElement.get(aElement);
-      if (item) {
-        return item;
-      }
-      aElement = aElement.parentNode;
-    }
-    return null;
-  },
-
-  /**
-   * Returns the list of labels in this container.
-   * @return array
-   */
-  get labels() {
-    let labels = [];
-    for (let [label] of this._itemsByLabel) {
-      labels.push(label);
-    }
-    return labels;
-  },
-
-  /**
-   * Returns the list of values in this container.
-   * @return array
-   */
-  get values() {
-    let values = [];
-    for (let [value] of this._itemsByValue) {
-      values.push(value);
-    }
-    return values;
-  },
-
-  /**
-   * Gets the total number of items in this container.
-   * @return number
-   */
-  get totalItems() {
-    return this._itemsByElement.size;
-  },
-
-  /**
-   * Returns a list of all the visible (non-hidden) items in this container.
-   * @return array
-   */
-  get visibleItems() {
-    let items = [];
-    for (let [element, item] of this._itemsByElement) {
-      if (!element.hidden) {
-        items.push(item);
-      }
-    }
-    return items;
-  },
-
-  /**
-   * Specifies the required conditions for an item to be considered unique.
-   * Possible values:
-   *   - 1: label AND value are different from all other items
-   *   - 2: label OR value are different from all other items
-   *   - 3: only label is required to be different
-   *   - 4: only value is required to be different
-   */
-  uniquenessQualifier: 1,
-
-  /**
-   * Checks if an item is unique in this container.
-   *
-   * @param MenuItem aItem
-   *        An object containing a label and a value property.
-   * @return boolean
-   *         True if the element is unique, false otherwise.
-   */
-  isUnique: function DVMC_isUnique(aItem) {
-    switch (this.uniquenessQualifier) {
-      case 1:
-        return !this._itemsByLabel.has(aItem.label) &&
-               !this._itemsByValue.has(aItem.value);
-      case 2:
-        return !this._itemsByLabel.has(aItem.label) ||
-               !this._itemsByValue.has(aItem.value);
-      case 3:
-        return !this._itemsByLabel.has(aItem.label);
-      case 4:
-        return !this._itemsByValue.has(aItem.value);
-    }
-    return false;
-  },
-
-  /**
-   * Checks if an item's label and value are eligible for this container.
-   *
-   * @param MenuItem aItem
-   *        An object containing a label and a value property.
-   * @return boolean
-   *         True if the element is eligible, false otherwise.
-   */
-  isEligible: function DVMC_isEligible(aItem) {
-    return this.isUnique(aItem) &&
-           aItem.label != "undefined" && aItem.label != "null" &&
-           aItem.value != "undefined" && aItem.value != "null";
-  },
-
-  /**
-   * Finds the expected item index in this container based on its label.
-   *
-   * @param string aLabel
-   *        The label used to identify the element.
-   * @return number
-   *         The expected item index.
-   */
-  _findExpectedIndex: function DVMC__findExpectedIndex(aLabel) {
-    let container = this._container;
-    let itemCount = container.itemCount;
-
-    for (let i = 0; i < itemCount; i++) {
-      if (this.getItemForElement(container.getItemAtIndex(i)).label > aLabel) {
-        return i;
-      }
-    }
-    return itemCount;
-  },
-
-  /**
-   * Immediately appends an item in this container.
-   *
-   * @param MenuItem aItem
-   *        An object containing a label and a value property.
-   * @param object aOptions [optional]
-   *        Additional options or flags supported by this operation:
-   *          - relaxed: true if this container should allow dupes & degenerates
-   * @return MenuItem
-   *         The item associated with the displayed element, null if rejected.
-   */
-  _appendItem: function DVMC__appendItem(aItem, aOptions = {}) {
-    if (!aOptions.relaxed && !this.isEligible(aItem)) {
-      return null;
-    }
-
-    this._entangleItem(aItem, this._container.appendItem(
-      aItem.label, aItem.value, "", aOptions.attachment));
-
-    // Handle any additional options after entangling the item.
-    if (aOptions.tooltip) {
-      aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
-    }
-
-    return aItem;
-  },
-
-  /**
-   * Immediately inserts an item in this container at the specified index.
-   *
-   * @param number aIndex
-   *        The position in the container intended for this item.
-   * @param MenuItem aItem
-   *        An object containing a label and a value property.
-   * @param object aOptions [optional]
-   *        Additional options or flags supported by this operation:
-   *          - relaxed: true if this container should allow dupes & degenerates
-   * @return MenuItem
-   *         The item associated with the displayed element, null if rejected.
-   */
-  _insertItemAt: function DVMC__insertItemAt(aIndex, aItem, aOptions) {
-    if (!aOptions.relaxed && !this.isEligible(aItem)) {
-      return null;
-    }
-
-    this._entangleItem(aItem, this._container.insertItemAt(
-      aIndex, aItem.label, aItem.value, "", aOptions.attachment));
-
-    // Handle any additional options after entangling the item.
-    if (aOptions.tooltip) {
-      aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
-    }
-
-    return aItem;
-  },
-
-  /**
-   * Entangles an item (model) with a displayed node element (view).
-   *
-   * @param MenuItem aItem
-   *        The item describing the element.
-   * @param nsIDOMNode aElement
-   *        The element displaying the item.
-   * @return MenuItem
-   *         The same item.
-   */
-  _entangleItem: function DVMC__entangleItem(aItem, aElement) {
-    this._itemsByLabel.set(aItem.label, aItem);
-    this._itemsByValue.set(aItem.value, aItem);
-    this._itemsByElement.set(aElement, aItem);
-
-    aItem._target = aElement;
-    return aItem;
-  },
-
-  /**
-   * Untangles an item (model) from a displayed node element (view).
-   *
-   * @param MenuItem aItem
-   *        The item describing the element.
-   * @return MenuItem
-   *         The same item.
-   */
-  _untangleItem: function DVMC__untangleItem(aItem) {
-    if (aItem.finalize instanceof Function) {
-      aItem.finalize(aItem);
-    }
-
-    this._itemsByLabel.delete(aItem.label);
-    this._itemsByValue.delete(aItem.value);
-    this._itemsByElement.delete(aItem.target);
-
-    aItem._target = null;
-    return aItem;
-  },
-
-  /**
-   * A generator-iterator over all the items in this container.
-   */
-  __iterator__: function DVMC_iterator() {
-    for (let [, item] of this._itemsByElement) {
-      yield item;
-    }
-  },
-
-  _container: null,
-  _stagedItems: null,
-  _itemsByLabel: null,
-  _itemsByValue: null,
-  _itemsByElement: null,
-  _preferredValue: null,
-  _emptyLabel: "",
-  _unavailableLabel: ""
-};
-
-/**
- * A stacked list of items, compatible with MenuContainer instances, used for
- * displaying views like the StackFrames, Breakpoints etc.
+ * You should never need to access these methods directly, use the wrapper
+ * MenuContainer instances.
  *
  * Custom methods introduced by this view, not necessary for a MenuContainer:
- * set emptyText(aValue:string)
- * set permaText(aValue:string)
- * set itemType(aType:string)
- * set itemFactory(aCallback:function)
+ *   - set emptyText(aValue:string)
+ *   - set permaText(aValue:string)
+ *   - set itemType(aType:string)
+ *   - set itemFactory(aCallback:function)
  *
  * @param nsIDOMNode aAssociatedNode
  *        The element associated with the displayed container.
  */
-function StackList(aAssociatedNode) {
+function ListWidget(aAssociatedNode) {
   this._parent = aAssociatedNode;
 
   // Create an internal list container.
   this._list = document.createElement("vbox");
   this._parent.appendChild(this._list);
+
+  // Delegate some of the associated node's methods to satisfy the interface
+  // required by MenuContainer instances.
+  ViewHelpers.delegateWidgetAttributeMethods(this, aAssociatedNode);
+  ViewHelpers.delegateWidgetEventMethods(this, aAssociatedNode);
 }
 
-StackList.prototype = {
+ListWidget.prototype = {
   /**
-   * Immediately appends an item in this container.
+   * Overrides an item's element type (e.g. "vbox" or "hbox") in this container.
+   * @param string aType
+   */
+  itemType: "hbox",
+
+  /**
+   * Customization function for creating an item's UI in this container.
    *
+   * @param nsIDOMNode aElementNode
+   *        The element associated with the displayed item.
    * @param string aLabel
-   *        The label displayed in the container.
+   *        The item's label.
    * @param string aValue
-   *        The actual internal value of the item.
-   * @param string aDescription [optional]
-   *        An optional description of the item.
-   * @param any aAttachment [optional]
-   *        Some attached primitive/object.
-   * @return nsIDOMNode
-   *         The element associated with the displayed item.
+   *        The item's value.
    */
-  appendItem:
-  function DVSL_appendItem(aLabel, aValue, aDescription, aAttachment) {
-    return this.insertItemAt(
-      Number.MAX_VALUE, aLabel, aValue, aDescription, aAttachment);
-  },
+  itemFactory: null,
 
   /**
    * Immediately inserts an item in this container at the specified index.
    *
    * @param number aIndex
    *        The position in the container intended for this item.
    * @param string aLabel
    *        The label displayed in the container.
@@ -1222,19 +588,20 @@ StackList.prototype = {
    *         The element associated with the displayed item.
    */
   insertItemAt:
   function DVSL_insertItemAt(aIndex, aLabel, aValue, aDescription, aAttachment) {
     let list = this._list;
     let childNodes = list.childNodes;
 
     let element = document.createElement(this.itemType);
-    this._createItemView(element, aLabel, aValue, aAttachment);
+    this.itemFactory(element, aAttachment, aLabel, aValue, aDescription);
     this._removeEmptyNotice();
 
+    element.classList.add("list-widget-item");
     return list.insertBefore(element, childNodes[aIndex]);
   },
 
   /**
    * Returns the child node in this container situated at the specified index.
    *
    * @param number aIndex
    *        The position in the container intended for this item.
@@ -1249,152 +616,69 @@ StackList.prototype = {
    * Immediately removes the specified child node from this container.
    *
    * @param nsIDOMNode aChild
    *        The element associated with the displayed item.
    */
   removeChild: function DVSL__removeChild(aChild) {
     this._list.removeChild(aChild);
 
-    if (!this.itemCount) {
+    if (this._selectedItem == aChild) {
+      this._selectedItem = null;
+    }
+    if (!this._list.hasChildNodes()) {
       this._appendEmptyNotice();
     }
   },
 
   /**
    * Immediately removes all of the child nodes from this container.
    */
   removeAllItems: function DVSL_removeAllItems() {
     let parent = this._parent;
     let list = this._list;
     let firstChild;
 
-    while (firstChild = list.firstChild) {
+    while ((firstChild = list.firstChild)) {
       list.removeChild(firstChild);
     }
     parent.scrollTop = 0;
     parent.scrollLeft = 0;
 
     this._selectedItem = null;
-    this._selectedIndex = -1;
     this._appendEmptyNotice();
   },
 
   /**
-   * Gets the number of child nodes present in this container.
-   * @return number
-   */
-  get itemCount() this._list.childNodes.length,
-
-  /**
-   * Gets the index of the selected child node in this container.
-   * @return number
-   */
-  get selectedIndex() this._selectedIndex,
-
-  /**
-   * Sets the index of the selected child node in this container.
-   * Only one child node may be selected at a time.
-   * @param number aIndex
-   */
-  set selectedIndex(aIndex) this.selectedItem = this._list.childNodes[aIndex],
-
-  /**
    * Gets the currently selected child node in this container.
    * @return nsIDOMNode
    */
   get selectedItem() this._selectedItem,
 
   /**
    * Sets the currently selected child node in this container.
    * @param nsIDOMNode aChild
    */
   set selectedItem(aChild) {
     let childNodes = this._list.childNodes;
 
     if (!aChild) {
       this._selectedItem = null;
-      this._selectedIndex = -1;
     }
     for (let node of childNodes) {
       if (node == aChild) {
         node.classList.add("selected");
-        this._selectedIndex = Array.indexOf(childNodes, node);
         this._selectedItem = node;
       } else {
         node.classList.remove("selected");
       }
     }
   },
 
   /**
-   * Applies an attribute to this container.
-   *
-   * @param string aName
-   *        The name of the attribute to set.
-   * @return string
-   *         The attribute value.
-   */
-  getAttribute: function DVSL_setAttribute(aName) {
-    return this._parent.getAttribute(aName);
-  },
-
-  /**
-   * Applies an attribute to this container.
-   *
-   * @param string aName
-   *        The name of the attribute to set.
-   * @param any aValue
-   *        The supplied attribute value.
-   */
-  setAttribute: function DVSL_setAttribute(aName, aValue) {
-    this._parent.setAttribute(aName, aValue);
-  },
-
-  /**
-   * Removes an attribute applied to this container.
-   *
-   * @param string aName
-   *        The name of the attribute to remove.
-   */
-  removeAttribute: function DVSL_removeAttribute(aName) {
-    this._parent.removeAttribute(aName);
-  },
-
-  /**
-   * Adds an event listener to this container.
-   *
-   * @param string aName
-   *        The name of the listener to set.
-   * @param function aCallback
-   *        The function to be called when the event is triggered.
-   * @param boolean aBubbleFlag
-   *        True if the event should bubble.
-   */
-  addEventListener:
-  function DVSL_addEventListener(aName, aCallback, aBubbleFlag) {
-    this._parent.addEventListener(aName, aCallback, aBubbleFlag);
-  },
-
-  /**
-   * Removes an event listener added to this container.
-   *
-   * @param string aName
-   *        The name of the listener to remove.
-   * @param function aCallback
-   *        The function called when the event was triggered.
-   * @param boolean aBubbleFlag
-   *        True if the event was bubbling.
-   */
-  removeEventListener:
-  function DVSL_removeEventListener(aName, aCallback, aBubbleFlag) {
-    this._parent.removeEventListener(aName, aCallback, aBubbleFlag);
-  },
-
-  /**
    * Sets the text displayed permanently in this container's header.
    * @param string aValue
    */
   set permaText(aValue) {
     if (this._permaTextNode) {
       this._permaTextNode.setAttribute("value", aValue);
     }
     this._permaTextValue = aValue;
@@ -1409,80 +693,41 @@ StackList.prototype = {
     if (this._emptyTextNode) {
       this._emptyTextNode.setAttribute("value", aValue);
     }
     this._emptyTextValue = aValue;
     this._appendEmptyNotice();
   },
 
   /**
-   * Overrides the item's element type (e.g. "vbox" or "hbox").
-   * @param string aType
-   */
-  itemType: "hbox",
-
-  /**
-   * Overrides the customization function for creating an item's UI.
-   * @param function aCallback
-   */
-  set itemFactory(aCallback) this._createItemView = aCallback,
-
-  /**
-   * Customization function for creating an item's UI for this container.
-   *
-   * @param nsIDOMNode aElementNode
-   *        The element associated with the displayed item.
-   * @param string aLabel
-   *        The item's label.
-   * @param string aValue
-   *        The item's value.
-   */
-  _createItemView: function DVSL__createItemView(aElementNode, aLabel, aValue) {
-    let labelNode = document.createElement("label");
-    let valueNode = document.createElement("label");
-    let spacer = document.createElement("spacer");
-
-    labelNode.setAttribute("value", aLabel);
-    valueNode.setAttribute("value", aValue);
-    spacer.setAttribute("flex", "1");
-
-    aElementNode.appendChild(labelNode);
-    aElementNode.appendChild(spacer);
-    aElementNode.appendChild(valueNode);
-
-    aElementNode.labelNode = labelNode;
-    aElementNode.valueNode = valueNode;
-  },
-
-  /**
    * Creates and appends a label displayed permanently in this container's header.
    */
   _appendPermaNotice: function DVSL__appendPermaNotice() {
     if (this._permaTextNode || !this._permaTextValue) {
       return;
     }
 
     let label = document.createElement("label");
-    label.className = "empty list-item";
+    label.className = "empty list-widget-item";
     label.setAttribute("value", this._permaTextValue);
 
     this._parent.insertBefore(label, this._list);
     this._permaTextNode = label;
   },
 
   /**
    * Creates and appends a label signaling that this container is empty.
    */
   _appendEmptyNotice: function DVSL__appendEmptyNotice() {
     if (this._emptyTextNode || !this._emptyTextValue) {
       return;
     }
 
     let label = document.createElement("label");
-    label.className = "empty list-item";
+    label.className = "empty list-widget-item";
     label.setAttribute("value", this._emptyTextValue);
 
     this._parent.appendChild(label);
     this._emptyTextNode = label;
   },
 
   /**
    * Removes the label signaling that this container is empty.
@@ -1493,17 +738,16 @@ StackList.prototype = {
     }
 
     this._parent.removeChild(this._emptyTextNode);
     this._emptyTextNode = null;
   },
 
   _parent: null,
   _list: null,
-  _selectedIndex: -1,
   _selectedItem: null,
   _permaTextNode: null,
   _permaTextValue: "",
   _emptyTextNode: null,
   _emptyTextValue: ""
 };
 
 /**
--- a/browser/devtools/debugger/debugger.css
+++ b/browser/devtools/debugger/debugger.css
@@ -1,88 +1,25 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/**
- * Sources searching
- */
+/* Sources search view */
 
 #globalsearch {
   overflow-x: hidden;
   overflow-y: auto;
 }
 
-.dbg-results-container:not([open]) {
-  display: none;
-}
-
-/**
- * Stack frames
- */
-
-#stackframes {
-  overflow: auto;
-}
-
-/**
- * Breakpoints view
- */
-
-#breakpoints {
-  overflow-x: hidden;
-  overflow-y: auto;
-}
-
-.dbg-breakpoint > .state,
-.dbg-breakpoint > .content {
-  overflow: hidden;
-}
-
-/**
- * Watch expressions view
- */
+/* Watch expressions view */
 
 #expressions {
   overflow-x: hidden;
   overflow-y: auto;
 }
 
-/**
- * Variables view
- */
-
-#variables {
-  overflow-x: hidden;
-  overflow-y: auto;
-}
-
-/**
- * Scope, variable and property elements
- */
-
-.details:not([open]) {
-  display: none;
-}
-
-.scope,
-.variable,
-.property {
-  -moz-user-focus: normal;
-}
-
-.scope[non-header] > .title,
-.variable[non-header] > .title,
-.variable[non-match] > .title,
-.property[non-header] > .title,
-.property[non-match] > .title {
-  display: none;
-}
-
-/**
- * Toolbar
- */
+/* Toolbar */
 
 .devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
   display: none;
 }
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -1,25 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/debugger.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/debugger.css" type="text/css"?>
 <!DOCTYPE window [
-<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd">
+  <!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd">
   %debuggerDTD;
 ]>
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
   <script type="text/javascript" src="chrome://global/content/globalOverlay.js"/>
   <script type="text/javascript" src="debugger-controller.js"/>
   <script type="text/javascript" src="debugger-view.js"/>
   <script type="text/javascript" src="debugger-toolbar.js"/>
   <script type="text/javascript" src="debugger-panes.js"/>
 
   <commandset id="editMenuCommands"/>
   <commandset id="sourceEditorCommands"/>
@@ -41,19 +42,19 @@
              oncommand="DebuggerView.Filtering._doTokenSearch()"/>
     <command id="lineSearchCommand"
              oncommand="DebuggerView.Filtering._doLineSearch()"/>
     <command id="variableSearchCommand"
              oncommand="DebuggerView.Filtering._doVariableSearch()"/>
     <command id="variablesFocusCommand"
              oncommand="DebuggerView.Filtering._doVariablesFocus()"/>
     <command id="addBreakpointCommand"
-             oncommand="DebuggerView.Breakpoints._onCmdAddBreakpoint()"/>
+             oncommand="DebuggerView.Sources._onCmdAddBreakpoint()"/>
     <command id="addConditionalBreakpointCommand"
-             oncommand="DebuggerView.Breakpoints._onCmdAddConditionalBreakpoint()"/>
+             oncommand="DebuggerView.Sources._onCmdAddConditionalBreakpoint()"/>
     <command id="addWatchExpressionCommand"
              oncommand="DebuggerView.WatchExpressions._onCmdAddExpression()"/>
     <command id="removeAllWatchExpressionsCommand"
              oncommand="DebuggerView.WatchExpressions._onCmdRemoveAllExpressions()"/>
     <command id="togglePauseOnExceptions"
              oncommand="DebuggerView.Options._togglePauseOnExceptions()"/>
     <command id="toggleShowPanesOnStartup"
              oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/>
@@ -111,30 +112,28 @@
                 key="variableSearchKey"
                 command="variableSearchCommand"/>
       <menuitem id="se-dbg-cMenu-focusVariables"
                 label="&debuggerUI.focusVariables;"
                 accesskey="&debuggerUI.focusVariables.key;"
                 key="variablesFocusKey"
                 command="variablesFocusCommand"/>
     </menupopup>
-
     <menupopup id="debuggerWatchExpressionsContextMenu">
       <menuitem id="add-watch-expression"
                 label="&debuggerUI.addWatch;"
                 accesskey="&debuggerUI.addWatch.key;"
                 key="addWatchExpressionKey"
                 command="addWatchExpressionCommand"/>
       <menuitem id="removeAll-watch-expression"
                 label="&debuggerUI.removeAllWatch;"
                 accesskey="&debuggerUI.removeAllWatch.key;"
                 key="removeAllWatchExpressionsKey"
                 command="removeAllWatchExpressionsCommand"/>
     </menupopup>
-
     <menupopup id="debuggerPrefsContextMenu"
                position="before_end"
                onpopupshowing="DebuggerView.Options._onPopupShowing()"
                onpopuphiding="DebuggerView.Options._onPopupHiding()">
       <menuitem id="pause-on-exceptions"
                 type="checkbox"
                 label="&debuggerUI.pauseExceptions;"
                 accesskey="&debuggerUI.pauseExceptions.key;"
@@ -209,17 +208,17 @@
          command="addWatchExpressionCommand"/>
     <key id="removeAllWatchExpressionsKey"
          key="&debuggerUI.removeAllWatch.key;"
          modifiers="accel alt"
          command="removeAllWatchExpressionsCommand"/>
   </keyset>
 
   <vbox id="body" flex="1">
-    <toolbar id="dbg-toolbar" class="devtools-toolbar">
+    <toolbar class="devtools-toolbar">
       <hbox id="debugger-controls">
         <toolbarbutton id="resume"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-over"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-in"
@@ -227,88 +226,98 @@
                        tabindex="0"/>
         <toolbarbutton id="step-out"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
       </hbox>
       <menulist id="chrome-globals"
                 class="devtools-menulist"
                 sizetopopup="none" hidden="true"/>
-      <menulist id="sources"
-                class="devtools-menulist"
-                sizetopopup="none"/>
+      <vbox id="stackframes" flex="1"/>
       <textbox id="searchbox"
                class="devtools-searchinput" type="search"/>
-      <spacer flex="1"/>
-      <toolbarbutton id="toggle-panes"
+      <toolbarbutton id="instruments-pane-toggle"
                      class="devtools-toolbarbutton"
                      tooltiptext="&debuggerUI.panesButton.tooltip;"
                      tabindex="0"/>
       <toolbarbutton id="debugger-options"
                      class="devtools-option-toolbarbutton"
                      tooltiptext="&debuggerUI.optsButton.tooltip;"
-                     popup="debuggerPrefsContextMenu"/>
+                     popup="debuggerPrefsContextMenu"
+                     tabindex="0"/>
     </toolbar>
-
-    <panel id="searchbox-panel"
-           level="top"
-           type="arrow"
-           noautofocus="true"
-           position="before_start">
-      <vbox>
-        <label class="description" value="&debuggerUI.searchPanelTitle;"/>
-        <hbox align="center">
-          <button id="global-operator-button" class="operator"
-                  command="globalSearchCommand"/>
-          <label id="global-operator-label" class="plain operator"/>
-        </hbox>
-        <hbox align="center">
-          <button id="token-operator-button" class="operator"
-                  command="tokenSearchCommand"/>
-          <label id="token-operator-label" class="plain operator"/>
-        </hbox>
-        <hbox align="center">
-          <button id="line-operator-button" class="operator"
-                  command="lineSearchCommand"/>
-          <label id="line-operator-label" class="plain operator"/>
-        </hbox>
-        <hbox align="center">
-          <button id="variable-operator-button" class="operator"
-                  command="variableSearchCommand"/>
-          <label id="variable-operator-label" class="plain operator"/>
-        </hbox>
-      </vbox>
-    </panel>
-
-    <panel id="conditional-breakpoint-panel"
-           level="top"
-           type="arrow"
-           noautofocus="true"
-           position="after_start">
-      <vbox>
-        <label class="description" value="&debuggerUI.condBreakPanelTitle;"/>
-        <textbox id="conditional-breakpoint-textbox"/>
-      </vbox>
-    </panel>
-
-    <vbox id="dbg-content" flex="1">
-      <vbox id="globalsearch" hidden="true"/>
-      <splitter id="globalsearch-splitter"
-                class="devtools-horizontal-splitter" hidden="true"/>
+    <vbox flex="1">
+      <scrollbox id="globalsearch" orient="vertical" hidden="true"/>
+      <splitter class="devtools-horizontal-splitter" hidden="true"/>
       <hbox flex="1">
-        <vbox id="stackframes+breakpoints">
-          <vbox id="stackframes" flex="1"/>
-          <splitter class="devtools-horizontal-splitter"/>
-          <vbox id="breakpoints"/>
+        <vbox id="sources-pane">
+          <vbox id="sources" flex="1"/>
         </vbox>
         <splitter class="devtools-side-splitter"/>
         <vbox id="editor" flex="1"/>
         <splitter class="devtools-side-splitter"/>
-        <vbox id="variables+expressions">
+        <vbox id="instruments-pane">
           <vbox id="expressions"/>
           <splitter class="devtools-horizontal-splitter"/>
           <vbox id="variables" flex="1"/>
         </vbox>
       </hbox>
     </vbox>
+  </vbox>
 
-  </vbox>
+  <panel id="searchbox-help-panel"
+         level="top"
+         type="arrow"
+         noautofocus="true"
+         position="before_start">
+    <vbox>
+      <label id="searchbox-panel-description"
+             value="&debuggerUI.searchPanelTitle;"/>
+      <hbox align="center">
+        <button id="global-operator-button"
+                class="searchbox-panel-operator-button"
+                command="globalSearchCommand"/>
+        <label id="global-operator-label"
+               class="plain searchbox-panel-operator-label"/>
+      </hbox>
+      <hbox align="center">
+        <button id="token-operator-button"
+                class="searchbox-panel-operator-button"
+                command="tokenSearchCommand"/>
+        <label id="token-operator-label"
+               class="plain searchbox-panel-operator-label"/>
+      </hbox>
+      <hbox align="center">
+        <button id="line-operator-button"
+                class="searchbox-panel-operator-button"
+                command="lineSearchCommand"/>
+        <label id="line-operator-label"
+               class="plain searchbox-panel-operator-label"/>
+      </hbox>
+      <hbox align="center">
+        <button id="variable-operator-button"
+                class="searchbox-panel-operator-button"
+                 command="variableSearchCommand"/>
+        <label id="variable-operator-label"
+               class="plain searchbox-panel-operator-label"/>
+      </hbox>
+    </vbox>
+  </panel>
+
+  <panel id="filtered-sources-panel"
+         level="top"
+         noautofocus="true"
+         position="before_start">
+  </panel>
+
+  <panel id="conditional-breakpoint-panel"
+         hidden="true"
+         level="top"
+         type="arrow"
+         noautofocus="true">
+    <vbox>
+      <label id="conditional-breakpoint-panel-description"
+             value="&debuggerUI.condBreakPanelTitle;"/>
+      <textbox id="conditional-breakpoint-panel-textbox"/>
+    </vbox>
+  </panel>
+
 </window>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -7,25 +7,26 @@ topsrcdir       = @top_srcdir@
 srcdir          = @srcdir@
 VPATH           = @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_aaa_run_first_leaktest.js \
+	browser_dbg_clean-exit.js \
 	browser_dbg_createChrome.js \
+	$(browser_dbg_createRemote.js disabled for intermittent failures, bug 753225) \
 	$(browser_dbg_debugger-tab-switch.js disabled until issues 106, 40 are fixed) \
 	$(browser_dbg_debugger-tab-switch-window.js disabled until issues 106, 40 are fixed) \
 	browser_dbg_debuggerstatement.js \
 	browser_dbg_listtabs.js \
 	browser_dbg_tabactor-01.js \
 	browser_dbg_tabactor-02.js \
 	browser_dbg_globalactor-01.js \
-	testactors.js \
 	browser_dbg_nav-01.js \
 	browser_dbg_propertyview-01.js \
 	browser_dbg_propertyview-02.js \
 	browser_dbg_propertyview-03.js \
 	browser_dbg_propertyview-04.js \
 	browser_dbg_propertyview-05.js \
 	browser_dbg_propertyview-06.js \
 	browser_dbg_propertyview-07.js \
@@ -55,55 +56,54 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_stack-01.js \
 	browser_dbg_stack-02.js \
 	browser_dbg_stack-03.js \
 	browser_dbg_stack-04.js \
 	browser_dbg_stack-05.js \
 	browser_dbg_location-changes.js \
 	browser_dbg_location-changes-new.js \
 	browser_dbg_location-changes-blank.js \
-	browser_dbg_script-switching.js \
+	browser_dbg_scripts-switching.js \
 	browser_dbg_scripts-sorting.js \
 	browser_dbg_scripts-searching-01.js \
 	browser_dbg_scripts-searching-02.js \
 	browser_dbg_scripts-searching-03.js \
 	browser_dbg_scripts-searching-04.js \
 	browser_dbg_scripts-searching-05.js \
 	browser_dbg_scripts-searching-06.js \
 	browser_dbg_scripts-searching-07.js \
 	browser_dbg_scripts-searching-08.js \
 	browser_dbg_scripts-searching-files_ui.js \
 	browser_dbg_scripts-searching-popup.js \
 	browser_dbg_pause-resume.js \
 	browser_dbg_pause-warning.js \
 	browser_dbg_update-editor-mode.js \
-	$(filter temporarily-disabled-due-to-oranges--bug-726609, browser_dbg_select-line.js) \
-	browser_dbg_clean-exit.js \
+	browser_dbg_select-line.js \
+	browser_dbg_breakpoint-new-script.js \
 	browser_dbg_bug723069_editor-breakpoints.js \
 	browser_dbg_bug723071_editor-breakpoints-pane.js \
 	browser_dbg_bug740825_conditional-breakpoints-01.js \
 	browser_dbg_bug740825_conditional-breakpoints-02.js \
 	browser_dbg_bug727429_watch-expressions-01.js \
 	browser_dbg_bug727429_watch-expressions-02.js \
 	browser_dbg_bug731394_editor-contextmenu.js \
+	browser_dbg_bug737803_editor_actual_location.js \
 	browser_dbg_bug786070_hide_nonenums.js \
 	browser_dbg_displayName.js \
-	browser_dbg_iframes.js \
 	browser_dbg_pause-exceptions.js \
 	browser_dbg_multiple-windows.js \
+	browser_dbg_iframes.js \
 	browser_dbg_bfcache.js \
-	browser_dbg_breakpoint-new-script.js \
-	browser_dbg_bug737803_editor_actual_location.js \
 	browser_dbg_progress-listener-bug.js \
 	browser_dbg_chrome-debugging.js \
-	$(filter disabled-for-intermittent-failures--bug-753225, browser_dbg_createRemote.js) \
 	head.js \
 	$(NULL)
 
 MOCHITEST_BROWSER_PAGES = \
+	testactors.js \
 	browser_dbg_tab1.html \
 	browser_dbg_tab2.html \
 	browser_dbg_debuggerstatement.html \
 	browser_dbg_stack.html \
 	browser_dbg_script-switching.html \
 	test-script-switching-01.js \
 	test-script-switching-02.js \
 	browser_dbg_big-data.html \
--- a/browser/devtools/debugger/test/browser_dbg_bfcache.js
+++ b/browser/devtools/debugger/test/browser_dbg_bfcache.js
@@ -7,17 +7,17 @@
  * back and forward in the tab.
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
-var gScripts = null;
+var gSources = null;
 
 function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
@@ -114,38 +114,37 @@ function testForward()
     });
   });
 
   info("Going forward.");
   content.history.forward();
 }
 
 function validateFirstPage() {
-  gScripts = gDebugger.DebuggerView.Sources._container;
-
-  is(gScripts.itemCount, 2, "Found the expected number of scripts.");
+  gSources = gDebugger.DebuggerView.Sources;
 
-  let label1 = "test-script-switching-01.js";
-  let label2 = "test-script-switching-02.js";
+  is(gSources.itemCount, 2,
+    "Found the expected number of scripts.");
 
-  ok(gDebugger.DebuggerView.Sources.containsLabel(label1),
+  ok(gDebugger.DebuggerView.Sources.containsLabel("test-script-switching-01.js"),
      "Found the first script label.");
-  ok(gDebugger.DebuggerView.Sources.containsLabel(label2),
+  ok(gDebugger.DebuggerView.Sources.containsLabel("test-script-switching-02.js"),
      "Found the second script label.");
 }
 
 function validateSecondPage() {
-  gScripts = gDebugger.DebuggerView.Sources._container;
+  gSources = gDebugger.DebuggerView.Sources;
 
-  is(gScripts.itemCount, 1, "Found the expected number of scripts.");
+  is(gSources.itemCount, 1,
+    "Found the expected number of scripts.");
 
   ok(gDebugger.DebuggerView.Sources.containsLabel("browser_dbg_stack.html"),
      "Found the single script label.");
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebuggee = null;
   gDebugger = null;
-  gScripts = null;
+  gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.html
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.html
@@ -1,11 +1,12 @@
 <!DOCTYPE html>
 <html>
 <head>
+<meta charset='utf-8'/>
 <script type="text/javascript">
 function runDebuggerStatement() {
   debugger;
 }
 function myFunction() {
   var a = 1;
   debugger;
 }
--- a/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.js
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoint-new-script.js
@@ -21,72 +21,68 @@ function test()
     gDebuggee = aDebuggee;
 
     testAddBreakpoint();
   });
 }
 
 function testAddBreakpoint()
 {
-  gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
-    gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
-    executeSoon(function() {
+  gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
+    Services.tm.currentThread.dispatch({ run: function() {
+
       var frames = gDebugger.DebuggerView.StackFrames._container._list;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
          "The debugger statement was reached.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 1,
          "Should have one frame.");
 
-      let location = { url: TAB_URL, line: 9 };
-      gPane.addBreakpoint(location, function (aResponse, bpClient) {
+      gPane.addBreakpoint({ url: TAB_URL, line: 9 }, function (aResponse, bpClient) {
         testResume();
       });
-    });
-  }, false);
+    }}, 0);
+  });
 
   gDebuggee.runDebuggerStatement();
 }
 
 function testResume()
 {
+  is(gDebugger.DebuggerController.activeThread.state, "paused",
+    "The breakpoint wasn't hit yet.");
+
   let thread = gDebugger.DebuggerController.activeThread;
   thread.addOneTimeListener("resumed", function() {
     thread.addOneTimeListener("paused", function() {
       executeSoon(testBreakpointHit);
     });
 
     EventUtils.sendMouseEvent({ type: "click" },
       content.document.querySelector("button"));
-
   });
 
   thread.resume();
 }
 
 function testBreakpointHit()
 {
   is(gDebugger.DebuggerController.activeThread.state, "paused",
     "The breakpoint was hit.");
 
-  resumeAndFinish();
-}
-
-function resumeAndFinish() {
   let thread = gDebugger.DebuggerController.activeThread;
   thread.addOneTimeListener("paused", function test(aEvent, aPacket) {
     thread.addOneTimeListener("resumed", function() {
       executeSoon(closeDebuggerAndFinish);
     });
 
     is(aPacket.why.type, "debuggerStatement", "Execution has advanced to the next line.");
     isnot(aPacket.why.type, "breakpoint", "No ghost breakpoint was hit.");
     thread.resume();
-
   });
 
   thread.resume();
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js
@@ -7,51 +7,44 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
+let gEditor = null;
 let gSources = null;
-let gEditor = null;
 let gBreakpoints = null;
 
 function test()
 {
-  let tempScope = {};
-  Cu.import("resource:///modules/source-editor.jsm", tempScope);
-  let SourceEditor = tempScope.SourceEditor;
-
   let scriptShown = false;
   let framesAdded = false;
   let testStarted = false;
 
   gTab = addTab(TAB_URL, function onAddTab() {
     info("tab added");
     gDebuggee = gTab.linkedBrowser.contentWindow.wrappedJSObject;
 
     let target = TargetFactory.forTab(gTab);
 
     gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
       info("jsdebugger panel opened");
       gPane = toolbox.getCurrentPanel();
       gDebugger = gPane.panelWin;
-      gDebugger.addEventListener("Debugger:AfterSourcesAdded",
-                                 onAfterSourcesAdded);
+      gDebugger.addEventListener("Debugger:AfterSourcesAdded", onAfterSourcesAdded);
     });
   });
 
   function onAfterSourcesAdded()
   {
     info("scripts added");
-    gDebugger.removeEventListener("Debugger:AfterSourcesAdded",
-                                  onAfterSourcesAdded);
-
+    gDebugger.removeEventListener("Debugger:AfterSourcesAdded",onAfterSourcesAdded);
     gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded",
       function onFramesAdded() {
         info("frames added");
         framesAdded = true;
         executeSoon(startTest);
       });
@@ -76,84 +69,80 @@ function test()
       info("test started");
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest()
   {
     gSources = gDebugger.DebuggerView.Sources;
+    gEditor = gDebugger.editor;
+    gBreakpoints = gPane.getAllBreakpoints();
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
-    is(gSources._container.itemCount, 2, "Found the expected number of scripts.");
-
-    gEditor = gDebugger.editor;
+    is(gSources.itemCount, 2,
+      "Found the expected number of scripts.");
 
     isnot(gEditor.getText().indexOf("debugger"), -1,
-          "The correct script was loaded initially.");
+      "The correct script was loaded initially.");
+
     isnot(gSources.selectedValue, gSources.values[0],
-          "the correct script is selected");
+      "The correct script is selected");
 
-    gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
-
     is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
-    gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                             onEditorBreakpointAddFirst);
-    let location = {url: gSources.selectedValue, line: 6};
+    gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
     executeSoon(function() {
-      gPane.addBreakpoint(location, onBreakpointAddFirst);
+      gPane.addBreakpoint({url: gSources.selectedValue, line: 6}, onBreakpointAddFirst);
     });
   }
 
   let breakpointsAdded = 0;
   let breakpointsRemoved = 0;
   let editorBreakpointChanges = 0;
 
   function onEditorBreakpointAddFirst(aEvent)
   {
-    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                onEditorBreakpointAddFirst);
+    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
     editorBreakpointChanges++;
 
     ok(aEvent, "breakpoint1 added to the editor");
     is(aEvent.added.length, 1, "one breakpoint added to the editor");
     is(aEvent.removed.length, 0, "no breakpoint was removed from the editor");
     is(aEvent.added[0].line, 5, "editor breakpoint line is correct");
 
     is(gEditor.getBreakpoints().length, 1,
-       "editor.getBreakpoints().length is correct");
+      "editor.getBreakpoints().length is correct");
   }
 
   function onBreakpointAddFirst(aBreakpointClient, aResponseError)
   {
     breakpointsAdded++;
 
     ok(aBreakpointClient, "breakpoint1 added, client received");
     ok(!aResponseError, "breakpoint1 added without errors");
     is(aBreakpointClient.location.url, gSources.selectedValue,
        "breakpoint1 client url is correct");
     is(aBreakpointClient.location.line, 6,
        "breakpoint1 client line is correct");
 
     executeSoon(function() {
       ok(aBreakpointClient.actor in gBreakpoints,
-         "breakpoint1 client found in the list of debugger breakpoints");
+        "breakpoint1 client found in the list of debugger breakpoints");
       is(Object.keys(gBreakpoints).length, 1,
-         "the list of debugger breakpoints holds only one breakpoint");
+        "the list of debugger breakpoints holds only one breakpoint");
       is(gPane.getBreakpoint(gSources.selectedValue, 6), aBreakpointClient,
-         "getBreakpoint returns the correct breakpoint");
+        "getBreakpoint returns the correct breakpoint");
 
       info("remove the first breakpoint");
-      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                               onEditorBreakpointRemoveFirst);
+      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
       gPane.removeBreakpoint(aBreakpointClient, onBreakpointRemoveFirst);
     });
   }
 
   function onBreakpointRemoveFirst(aLocation)
   {
     breakpointsRemoved++;
 
@@ -161,120 +150,111 @@ function test()
     is(aLocation.url, gSources.selectedValue, "breakpoint1 remove: url is correct");
     is(aLocation.line, 6, "breakpoint1 remove: line is correct");
 
     executeSoon(testBreakpointAddBackground);
   }
 
   function onEditorBreakpointRemoveFirst(aEvent)
   {
-    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                onEditorBreakpointRemoveFirst);
+    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
     editorBreakpointChanges++;
 
     ok(aEvent, "breakpoint1 removed from the editor");
     is(aEvent.added.length, 0, "no breakpoint was added to the editor");
     is(aEvent.removed.length, 1, "one breakpoint was removed from the editor");
     is(aEvent.removed[0].line, 5, "editor breakpoint line is correct");
 
-    is(gEditor.getBreakpoints().length, 0, "editor.getBreakpoints().length is correct");
+    is(gEditor.getBreakpoints().length, 0,
+      "editor.getBreakpoints().length is correct");
   }
 
   function testBreakpointAddBackground()
   {
     info("add a breakpoint to the second script which is not selected");
 
     is(Object.keys(gBreakpoints).length, 0, "no breakpoints in the debugger");
     ok(!gPane.getBreakpoint(gSources.selectedValue, 6),
-       "getBreakpoint(selectedScript, 6) returns no breakpoint");
+      "getBreakpoint(selectedScript, 6) returns no breakpoint");
+    isnot(gSources.values[0], gSources.selectedValue,
+      "first script location is not the currently selected script");
 
-    let script0 = gSources.values[0];
-    isnot(script0, gSources.selectedValue,
-          "first script location is not the currently selected script");
-
-    let location = {url: script0, line: 5};
-    gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                             onEditorBreakpointAddBackgroundTrap);
-    gPane.addBreakpoint(location, onBreakpointAddBackground);
+    gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
+    gPane.addBreakpoint({url: gSources.values[0], line: 5}, onBreakpointAddBackground);
   }
 
   function onEditorBreakpointAddBackgroundTrap(aEvent)
   {
-    // trap listener: no breakpoint must be added to the editor when a breakpoint
-    // is added to a script that is not currently selected.
-    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                onEditorBreakpointAddBackgroundTrap);
+    // Trap listener: no breakpoint must be added to the editor when a
+    // breakpoint is added to a script that is not currently selected.
+    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
     editorBreakpointChanges++;
     ok(false, "breakpoint2 must not be added to the editor");
   }
 
   function onBreakpointAddBackground(aBreakpointClient, aResponseError)
   {
     breakpointsAdded++;
 
     ok(aBreakpointClient, "breakpoint2 added, client received");
     ok(!aResponseError, "breakpoint2 added without errors");
     is(aBreakpointClient.location.url, gSources.values[0],
-       "breakpoint2 client url is correct");
+      "breakpoint2 client url is correct");
     is(aBreakpointClient.location.line, 5,
-       "breakpoint2 client line is correct");
+      "breakpoint2 client line is correct");
 
     executeSoon(function() {
       ok(aBreakpointClient.actor in gBreakpoints,
-         "breakpoint2 client found in the list of debugger breakpoints");
+        "breakpoint2 client found in the list of debugger breakpoints");
       is(Object.keys(gBreakpoints).length, 1, "one breakpoint in the debugger");
       is(gPane.getBreakpoint(gSources.values[0], 5), aBreakpointClient,
-         "getBreakpoint(locations[0], 5) returns the correct breakpoint");
+        "getBreakpoint(locations[0], 5) returns the correct breakpoint");
 
       // remove the trap listener
-      gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                  onEditorBreakpointAddBackgroundTrap);
-
-      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                               onEditorBreakpointAddSwitch);
-      gEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                               onEditorTextChanged);
+      gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
 
       info("switch to the second script");
-
-      gSources._container.selectedIndex = 0;
+      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
+      gEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
+      gSources.selectedIndex = 0;
     });
   }
 
   function onEditorBreakpointAddSwitch(aEvent)
   {
-    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                onEditorBreakpointAddSwitch);
+    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
     editorBreakpointChanges++;
 
     ok(aEvent, "breakpoint2 added to the editor");
     is(aEvent.added.length, 1, "one breakpoint added to the editor");
     is(aEvent.removed.length, 0, "no breakpoint was removed from the editor");
     is(aEvent.added[0].line, 4, "editor breakpoint line is correct");
 
     is(gEditor.getBreakpoints().length, 1,
        "editor.getBreakpoints().length is correct");
   }
 
   function onEditorTextChanged()
   {
-    gEditor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                onEditorTextChanged);
+    // Wait for the actual text to be shown.
+    if (gDebugger.editor.getText() == gDebugger.L10N.getStr("loadingText")) {
+      return;
+    }
+    // The requested source text has been shown, remove the event listener.
+    gEditor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
 
     is(gEditor.getText().indexOf("debugger"), -1,
-       "The second script is no longer displayed.");
+      "The second script is no longer displayed.");
 
     isnot(gEditor.getText().indexOf("firstCall"), -1,
-          "The first script is displayed.");
+      "The first script is displayed.");
 
     executeSoon(function() {
       info("remove the second breakpoint using the mouse");
-
-      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                               onEditorBreakpointRemoveSecond);
+      gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
 
       let iframe = gEditor.editorElement;
       let testWin = iframe.ownerDocument.defaultView;
 
       // flush the layout for the iframe
       info("rect " + iframe.contentDocument.documentElement.getBoundingClientRect());
 
       let utils = testWin.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -286,48 +266,48 @@ function test()
       utils.sendMouseEventToWindow("mousedown", left, top, 0, 1, 0, false, 0, 0);
       utils.sendMouseEventToWindow("mouseup", left, top, 0, 1, 0, false, 0, 0);
     });
 
   }
 
   function onEditorBreakpointRemoveSecond(aEvent)
   {
-    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
-                                onEditorBreakpointRemoveSecond);
+    gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
     editorBreakpointChanges++;
 
     ok(aEvent, "breakpoint2 removed from the editor");
     is(aEvent.added.length, 0, "no breakpoint was added to the editor");
     is(aEvent.removed.length, 1, "one breakpoint was removed from the editor");
     is(aEvent.removed[0].line, 4, "editor breakpoint line is correct");
 
-    is(gEditor.getBreakpoints().length, 0, "editor.getBreakpoints().length is correct");
+    is(gEditor.getBreakpoints().length, 0,
+      "editor.getBreakpoints().length is correct");
 
     executeSoon(function() {
       gDebugger.gClient.addOneTimeListener("resumed", function() {
         finalCheck();
         closeDebuggerAndFinish();
       });
       gDebugger.DebuggerController.activeThread.resume();
     });
   }
 
   function finalCheck() {
     is(Object.keys(gBreakpoints).length, 0, "no breakpoint in the debugger");
     ok(!gPane.getBreakpoint(gSources.values[0], 5),
-       "getBreakpoint(locations[0], 5) returns no breakpoint");
+      "getBreakpoint(locations[0], 5) returns no breakpoint");
   }
 
   registerCleanupFunction(function() {
     removeTab(gTab);
     is(breakpointsAdded, 2, "correct number of breakpoints have been added");
     is(breakpointsRemoved, 1, "correct number of breakpoints have been removed");
     is(editorBreakpointChanges, 4, "correct number of editor breakpoint changes");
     gPane = null;
     gTab = null;
     gDebuggee = null;
     gDebugger = null;
+    gEditor = null;
     gSources = null;
-    gEditor = null;
     gBreakpoints = null;
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_bug723071_editor-breakpoints-pane.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug723071_editor-breakpoints-pane.js
@@ -7,19 +7,19 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
-let gScripts = null;
+let gEditor = null;
+let gSources = null;
 let gBreakpoints = null;
-let gBreakpointsContainer = null;
 let gBreakpointsParent = null;
 let gBreakpointsList = null;
 
 function test()
 {
   let scriptShown = false;
   let framesAdded = false;
   let resumed = false;
@@ -60,95 +60,104 @@ function test()
   }
 
   let breakpointsAdded = 0;
   let breakpointsDisabled = 0;
   let breakpointsRemoved = 0;
 
   function performTest()
   {
-    gScripts = gDebugger.DebuggerView.Sources;
+    gEditor = gDebugger.editor;
+    gSources = gDebugger.DebuggerView.Sources;
+    gBreakpoints = gPane.getAllBreakpoints();
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
-    is(gScripts._container.itemCount, 2, "Found the expected number of scripts.");
-
-    let editor = gDebugger.editor;
+    is(gSources.itemCount, 2,
+      "Found the expected number of scripts.");
 
-    isnot(editor.getText().indexOf("debugger"), -1,
-          "The correct script was loaded initially.");
-    isnot(gScripts.selectedValue, gScripts.values[0],
-          "the correct script is selected");
+    isnot(gEditor.getText().indexOf("debugger"), -1,
+      "The correct script was loaded initially.");
 
-    gBreakpoints = gPane.getAllBreakpoints();
-    is(Object.keys(gBreakpoints), 0, "no breakpoints");
+    isnot(gSources.selectedValue, gSources.values[0],
+      "The correct script is selected");
+
+    is(Object.keys(gBreakpoints).length, 0, "no breakpoints");
     ok(!gPane.getBreakpoint("chocolate", 3), "getBreakpoint('chocolate', 3) returns falsey");
+    is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
-    is(editor.getBreakpoints().length, 0, "no breakpoints in the editor");
+    gBreakpointsParent = gSources._container._parent;
+    gBreakpointsList = gSources._container._list;
 
-    gBreakpointsContainer = gDebugger.DebuggerView.Breakpoints;
-    gBreakpointsParent = gBreakpointsContainer._container._parent;
-    gBreakpointsList = gBreakpointsContainer._container._list;
-
-    is(gBreakpointsParent.querySelectorAll(".list-item.empty").length, 1,
-      "The breakpoints pane should be empty, but showing a " +
-      "'no breakpoints' information message.");
-    is(gBreakpointsList.childNodes.length, 0,
-       "Found junk in the breakpoints container.");
+    is(gBreakpointsParent.childNodes.length, 1, // one sources list
+      "Found junk in the breakpoints container.");
+    is(gBreakpointsList.childNodes.length, 1, // one sources group
+      "Found junk in the breakpoints container.");
+    is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
+      "No breakpoints should be visible at this point.");
 
     addBreakpoints(function() {
       is(breakpointsAdded, 3,
         "Should have added 3 breakpoints so far.");
       is(breakpointsDisabled, 0,
         "Shouldn't have disabled anything so far.");
       is(breakpointsRemoved, 0,
         "Shouldn't have removed anything so far.");
 
-      is(gBreakpointsList.childNodes.length,
-         gBreakpointsParent.querySelectorAll(".dbg-breakpoint").length,
-         "Found junk in the breakpoints container.");
+      is(gBreakpointsParent.childNodes.length, 1, // one sources list
+        "Found junk in the breakpoints container.");
+      is(gBreakpointsList.childNodes.length, 1, // one sources group
+        "Found junk in the breakpoints container.");
+      is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 3,
+        "3 breakpoints should be visible at this point.");
 
       disableBreakpoints(function() {
         is(breakpointsAdded, 3,
           "Should still have 3 breakpoints added so far.");
         is(breakpointsDisabled, 3,
           "Should have 3 disabled breakpoints.");
         is(breakpointsRemoved, 0,
           "Shouldn't have removed anything so far.");
 
-        is(gBreakpointsList.childNodes.length, breakpointsAdded,
+        is(gBreakpointsParent.childNodes.length, 1, // one sources list
+          "Found junk in the breakpoints container.");
+        is(gBreakpointsList.childNodes.length, 1, // one sources group
+          "Found junk in the breakpoints container.");
+        is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
           "Should have the same number of breakpoints in the pane.");
-        is(gBreakpointsList.childNodes.length, breakpointsDisabled,
+        is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsDisabled,
           "Should have the same number of disabled breakpoints.");
 
         addBreakpoints(function() {
           is(breakpointsAdded, 3,
             "Should still have only 3 breakpoints added so far.");
           is(breakpointsDisabled, 3,
             "Should still have 3 disabled breakpoints.");
           is(breakpointsRemoved, 0,
             "Shouldn't have removed anything so far.");
 
-          is(gBreakpointsList.childNodes.length, breakpointsAdded,
+          is(gBreakpointsParent.childNodes.length, 1, // one sources list
+            "Found junk in the breakpoints container.");
+          is(gBreakpointsList.childNodes.length, 1, // one sources group
+            "Found junk in the breakpoints container.");
+          is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
             "Since half of the breakpoints already existed, but disabled, " +
             "only half of the added breakpoints are actually in the pane.");
-          is(gBreakpointsList.childNodes.length,
-             gBreakpointsParent.querySelectorAll(".dbg-breakpoint").length,
-             "Found junk in the breakpoints container.");
 
           removeBreakpoints(function() {
             is(breakpointsRemoved, 3,
               "Should have 3 removed breakpoints.");
 
-            is(gBreakpointsParent.querySelectorAll(".list-item.empty").length, 1,
-              "The breakpoints pane should be empty, but showing a " +
-              "'no breakpoints' information message.");
-            is(gBreakpointsList.childNodes.length, 0,
+            is(gBreakpointsParent.childNodes.length, 1, // one sources list
                "Found junk in the breakpoints container.");
+            is(gBreakpointsList.childNodes.length, 1, // one sources group
+               "Found junk in the breakpoints container.");
+            is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
+               "No breakpoints should be visible at this point.");
 
             executeSoon(function() {
               gDebugger.gClient.addOneTimeListener("resumed", function() {
                 finalCheck();
                 closeDebuggerAndFinish();
               });
               gDebugger.DebuggerController.activeThread.resume();
             });
@@ -159,77 +168,82 @@ function test()
 
     function addBreakpoints(callback, increment)
     {
       let line;
 
       executeSoon(function()
       {
         line = 6;
-        gPane.addBreakpoint({url: gScripts.selectedValue, line: line},
+        gPane.addBreakpoint({url: gSources.selectedValue, line: line},
           function(cl, err) {
           onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
 
           line = 7;
-          gPane.addBreakpoint({url: gScripts.selectedValue, line: line},
+          gPane.addBreakpoint({url: gSources.selectedValue, line: line},
             function(cl, err) {
             onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
 
             line = 9;
-            gPane.addBreakpoint({url: gScripts.selectedValue, line: line},
+            gPane.addBreakpoint({url: gSources.selectedValue, line: line},
               function(cl, err) {
               onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
 
               executeSoon(function() {
                 callback();
               });
             });
           });
         });
       });
     }
 
     function disableBreakpoints(callback)
     {
-      let nodes = Array.slice(gBreakpointsList.childNodes);
+      let nodes = Array.slice(gBreakpointsList.querySelectorAll(".dbg-breakpoint"));
       info("Nodes to disable: " + breakpointsAdded);
+
       is(nodes.length, breakpointsAdded,
         "The number of nodes to disable is incorrect.");
 
       Array.forEach(nodes, function(bkp) {
         info("Disabling breakpoint: " + bkp.id);
 
-        let item = gBreakpointsContainer.getItemForElement(bkp);
-        let { sourceLocation: url, lineNumber: line } = item.attachment;
+        let sourceItem = gSources.getItemForElement(bkp);
+        let breakpointItem = gSources.getItemForElement.call(sourceItem, bkp);
+        let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+        info("Found data: " + breakpointItem.attachment.toSource());
 
-        gDebugger.DebuggerView.Breakpoints.disableBreakpoint(url, line, { callback: function() {
+        gSources.disableBreakpoint(url, line, { callback: function() {
           if (++breakpointsDisabled !== breakpointsAdded) {
             return;
           }
           executeSoon(function() {
             callback();
           });
         }});
       });
     }
 
     function removeBreakpoints(callback)
     {
-      let nodes = Array.slice(gBreakpointsList.childNodes);
+      let nodes = Array.slice(gBreakpointsList.querySelectorAll(".dbg-breakpoint"));
       info("Nodes to remove: " + breakpointsAdded);
+
       is(nodes.length, breakpointsAdded,
         "The number of nodes to remove is incorrect.");
 
       Array.forEach(nodes, function(bkp) {
         info("Removing breakpoint: " + bkp.id);
 
-        let item = gBreakpointsContainer.getItemForElement(bkp);
-        let { sourceLocation: url, lineNumber: line } = item.attachment;
+        let sourceItem = gSources.getItemForElement(bkp);
+        let breakpointItem = gSources.getItemForElement.call(sourceItem, bkp);
+        let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
+        info("Found data: " + breakpointItem.attachment.toSource());
 
-        gDebugger.DebuggerView.Breakpoints.removeBreakpoint(url, line);
         gPane.removeBreakpoint(gPane.getBreakpoint(url, line), function() {
           if (++breakpointsRemoved !== breakpointsAdded) {
             return;
           }
           executeSoon(function() {
             callback();
           });
         });
@@ -237,61 +251,51 @@ function test()
     }
 
     function onBreakpointAdd(aBreakpointClient, aResponseError)
     {
       if (this.increment) {
         breakpointsAdded++;
       }
 
-      is(gBreakpointsList.childNodes.length, breakpointsAdded, this.increment
-        ? "Should have added a breakpoint in the pane."
-        : "Should have the same number of breakpoints in the pane.");
+      is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
+        this.increment ? "Should have added a breakpoint in the pane."
+                       : "Should have the same number of breakpoints in the pane.");
 
       let id = "breakpoint-" + aBreakpointClient.actor;
       let bkp = gDebugger.document.getElementById(id);
-      let info = bkp.getElementsByClassName("dbg-breakpoint-info")[0];
+      let line = bkp.getElementsByClassName("dbg-breakpoint-line")[0];
       let text = bkp.getElementsByClassName("dbg-breakpoint-text")[0];
       let check = bkp.querySelector("checkbox");
 
       is(bkp.id, id,
         "Breakpoint element " + id + " found successfully.");
-      is(info.getAttribute("value"), getExpectedBreakpointInfo(this.line),
+      is(line.getAttribute("value"), this.line,
         "The expected information wasn't found in the breakpoint element.");
-      is(text.getAttribute("value"), getExpectedLineText(this.line).trim(),
+      is(text.getAttribute("value"), gDebugger.DebuggerView.getEditorLine(this.line - 1).trim(),
         "The expected line text wasn't found in the breakpoint element.");
       is(check.getAttribute("checked"), "true",
         "The breakpoint enable checkbox is checked as expected.");
     }
-
-    function getExpectedBreakpointInfo(line) {
-      let url = gDebugger.DebuggerView.Sources.selectedValue;
-      let label = gDebugger.SourceUtils.getSourceLabel(url);
-      return label + ":" + line;
-    }
-
-    function getExpectedLineText(line) {
-      return gDebugger.DebuggerView.getEditorLine(line - 1);
-    }
   }
 
   function finalCheck() {
     is(Object.keys(gBreakpoints).length, 0, "no breakpoint in the debugger");
-    ok(!gPane.getBreakpoint(gScripts.values[0], 5),
+    ok(!gPane.getBreakpoint(gSources.values[0], 5),
        "getBreakpoint(locations[0], 5) returns no breakpoint");
   }
 
   registerCleanupFunction(function() {
     is(breakpointsAdded, 3, "correct number of breakpoints have been added");
     is(breakpointsDisabled, 3, "correct number of breakpoints have been disabled");
     is(breakpointsRemoved, 3, "correct number of breakpoints have been removed");
     removeTab(gTab);
     gPane = null;
     gTab = null;
     gDebuggee = null;
     gDebugger = null;
-    gScripts = null;
+    gEditor = null;
+    gSources = null;
     gBreakpoints = null;
-    gBreakpointsContainer = null;
     gBreakpointsParent = null;
     gBreakpointsList = null;
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-01.js
@@ -17,17 +17,17 @@ function test()
 {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
 
-    gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
+    gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
     performTest();
   });
 
   function performTest()
   {
     is(gWatch.getExpressions().length, 0,
       "There should initially be no watch expressions");
 
@@ -64,39 +64,39 @@ function test()
       "Duplicate watch expressions are automatically removed");
 
 
     addAndCheckCustomExpression(2, 0, "bazΩΩka");
     addAndCheckCustomExpression(3, 0, "bambøøcha");
 
 
     EventUtils.sendMouseEvent({ type: "click" },
-      gWatch.getItemAtIndex(0).target.closeNode,
+      gWatch.getItemAtIndex(0).attachment.closeNode,
       gDebugger);
 
     is(gWatch.getExpressions().length, 2,
       "Watch expressions are removed when the close button is pressed");
     is(gWatch.getExpressions()[0], "bazΩΩka",
       "The expression at index " + 0 + " should be correct (1)");
     is(gWatch.getExpressions()[1], "a",
       "The expression at index " + 1 + " should be correct (2)");
 
 
     EventUtils.sendMouseEvent({ type: "click" },
-      gWatch.getItemAtIndex(0).target.closeNode,
+      gWatch.getItemAtIndex(0).attachment.closeNode,
       gDebugger);
 
     is(gWatch.getExpressions().length, 1,
       "Watch expressions are removed when the close button is pressed");
     is(gWatch.getExpressions()[0], "a",
       "The expression at index " + 0 + " should be correct (3)");
 
 
     EventUtils.sendMouseEvent({ type: "click" },
-      gWatch.getItemAtIndex(0).target.closeNode,
+      gWatch.getItemAtIndex(0).attachment.closeNode,
       gDebugger);
 
     is(gWatch.getExpressions().length, 0,
       "Watch expressions are removed when the close button is pressed");
 
 
     EventUtils.sendMouseEvent({ type: "click" },
       gWatch._container._parent,
@@ -137,17 +137,17 @@ function test()
       "The expression at index " + index + " should be correct (4)");
   }
 
   function addAndCheckExpressions(total, index, string, noBlur) {
     gWatch.addExpression(string);
 
     is(gWatch.getExpressions().length, total,
       "There should be " + total + " watch expressions available (1)");
-    is(gWatch.totalItems, total,
+    is(gWatch.itemCount, total,
       "There should be " + total + " watch expressions available (2)");
 
     ok(gWatch.getItemAtIndex(index),
       "The expression at index " + index + " should be available");
     ok(gWatch.getItemAtIndex(index).attachment.id,
       "The expression at index " + index + " should have an id");
     is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
       "The expression at index " + index + " should have an initial expression");
@@ -164,21 +164,21 @@ function test()
 
     ok(gWatch.getItemAtIndex(index) instanceof gDebugger.MenuItem,
       "The correct watch expression element was accessed (1)");
     ok(gWatch._container.getItemAtIndex(index) instanceof XULElement,
       "The correct watch expression element was accessed (2)");
     is(element, gWatch._container.getItemAtIndex(index),
       "The correct watch expression element was accessed (3)");
 
-    is(element.arrowNode.hidden, false,
+    is(gWatch.getItemForElement(element).attachment.arrowNode.hidden, false,
       "The arrow node should be visible");
-    is(element.closeNode.hidden, false,
+    is(gWatch.getItemForElement(element).attachment.closeNode.hidden, false,
       "The close button should be visible");
-    is(element.inputNode.getAttribute("focused"), "true",
+    is(gWatch.getItemForElement(element).attachment.inputNode.getAttribute("focused"), "true",
       "The textbox input should be focused");
 
     is(gWatch._variables.scrollTop, 0,
       "The variables view should be scrolled to top");
 
     is(gWatch._cache[0], gWatch.getItemAtIndex(index),
       "The correct watch expression was added to the cache (1)");
     is(gWatch._cache[0], gWatch.getItemForElement(element),
@@ -204,17 +204,17 @@ function test()
     }
   }
 
   function removeAndCheckExpression(total, index, string) {
     gWatch.removeExpressionAt(index);
 
     is(gWatch.getExpressions().length, total,
       "There should be " + total + " watch expressions available (1)");
-    is(gWatch.totalItems, total,
+    is(gWatch.itemCount, total,
       "There should be " + total + " watch expressions available (2)");
 
     ok(gWatch.getItemAtIndex(index),
       "The expression at index " + index + " should still be available");
     ok(gWatch.getItemAtIndex(index).attachment.id,
       "The expression at index " + index + " should still have an id");
     is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
       "The expression at index " + index + " should still have an initial expression");
--- a/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug727429_watch-expressions-02.js
@@ -19,17 +19,17 @@ function test()
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
     gVars = gDebugger.DebuggerView.Variables;
 
-    gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
+    gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
     addExpressions();
     performTest();
   });
 
   function addExpressions()
   {
     gWatch.addExpression("'a'");
     gWatch.addExpression("\"a\"");
--- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js
@@ -9,20 +9,16 @@ const TAB_URL = EXAMPLE_URL + "browser_d
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
 
 function test()
 {
-  let tempScope = {};
-  Cu.import("resource:///modules/source-editor.jsm", tempScope);
-  let SourceEditor = tempScope.SourceEditor;
-
   let contextMenu = null;
   let scriptShown = false;
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
@@ -54,27 +50,28 @@ function test()
       testStarted = true;
       gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest()
   {
-    let scripts = gDebugger.DebuggerView.Sources._container;
+    let scripts = gDebugger.DebuggerView.Sources;
+    let editor = gDebugger.editor;
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
-    is(scripts.itemCount, 2, "Found the expected number of scripts.");
-
-    let editor = gDebugger.editor;
+    is(scripts.itemCount, 2,
+      "Found the expected number of scripts.");
 
     isnot(editor.getText().indexOf("debugger"), -1,
-          "The correct script was loaded initially.");
+      "The correct script was loaded initially.");
+
     isnot(editor.getText().indexOf("\u263a"), -1,
       "Unicode characters are converted correctly.");
 
     contextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
     ok(contextMenu, "source editor context menupopup");
     ok(editor.readOnly, "editor is read only");
 
     editor.focus();
@@ -100,20 +97,20 @@ function test()
 
     // Map command ids to their expected disabled state.
     let commands = {"se-cmd-undo": true, "se-cmd-redo": true,
                     "se-cmd-cut": true, "se-cmd-paste": true,
                     "se-cmd-delete": true, "cmd_findAgain": true,
                     "cmd_findPrevious": true, "cmd_find": false,
                     "cmd_gotoLine": false, "cmd_copy": false,
                     "se-cmd-selectAll": false};
+
     for (let id in commands) {
-      let element = document.getElementById(id);
-      is(element.hasAttribute("disabled"), commands[id],
-         id + " hasAttribute('disabled') check");
+      is(document.getElementById(id).hasAttribute("disabled"), commands[id],
+        id + " hasAttribute('disabled') check");
     }
 
     executeSoon(function() {
       contextMenu.hidePopup();
       closeDebuggerAndFinish();
     });
   }
 
--- a/browser/devtools/debugger/test/browser_dbg_bug737803_editor_actual_location.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug737803_editor_actual_location.js
@@ -7,25 +7,21 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
-let gScripts = null;
+let gSources = null;
 let gEditor = null;
 let gBreakpoints = null;
 
 function test() {
-  let tempScope = {};
-  Cu.import("resource:///modules/source-editor.jsm", tempScope);
-  let SourceEditor = tempScope.SourceEditor;
-
   let scriptShown = false;
   let framesAdded = false;
   let testStarted = false;
   let resumed = false;
 
   debug_tab_pane(TAB_URL, function (aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
@@ -54,54 +50,54 @@ function test() {
     if (scriptShown && framesAdded && resumed && !testStarted) {
       gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest() {
-    gScripts = gDebugger.DebuggerView.Sources;
+    gSources = gDebugger.DebuggerView.Sources;
     gEditor = gDebugger.editor;
     gBreakpoints = gPane.getAllBreakpoints();
     is(Object.keys(gBreakpoints), 0, "There are no breakpoints");
 
     gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
       onEditorBreakpointAdd);
 
-    let location = { url: gScripts.selectedValue, line: 4 };
+    let location = { url: gSources.selectedValue, line: 4 };
     executeSoon(function () {
       gPane.addBreakpoint(location, onBreakpointAdd);
     });
   }
 
   let onBpDebuggerAdd = false;
   let onBpEditorAdd = false;
 
   function onBreakpointAdd(aBpClient) {
-    is(aBpClient.location.url, gScripts.selectedValue, "URL is the same");
+    is(aBpClient.location.url, gSources.selectedValue, "URL is the same");
     is(aBpClient.location.line, 6, "Line number is new");
     is(aBpClient.requestedLocation.line, 4, "Requested location is correct");
 
     onBpDebuggerAdd = true;
     tryFinish();
   }
 
   function onEditorBreakpointAdd(aEvent) {
     gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
       onEditorBreakpointAdd);
 
     is(gEditor.getBreakpoints().length, 1,
       "There is only one breakpoint in the editor");
 
-    ok(!gPane.getBreakpoint(gScripts.selectedValue, 4),
+    ok(!gPane.getBreakpoint(gSources.selectedValue, 4),
       "There are no breakpoints on an invalid line");
 
-    let br = gPane.getBreakpoint(gScripts.selectedValue, 6);
-    is(br.location.url, gScripts.selectedValue, "URL is correct");
+    let br = gPane.getBreakpoint(gSources.selectedValue, 6);
+    is(br.location.url, gSources.selectedValue, "URL is correct");
     is(br.location.line, 6, "Line number is correct");
 
     onBpEditorAdd = true;
     tryFinish();
   }
 
   function tryFinish() {
     info("onBpDebuggerAdd: " + onBpDebuggerAdd);
@@ -113,13 +109,13 @@ function test() {
   }
 
   registerCleanupFunction(function () {
     removeTab(gTab);
     gPane = null;
     gTab = null;
     gDebuggee = null;
     gDebugger = null;
-    gScripts = null;
+    gSources = null;
     gEditor = null;
     gBreakpoints = null;
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-01.js
@@ -6,39 +6,36 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_conditional-breakpoints.html";
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
-let gScripts = null;
 let gEditor = null;
+let gSources = null;
 let gBreakpoints = null;
-let gBreakpointsPane = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
   let scriptShown = false;
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
-    gBreakpoints = gDebugger.DebuggerController.Breakpoints;
-    gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
 
-    gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
+    gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
     resumed = true;
 
     gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
@@ -60,126 +57,130 @@ function test()
       gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: addBreakpoints }, 0);
     }
   }
 
   function performTest()
   {
-    gScripts = gDebugger.DebuggerView.Sources;
+    gEditor = gDebugger.editor;
+    gSources = gDebugger.DebuggerView.Sources;
+    gBreakpoints = gPane.getAllBreakpoints();
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
-    is(gScripts._container.itemCount, 1, "Found the expected number of scripts.");
-
-    gEditor = gDebugger.editor;
+    is(gSources.itemCount, 1,
+      "Found the expected number of scripts.");
 
     isnot(gEditor.getText().indexOf("ermahgerd"), -1,
-          "The correct script was loaded initially.");
-    is(gScripts.selectedValue, gScripts.values[0],
-          "The correct script is selected");
+      "The correct script was loaded initially.");
 
-    gBreakpoints = gPane.getAllBreakpoints();
+    is(gSources.selectedValue, gSources.values[0],
+      "The correct script is selected");
+
     is(Object.keys(gBreakpoints).length, 13, "thirteen breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
-
     is(gEditor.getBreakpoints().length, 13, "thirteen breakpoints in the editor");
 
     executeSoon(test1);
   }
 
   function test1(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 14, test2);
+    resumeAndTestBreakpoint(gSources.selectedValue, 14, test2);
   }
 
   function test2(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 15, test3);
+    resumeAndTestBreakpoint(gSources.selectedValue, 15, test3);
   }
 
   function test3(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 16, test4);
+    resumeAndTestBreakpoint(gSources.selectedValue, 16, test4);
   }
 
   function test4(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 17, test5);
+    resumeAndTestBreakpoint(gSources.selectedValue, 17, test5);
   }
 
   function test5(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 18, test6);
+    resumeAndTestBreakpoint(gSources.selectedValue, 18, test6);
   }
 
   function test6(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 19, test7);
+    resumeAndTestBreakpoint(gSources.selectedValue, 19, test7);
   }
 
   function test7(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 21, test8);
+    resumeAndTestBreakpoint(gSources.selectedValue, 21, test8);
   }
 
   function test8(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 22, test9);
+    resumeAndTestBreakpoint(gSources.selectedValue, 22, test9);
   }
 
   function test9(callback)
   {
-    resumeAndTestBreakpoint(gScripts.selectedValue, 23, test10);
+    resumeAndTestBreakpoint(gSources.selectedValue, 23, test10);
   }
 
   function test10(callback)
   {
     gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
       gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
 
-      is(gBreakpointsPane.selectedItem, null,
-        "There should be no selected breakpoint in the breakpoints pane.")
-      is(gBreakpointsPane._popupShown, false,
+      isnot(gSources.selectedItem, null,
+        "There should be a selected script in the scripts pane.")
+      is(gSources.selectedBreakpoint, null,
+        "There should be no selected breakpoint in the scripts pane.")
+      is(gSources.selectedClient, null,
+        "There should be no selected client in the scripts pane.");
+      is(gSources._conditionalPopupVisible, false,
         "The breakpoint conditional expression popup should not be shown.");
 
-      is(gDebugger.DebuggerView.StackFrames.visibleItems.length, 0,
+      is(gDebugger.DebuggerView.StackFrames._container._list.querySelectorAll(".dbg-stackframe").length, 0,
         "There should be no visible stackframes.");
-      is(gDebugger.DebuggerView.Breakpoints.visibleItems.length, 13,
+      is(gDebugger.DebuggerView.Sources._container._list.querySelectorAll(".dbg-breakpoint").length, 13,
         "There should be thirteen visible breakpoints.");
 
       testReload();
     }, true);
 
     gDebugger.DebuggerController.activeThread.resume();
   }
 
   function resumeAndTestBreakpoint(url, line, callback)
   {
     resume(line, function() {
       waitForCaretPos(line - 1, function() {
-        testBreakpoint(gBreakpointsPane.selectedItem, gBreakpointsPane.selectedClient, url, line, true);
+        testBreakpoint(gSources.selectedBreakpoint, gSources.selectedClient, url, line, true);
         callback();
       });
     });
   }
 
   function testBreakpoint(aBreakpointItem, aBreakpointClient, url, line, editor)
   {
-    is(aBreakpointItem.attachment.sourceLocation, gScripts.selectedValue,
+    is(aBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
       "The breakpoint on line " + line + " wasn't added on the correct source.");
     is(aBreakpointItem.attachment.lineNumber, line,
       "The breakpoint on line " + line + " wasn't found.");
-    is(aBreakpointItem.attachment.enabled, true,
+    is(!!aBreakpointItem.attachment.disabled, false,
       "The breakpoint on line " + line + " should be enabled.");
-    is(aBreakpointItem.attachment.isConditional, true,
-      "The breakpoint on line " + line + " should be conditional.");
-    is(gBreakpointsPane._popupShown, false,
+    is(!!aBreakpointItem.attachment.openPopupFlag, false,
+      "The breakpoint on line " + line + " should not open a popup.");
+    is(gSources._conditionalPopupVisible, false,
       "The breakpoint conditional expression popup should not be shown.");
 
     is(aBreakpointClient.location.url, url,
        "The breakpoint's client url is correct");
     is(aBreakpointClient.location.line, line,
        "The breakpoint's client line is correct");
     isnot(aBreakpointClient.conditionalExpression, undefined,
       "The breakpoint on line " + line + " should have a conditional expression.");
@@ -248,58 +249,63 @@ function test()
       });
     }, {
       conditionalExpression: "undefined"
     });
   }
 
   function testReload()
   {
+    info("Testing reload...");
+
     function _get(url, line) {
       return [
-        gDebugger.DebuggerView.Breakpoints.getBreakpoint(url, line),
+        gDebugger.DebuggerView.Sources.getBreakpoint(url, line),
         gDebugger.DebuggerController.Breakpoints.getBreakpoint(url, line),
         url,
         line,
-        false
       ];
     }
 
     gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown() {
       gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
 
       waitForBreakpoints(13, function() {
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 14));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 15));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 16));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 17));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 18));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 19));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 21));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 22));
-        testBreakpoint.apply(this, _get(gScripts.selectedValue, 23));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 14));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 15));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 16));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 17));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 18));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 19));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 21));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 22));
+        testBreakpoint.apply(this, _get(gSources.selectedValue, 23));
 
-        is(gBreakpointsPane.selectedItem, null,
-          "There should be no selected item in the breakpoints pane.");
-        is(gBreakpointsPane.selectedClient, null,
-          "There should be no selected client in the breakpoints pane.");
+      isnot(gSources.selectedItem, null,
+        "There should be a selected script in the scripts pane.")
+      is(gSources.selectedBreakpoint, null,
+        "There should be no selected breakpoint in the scripts pane.")
+      is(gSources.selectedClient, null,
+        "There should be no selected client in the scripts pane.");
+      is(gSources._conditionalPopupVisible, false,
+        "The breakpoint conditional expression popup should not be shown.");
 
         closeDebuggerAndFinish();
       });
     });
 
     finalCheck();
     gDebuggee.location.reload();
   }
 
   function finalCheck() {
     isnot(gEditor.getText().indexOf("ermahgerd"), -1,
-          "The correct script is still loaded.");
-    is(gScripts.selectedValue, gScripts.values[0],
-          "The correct script is still selected");
+      "The correct script is still loaded.");
+    is(gSources.selectedValue, gSources.values[0],
+      "The correct script is still selected");
   }
 
   function resume(expected, callback) {
     gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
       waitForBreakpoint(expected, callback);
     });
 
     EventUtils.sendMouseEvent({ type: "mousedown" },
@@ -319,18 +325,18 @@ function test()
     let count = 0;
     let intervalID = window.setInterval(function() {
       info("count: " + count + " ");
       if (++count > 50) {
         ok(false, "Timed out while polling for the breakpoint.");
         window.clearInterval(intervalID);
         return closeDebuggerAndFinish();
       }
-      if ((gBreakpointsPane.selectedClient !== expected) &&
-          (gBreakpointsPane.selectedClient || bogusClient).location.line !== expected) {
+      if ((gSources.selectedClient !== expected) &&
+          (gSources.selectedClient || bogusClient).location.line !== expected) {
         return;
       }
       // We arrived at the expected line, it's safe to callback.
       window.clearInterval(intervalID);
       callback();
     }, 100);
   }
 
@@ -340,17 +346,17 @@ function test()
     let count = 0;
     let intervalID = window.setInterval(function() {
       info("count: " + count + " ");
       if (++count > 50) {
         ok(false, "Timed out while polling for the breakpoints.");
         window.clearInterval(intervalID);
         return closeDebuggerAndFinish();
       }
-      if (gBreakpointsPane.visibleItems.length != total) {
+      if (gSources._container._list.querySelectorAll(".dbg-breakpoint").length != total) {
         return;
       }
       // We got all the breakpoints, it's safe to callback.
       window.clearInterval(intervalID);
       callback();
     }, 100);
   }
 
@@ -375,14 +381,13 @@ function test()
   }
 
   registerCleanupFunction(function() {
     removeTab(gTab);
     gPane = null;
     gTab = null;
     gDebuggee = null;
     gDebugger = null;
-    gScripts = null;
     gEditor = null;
+    gSources = null;
     gBreakpoints = null;
-    gBreakpointsPane = null;
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug740825_conditional-breakpoints-02.js
@@ -6,45 +6,38 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_conditional-breakpoints.html";
 
 let gPane = null;
 let gTab = null;
 let gDebuggee = null;
 let gDebugger = null;
-let gScripts = null;
 let gEditor = null;
+let gSources = null;
 let gBreakpoints = null;
-let gBreakpointsPane = null;
 
 requestLongerTimeout(2);
 
 function test()
 {
-  let tempScope = {};
-  Cu.import("resource:///modules/source-editor.jsm", tempScope);
-  let SourceEditor = tempScope.SourceEditor;
-
   let scriptShown = false;
   let framesAdded = false;
   let resumed = false;
   let testStarted = false;
 
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
-    gBreakpoints = gDebugger.DebuggerController.Breakpoints;
-    gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
 
     gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
 
-    gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
+    gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
     resumed = true;
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       framesAdded = true;
       executeSoon(startTest);
     });
 
     executeSoon(function() {
@@ -64,271 +57,279 @@ function test()
       gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
       testStarted = true;
       Services.tm.currentThread.dispatch({ run: performTest }, 0);
     }
   }
 
   function performTest()
   {
-    gScripts = gDebugger.DebuggerView.Sources;
+    gEditor = gDebugger.editor;
+    gSources = gDebugger.DebuggerView.Sources;
+    gBreakpoints = gPane.getAllBreakpoints();
 
     is(gDebugger.DebuggerController.activeThread.state, "paused",
       "Should only be getting stack frames while paused.");
 
-    is(gScripts._container.itemCount, 1, "Found the expected number of scripts.");
-
-    gEditor = gDebugger.editor;
+    is(gSources.itemCount, 1,
+      "Found the expected number of scripts.");
 
     isnot(gEditor.getText().indexOf("ermahgerd"), -1,
-          "The correct script was loaded initially.");
-    is(gScripts.selectedValue, gScripts.values[0],
-          "The correct script is selected");
+      "The correct script was loaded initially.");
 
-    gBreakpoints = gPane.getAllBreakpoints();
+    is(gSources.selectedValue, gSources.values[0],
+      "The correct script is selected");
+
     is(Object.keys(gBreakpoints), 0, "no breakpoints");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
-
     is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
 
     executeSoon(addBreakpoint1);
   }
 
   function addBreakpoint1()
   {
-    gPane.addBreakpoint({ url: gScripts.selectedValue, line: 12 });
+    gPane.addBreakpoint({ url: gSources.selectedValue, line: 12 });
 
     waitForBreakpoint(12, function() {
       waitForCaretPos(10, function() {
         waitForPopup(false, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 12, false, false, false);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 12, false, false, false);
 
           executeSoon(addBreakpoint2);
         });
       });
     });
   }
 
   function addBreakpoint2()
   {
-    gBreakpointsPane._editorContextMenuLineNumber = 12;
-    gBreakpointsPane._onCmdAddBreakpoint();
+    gSources._editorContextMenuLineNumber = 12;
+    gSources._onCmdAddBreakpoint();
 
     waitForBreakpoint(13, function() {
       waitForCaretPos(12, function() {
         waitForPopup(false, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 13, false, false, true);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 13, false, false, true);
 
           executeSoon(modBreakpoint2);
         });
       });
     });
   }
 
   function modBreakpoint2()
   {
-    gBreakpointsPane._editorContextMenuLineNumber = 12;
-    gBreakpointsPane._onCmdAddConditionalBreakpoint();
+    gSources._editorContextMenuLineNumber = 12;
+    gSources._onCmdAddConditionalBreakpoint();
 
     waitForBreakpoint(13, function() {
       waitForCaretPos(12, function() {
         waitForPopup(true, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 13, true, true, true);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 13, true, true, true);
 
           executeSoon(addBreakpoint3);
         });
       });
     });
   }
 
   function addBreakpoint3()
   {
-    gBreakpointsPane._editorContextMenuLineNumber = 13;
-    gBreakpointsPane._onCmdAddConditionalBreakpoint();
+    gSources._editorContextMenuLineNumber = 13;
+    gSources._onCmdAddConditionalBreakpoint();
 
     waitForBreakpoint(14, function() {
       waitForCaretPos(13, function() {
         waitForPopup(true, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 14, true, true, true);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 14, true, true, true);
 
           executeSoon(modBreakpoint3);
         });
       });
     });
   }
 
   function modBreakpoint3()
   {
     write("bamboocha");
     EventUtils.sendKey("RETURN", gDebugger);
 
     waitForBreakpoint(14, function() {
       waitForCaretPos(13, function() {
         waitForPopup(false, function() {
-          is(gBreakpointsPane.selectedClient.conditionalExpression, "bamboocha",
+          is(gSources.selectedClient.conditionalExpression, "bamboocha",
             "The bamboocha expression wasn't fonud on the conditional breakpoint");
 
           executeSoon(setContextMenu);
         });
       });
     });
   }
 
   function setContextMenu()
   {
     let contextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
+    info("Testing source editor popup...");
 
     contextMenu.addEventListener("popupshown", function onPopupShown() {
       contextMenu.removeEventListener("popupshown", onPopupShown, false);
+      info("Source editor popup shown...");
 
       contextMenu.addEventListener("popuphidden", function onPopupHidden() {
         contextMenu.removeEventListener("popuphidden", onPopupHidden, false);
+        info("Source editor popup hidden...");
 
+        is(gSources._editorContextMenuLineNumber, 14,
+          "The context menu line number is incorrect after the popup was hidden.");
         executeSoon(addBreakpoint4);
       }, false);
 
-      gBreakpointsPane._editorContextMenuLineNumber = 0;
+      is(gSources._editorContextMenuLineNumber, 14,
+        "The context menu line number is incorrect after the popup was shown.");
       contextMenu.hidePopup();
     }, false);
 
-    gBreakpointsPane._editorContextMenuLineNumber = 14;
+    is(gSources._editorContextMenuLineNumber, -1,
+      "The context menu line number was incorrect before the popup was shown.");
+    gSources._editorContextMenuLineNumber = 14;
     contextMenu.openPopup(gEditor.editorElement, "overlap", 0, 0, true, false);
   }
 
   function addBreakpoint4()
   {
     gEditor.setCaretPosition(14);
-    gBreakpointsPane._onCmdAddBreakpoint();
+    gSources._onCmdAddBreakpoint();
 
     waitForBreakpoint(15, function() {
       waitForCaretPos(14, function() {
         waitForPopup(false, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 15, false, false, true);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 15, false, false, true);
 
           executeSoon(delBreakpoint4);
         });
       });
     });
   }
 
   function delBreakpoint4()
   {
     gEditor.setCaretPosition(14);
-    gBreakpointsPane._onCmdAddBreakpoint();
+    gSources._onCmdAddBreakpoint();
 
     waitForBreakpoint(null, function() {
       waitForCaretPos(14, function() {
         waitForPopup(false, function() {
-          is(gBreakpointsPane.selectedItem, null,
+          is(gSources.selectedBreakpoint, null,
             "There should be no selected breakpoint in the breakpoints pane.")
-          is(gBreakpointsPane._popupShown, false,
+          is(gSources._conditionalPopupVisible, false,
             "The breakpoint conditional expression popup should not be shown.");
 
           executeSoon(moveHighlight1);
         });
       });
     });
   }
 
   function moveHighlight1()
   {
     gEditor.setCaretPosition(13);
 
     waitForBreakpoint(14, function() {
       waitForCaretPos(13, function() {
         waitForPopup(false, function() {
-          testBreakpoint(gBreakpointsPane.selectedItem,
-                         gBreakpointsPane.selectedClient,
-                         gScripts.selectedValue, 14, true, false, true);
+          testBreakpoint(gSources.selectedBreakpoint,
+                         gSources.selectedClient,
+                         gSources.selectedValue, 14, false, true, true);
 
           executeSoon(testHighlights1);
         });
       });
     });
   }
 
   function testHighlights1()
   {
-    isnot(gBreakpointsPane.selectedItem, null,
+    isnot(gSources.selectedBreakpoint, null,
       "There should be a selected breakpoint in the breakpoints pane.");
-    is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+    is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
       "The selected breakpoint should have the correct location.");
-    is(gBreakpointsPane.selectedItem.attachment.lineNumber, 14,
+    is(gSources.selectedBreakpoint.attachment.lineNumber, 14,
       "The selected breakpoint should have the correct line number.");
-    is(gBreakpointsPane._popupShown, false,
+    is(gSources._conditionalPopupVisible, false,
       "The breakpoint conditional expression popup should not be shown.");
     is(gEditor.getCaretPosition().line, 13,
       "The source editor caret position should be at line 13");
     is(gEditor.getCaretPosition().col, 0,
       "The source editor caret position should be at column 0");
 
     gEditor.setCaretPosition(12);
 
     waitForCaretPos(12, function() {
       waitForPopup(false, function() {
-        isnot(gBreakpointsPane.selectedItem, null,
+        isnot(gSources.selectedBreakpoint, null,
           "There should be a selected breakpoint in the breakpoints pane.");
-        is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+        is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
           "The selected breakpoint should have the correct location.");
-        is(gBreakpointsPane.selectedItem.attachment.lineNumber, 13,
+        is(gSources.selectedBreakpoint.attachment.lineNumber, 13,
           "The selected breakpoint should have the correct line number.");
-        is(gBreakpointsPane._popupShown, false,
+        is(gSources._conditionalPopupVisible, false,
           "The breakpoint conditional expression popup should not be shown.");
         is(gEditor.getCaretPosition().line, 12,
           "The source editor caret position should be at line 12");
         is(gEditor.getCaretPosition().col, 0,
           "The source editor caret position should be at column 0");
 
         gEditor.setCaretPosition(11);
 
         waitForCaretPos(11, function() {
           waitForPopup(false, function() {
-            isnot(gBreakpointsPane.selectedItem, null,
+            isnot(gSources.selectedBreakpoint, null,
               "There should be a selected breakpoint in the breakpoints pane.");
-            is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+            is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
               "The selected breakpoint should have the correct location.");
-            is(gBreakpointsPane.selectedItem.attachment.lineNumber, 12,
+            is(gSources.selectedBreakpoint.attachment.lineNumber, 12,
               "The selected breakpoint should have the correct line number.");
-            is(gBreakpointsPane._popupShown, false,
+            is(gSources._conditionalPopupVisible, false,
               "The breakpoint conditional expression popup should not be shown.");
             is(gEditor.getCaretPosition().line, 11,
               "The source editor caret position should be at line 11");
             is(gEditor.getCaretPosition().col, 0,
               "The source editor caret position should be at column 0");
 
             gEditor.setCaretPosition(10);
 
             waitForCaretPos(10, function() {
               waitForPopup(false, function() {
-                is(gBreakpointsPane.selectedItem, null,
+                is(gSources.selectedBreakpoint, null,
                   "There should not be a selected breakpoint in the breakpoints pane.");
-                is(gBreakpointsPane._popupShown, false,
+                is(gSources._conditionalPopupVisible, false,
                   "The breakpoint conditional expression popup should not be shown.");
                 is(gEditor.getCaretPosition().line, 10,
                   "The source editor caret position should be at line 10");
                 is(gEditor.getCaretPosition().col, 0,
                   "The source editor caret position should be at column 0");
 
                 gEditor.setCaretPosition(14);
 
                 waitForCaretPos(14, function() {
                   waitForPopup(false, function() {
-                    is(gBreakpointsPane.selectedItem, null,
+                    is(gSources.selectedBreakpoint, null,
                       "There should not be a selected breakpoint in the breakpoints pane.");
-                    is(gBreakpointsPane._popupShown, false,
+                    is(gSources._conditionalPopupVisible, false,
                       "The breakpoint conditional expression popup should not be shown.");
                     is(gEditor.getCaretPosition().line, 14,
                       "The source editor caret position should be at line 14");
                     is(gEditor.getCaretPosition().col, 0,
                       "The source editor caret position should be at column 0");
 
                     executeSoon(testHighlights2);
                   });
@@ -339,66 +340,66 @@ function test()
         });
       });
     });
   }
 
   function testHighlights2()
   {
     EventUtils.sendMouseEvent({ type: "click" },
-      gBreakpointsPane._container.getItemAtIndex(2),
+      gSources._container._list.querySelectorAll(".dbg-breakpoint")[2],
       gDebugger);
 
     waitForCaretPos(13, function() {
       waitForPopup(true, function() {
-        isnot(gBreakpointsPane.selectedItem, null,
+        isnot(gSources.selectedBreakpoint, null,
           "There should be a selected breakpoint in the breakpoints pane.");
-        is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+        is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
           "The selected breakpoint should have the correct location.");
-        is(gBreakpointsPane.selectedItem.attachment.lineNumber, 14,
+        is(gSources.selectedBreakpoint.attachment.lineNumber, 14,
           "The selected breakpoint should have the correct line number.");
-        is(gBreakpointsPane._popupShown, true,
+        is(gSources._conditionalPopupVisible, true,
           "The breakpoint conditional expression popup should be shown.");
         is(gEditor.getCaretPosition().line, 13,
           "The source editor caret position should be at line 13");
         is(gEditor.getCaretPosition().col, 0,
           "The source editor caret position should be at column 0");
 
         EventUtils.sendMouseEvent({ type: "click" },
-          gBreakpointsPane._container.getItemAtIndex(1),
+          gSources._container._list.querySelectorAll(".dbg-breakpoint")[1],
           gDebugger);
 
         waitForCaretPos(12, function() {
           waitForPopup(true, function() {
-            isnot(gBreakpointsPane.selectedItem, null,
+            isnot(gSources.selectedBreakpoint, null,
               "There should be a selected breakpoint in the breakpoints pane.");
-            is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+            is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
               "The selected breakpoint should have the correct location.");
-            is(gBreakpointsPane.selectedItem.attachment.lineNumber, 13,
+            is(gSources.selectedBreakpoint.attachment.lineNumber, 13,
               "The selected breakpoint should have the correct line number.");
-            is(gBreakpointsPane._popupShown, true,
+            is(gSources._conditionalPopupVisible, true,
               "The breakpoint conditional expression popup should be shown.");
             is(gEditor.getCaretPosition().line, 12,
               "The source editor caret position should be at line 12");
             is(gEditor.getCaretPosition().col, 0,
               "The source editor caret position should be at column 0");
 
             EventUtils.sendMouseEvent({ type: "click" },
-              gBreakpointsPane._container.getItemAtIndex(0),
+              gSources._container._list.querySelectorAll(".dbg-breakpoint")[0],
               gDebugger);
 
             waitForCaretPos(11, function() {
               waitForPopup(false, function() {
-                isnot(gBreakpointsPane.selectedItem, null,
+                isnot(gSources.selectedBreakpoint, null,
                   "There should be a selected breakpoint in the breakpoints pane.");
-                is(gBreakpointsPane.selectedItem.attachment.sourceLocation, gScripts.selectedValue,
+                is(gSources.selectedBreakpoint.attachment.sourceLocation, gSources.selectedValue,
                   "The selected breakpoint should have the correct location.");
-                is(gBreakpointsPane.selectedItem.attachment.lineNumber, 12,
+                is(gSources.selectedBreakpoint.attachment.lineNumber, 12,
                   "The selected breakpoint should have the correct line number.");
-                is(gBreakpointsPane._popupShown, false,
+                is(gSources._conditionalPopupVisible, false,
                   "The breakpoint conditional expression popup should be shown.");
                 is(gEditor.getCaretPosition().line, 11,
                   "The source editor caret position should be at line 11");
                 is(gEditor.getCaretPosition().col, 0,
                   "The source editor caret position should be at column 0");
 
                 executeSoon(delBreakpoint2);
               });
@@ -406,70 +407,67 @@ function test()
           });
         });
       });
     });
   }
 
   function delBreakpoint2()
   {
-    gBreakpointsPane._editorContextMenuLineNumber = 12;
-    gBreakpointsPane._onCmdAddBreakpoint();
+    gSources._editorContextMenuLineNumber = 12;
+    gSources._onCmdAddBreakpoint();
 
     waitForBreakpoint(null, function() {
       waitForPopup(false, function() {
-        is(gBreakpointsPane.selectedItem, null,
+        is(gSources.selectedBreakpoint, null,
           "There should be no selected breakpoint in the breakpoints pane.")
-        is(gBreakpointsPane._popupShown, false,
+        is(gSources._conditionalPopupVisible, false,
           "The breakpoint conditional expression popup should not be shown.");
 
         executeSoon(delBreakpoint3);
       });
     });
   }
 
   function delBreakpoint3()
   {
-    gBreakpointsPane._editorContextMenuLineNumber = 13;
-    gBreakpointsPane._onCmdAddBreakpoint();
+    gSources._editorContextMenuLineNumber = 13;
+    gSources._onCmdAddBreakpoint();
 
     waitForBreakpoint(null, function() {
       waitForPopup(false, function() {
-        is(gBreakpointsPane.selectedItem, null,
+        is(gSources.selectedBreakpoint, null,
           "There should be no selected breakpoint in the breakpoints pane.")
-        is(gBreakpointsPane._popupShown, false,
+        is(gSources._conditionalPopupVisible, false,
           "The breakpoint conditional expression popup should not be shown.");
 
         executeSoon(testBreakpoints);
       });
     });
   }
 
   function testBreakpoints()
   {
     is(Object.keys(gBreakpoints).length, 1, "one breakpoint");
     ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
-
     is(gEditor.getBreakpoints().length, 1, "one breakpoint in the editor");
 
     closeDebuggerAndFinish();
   }
 
-  function testBreakpoint(aBreakpointItem, aBreakpointClient, url, line, conditional, popup, editor)
+  function testBreakpoint(aBreakpointItem, aBreakpointClient, url, line, popup, conditional, editor)
   {
-    is(aBreakpointItem.attachment.sourceLocation, gScripts.selectedValue,
+    is(aBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
       "The breakpoint on line " + line + " wasn't added on the correct source.");
     is(aBreakpointItem.attachment.lineNumber, line,
       "The breakpoint on line " + line + " wasn't found.");
-    is(aBreakpointItem.attachment.enabled, true,
+    is(!aBreakpointItem.attachment.disabled, true,
       "The breakpoint on line " + line + " should be enabled.");
-    is(aBreakpointItem.attachment.isConditional, conditional,
-      "The breakpoint on line " + line + " should " + (conditional ? "" : "not ") + "be conditional.");
-    is(gBreakpointsPane._popupShown, popup,
-      "The breakpoint conditional expression popup should" + (popup ? "" : "not ") + "be shown.");
+    is(gSources._conditionalPopupVisible, popup,
+      "The breakpoint conditional expression popup should " + (popup ? "" : "not ") + "be shown.");
 
     is(aBreakpointClient.location.url, url,
        "The breakpoint's client url is correct");
     is(aBreakpointClient.location.line, line,
        "The breakpoint's client line is correct");
 
     if (conditional) {
       isnot(aBreakpointClient.conditionalExpression, undefined,
@@ -499,18 +497,18 @@ function test()
     let count = 0;
     let intervalID = window.setInterval(function() {
       info("count: " + count + " ");
       if (++count > 50) {
         ok(false, "Timed out while polling for the breakpoint.");
         window.clearInterval(intervalID);
         return closeDebuggerAndFinish();
       }
-      if ((gBreakpointsPane.selectedClient !== expected) &&
-          (gBreakpointsPane.selectedClient || bogusClient).location.line !== expected) {
+      if ((gSources.selectedClient !== expected) &&
+          (gSources.selectedClient || bogusClient).location.line !== expected) {
         return;
       }
       // We arrived at the expected line, it's safe to callback.
       window.clearInterval(intervalID);
       callback();
     }, 100);
   }
 
@@ -540,47 +538,46 @@ function test()
     let count = 0;
     let intervalID = window.setInterval(function() {
       info("count: " + count + " ");
       if (++count > 50) {
         ok(false, "Timed out while polling for the popup.");
         window.clearInterval(intervalID);
         return closeDebuggerAndFinish();
       }
-      if (gBreakpointsPane._popupShown != state) {
+      if (gSources._conditionalPopupVisible != state) {
         return;
       }
       // We got the expression popup at the expected state, it's safe to callback.
       window.clearInterval(intervalID);
       callback();
     }, 100);
   }
 
   function clear() {
-    gBreakpointsPane._cbTextbox.focus();
-    gBreakpointsPane._cbTextbox.value = "";
+    gSources._cbTextbox.focus();
+    gSources._cbTextbox.value = "";
   }
 
   function write(text) {
     clear();
     append(text);
   }
 
   function append(text) {
-    gBreakpointsPane._cbTextbox.focus();
+    gSources._cbTextbox.focus();
 
     for (let i = 0; i < text.length; i++) {
       EventUtils.sendChar(text[i], gDebugger);
     }
   }
 
   registerCleanupFunction(function() {
     removeTab(gTab);
     gPane = null;
     gTab = null;
     gDebuggee = null;
     gDebugger = null;
-    gScripts = null;
     gEditor = null;
+    gSources = null;
     gBreakpoints = null;
-    gBreakpointsPane = null;
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js
+++ b/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js
@@ -17,24 +17,25 @@ function test() {
 
     testNonEnumProperties();
   });
 }
 
 function testNonEnumProperties() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
+
       let testScope = gDebugger.DebuggerView.Variables.addScope("test-scope");
       let testVar = testScope.addVar("foo");
+
       testVar.addProperties({
         foo: {
           value: "bar",
           enumerable: true
         },
-
         bar: {
           value: "foo",
           enumerable: false
         }
       });
 
       // Expand the variable.
       testScope.expand();
--- a/browser/devtools/debugger/test/browser_dbg_chrome-debugging.js
+++ b/browser/devtools/debugger/test/browser_dbg_chrome-debugging.js
@@ -8,16 +8,17 @@
 
 var gClient = null;
 var gTab = null;
 var gHomeTab = null;
 var gThreadClient = null;
 var gNewGlobal = false;
 var gAttached = false;
 var gChromeScript = false;
+
 const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
 
 function test()
 {
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.connect(function(aType, aTraits) {
     gTab = addTab(DEBUGGER_TAB_URL, function() {
--- a/browser/devtools/debugger/test/browser_dbg_clean-exit.js
+++ b/browser/devtools/debugger/test/browser_dbg_clean-exit.js
@@ -19,16 +19,17 @@ function test() {
 
     testCleanExit();
   });
 }
 
 function testCleanExit() {
   gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
     Services.tm.currentThread.dispatch({ run: function() {
+
       is(gDebugger.DebuggerController.activeThread.paused, true,
         "Should be paused after the debugger statement.");
 
       closeDebuggerAndFinish();
     }}, 0);
   });
 
   gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
--- a/browser/devtools/debugger/test/browser_dbg_displayName.js
+++ b/browser/devtools/debugger/test/browser_dbg_displayName.js
@@ -31,17 +31,17 @@ function testAnonCall() {
       let frames = gDebugger.DebuggerView.StackFrames._container._list;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
-      is(frames.querySelector("#stackframe-0 .dbg-stackframe-name").getAttribute("value"),
+      is(frames.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
         "anonFunc", "Frame name should be anonFunc");
 
       testInferredName();
     }}, 0);
   });
 
   gDebuggee.evalCall();
 }
@@ -53,17 +53,17 @@ function testInferredName() {
       let frames = gDebugger.DebuggerView.StackFrames._container._list;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
-      is(frames.querySelector("#stackframe-0 .dbg-stackframe-name").getAttribute("value"),
+      is(frames.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
         "a/<", "Frame name should be a/<");
 
       resumeAndFinish();
     }}, 0);
   });
 
   gDebugger.DebuggerController.activeThread.resume();
 }
--- a/browser/devtools/debugger/test/browser_dbg_iframes.js
+++ b/browser/devtools/debugger/test/browser_dbg_iframes.js
@@ -2,24 +2,25 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests that iframes can be added as debuggees.
 
 var gPane = null;
 var gTab = null;
+var gDebugger = null;
 
 const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
 
 function test() {
   debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
-    let gDebugger = gPane.panelWin;
+    gDebugger = gPane.panelWin;
 
     is(gDebugger.DebuggerController.activeThread.paused, false,
       "Should be running after debug_tab_pane.");
 
     gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
       Services.tm.currentThread.dispatch({ run: function() {
 
         let frames = gDebugger.DebuggerView.StackFrames._container._list;
@@ -57,9 +58,10 @@ function test() {
     handler();
   });
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
+  gDebugger = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-blank.js
@@ -81,23 +81,23 @@ function testLocationChange()
       gDebugger.DebuggerController.client.removeListener("tabNavigated", onTabNavigated);
 
       ok(true, "tabNavigated event was fired.");
       info("Still attached to the tab.");
 
       gDebugger.addEventListener("Debugger:AfterSourcesAdded", function _onEvent(aEvent) {
         gDebugger.removeEventListener(aEvent.type, _onEvent);
 
-        is(gDebugger.DebuggerView.Sources.selectedValue, null,
+        is(gDebugger.DebuggerView.Sources.selectedValue, "",
           "There should be no selected script.");
         is(gDebugger.editor.getText().length, 0,
           "The source editor not have any text displayed.");
 
         let menulist = gDebugger.DebuggerView.Sources._container;
-        let noScripts = gDebugger.L10N.getStr("noScriptsText");
+        let noScripts = gDebugger.L10N.getStr("noSourcesText");
         is(menulist.getAttribute("label"), noScripts,
           "The menulist should display a notice that there are no scripts availalble.");
         is(menulist.getAttribute("tooltiptext"), "",
           "The menulist shouldn't have any tooltip text attributed when there are no scripts available.");
 
         closeDebuggerAndFinish();
       });
     });
--- a/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
@@ -87,17 +87,17 @@ function testLocationChange()
         gDebugger.removeEventListener(aEvent.type, _onEvent);
 
         isnot(gDebugger.DebuggerView.Sources.selectedValue, null,
           "There should be a selected script.");
         isnot(gDebugger.editor.getText().length, 0,
           "The source editor should have some text displayed.");
 
         let menulist = gDebugger.DebuggerView.Sources._container;
-        let noScripts = gDebugger.L10N.getStr("noScriptsText");
+        let noScripts = gDebugger.L10N.getStr("noSourcesText");
         isnot(menulist.getAttribute("label"), noScripts,
           "The menulist should not display a notice that there are no scripts availalble.");
         isnot(menulist.getAttribute("tooltiptext"), "",
           "The menulist should have a tooltip text attributed.");
 
         closeDebuggerAndFinish();
       });
     });
--- a/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
+++ b/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
@@ -16,177 +16,130 @@ function test() {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
 
     testPanesState();
 
-    gView.togglePanes({ visible: true, animated: false });
-    testPaneCollapse1();
-    testPaneCollapse2();
-    testPanesStartupPref(closeDebuggerAndFinish);
+    gView.toggleInstrumentsPane({ visible: true, animated: false });
+    testInstrumentsPaneCollapse();
+    testPanesStartupPref();
   });
 }
 
 function testPanesState() {
-  let togglePanesButton =
-    gDebugger.document.getElementById("toggle-panes");
+  let instrumentsPaneToggleButton =
+    gDebugger.document.getElementById("instruments-pane-toggle");
 
-  ok(togglePanesButton.getAttribute("panesHidden"),
-    "The debugger view panes should initially be hidden.");
+  ok(instrumentsPaneToggleButton.getAttribute("toggled"),
+    "The debugger view instruments pane should initially be hidden.");
   is(gDebugger.Prefs.panesVisibleOnStartup, false,
-    "The debugger view panes should initially be preffed as hidden.");
+    "The debugger view instruments pane should initially be preffed as hidden.");
   isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
     "The options menu item should not be checked.");
 }
 
-function testPaneCollapse1() {
-  let stackframesAndBrekpoints =
-    gDebugger.document.getElementById("stackframes+breakpoints");
-  let togglePanesButton =
-    gDebugger.document.getElementById("toggle-panes");
+function testInstrumentsPaneCollapse() {
+  let instrumentsPane =
+    gDebugger.document.getElementById("instruments-pane");
+  let instrumentsPaneToggleButton =
+    gDebugger.document.getElementById("instruments-pane-toggle");
 
-  let width = parseInt(stackframesAndBrekpoints.getAttribute("width"));
-  is(width, gDebugger.Prefs.stackframesWidth,
-    "The stackframes and breakpoints pane has an incorrect width.");
-  is(stackframesAndBrekpoints.style.marginLeft, "0px",
-    "The stackframes and breakpoints pane has an incorrect left margin.");
-  ok(!stackframesAndBrekpoints.hasAttribute("animated"),
-    "The stackframes and breakpoints pane has an incorrect animated attribute.");
-  ok(!togglePanesButton.getAttribute("panesHidden"),
-    "The stackframes and breakpoints pane should at this point be visible.");
+  let width = parseInt(instrumentsPane.getAttribute("width"));
+  is(width, gDebugger.Prefs.instrumentsWidth,
+    "The instruments pane has an incorrect width.");
+  is(instrumentsPane.style.marginLeft, "0px",
+    "The instruments pane has an incorrect left margin.");
+  is(instrumentsPane.style.marginRight, "0px",
+    "The instruments pane has an incorrect right margin.");
+  ok(!instrumentsPane.hasAttribute("animated"),
+    "The instruments pane has an incorrect animated attribute.");
+  ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
+    "The instruments pane should at this point be visible.");
 
-  gView.togglePanes({ visible: false, animated: true });
+  gView.toggleInstrumentsPane({ visible: false, animated: true });
 
   is(gDebugger.Prefs.panesVisibleOnStartup, false,
     "The debugger view panes should still initially be preffed as hidden.");
   isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
     "The options menu item should still not be checked.");
 
   let margin = -(width + 1) + "px";
-  is(width, gDebugger.Prefs.stackframesWidth,
-    "The stackframes and breakpoints pane has an incorrect width after collapsing.");
-  is(stackframesAndBrekpoints.style.marginLeft, margin,
-    "The stackframes and breakpoints pane has an incorrect left margin after collapsing.");
-  ok(stackframesAndBrekpoints.hasAttribute("animated"),
-    "The stackframes and breakpoints pane has an incorrect attribute after an animated collapsing.");
-  ok(togglePanesButton.hasAttribute("panesHidden"),
-    "The stackframes and breakpoints pane should not be visible after collapsing.");
+  is(width, gDebugger.Prefs.instrumentsWidth,
+    "The instruments pane has an incorrect width after collapsing.");
+  is(instrumentsPane.style.marginLeft, margin,
+    "The instruments pane has an incorrect left margin after collapsing.");
+  is(instrumentsPane.style.marginRight, margin,
+    "The instruments pane has an incorrect right margin after collapsing.");
+  ok(instrumentsPane.hasAttribute("animated"),
+    "The instruments pane has an incorrect attribute after an animated collapsing.");
+  ok(instrumentsPaneToggleButton.hasAttribute("toggled"),
+    "The instruments pane should not be visible after collapsing.");
 
-  gView.togglePanes({ visible: true, animated: false });
+  gView.toggleInstrumentsPane({ visible: true, animated: false });
 
   is(gDebugger.Prefs.panesVisibleOnStartup, false,
     "The debugger view panes should still initially be preffed as hidden.");
   isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
     "The options menu item should still not be checked.");
 
-  is(width, gDebugger.Prefs.stackframesWidth,
-    "The stackframes and breakpoints pane has an incorrect width after uncollapsing.");
-  is(stackframesAndBrekpoints.style.marginLeft, "0px",
-    "The stackframes and breakpoints pane has an incorrect left margin after uncollapsing.");
-  ok(!stackframesAndBrekpoints.hasAttribute("animated"),
-    "The stackframes and breakpoints pane has an incorrect attribute after an unanimated uncollapsing.");
-  ok(!togglePanesButton.getAttribute("panesHidden"),
-    "The stackframes and breakpoints pane should be visible again after uncollapsing.");
+  is(width, gDebugger.Prefs.instrumentsWidth,
+    "The instruments pane has an incorrect width after uncollapsing.");
+  is(instrumentsPane.style.marginLeft, "0px",
+    "The instruments pane has an incorrect left margin after uncollapsing.");
+  is(instrumentsPane.style.marginRight, "0px",
+    "The instruments pane has an incorrect right margin after uncollapsing.");
+  ok(!instrumentsPane.hasAttribute("animated"),
+    "The instruments pane has an incorrect attribute after an unanimated uncollapsing.");
+  ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
+    "The instruments pane should be visible again after uncollapsing.");
 }
 
-function testPaneCollapse2() {
-  let variablesAndExpressions =
-    gDebugger.document.getElementById("variables+expressions");
-  let togglePanesButton =
-    gDebugger.document.getElementById("toggle-panes");
-
-  let width = parseInt(variablesAndExpressions.getAttribute("width"));
-  is(width, gDebugger.Prefs.variablesWidth,
-    "The variables and expressions pane has an incorrect width.");
-  is(variablesAndExpressions.style.marginRight, "0px",
-    "The variables and expressions pane has an incorrect right margin.");
-  ok(!variablesAndExpressions.hasAttribute("animated"),
-    "The variables and expressions pane has an incorrect animated attribute.");
-  ok(!togglePanesButton.getAttribute("panesHidden"),
-    "The variables and expressions pane should at this point be visible.");
-
-  gView.togglePanes({ visible: false, animated: true });
-
-  is(gDebugger.Prefs.panesVisibleOnStartup, false,
-    "The debugger view panes should still initially be preffed as hidden.");
-  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
-    "The options menu item should still not be checked.");
-
-  let margin = -(width + 1) + "px";
-  is(width, gDebugger.Prefs.variablesWidth,
-    "The variables and expressions pane has an incorrect width after collapsing.");
-  is(variablesAndExpressions.style.marginRight, margin,
-    "The variables and expressions pane has an incorrect right margin after collapsing.");
-  ok(variablesAndExpressions.hasAttribute("animated"),
-    "The variables and expressions pane has an incorrect attribute after an animated collapsing.");
-  ok(togglePanesButton.hasAttribute("panesHidden"),
-    "The variables and expressions pane should not be visible after collapsing.");
-
-  gView.togglePanes({ visible: true, animated: false });
-
-  is(gDebugger.Prefs.panesVisibleOnStartup, false,
-    "The debugger view panes should still initially be preffed as hidden.");
-  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
-    "The options menu item should still not be checked.");
-
-  is(width, gDebugger.Prefs.variablesWidth,
-    "The variables and expressions pane has an incorrect width after uncollapsing.");
-  is(variablesAndExpressions.style.marginRight, "0px",
-    "The variables and expressions pane has an incorrect right margin after uncollapsing.");
-  ok(!variablesAndExpressions.hasAttribute("animated"),
-    "The variables and expressions pane has an incorrect attribute after an unanimated uncollapsing.");
-  ok(!togglePanesButton.getAttribute("panesHidden"),
-    "The variables and expressions pane should be visible again after uncollapsing.");
-}
-
-function testPanesStartupPref(aCallback) {
-  let stackframesAndBrekpoints =
-    gDebugger.document.getElementById("stackframes+breakpoints");
-  let variablesAndExpressions =
-    gDebugger.document.getElementById("variables+expressions");
-  let togglePanesButton =
-    gDebugger.document.getElementById("toggle-panes");
+function testPanesStartupPref() {
+  let instrumentsPane =
+    gDebugger.document.getElementById("instruments-pane");
+  let instrumentsPaneToggleButton =
+    gDebugger.document.getElementById("instruments-pane-toggle");
 
   is(gDebugger.Prefs.panesVisibleOnStartup, false,
     "The debugger view panes should still initially be preffed as hidden.");
 
-  ok(!togglePanesButton.getAttribute("panesHidden"),
-    "The debugger panes should at this point be visible.");
+  ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
+    "The debugger instruments pane should at this point be visible.");
   is(gDebugger.Prefs.panesVisibleOnStartup, false,
     "The debugger view panes should initially be preffed as hidden.");
   isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
     "The options menu item should still not be checked.");
 
   gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "true");
   gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
 
   executeSoon(function() {
-    ok(!togglePanesButton.getAttribute("panesHidden"),
-      "The debugger panes should at this point be visible.");
+    ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
+      "The debugger instruments pane should at this point be visible.");
     is(gDebugger.Prefs.panesVisibleOnStartup, true,
       "The debugger view panes should now be preffed as visible.");
     is(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
       "The options menu item should now be checked.");
 
     gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "false");
     gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
 
     executeSoon(function() {
-      ok(!togglePanesButton.getAttribute("panesHidden"),
-        "The debugger panes should at this point be visible.");
+      ok(!instrumentsPaneToggleButton.getAttribute("toggled"),
+        "The debugger instruments pane should at this point be visible.");
       is(gDebugger.Prefs.panesVisibleOnStartup, false,
         "The debugger view panes should now be preffed as hidden.");
       isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
         "The options menu item should now be unchecked.");
 
       executeSoon(function() {
-        aCallback();
+        closeDebuggerAndFinish();
       });
     });
   });
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
--- a/browser/devtools/debugger/test/browser_dbg_panesize-inner.js
+++ b/browser/devtools/debugger/test/browser_dbg_panesize-inner.js
@@ -11,65 +11,67 @@ function test() {
 
     ok(!gDevTools.getToolbox(target1),
       "Shouldn't have a debugger panel for this tab yet.");
 
     gDevTools.showToolbox(target1, "jsdebugger").then(function(toolbox) {
       let dbg = toolbox.getCurrentPanel();
       ok(dbg, "We should have a debugger panel.");
 
-      let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
-      let preferredBpw = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
+      let preferredSw = Services.prefs.getIntPref("devtools.debugger.ui.panes-sources-width");
+      let preferredIw = Services.prefs.getIntPref("devtools.debugger.ui.panes-instruments-width");
       let someWidth1, someWidth2;
 
       do {
         someWidth1 = parseInt(Math.random() * 200) + 100;
         someWidth2 = parseInt(Math.random() * 200) + 100;
-      } while (someWidth1 == preferredSfw ||
-               someWidth2 == preferredBpw)
+      } while (someWidth1 == preferredSw ||
+               someWidth2 == preferredIw)
 
       let someWidth1 = parseInt(Math.random() * 200) + 100;
       let someWidth2 = parseInt(Math.random() * 200) + 100;
 
-      info("Preferred stackframes width: " + preferredSfw);
-      info("Preferred variables width: " + preferredBpw);
-      info("Generated stackframes width: " + someWidth1);
-      info("Generated variables width: " + someWidth2);
+      info("Preferred sources width: " + preferredSw);
+      info("Preferred instruments width: " + preferredIw);
+      info("Generated sources width: " + someWidth1);
+      info("Generated instruments width: " + someWidth2);
 
       let content = dbg.panelWin;
-      let stackframes;
-      let variables;
+      let sources;
+      let instruments;
 
       wait_for_connect_and_resume(function() {
-        ok(content.Prefs.stackframesWidth,
-          "The debugger preferences should have a saved stackframesWidth value.");
-        ok(content.Prefs.variablesWidth,
-          "The debugger preferences should have a saved variablesWidth value.");
+        ok(content.Prefs.sourcesWidth,
+          "The debugger preferences should have a saved sourcesWidth value.");
+        ok(content.Prefs.instrumentsWidth,
+          "The debugger preferences should have a saved instrumentsWidth value.");
 
-        stackframes = content.document.getElementById("stackframes+breakpoints");
-        variables = content.document.getElementById("variables+expressions");
+        sources = content.document.getElementById("sources-pane");
+        instruments = content.document.getElementById("instruments-pane");
 
-        is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
-          "The stackframes pane width should be the same as the preferred value.");
-        is(content.Prefs.variablesWidth, variables.getAttribute("width"),
-          "The variables pane width should be the same as the preferred value.");
+        is(content.Prefs.sourcesWidth, sources.getAttribute("width"),
+          "The sources pane width should be the same as the preferred value.");
+        is(content.Prefs.instrumentsWidth, instruments.getAttribute("width"),
+          "The instruments pane width should be the same as the preferred value.");
 
-        stackframes.setAttribute("width", someWidth1);
-        variables.setAttribute("width", someWidth2);
+        sources.setAttribute("width", someWidth1);
+        instruments.setAttribute("width", someWidth2);
 
         removeTab(tab1);
       }, tab1);
 
       window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
         window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
 
-        is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
-          "The stackframes pane width should have been saved by now.");
-        is(content.Prefs.variablesWidth, variables.getAttribute("width"),
-          "The variables pane width should have been saved by now.");
+        is(content.Prefs.sourcesWidth, sources.getAttribute("width"),
+          "The sources pane width should have been saved by now.");
+        is(content.Prefs.instrumentsWidth, instruments.getAttribute("width"),
+          "The instruments pane width should have been saved by now.");
+
+        // Cleanup after ourselves!
+        Services.prefs.setIntPref("devtools.debugger.ui.panes-sources-width", preferredSw);
+        Services.prefs.setIntPref("devtools.debugger.ui.panes-instruments-width", preferredIw);
 
         finish();
-
       }, true);
     });
-
   });
 }
--- a/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
@@ -69,17 +69,17 @@ function testWithFrame()
           }
           is(count, 2, "B. Second Debugger:FetchedVariables event received.");
           gDebugger.removeEventListener("Debugger:FetchedVariables", testB, false);
           Services.tm.currentThread.dispatch({ run: function() {
 
             var frames = gDebugger.DebuggerView.StackFrames._container._list,
                 scopes = gDebugger.DebuggerView.Variables._list,
                 innerScope = scopes.firstChild,
-                innerNodes = innerScope.querySelector(".details").childNodes;
+                innerNodes = innerScope.querySelector(".variables-view-element-details").childNodes;
 
             is(gDebugger.DebuggerController.activeThread.state, "paused",
               "Should only be getting stack frames while paused.");
 
             is(frames.querySelectorAll(".dbg-stackframe").length, 1,
               "Should have one frame.");
 
             is(scopes.children.length, 3, "Should have 3 variable scopes.");
--- a/browser/devtools/debugger/test/browser_dbg_pause-warning.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-warning.js
@@ -3,29 +3,25 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var gPane = null;
 var gTab = null;
 var gDebugger = null;
 var gView = null;
-var gLH = null;
-var gL10N = null;
 var gToolbox = null;
 var gTarget = null;
 
 function test() {
   debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gView = gDebugger.DebuggerView;
-    gLH = gDebugger.LayoutHelpers;
-    gL10N = gDebugger.L10N;
 
     gTarget = TargetFactory.forTab(gBrowser.selectedTab);
     gToolbox = gDevTools.getToolbox(gTarget);
 
     testPause();
   });
 }
 
@@ -91,13 +87,11 @@ function testResume() {
 }
 
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebugger = null;
   gView = null;
-  gLH = null;
-  gL10N = null;
   gToolbox = null;
   gTarget = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js
@@ -56,37 +56,37 @@ function testlabelshortening() {
       { href: "http://some.address.com/random/", leaf: "suprandom/?a=1" },
       { href: "http://some.address.com/random/", leaf: "?a=1" },
       { href: "https://another.address.org/random/subrandom/", leaf: "page.html" },
 
       { href: "ftp://interesting.address.org/random/", leaf: "script.js" },
       { href: "ftp://interesting.address.com/random/", leaf: "script.js" },
       { href: "ftp://interesting.address.com/random/", leaf: "x/script.js" },
       { href: "ftp://interesting.address.com/random/", leaf: "x/y/script.js?a=1" },
-      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=1&b=2", dupe: true },
-      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=1&b=2&c=3", dupe: true },
-      { href: "ftp://interesting.address.com/random/", leaf: "x/y/script.js?a=2", dupe: true },
-      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=2&b=3", dupe: true },
-      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=2&b=3&c=4", dupe: true },
+      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=1&b=2" },
+      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=1&b=2&c=3" },
+      { href: "ftp://interesting.address.com/random/", leaf: "x/y/script.js?a=2" },
+      { href: "ftp://interesting.address.com/random/x/", leaf: "y/script.js?a=2&b=3" },
+      { href: "ftp://interesting.address.com/random/x/y/", leaf: "script.js?a=2&b=3&c=4" },
 
       { href: "file://random/", leaf: "script_t1.js&a=1&b=2&c=3" },
       { href: "file://random/", leaf: "script_t2_1.js#id" },
       { href: "file://random/", leaf: "script_t2_2.js?a" },
       { href: "file://random/", leaf: "script_t2_3.js&b" },
       { href: "resource://random/", leaf: "script_t3_1.js#id?a=1&b=2" },
       { href: "resource://random/", leaf: "script_t3_2.js?a=1&b=2#id" },
       { href: "resource://random/", leaf: "script_t3_3.js&a=1&b=2#id" },
 
       { href: nanana, leaf: "Batman!" + "{trim me, now and forevermore}" }
     ];
 
     urls.forEach(function(url) {
       executeSoon(function() {
         let loc = url.href + url.leaf;
-        vs.push(sv.getSourceLabel(loc, url.href), loc, { forced: true });
+        vs.push([sv.getSourceLabel(loc), loc], { forced: true });
       });
     });
 
     executeSoon(function() {
       info("Script labels:");
       info(vs.labels.toSource());
 
       info("Script locations:");
@@ -132,17 +132,17 @@ function testlabelshortening() {
       ok(vs.containsLabel("script_t3_2.js"),
         "Script (13) label is incorrect.");
       ok(vs.containsLabel("script_t3_3.js"),
         "Script (14) label is incorrect.");
 
       ok(vs.containsLabel(nanana + "Batman!" + ellipsis),
         "Script (15) label is incorrect.");
 
-      is(vs._container.itemCount, urls.filter(function(url) !url.dupe).length,
+      is(vs.itemCount, urls.filter(function(url) !url.dupe).length,
         "Didn't get the correct number of scripts in the list.");
 
       is(vs.getItemByValue("http://some.address.com/random/subrandom/").label, "random/subrandom/",
         "Scripts.getItemByValue isn't functioning properly (0).");
       is(vs.getItemByValue("http://some.address.com/random/suprandom/?a=1").label, "random/suprandom/?a=1",
         "Scripts.getItemByValue isn't functioning properly (1).");
 
       is(vs.getItemByLabel("random/subrandom/").value, "http://some.address.com/random/subrandom/",
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-02.js
@@ -29,17 +29,17 @@ function testSimpleCall() {
         "Should have created a scope.");
 
       is(testScope.id.substring(0, 4), "test",
         "The newly created scope should have the default id set.");
 
       is(testScope.target.querySelector(".name").getAttribute("value"), "test",
         "Any new scope should have the designated title.");
 
-      is(testScope.target.querySelector(".details").childNodes.length, 0,
+      is(testScope.target.querySelector(".variables-view-element-details").childNodes.length, 0,
         "Any new scope should have a container with no child nodes.");
 
       is(gDebugger.DebuggerView.Variables._list.childNodes.length, 3,
         "Should have 3 scopes created.");
 
 
       ok(!testScope.expanded,
         "Any new created scope should be initially collapsed.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-03.js
@@ -52,17 +52,17 @@ function testSimpleCall() {
         "Should have the correct variable name.");
 
       is(duplVar, null,
         "Shouldn't be able to duplicate variables in the same scope.");
 
       is(testVar.target.querySelector(".name").getAttribute("value"), "something",
         "Any new variable should have the designated title.");
 
-      is(testVar.target.querySelector(".details").childNodes.length, 0,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 0,
         "Any new variable should have a details container with no child nodes.");
 
 
       let properties = testVar.addProperties({ "child": { "value": { "type": "object",
                                                                      "class": "Object" } } });
 
 
       ok(!testVar.expanded,
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-04.js
@@ -27,40 +27,38 @@ function testSimpleCall() {
       let testVar = testScope.addVar("something");
 
       let properties = testVar.addProperties({
         "child": {
           "value": {
             "type": "object",
             "class": "Object"
           },
-
           "enumerable": true
         }
       });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 1,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 1,
         "A new detail node should have been added in the variable tree.");
 
       ok(testVar.get("child"),
         "The added detail property should be accessible from the variable.");
 
 
       let properties2 = testVar.get("child").addProperties({
         "grandchild": {
           "value": {
             "type": "object",
             "class": "Object"
           },
-
           "enumerable": true
         }
       });
 
-      is(testVar.get("child").target.querySelector(".details").childNodes.length, 1,
+      is(testVar.get("child").target.querySelector(".variables-view-element-details").childNodes.length, 1,
         "A new detail node should have been added in the variable tree.");
 
       ok(testVar.get("child").get("grandchild"),
         "The added detail property should be accessible from the variable.");
 
 
       gDebugger.DebuggerController.activeThread.resume(function() {
         closeDebuggerAndFinish();
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-05.js
@@ -26,57 +26,57 @@ function testSimpleCall() {
       let testScope = gDebugger.DebuggerView.Variables.addScope("test");
       let testVar = testScope.addVar("something");
 
       testVar.setGrip(1.618);
 
       is(testVar.target.querySelector(".value").getAttribute("value"), "1.618",
         "The grip information for the variable wasn't set correctly.");
 
-      is(testVar.target.querySelector(".details").childNodes.length, 0,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 0,
         "Adding a value property shouldn't add any new tree nodes.");
 
 
       testVar.setGrip({ "type": "object", "class": "Window" });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 0,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 0,
         "Adding type and class properties shouldn't add any new tree nodes.");
 
       is(testVar.target.querySelector(".value").getAttribute("value"), "[object Window]",
         "The information for the variable wasn't set correctly.");
 
 
       testVar.addProperties({ "helloWorld": { "value": "hello world", "enumerable": true } });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 1,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 1,
         "A new detail node should have been added in the variable tree.");
 
 
       testVar.addProperties({ "helloWorld": { "value": "hello jupiter", "enumerable": true } });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 1,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 1,
         "Shouldn't be able to duplicate nodes added in the variable tree.");
 
 
       testVar.addProperties({ "someProp0": { "value": "random string", "enumerable": true },
                               "someProp1": { "value": "another string", "enumerable": true } });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 3,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 3,
         "Two new detail nodes should have been added in the variable tree.");
 
 
       testVar.addProperties({ "someProp2": { "value": { "type": "null" }, "enumerable": true },
                               "someProp3": { "value": { "type": "undefined" }, "enumerable": true },
                               "someProp4": {
                                 "value": { "type": "object", "class": "Object" },
                                 "enumerable": true
                               }
                             });
 
-      is(testVar.target.querySelector(".details").childNodes.length, 6,
+      is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 6,
         "Three new detail nodes should have been added in the variable tree.");
 
 
       gDebugger.DebuggerController.activeThread.resume(function() {
         closeDebuggerAndFinish();
       });
     }}, 0);
   });
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js
@@ -93,20 +93,20 @@ function testSimpleCall() {
 
       for each (let elt in localScope.target.querySelector(".nonenum").childNodes) {
         info("localScope :: " + { id: elt.id, className: elt.className }.toSource());
       }
       is(localScope.target.querySelector(".nonenum").childNodes.length, 6,
         "The localScope doesn't contain all the created variable elements.");
 
 
-      is(localVar5.target.querySelector(".details").childNodes.length, 6,
+      is(localVar5.target.querySelector(".variables-view-element-details").childNodes.length, 6,
         "The localVar5 doesn't contain all the created properties.");
 
-      is(localVar5.get("someProp5").target.querySelector(".details").childNodes.length, 6,
+      is(localVar5.get("someProp5").target.querySelector(".variables-view-element-details").childNodes.length, 6,
         "The localVar5.someProp5 doesn't contain all the created properties.");
 
 
       is(windowVar.target.querySelector(".value").getAttribute("value"), "[object Window]",
         "The grip information for the windowVar wasn't set correctly.");
 
       is(documentVar.target.querySelector(".value").getAttribute("value"), "[object HTMLDocument]",
         "The grip information for the documentVar wasn't set correctly.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -25,19 +25,18 @@ function test()
 
 function testFrameParameters()
 {
   gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       var frames = gDebugger.DebuggerView.StackFrames._container._list,
-          childNodes = frames.childNodes,
-          localScope = gDebugger.DebuggerView.Variables._list.querySelector(".scope"),
-          localNodes = localScope.querySelector(".details").childNodes;
+          localScope = gDebugger.DebuggerView.Variables._list.querySelector(".variables-view-scope"),
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
       is(localNodes.length, 12,
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -25,18 +25,18 @@ function test()
 
 function testFrameParameters()
 {
   gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       var frames = gDebugger.DebuggerView.StackFrames._container._list,
-          localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[0],
-          localNodes = localScope.querySelector(".details").childNodes,
+          localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[0],
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
           localNonEnums = localScope.querySelector(".nonenum").childNodes;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
@@ -49,33 +49,33 @@ function testFrameParameters()
         "Should have the right property value for 'arguments'.");
       is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
         "Should have the right property value for 'c'.");
 
 
       let gVars = gDebugger.DebuggerView.Variables;
 
       is(gVars.getScopeForNode(
-         gVars._list.querySelectorAll(".scope")[0]).target,
-         gVars._list.querySelectorAll(".scope")[0],
+         gVars._list.querySelectorAll(".variables-view-scope")[0]).target,
+         gVars._list.querySelectorAll(".variables-view-scope")[0],
         "getScopeForNode([0]) didn't return the expected scope.");
       is(gVars.getScopeForNode(
-         gVars._list.querySelectorAll(".scope")[1]).target,
-         gVars._list.querySelectorAll(".scope")[1],
+         gVars._list.querySelectorAll(".variables-view-scope")[1]).target,
+         gVars._list.querySelectorAll(".variables-view-scope")[1],
         "getScopeForNode([1]) didn't return the expected scope.");
       is(gVars.getScopeForNode(
-         gVars._list.querySelectorAll(".scope")[2]).target,
-         gVars._list.querySelectorAll(".scope")[2],
+         gVars._list.querySelectorAll(".variables-view-scope")[2]).target,
+         gVars._list.querySelectorAll(".variables-view-scope")[2],
         "getScopeForNode([2]) didn't return the expected scope.");
 
-      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".scope")[0]).expanded, true,
+      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".variables-view-scope")[0]).expanded, true,
         "The local scope should be expanded by default.");
-      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".scope")[1]).expanded, false,
+      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".variables-view-scope")[1]).expanded, false,
         "The block scope should be collapsed by default.");
-      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".scope")[2]).expanded, false,
+      is(gVars.getScopeForNode(gVars._list.querySelectorAll(".variables-view-scope")[2]).expanded, false,
         "The global scope should be collapsed by default.");
 
 
       let thisNode = gVars.getItemForNode(localNodes[0]);
       let argumentsNode = gVars.getItemForNode(localNodes[8]);
       let cNode = gVars.getItemForNode(localNodes[10]);
 
       is(thisNode.expanded, false,
@@ -134,86 +134,86 @@ function testFrameParameters()
            .getAttribute("value").search(/object/) != -1,
           "'document' should be an object.");
 
 
         is(argumentsNode.target.querySelector(".value")
            .getAttribute("value"), "[object Arguments]",
           "Should have the right property value for 'arguments'.");
 
-        is(argumentsNode.target.querySelectorAll(".property > .title > .name")[0]
+        is(argumentsNode.target.querySelectorAll(".variables-view-property > .title > .name")[0]
            .getAttribute("value"), "0",
           "Should have the right property name for 'arguments[0]'.");
-        ok(argumentsNode.target.querySelectorAll(".property > .title > .value")[0]
+        ok(argumentsNode.target.querySelectorAll(".variables-view-property > .title > .value")[0]
            .getAttribute("value").search(/object/) != -1,
           "'arguments[0]' should be an object.");
 
-        is(argumentsNode.target.querySelectorAll(".property > .title > .name")[7]
+        is(argumentsNode.target.querySelectorAll(".variables-view-property > .title > .name")[7]
            .getAttribute("value"), "__proto__",
           "Should have the right property name for '__proto__'.");
-        ok(argumentsNode.target.querySelectorAll(".property > .title > .value")[7]
+        ok(argumentsNode.target.querySelectorAll(".variables-view-property > .title > .value")[7]
            .getAttribute("value").search(/object/) != -1,
           "'__proto__' should be an object.");
 
 
         is(cNode.target.querySelector(".value")
            .getAttribute("value"), "[object Object]",
           "Should have the right property value for 'c'.");
 
-        is(cNode.target.querySelectorAll(".property > .title > .name")[0]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .name")[0]
            .getAttribute("value"), "a",
           "Should have the right property name for 'c.a'.");
-        is(cNode.target.querySelectorAll(".property > .title > .value")[0]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .value")[0]
            .getAttribute("value"), "1",
           "Should have the right value for 'c.a'.");
 
-        is(cNode.target.querySelectorAll(".property > .title > .name")[1]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .name")[1]
            .getAttribute("value"), "b",
           "Should have the right property name for 'c.b'.");
-        is(cNode.target.querySelectorAll(".property > .title > .value")[1]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .value")[1]
            .getAttribute("value"), "\"beta\"",
           "Should have the right value for 'c.b'.");
 
-        is(cNode.target.querySelectorAll(".property > .title > .name")[2]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .name")[2]
            .getAttribute("value"), "c",
           "Should have the right property name for 'c.c'.");
-        is(cNode.target.querySelectorAll(".property > .title > .value")[2]
+        is(cNode.target.querySelectorAll(".variables-view-property > .title > .value")[2]
            .getAttribute("value"), "true",
           "Should have the right value for 'c.c'.");
 
 
         is(gVars.getItemForNode(
-           cNode.target.querySelectorAll(".property")[0]).target,
-           cNode.target.querySelectorAll(".property")[0],
+           cNode.target.querySelectorAll(".variables-view-property")[0]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[0],
           "getItemForNode([0]) didn't return the expected property.");
 
         is(gVars.getItemForNode(
-           cNode.target.querySelectorAll(".property")[1]).target,
-           cNode.target.querySelectorAll(".property")[1],
+           cNode.target.querySelectorAll(".variables-view-property")[1]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[1],
           "getItemForNode([1]) didn't return the expected property.");
 
         is(gVars.getItemForNode(
-           cNode.target.querySelectorAll(".property")[2]).target,
-           cNode.target.querySelectorAll(".property")[2],
+           cNode.target.querySelectorAll(".variables-view-property")[2]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[2],
           "getItemForNode([2]) didn't return the expected property.");
 
 
         is(cNode.find(
-           cNode.target.querySelectorAll(".property")[0]).target,
-           cNode.target.querySelectorAll(".property")[0],
+           cNode.target.querySelectorAll(".variables-view-property")[0]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[0],
           "find([0]) didn't return the expected property.");
 
         is(cNode.find(
-           cNode.target.querySelectorAll(".property")[1]).target,
-           cNode.target.querySelectorAll(".property")[1],
+           cNode.target.querySelectorAll(".variables-view-property")[1]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[1],
           "find([1]) didn't return the expected property.");
 
         is(cNode.find(
-           cNode.target.querySelectorAll(".property")[2]).target,
-           cNode.target.querySelectorAll(".property")[2],
+           cNode.target.querySelectorAll(".variables-view-property")[2]).target,
+           cNode.target.querySelectorAll(".variables-view-property")[2],
           "find([2]) didn't return the expected property.");
 
 
         resumeAndFinish();
       }, 100);
     }}, 0);
   }, false);
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-09.js
@@ -36,18 +36,18 @@ function testFrameParameters()
     if (++count < 2) {
       info("Number of received Debugger:FetchedVariables events: " + count);
       return;
     }
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       var frames = gDebugger.DebuggerView.StackFrames._container._list,
-          globalScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[2],
-          globalNodes = globalScope.querySelector(".details").childNodes;
+          globalScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[2],
+          globalNodes = globalScope.querySelector(".variables-view-element-details").childNodes;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 3,
         "Should have three frames.");
 
       is(globalNodes[0].querySelector(".name").getAttribute("value"), "InstallTrigger",
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-10.js
@@ -37,20 +37,20 @@ function testWithFrame()
       info("Number of received Debugger:FetchedVariables events: " + count);
       return;
     }
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       var frames = gDebugger.DebuggerView.StackFrames._container._list,
           scopes = gDebugger.DebuggerView.Variables._list,
-          innerScope = scopes.querySelectorAll(".scope")[0],
-          globalScope = scopes.querySelectorAll(".scope")[4],
-          innerNodes = innerScope.querySelector(".details").childNodes,
-          globalNodes = globalScope.querySelector(".details").childNodes;
+          innerScope = scopes.querySelectorAll(".variables-view-scope")[0],
+          globalScope = scopes.querySelectorAll(".variables-view-scope")[4],
+          innerNodes = innerScope.querySelector(".variables-view-element-details").childNodes,
+          globalNodes = globalScope.querySelector(".variables-view-element-details").childNodes;
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(frames.querySelectorAll(".dbg-stackframe").length, 2,
         "Should have three frames.");
 
       is(scopes.childNodes.length, 5, "Should have 5 variable scopes.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-11.js
@@ -34,20 +34,20 @@ function testFrameParameters()
     // scope and the regular one.
     if (++count < 2) {
       info("Number of received Debugger:FetchedVariables events: " + count);
       return;
     }
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
-      let anonymousScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[1],
-          globalScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[2],
-          anonymousNodes = anonymousScope.querySelector(".details").childNodes,
-          globalNodes = globalScope.querySelector(".details").childNodes,
+      let anonymousScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[1],
+          globalScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[2],
+          anonymousNodes = anonymousScope.querySelector(".variables-view-element-details").childNodes,
+          globalNodes = globalScope.querySelector(".variables-view-element-details").childNodes,
           gVars = gDebugger.DebuggerView.Variables;
 
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
       is(anonymousNodes[1].querySelector(".name").getAttribute("value"), "button",
         "Should have the right property name for |button|.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data-big.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data-big.js
@@ -38,21 +38,21 @@ function testWithFrame()
     if (++count < 2) {
       info("Number of received Debugger:FetchedVariables events: " + count);
       return;
     }
     gDebugger.removeEventListener("Debugger:FetchedVariables", test1, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       var scopes = gDebugger.DebuggerView.Variables._list,
-          innerScope = scopes.querySelectorAll(".scope")[0],
-          loadScope = scopes.querySelectorAll(".scope")[1],
-          globalScope = scopes.querySelectorAll(".scope")[2],
-          innerNodes = innerScope.querySelector(".details").childNodes,
-          arrayNodes = innerNodes[4].querySelector(".details").childNodes;
+          innerScope = scopes.querySelectorAll(".variables-view-scope")[0],
+          loadScope = scopes.querySelectorAll(".variables-view-scope")[1],
+          globalScope = scopes.querySelectorAll(".variables-view-scope")[2],
+          innerNodes = innerScope.querySelector(".variables-view-element-details").childNodes,
+          arrayNodes = innerNodes[4].querySelector(".variables-view-element-details").childNodes;
 
       is(innerNodes[3].querySelector(".name").getAttribute("value"), "buffer",
         "Should have the right property name for |buffer|.");
 
       is(innerNodes[3].querySelector(".value").getAttribute("value"), "[object ArrayBuffer]",
         "Should have the right property value for |buffer|.");
 
       is(innerNodes[4].querySelector(".name").getAttribute("value"), "z",
@@ -110,19 +110,19 @@ function testWithFrame()
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
     content.window);
 }
 
 function waitForProperties(total, callbacks)
 {
   var scopes = gDebugger.DebuggerView.Variables._list,
-      innerScope = scopes.querySelectorAll(".scope")[0],
-      innerNodes = innerScope.querySelector(".details").childNodes,
-      arrayNodes = innerNodes[4].querySelector(".details").childNodes;
+      innerScope = scopes.querySelectorAll(".variables-view-scope")[0],
+      innerNodes = innerScope.querySelector(".variables-view-element-details").childNodes,
+      arrayNodes = innerNodes[4].querySelector(".variables-view-element-details").childNodes;
 
   // Poll every few milliseconds until the properties are retrieved.
   let count = 0;
   let intervalID = window.setInterval(function() {
     info("count: " + count + " ");
     if (++count > total) {
       ok(false, "Timed out while polling for the properties.");
       window.clearInterval(intervalID);
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data-getset-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data-getset-01.js
@@ -218,18 +218,18 @@ function addWatchExpressions(callback)
   });
 
   gWatch.addExpression("myVar.prop");
   gDebugger.editor.focus();
 }
 
 function testEdit(what, string, callback, expected)
 {
-  let localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[1],
-      localNodes = localScope.querySelector(".details").childNodes,
+  let localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[1],
+      localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
       myVar = gVars.getItemForNode(localNodes[11]);
 
   waitForProperties(function() {
     let prop = myVar.get("prop");
     let getterOrSetter = (what != "self" ? prop.get(what) : prop);
 
     EventUtils.sendMouseEvent({ type: "mousedown" },
       getterOrSetter._target.querySelector(".title > .value"),
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data-getset-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data-getset-02.js
@@ -76,18 +76,18 @@ function addWatchExpressions(callback)
   });
 
   gWatch.addExpression("myVar.prop");
   gDebugger.editor.focus();
 }
 
 function testEdit(string, expected, callback)
 {
-  let localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[1],
-      localNodes = localScope.querySelector(".details").childNodes,
+  let localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[1],
+      localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
       myVar = gVars.getItemForNode(localNodes[11]);
 
   waitForProperties(function() {
     let prop = myVar.get("prop");
 
     is(prop.ownerView.name, "myVar",
       "The right owner property name wasn't found.");
     is(prop.name, "prop",
@@ -103,17 +103,17 @@ function testEdit(string, expected, call
     is(prop.value, undefined,
       "The right property value wasn't found.");
     ok(prop.getter,
       "The right property getter wasn't found.");
     ok(prop.setter,
       "The right property setter wasn't found.");
 
     EventUtils.sendMouseEvent({ type: "mousedown" },
-      prop._target.querySelector(".dbg-variable-edit"),
+      prop._target.querySelector(".variables-view-edit"),
       gDebugger);
 
     waitForElement(".element-value-input", true, function() {
       waitForWatchExpressions(function() {
         let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel");
         let scope = gVars._currHierarchy.get(label);
 
         let expr = scope.get("myVar.prop");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
@@ -16,17 +16,17 @@ var gVariable = null;
 function test()
 {
   debug_tab_pane(TAB1_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gVariablesView = gDebugger.DebuggerView.Variables;
 
-    gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });
+    gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
     testVariablesView();
   });
 }
 
 function testVariablesView()
 {
   let arr = [
     42,
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-edit-value.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-edit-value.js
@@ -10,17 +10,17 @@
 
 const TAB_URL = EXAMPLE_URL + "browser_dbg_frame-parameters.html";
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 
-requestLongerTimeout(2);
+requestLongerTimeout(3);
 
 function test() {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
 
@@ -33,18 +33,18 @@ function test() {
 function testFrameEval() {
   gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
     gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
-      var localScope = gDebugger.DebuggerView.Variables._list.querySelector(".scope"),
-          localNodes = localScope.querySelector(".details").childNodes,
+      var localScope = gDebugger.DebuggerView.Variables._list.querySelector(".variables-view-scope"),
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
           varA = localNodes[7];
 
       is(varA.querySelector(".name").getAttribute("value"), "a",
         "Should have the right name for 'a'.");
 
       is(varA.querySelector(".value").getAttribute("value"), 1,
         "Should have the right initial value for 'a'.");
 
@@ -83,18 +83,18 @@ function testModification(aVar, aCallbac
       // object scope and the regular one.
       if (++count < 2) {
         info("Number of received Debugger:FetchedVariables events: " + count);
         return;
       }
       gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
       // Get the variable reference anew, since the old ones were discarded when
       // we resumed.
-      var localScope = gDebugger.DebuggerView.Variables._list.querySelector(".scope"),
-          localNodes = localScope.querySelector(".details").childNodes,
+      var localScope = gDebugger.DebuggerView.Variables._list.querySelector(".variables-view-scope"),
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
           varA = localNodes[7];
 
       is(varA.querySelector(".value").getAttribute("value"), aNewResult,
         "Should have the right value for 'a'.");
 
       executeSoon(function() {
         aCallback(varA);
       });
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-edit-watch.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-edit-watch.js
@@ -12,17 +12,17 @@ const TAB_URL = EXAMPLE_URL + "browser_d
 
 var gPane = null;
 var gTab = null;
 var gDebuggee = null;
 var gDebugger = null;
 var gWatch = null;
 var gVars = null;
 
-requestLongerTimeout(2);
+requestLongerTimeout(3);
 
 function test() {
   debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.panelWin;
     gWatch = gDebugger.DebuggerView.WatchExpressions;
@@ -37,18 +37,18 @@ function test() {
 function testFrameEval() {
   gDebugger.addEventListener("Debugger:FetchedWatchExpressions", function test() {
     gDebugger.removeEventListener("Debugger:FetchedWatchExpressions", test, false);
     Services.tm.currentThread.dispatch({ run: function() {
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should only be getting stack frames while paused.");
 
-      var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[1],
-          localNodes = localScope.querySelector(".details").childNodes,
+      var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[1],
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
           aArg = localNodes[1],
           varT = localNodes[3];
 
       is(aArg.querySelector(".name").getAttribute("value"), "aArg",
         "Should have the right name for 'aArg'.");
       is(varT.querySelector(".name").getAttribute("value"), "t",
         "Should have the right name for 't'.");
 
@@ -65,59 +65,59 @@ function testFrameEval() {
       let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel");
       let scope = gVars._currHierarchy.get(label);
 
       ok(scope, "There should be a wach expressions scope in the variables view");
       is(scope._store.size, 5, "There should be 5 evaluations availalble");
 
       is(scope.get("this")._isContentVisible, true,
         "Should have the right visibility state for 'this'.");
-      is(scope.get("this").target.querySelectorAll(".dbg-variable-delete").length, 1,
+      is(scope.get("this").target.querySelectorAll(".variables-view-delete").length, 1,
         "Should have the one close button visible for 'this'.");
       is(scope.get("this").name, "this",
         "Should have the right name for 'this'.");
       is(scope.get("this").value.type, "object",
         "Should have the right value type for 'this'.");
       is(scope.get("this").value.class, "Proxy",
         "Should have the right value type for 'this'.");
 
       is(scope.get("ermahgerd")._isContentVisible, true,
         "Should have the right visibility state for 'ermahgerd'.");
-      is(scope.get("ermahgerd").target.querySelectorAll(".dbg-variable-delete").length, 1,
+      is(scope.get("ermahgerd").target.querySelectorAll(".variables-view-delete").length, 1,
         "Should have the one close button visible for 'ermahgerd'.");
       is(scope.get("ermahgerd").name, "ermahgerd",
         "Should have the right name for 'ermahgerd'.");
       is(scope.get("ermahgerd").value.type, "object",
         "Should have the right value type for 'ermahgerd'.");
       is(scope.get("ermahgerd").value.class, "Function",
         "Should have the right value type for 'ermahgerd'.");
 
       is(scope.get("aArg")._isContentVisible, true,
         "Should have the right visibility state for 'aArg'.");
-      is(scope.get("aArg").target.querySelectorAll(".dbg-variable-delete").length, 1,
+      is(scope.get("aArg").target.querySelectorAll(".variables-view-delete").length, 1,
         "Should have the one close button visible for 'aArg'.");
       is(scope.get("aArg").name, "aArg",
         "Should have the right name for 'aArg'.");
       is(scope.get("aArg").value, undefined,
         "Should have the right value for 'aArg'.");
 
       is(scope.get("document.title")._isContentVisible, true,
         "Should have the right visibility state for 'document.title'.");
-      is(scope.get("document.title").target.querySelectorAll(".dbg-variable-delete").length, 1,
+      is(scope.get("document.title").target.querySelectorAll(".variables-view-delete").length, 1,
         "Should have the one close button visible for 'document.title'.");
       is(scope.get("document.title").name, "document.title",
         "Should have the right name for 'document.title'.");
       is(scope.get("document.title").value, "42",
         "Should have the right value for 'document.title'.");
       is(typeof scope.get("document.title").value, "string",
         "Should have the right value type for 'document.title'.");
 
       is(scope.get("document.title = 42")._isContentVisible, true,
         "Should have the right visibility state for 'document.title = 42'.");
-      is(scope.get("document.title = 42").target.querySelectorAll(".dbg-variable-delete").length, 1,
+      is(scope.get("document.title = 42").target.querySelectorAll(".variables-view-delete").length, 1,
         "Should have the one close button visible for 'document.title = 42'.");
       is(scope.get("document.title = 42").name, "document.title = 42",
         "Should have the right name for 'document.title = 42'.");
       is(scope.get("document.title = 42").value, 42,
         "Should have the right value for 'document.title = 42'.");
       is(typeof scope.get("document.title = 42").value, "number",
         "Should have the right value type for 'document.title = 42'.");
 
@@ -199,18 +199,18 @@ function testModification(aVar, aTest, a
     function continueTest() {
       if (testContinued || !fetchedVariables || !fetchedExpressions) {
         return;
       }
       testContinued = true;
 
       // Get the variable reference anew, since the old ones were discarded when
       // we resumed.
-      var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[aLocalScopeIndex],
-          localNodes = localScope.querySelector(".details").childNodes,
+      var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[aLocalScopeIndex],
+          localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
           aArg = localNodes[1];
 
       is(aArg.querySelector(".value").getAttribute("value"), aArgResult,
         "Should have the right value for 'aArg'.");
 
       let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel");
       let scope = gVars._currHierarchy.get(label);
       info("Found the watch expressions scope: " + scope);
@@ -281,18 +281,18 @@ function testExprDeletion(aVar, aTest, a
   function continueTest() {
     if ((testContinued || !fetchedVariables || !fetchedExpressions) && !aFinalFlag) {
       return;
     }
     testContinued = true;
 
     // Get the variable reference anew, since the old ones were discarded when
     // we resumed.
-    var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".scope")[aLocalScopeIndex],
-        localNodes = localScope.querySelector(".details").childNodes,
+    var localScope = gDebugger.DebuggerView.Variables._list.querySelectorAll(".variables-view-scope")[aLocalScopeIndex],
+        localNodes = localScope.querySelector(".variables-view-element-details").childNodes,
         aArg = localNodes[1];
 
     is(aArg.querySelector(".value").getAttribute("value"), aArgResult,
       "Should have the right value for 'aArg'.");
 
     let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel");
     let scope = gVars._currHierarchy.get(label);
     info("Found the watch expressions scope: " + scope);
@@ -320,161 +320,161 @@ function testExprDeletion(aVar, aTest, a
   }
 
   if (aRemoveAllFlag) {
     gWatch._onCmdRemoveAllExpressions();
     return;
   }
 
   EventUtils.sendMouseEvent({ type: "click" },
-    aVar.querySelector(".dbg-variable-delete"),
+    aVar.querySelector(".variables-view-delete"),
     gDebugger);
 }
 
 function test1(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 5,
     "There should be 5 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 5, "There should be 5 evaluations availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "document.title = 43",
+  is(gWatch._cache[0].attachment.inputNode.value, "document.title = 43",
     "The first textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "document.title = 43",
     "The first textbox input value is not the correct one");
-  is(gWatch._cache[1].target.inputNode.value, "document.title",
+  is(gWatch._cache[1].attachment.inputNode.value, "document.title",
     "The second textbox input value is not the correct one");
   is(gWatch._cache[1].attachment.currentExpression, "document.title",
     "The second textbox input value is not the correct one");
-  is(gWatch._cache[2].target.inputNode.value, "aArg",
+  is(gWatch._cache[2].attachment.inputNode.value, "aArg",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[2].attachment.currentExpression, "aArg",
     "The third textbox input value is not the correct one");
-  is(gWatch._cache[3].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[3].attachment.inputNode.value, "ermahgerd",
     "The fourth textbox input value is not the correct one");
   is(gWatch._cache[3].attachment.currentExpression, "ermahgerd",
     "The fourth textbox input value is not the correct one");
-  is(gWatch._cache[4].target.inputNode.value, "this",
+  is(gWatch._cache[4].attachment.inputNode.value, "this",
     "The fifth textbox input value is not the correct one");
   is(gWatch._cache[4].attachment.currentExpression, "this",
     "The fifth textbox input value is not the correct one");
 }
 
 function test2(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 5,
     "There should be 5 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 5, "There should be 5 evaluations availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "document.title = 43",
+  is(gWatch._cache[0].attachment.inputNode.value, "document.title = 43",
     "The first textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "document.title = 43",
     "The first textbox input value is not the correct one");
-  is(gWatch._cache[1].target.inputNode.value, "document.title",
+  is(gWatch._cache[1].attachment.inputNode.value, "document.title",
     "The second textbox input value is not the correct one");
   is(gWatch._cache[1].attachment.currentExpression, "document.title",
     "The second textbox input value is not the correct one");
-  is(gWatch._cache[2].target.inputNode.value, "aArg = 44",
+  is(gWatch._cache[2].attachment.inputNode.value, "aArg = 44",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[2].attachment.currentExpression, "aArg = 44",
     "The third textbox input value is not the correct one");
-  is(gWatch._cache[3].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[3].attachment.inputNode.value, "ermahgerd",
     "The fourth textbox input value is not the correct one");
   is(gWatch._cache[3].attachment.currentExpression, "ermahgerd",
     "The fourth textbox input value is not the correct one");
-  is(gWatch._cache[4].target.inputNode.value, "this",
+  is(gWatch._cache[4].attachment.inputNode.value, "this",
     "The fifth textbox input value is not the correct one");
   is(gWatch._cache[4].attachment.currentExpression, "this",
     "The fifth textbox input value is not the correct one");
 }
 
 function test3(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 4,
     "There should be 4 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 4, "There should be 4 evaluations availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "document.title = 43",
+  is(gWatch._cache[0].attachment.inputNode.value, "document.title = 43",
     "The first textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "document.title = 43",
     "The first textbox input value is not the correct one");
-  is(gWatch._cache[1].target.inputNode.value, "document.title",
+  is(gWatch._cache[1].attachment.inputNode.value, "document.title",
     "The second textbox input value is not the correct one");
   is(gWatch._cache[1].attachment.currentExpression, "document.title",
     "The second textbox input value is not the correct one");
-  is(gWatch._cache[2].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[2].attachment.inputNode.value, "ermahgerd",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[2].attachment.currentExpression, "ermahgerd",
     "The third textbox input value is not the correct one");
-  is(gWatch._cache[3].target.inputNode.value, "this",
+  is(gWatch._cache[3].attachment.inputNode.value, "this",
     "The fourth textbox input value is not the correct one");
   is(gWatch._cache[3].attachment.currentExpression, "this",
     "The fourth textbox input value is not the correct one");
 }
 
 function test4(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 3,
     "There should be 3 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 3, "There should be 3 evaluations availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "document.title",
+  is(gWatch._cache[0].attachment.inputNode.value, "document.title",
     "The first textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "document.title",
     "The first textbox input value is not the correct one");
-  is(gWatch._cache[1].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[1].attachment.inputNode.value, "ermahgerd",
     "The second textbox input value is not the correct one");
   is(gWatch._cache[1].attachment.currentExpression, "ermahgerd",
     "The second textbox input value is not the correct one");
-  is(gWatch._cache[2].target.inputNode.value, "this",
+  is(gWatch._cache[2].attachment.inputNode.value, "this",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[2].attachment.currentExpression, "this",
     "The third textbox input value is not the correct one");
 }
 
 function test5(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 2,
     "There should be 2 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 2, "There should be 2 evaluations availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[0].attachment.inputNode.value, "ermahgerd",
     "The second textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "ermahgerd",
     "The second textbox input value is not the correct one");
-  is(gWatch._cache[1].target.inputNode.value, "this",
+  is(gWatch._cache[1].attachment.inputNode.value, "this",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[1].attachment.currentExpression, "this",
     "The third textbox input value is not the correct one");
 }
 
 function test6(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").length, 1,
     "There should be 1 hidden nodes in the watch expressions container");
   is(gWatch._container._parent.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0,
     "There should be 0 visible nodes in the watch expressions container");
 
   ok(scope, "There should be a wach expressions scope in the variables view");
   is(scope._store.size, 1, "There should be 1 evaluation availalble");
 
-  is(gWatch._cache[0].target.inputNode.value, "ermahgerd",
+  is(gWatch._cache[0].attachment.inputNode.value, "ermahgerd",
     "The third textbox input value is not the correct one");
   is(gWatch._cache[0].attachment.currentExpression, "ermahgerd",
     "The third textbox input value is not the correct one");
 }
 
 function test7(scope) {
   is(gWatch._container._parent.querySelectorAll(".dbg-expression[hidden=true]").leng