static getLayoutShiftEvents(processedTrace) {
    const layoutShiftEvents = [];

    // Chromium will set `had_recent_input` if there was recent user input, which
    // skips shift events from contributing to CLS. This flag is also set when
    // Lighthouse changes the emulation size. This results in the first few shift
    // events having `had_recent_input` set, so ignore it for those events.
    // See https://bugs.chromium.org/p/chromium/issues/detail?id=1094974.
    let mustRespectHadRecentInput = false;

    // Even if emulation was applied before navigating, Chrome will issue a viewport
    // change event after a navigation starts which is treated as an interaction when
    // deciding the `had_recent_input` flag. Anything within 500ms of this event should
    // always be counted for CLS regardless of the `had_recent_input` flag.
    // See https://bugs.chromium.org/p/chromium/issues/detail?id=1302667
    let viewportChangeTs = processedTrace.timestamps.timeOrigin;
    const firstViewportEvent = processedTrace.frameEvents.find(event => event.name === 'viewport');
    if (firstViewportEvent) {
      viewportChangeTs = firstViewportEvent.ts;
    }

    for (const event of processedTrace.frameTreeEvents) {
      if (event.name !== 'LayoutShift' ||
          !event.args.data ||
          event.args.data.is_main_frame === undefined) {
        continue;
      }

      // For all-frames CLS calculation, we rely on `weighted_score_delta`
      // All layout shift events should have this since M90: https://crbug.com/1173139
      if (event.args.data.weighted_score_delta === undefined) {
        throw new Error('CLS missing weighted_score_delta');
      }

      if (event.args.data.had_recent_input) {
        const timing = (event.ts - viewportChangeTs) / 1000;
        if (timing > RECENT_INPUT_WINDOW || mustRespectHadRecentInput) continue;
      } else {
        mustRespectHadRecentInput = true;
      }

      layoutShiftEvents.push({
        ts: event.ts,
        isMainFrame: event.args.data.is_main_frame,
        weightedScore: event.args.data.weighted_score_delta,
        impactedNodes: event.args.data.impacted_nodes,
        event,
      });
    }

    return layoutShiftEvents;
  }
Returns all LayoutShift events that had no recent input.
Only a `weightedScore` per event is returned. For non-main-frame events, this is
the only score that matters. For main-frame events, `weighted_score_delta === score`.
@see https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/layout/layout_shift_tracker.cc;l=492-495;drc=de3b3a8a8839269c6b44403fa38a13a1ed12fed5
@param {LH.Artifacts.ProcessedTrace} processedTrace
@return {Array<LayoutShiftEvent>}