|
| 1 | +const { |
| 2 | + ArrayPrototypeShift, |
| 3 | + ArrayPrototypeSplice, |
| 4 | + ArrayPrototypeIncludes, |
| 5 | + StringPrototypeSplit, |
| 6 | + RegExpPrototypeExec, |
| 7 | +} = primordials; |
| 8 | + |
| 9 | +function parseBoolean(value) { |
| 10 | + return value === 'true' || value === '1' || value === 'yes'; |
| 11 | +} |
| 12 | + |
| 13 | +function validatePauseOnExceptionState(value) { |
| 14 | + const validStates = ['uncaught', 'none', 'all']; |
| 15 | + if (!ArrayPrototypeIncludes(validStates, value)) { |
| 16 | + throw new Error(`Invalid state passed for pauseOnExceptionState: ${value}. Must be one of 'uncaught', 'none', or 'all'.`); |
| 17 | + } |
| 18 | + return value; |
| 19 | +} |
| 20 | + |
| 21 | +function parseArguments(argv) { |
| 22 | + const legacyArguments = processLegacyArgs(argv) |
| 23 | + |
| 24 | + let options = { |
| 25 | + pauseOnExceptionState: undefined, |
| 26 | + inspectResumeOnStart: undefined |
| 27 | + } |
| 28 | + |
| 29 | + // `NODE_INSPECT_OPTIONS` is parsed first and can be overwritten by command line arguments |
| 30 | + |
| 31 | + if (process.env.NODE_INSPECT_OPTIONS) { |
| 32 | + const envOptions = StringPrototypeSplit(process.env.NODE_INSPECT_OPTIONS, ' '); |
| 33 | + for (let i = 0; i < envOptions.length; i++) { |
| 34 | + switch (envOptions[i]) { |
| 35 | + case '--pause-on-exception-state': |
| 36 | + options.pauseOnExceptionState = validatePauseOnExceptionState(envOptions[++i]); |
| 37 | + break; |
| 38 | + case '--inspect-resume-on-start': |
| 39 | + options.inspectResumeOnStart = parseBoolean(envOptions[++i]); |
| 40 | + break; |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + for (let i = 0; i < argv.length;) { |
| 46 | + switch (argv[i]) { |
| 47 | + case '--pause-on-exception-state': |
| 48 | + options.pauseOnExceptionState = validatePauseOnExceptionState(argv[i+1]); |
| 49 | + ArrayPrototypeSplice(argv, i, 2); |
| 50 | + break; |
| 51 | + case '--inspect-resume-on-start': |
| 52 | + options.inspectResumeOnStart = parseBoolean(argv[i+1]); |
| 53 | + ArrayPrototypeSplice(argv, i, 2); |
| 54 | + break; |
| 55 | + default: |
| 56 | + i++; |
| 57 | + break; |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + return {...options, ...legacyArguments}; |
| 62 | +} |
| 63 | + |
| 64 | +// the legacy `node inspect` options assumed the first argument was the target |
| 65 | +// to avoid breaking existing scripts, we maintain this behavior |
| 66 | + |
| 67 | +function processLegacyArgs(args) { |
| 68 | + const target = ArrayPrototypeShift(args); |
| 69 | + let host = '127.0.0.1'; |
| 70 | + let port = 9229; |
| 71 | + let isRemote = false; |
| 72 | + let script = target; |
| 73 | + let scriptArgs = args; |
| 74 | + |
| 75 | + const hostMatch = RegExpPrototypeExec(/^([^:]+):(\d+)$/, target); |
| 76 | + const portMatch = RegExpPrototypeExec(/^--port=(\d+)$/, target); |
| 77 | + |
| 78 | + if (hostMatch) { |
| 79 | + // Connecting to remote debugger |
| 80 | + host = hostMatch[1]; |
| 81 | + port = Number(hostMatch[2]); |
| 82 | + isRemote = true; |
| 83 | + script = null; |
| 84 | + } else if (portMatch) { |
| 85 | + // Start on custom port |
| 86 | + port = Number(portMatch[1]); |
| 87 | + script = args[0]; |
| 88 | + scriptArgs = ArrayPrototypeSlice(args, 1); |
| 89 | + } else if (args.length === 1 && RegExpPrototypeExec(/^\d+$/, args[0]) !== null && |
| 90 | + target === '-p') { |
| 91 | + // Start debugger against a given pid |
| 92 | + const pid = Number(args[0]); |
| 93 | + try { |
| 94 | + process._debugProcess(pid); |
| 95 | + } catch (e) { |
| 96 | + if (e.code === 'ESRCH') { |
| 97 | + process.stderr.write(`Target process: ${pid} doesn't exist.\n`); |
| 98 | + process.exit(kGenericUserError); |
| 99 | + } |
| 100 | + throw e; |
| 101 | + } |
| 102 | + script = null; |
| 103 | + isRemote = true; |
| 104 | + } |
| 105 | + |
| 106 | + return { |
| 107 | + host, port, isRemote, script, scriptArgs, |
| 108 | + }; |
| 109 | +} |
| 110 | + |
| 111 | +module.exports = parseArguments; |
0 commit comments