File: generate-runtime-code.js

package info (click to toggle)
node-webpack 5.97.1%2Bdfsg1%2B~cs11.18.27-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 59,064 kB
  • sloc: javascript: 185,073; makefile: 16; sh: 6
file content (99 lines) | stat: -rw-r--r-- 2,661 bytes parent folder | download
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
const path = require("path");
const fs = require("fs");
const terser = require("terser");
const prettier = require("prettier");

// When --write is set, files will be written in place
// Otherwise it only prints outdated files
const doWrite = process.argv.includes("--write");

const files = ["lib/util/semver.js"];

(async () => {
	for (const file of files) {
		const filePath = path.resolve(__dirname, "..", file);
		const content = fs.readFileSync(filePath, "utf-8");
		const exports = require(`../${file}`);

		const regexp =
			/\n\/\/#region runtime code: (.+)\n[\s\S]+?\/\/#endregion\n/g;

		const replaces = new Map();

		let match = regexp.exec(content);
		while (match) {
			const [fullMatch, name] = match;
			const originalCode = exports[name].toString();
			const header =
				/** @type {RegExpExecArray} */
				(/^\(?([^=)]+)\)?\s=> \{/.exec(originalCode));
			const body = originalCode.slice(header[0].length, -1);
			const result = await terser.minify(
				{
					["input.js"]: body
				},
				{
					compress: true,
					mangle: true,
					ecma: 5,
					toplevel: true,
					parse: {
						// eslint-disable-next-line camelcase
						bare_returns: true
					}
				}
			);

			if (!result.code) {
				throw new Error(`No code generated for ${name} in ${file}`);
			}

			const args = header[1];
			if (/`|const|let|=>|\.\.\./.test(result.code)) {
				throw new Error(`Code Style of ${name} in ${file} is too high`);
			}
			let templateLiteral = false;
			const code = result.code
				.replace(/\\/g, "\\\\")
				.replace(/'/g, "\\'")
				.replace(/function\(([^)]+)\)/g, (m, args) => {
					templateLiteral = true;
					return `\${runtimeTemplate.supportsArrowFunction() ? '${
						args.includes(",") ? `(${args})` : args
					}=>' : 'function(${args})'}`;
				});
			replaces.set(
				fullMatch,
				`
//#region runtime code: ${name}
/**
 * @param {RuntimeTemplate} runtimeTemplate
 * @returns {string}
 */
exports.${name}RuntimeCode = runtimeTemplate => \`var ${name} = \${runtimeTemplate.basicFunction("${args}", [
	"// see webpack/${file} for original code",
	${templateLiteral ? `\`${code}\`` : `'${code}'`}
])}\`;
//#endregion
`
			);
			match = regexp.exec(content);
		}

		const prettierConfig = await prettier.resolveConfig(filePath);
		const newContent = await prettier.format(
			content.replace(regexp, match => replaces.get(match)),
			{ filepath: filePath, ...prettierConfig }
		);

		if (newContent !== content) {
			if (doWrite) {
				fs.writeFileSync(filePath, newContent, "utf-8");
				console.error(`${file} updated`);
			} else {
				console.error(`${file} need to be updated`);
				process.exitCode = 1;
			}
		}
	}
})();