| | |
| | | import fs from "fs"; |
| | | import { join } from "path"; |
| | | import { URL, fileURLToPath } from "url"; |
| | | import { minify } from "terser"; // eslint-disable-line |
| | | |
| | | const HELPERS_FOLDER = new URL("../src/helpers", import.meta.url); |
| | | const IGNORED_FILES = new Set(["package.json"]); |
| | | |
| | | export default async function generateAsserts() { |
| | | export default async function generateHelpers() { |
| | | let output = `/* |
| | | * This file is auto-generated! Do not modify it directly. |
| | | * To re-generate run 'make build' |
| | | * To re-generate run 'yarn gulp generate-runtime-helpers' |
| | | */ |
| | | |
| | | import template from "@babel/template"; |
| | | |
| | | function helper(minVersion, source) { |
| | | return Object.freeze({ |
| | | minVersion, |
| | | ast: () => template.program.ast(source), |
| | | }) |
| | | } |
| | | |
| | | export default Object.freeze({ |
| | | `; |
| | | |
| | | for (const file of (await fs.promises.readdir(HELPERS_FOLDER)).sort()) { |
| | |
| | | if (file.startsWith(".")) continue; // ignore e.g. vim swap files |
| | | |
| | | const [helperName] = file.split("."); |
| | | const isValidId = isValidBindingIdentifier(helperName); |
| | | const varName = isValidId ? helperName : `_${helperName}`; |
| | | |
| | | const filePath = join(fileURLToPath(HELPERS_FOLDER), file); |
| | | if (!file.endsWith(".js")) { |
| | | console.error("ignoring", filePath); |
| | | continue; |
| | | } |
| | | |
| | | const fileContents = await fs.promises.readFile(filePath, "utf8"); |
| | | const minVersionMatch = fileContents.match( |
| | | /^\s*\/\*\s*@minVersion\s+(?<minVersion>\S+)\s*\*\/\s*$/m |
| | |
| | | } |
| | | const { minVersion } = minVersionMatch.groups; |
| | | |
| | | // TODO: We can minify the helpers in production |
| | | const source = fileContents |
| | | // Remove comments |
| | | .replace(/\/\*[^]*?\*\/|\/\/.*/g, "") |
| | | // Remove multiple newlines |
| | | .replace(/\n{2,}/g, "\n"); |
| | | const source = await minify(fileContents, { |
| | | mangle: false, |
| | | // The _typeof helper has a custom directive that we must keep |
| | | compress: { directives: false }, |
| | | }); |
| | | |
| | | const intro = isValidId |
| | | ? "export " |
| | | : `export { ${varName} as ${helperName} }\n`; |
| | | |
| | | output += `\n${intro}const ${varName} = { |
| | | minVersion: ${JSON.stringify(minVersion)}, |
| | | ast: () => template.program.ast(${JSON.stringify(source)}) |
| | | };\n`; |
| | | output += `\ |
| | | ${JSON.stringify(helperName)}: helper( |
| | | ${JSON.stringify(minVersion)}, |
| | | ${JSON.stringify(source.code)}, |
| | | ), |
| | | `; |
| | | } |
| | | |
| | | output += "});"; |
| | | return output; |
| | | } |
| | | |
| | | function isValidBindingIdentifier(name) { |
| | | try { |
| | | Function(`var ${name}`); |
| | | return true; |
| | | } catch { |
| | | return false; |
| | | } |
| | | } |