You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/scripts/globals-extractor.mjs

92 lines
3.1 KiB

/** ----------------------------------------------------------------------
This script gets a list of global objects/functions of browser.
This process is simple for now, so it is handled without AST parser.
Please run `node scripts/globals-extractor.mjs` at the project root.
see: https://github.com/microsoft/TypeScript/tree/main/lib
---------------------------------------------------------------------- */
import http from 'https';
import fs from 'fs';
const GLOBAL_TS_PATH = './src/compiler/utils/globals.ts';
// MEMO: add additional objects/functions which existed in `src/compiler/utils/names.ts`
// before this script was introduced but could not be retrieved by this process.
const SPECIALS = ['global', 'globalThis', 'InternalError', 'process', 'undefined'];
const get_url = (name) => `https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.${name}.d.ts`;
const extract_name = (split) => split.match(/^[a-zA-Z0-9_$]+/)[0];
const extract_functions_and_references = (name, data) => {
const functions = [];
const references = [];
data.split('\n').forEach(line => {
const trimmed = line.trim();
const split = trimmed.replace(/[\s+]/, ' ').split(' ');
if (split[0] === 'declare' && split[1] !== 'type') {
functions.push(extract_name(split[2]));
} else if (trimmed.startsWith('/// <reference')) {
const matched = trimmed.match(/ lib="(.+)"/);
const reference = matched && matched[1];
if (reference) references.push(reference);
}
});
return { functions, references };
};
const do_get = (url) => new Promise((resolve, reject) => {
http.get(url, (res) => {
let body = '';
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => resolve(body));
}).on('error', (e) => {
console.error(e.message);
reject(e);
});
});
const fetched_names = new Set();
const get_functions = async (name) => {
const res = [];
if (fetched_names.has(name)) return res;
fetched_names.add(name);
const body = await do_get(get_url(name));
const { functions, references } = extract_functions_and_references(name, body);
res.push(...functions);
const chile_functions = await Promise.all(references.map(get_functions));
chile_functions.forEach(i => res.push(...i));
return res;
};
const build_output = (functions) => {
const sorted = Array.from(new Set(functions.sort()));
return `\
/** ----------------------------------------------------------------------
This file is automatically generated by \`scripts/globals-extractor.mjs\`.
Generated At: ${new Date().toISOString()}
---------------------------------------------------------------------- */
export default new Set([
${sorted.map((i) => `\t'${i}'`).join(',\n')}
]);
`;
};
const get_exists_globals = () => {
const regexp = /^\s*["'](.+)["'],?\s*$/;
return fs.readFileSync(GLOBAL_TS_PATH, 'utf8')
.split('\n')
.filter(line => line.match(regexp))
.map(line => line.match(regexp)[1]);
};
(async () => {
const globals = get_exists_globals();
const new_globals = await get_functions('es2021.full');
globals.forEach((g) => new_globals.push(g));
SPECIALS.forEach((g) => new_globals.push(g));
fs.writeFileSync(GLOBAL_TS_PATH, build_output(new_globals));
})();