static async audit(artifacts) {
    if (/HeadlessChrome/.test(artifacts.HostProduct)) {
      return {
        score: null,
        notApplicable: true,
        warnings: [str_(UIStrings.warningHeadless)],
      };
    }

    const failures = artifacts.BFCacheFailures;
    if (!failures.length) return {score: 1};

    // TODO: Analyze more than one bf cache failure.
    const {notRestoredReasonsTree} = failures[0];

    let totalIssues = 0;

    /** @type {LH.Audit.Details.TableItem[]} */
    const results = [];

    for (const failureType of ORDERED_FAILURE_TYPES) {
      const reasonsMap = notRestoredReasonsTree[failureType];

      for (const [reason, frameUrls] of Object.entries(reasonsMap)) {
        totalIssues += frameUrls.length;

        results.push({
          reason: NotRestoredReasonDescription[reason]?.name ?? reason,
          failureType: FAILURE_TYPE_TO_STRING[failureType],
          subItems: {
            type: 'subitems',
            items: frameUrls.map(frameUrl => ({frameUrl})),
          },
          // Include hidden protocol reason code for debugging.
          protocolReason: reason,
        });
      }
    }

    /** @type {LH.Audit.Details.Table['headings']} */
    const headings = [
      /* eslint-disable max-len */
      {key: 'reason', valueType: 'text', subItemsHeading: {key: 'frameUrl', valueType: 'url'}, label: str_(UIStrings.failureReasonColumn)},
      {key: 'failureType', valueType: 'text', label: str_(UIStrings.failureTypeColumn)},
      /* eslint-enable max-len */
    ];

    const details = Audit.makeTableDetails(headings, results);

    const displayValue = totalIssues ?
      str_(UIStrings.displayValue, {itemCount: totalIssues}) :
      undefined;

    return {
      score: results.length ? 0 : 1,
      displayValue,
      details,
    };
  }
@param {LH.Artifacts} artifacts
@return {Promise<LH.Audit.Product>}