export default function launchEditor()

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;
  });
}