-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathtest-versions.js
179 lines (164 loc) · 5.87 KB
/
test-versions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
'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
*/
const browsers = require('../..').browsers;
/** @type {Object<string, string[]>} */
const validBrowserVersions = {};
/** @type {Object<string, string[]>} */
const VERSION_RANGE_BROWSERS = {
webview_android: ['≤37'],
};
/** @type string[] */
const FLAGLESS_BROWSERS = ['webview_android'];
for (const browser of Object.keys(browsers)) {
validBrowserVersions[browser] = Object.keys(browsers[browser].releases);
if (VERSION_RANGE_BROWSERS[browser]) {
validBrowserVersions[browser].push(...VERSION_RANGE_BROWSERS[browser]);
}
}
/**
* @param {string} browserIdentifier
* @param {VersionValue} version
*/
function isValidVersion(browserIdentifier, version) {
if (typeof version === 'string') {
return validBrowserVersions[browserIdentifier].includes(version);
} else {
return true;
}
}
/**
* @param {SupportBlock} supportData
* @param {string} relPath
* @param {import('../utils').Logger} logger
*/
function checkVersions(supportData, relPath, logger) {
let hasErrors = false;
const browsersToCheck = Object.keys(supportData);
for (const browser of browsersToCheck) {
if (validBrowserVersions[browser]) {
/** @type {SimpleSupportStatement[]} */
const supportStatements = [];
if (Array.isArray(supportData[browser])) {
Array.prototype.push.apply(supportStatements, supportData[browser]);
} else {
supportStatements.push(supportData[browser]);
}
const validBrowserVersionsString = `true, false, null, ${validBrowserVersions[
browser
].join(', ')}`;
const validBrowserVersionsTruthy = `true, ${validBrowserVersions[
browser
].join(', ')}`;
for (const statement of supportStatements) {
if (!isValidVersion(browser, statement.version_added)) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_added: "${statement.version_added}"} is {bold NOT} a valid version number for {bold ${browser}}\n Valid {bold ${browser}} versions are: ${validBrowserVersionsString}}`,
);
hasErrors = true;
}
if (!isValidVersion(browser, statement.version_removed)) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_removed: "${statement.version_removed}"} is {bold NOT} a valid version number for {bold ${browser}}\n Valid {bold ${browser}} versions are: ${validBrowserVersionsString}}`,
);
hasErrors = true;
}
if ('version_removed' in statement && 'version_added' in statement) {
if (
typeof statement.version_added !== 'string' &&
statement.version_added !== true
) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_added: "${statement.version_added}"} is {bold NOT} a valid version number for {bold ${browser}} when {bold version_removed} is present\n Valid {bold ${browser}} versions are: ${validBrowserVersionsTruthy}}`,
);
hasErrors = true;
} else if (
typeof statement.version_added === 'string' &&
typeof statement.version_removed === 'string'
) {
if (
(statement.version_added.startsWith('≤') &&
statement.version_removed.startsWith('≤') &&
compareVersions.compare(
statement.version_added.replace('≤', ''),
statement.version_removed.replace('≤', ''),
'<',
)) ||
((!statement.version_added.startsWith('≤') ||
!statement.version_removed.startsWith('≤')) &&
compareVersions.compare(
statement.version_added.replace('≤', ''),
statement.version_removed.replace('≤', ''),
'>=',
))
) {
logger.error(
chalk`{red → {bold ${relPath}} - {bold version_removed: "${statement.version_removed}"} must be greater than {bold version_added: "${statement.version_added}"}}`,
);
hasErrors = true;
}
}
}
if ('flags' in statement) {
if (FLAGLESS_BROWSERS.includes(browser)) {
logger.error(
chalk`{red → {bold ${relPath}} - This browser ({bold ${browser}}) does not support flags, so support cannot be behind a flag for this feature.}`,
);
hasErrors = true;
}
}
}
}
}
return hasErrors;
}
/**
* @param {string} filename
*/
function testVersions(filename) {
/** @type {Identifier} */
const data = require(filename);
/** @type {string[]} */
const errors = [];
const logger = {
/** @param {...unknown} message */
error: (...message) => {
errors.push(message.join(' '));
},
};
/**
* @param {Identifier} data
* @param {string} [relPath]
*/
function findSupport(data, relPath) {
for (const prop in data) {
if (prop === '__compat' && data[prop].support) {
checkVersions(data[prop].support, relPath, logger);
}
const sub = data[prop];
if (typeof sub === 'object') {
findSupport(sub, relPath ? `${relPath}.${prop}` : `${prop}`);
}
}
}
findSupport(data);
if (errors.length) {
console.error(
chalk`{red Versions – {bold ${errors.length}} ${
errors.length === 1 ? 'error' : 'errors'
}:}`,
);
for (const error of errors) {
console.error(` ${error}`);
}
return true;
}
return false;
}
module.exports = testVersions;