From 9843b04ba9cbbfa8f5b1aa0b6537bc59dd83d827 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 26 Mar 2020 19:05:56 -0700 Subject: [PATCH 1/5] Refactor: update all JSDocs --- scripts/compare-features.js | 5 +- scripts/fix-browser-order.js | 30 +++--- scripts/fix-feature-order.js | 34 ++++--- scripts/fix.js | 5 +- .../migrations/002-remove-webview-flags.js | 27 +++++- .../002-remove-webview-flags.test.js | 13 +++ scripts/mirror.js | 3 +- scripts/release-notes.js | 65 +++++++++++++ scripts/statistics.js | 23 ++--- scripts/traverse.js | 14 +++ test/linter/test-browsers.js | 32 +++++-- test/linter/test-consistency.js | 92 ++++++++++++------- test/linter/test-links.js | 31 +++++-- test/linter/test-prefix.js | 26 ++++-- test/linter/test-real-values.js | 33 +++++-- test/linter/test-schema.js | 7 +- test/linter/test-style.js | 23 ++++- test/linter/test-versions.js | 46 +++++++--- test/test-migrations.js | 8 +- test/test-regexes.js | 3 +- test/utils.js | 5 +- 21 files changed, 390 insertions(+), 135 deletions(-) diff --git a/scripts/compare-features.js b/scripts/compare-features.js index 3784fd99fed53a..a3c27961cb2424 100644 --- a/scripts/compare-features.js +++ b/scripts/compare-features.js @@ -5,15 +5,16 @@ 'use strict'; /** - * * Sort a list of features based upon a specific order: * 1. __compat is always first * 2. Alphanumerical features starting with an uppercase letter (without symbols aside from - or _) * 3. Alphanumerical features starting with a lowercase letter (without symbols aside from - or _) * 4. All other features * + * @param {string} a The name of the first object to perform comparison with + * @param {string} b The name of the second object to perform comparison with + * @returns {boolean} Result of localeCompare */ - const compareFeatures = (a, b) => { if (a == '__compat') return -1; if (b == '__compat') return 1; diff --git a/scripts/fix-browser-order.js b/scripts/fix-browser-order.js index c9475bbb70135b..de652d198e9a74 100644 --- a/scripts/fix-browser-order.js +++ b/scripts/fix-browser-order.js @@ -2,20 +2,12 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +'use strict'; + /** - * Return a new "support_block" object whose first-level properties - * (browser names) have been ordered according to Array.prototype.sort, - * and so will be stringified in that order as well. This relies on - * guaranteed "own" property ordering, which is insertion order for - * non-integer keys (which is our case). - * - * @param {string} key The key in the object - * @param {*} value The value of the key - * - * @returns {*} The new value + * @typedef {import('../../types').Identifier} Identifier */ -'use strict'; const fs = require('fs'); const path = require('path'); const { platform } = require('os'); @@ -23,6 +15,17 @@ const { platform } = require('os'); /** Determines if the OS is Windows */ const IS_WINDOWS = platform() === 'win32'; +/** + * Return a new "support_block" object whose first-level properties + * (browser names) have been ordered according to Array.prototype.sort, + * and so will be stringified in that order as well. This relies on + * guaranteed "own" property ordering, which is insertion order for + * non-integer keys (which is our case). + * + * @param {string} key The key of the object + * @param {Identifier} value The value of the key + * @returns {Identifier} Value with sorting applied + */ const orderSupportBlock = (key, value) => { if (key === '__compat') { value.support = Object.keys(value.support) @@ -36,7 +39,10 @@ const orderSupportBlock = (key, value) => { }; /** - * @param {Promise} filename + * Perform a fix of the browser order of a __compat.support block within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * + * @param {string} filename The filename to perform fix upon + * @returns {void} */ const fixBrowserOrder = filename => { let actual = fs.readFileSync(filename, 'utf-8').trim(); diff --git a/scripts/fix-feature-order.js b/scripts/fix-feature-order.js index 428dafad1ee804..94e26d867f9ac3 100644 --- a/scripts/fix-feature-order.js +++ b/scripts/fix-feature-order.js @@ -2,29 +2,32 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +'use strict'; + /** - * Return a new feature object whose first-level properties have been - * ordered according to Array.prototype.sort, and so will be - * stringified in that order as well. This relies on guaranteed "own" - * property ordering, which is insertion order for non-integer keys - * (which is our case). - * - * @param {string} key The key in the object - * @param {*} value The value of the key - * - * @returns {*} The new value + * @typedef {import('../../types').Identifier} Identifier */ -'use strict'; const fs = require('fs'); const path = require('path'); const { platform } = require('os'); +const compareFeatures = require('./compare-features'); + /** Determines if the OS is Windows */ const IS_WINDOWS = platform() === 'win32'; -const compareFeatures = require('./compare-features'); - +/** + * Return a new feature object whose first-level properties have been + * ordered according to Array.prototype.sort, and so will be + * stringified in that order as well. This relies on guaranteed "own" + * property ordering, which is insertion order for non-integer keys + * (which is our case). + * + * @param {string} key The key in the object + * @param {Identifier} value The value of the key + * @returns {Identifier} The new value + */ function orderFeatures(key, value) { if (value instanceof Object && '__compat' in value) { value = Object.keys(value) @@ -38,7 +41,10 @@ function orderFeatures(key, value) { } /** - * @param {Promise} filename + * Perform a fix of feature order within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * + * @param {string} filename The filename to perform fix upon + * @returns {void} */ const fixFeatureOrder = filename => { let actual = fs.readFileSync(filename, 'utf-8').trim(); diff --git a/scripts/fix.js b/scripts/fix.js index a2550ae062240c..9cfbf1e50213b1 100644 --- a/scripts/fix.js +++ b/scripts/fix.js @@ -6,7 +6,10 @@ const fixFeatureOrder = require('./fix-feature-order'); const format = require('./fix-format'); /** - * @param {string[]} files + * Recursively load one or more files and/or directories passed as arguments and perform automatic fixes. + * + * @param {string[]} files The files to load and perform fix upon + * @returns {void} */ function load(...files) { for (let file of files) { diff --git a/scripts/migrations/002-remove-webview-flags.js b/scripts/migrations/002-remove-webview-flags.js index 1f8c362b876008..9c23a33808003b 100644 --- a/scripts/migrations/002-remove-webview-flags.js +++ b/scripts/migrations/002-remove-webview-flags.js @@ -3,13 +3,29 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ 'use strict'; + +/** + * @typedef {import('../../types').Identifier} Identifier + */ + const fs = require('fs'); const path = require('path'); const { platform } = require('os'); -/** Determines if the OS is Windows */ +/** + * Determines if the OS is Windows + * + * @constant {boolean} + */ const IS_WINDOWS = platform() === 'win32'; +/** + * Recursively load one or more files and/or directories passed as arguments and perform feature sorting. + * + * @param {string} key The key in the object + * @param {Identifier} value The value of the key + * @returns {Identifier} The new value with WebView flags removed + */ const removeWebViewFlags = (key, value) => { if (key === '__compat') { if (value.support.webview_android !== undefined) { @@ -37,7 +53,9 @@ const removeWebViewFlags = (key, value) => { }; /** - * @param {Promise} filename + * Perform removal of flags within WebView data within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * + * @param {string} filename The filename to perform migration upon */ const fixWebViewFlags = filename => { const actual = fs.readFileSync(filename, 'utf-8').trim(); @@ -60,7 +78,10 @@ const fixWebViewFlags = filename => { if (require.main === module) { /** - * @param {string[]} files + * Recursively load one or more files and/or directories passed as arguments and perform removal of flags from WebView support data. + * + * @param {string[]} files The files to load and perform migration upon + * @returns {void} */ function load(...files) { for (let file of files) { diff --git a/scripts/migrations/002-remove-webview-flags.test.js b/scripts/migrations/002-remove-webview-flags.test.js index e0dcf59a3f6e8c..722387ff390cc3 100644 --- a/scripts/migrations/002-remove-webview-flags.test.js +++ b/scripts/migrations/002-remove-webview-flags.test.js @@ -3,6 +3,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ 'use strict'; + +/** + * @typedef {import('../../types').Identifier} Identifier + */ + const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); @@ -10,6 +15,9 @@ const { platform } = require('os'); const { removeWebViewFlags } = require('./002-remove-webview-flags.js'); +/** + * @constant {{input: Identifier, output: Identifier}[]} Objects of each test, with input and expected output + */ const tests = [ { input: { @@ -134,6 +142,11 @@ const tests = [ }, ]; +/** + * Test the WebView flags removal migration, using predefined tests + * + * @returns {boolean} Whether the test has found errors + */ const testFixWebViewFlags = (logger = console) => { let hasErrors = false; for (let i = 0; i < tests.length; i++) { diff --git a/scripts/mirror.js b/scripts/mirror.js index eb004f19881af6..b651337df0ba80 100644 --- a/scripts/mirror.js +++ b/scripts/mirror.js @@ -2,13 +2,14 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +'use strict'; + /** * @typedef {import('../types').Identifier} Identifier * @typedef {import('../types').SupportStatement} SupportStatement * @typedef {import('../types').ReleaseStatement} ReleaseStatement */ -'use strict'; const fs = require('fs'); const path = require('path'); diff --git a/scripts/release-notes.js b/scripts/release-notes.js index 526e88d743d278..8bc5fa7408a8dd 100644 --- a/scripts/release-notes.js +++ b/scripts/release-notes.js @@ -16,6 +16,12 @@ const { argv } = require('yargs').command( }, ); +/** + * Get the JSON response from a specified URL + * + * @param {string} url The URL to get the JSON from + * @returns {object} The JSON obtained from the specified URL + */ const getJSON = url => new Promise((resolve, reject) => http.get( @@ -34,6 +40,12 @@ const getJSON = url => ), ); +/** + * Display a prompt to the user and await input, then return the user's input + * + * @param {string} query The query to present to the user + * @returns {string} The user's response to said query + */ const question = query => { const rl = readline.createInterface({ input: process.stdin, @@ -45,8 +57,20 @@ const question = query => { }); }; +/** + * Checks whether a user's input is a confirmation -- in other words, not "n" or "no" (case-insensitive). Used as a type to questions passed to the prompt() function. + * + * @param {string} str The string to check against + * @returns {boolean} True if the string represents a confirmation + */ const confirm = str => !['n', 'no'].includes(str.toLowerCase()); +/** + * Display a series of prompts to the user and collect the input, converting it to the specified type. + * + * @param {{name: string, type: object, message: string}} questions The prompts to display to the user + * @returns {object.} The results from each and every prompt + */ const prompt = async questions => { const results = {}; for (const q of questions) { @@ -56,11 +80,23 @@ const prompt = async questions => { return results; }; +/** + * Get the number of stargazers from the BCD repository and return it + * + * @returns {number} The number of stargazers for the BCD repository + */ const stargazers = () => getJSON('https://api.github.com/repos/mdn/browser-compat-data').then( json => json.stargazers_count, ); +/** + * Obtain the number of changes (commits, files changed, insertions, deletions) + * + * @param {string} version The current version + * @param {string} previousVersion The previous version + * @returns {{commits: string, changed: string, insertions: string, deletions: string}} The commits, files changed, insertions, and deletions between the current and previous versions + */ const stats = (version, previousVersion) => { // Get just the diff stats summary const diff = execSync( @@ -87,6 +123,13 @@ const stats = (version, previousVersion) => { }; }; +/** + * Obtain the number of changes (commits, files changed, insertions, deletions) + * + * @param {string} version The current version + * @param {string} previousVersion The previous version + * @returns {{commits: string, changed: string, insertions: string, deletions: string}} The commits, files changed, insertions, and deletions between the current and previous versions + */ const contributors = (version, previousVersion) => prompt([ { @@ -102,6 +145,11 @@ const contributors = (version, previousVersion) => }, ]); +/** + * Prompt the user if there are any notable changes, and return a string to indicate as such + * + * @returns {string} "None" if the user said no, or a dummy string to be later replaced + */ const notableChanges = async () => { const { result } = await prompt([ { @@ -118,6 +166,11 @@ const notableChanges = async () => { return 'REPLACE ME WITH ACTUAL RELEASE NOTES'; }; +/** + * Count the number of features throughout BCD + * + * @returns {number} The count of features in BCD + */ const countFeatures = () => { let count = 0; JSON.parse(JSON.stringify(bcd), k => { @@ -129,6 +182,13 @@ const countFeatures = () => { return count; }; +/** + * Generate the URL to create a release on GitHub + * + * @param {string} version The version tag to use + * @param {string} body The body of the release + * @returns {string} The generated URL + */ const makeURL = (version, body) => { const baseURL = 'https://github.com/mdn/browser-compat-data/releases/new'; @@ -141,6 +201,11 @@ const makeURL = (version, body) => { return `${baseURL}?title=${version}&tag=${version}&body=${encodedBody}`; }; +/** + * Initiate a release of the package on GitHub + * + * @returns {void} + */ const main = async () => { const version = argv.versionTag; const previousVersion = execSync(`git describe --abbrev=0 ${version}^`, { diff --git a/scripts/statistics.js b/scripts/statistics.js index 10c1556b300d47..424507c89d4474 100644 --- a/scripts/statistics.js +++ b/scripts/statistics.js @@ -3,6 +3,18 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ 'use strict'; + +/** + * @typedef {import('../../types').Identifier} Identifier + * + * @typedef {object} VersionStats + * @property {number} all The total number of occurrences for the browser. + * @property {number} true The total number of `true` values for the browser. + * @property {number} null The total number of `null` values for the browser. + * @property {number} range The total number of range values for the browser. + * @property {number} real The total number of real values for the browser. + */ + const chalk = require('chalk'); const bcd = require('..'); @@ -25,17 +37,6 @@ const { argv } = require('yargs').command( }, ); -/** - * @typedef {import('../../types').Identifier} Identifier - * - * @typedef {object} VersionStats - * @property {number} all The total number of occurrences for the browser. - * @property {number} true The total number of `true` values for the browser. - * @property {number} null The total number of `null` values for the browser. - * @property {number} range The total number of range values for the browser. - * @property {number} real The total number of real values for the browser. - */ - /** * @constant {string[]} */ diff --git a/scripts/traverse.js b/scripts/traverse.js index 10b419030c8438..0e362954bfe956 100644 --- a/scripts/traverse.js +++ b/scripts/traverse.js @@ -1,4 +1,9 @@ 'use strict'; + +/** + * @typedef {import('../../types').Identifier} Identifier + */ + const bcd = require('..'); const { argv } = require('yargs').command( @@ -23,6 +28,15 @@ const { argv } = require('yargs').command( }, ); +/** + * Traverse all of the features within a specified object and find all features that have one of the specified values + * + * @param {Identifier} obj The compat data to traverse through + * @param {number} depth The depth to traverse + * @param {string} identifier The identifier of the current object + * @param {string} values The values to test for in stringified format + * @returns {void} + */ function traverseFeatures(obj, depth, identifier) { depth--; if (depth >= 0) { diff --git a/test/linter/test-browsers.js b/test/linter/test-browsers.js index 2dba44a66efbcc..d201fa53ca3c06 100644 --- a/test/linter/test-browsers.js +++ b/test/linter/test-browsers.js @@ -7,7 +7,7 @@ const chalk = require('chalk'); * @typedef {import('../utils').Logger} Logger */ -/** @type {Record} */ +/** @type {object.} */ const browsers = { desktop: ['chrome', 'edge', 'firefox', 'ie', 'opera', 'safari'], mobile: [ @@ -27,13 +27,15 @@ const browsers = { }; /** - * @param {Identifier} data - * @param {string[]} displayBrowsers - * @param {string[]} requiredBrowsers - * @param {string} category - * @param {Logger} logger - * @param {string} [path] - * @returns {boolean} + * Check the data for any disallowed browsers or if it's missing required browsers + * + * @param {Identifier} data The data to test + * @param {string[]} displayBrowsers All of the allowed browsers for this data + * @param {string[]} requiredBrowsers All of the required browsers for this data + * @param {string} category The category the data belongs to + * @param {Logger} logger The logger to output errors to + * @param {string} [path] The path of the data + * @returns {void} */ function processData( data, @@ -72,6 +74,12 @@ function processData( const statementList = Array.isArray(supportStatement) ? supportStatement : [supportStatement]; + /** + * Checks a support statement and identifies whether it only has 'version_added' + * + * @param {Identifier} statement The support statement to check + * @returns {boolean} If the statement only has 'version_added' + */ function hasVersionAddedOnly(statement) { const keys = Object.keys(statement); return keys.length === 1 && keys[0] === 'version_added'; @@ -107,6 +115,9 @@ function processData( /** * @param {string} filename + * Test for issues within the browsers in the data within the specified file + * + * @param {string} filename The file to test * @returns {boolean} If the file contains errors */ function testBrowsers(filename) { @@ -146,6 +157,11 @@ function testBrowsers(filename) { const errors = []; const logger = { /** @param {...unknown} message */ + /** + * logger.error + * + * @param {...*} message Messages to add to errors + */ error: (...message) => { errors.push(message.join(' ')); }, diff --git a/test/linter/test-consistency.js b/test/linter/test-consistency.js index 6127202c328226..976f815fbd79bd 100644 --- a/test/linter/test-consistency.js +++ b/test/linter/test-consistency.js @@ -15,15 +15,15 @@ const chalk = require('chalk'); * @typedef {'unsupported' | 'support_unknown' | 'subfeature_earlier_implementation'} ErrorType * * @typedef {object} ConsistencyError - * @property {string} feature - * @property {string[]} path - * @property {FeatureError[]} errors + * @property {string} feature The identifier of the feature + * @property {string[]} path The path of the feature + * @property {FeatureError[]} errors Any errors found * * @typedef {object} FeatureError - * @property {ErrorType} errortype - * @property {string} browser - * @property {VersionValue} parent_value - * @property {[string, VersionValue][]} subfeatures + * @property {ErrorType} errortype The type of the error + * @property {string} browser The browser the error was found + * @property {VersionValue} parent_value The value of the parent feature + * @property {[string, VersionValue][]} subfeatures The versions of the subfeatures */ /** @@ -34,17 +34,21 @@ const chalk = require('chalk'); */ class ConsistencyChecker { /** - * @param {Identifier} data - * @return {ConsistencyError[]} + * Checks the data for any errors + * + * @param {Identifier} data The data to test + * @returns {ConsistencyError[]} Any errors found within the data */ check(data) { return this.checkSubfeatures(data); } /** - * @param {Identifier} data - * @param {string[]} [path] - * @return {ConsistencyError[]} + * Recursively checks the data for any errors + * + * @param {Identifier} data The data to test + * @param {string[]} [path] The path of the data + * @returns {ConsistencyError[]} Any errors found within the data */ checkSubfeatures(data, path = []) { /** @type {ConsistencyError[]} */ @@ -78,8 +82,10 @@ class ConsistencyChecker { } /** - * @param {PrimaryIdentifier & Required} data - * @return {FeatureError[]} + * Checks a specific feature for errors + * + * @param {Identifier} data The data to test + * @returns {FeatureError[]} Any errors found within the data */ checkFeature(data) { /** @type {FeatureError[]} */ @@ -217,16 +223,20 @@ class ConsistencyChecker { } /** - * @param {Identifier} data - * @return {data is Required} + * Checks if the data is a feature + * + * @param {Identifier} data The data to test + * @returns {boolean} If the data is a feature statement */ isFeature(data) { return '__compat' in data; } /** - * @param {CompatStatement} compatData - * @return {string[]} + * Get all of the unsupported browsers in a feature + * + * @param {CompatStatement} compatData The compat data to process + * @returns {string[]} The list of browsers marked as unsupported */ extractUnsupportedBrowsers(compatData) { return this.extractBrowsers( @@ -239,8 +249,10 @@ class ConsistencyChecker { } /** - * @param {CompatStatement} compatData - * @return {string[]} + * Get all of the browsers with unknown support in a feature + * + * @param {CompatStatement} compatData The compat data to process + * @returns {string[]} The list of browsers with unknown support */ extractSupportUnknownBrowsers(compatData) { return this.extractBrowsers( @@ -250,8 +262,10 @@ class ConsistencyChecker { } /** - * @param {CompatStatement} compatData - * @return {string[]} + * Get all of the browsers with either unknown or no support in a feature + * + * @param {CompatStatement} compatData The compat data to process + * @returns {string[]} The list of browsers with non-truthy (false or null) support */ extractSupportNotTrueBrowsers(compatData) { return this.extractBrowsers( @@ -264,8 +278,10 @@ class ConsistencyChecker { ); } /** - * @param {CompatStatement} compatData - * @return {string[]} + * Get all of the browsers with a version number in a feature + * + * @param {CompatStatement} compatData The compat data to process + * @returns {string[]} The list of browsers with an exact version number */ extractSupportedBrowsersWithVersion(compatData) { return this.extractBrowsers( @@ -275,11 +291,13 @@ class ConsistencyChecker { } /** - * @param {SupportStatement} compatData - * @return {string | null} + * Get the version added for a feature or recursively search the array for the earliest version + * + * @param {SupportStatement} compatData The compat data to process + * @returns {?string} The earliest version added in the data */ getVersionAdded(compatData) { - /** @type {string | null} */ + /** @type {?string} */ var version_added = null; if (typeof compatData.version_added === 'string') @@ -307,9 +325,11 @@ class ConsistencyChecker { } /** - * @param {SupportStatement} a - * @param {SupportStatement} b - * @return {boolean} + * Compare two versions and determine if a's version is greater (later) than b's version + * + * @param {SupportStatement} a The first support statement to compare + * @param {SupportStatement} b The second support statement to compare + * @returns {boolean} If a's version is greater (later) than b's version */ isVersionAddedGreater(a, b) { var a_version_added = this.getVersionAdded(a); @@ -329,10 +349,11 @@ class ConsistencyChecker { } /** + * Get all of the browsers within the data and send the data to the callback * - * @param {CompatStatement} compatData - * @param {(browserData: SimpleSupportStatement) => boolean} callback - * @return {string[]} + * @param {CompatStatement} compatData The compat data to process + * @param {(browserData: SimpleSupportStatement) => boolean} callback The function to send the data to + * @returns {boolean} The response of the callback, or "false" */ extractBrowsers(compatData, callback) { return Object.keys(compatData.support).filter(browser => { @@ -350,7 +371,10 @@ class ConsistencyChecker { } /** - * @param {string} filename + * Test the version consistency within the file + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors */ function testConsistency(filename) { /** @type {Identifier} */ diff --git a/test/linter/test-links.js b/test/linter/test-links.js index 8f9f36e1be447c..089e76aa72d111 100644 --- a/test/linter/test-links.js +++ b/test/linter/test-links.js @@ -4,12 +4,19 @@ const chalk = require('chalk'); const { IS_WINDOWS, indexToPos, indexToPosRaw } = require('../utils.js'); /** - * @typedef {import('../utils').Logger} Logger + * @typedef {object} LinkError + * @property {string} issue The description of the error + * @property {[?number, ?number]} pos The cursor position of the issue in number-array form + * @property {string} posString The cursor position of the issue in string form + * @property {?string} expected The expected string if applicable + * @property {string} actualLink What the link currently is */ /** - * @param {string} filename - * @param {Logger} logger + * Process the data for any errors within the links + * + * @param {string} filename The file to test + * @returns {LinkError[]} A list of errors found in the links */ function processData(filename) { let errors = []; @@ -115,7 +122,7 @@ function processData(filename) { if (!expectedPath.startsWith('docs/')) { // Convert legacy zone URLs (see https://bugzil.la/1462475): - const [zone, index] = /** @return {[string|null, number]} */ (() => { + const [zone, index] = /** @returns {[?string, number]} */ (() => { const match = expectedPath.match( /\b(Add-ons|Apps|Archive|Firefox|Learn|Web)\b/, ); @@ -175,10 +182,13 @@ function processData(filename) { } /** - * @param {Object[]} errors - * @param {string} actual - * @param {string|RegExp} regexp - * @param {(match: RegExpExecArray) => Object} matchHandler + * Given a RegEx expression, test the link for errors + * + * @param {LinkError[]} errors The errors object to push the new errors to + * @param {string} actual The link to test + * @param {string|RegExp} regexp The regex to test with + * @param {(match: Array.) => object} matchHandler The callback + * @returns {void} */ function processLink(errors, actual, regexp, matchHandler) { const re = new RegExp(regexp, 'g'); @@ -203,7 +213,10 @@ function processLink(errors, actual, regexp, matchHandler) { } /** - * @param {string} filename + * Test for any malformed links + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors */ function testLinks(filename) { /** @type {Object[]} */ diff --git a/test/linter/test-prefix.js b/test/linter/test-prefix.js index 542e3939060dec..e74e68f8a1a113 100644 --- a/test/linter/test-prefix.js +++ b/test/linter/test-prefix.js @@ -7,11 +7,14 @@ const chalk = require('chalk'); */ /** - * @param {Identifier} data - * @param {string} category - * @param {string[]} errors - * @param {string} prefix - * @param {string} [path] + * Check the prefix of a specific feature + * + * @param {Identifier} data The data to test + * @param {string} category The category the data belongs to + * @param {string[]} errors The errors object to push the new errors to + * @param {string} prefix The browser-based prefix to test + * @param {string} [path] The path to the data + * @returns {string[]} Any errors found within the data */ function checkPrefix(data, category, errors, prefix, path = '') { for (const key in data) { @@ -37,9 +40,11 @@ function checkPrefix(data, category, errors, prefix, path = '') { } /** - * @param {Identifier} data - * @param {string} category - * @return {string[]} + * Process the data for prefix errors + * + * @param {Identifier} data The data to test + * @param {string} category The category the data belongs to + * @returns {string[]} Any errors found within the data */ function processData(data, category) { let errors = []; @@ -59,7 +64,10 @@ function processData(data, category) { } /** - * @param {string} filename + * Test for issues with feature's prefix + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors */ function testPrefix(filename) { const relativePath = path.relative( diff --git a/test/linter/test-real-values.js b/test/linter/test-real-values.js index 64c913a0e5f9b7..05921602860459 100644 --- a/test/linter/test-real-values.js +++ b/test/linter/test-real-values.js @@ -26,7 +26,7 @@ const blockMany = [ 'webview_android', ]; -/** @type {Record} */ +/** @type {object.} */ const blockList = { api: [], css: blockMany, @@ -42,10 +42,13 @@ const blockList = { }; /** - * @param {SupportBlock} supportData - * @param {string[]} blockList - * @param {string} relPath - * @param {Logger} logger + * Check if the feature has any browsers with nonreal data + * + * @param {SupportBlock} supportData The data to test + * @param {string[]} blockList The list of browsers required to have real values + * @param {string} relPath The path of the data + * @param {Logger} logger The logger to output errors to + * @returns {void} */ function checkRealValues(supportData, blockList, relPath, logger) { for (const browser of blockList) { @@ -79,7 +82,10 @@ function checkRealValues(supportData, blockList, relPath, logger) { } /** - * @param {string} filename + * Test for real values within the data + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors */ function testRealValues(filename) { const relativePath = path.relative( @@ -94,15 +100,24 @@ function testRealValues(filename) { /** @type {string[]} */ const errors = []; const logger = { - /** @param {...unknown} message */ + /** + * logger.error + * + * @param {...*} message Messages to add to errors + */ error: (...message) => { errors.push(message.join(' ')); }, }; /** - * @param {Identifier} data - * @param {string} [relPath] + * Process the data for nonreal values + * + * @param {Identifier} data The data to test + * @param {string} category The category the data belongs to + * @param {Logger} logger The logger to output errors to + * @param {string} [relPath] The path to the data + * @returns {void} */ function findSupport(data, relPath) { for (const prop in data) { diff --git a/test/linter/test-schema.js b/test/linter/test-schema.js index 9cb809552b0c3d..ca4dcb3962b2d9 100644 --- a/test/linter/test-schema.js +++ b/test/linter/test-schema.js @@ -7,8 +7,11 @@ const chalk = require('chalk'); const ajv = new Ajv({ jsonPointers: true, allErrors: true }); /** - * @param {string} dataFilename - * @param {string} [schemaFilename] + * Test a file to make sure it follows the defined schema + * + * @param {string} dataFilename The file to test + * @param {string} [schemaFilename] A specific schema file to test with, if needed + * @returns {boolean} If the file contains errors */ function testSchema( dataFilename, diff --git a/test/linter/test-style.js b/test/linter/test-style.js index 5bddec3d9cdaf6..3079c085a69d2a 100644 --- a/test/linter/test-style.js +++ b/test/linter/test-style.js @@ -1,4 +1,9 @@ 'use strict'; + +/** + * @typedef {import('../utils').Logger} Logger + */ + const fs = require('fs'); const url = require('url'); const chalk = require('chalk'); @@ -54,8 +59,10 @@ function orderFeatures(key, value) { } /** - * @param {string} filename - * @param {import('../utils').Logger} logger + * Process the data for any styling errors that cannot be caught by Prettier or the schema + * + * @param {string} filename The file to test + * @param {Logger} logger The logger to output errors to */ function processData(filename, logger) { let actual = fs.readFileSync(filename, 'utf-8').trim(); @@ -139,11 +146,21 @@ function processData(filename, logger) { } } +/** + * Test the data for any styling errors that cannot be caught by Prettier or the schema + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors + */ function testStyle(filename) { /** @type {string[]} */ const errors = []; const logger = { - /** @param {...unknown} message */ + /** + * logger.error + * + * @param {...*} message Messages to add to errors + */ error: (...message) => { errors.push(message.join(' ')); }, diff --git a/test/linter/test-versions.js b/test/linter/test-versions.js index 5a7a52c9817cf0..2c9b24d47cb087 100644 --- a/test/linter/test-versions.js +++ b/test/linter/test-versions.js @@ -1,19 +1,22 @@ 'use strict'; -const compareVersions = require('compare-versions'); -const chalk = require('chalk'); /** * @typedef {import('../../types').Identifier} Identifier * @typedef {import('../../types').SimpleSupportStatement} SimpleSupportStatement * @typedef {import('../../types').SupportBlock} SupportBlock * @typedef {import('../../types').VersionValue} VersionValue + * @typedef {import('../../types').Logger} Logger */ + +const compareVersions = require('compare-versions'); +const chalk = require('chalk'); + const browsers = require('../..').browsers; -/** @type {Object} */ +/** @type {object.} */ const validBrowserVersions = {}; -/** @type {Object} */ +/** @type {object.} */ const VERSION_RANGE_BROWSERS = { webview_android: ['≤37'], opera: ['≤12.1', '≤15'], @@ -32,8 +35,11 @@ for (const browser of Object.keys(browsers)) { } /** - * @param {string} browserIdentifier - * @param {VersionValue} version + * Test to see if the browser allows for the specified version + * + * @param {string} browser The browser to check + * @param {VersionValue} version The version to test + * @returns {boolean} Whether the browser allows that version */ function isValidVersion(browserIdentifier, version) { if (typeof version === 'string') { @@ -44,9 +50,12 @@ function isValidVersion(browserIdentifier, version) { } /** - * @param {SupportBlock} supportData - * @param {string} relPath - * @param {import('../utils').Logger} logger + * Check the data for any errors in provided versions + * + * @param {SupportBlock} supportData The data to test + * @param {string} relPath The path to the data + * @param {Logger} logger The logger to output errors to + * @returns {void} */ function checkVersions(supportData, relPath, logger) { const browsersToCheck = Object.keys(supportData); @@ -125,7 +134,10 @@ function checkVersions(supportData, relPath, logger) { } /** - * @param {string} filename + * Test for version errors + * + * @param {string} filename The file to test + * @returns {boolean} If the file contains errors */ function testVersions(filename) { /** @type {Identifier} */ @@ -134,15 +146,23 @@ function testVersions(filename) { /** @type {string[]} */ const errors = []; const logger = { - /** @param {...unknown} message */ + /** + * logger.error + * + * @param {...*} message Messages to add to errors + */ error: (...message) => { errors.push(message.join(' ')); }, }; /** - * @param {Identifier} data - * @param {string} [relPath] + * Process the data for version errors + * + * @param {Identifier} data The data to test + * @param {Logger} logger The logger to ouptut errors to + * @param {string} [relPath] The path of the data + * @returns {void} */ function findSupport(data, relPath) { for (const prop in data) { diff --git a/test/test-migrations.js b/test/test-migrations.js index 086a308a4f8011..0ea3fbaa8dd196 100644 --- a/test/test-migrations.js +++ b/test/test-migrations.js @@ -10,13 +10,19 @@ const chalk = require('chalk'); const m002 = require('../scripts/migrations/002-remove-webview-flags.test.js'); /** + * Test all of the migration scripts and ensure their functionality + * * @returns {boolean} If the migrations aren't functioning properly */ const testMigrations = () => { /** @type {string[]} */ const errors = []; const logger = { - /** @param {...unknown} message */ + /** + * logger.error + * + * @param {...*} message Messages to add to errors + */ error: (...message) => { errors.push(message.join(' ')); }, diff --git a/test/test-regexes.js b/test/test-regexes.js index 470b1abda0ef43..ecb7d302b2b348 100644 --- a/test/test-regexes.js +++ b/test/test-regexes.js @@ -1,5 +1,4 @@ 'use strict'; -const assert = require('assert'); /** * @typedef {import('../types').Identifier} Identifier @@ -10,6 +9,8 @@ const assert = require('assert'); * @property {string[]} misses */ +const assert = require('assert'); + /** @type {Identifier} */ const bcd = require('..'); diff --git a/test/utils.js b/test/utils.js index fa561f0cc16487..ce358287d492e1 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,12 +1,13 @@ 'use strict'; -const { platform } = require('os'); -const chalk = require('chalk'); /** * @typedef {object} Logger * @property {(...message: unknown[]) => void} error */ +const { platform } = require('os'); +const chalk = require('chalk'); + /** @type {{readonly [char: string]: string}} */ const INVISIBLES_MAP = Object.freeze( Object.assign(Object.create(null), { From eace165326fd4ffc48a3563aa26c7340eeafad9a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 8 Oct 2020 15:36:34 -0700 Subject: [PATCH 2/5] Fix issues from bad merge --- test/linter/test-versions.js | 3 --- test/utils.js | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/linter/test-versions.js b/test/linter/test-versions.js index 81b82a270394a7..30f73e9cf812d9 100644 --- a/test/linter/test-versions.js +++ b/test/linter/test-versions.js @@ -11,9 +11,6 @@ const { Logger } = require('./utils.js'); * @typedef {import('../../types').Logger} Logger */ -const compareVersions = require('compare-versions'); -const chalk = require('chalk'); - const browsers = require('../..').browsers; /** @type {object.} */ diff --git a/test/utils.js b/test/utils.js index 154245c31cb05a..0e787834141cd8 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,4 +1,6 @@ 'use strict'; +const { platform } = require('os'); +const chalk = require('chalk'); /** @type {{readonly [char: string]: string}} */ const INVISIBLES_MAP = Object.freeze( From 53c2a5c2a6557e466e20633b214bb5c0dd70ffd8 Mon Sep 17 00:00:00 2001 From: "Queen Vinyl Da.i'gyu-Kazotetsu" Date: Thu, 12 May 2022 13:29:48 -0700 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Claas Augner --- scripts/fix-browser-order.js | 4 +--- scripts/fix-feature-order.js | 2 -- scripts/mirror.js | 2 -- test/linter/test-browsers-presence.js | 3 +-- test/linter/test-consistency.js | 8 ++++---- test/linter/test-versions.js | 3 +-- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/scripts/fix-browser-order.js b/scripts/fix-browser-order.js index 9c22b4637c274e..389faf70932784 100644 --- a/scripts/fix-browser-order.js +++ b/scripts/fix-browser-order.js @@ -3,8 +3,6 @@ 'use strict'; -'use strict'; - /** * @typedef {import('../../types').Identifier} Identifier */ @@ -42,7 +40,7 @@ const orderSupportBlock = (key, value) => { /** * Perform a fix of the browser order of a __compat.support block within all the data in a specified file. The function will then automatically write any needed changes back into the file. * - * @param {string} filename The filename to perform fix upon + * @param {string} filename The path to the file to fix in-place * @returns {void} */ const fixBrowserOrder = (filename) => { diff --git a/scripts/fix-feature-order.js b/scripts/fix-feature-order.js index 05f224dd6b6acb..439532acb813ff 100644 --- a/scripts/fix-feature-order.js +++ b/scripts/fix-feature-order.js @@ -3,8 +3,6 @@ 'use strict'; -'use strict'; - /** * @typedef {import('../../types').Identifier} Identifier */ diff --git a/scripts/mirror.js b/scripts/mirror.js index 7d1011ba41d343..b691fef7094a7f 100644 --- a/scripts/mirror.js +++ b/scripts/mirror.js @@ -3,8 +3,6 @@ 'use strict'; -'use strict'; - /** * @typedef {import('../types').Identifier} Identifier * @typedef {import('../types').SupportStatement} SupportStatement diff --git a/test/linter/test-browsers-presence.js b/test/linter/test-browsers-presence.js index 81f6befd2e5c81..d32de3e543f80a 100644 --- a/test/linter/test-browsers-presence.js +++ b/test/linter/test-browsers-presence.js @@ -115,8 +115,7 @@ function processData( } /** - * @param {string} filename - * Test for issues within the browsers in the data within the specified file + * Test for issues within the browsers in the data within the specified file. * * @param {string} filename The file to test * @returns {boolean} If the file contains errors diff --git a/test/linter/test-consistency.js b/test/linter/test-consistency.js index b651a5e266b56f..de1ae088ada6ac 100644 --- a/test/linter/test-consistency.js +++ b/test/linter/test-consistency.js @@ -281,7 +281,7 @@ class ConsistencyChecker { ); } /** - * Get all of the browsers with a version number in a feature + * Get all of the browsers with a version number in a feature. * * @param {CompatStatement} compatData The compat data to process * @returns {string[]} The list of browsers with an exact version number @@ -376,11 +376,11 @@ class ConsistencyChecker { } /** - * Get all of the browsers within the data and send the data to the callback + * Get all of the browsers within the data and pass the data to the callback. * * @param {CompatStatement} compatData The compat data to process - * @param {(browserData: SimpleSupportStatement) => boolean} callback The function to send the data to - * @returns {boolean} The response of the callback, or "false" + * @param {(browserData: SimpleSupportStatement) => boolean} callback The function to pass the data to + * @returns {boolean} The result of the invoked callback, or "false" */ extractBrowsers(compatData, callback) { return Object.keys(compatData.support).filter((browser) => { diff --git a/test/linter/test-versions.js b/test/linter/test-versions.js index 28ba305e62a4cd..bc0d866625e2e2 100644 --- a/test/linter/test-versions.js +++ b/test/linter/test-versions.js @@ -178,8 +178,7 @@ function testVersions(filename) { * Process the data for version errors * * @param {Identifier} data The data to test - * @param {Logger} logger The logger to ouptut errors to - * @param {string} [relPath] The path of the data + * @param {string} relPath The path of the data * @returns {void} */ function findSupport(data, relPath) { From f46024fea897f31c99088eba700cabae8d317ad3 Mon Sep 17 00:00:00 2001 From: "Queen Vinyl Da.i'gyu-Kazotetsu" Date: Thu, 12 May 2022 13:35:38 -0700 Subject: [PATCH 4/5] Address review comments --- scripts/fix-browser-order.js | 4 +++- scripts/fix-feature-order.js | 3 ++- scripts/migrations/002-remove-webview-flags.js | 16 ++++++++-------- test/linter/test-versions.js | 5 +++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/fix-browser-order.js b/scripts/fix-browser-order.js index 389faf70932784..49e59d3cbd539f 100644 --- a/scripts/fix-browser-order.js +++ b/scripts/fix-browser-order.js @@ -38,7 +38,9 @@ const orderSupportBlock = (key, value) => { }; /** - * Perform a fix of the browser order of a __compat.support block within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * Perform a fix of the browser order of a __compat.support block within + * all the data in a specified file. The function will then automatically + * write any needed changes back into the file. * * @param {string} filename The path to the file to fix in-place * @returns {void} diff --git a/scripts/fix-feature-order.js b/scripts/fix-feature-order.js index 439532acb813ff..8c3ab62338bc31 100644 --- a/scripts/fix-feature-order.js +++ b/scripts/fix-feature-order.js @@ -40,7 +40,8 @@ function orderFeatures(key, value) { } /** - * Perform a fix of feature order within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * Perform a fix of feature order within all the data in a specified file. + * The function will then automatically write any needed changes back into the file. * * @param {string} filename The filename to perform fix upon * @returns {void} diff --git a/scripts/migrations/002-remove-webview-flags.js b/scripts/migrations/002-remove-webview-flags.js index 9db180444185b1..d51eaf0477e46f 100644 --- a/scripts/migrations/002-remove-webview-flags.js +++ b/scripts/migrations/002-remove-webview-flags.js @@ -11,15 +11,12 @@ const fs = require('fs'); const path = require('path'); const { platform } = require('os'); -/** - * Determines if the OS is Windows - * - * @constant {boolean} - */ +/** Determines if the OS is Windows */ const IS_WINDOWS = platform() === 'win32'; /** - * Recursively load one or more files and/or directories passed as arguments and perform feature sorting. + * Check to see if the key is __compat and modify the value to remove + * flags from WebView Android. * * @param {string} key The key in the object * @param {Identifier} value The value of the key @@ -52,7 +49,9 @@ const removeWebViewFlags = (key, value) => { }; /** - * Perform removal of flags within WebView data within all the data in a specified file. The function will then automatically write any needed changes back into the file. + * Perform removal of flags within WebView data within all the datain a + * specified file. The function will then automatically write any needed + * changes back into the file. * * @param {string} filename The filename to perform migration upon */ @@ -77,7 +76,8 @@ const fixWebViewFlags = (filename) => { if (require.main === module) { /** - * Recursively load one or more files and/or directories passed as arguments and perform removal of flags from WebView support data. + * Recursively load one or more files and/or directories passed as arguments + * and perform removal of flags from WebView support data. * * @param {string[]} files The files to load and perform migration upon * @returns {void} diff --git a/test/linter/test-versions.js b/test/linter/test-versions.js index bc0d866625e2e2..3b4f7a7b543a59 100644 --- a/test/linter/test-versions.js +++ b/test/linter/test-versions.js @@ -57,8 +57,9 @@ function isValidVersion(browserIdentifier, version) { } /** - * Checks if the version number of version_removed is greater than or equal to that of version_added, - * assuming they are both version strings. If either one is not a valid version string, return null. + * Checks if the version number of version_removed is greater than or equal to + * that of version_added, assuming they are both version strings. If either one + * is not a valid version string, return null. * * @param {SimpleSupportStatement} statement * @returns {(boolean|null)} From 04eda864a67984091bc9151dba27a7471974a9a4 Mon Sep 17 00:00:00 2001 From: "Queen Vinyl Da.i'gyu-Kazotetsu" Date: Fri, 13 May 2022 12:52:10 -0700 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Claas Augner --- scripts/compare-features.js | 6 +++--- scripts/statistics.js | 10 +++++----- scripts/traverse.js | 1 - test/linter/test-browsers-presence.js | 10 +++++----- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/scripts/compare-features.js b/scripts/compare-features.js index 3c4fb6d20f63a8..593b28a04a5196 100644 --- a/scripts/compare-features.js +++ b/scripts/compare-features.js @@ -12,9 +12,9 @@ * 5. Alphanumerical features starting with a lowercase letter (without symbols aside from - or _) * 6. All other features * - * @param {string} a The name of the first object to perform comparison with - * @param {string} b The name of the second object to perform comparison with - * @returns {boolean} Result of localeCompare + * @param {string} a - The name of the first object to perform comparison with + * @param {string} b - The name of the second object to perform comparison with + * @returns {number} Result of localeCompare */ const compareFeatures = (a, b) => { if (a == '__compat') return -1; diff --git a/scripts/statistics.js b/scripts/statistics.js index 9140fd9d5c55fa..a3b01a308597a0 100644 --- a/scripts/statistics.js +++ b/scripts/statistics.js @@ -7,11 +7,11 @@ * @typedef {import('../../types').Identifier} Identifier * * @typedef {object} VersionStats - * @property {number} all The total number of occurrences for the browser. - * @property {number} true The total number of `true` values for the browser. - * @property {number} null The total number of `null` values for the browser. - * @property {number} range The total number of range values for the browser. - * @property {number} real The total number of real values for the browser. + * @property {number} all - The total number of occurrences for the browser. + * @property {number} true - The total number of `true` values for the browser. + * @property {number} null - The total number of `null` values for the browser. + * @property {number} range - The total number of range values for the browser. + * @property {number} real - The total number of real values for the browser. */ const chalk = require('chalk'); diff --git a/scripts/traverse.js b/scripts/traverse.js index b733ca8d9b929d..69ed1b4e89f087 100644 --- a/scripts/traverse.js +++ b/scripts/traverse.js @@ -44,7 +44,6 @@ const { argv } = require('yargs').command( * @param {Identifier} obj The compat data to traverse through * @param {number} depth The depth to traverse * @param {string} identifier The identifier of the current object - * @param {string} values The values to test for in stringified format * @returns {void} */ function traverseFeatures(obj, depth, identifier) { diff --git a/test/linter/test-browsers-presence.js b/test/linter/test-browsers-presence.js index 040bef599bcc02..b0d65d5106b75c 100644 --- a/test/linter/test-browsers-presence.js +++ b/test/linter/test-browsers-presence.js @@ -31,11 +31,11 @@ const browsers = { * Check the data for any disallowed browsers or if it's missing required browsers * * @param {Identifier} data The data to test - * @param {string[]} displayBrowsers All of the allowed browsers for this data - * @param {string[]} requiredBrowsers All of the required browsers for this data - * @param {string} category The category the data belongs to - * @param {Logger} logger The logger to output errors to - * @param {string} [path] The path of the data + * @param {string[]} displayBrowsers All of the allowed browsers for this data. + * @param {string[]} requiredBrowsers All of the required browsers for this data. + * @param {string} category The category the data belongs to. + * @param {Logger} logger The logger to output errors to. + * @param {string} [path] The path of the data. * @returns {void} */ function processData(