Exemplo n.º 1
0
 }).then(node => {
   if (hasNavigated()) {
     return promise.reject("navigated; resolution of _defaultNode aborted");
   }
   this._defaultNode = node;
   return node;
 });
function test () {
  let loader = makeLoader();
  let module = Module("./main", gTestPath);
  let require = Require(loader, module);

  try {
    let Model = require("resource://gre/modules/BlinkTag.jsm");
    ok(false, "requiring a JS module that doesn't exist should throw");
  }
  catch (e) {
    ok(e, "requiring a JS module that doesn't exist should throw");
  }

  /*
   * Relative resource:// URI of JSM
   */

  let { square } = require("./Math.jsm").Math;
  is(square(5), 25, "loads relative URI of JSM");

  /*
   * Absolute resource:// URI of JSM
   */
  let { defer } = require("resource://gre/modules/Promise.jsm").Promise;
  let { resolve, promise } = defer();
  resolve(5);
  promise.then(val => {
    is(val, 5, "loads absolute resource:// URI of JSM");
  }).then(finish);

}
Exemplo n.º 3
0
 }).then(node => {
   if (walker !== this.walker) {
     promise.reject(null);
   }
   this._defaultNode = node;
   return node;
 });
Exemplo n.º 4
0
  destroy: function() {
    if (this._panelDestroyer) {
      return this._panelDestroyer;
    }

    if (this.walker) {
      this.walker.off("new-root", this.onNewRoot);
      this.pageStyle = null;
    }

    this.cancelUpdate();
    this.cancelLayoutChange();

    if (this.browser) {
      this.browser.removeEventListener("resize", this.scheduleLayoutChange, true);
      this.browser = null;
    }

    this.target.off("will-navigate", this._onBeforeNavigate);

    this.target.off("thread-paused", this.updateDebuggerPausedWarning);
    this.target.off("thread-resumed", this.updateDebuggerPausedWarning);
    this._toolbox.off("select", this.updateDebuggerPausedWarning);
    this._toolbox.off("host-changed", this.onToolboxHostChanged);

    this.sidebar.off("select", this._setDefaultSidebar);
    let sidebarDestroyer = this.sidebar.destroy();
    this.sidebar = null;

    this.nodemenu.removeEventListener("popupshowing", this._setupNodeMenu, true);
    this.nodemenu.removeEventListener("popuphiding", this._resetNodeMenu, true);
    this.breadcrumbs.destroy();
    this._paneToggleButton.removeEventListener("mousedown",
      this.onPaneToggleButtonClicked);
    this._paneToggleButton = null;
    this.searchSuggestions.destroy();
    this.searchBox = null;
    this.selection.off("new-node-front", this.onNewSelection);
    this.selection.off("before-new-node", this.onBeforeNewSelection);
    this.selection.off("before-new-node-front", this.onBeforeNewSelection);
    this.selection.off("detached-front", this.onDetached);
    let markupDestroyer = this._destroyMarkup();
    this.panelWin.inspector = null;
    this.target = null;
    this.panelDoc = null;
    this.panelWin = null;
    this.breadcrumbs = null;
    this.searchSuggestions = null;
    this.lastNodemenuItem = null;
    this.nodemenu = null;
    this._toolbox = null;

    this._panelDestroyer = promise.all([
      sidebarDestroyer,
      markupDestroyer
    ]);

    return this._panelDestroyer;
  },
Exemplo n.º 5
0
  pasteAdjacentHTML: function(position) {
    let content = this._getClipboardContentForPaste();
    if (!content)
      return promise.reject("No clipboard content for paste");

    let node = this.selection.nodeFront;
    return this.markup.insertAdjacentHTMLToNode(node, position, content);
  },
Exemplo n.º 6
0
  pasteInnerHTML: function() {
    let content = this._getClipboardContentForPaste();
    if (!content)
      return promise.reject("No clipboard content for paste");

    let node = this.selection.nodeFront;
    return this.markup.getNodeInnerHTML(node).then(oldContent => {
      this.markup.updateNodeInnerHTML(node, content, oldContent);
    });
  },
Exemplo n.º 7
0
    }).then(front => {
      if (hasNavigated()) {
        return promise.reject("navigated; resolution of _defaultNode aborted");
      }

      if (front) {
        return front;
      }
      return this.walker.documentElement();
    }).then(node => {
Exemplo n.º 8
0
    return walker.getRootNode().then(aRootNode => {
      if (hasNavigated()) {
        return promise.reject("navigated; resolution of _defaultNode aborted");
      }

      rootNode = aRootNode;
      if (this.selectionCssSelector) {
        return walker.querySelector(rootNode, this.selectionCssSelector);
      }
    }).then(front => {
Exemplo n.º 9
0
    }).then(front => {
      if (hasNavigated()) {
        return promise.reject("navigated; resolution of _defaultNode aborted");
      }

      if (front) {
        return front;
      }
      return walker.querySelector(rootNode, "body");
    }).then(front => {
Exemplo n.º 10
0
    }).then(queryList => {
      // Value has changed since we started this request, we're done.
      if (query != this.searchBox.value) {
        if (queryList) {
          queryList.release();
        }
        return promise.reject(null);
      }

      this._searchResults = queryList || [];
      if (this._searchResults && this._searchResults.length > 0) {
        this._lastValidSearch = query;
        // Even though the selector matched atleast one node, there is still
        // possibility of suggestions.
        if (query.match(/[\s>+]$/)) {
          // If the query has a space or '>' at the end, create a selector to match
          // the children of the selector inside the search box by adding a '*'.
          this._lastValidSearch += "*";
        }
        else if (query.match(/[\s>+][\.#a-zA-Z][\.#>\s+]*$/)) {
          // If the query is a partial descendant selector which does not matches
          // any node, remove the last incomplete part and add a '*' to match
          // everything. For ex, convert 'foo > b' to 'foo > *' .
          let lastPart = query.match(/[\s>+][\.#a-zA-Z][^>\s+]*$/)[0];
          this._lastValidSearch = query.slice(0, -1 * lastPart.length + 1) + "*";
        }

        if (!query.slice(-1).match(/[\.#\s>+]/)) {
          // Hide the popup if we have some matching nodes and the query is not
          // ending with [.# >] which means that the selector is not at the
          // beginning of a new class, tag or id.
          if (this.searchPopup.isOpen) {
            this.searchPopup.hidePopup();
          }
          this.searchBox.classList.remove("devtools-no-search-result");

          return this._selectResult(0);
        }
        return this._selectResult(0).then(() => {
          this.searchBox.classList.remove("devtools-no-search-result");
        }).then(() => this.showSuggestions());
      }
      if (query.match(/[\s>+]$/)) {
        this._lastValidSearch = query + "*";
      }
      else if (query.match(/[\s>+][\.#a-zA-Z][\.#>\s+]*$/)) {
        let lastPart = query.match(/[\s+>][\.#a-zA-Z][^>\s+]*$/)[0];
        this._lastValidSearch = query.slice(0, -1 * lastPart.length + 1) + "*";
      }
      this.searchBox.classList.add("devtools-no-search-result");
      return this.showSuggestions();
    }).then(() => this.emit("processing-done"), Cu.reportError);
Exemplo n.º 11
0
function onFrameLoad (frame) {
  let { resolve, promise } = Promise.defer();

  if (frame.contentWindow) {
    let domHelper = new DOMHelpers(frame.contentWindow);
    domHelper.onceDOMReady(resolve);
  } else {
    let callback = () => {
      frame.removeEventListener("DOMContentLoaded", callback);
      resolve();
    }
    frame.addEventListener("DOMContentLoaded", callback);
  }

  return promise;
}
Exemplo n.º 12
0
/**
 * Converts any input box on a page to a CSS selector search and suggestion box.
 *
 * Emits 'processing-done' event when it is done processing the current
 * keypress, search request or selection from the list, whether that led to a
 * search or not.
 *
 * @constructor
 * @param InspectorPanel aInspector
 *        The InspectorPanel whose `walker` attribute should be used for
 *        document traversal.
 * @param nsiInputElement aInputNode
 *        The input element to which the panel will be attached and from where
 *        search input will be taken.
 */
function SelectorSearch(aInspector, aInputNode) {
  this.inspector = aInspector;
  this.searchBox = aInputNode;
  this.panelDoc = this.searchBox.ownerDocument;

  // initialize variables.
  this._lastSearched = null;
  this._lastValidSearch = "";
  this._lastToLastValidSearch = null;
  this._searchResults = null;
  this._searchSuggestions = {};
  this._searchIndex = 0;

  // bind!
  this._showPopup = this._showPopup.bind(this);
  this._onHTMLSearch = this._onHTMLSearch.bind(this);
  this._onSearchKeypress = this._onSearchKeypress.bind(this);
  this._onListBoxKeypress = this._onListBoxKeypress.bind(this);

  // Options for the AutocompletePopup.
  let options = {
    panelId: "inspector-searchbox-panel",
    listBoxId: "searchbox-panel-listbox",
    autoSelect: true,
    position: "before_start",
    direction: "ltr",
    theme: "auto",
    onClick: this._onListBoxKeypress,
    onKeypress: this._onListBoxKeypress
  };
  this.searchPopup = new AutocompletePopup(this.panelDoc, options);

  // event listeners.
  this.searchBox.addEventListener("command", this._onHTMLSearch, true);
  this.searchBox.addEventListener("keypress", this._onSearchKeypress, true);

  // For testing, we need to be able to wait for the most recent node request
  // to finish.  Tests can watch this promise for that.
  this._lastQuery = promise.resolve(null);
  EventEmitter.decorate(this);
}
Exemplo n.º 13
0
  _pullAllocationSites: Task.async(function *() {
    let { promise, resolve } = Promise.defer();
    this._lastPullAllocationSitesFinished = promise;

    if ((yield this.getState()) !== "attached") {
      resolve();
      return;
    }

    let memoryData = yield this.getAllocations();
    // Match the signature of the TimelineFront events, with "timeline-data"
    // being the event name, and the second argument describing the type.
    this.emit("timeline-data", "allocations", {
      sites: memoryData.allocations,
      timestamps: memoryData.allocationsTimestamps,
      frames: memoryData.frames,
      counts: memoryData.counts
    });

    resolve();
  }),
Exemplo n.º 14
0
  _destroyMarkup: function() {
    let destroyPromise;

    if (this._boundMarkupFrameLoad) {
      this._markupFrame.removeEventListener("load", this._boundMarkupFrameLoad, true);
      this._boundMarkupFrameLoad = null;
    }

    if (this.markup) {
      destroyPromise = this.markup.destroy();
      this.markup = null;
    } else {
      destroyPromise = promise.resolve();
    }

    if (this._markupFrame) {
      this._markupFrame.parentNode.removeChild(this._markupFrame);
      this._markupFrame = null;
    }

    this._markupBox = null;

    return destroyPromise;
  },
Exemplo n.º 15
0
  _deferredOpen: function(defaultSelection) {
    let deferred = promise.defer();

    this.onNewRoot = this.onNewRoot.bind(this);
    this.walker.on("new-root", this.onNewRoot);

    this.nodemenu = this.panelDoc.getElementById("inspector-node-popup");
    this.lastNodemenuItem = this.nodemenu.lastChild;
    this._setupNodeMenu = this._setupNodeMenu.bind(this);
    this._resetNodeMenu = this._resetNodeMenu.bind(this);
    this.nodemenu.addEventListener("popupshowing", this._setupNodeMenu, true);
    this.nodemenu.addEventListener("popuphiding", this._resetNodeMenu, true);

    this.onNewSelection = this.onNewSelection.bind(this);
    this.selection.on("new-node-front", this.onNewSelection);
    this.onBeforeNewSelection = this.onBeforeNewSelection.bind(this);
    this.selection.on("before-new-node-front", this.onBeforeNewSelection);
    this.onDetached = this.onDetached.bind(this);
    this.selection.on("detached-front", this.onDetached);

    this.breadcrumbs = new HTMLBreadcrumbs(this);

    this.onToolboxHostChanged = this.onToolboxHostChanged.bind(this);
    this._toolbox.on("host-changed", this.onToolboxHostChanged);

    if (this.target.isLocalTab) {
      this.browser = this.target.tab.linkedBrowser;
      this.scheduleLayoutChange = this.scheduleLayoutChange.bind(this);
      this.browser.addEventListener("resize", this.scheduleLayoutChange, true);

      // Show a warning when the debugger is paused.
      // We show the warning only when the inspector
      // is selected.
      this.updateDebuggerPausedWarning = () => {
        let notificationBox = this._toolbox.getNotificationBox();
        let notification = notificationBox.getNotificationWithValue("inspector-script-paused");
        if (!notification && this._toolbox.currentToolId == "inspector" &&
            this.target.isThreadPaused) {
          let message = strings.GetStringFromName("debuggerPausedWarning.message");
          notificationBox.appendNotification(message,
            "inspector-script-paused", "", notificationBox.PRIORITY_WARNING_HIGH);
        }

        if (notification && this._toolbox.currentToolId != "inspector") {
          notificationBox.removeNotification(notification);
        }

        if (notification && !this.target.isThreadPaused) {
          notificationBox.removeNotification(notification);
        }

      };
      this.target.on("thread-paused", this.updateDebuggerPausedWarning);
      this.target.on("thread-resumed", this.updateDebuggerPausedWarning);
      this._toolbox.on("select", this.updateDebuggerPausedWarning);
      this.updateDebuggerPausedWarning();
    }

    this._initMarkup();
    this.isReady = false;

    this.once("markuploaded", () => {
      this.isReady = true;

      // All the components are initialized. Let's select a node.
      this.selection.setNodeFront(defaultSelection, "inspector-open");

      this.markup.expandNode(this.selection.nodeFront);

      this.emit("ready");
      deferred.resolve(this);
    });

    this.setupSearchBox();
    this.setupSidebar();

    return deferred.promise;
  },
Exemplo n.º 16
0
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);
 *   graph.once("ready", () => {
 *     let data = FlameGraphUtils.createFlameGraphDataFromSamples(samples);
 *     let bounds = { startTime, endTime };
 *     graph.setData({ data, bounds });
 *   });
 *
 * 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();

  this.setTheme();

  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._bounds = new GraphArea();
    this._selection = new GraphArea();
    this._selectionDragger = new GraphAreaDragger();
    this._verticalOffset = 0;
    this._verticalOffsetDragger = new GraphAreaDragger(0);

    // 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._onAnimationFrame = this._onAnimationFrame.bind(this);
    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._onResize = this._onResize.bind(this);
    this.refresh = this.refresh.bind(this);

    this._window.addEventListener("mousemove", this._onMouseMove);
    this._window.addEventListener("mousedown", this._onMouseDown);
    this._window.addEventListener("mouseup", this._onMouseUp);
    this._window.addEventListener("MozMousePixelScroll", this._onMouseWheel);

    let ownerWindow = this._parent.ownerDocument.defaultView;
    ownerWindow.addEventListener("resize", this._onResize);

    this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);

    this._ready.resolve(this);
    this.emit("ready", this);
  });
}
Exemplo n.º 17
0
function wait (n) {
  let { resolve, promise } = Promise.defer();
  setTimeout(resolve, n);
  return promise;
}