2017-10-29 18:19:24 +01:00
'use strict' ;
2019-11-22 18:04:46 +01:00
const {
2022-12-17 20:15:24 +01:00
ArrayPrototypePushApply ,
2024-04-21 18:53:08 +02:00
ArrayPrototypeSome ,
2020-11-16 16:39:28 +01:00
FunctionPrototypeBind ,
2020-05-22 14:02:04 +02:00
ObjectDefineProperty ,
2019-11-22 18:04:46 +01:00
ObjectKeys ,
2022-01-25 07:14:18 -08:00
ObjectPrototypeHasOwnProperty ,
2022-09-10 20:01:42 +03:00
RegExpPrototypeExec ,
2022-09-13 09:41:19 +03:00
SafeWeakMap ,
2019-11-22 18:04:46 +01:00
} = primordials ;
2019-04-09 09:55:53 +02:00
2022-09-10 20:01:42 +03:00
const { validatePort } = require ( 'internal/validators' ) ;
2023-07-27 09:31:20 -03:00
const permission = require ( 'internal/process/permission' ) ;
2022-09-10 20:01:42 +03:00
const kMinPort = 1024 ;
const kMaxPort = 65535 ;
const kInspectArgRegex = /--inspect(?:-brk|-port)?|--debug-port/ ;
2022-12-01 22:12:07 -05:00
const kInspectMsgRegex = /Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\/|For help, see: https:\/\/nodejs\.org\/en\/docs\/inspector|Debugger attached|Waiting for the debugger to disconnect\.\.\./ ;
2022-09-10 20:01:42 +03:00
2022-09-13 09:41:19 +03:00
const _isUsingInspector = new SafeWeakMap ( ) ;
function isUsingInspector ( execArgv = process . execArgv ) {
if ( ! _isUsingInspector . has ( execArgv ) ) {
_isUsingInspector . set ( execArgv ,
ArrayPrototypeSome ( execArgv , ( arg ) => RegExpPrototypeExec ( kInspectArgRegex , arg ) !== null ) ||
RegExpPrototypeExec ( kInspectArgRegex , process . env . NODE _OPTIONS ) !== null ) ;
}
return _isUsingInspector . get ( execArgv ) ;
2022-09-10 20:01:42 +03:00
}
let debugPortOffset = 1 ;
function getInspectPort ( inspectPort ) {
if ( typeof inspectPort === 'function' ) {
inspectPort = inspectPort ( ) ;
} else if ( inspectPort == null ) {
inspectPort = process . debugPort + debugPortOffset ;
if ( inspectPort > kMaxPort )
inspectPort = inspectPort - kMaxPort + kMinPort - 1 ;
debugPortOffset ++ ;
}
validatePort ( inspectPort ) ;
return inspectPort ;
}
2017-10-29 18:19:24 +01:00
let session ;
function sendInspectorCommand ( cb , onError ) {
2019-01-15 21:57:29 +08:00
const { hasInspector } = internalBinding ( 'config' ) ;
2017-10-29 18:19:24 +01:00
if ( ! hasInspector ) return onError ( ) ;
2023-07-27 09:31:20 -03:00
// Do not preview when the permission model is enabled
// because this feature require access to the inspector,
// which is unavailable in this case.
if ( permission . isEnabled ( ) ) return onError ( ) ;
2019-01-30 23:19:45 +08:00
const inspector = require ( 'inspector' ) ;
2017-10-29 18:19:24 +01:00
if ( session === undefined ) session = new inspector . Session ( ) ;
2020-01-01 16:42:17 +01:00
session . connect ( ) ;
2017-10-29 18:19:24 +01:00
try {
2020-01-01 16:42:17 +01:00
return cb ( session ) ;
} finally {
session . disconnect ( ) ;
2017-10-29 18:19:24 +01:00
}
}
2022-09-10 20:01:42 +03:00
function isInspectorMessage ( string ) {
return isUsingInspector ( ) && RegExpPrototypeExec ( kInspectMsgRegex , string ) !== null ;
}
2019-01-15 21:57:29 +08:00
// Create a special require function for the inspector command line API
function installConsoleExtensions ( commandLineApi ) {
if ( commandLineApi . require ) { return ; }
const { tryGetCwd } = require ( 'internal/process/execution' ) ;
2019-05-18 22:48:46 -05:00
const CJSModule = require ( 'internal/modules/cjs/loader' ) . Module ;
2022-12-13 22:24:28 +01:00
const { makeRequireFunction } = require ( 'internal/modules/helpers' ) ;
2019-01-15 21:57:29 +08:00
const consoleAPIModule = new CJSModule ( '<inspector console>' ) ;
const cwd = tryGetCwd ( ) ;
2022-12-17 20:15:24 +01:00
consoleAPIModule . paths = [ ] ;
ArrayPrototypePushApply ( consoleAPIModule . paths , CJSModule . _nodeModulePaths ( cwd ) ) ;
ArrayPrototypePushApply ( consoleAPIModule . paths , CJSModule . globalPaths ) ;
2019-01-15 21:57:29 +08:00
commandLineApi . require = makeRequireFunction ( consoleAPIModule ) ;
}
// Wrap a console implemented by Node.js with features from the VM inspector
2022-05-18 23:30:49 +08:00
function wrapConsole ( consoleFromNode ) {
const { consoleCall , console : consoleFromVM } = internalBinding ( 'inspector' ) ;
2019-11-22 18:04:46 +01:00
for ( const key of ObjectKeys ( consoleFromVM ) ) {
2019-01-15 21:57:29 +08:00
// If global console has the same method as inspector console,
// then wrap these two methods into one. Native wrapper will preserve
// the original stack.
2022-01-25 07:14:18 -08:00
if ( ObjectPrototypeHasOwnProperty ( consoleFromNode , key ) ) {
2020-11-16 16:39:28 +01:00
consoleFromNode [ key ] = FunctionPrototypeBind (
consoleCall ,
consoleFromNode ,
consoleFromVM [ key ] ,
2023-02-14 18:45:16 +01:00
consoleFromNode [ key ] ,
2020-11-16 16:39:28 +01:00
) ;
2020-05-22 14:02:04 +02:00
ObjectDefineProperty ( consoleFromNode [ key ] , 'name' , {
2022-06-03 10:23:58 +02:00
_ _proto _ _ : null ,
2023-02-28 12:14:11 +01:00
value : key ,
2020-05-22 14:02:04 +02:00
} ) ;
2019-01-15 21:57:29 +08:00
} else {
// Add additional console APIs from the inspector
consoleFromNode [ key ] = consoleFromVM [ key ] ;
}
}
}
2017-10-29 18:19:24 +01:00
module . exports = {
2022-09-10 20:01:42 +03:00
getInspectPort ,
2019-01-15 21:57:29 +08:00
installConsoleExtensions ,
2022-09-10 20:01:42 +03:00
isInspectorMessage ,
isUsingInspector ,
2019-01-15 21:57:29 +08:00
sendInspectorCommand ,
wrapConsole ,
2017-10-29 18:19:24 +01:00
} ;