• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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