Repository: microsoft/playwright
File: packages/playwright/src/cli/client/session.ts (TypeScript)

Code before:
  }

  private _onMessage(object: { id: number, error?: string, result: any }) {
    if (object.id && this._callbacks.has(object.id)) {
      const callback = this._callbacks.get(object.id)!;
      this._callbacks.delete(object.id);
      if (object.error)
        callback.reject(new Error(object.error));
      else
        callback.resolve(object.result);
    } else if (object.id) {
      throw new Error(`Unexpected message id: ${object.id}`);
    } else {
      throw new Error(`Unexpected message without id: ${JSON.stringify(object)}`);
    }
  }

  private _sessionFile(suffix: string) {
    return path.resolve(this._clientInfo.daemonProfilesDir, `${this.name}${suffix}`);
  }

  private async _startDaemon(): Promise<net.Socket> {
    await fs.promises.mkdir(this._clientInfo.daemonProfilesDir, { recursive: true });
    const cliPath = path.join(__dirname, '../../../cli.js');

    const sessionConfigFile = this._sessionFile('.session');
    this.config.version = this._clientInfo.version;
    this.config.timestamp = Date.now();
    await fs.promises.writeFile(sessionConfigFile, JSON.stringify(this.config, null, 2));

    const errLog = this._sessionFile('.err');
    const err = fs.openSync(errLog, 'w');

    const args = [
      cliPath,
      'run-cli-server',
      `--daemon-session=${sessionConfigFile}`,
    ];

    const child = spawn(process.execPath, args, {
      detached: true,
      stdio: ['ignore', 'pipe', err],
      cwd: process.cwd(), // Will be used as root.
    });

    let signalled = false;
    const sigintHandler = () => {
      signalled = true;
      child.kill('SIGINT');
    };
    const sigtermHandler = () => {

Review comment (suggestion):
I'd recommend to append `.err` instead of replacing, just in case there is `.session` in the middle somewhere.

Code after:
  }

  private _onMessage(object: { id: number, error?: string, result: any }) {
    if (object.id && this._callbacks.has(object.id)) {
      const callback = this._callbacks.get(object.id)!;
      this._callbacks.delete(object.id);
      if (object.error)
        callback.reject(new Error(object.error));
      else
        callback.resolve(object.result);
    } else if (object.id) {
      throw new Error(`Unexpected message id: ${object.id}`);
    } else {
      throw new Error(`Unexpected message without id: ${JSON.stringify(object)}`);
    }
  }

  private async _startDaemon(): Promise<net.Socket> {
    await fs.promises.mkdir(this._sessionFile.daemonDir, { recursive: true });
    const cliPath = path.join(__dirname, '../../../cli.js');

    this.config.version = this.config.version;
    this.config.timestamp = Date.now();
    await fs.promises.writeFile(this._sessionFile.file, JSON.stringify(this.config, null, 2));

    const errLog = this._sessionFile.file.replace('.session', '.err');
    const err = fs.openSync(errLog, 'w');

    const args = [
      cliPath,
      'run-cli-server',
      `--daemon-session=${this._sessionFile.file}`,
    ];

    const child = spawn(process.execPath, args, {
      detached: true,
      stdio: ['ignore', 'pipe', err],
      cwd: process.cwd(), // Will be used as root.
    });

    let signalled = false;
    const sigintHandler = () => {
      signalled = true;
      child.kill('SIGINT');
    };
    const sigtermHandler = () => {
      signalled = true;
      child.kill('SIGTERM');
    };
    process.on('SIGINT', sigintHandler);
    process.on('SIGTERM', sigtermHandler);