Wed, 31 Dec 2014 06:09:35 +0100
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; });