browser/devtools/sourceeditor/debugger.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5  "use strict";
     7 const dbginfo = new WeakMap();
     9 // These functions implement search within the debugger. Since
    10 // search in the debugger is different from other components,
    11 // we can't use search.js CodeMirror addon. This is a slightly
    12 // modified version of that addon. Depends on searchcursor.js.
    14 function SearchState() {
    15   this.posFrom = this.posTo = this.query = null;
    16 }
    18 function getSearchState(cm) {
    19   return cm.state.search || (cm.state.search = new SearchState());
    20 }
    22 function getSearchCursor(cm, query, pos) {
    23   // If the query string is all lowercase, do a case insensitive search.
    24   return cm.getSearchCursor(query, pos,
    25     typeof query == "string" && query == query.toLowerCase());
    26 }
    28 /**
    29  * If there's a saved search, selects the next results.
    30  * Otherwise, creates a new search and selects the first
    31  * result.
    32  */
    33 function doSearch(ctx, rev, query) {
    34   let { cm } = ctx;
    35   let state = getSearchState(cm);
    37   if (state.query) {
    38     searchNext(ctx, rev);
    39     return;
    40   }
    42   cm.operation(function () {
    43     if (state.query) return;
    45     state.query = query;
    46     state.posFrom = state.posTo = { line: 0, ch: 0 };
    47     searchNext(ctx, rev);
    48   });
    49 }
    51 /**
    52  * Selects the next result of a saved search.
    53  */
    54 function searchNext(ctx, rev) {
    55   let { cm, ed } = ctx;
    56   cm.operation(function () {
    57     let state = getSearchState(cm)
    58     let cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
    60     if (!cursor.find(rev)) {
    61       cursor = getSearchCursor(cm, state.query, rev ?
    62         { line: cm.lastLine(), ch: null } : { line: cm.firstLine(), ch: 0 });
    63       if (!cursor.find(rev))
    64         return;
    65     }
    67     ed.alignLine(cursor.from().line, "center");
    68     cm.setSelection(cursor.from(), cursor.to());
    69     state.posFrom = cursor.from();
    70     state.posTo = cursor.to();
    71   });
    72 }
    74 /**
    75  * Clears the currently saved search.
    76  */
    77 function clearSearch(cm) {
    78   let state = getSearchState(cm);
    80   if (!state.query)
    81     return;
    83   state.query = null;
    84 }
    86 // Exported functions
    88 /**
    89  * This function is called whenever Editor is extended with functions
    90  * from this module. See Editor.extend for more info.
    91  */
    92 function initialize(ctx) {
    93   let { ed } = ctx;
    95   dbginfo.set(ed, {
    96     breakpoints:   {},
    97     debugLocation: null
    98   });
    99 }
   101 /**
   102  * True if editor has a visual breakpoint at that line, false
   103  * otherwise.
   104  */
   105 function hasBreakpoint(ctx, line) {
   106   let { cm } = ctx;
   107   let markers = cm.lineInfo(line).gutterMarkers;
   109   return markers != null &&
   110     markers.breakpoints.classList.contains("breakpoint");
   111 }
   113 /**
   114  * Adds a visual breakpoint for a specified line. Third
   115  * parameter 'cond' can hold any object.
   116  *
   117  * After adding a breakpoint, this function makes Editor to
   118  * emit a breakpointAdded event.
   119  */
   120 function addBreakpoint(ctx, line, cond) {
   121   if (hasBreakpoint(ctx, line))
   122     return;
   124   let { ed, cm } = ctx;
   125   let meta = dbginfo.get(ed);
   126   let info = cm.lineInfo(line);
   128   ed.addMarker(line, "breakpoints", "breakpoint");
   129   meta.breakpoints[line] = { condition: cond };
   131   info.handle.on("delete", function onDelete() {
   132     info.handle.off("delete", onDelete);
   133     meta.breakpoints[info.line] = null;
   134   });
   136   ed.emit("breakpointAdded", line);
   137 }
   139 /**
   140  * Removes a visual breakpoint from a specified line and
   141  * makes Editor to emit a breakpointRemoved event.
   142  */
   143 function removeBreakpoint(ctx, line) {
   144   if (!hasBreakpoint(ctx, line))
   145     return;
   147   let { ed, cm } = ctx;
   148   let meta = dbginfo.get(ed);
   149   let info = cm.lineInfo(line);
   151   meta.breakpoints[info.line] = null;
   152   ed.removeMarker(info.line, "breakpoints", "breakpoint");
   153   ed.emit("breakpointRemoved", line);
   154 }
   156 /**
   157  * Returns a list of all breakpoints in the current Editor.
   158  */
   159 function getBreakpoints(ctx) {
   160   let { ed } = ctx;
   161   let meta = dbginfo.get(ed);
   163   return Object.keys(meta.breakpoints).reduce((acc, line) => {
   164     if (meta.breakpoints[line] != null)
   165       acc.push({ line: line, condition: meta.breakpoints[line].condition });
   166     return acc;
   167   }, []);
   168 }
   170 /**
   171  * Saves a debug location information and adds a visual anchor to
   172  * the breakpoints gutter. This is used by the debugger UI to
   173  * display the line on which the Debugger is currently paused.
   174  */
   175 function setDebugLocation(ctx, line) {
   176   let { ed } = ctx;
   177   let meta = dbginfo.get(ed);
   179   clearDebugLocation(ctx);
   181   meta.debugLocation = line;
   182   ed.addMarker(line, "breakpoints", "debugLocation");
   183   ed.addLineClass(line, "debug-line");
   184 }
   186 /**
   187  * Returns a line number that corresponds to the current debug
   188  * location.
   189  */
   190 function getDebugLocation(ctx) {
   191   let { ed } = ctx;
   192   let meta = dbginfo.get(ed);
   194   return meta.debugLocation;
   195 }
   197 /**
   198  * Clears the debug location. Clearing the debug location
   199  * also removes a visual anchor from the breakpoints gutter.
   200  */
   201 function clearDebugLocation(ctx) {
   202   let { ed } = ctx;
   203   let meta = dbginfo.get(ed);
   205   if (meta.debugLocation != null) {
   206     ed.removeMarker(meta.debugLocation, "breakpoints", "debugLocation");
   207     ed.removeLineClass(meta.debugLocation, "debug-line");
   208     meta.debugLocation = null;
   209   }
   210 }
   212 /**
   213  * Starts a new search.
   214  */
   215 function find(ctx, query) {
   216   clearSearch(ctx.cm);
   217   doSearch(ctx, false, query);
   218 }
   220 /**
   221  * Finds the next item based on the currently saved search.
   222  */
   223 function findNext(ctx, query) {
   224   doSearch(ctx, false, query);
   225 }
   227 /**
   228  * Finds the previous item based on the currently saved search.
   229  */
   230 function findPrev(ctx, query) {
   231   doSearch(ctx, true, query);
   232 }
   235 // Export functions
   237 [
   238   initialize, hasBreakpoint, addBreakpoint, removeBreakpoint,
   239   getBreakpoints, setDebugLocation, getDebugLocation,
   240   clearDebugLocation, find, findNext, findPrev
   241 ].forEach(function (func) { module.exports[func.name] = func; });

mercurial