244 строки
7.0 KiB
JavaScript
244 строки
7.0 KiB
JavaScript
let options = {
|
|
'beta1': {
|
|
value: null,
|
|
type: 'option',
|
|
},
|
|
'beta2': {
|
|
value: null,
|
|
type: 'option',
|
|
},
|
|
};
|
|
|
|
function getOption(name) {
|
|
return options[name].value;
|
|
}
|
|
|
|
function getOptionType(name) {
|
|
return options[name].type;
|
|
}
|
|
|
|
function setOption(name, value) {
|
|
return options[name].value = value;
|
|
}
|
|
|
|
let onLoad = new Promise(function(resolve, reject) {
|
|
window.onload = resolve;
|
|
});
|
|
|
|
function getComparison() {
|
|
if (!getOption('beta1') || !getOption('beta2')) {
|
|
return;
|
|
}
|
|
|
|
let version1 = getOption('beta1');
|
|
let version2 = getOption('beta2');
|
|
let build_id1 = '';
|
|
let build_id2 = '';
|
|
if (version1.includes(' - ')) {
|
|
let vals = version1.split(' - ');
|
|
version1 = vals[0];
|
|
build_id1 = vals[1];
|
|
}
|
|
if (version2.includes(' - ')) {
|
|
let vals = version2.split(' - ');
|
|
version2 = vals[0];
|
|
build_id2 = vals[1];
|
|
}
|
|
|
|
let url = new URL(location.href);
|
|
url.search = '?beta1=' + getOption('beta1') + '&beta2=' + getOption('beta2');
|
|
history.replaceState({}, document.title, url.href);
|
|
|
|
document.getElementById('frame').src = 'https://crash-analysis.mozilla.com/rkaiser/datil/searchcompare/?common=product%3DFirefox&p1=version%3D' + version1 + ((build_id1) ? '%26build_id=' + build_id1 : '') + '&p2=version%3D' + version2 + ((build_id2) ? '%26build_id=' + build_id2 : '');
|
|
|
|
let total1, total2;
|
|
Promise.all([
|
|
fetch('https://crash-stats.mozilla.com/api/SuperSearch/?product=Firefox&version=' + version1 + ((build_id1) ? '&build_id=' + build_id1 : '') + '&_results_number=0&_facets_size=0')
|
|
.then(response => response.json())
|
|
.then(results => total1 = results['total']),
|
|
fetch('https://crash-stats.mozilla.com/api/SuperSearch/?product=Firefox&version=' + version2 + ((build_id2) ? '&build_id=' + build_id2 : '') + '&_results_number=0&_facets_size=0')
|
|
.then(response => response.json())
|
|
.then(results => total2 = results['total']),
|
|
])
|
|
.then(() => {
|
|
let warning = '';
|
|
if (total1 < total2 * 0.3) {
|
|
warning = 'WARNING: Number of crash reports for ' + getOption('beta1') + ' (' + total1 + ') are way lower than for ' + getOption('beta2') + ' (' + total2 +'); the comparison might be skewed.';
|
|
} else if (total2 < total1 * 0.3) {
|
|
warning = 'WARNING: Number of crash reports for ' + getOption('beta2') + ' (' + total2 + ') are way lower than for ' + getOption('beta1') + ' (' + total1 +'); the comparison might be skewed.';
|
|
}
|
|
document.getElementById('warning').textContent = warning;
|
|
})
|
|
}
|
|
|
|
function compareBuildIDs(build_id1, build_id2) {
|
|
let year1 = Number(build_id1.substring(0, 4));
|
|
let year2 = Number(build_id2.substring(0, 4));
|
|
if (year1 > year2) {
|
|
return 1;
|
|
} else if (year1 < year2) {
|
|
return -1;
|
|
}
|
|
|
|
let month1 = Number(build_id1.substring(4, 6));
|
|
let month2 = Number(build_id2.substring(4, 6));
|
|
if (month1 > month2) {
|
|
return 1;
|
|
} else if (month1 < month2) {
|
|
return -1;
|
|
}
|
|
|
|
let day1 = Number(build_id1.substring(6, 8));
|
|
let day2 = Number(build_id2.substring(6, 8));
|
|
if (day1 > day2) {
|
|
return 1;
|
|
} else if (day1 < day2) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function compareVersions(versionA, versionB) {
|
|
let majorA = Number(versionA.substring(0, versionA.indexOf('.')));
|
|
let majorB = Number(versionB.substring(0, versionB.indexOf('.')));
|
|
|
|
if (majorA > majorB) {
|
|
return 1
|
|
} else if (majorA < majorB) {
|
|
return -1;
|
|
}
|
|
|
|
let minorA;
|
|
let minorB;
|
|
if (!versionA.includes(' - ')) {
|
|
minorA = Number(versionA.substring(versionA.indexOf('b') + 1))
|
|
} else {
|
|
minorA = Number(versionA.substring(versionA.indexOf('b') + 1), versionA.indexOf(' '));
|
|
}
|
|
if (!versionB.includes(' - ')) {
|
|
minorB = Number(versionB.substring(versionB.indexOf('b') + 1))
|
|
} else {
|
|
minorB = Number(versionB.substring(versionB.indexOf('b') + 1), versionB.indexOf(' '));
|
|
}
|
|
|
|
if (minorA > minorB) {
|
|
return 1;
|
|
} else if (minorA < minorB) {
|
|
return -1;
|
|
}
|
|
|
|
let buildIDA = versionA.substring(versionA.indexOf(' - ') + 3);
|
|
let buildIDB = versionB.substring(versionB.indexOf(' - ') + 3);
|
|
|
|
return compareBuildIDs(buildIDA, buildIDB);
|
|
}
|
|
|
|
onLoad
|
|
.then(() => fetch('https://crash-stats.mozilla.com/api/ProductVersions/?product=Firefox&active=true&build_type=beta'))
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
let versions = data['hits'].map(hit => hit['version']).filter(version => !isNaN(version[version.length - 1]));
|
|
|
|
let rc = versions.find(version => version.endsWith('b99'));
|
|
if (rc) {
|
|
return fetch('https://crash-stats.mozilla.com/api/SuperSearch/?version=' + rc + '&product=Firefox&_facets=build_id&_results_number=0')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
return data['facets']['build_id'].map(elem => rc + ' - ' + elem['term'])
|
|
.concat(versions)
|
|
.sort(compareVersions);
|
|
});
|
|
} else {
|
|
return versions;
|
|
}
|
|
})
|
|
.then(versions => {
|
|
// Only consider the latest 10 builds.
|
|
if (versions.length > 10) {
|
|
versions = versions.slice(versions.length - 10);
|
|
}
|
|
|
|
return versions;
|
|
})
|
|
.then(versions => {
|
|
let betas1 = document.getElementById('beta1');
|
|
let betas2 = document.getElementById('beta2');
|
|
|
|
for (let i = 0; i < versions.length; i++) {
|
|
let version = versions[i];
|
|
|
|
var opt = document.createElement('option');
|
|
opt.value = opt.textContent = version;
|
|
|
|
if (i != versions.length - 1) {
|
|
betas1.appendChild(opt);
|
|
}
|
|
|
|
if (i != 0) {
|
|
betas2.appendChild(opt.cloneNode(true));
|
|
}
|
|
}
|
|
|
|
betas1.selectedIndex = betas1.options.length - 1;
|
|
betas2.selectedIndex = betas2.options.length - 1;
|
|
})
|
|
.then(function() {
|
|
let queryVars = new URL(location.href).search.substring(1).split('&');
|
|
|
|
Object.keys(options)
|
|
.forEach(function(optionName) {
|
|
let optionType = getOptionType(optionName);
|
|
let elem = document.getElementById(optionName);
|
|
|
|
for (let queryVar of queryVars) {
|
|
if (queryVar.startsWith(optionName + '=')) {
|
|
let option = queryVar.substring((optionName + '=').length).trim();
|
|
setOption(optionName, option);
|
|
}
|
|
}
|
|
|
|
if (optionType === 'select') {
|
|
if (getOption(optionName)) {
|
|
elem.checked = getOption(optionName);
|
|
}
|
|
|
|
setOption(optionName, elem.checked);
|
|
} else if (optionType === 'option') {
|
|
if (getOption(optionName)) {
|
|
for (let i = 0; i < elem.options.length; i++) {
|
|
if (elem.options[i].value === decodeURIComponent(getOption(optionName))) {
|
|
elem.selectedIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
setOption(optionName, elem.options[elem.selectedIndex].value);
|
|
|
|
elem.onchange = function() {
|
|
setOption(optionName, elem.options[elem.selectedIndex].value);
|
|
};
|
|
} else if (optionType === 'button') {
|
|
if (getOption(optionName)) {
|
|
elem.value = getOption(optionName);
|
|
}
|
|
|
|
setOption(optionName, elem.value.trim());
|
|
} else {
|
|
throw new Error('Unexpected option type.');
|
|
}
|
|
|
|
document.getElementById('compareButton').onclick = function() {
|
|
getComparison();
|
|
};
|
|
});
|
|
|
|
if (queryVars.length >= 2) {
|
|
getComparison();
|
|
}
|
|
})
|
|
.catch(function(err) {
|
|
console.error(err);
|
|
});
|