static async getTopLayoutShifts(trace, traceEngineResult, context) {
    const {impactByNodeId} = await CumulativeLayoutShift.request(trace, context);
    const clusters = traceEngineResult.LayoutShifts.clusters ?? [];
    const layoutShiftEvents =
      /** @type {import('../../lib/trace-engine.js').SaneSyntheticLayoutShift[]} */(
        clusters.flatMap(c => c.events)
      );

    return layoutShiftEvents
      .sort((a, b) => b.args.data.weighted_score_delta - a.args.data.weighted_score_delta)
      .slice(0, MAX_LAYOUT_SHIFTS)
      .flatMap(event => {
        const nodeIds = [];
        const impactedNodes = event.args.data.impacted_nodes || [];
        const biggestImpactedNodeId =
          this.getBiggestImpactNodeForShiftEvent(impactedNodes, impactByNodeId);
        if (biggestImpactedNodeId !== undefined) {
          nodeIds.push(biggestImpactedNodeId);
        }

        return nodeIds.map(nodeId => ({nodeId}));
      });
  }
This function finds the top (up to 15) layout shifts on the page, and returns
the id of the largest impacted node of each shift, along with any related nodes
that may have caused the shift.

@param {LH.Trace} trace
@param {LH.Artifacts.TraceEngineResult['parsedTrace']} traceEngineResult
@param {LH.Gatherer.Context} context
@return {Promise<Array<{nodeId: number}>>}