static async computeTbtImpact(artifacts, context) {
    let tbtImpact = 0;

    // We still want to surface this audit in snapshot mode, but since we don't compute TBT
    // the impact should always be undefined.
    const {GatherContext, DevtoolsLog, Trace} = artifacts;
    if (GatherContext.gatherMode !== 'navigation') {
      return undefined;
    }

    // Since the artifacts are optional, it's still possible for them to be missing in navigation mode.
    // Navigation mode does compute TBT so we should surface a numerical savings of 0.
    if (!DevtoolsLog || !Trace) {
      return 0;
    }

    const metricComputationData = Audit.makeMetricComputationDataInput(artifacts, context);

    try {
      // The TBT impact of style/layout tasks is correlated to the DOM size.
      // Even in situations where the page forces a style recalc, the DOM size is partially to blame
      // for any time spent blocking the main thread.
      //
      // `tbtImpact` should be exactly 0 for small DOMs since `selfTbtImpact` accounts for the blocking
      // time and not the main thread time.
      const tbtImpactTasks = await TBTImpactTasks.request(metricComputationData, context);
      for (const task of tbtImpactTasks) {
        if (task.group.id !== 'styleLayout') continue;
        tbtImpact += task.selfTbtImpact;
      }
    } catch {}

    return Math.round(tbtImpact);
  }
@param {LH.Artifacts} artifacts
@param {LH.Audit.Context} context
@return {Promise<number|undefined>}