Backout 175e66ebdb05 (bug 1077444) for dt2 orange
authorWes Kocher <wkocher@mozilla.com>
Fri, 09 Jan 2015 14:00:31 -0800
changeset 249032 2c169c448081ad0ba4911e3d5c5851a3f2d3b581
parent 249031 ba0cafaf462db8a9816c64eb9b21be4f7e7cb5eb
child 249033 1d30c40f6e7a97f2c49acdd0173916346a46ec7f
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1077444
milestone37.0a1
backs out175e66ebdb0559429b257074384282161a41d457
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout 175e66ebdb05 (bug 1077444) for dt2 orange
browser/devtools/shared/moz.build
browser/devtools/shared/test/browser.ini
browser/devtools/shared/test/browser_flame-graph-01.js
browser/devtools/shared/test/browser_flame-graph-02.js
browser/devtools/shared/test/browser_flame-graph-03.js
browser/devtools/shared/test/browser_flame-graph-04.js
browser/devtools/shared/widgets/FlameGraph.jsm
browser/devtools/shared/widgets/Graphs.jsm
--- a/browser/devtools/shared/moz.build
+++ b/browser/devtools/shared/moz.build
@@ -17,17 +17,16 @@ EXTRA_JS_MODULES.devtools += [
     'Parser.jsm',
     'SplitView.jsm',
 ]
 
 EXTRA_JS_MODULES.devtools += [
     'widgets/AbstractTreeItem.jsm',
     'widgets/BreadcrumbsWidget.jsm',
     'widgets/Chart.jsm',
-    'widgets/FlameGraph.jsm',
     'widgets/Graphs.jsm',
     'widgets/GraphsWorker.js',
     'widgets/SideMenuWidget.jsm',
     'widgets/SimpleListWidget.jsm',
     'widgets/VariablesView.jsm',
     'widgets/VariablesViewController.jsm',
     'widgets/ViewHelpers.jsm',
 ]
--- a/browser/devtools/shared/test/browser.ini
+++ b/browser/devtools/shared/test/browser.ini
@@ -10,20 +10,16 @@ support-files =
   browser_toolbar_webconsole_errors_count.html
   head.js
   leakhunt.js
 
 [browser_css_color.js]
 [browser_cubic-bezier-01.js]
 [browser_cubic-bezier-02.js]
 [browser_cubic-bezier-03.js]
-[browser_flame-graph-01.js]
-[browser_flame-graph-02.js]
-[browser_flame-graph-03.js]
-[browser_flame-graph-04.js]
 [browser_graphs-01.js]
 [browser_graphs-02.js]
 [browser_graphs-03.js]
 [browser_graphs-04.js]
 [browser_graphs-05.js]
 [browser_graphs-06.js]
 [browser_graphs-07a.js]
 [browser_graphs-07b.js]
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_flame-graph-01.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that flame graph widget works properly.
-
-let {FlameGraph} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
-let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  doc.body.setAttribute("style", "position: fixed; width: 100%; height: 100%; margin: 0;");
-
-  let graph = new FlameGraph(doc.body);
-
-  let readyEventEmitted;
-  graph.once("ready", () => readyEventEmitted = true);
-
-  yield graph.ready();
-  ok(readyEventEmitted, "The 'ready' event should have been emitted");
-
-  testGraph(host, graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function testGraph(host, graph) {
-  ok(graph._container.classList.contains("flame-graph-widget-container"),
-    "The correct graph container was created.");
-  ok(graph._canvas.classList.contains("flame-graph-widget-canvas"),
-    "The correct graph container was created.");
-
-  let bounds = host.frame.getBoundingClientRect();
-
-  is(graph.width, bounds.width * window.devicePixelRatio,
-    "The graph has the correct width.");
-  is(graph.height, bounds.height * window.devicePixelRatio,
-    "The graph has the correct height.");
-
-  ok(graph._selection.start === null,
-    "The graph's selection start value is initially null.");
-  ok(graph._selection.end === null,
-    "The graph's selection end value is initially null.");
-
-  ok(graph._selectionDragger.origin === null,
-    "The graph's dragger origin value is initially null.");
-  ok(graph._selectionDragger.anchor.start === null,
-    "The graph's dragger anchor start value is initially null.");
-  ok(graph._selectionDragger.anchor.end === null,
-    "The graph's dragger anchor end value is initially null.");
-}
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_flame-graph-02.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that flame graph widgets may have a fixed width or height.
-
-let {FlameGraph} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
-let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  doc.body.setAttribute("style", "position: fixed; width: 100%; height: 100%; margin: 0;");
-
-  let graph = new FlameGraph(doc.body);
-  graph.fixedWidth = 200;
-  graph.fixedHeight = 100;
-
-  yield graph.ready();
-  testGraph(host, graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function testGraph(host, graph) {
-  let bounds = host.frame.getBoundingClientRect();
-
-  isnot(graph.width, bounds.width * window.devicePixelRatio,
-    "The graph should not span all the parent node's width.");
-  isnot(graph.height, bounds.height * window.devicePixelRatio,
-    "The graph should not span all the parent node's height.");
-
-  is(graph.width, graph.fixedWidth * window.devicePixelRatio,
-    "The graph has the correct width.");
-  is(graph.height, graph.fixedHeight * window.devicePixelRatio,
-    "The graph has the correct height.");
-}
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_flame-graph-03.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that selections in the flame graph widget work properly.
-
-let TEST_DATA = [{ color: "#f00", blocks: [{ x: 0, y: 0, width: 50, height: 20, text: "FOO" }, { x: 50, y: 0, width: 100, height: 20, text: "BAR" }] }, { color: "#00f", blocks: [{ x: 0, y: 30, width: 30, height: 20, text: "BAZ" }] }];
-let TEST_WIDTH = 200;
-let TEST_HEIGHT = 100;
-
-let {FlameGraph} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
-let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  doc.body.setAttribute("style", "position: fixed; width: 100%; height: 100%; margin: 0;");
-
-  let graph = new FlameGraph(doc.body, 1);
-  graph.fixedWidth = TEST_WIDTH;
-  graph.fixedHeight = TEST_HEIGHT;
-
-  yield graph.ready();
-
-  testGraph(graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function testGraph(graph) {
-  graph.setData(TEST_DATA);
-
-  is(graph.getDataWindowStart(), 0,
-    "The selection start boundary is correct (1).");
-  is(graph.getDataWindowEnd(), TEST_WIDTH,
-    "The selection end boundary is correct (1).");
-
-  scroll(graph, 200, HORIZONTAL_AXIS, 10);
-  is(graph.getDataWindowStart() | 0, 100,
-    "The selection start boundary is correct (2).");
-  is(graph.getDataWindowEnd() | 0, 300,
-    "The selection end boundary is correct (2).");
-
-  scroll(graph, -200, HORIZONTAL_AXIS, 10);
-  is(graph.getDataWindowStart() | 0, 0,
-    "The selection start boundary is correct (3).");
-  is(graph.getDataWindowEnd() | 0, 200,
-    "The selection end boundary is correct (3).");
-
-  scroll(graph, 200, VERTICAL_AXIS, TEST_WIDTH / 2);
-  is(graph.getDataWindowStart() | 0, 0,
-    "The selection start boundary is correct (4).");
-  is(graph.getDataWindowEnd() | 0, 207,
-    "The selection end boundary is correct (4).");
-
-  scroll(graph, -200, VERTICAL_AXIS, TEST_WIDTH / 2);
-  is(graph.getDataWindowStart() | 0, 7,
-    "The selection start boundary is correct (5).");
-  is(graph.getDataWindowEnd() | 0, 199,
-    "The selection end boundary is correct (5).");
-
-  dragStart(graph, TEST_WIDTH / 2);
-  is(graph.getDataWindowStart() | 0, 7,
-    "The selection start boundary is correct (6).");
-  is(graph.getDataWindowEnd() | 0, 199,
-    "The selection end boundary is correct (6).");
-
-  hover(graph, TEST_WIDTH / 2 - 10);
-  is(graph.getDataWindowStart() | 0, 16,
-    "The selection start boundary is correct (7).");
-  is(graph.getDataWindowEnd() | 0, 209,
-    "The selection end boundary is correct (7).");
-
-  dragStop(graph, 10);
-  is(graph.getDataWindowStart() | 0, 93,
-    "The selection start boundary is correct (8).");
-  is(graph.getDataWindowEnd() | 0, 286,
-    "The selection end boundary is correct (8).");
-}
-
-// EventUtils just doesn't work!
-
-function hover(graph, x, y = 1) {
-  x /= window.devicePixelRatio;
-  y /= window.devicePixelRatio;
-  graph._onMouseMove({ clientX: x, clientY: y });
-}
-
-function dragStart(graph, x, y = 1) {
-  x /= window.devicePixelRatio;
-  y /= window.devicePixelRatio;
-  graph._onMouseMove({ clientX: x, clientY: y });
-  graph._onMouseDown({ clientX: x, clientY: y });
-}
-
-function dragStop(graph, x, y = 1) {
-  x /= window.devicePixelRatio;
-  y /= window.devicePixelRatio;
-  graph._onMouseMove({ clientX: x, clientY: y });
-  graph._onMouseUp({ clientX: x, clientY: y });
-}
-
-let HORIZONTAL_AXIS = 1;
-let VERTICAL_AXIS = 2;
-
-function scroll(graph, wheel, axis, x, y = 1) {
-  x /= window.devicePixelRatio;
-  y /= window.devicePixelRatio;
-  graph._onMouseMove({ clientX: x, clientY: y });
-  graph._onMouseWheel({ clientX: x, clientY: y, axis, detail: wheel, axis,
-    HORIZONTAL_AXIS,
-    VERTICAL_AXIS
-  });
-}
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_flame-graph-04.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that text metrics in the flame graph widget work properly.
-
-let HTML_NS = "http://www.w3.org/1999/xhtml";
-let FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE = 9; // px
-let FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY = "sans-serif";
-let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
-let {FlameGraph} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
-let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let L10N = new ViewHelpers.L10N();
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  let graph = new FlameGraph(doc.body, 1);
-  yield graph.ready();
-
-  testGraph(graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function testGraph(graph) {
-  is(graph._averageCharWidth, getAverageCharWidth(),
-    "The average char width was calculated correctly.");
-  is(graph._overflowCharWidth, getCharWidth(L10N.ellipsis),
-    "The ellipsis char width was calculated correctly.");
-
-  is(graph._getTextWidthApprox("This text is maybe overflowing"),
-    getAverageCharWidth() * 30,
-    "The approximate width was calculated correctly.");
-
-  is(graph._getFittedText("This text is maybe overflowing", 1000),
-    "This text is maybe overflowing",
-    "The fitted text for 1000px width is correct.");
-
-  isnot(graph._getFittedText("This text is maybe overflowing", 100),
-    "This text is maybe overflowing",
-    "The fitted text for 100px width is correct (1).");
-
-  ok(graph._getFittedText("This text is maybe overflowing", 100)
-    .contains(L10N.ellipsis),
-    "The fitted text for 100px width is correct (2).");
-
-  is(graph._getFittedText("This text is maybe overflowing", 10),
-    L10N.ellipsis,
-    "The fitted text for 10px width is correct.");
-
-  is(graph._getFittedText("This text is maybe overflowing", 1),
-    "",
-    "The fitted text for 1px width is correct.");
-}
-
-function getAverageCharWidth() {
-  let letterWidthsSum = 0;
-  let start = 32; // space
-  let end = 123; // "z"
-
-  for (let i = start; i < end; i++) {
-    let char = String.fromCharCode(i);
-    letterWidthsSum += getCharWidth(char);
-  }
-
-  return letterWidthsSum / (end - start);
-}
-
-function getCharWidth(char) {
-  let canvas = document.createElementNS(HTML_NS, "canvas");
-  let ctx = canvas.getContext("2d");
-
-  let fontSize = FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE;
-  let fontFamily = FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY;
-  ctx.font = fontSize + "px " + fontFamily;
-
-  return ctx.measureText(char).width;
-}
deleted file mode 100644
--- a/browser/devtools/shared/widgets/FlameGraph.jsm
+++ /dev/null
@@ -1,755 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const Cu = Components.utils;
-
-Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
-Cu.import("resource:///modules/devtools/Graphs.jsm");
-const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
-const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
-
-this.EXPORTED_SYMBOLS = [
-  "FlameGraph",
-  "FlameGraphUtils"
-];
-
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const GRAPH_SRC = "chrome://browser/content/devtools/graphs-frame.xhtml";
-const L10N = new ViewHelpers.L10N();
-
-const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00035;
-const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5;
-const GRAPH_MIN_SELECTION_WIDTH = 10; // ms
-
-const TIMELINE_TICKS_MULTIPLE = 5; // ms
-const TIMELINE_TICKS_SPACING_MIN = 75; // px
-
-const OVERVIEW_HEADER_HEIGHT = 18; // px
-const OVERVIEW_HEADER_SAFE_BOUNDS = 50; // px
-const OVERVIEW_HEADER_TEXT_COLOR = "#18191a";
-const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
-const OVERVIEW_HEADER_TEXT_FONT_FAMILY = "sans-serif";
-const OVERVIEW_HEADER_TEXT_PADDING_LEFT = 6; // px
-const OVERVIEW_HEADER_TEXT_PADDING_TOP = 5; // px
-const OVERVIEW_TIMELINE_STROKES = "#ddd";
-
-const FLAME_GRAPH_BLOCK_BORDER = 1; // px
-const FLAME_GRAPH_BLOCK_TEXT_COLOR = "#000";
-const FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE = 9; // px
-const FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY = "sans-serif";
-const FLAME_GRAPH_BLOCK_TEXT_PADDING_TOP = 1; // px
-const FLAME_GRAPH_BLOCK_TEXT_PADDING_LEFT = 3; // px
-const FLAME_GRAPH_BLOCK_TEXT_PADDING_RIGHT = 3; // px
-
-/**
- * A flamegraph visualization. This implementation is responsable only with
- * drawing the graph, using a data source consisting of rectangles and
- * their corresponding widths.
- *
- * Example usage:
- *   let graph = new FlameGraph(node);
- *   let src = FlameGraphUtils.createFlameGraphDataFromSamples(samples);
- *   graph.once("ready", () => {
- *     graph.setData(src);
- *   });
- *
- * Data source format:
- *   [
- *     {
- *       color: "string",
- *       blocks: [
- *         {
- *           x: number,
- *           y: number,
- *           width: number,
- *           height: number,
- *           text: "string"
- *         },
- *         ...
- *       ]
- *     },
- *     {
- *       color: "string",
- *       blocks: [...]
- *     },
- *     ...
- *     {
- *       color: "string",
- *       blocks: [...]
- *     }
- *   ]
- *
- * Use `FlameGraphUtils` to convert profiler data (or any other data source)
- * into a drawable format.
- *
- * @param nsIDOMNode parent
- *        The parent node holding the graph.
- * @param number sharpness [optional]
- *        Defaults to the current device pixel ratio.
- */
-function FlameGraph(parent, sharpness) {
-  EventEmitter.decorate(this);
-
-  this._parent = parent;
-  this._ready = promise.defer();
-
-  AbstractCanvasGraph.createIframe(GRAPH_SRC, parent, iframe => {
-    this._iframe = iframe;
-    this._window = iframe.contentWindow;
-    this._document = iframe.contentDocument;
-    this._pixelRatio = sharpness || this._window.devicePixelRatio;
-
-    let container = this._container = this._document.getElementById("graph-container");
-    container.className = "flame-graph-widget-container graph-widget-container";
-
-    let canvas = this._canvas = this._document.getElementById("graph-canvas");
-    canvas.className = "flame-graph-widget-canvas graph-widget-canvas";
-
-    let bounds = parent.getBoundingClientRect();
-    bounds.width = this.fixedWidth || bounds.width;
-    bounds.height = this.fixedHeight || bounds.height;
-    iframe.setAttribute("width", bounds.width);
-    iframe.setAttribute("height", bounds.height);
-
-    this._width = canvas.width = bounds.width * this._pixelRatio;
-    this._height = canvas.height = bounds.height * this._pixelRatio;
-    this._ctx = canvas.getContext("2d");
-
-    this._selection = new GraphSelection();
-    this._selectionDragger = new GraphSelectionDragger();
-
-    // Calculating text widths is necessary to trim the text inside the blocks
-    // while the scaling changes (e.g. via scrolling). This is very expensive,
-    // so maintain a cache of string contents to text widths.
-    this._textWidthsCache = {};
-
-    let fontSize = FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE * this._pixelRatio;
-    let fontFamily = FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY;
-    this._ctx.font = fontSize + "px " + fontFamily;
-    this._averageCharWidth = this._calcAverageCharWidth();
-    this._overflowCharWidth = this._getTextWidth(this.overflowChar);
-
-    this._onMouseMove = this._onMouseMove.bind(this);
-    this._onMouseDown = this._onMouseDown.bind(this);
-    this._onMouseUp = this._onMouseUp.bind(this);
-    this._onMouseWheel = this._onMouseWheel.bind(this);
-    this._onAnimationFrame = this._onAnimationFrame.bind(this);
-
-    container.addEventListener("mousemove", this._onMouseMove);
-    container.addEventListener("mousedown", this._onMouseDown);
-    container.addEventListener("mouseup", this._onMouseUp);
-    container.addEventListener("MozMousePixelScroll", this._onMouseWheel);
-
-    this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
-
-    this._ready.resolve(this);
-    this.emit("ready", this);
-  });
-}
-
-FlameGraph.prototype = {
-  /**
-   * Read-only width and height of the canvas.
-   * @return number
-   */
-  get width() {
-    return this._width;
-  },
-  get height() {
-    return this._height;
-  },
-
-  /**
-   * Returns a promise resolved once this graph is ready to receive data.
-   */
-  ready: function() {
-    return this._ready.promise;
-  },
-
-  /**
-   * Destroys this graph.
-   */
-  destroy: function() {
-    let container = this._container;
-    container.removeEventListener("mousemove", this._onMouseMove);
-    container.removeEventListener("mousedown", this._onMouseDown);
-    container.removeEventListener("mouseup", this._onMouseUp);
-    container.removeEventListener("MozMousePixelScroll", this._onMouseWheel);
-
-    this._window.cancelAnimationFrame(this._animationId);
-    this._iframe.remove();
-
-    this._selection = null;
-    this._selectionDragger = null;
-
-    this._data = null;
-
-    this.emit("destroyed");
-  },
-
-  /**
-   * Rendering options. Subclasses should override these.
-   */
-  overviewHeaderTextColor: OVERVIEW_HEADER_TEXT_COLOR,
-  overviewTimelineStrokes: OVERVIEW_TIMELINE_STROKES,
-  blockTextColor: FLAME_GRAPH_BLOCK_TEXT_COLOR,
-
-  /**
-   * Makes sure the canvas graph is of the specified width or height, and
-   * doesn't flex to fit all the available space.
-   */
-  fixedWidth: null,
-  fixedHeight: null,
-
-  /**
-   * The units used in the overhead ticks. Could be "ms", for example.
-   * Overwrite this with your own localized format.
-   */
-  timelineTickUnits: "",
-
-  /**
-   * Character used when a block's text is overflowing.
-   * Defaults to an ellipsis.
-   */
-  overflowChar: L10N.ellipsis,
-
-  /**
-   * Sets the data source for this graph.
-   *
-   * @param object data
-   *        The data source. See the constructor for more information.
-   */
-  setData: function(data) {
-    this._data = data;
-    this._selection = { start: 0, end: this._width };
-    this._shouldRedraw = true;
-  },
-
-  /**
-   * Same as `setData`, but waits for this graph to finish initializing first.
-   *
-   * @param object data
-   *        The data source. See the constructor for more information.
-   * @return promise
-   *         A promise resolved once the data is set.
-   */
-  setDataWhenReady: Task.async(function*(data) {
-    yield this.ready();
-    this.setData(data);
-  }),
-
-  /**
-   * Gets the start or end of this graph's selection, i.e. the 'data window'.
-   * @return number
-   */
-  getDataWindowStart: function() {
-    return this._selection.start;
-  },
-  getDataWindowEnd: function() {
-    return this._selection.end;
-  },
-
-  /**
-   * The contents of this graph are redrawn only when something changed,
-   * like the data source, or the selection bounds etc. This flag tracks
-   * if the rendering is "dirty" and needs to be refreshed.
-   */
-  _shouldRedraw: false,
-
-  /**
-   * Animation frame callback, invoked on each tick of the refresh driver.
-   */
-  _onAnimationFrame: function() {
-    this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
-    this._drawWidget();
-  },
-
-  /**
-   * Redraws the widget when necessary. The actual graph is not refreshed
-   * every time this function is called, only the cliphead, selection etc.
-   */
-  _drawWidget: function() {
-    if (!this._shouldRedraw) {
-      return;
-    }
-    let ctx = this._ctx;
-    let canvasWidth = this._width;
-    let canvasHeight = this._height;
-    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-
-    let selection = this._selection;
-    let selectionWidth = selection.end - selection.start;
-    let selectionScale = canvasWidth / selectionWidth;
-    this._drawTicks(selection.start, selectionScale);
-    this._drawPyramid(this._data, selection.start, selectionScale);
-
-    this._shouldRedraw = false;
-  },
-
-  /**
-   * Draws the overhead ticks in this graph.
-   *
-   * @param number dataOffset, dataScale
-   *        Offsets and scales the data source by the specified amount.
-   *        This is used for scrolling the visualization.
-   */
-  _drawTicks: function(dataOffset, dataScale) {
-    let ctx = this._ctx;
-    let canvasWidth = this._width;
-    let canvasHeight = this._height;
-    let scaledOffset = dataOffset * dataScale;
-
-    let safeBounds = OVERVIEW_HEADER_SAFE_BOUNDS * this._pixelRatio;
-    let availableWidth = canvasWidth - safeBounds;
-
-    let fontSize = OVERVIEW_HEADER_TEXT_FONT_SIZE * this._pixelRatio;
-    let fontFamily = OVERVIEW_HEADER_TEXT_FONT_FAMILY;
-    let textPaddingLeft = OVERVIEW_HEADER_TEXT_PADDING_LEFT * this._pixelRatio;
-    let textPaddingTop = OVERVIEW_HEADER_TEXT_PADDING_TOP * this._pixelRatio;
-    let tickInterval = this._findOptimalTickInterval(dataScale);
-
-    ctx.textBaseline = "top";
-    ctx.font = fontSize + "px " + fontFamily;
-    ctx.fillStyle = this.overviewHeaderTextColor;
-    ctx.strokeStyle = this.overviewTimelineStrokes;
-    ctx.beginPath();
-
-    for (let x = 0; x < availableWidth + scaledOffset; x += tickInterval) {
-      let lineLeft = x - scaledOffset;
-      let textLeft = lineLeft + textPaddingLeft;
-      let time = Math.round(x / dataScale / this._pixelRatio);
-      let label = time + " " + this.timelineTickUnits;
-      ctx.fillText(label, textLeft, textPaddingTop);
-      ctx.moveTo(lineLeft, 0);
-      ctx.lineTo(lineLeft, canvasHeight);
-    }
-
-    ctx.stroke();
-  },
-
-  /**
-   * Draws the blocks and text in this graph.
-   *
-   * @param object dataSource
-   *        The data source. See the constructor for more information.
-   * @param number dataOffset, dataScale
-   *        Offsets and scales the data source by the specified amount.
-   *        This is used for scrolling the visualization.
-   */
-  _drawPyramid: function(dataSource, dataOffset, dataScale) {
-    let ctx = this._ctx;
-
-    let fontSize = FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE * this._pixelRatio;
-    let fontFamily = FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY;
-    let visibleBlocks = this._drawPyramidFill(dataSource, dataOffset, dataScale);
-
-    ctx.textBaseline = "middle";
-    ctx.font = fontSize + "px " + fontFamily;
-    ctx.fillStyle = this.blockTextColor;
-
-    this._drawPyramidText(visibleBlocks, dataOffset, dataScale);
-  },
-
-  /**
-   * Fills all block inside this graph's pyramid.
-   * @see FlameGraph.prototype._drawPyramid
-   */
-  _drawPyramidFill: function(dataSource, dataOffset, dataScale) {
-    let visibleBlocksStore = [];
-    let minVisibleBlockWidth = this._overflowCharWidth;
-
-    for (let { color, blocks } of dataSource) {
-      this._drawBlocksFill(
-        color, blocks, dataOffset, dataScale,
-        visibleBlocksStore, minVisibleBlockWidth);
-    }
-
-    return visibleBlocksStore;
-  },
-
-  /**
-   * Adds the text for all block inside this graph's pyramid.
-   * @see FlameGraph.prototype._drawPyramid
-   */
-  _drawPyramidText: function(blocks, dataOffset, dataScale) {
-    for (let block of blocks) {
-      this._drawBlockText(block, dataOffset, dataScale);
-    }
-  },
-
-  /**
-   * Fills a group of blocks sharing the same style.
-   *
-   * @param string color
-   *        The color used as the block's background.
-   * @param array blocks
-   *        A list of { x, y, width, height } objects visually representing
-   *        all the blocks sharing this particular style.
-   * @param number dataOffset, dataScale
-   *        Offsets and scales the data source by the specified amount.
-   *        This is used for scrolling the visualization.
-   * @param array visibleBlocksStore
-   *        An array to store all the visible blocks into, after drawing them.
-   *        The provided array will be populated.
-   * @param number minVisibleBlockWidth
-   *        The minimum width of the blocks that will be added into
-   *        the `visibleBlocksStore`.
-   */
-  _drawBlocksFill: function(
-    color, blocks, dataOffset, dataScale,
-    visibleBlocksStore, minVisibleBlockWidth)
-  {
-    let ctx = this._ctx;
-    let canvasWidth = this._width;
-    let canvasHeight = this._height;
-    let scaledOffset = dataOffset * dataScale;
-
-    ctx.fillStyle = color;
-    ctx.beginPath();
-
-    for (let block of blocks) {
-      let { x, y, width, height } = block;
-      let rectLeft = x * this._pixelRatio * dataScale - scaledOffset;
-      let rectTop = (y + OVERVIEW_HEADER_HEIGHT) * this._pixelRatio;
-      let rectWidth = width * this._pixelRatio * dataScale;
-      let rectHeight = height * this._pixelRatio;
-
-      if (rectLeft > canvasWidth || // Too far right.
-          rectLeft < -rectWidth ||  // Too far left.
-          rectTop > canvasHeight) { // Too far bottom.
-        continue;
-      }
-
-      // Clamp the blocks position to start at 0. Avoid negative X coords,
-      // to properly place the text inside the blocks.
-      if (rectLeft < 0) {
-        rectWidth += rectLeft;
-        rectLeft = 0;
-      }
-
-      // Avoid drawing blocks that are too narrow.
-      if (rectWidth <= FLAME_GRAPH_BLOCK_BORDER ||
-          rectHeight <= FLAME_GRAPH_BLOCK_BORDER) {
-        continue;
-      }
-
-      ctx.rect(
-        rectLeft, rectTop,
-        rectWidth - FLAME_GRAPH_BLOCK_BORDER,
-        rectHeight - FLAME_GRAPH_BLOCK_BORDER);
-
-      // Populate the visible blocks store with this block if the width
-      // is longer than a given threshold.
-      if (rectWidth > minVisibleBlockWidth) {
-        visibleBlocksStore.push(block);
-      }
-    }
-
-    ctx.fill();
-  },
-
-  /**
-   * Adds text for a single block.
-   *
-   * @param object block
-   *        A single { x, y, width, height, text } object visually representing
-   *        the block containing the text.
-   * @param number dataOffset, dataScale
-   *        Offsets and scales the data source by the specified amount.
-   *        This is used for scrolling the visualization.
-   */
-  _drawBlockText: function(block, dataOffset, dataScale) {
-    let ctx = this._ctx;
-    let scaledOffset = dataOffset * dataScale;
-
-    let { x, y, width, height, text } = block;
-
-    let paddingTop = FLAME_GRAPH_BLOCK_TEXT_PADDING_TOP * this._pixelRatio;
-    let paddingLeft = FLAME_GRAPH_BLOCK_TEXT_PADDING_LEFT * this._pixelRatio;
-    let paddingRight = FLAME_GRAPH_BLOCK_TEXT_PADDING_RIGHT * this._pixelRatio;
-    let totalHorizontalPadding = paddingLeft + paddingRight;
-
-    let rectLeft = x * this._pixelRatio * dataScale - scaledOffset;
-    let rectWidth = width * this._pixelRatio * dataScale;
-
-    // Clamp the blocks position to start at 0. Avoid negative X coords,
-    // to properly place the text inside the blocks.
-    if (rectLeft < 0) {
-      rectWidth += rectLeft;
-      rectLeft = 0;
-    }
-
-    let textLeft = rectLeft + paddingLeft;
-    let textTop = (y + height / 2 + OVERVIEW_HEADER_HEIGHT) * this._pixelRatio + paddingTop;
-    let textAvailableWidth = rectWidth - totalHorizontalPadding;
-
-    // Massage the text to fit inside a given width. This clamps the string
-    // at the end to avoid overflowing.
-    let fittedText = this._getFittedText(text, textAvailableWidth);
-    if (fittedText.length < 1) {
-      return;
-    }
-
-    ctx.fillText(fittedText, textLeft, textTop);
-  },
-
-  /**
-   * Calculating text widths is necessary to trim the text inside the blocks
-   * while the scaling changes (e.g. via scrolling). This is very expensive,
-   * so maintain a cache of string contents to text widths.
-   */
-  _textWidthsCache: null,
-  _overflowCharWidth: null,
-  _averageCharWidth: null,
-
-  /**
-   * Gets the width of the specified text, for the current context state
-   * (font size, family etc.).
-   *
-   * @param string text
-   *        The text to analyze.
-   * @return number
-   *         The text width.
-   */
-  _getTextWidth: function(text) {
-    let cachedWidth = this._textWidthsCache[text];
-    if (cachedWidth) {
-      return cachedWidth;
-    }
-    let metrics = this._ctx.measureText(text);
-    return (this._textWidthsCache[text] = metrics.width);
-  },
-
-  /**
-   * Gets an approximate width of the specified text. This is much faster
-   * than `_getTextWidth`, but inexact.
-   *
-   * @param string text
-   *        The text to analyze.
-   * @return number
-   *         The approximate text width.
-   */
-  _getTextWidthApprox: function(text) {
-    return text.length * this._averageCharWidth;
-  },
-
-  /**
-   * Gets the average letter width in the English alphabet, for the current
-   * context state (font size, family etc.). This provides a close enough
-   * value to use in `_getTextWidthApprox`.
-   *
-   * @return number
-   *         The average letter width.
-   */
-  _calcAverageCharWidth: function() {
-    let letterWidthsSum = 0;
-    let start = 32; // space
-    let end = 123; // "z"
-
-    for (let i = start; i < end; i++) {
-      let char = String.fromCharCode(i);
-      letterWidthsSum += this._getTextWidth(char);
-    }
-
-    return letterWidthsSum / (end - start);
-  },
-
-  /**
-   * Massage a text to fit inside a given width. This clamps the string
-   * at the end to avoid overflowing.
-   *
-   * @param string text
-   *        The text to fit inside the given width.
-   * @param number maxWidth
-   *        The available width for the given text.
-   * @return string
-   *         The fitted text.
-   */
-  _getFittedText: function(text, maxWidth) {
-    let textWidth = this._getTextWidth(text);
-    if (textWidth < maxWidth) {
-      return text;
-    }
-    if (this._overflowCharWidth > maxWidth) {
-      return "";
-    }
-    for (let i = 1, len = text.length; i <= len; i++) {
-      let trimmedText = text.substring(0, len - i);
-      let trimmedWidth = this._getTextWidthApprox(trimmedText) + this._overflowCharWidth;
-      if (trimmedWidth < maxWidth) {
-        return trimmedText + this.overflowChar;
-      }
-    }
-    return "";
-  },
-
-  /**
-   * Listener for the "mousemove" event on the graph's container.
-   */
-  _onMouseMove: function(e) {
-    let offset = this._getContainerOffset();
-    let mouseX = (e.clientX - offset.left) * this._pixelRatio;
-
-    let canvasWidth = this._width;
-    let canvasHeight = this._height;
-
-    let selection = this._selection;
-    let selectionWidth = selection.end - selection.start;
-    let selectionScale = canvasWidth / selectionWidth;
-
-    let dragger = this._selectionDragger;
-    if (dragger.origin != null) {
-      selection.start = dragger.anchor.start + (dragger.origin - mouseX) / selectionScale;
-      selection.end = dragger.anchor.end + (dragger.origin - mouseX) / selectionScale;
-      this._normalizeSelectionBounds();
-      this._shouldRedraw = true;
-    }
-  },
-
-  /**
-   * Listener for the "mousedown" event on the graph's container.
-   */
-  _onMouseDown: function(e) {
-    let offset = this._getContainerOffset();
-    let mouseX = (e.clientX - offset.left) * this._pixelRatio;
-
-    this._selectionDragger.origin = mouseX;
-    this._selectionDragger.anchor.start = this._selection.start;
-    this._selectionDragger.anchor.end = this._selection.end;
-    this._canvas.setAttribute("input", "adjusting-selection-boundary");
-  },
-
-  /**
-   * Listener for the "mouseup" event on the graph's container.
-   */
-  _onMouseUp: function() {
-    this._selectionDragger.origin = null;
-    this._canvas.removeAttribute("input");
-  },
-
-  /**
-   * Listener for the "wheel" event on the graph's container.
-   */
-  _onMouseWheel: function(e) {
-    let offset = this._getContainerOffset();
-    let mouseX = (e.clientX - offset.left) * this._pixelRatio;
-
-    let canvasWidth = this._width;
-    let canvasHeight = this._height;
-
-    let selection = this._selection;
-    let selectionWidth = selection.end - selection.start;
-    let selectionScale = canvasWidth / selectionWidth;
-
-    switch (e.axis) {
-      case e.VERTICAL_AXIS: {
-        let distFromStart = mouseX;
-        let distFromEnd = canvasWidth - mouseX;
-        let vector = e.detail * GRAPH_WHEEL_ZOOM_SENSITIVITY / selectionScale;
-        selection.start -= distFromStart * vector;
-        selection.end += distFromEnd * vector;
-        break;
-      }
-      case e.HORIZONTAL_AXIS: {
-        let vector = e.detail * GRAPH_WHEEL_SCROLL_SENSITIVITY / selectionScale;
-        selection.start += vector;
-        selection.end += vector;
-        break;
-      }
-    }
-
-    this._normalizeSelectionBounds();
-    this._shouldRedraw = true;
-  },
-
-  /**
-   * Makes sure the start and end points of the current selection
-   * are withing the graph's visible bounds, and that they form a selection
-   * wider than the allowed minimum width.
-   */
-  _normalizeSelectionBounds: function() {
-    let canvasWidth = this._width * 2;
-    let canvasHeight = this._height;
-
-    let { start, end } = this._selection;
-    let minSelectionWidth = GRAPH_MIN_SELECTION_WIDTH * this._pixelRatio;
-
-    if (start < 0) {
-      start = 0;
-    }
-    if (end < 0) {
-      start = 0;
-      end = minSelectionWidth;
-    }
-    if (end > canvasWidth) {
-      end = canvasWidth;
-    }
-    if (start > canvasWidth) {
-      end = canvasWidth;
-      start = canvasWidth - minSelectionWidth;
-    }
-    if (end - start < minSelectionWidth) {
-      let midPoint = (start + end) / 2;
-      start = midPoint - minSelectionWidth / 2;
-      end = midPoint + minSelectionWidth / 2;
-    }
-
-    this._selection.start = start;
-    this._selection.end = end;
-  },
-
-  /**
-   *
-   * Finds the optimal tick interval between time markers in this graph.
-   *
-   * @param number dataScale
-   * @return number
-   */
-  _findOptimalTickInterval: function(dataScale) {
-    let timingStep = TIMELINE_TICKS_MULTIPLE;
-    let spacingMin = TIMELINE_TICKS_SPACING_MIN * this._pixelRatio;
-
-    if (dataScale > spacingMin) {
-      return dataScale;
-    }
-
-    while (true) {
-      let scaledStep = dataScale * timingStep;
-      if (scaledStep < spacingMin) {
-        timingStep <<= 1;
-        continue;
-      }
-      return scaledStep;
-    }
-  },
-
-  /**
-   * Gets the offset of this graph's container relative to the owner window.
-   *
-   * @return object
-   *         The { left, top } offset.
-   */
-  _getContainerOffset: function() {
-    let node = this._canvas;
-    let x = 0;
-    let y = 0;
-
-    while ((node = node.offsetParent)) {
-      x += node.offsetLeft;
-      y += node.offsetTop;
-    }
-
-    return { left: x, top: y };
-  }
-};
-
-/**
- * A collection of utility functions converting various data sources
- * into a format drawable by the FlameGraph.
- */
-let FlameGraphUtils = {
-  // TODO bug 1077459
-};
--- a/browser/devtools/shared/widgets/Graphs.jsm
+++ b/browser/devtools/shared/widgets/Graphs.jsm
@@ -2,24 +2,20 @@
  * 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 Cu = Components.utils;
 
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
 const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
-const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
 
 this.EXPORTED_SYMBOLS = [
-  "GraphCursor",
-  "GraphSelection",
-  "GraphSelectionDragger",
-  "GraphSelectionResizer",
   "AbstractCanvasGraph",
   "LineGraphWidget",
   "BarGraphWidget",
   "CanvasGraphUtils"
 ];
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const GRAPH_SRC = "chrome://browser/content/devtools/graphs-frame.xhtml";
@@ -92,33 +88,38 @@ const BAR_GRAPH_REGION_STRIPES_COLOR = "
 const BAR_GRAPH_HIGHLIGHTS_MASK_BACKGROUND = "rgba(255,255,255,0.75)";
 const BAR_GRAPH_HIGHLIGHTS_MASK_STRIPES = "rgba(255,255,255,0.5)";
 
 const BAR_GRAPH_LEGEND_MOUSEOVER_DEBOUNCE = 50; // ms
 
 /**
  * Small data primitives for all graphs.
  */
-this.GraphCursor = function() {
-  this.x = null;
-  this.y = null;
+this.GraphCursor = function() {};
+this.GraphSelection = function() {};
+this.GraphSelectionDragger = function() {};
+this.GraphSelectionResizer = function() {};
+
+GraphCursor.prototype = {
+  x: null,
+  y: null
 };
 
-this.GraphSelection = function() {
-  this.start = null;
-  this.end = null;
+GraphSelection.prototype = {
+  start: null,
+  end: null
 };
 
-this.GraphSelectionDragger = function() {
-  this.origin = null;
-  this.anchor = new GraphSelection();
+GraphSelectionDragger.prototype = {
+  origin: null,
+  anchor: new GraphSelection()
 };
 
-this.GraphSelectionResizer = function() {
-  this.margin = null;
+GraphSelectionResizer.prototype = {
+  margin: null
 };
 
 /**
  * Base class for all graphs using a canvas to render the data source. Handles
  * frame creation, data source, selection bounds, cursor position, etc.
  *
  * Language:
  *   - The "data" represents the values used when building the graph.
@@ -239,21 +240,16 @@ AbstractCanvasGraph.prototype = {
     container.removeEventListener("mouseout", this._onMouseOut);
 
     let ownerWindow = this._parent.ownerDocument.defaultView;
     ownerWindow.removeEventListener("resize", this._onResize);
 
     this._window.cancelAnimationFrame(this._animationId);
     this._iframe.remove();
 
-    this._cursor = null;
-    this._selection = null;
-    this._selectionDragger = null;
-    this._selectionResizer = null;
-
     this._data = null;
     this._mask = null;
     this._maskArgs = null;
     this._regions = null;
 
     this._cachedBackgroundImage = null;
     this._cachedGraphImage = null;
     this._cachedMaskImage = null;
@@ -891,19 +887,16 @@ AbstractCanvasGraph.prototype = {
    * @return boolean
    */
   _isHoveringRegion: function() {
     return !!this.getHoveredRegion();
   },
 
   /**
    * Gets the offset of this graph's container relative to the owner window.
-   *
-   * @return object
-   *         The { left, top } offset.
    */
   _getContainerOffset: function() {
     let node = this._canvas;
     let x = 0;
     let y = 0;
 
     while (node = node.offsetParent) {
       x += node.offsetLeft;