Repository: puppeteer/puppeteer
File: packages/puppeteer-core/src/bidi/core/Session.ts (TypeScript)

Code before:
  readonly #disposables = new DisposableStack();
  readonly #info: Bidi.Session.NewResult;
  readonly browser!: Browser;
  @bubble()
  accessor connection: Connection;
  // keep-sorted end

  private constructor(connection: Connection, info: Bidi.Session.NewResult) {
    super();
    // keep-sorted start
    this.#info = info;
    this.connection = connection;
    // keep-sorted end
  }

  async #initialize(): Promise<void> {
    // SAFETY: We use `any` to allow assignment of the readonly property.
    (this as any).browser = await Browser.from(this);

    const browserEmitter = this.#disposables.use(this.browser);
    browserEmitter.once('closed', ({reason}) => {
      this.dispose(reason);
    });

    // TODO: Currently, some implementations do not emit navigationStarted event
    // for fragement navigations (as per spec) and some do. This code emits a
    // synthetic navigationStarted to work around this inconsistency.
    const seen = new WeakSet();
    this.on('browsingContext.fragmentNavigated', info => {
      if (seen.has(info)) {
        return;
      }
      seen.add(info);
      this.emit('browsingContext.navigationStarted', info);
      this.emit('browsingContext.fragmentNavigated', info);
    });
  }

  // keep-sorted start block=yes
  get capabilities(): Bidi.Session.NewResult['capabilities'] {
    return this.#info.capabilities;
  }
  get disposed(): boolean {
    return this.ended;
  }
  get ended(): boolean {
    return this.#reason !== undefined;
  }
  get id(): string {
    return this.#info.sessionId;
  }

Review comment (suggestion):
```suggestion
    // for fragment navigations (as per spec) and some do. This code emits a
```

Code after:
  readonly #disposables = new DisposableStack();
  readonly #info: Bidi.Session.NewResult;
  readonly browser!: Browser;
  @bubble()
  accessor connection: Connection;
  // keep-sorted end

  private constructor(connection: Connection, info: Bidi.Session.NewResult) {
    super();
    // keep-sorted start
    this.#info = info;
    this.connection = connection;
    // keep-sorted end
  }

  async #initialize(): Promise<void> {
    // SAFETY: We use `any` to allow assignment of the readonly property.
    (this as any).browser = await Browser.from(this);

    const browserEmitter = this.#disposables.use(this.browser);
    browserEmitter.once('closed', ({reason}) => {
      this.dispose(reason);
    });

    // TODO: Currently, some implementations do not emit navigationStarted event
    // for fragment navigations (as per spec) and some do. This could emits a
    // synthetic navigationStarted to work around this inconsistency.
    const seen = new WeakSet();
    this.on('browsingContext.fragmentNavigated', info => {
      if (seen.has(info)) {
        return;
      }
      seen.add(info);
      this.emit('browsingContext.navigationStarted', info);
      this.emit('browsingContext.fragmentNavigated', info);
    });
  }

  // keep-sorted start block=yes
  get capabilities(): Bidi.Session.NewResult['capabilities'] {
    return this.#info.capabilities;
  }
  get disposed(): boolean {
    return this.ended;
  }
  get ended(): boolean {
    return this.#reason !== undefined;
  }
  get id(): string {
    return this.#info.sessionId;
  }