| /* This file is a part of @mdn/browser-compat-data |
| * See LICENSE file for more information. */ |
| |
| import stringify from 'fast-json-stable-stringify'; |
| |
| import bcd from '../../index.js'; |
| import { walk } from '../../utils/index.js'; |
| import mirrorSupport from '../../scripts/build/mirror.js'; |
| |
| /** @import {CompatData, BrowserName} from '../../types/types.js' */ |
| /** @import {InternalSupportStatement, InternalSupportBlock} from '../../types/index.js' */ |
| |
| const downstreamBrowsers = /** @type {(keyof typeof bcd.browsers)[]} */ ( |
| Object.keys(bcd.browsers) |
| ).filter((browser) => bcd.browsers[browser].upstream); |
| |
| /** |
| * Check to see if the statement is equal to the mirrored statement |
| * @param {InternalSupportBlock} support The support statement to test |
| * @param {BrowserName} browser The browser to mirror for |
| * @returns {boolean} Whether the support statement is equal to mirroring |
| */ |
| export const isMirrorEquivalent = (support, browser) => { |
| const original = support[browser]; |
| if (!original) { |
| return false; // No data for browser. |
| } |
| if (original === 'mirror') { |
| return false; // Already mirrored. |
| } |
| let mirrored; |
| try { |
| mirrored = mirrorSupport(browser, support); |
| } catch { |
| // This can happen with missing engine_version. Don't mirror anything. |
| return false; |
| } |
| return stringify(mirrored) === stringify(original); |
| }; |
| |
| /** |
| * Check to see if mirroring is required |
| * @param {Partial<Record<BrowserName, *>>} supportData The support statement to test |
| * @param {string} browser The browser to mirror for |
| * @returns {boolean} Whether mirroring is required |
| */ |
| export const isMirrorRequired = (supportData, browser) => { |
| const current = bcd.browsers[browser]; |
| /** @type {BrowserName | undefined} */ |
| const upstream = current.upstream; |
| |
| if (!upstream || !supportData[browser] || !supportData[upstream]) { |
| return false; |
| } |
| |
| if ( |
| supportData[browser].version_added === false && |
| supportData[upstream].version_added === 'preview' && |
| !current.preview_name |
| ) { |
| // Allow `"version_added": false` if |
| // - upstream only has preview support, and |
| // - target does not have preview versions. |
| return false; |
| } |
| |
| return true; |
| }; |
| |
| /** |
| * Set the support statement for each browser to mirror if it matches mirroring |
| * @param {CompatData} bcd The compat data to update |
| * @returns {void} |
| */ |
| export const mirrorIfEquivalent = (bcd) => { |
| for (const { compat } of walk(undefined, bcd)) { |
| for (const browser of downstreamBrowsers) { |
| if ( |
| isMirrorRequired(compat.support, browser) && |
| isMirrorEquivalent(compat.support, browser) |
| ) { |
| /** @type {InternalSupportStatement} */ (compat.support[browser]) = |
| 'mirror'; |
| } |
| } |
| } |
| }; |
| |
| /** |
| * Update compat data to 'mirror' if the statement matches mirroring |
| * @param {string} filename The name of the file to fix |
| * @param {string} actual The current content of the file |
| * @returns {string} expected content of the file |
| */ |
| const fixMirror = (filename, actual) => { |
| if (filename.includes('/browsers/')) { |
| return actual; |
| } |
| |
| const bcd = JSON.parse(actual); |
| mirrorIfEquivalent(bcd); |
| |
| return JSON.stringify(bcd, null, 2); |
| }; |
| |
| export default fixMirror; |