in packages/relay-devtools-core/src/launchEditor.js [112:178]
export default function launchEditor(
maybeRelativePath: string,
lineNumber: number,
absoluteProjectRoots: Array<string>
) {
// We use relative paths at Facebook with deterministic builds.
// This is why our internal tooling calls Relay DevTools with absoluteProjectRoots.
// If the filename is absolute then we don't need to care about this.
let filePath;
if (isAbsolute(maybeRelativePath)) {
if (existsSync(maybeRelativePath)) {
filePath = maybeRelativePath;
}
} else {
for (let i = 0; i < absoluteProjectRoots.length; i++) {
const projectRoot = absoluteProjectRoots[i];
const joinedPath = join(projectRoot, maybeRelativePath);
if (existsSync(joinedPath)) {
filePath = joinedPath;
break;
}
}
}
if (!filePath) {
return;
}
// Sanitize lineNumber to prevent malicious use on win32
// via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333
if (lineNumber && isNaN(lineNumber)) {
return;
}
// eslint-disable-next-line prefer-const
let [editor, ...args] = guessEditor();
if (!editor) {
return;
}
if (lineNumber) {
args = args.concat(getArgumentsForLineNumber(editor, filePath, lineNumber));
} else {
args.push(filePath);
}
if (childProcess && isTerminalEditor(editor)) {
// There's an existing editor process already and it's attached
// to the terminal, so go kill it. Otherwise two separate editor
// instances attach to the stdin/stdout which gets confusing.
childProcess.kill('SIGKILL');
}
if (process.platform === 'win32') {
// On Windows, launch the editor in a shell because spawn can only
// launch .exe files.
childProcess = spawn('cmd.exe', ['/C', editor].concat(args), {
stdio: 'inherit',
});
} else {
childProcess = spawn(editor, args, { stdio: 'inherit' });
}
childProcess.on('error', function() {});
childProcess.on('exit', function(errorCode) {
childProcess = null;
});
}