static async audit(artifacts, context) {
    const {SourceMaps} = artifacts;
    const devtoolsLog = artifacts.DevtoolsLog;
    const classifiedEntities = await EntityClassification.request(
      {URL: artifacts.URL, devtoolsLog}, context);

    /** @type {Set<string>} */
    const isMissingMapForLargeFirstPartyScriptUrl = new Set();

    let missingMapsForLargeFirstPartyFile = false;
    const results = [];
    for (const script of artifacts.Scripts) {
      const sourceMap = SourceMaps.find(m => m.scriptId === script.scriptId);
      const errors = [];
      const isLargeFirstParty = this.isLargeFirstPartyJS(script, classifiedEntities);

      if (isLargeFirstParty && (!sourceMap || !sourceMap.map)) {
        missingMapsForLargeFirstPartyFile = true;
        isMissingMapForLargeFirstPartyScriptUrl.add(script.url);
        errors.push({error: str_(UIStrings.missingSourceMapErrorMessage)});
      }

      if (sourceMap && !sourceMap.map) {
        errors.push({error: sourceMap.errorMessage});
      }

      // Sources content errors.
      if (sourceMap?.map) {
        const sourcesContent = sourceMap.map.sourcesContent || [];
        let missingSourcesContentCount = 0;
        for (let i = 0; i < sourceMap.map.sources.length; i++) {
          if (sourcesContent.length < i || !sourcesContent[i]) missingSourcesContentCount += 1;
        }
        if (missingSourcesContentCount > 0) {
          errors.push({error: str_(UIStrings.missingSourceMapItemsWarningMesssage,
              {missingItems: missingSourcesContentCount})});
        }
      }

      if (sourceMap || errors.length) {
        results.push({
          scriptUrl: script.url,
          sourceMapUrl: sourceMap?.sourceMapUrl,
          subItems: {
            type: /** @type {const} */ ('subitems'),
            items: errors,
          },
        });
      }
    }

    /** @type {LH.Audit.Details.TableColumnHeading[]} */
    const headings = [
      {
        key: 'scriptUrl',
        valueType: 'url',
        subItemsHeading: {key: 'error'},
        label: str_(i18n.UIStrings.columnURL),
      },
      {key: 'sourceMapUrl', valueType: 'url', label: str_(UIStrings.columnMapURL)},
    ];

    results.sort((a, b) => {
      // Show the items that can fail the audit first.
      const missingMapA = isMissingMapForLargeFirstPartyScriptUrl.has(a.scriptUrl);
      const missingMapB = isMissingMapForLargeFirstPartyScriptUrl.has(b.scriptUrl);
      if (missingMapA && !missingMapB) return -1;
      if (!missingMapA && missingMapB) return 1;

      // Then sort by whether one has errors and the other doesn't.
      if (a.subItems.items.length && !b.subItems.items.length) return -1;
      if (!a.subItems.items.length && b.subItems.items.length) return 1;

      // Then sort by script url.
      return b.scriptUrl.localeCompare(a.scriptUrl);
    });

    // Only fails if `missingMapsForLargeFirstPartyFile` is true. All other errors are diagnostical.
    return {
      score: missingMapsForLargeFirstPartyFile ? 0 : 1,
      details: Audit.makeTableDetails(headings, results),
    };
  }
@param {LH.Artifacts} artifacts
@param {LH.Audit.Context} context