207 lines
5.9 KiB
JavaScript
207 lines
5.9 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/* Shorthand constructors to construct an nsI(Local)File and zip reader: */
|
|
const LocalFile = new Components.Constructor(
|
|
"@mozilla.org/file/local;1",
|
|
Ci.nsIFile,
|
|
"initWithPath"
|
|
);
|
|
const ZipReader = new Components.Constructor(
|
|
"@mozilla.org/libjar/zip-reader;1",
|
|
"nsIZipReader",
|
|
"open"
|
|
);
|
|
|
|
const IS_ALPHA = /^[a-z]+$/i;
|
|
|
|
var { PerfTestHelpers } = ChromeUtils.importESModule(
|
|
"resource://testing-common/PerfTestHelpers.sys.mjs"
|
|
);
|
|
|
|
const kESModuleList = new Set([
|
|
/browser\/lockwise-card.js$/,
|
|
/browser\/monitor-card.js$/,
|
|
/browser\/proxy-card.js$/,
|
|
/browser\/vpn-card.js$/,
|
|
/toolkit\/content\/global\/certviewer\/components\/.*\.js$/,
|
|
/toolkit\/content\/global\/certviewer\/.*\.js$/,
|
|
/toolkit\/content\/global\/ml\/transformers.*\.js$/,
|
|
/chrome\/pdfjs\/content\/web\/.*\.js$/,
|
|
]);
|
|
|
|
/**
|
|
* Check if a URI should be parsed as an ES module.
|
|
*
|
|
* @param uri the uri to check against the ES module list
|
|
* @return true if the uri should be parsed as a module, otherwise parse it as a script.
|
|
*/
|
|
function uriIsESModule(uri) {
|
|
if (uri.filePath.endsWith(".mjs")) {
|
|
return true;
|
|
}
|
|
|
|
for (let allowlistItem of kESModuleList) {
|
|
if (allowlistItem.test(uri.spec)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns a promise that is resolved with a list of files that have one of the
|
|
* extensions passed, represented by their nsIURI objects, which exist inside
|
|
* the directory passed.
|
|
*
|
|
* @param dir the directory which to scan for files (nsIFile)
|
|
* @param extensions the extensions of files we're interested in (Array).
|
|
*/
|
|
function generateURIsFromDirTree(dir, extensions) {
|
|
if (!Array.isArray(extensions)) {
|
|
extensions = [extensions];
|
|
}
|
|
let dirQueue = [dir.path];
|
|
return (async function () {
|
|
let rv = [];
|
|
while (dirQueue.length) {
|
|
let nextDir = dirQueue.shift();
|
|
let { subdirs, files } = await iterateOverPath(nextDir, extensions);
|
|
dirQueue.push(...subdirs);
|
|
rv.push(...files);
|
|
}
|
|
return rv;
|
|
})();
|
|
}
|
|
|
|
/**
|
|
* Iterate over the children of |path| and find subdirectories and files with
|
|
* the given extension.
|
|
*
|
|
* This function recurses into ZIP and JAR archives as well.
|
|
*
|
|
* @param {string} path The path to check.
|
|
* @param {string[]} extensions The file extensions we're interested in.
|
|
*
|
|
* @returns {Promise<object>}
|
|
* A promise that resolves to an object containing the following
|
|
* properties:
|
|
* - files: an array of nsIURIs corresponding to
|
|
* files that match the extensions passed
|
|
* - subdirs: an array of paths for subdirectories we need to recurse
|
|
* into (handled by generateURIsFromDirTree above)
|
|
*/
|
|
async function iterateOverPath(path, extensions) {
|
|
const children = await IOUtils.getChildren(path);
|
|
|
|
const files = [];
|
|
const subdirs = [];
|
|
|
|
for (const entry of children) {
|
|
let stat;
|
|
try {
|
|
stat = await IOUtils.stat(entry);
|
|
} catch (error) {
|
|
if (error.name === "NotFoundError") {
|
|
// Ignore symlinks from prior builds to subsequently removed files
|
|
continue;
|
|
}
|
|
throw error;
|
|
}
|
|
|
|
if (stat.type === "directory") {
|
|
subdirs.push(entry);
|
|
} else if (extensions.some(extension => entry.endsWith(extension))) {
|
|
if (await IOUtils.exists(entry)) {
|
|
const spec = PathUtils.toFileURI(entry);
|
|
files.push(Services.io.newURI(spec));
|
|
}
|
|
} else if (
|
|
entry.endsWith(".ja") ||
|
|
entry.endsWith(".jar") ||
|
|
entry.endsWith(".zip") ||
|
|
entry.endsWith(".xpi")
|
|
) {
|
|
const file = new LocalFile(entry);
|
|
for (const extension of extensions) {
|
|
files.push(...generateEntriesFromJarFile(file, extension));
|
|
}
|
|
}
|
|
}
|
|
|
|
return { files, subdirs };
|
|
}
|
|
|
|
/* Helper function to generate a URI spec (NB: not an nsIURI yet!)
|
|
* given an nsIFile object */
|
|
function getURLForFile(file) {
|
|
let fileHandler = Services.io.getProtocolHandler("file");
|
|
fileHandler = fileHandler.QueryInterface(Ci.nsIFileProtocolHandler);
|
|
return fileHandler.getURLSpecFromActualFile(file);
|
|
}
|
|
|
|
/**
|
|
* A generator that generates nsIURIs for particular files found in jar files
|
|
* like omni.ja.
|
|
*
|
|
* @param jarFile an nsIFile object for the jar file that needs checking.
|
|
* @param extension the extension we're interested in.
|
|
*/
|
|
function* generateEntriesFromJarFile(jarFile, extension) {
|
|
let zr = new ZipReader(jarFile);
|
|
const kURIStart = getURLForFile(jarFile);
|
|
|
|
for (let entry of zr.findEntries("*" + extension + "$")) {
|
|
// Ignore the JS cache which is stored in omni.ja
|
|
if (entry.startsWith("jsloader") || entry.startsWith("jssubloader")) {
|
|
continue;
|
|
}
|
|
let entryURISpec = "jar:" + kURIStart + "!/" + entry;
|
|
yield Services.io.newURI(entryURISpec);
|
|
}
|
|
zr.close();
|
|
}
|
|
|
|
function fetchFile(uri) {
|
|
return new Promise(resolve => {
|
|
let xhr = new XMLHttpRequest();
|
|
xhr.responseType = "text";
|
|
xhr.open("GET", uri, true);
|
|
xhr.onreadystatechange = function () {
|
|
if (this.readyState != this.DONE) {
|
|
return;
|
|
}
|
|
try {
|
|
resolve(this.responseText);
|
|
} catch (ex) {
|
|
ok(false, `Script error reading ${uri}: ${ex}`);
|
|
resolve("");
|
|
}
|
|
};
|
|
xhr.onerror = error => {
|
|
ok(false, `XHR error reading ${uri}: ${error}`);
|
|
resolve("");
|
|
};
|
|
xhr.send(null);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns whether or not a word (presumably in en-US) is capitalized per
|
|
* expectations.
|
|
*
|
|
* @param {String} word The single word to check.
|
|
* @param {boolean} expectCapitalized True if the word should be capitalized.
|
|
* @returns {boolean} True if the word matches the expected capitalization.
|
|
*/
|
|
function hasExpectedCapitalization(word, expectCapitalized) {
|
|
let firstChar = word[0];
|
|
if (!IS_ALPHA.test(firstChar)) {
|
|
return true;
|
|
}
|
|
|
|
let isCapitalized = firstChar == firstChar.toLocaleUpperCase("en-US");
|
|
return isCapitalized == expectCapitalized;
|
|
}
|