make-debugger.js (4494B)
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/. */ 4 5 "use strict"; 6 7 const EventEmitter = require("resource://devtools/shared/event-emitter.js"); 8 const Debugger = require("Debugger"); 9 10 const { 11 reportException, 12 } = require("resource://devtools/shared/DevToolsUtils.js"); 13 14 /** 15 * Multiple actors that use a |Debugger| instance come in a few versions, each 16 * with a different set of debuggees. One version for content tabs (globals 17 * within a tab), one version for chrome debugging (all globals), and sometimes 18 * a third version for addon debugging (chrome globals the addon is loaded in 19 * and content globals the addon injects scripts into). The |makeDebugger| 20 * function helps us avoid repeating the logic for finding and maintaining the 21 * correct set of globals for a given |Debugger| instance across each version of 22 * all of our actors. 23 * 24 * The |makeDebugger| function expects a single object parameter with the 25 * following properties: 26 * 27 * @param Function findDebuggees 28 * Called with one argument: a |Debugger| instance. This function should 29 * return an iterable of globals to be added to the |Debugger| 30 * instance. The globals are the actual global objects and aren't wrapped 31 * in in a |Debugger.Object|. 32 * 33 * @param Function shouldAddNewGlobalAsDebuggee 34 * Called with one argument: a |Debugger.Object| wrapping a global 35 * object. This function must return |true| if the global object should 36 * be added as debuggee, and |false| otherwise. 37 * 38 * @returns Debugger 39 * Returns a |Debugger| instance that can manage its set of debuggee 40 * globals itself and is decorated with the |EventEmitter| class. 41 * 42 * Existing |Debugger| properties set on the returned |Debugger| 43 * instance: 44 * 45 * - onNewGlobalObject: The |Debugger| will automatically add new 46 * globals as debuggees if calling |shouldAddNewGlobalAsDebuggee| 47 * with the global returns true. 48 * 49 * - uncaughtExceptionHook: The |Debugger| already has an error 50 * reporter attached to |uncaughtExceptionHook|, so if any 51 * |Debugger| hooks fail, the error will be reported. 52 * 53 * New properties set on the returned |Debugger| instance: 54 * 55 * - addDebuggees: A function which takes no arguments. It adds all 56 * current globals that should be debuggees (as determined by 57 * |findDebuggees|) to the |Debugger| instance. 58 */ 59 module.exports = function makeDebugger({ 60 findDebuggees, 61 shouldAddNewGlobalAsDebuggee, 62 } = {}) { 63 const dbg = new Debugger(); 64 EventEmitter.decorate(dbg); 65 66 // By default, we disable asm.js and WASM debugging because of performance reason. 67 // Enabling asm.js debugging (allowUnobservedAsmJS=false) will make asm.js fallback to JS compiler 68 // and be debugging as a regular JS script. 69 dbg.allowUnobservedAsmJS = true; 70 // Enabling WASM debugging (allowUnobservedWasm=false) will make the engine compile WASM scripts 71 // into different machine code with debugging instructions. This significantly increase the memory usage of it. 72 dbg.allowUnobservedWasm = true; 73 74 dbg.uncaughtExceptionHook = reportDebuggerHookException; 75 76 const onNewGlobalObject = function (global) { 77 if (shouldAddNewGlobalAsDebuggee(global)) { 78 safeAddDebuggee(this, global); 79 } 80 }; 81 82 dbg.onNewGlobalObject = onNewGlobalObject; 83 dbg.addDebuggees = function () { 84 for (const global of findDebuggees(this)) { 85 safeAddDebuggee(this, global); 86 } 87 }; 88 89 dbg.disable = function () { 90 dbg.removeAllDebuggees(); 91 dbg.onNewGlobalObject = undefined; 92 }; 93 94 dbg.enable = function () { 95 dbg.addDebuggees(); 96 dbg.onNewGlobalObject = onNewGlobalObject; 97 }; 98 dbg.findDebuggees = function (includeAllSameProcessGlobals) { 99 return findDebuggees(dbg, includeAllSameProcessGlobals); 100 }; 101 102 return dbg; 103 }; 104 105 const reportDebuggerHookException = e => reportException("DBG-SERVER", e); 106 107 /** 108 * Add |global| as a debuggee to |dbg|, handling error cases. 109 */ 110 function safeAddDebuggee(dbg, global) { 111 let globalDO; 112 try { 113 globalDO = dbg.addDebuggee(global); 114 } catch (e) { 115 // Ignoring attempt to add the debugger's compartment as a debuggee. 116 return; 117 } 118 119 if (dbg.onNewDebuggee) { 120 dbg.onNewDebuggee(globalDO); 121 } 122 }