async collectExtraDetails(driver, elements) {
    // Don't do more than 5s of this expensive devtools protocol work. See #11289
    let reachedGatheringBudget = false;
    setTimeout(_ => (reachedGatheringBudget = true), 5000);
    let skippedCount = 0;

    for (const element of elements) {
      if (reachedGatheringBudget) {
        skippedCount++;
        continue;
      }

      // Need source rules to determine if sized via CSS (for unsized-images).
      if (!element.isInShadowDOM && !element.isCss) {
        await this.fetchSourceRules(driver.defaultSession, element.node.devtoolsNodePath, element);
      }
      // Images within `picture` behave strangely and natural size information isn't accurate,
      // CSS images have no natural size information at all. Try to get the actual size if we can.
      if (element.isPicture || element.isCss || element.srcset) {
        await this.fetchElementWithSizeInformation(driver, element);
      }
    }

    if (reachedGatheringBudget) {
      log.warn('ImageElements', `Reached gathering budget of 5s. Skipped extra details for ${skippedCount}/${elements.length}`); // eslint-disable-line max-len
    }
  }
@param {LH.Gatherer.Driver} driver
@param {LH.Artifacts.ImageElement[]} elements