1'use strict'; 2 3const { 4 ArrayPrototypeSome, 5 ArrayPrototypePushApply, 6 FunctionPrototypeBind, 7 ObjectDefineProperty, 8 ObjectKeys, 9 ObjectPrototypeHasOwnProperty, 10 RegExpPrototypeExec, 11 SafeWeakMap, 12} = primordials; 13 14const { validatePort } = require('internal/validators'); 15 16const kMinPort = 1024; 17const kMaxPort = 65535; 18const kInspectArgRegex = /--inspect(?:-brk|-port)?|--debug-port/; 19const kInspectMsgRegex = /Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\/|For help, see: https:\/\/nodejs\.org\/en\/docs\/inspector|Debugger attached|Waiting for the debugger to disconnect\.\.\./; 20 21const _isUsingInspector = new SafeWeakMap(); 22function isUsingInspector(execArgv = process.execArgv) { 23 if (!_isUsingInspector.has(execArgv)) { 24 _isUsingInspector.set(execArgv, 25 ArrayPrototypeSome(execArgv, (arg) => RegExpPrototypeExec(kInspectArgRegex, arg) !== null) || 26 RegExpPrototypeExec(kInspectArgRegex, process.env.NODE_OPTIONS) !== null); 27 } 28 return _isUsingInspector.get(execArgv); 29} 30 31let debugPortOffset = 1; 32function getInspectPort(inspectPort) { 33 if (typeof inspectPort === 'function') { 34 inspectPort = inspectPort(); 35 } else if (inspectPort == null) { 36 inspectPort = process.debugPort + debugPortOffset; 37 if (inspectPort > kMaxPort) 38 inspectPort = inspectPort - kMaxPort + kMinPort - 1; 39 debugPortOffset++; 40 } 41 validatePort(inspectPort); 42 43 return inspectPort; 44} 45 46let session; 47function sendInspectorCommand(cb, onError) { 48 const { hasInspector } = internalBinding('config'); 49 if (!hasInspector) return onError(); 50 const inspector = require('inspector'); 51 if (session === undefined) session = new inspector.Session(); 52 session.connect(); 53 try { 54 return cb(session); 55 } finally { 56 session.disconnect(); 57 } 58} 59 60function isInspectorMessage(string) { 61 return isUsingInspector() && RegExpPrototypeExec(kInspectMsgRegex, string) !== null; 62} 63 64// Create a special require function for the inspector command line API 65function installConsoleExtensions(commandLineApi) { 66 if (commandLineApi.require) { return; } 67 const { tryGetCwd } = require('internal/process/execution'); 68 const CJSModule = require('internal/modules/cjs/loader').Module; 69 const { makeRequireFunction } = require('internal/modules/cjs/helpers'); 70 const consoleAPIModule = new CJSModule('<inspector console>'); 71 const cwd = tryGetCwd(); 72 consoleAPIModule.paths = []; 73 ArrayPrototypePushApply(consoleAPIModule.paths, CJSModule._nodeModulePaths(cwd)); 74 ArrayPrototypePushApply(consoleAPIModule.paths, CJSModule.globalPaths); 75 commandLineApi.require = makeRequireFunction(consoleAPIModule); 76} 77 78// Wrap a console implemented by Node.js with features from the VM inspector 79function wrapConsole(consoleFromNode) { 80 const { consoleCall, console: consoleFromVM } = internalBinding('inspector'); 81 for (const key of ObjectKeys(consoleFromVM)) { 82 // If global console has the same method as inspector console, 83 // then wrap these two methods into one. Native wrapper will preserve 84 // the original stack. 85 if (ObjectPrototypeHasOwnProperty(consoleFromNode, key)) { 86 consoleFromNode[key] = FunctionPrototypeBind( 87 consoleCall, 88 consoleFromNode, 89 consoleFromVM[key], 90 consoleFromNode[key], 91 ); 92 ObjectDefineProperty(consoleFromNode[key], 'name', { 93 __proto__: null, 94 value: key, 95 }); 96 } else { 97 // Add additional console APIs from the inspector 98 consoleFromNode[key] = consoleFromVM[key]; 99 } 100 } 101} 102 103module.exports = { 104 getInspectPort, 105 installConsoleExtensions, 106 isInspectorMessage, 107 isUsingInspector, 108 sendInspectorCommand, 109 wrapConsole, 110}; 111