Repository: facebook/react
File: packages/react-devtools-shared/src/bridge.js (JavaScript)

Code before:
  get wall(): Wall {
    return this._wall;
  }

  send<EventName: $Keys<OutgoingEvents>>(
    event: EventName,
    ...payload: $ElementType<OutgoingEvents, EventName>
  ) {
    if (this._isShutdown) {
      console.warn(
        `Cannot send message "${event}" through a Bridge that has been shutdown.`,
      );
      return;
    }

    // When we receive a message:
    // - we add it to our queue of messages to be sent
    // - if there hasn't been a message recently, we set a timer for 0 ms in
    //   the future, allowing all messages created in the same tick to be sent
    //   together
    // - if there *has* been a message flushed in the last BATCH_DURATION ms
    //   (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
    //   be set, and we'll simply add to the queue and wait for that
    this._messageQueue.push(event, payload);
    if (!this._timeoutID) {
      this._timeoutID = setTimeout(this._flush, 0);
    }
  }

  shutdown() {
    if (this._isShutdown) {
      console.warn('Bridge was already shutdown.');
      return;
    }

    // Queue the shutdown outgoing message for subscribers.
    this.emit('shutdown');
    this.send('shutdown');

    // Mark this bridge as destroyed, i.e. disable its public API.
    this._isShutdown = true;

    // Disable the API inherited from EventEmitter that can add more listeners and send more messages.
    // $FlowFixMe[cannot-write] This property is not writable.
    this.addListener = function () {};
    // $FlowFixMe[cannot-write] This property is not writable.
    this.emit = function () {};
    // NOTE: There's also EventEmitter API like `on` and `prependListener` that we didn't add to our Flow type of EventEmitter.

    // Unsubscribe this bridge incoming message listeners to be sure, and so they don't have to do that.
    this.removeAllListeners();

Review comment (suggestion):
This is an unfortunate hack. I couldn't figure out how to mock this without rewriting all the tests. In particular all the sync one needs to move to async ones.

That's because React itself also uses queueMicrotask and the tests don't expect that those are mocked as a timer, but they expect that the bridge is mocked as a timer.

Code after:
  }

  send<EventName: $Keys<OutgoingEvents>>(
    event: EventName,
    ...payload: $ElementType<OutgoingEvents, EventName>
  ) {
    if (this._isShutdown) {
      console.warn(
        `Cannot send message "${event}" through a Bridge that has been shutdown.`,
      );
      return;
    }

    // When we receive a message:
    // - we add it to our queue of messages to be sent
    // - if there hasn't been a message recently, we set a timer for 0 ms in
    //   the future, allowing all messages created in the same tick to be sent
    //   together
    // - if there *has* been a message flushed in the last BATCH_DURATION ms
    //   (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
    //   be set, and we'll simply add to the queue and wait for that
    this._messageQueue.push(event, payload);
    if (!this._scheduledFlush) {
      this._scheduledFlush = true;
      // $FlowFixMe
      if (typeof devtoolsJestTestScheduler === 'function') {
        // This exists just for our own jest tests.
        // They're written in such a way that we can neither mock queueMicrotask
        // because then we break React DOM and we can't not mock it because then
        // we can't synchronously flush it. So they need to be rewritten.
        // $FlowFixMe
        devtoolsJestTestScheduler(this._flush); // eslint-disable-line no-undef
      } else {
        queueMicrotask(this._flush);
      }
    }
  }

  shutdown() {
    if (this._isShutdown) {
      console.warn('Bridge was already shutdown.');
      return;
    }

    // Queue the shutdown outgoing message for subscribers.
    this.emit('shutdown');
    this.send('shutdown');

    // Mark this bridge as destroyed, i.e. disable its public API.
    this._isShutdown = true;