source: frontend/node_modules/webpack/lib/optimize/MangleExportsPlugin.js@ cdcff72

Last change on this file since cdcff72 was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { UsageState } = require("../ExportsInfo");
9const {
10 NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS,
11 NUMBER_OF_IDENTIFIER_START_CHARS,
12 numberToIdentifier
13} = require("../Template");
14const { assignDeterministicIds } = require("../ids/IdHelpers");
15const { compareSelect, compareStringsNumeric } = require("../util/comparators");
16
17/** @typedef {import("../Compiler")} Compiler */
18/** @typedef {import("../ExportsInfo")} ExportsInfo */
19/** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
20/** @typedef {import("../util/concatenate").UsedNames} UsedNames */
21
22/**
23 * Defines the comparator type used by this module.
24 * @template T
25 * @typedef {import("../util/comparators").Comparator<T>} Comparator
26 */
27
28/**
29 * Checks whether it can mangle.
30 * @param {ExportsInfo} exportsInfo exports info
31 * @returns {boolean} mangle is possible
32 */
33const canMangle = (exportsInfo) => {
34 if (exportsInfo.otherExportsInfo.getUsed(undefined) !== UsageState.Unused) {
35 return false;
36 }
37 let hasSomethingToMangle = false;
38 for (const exportInfo of exportsInfo.exports) {
39 if (exportInfo.canMangle === true) {
40 hasSomethingToMangle = true;
41 }
42 }
43 return hasSomethingToMangle;
44};
45
46// Sort by name
47/** @type {Comparator<ExportInfo>} */
48const comparator = compareSelect((e) => e.name, compareStringsNumeric);
49/**
50 * Mangle exports info.
51 * @param {boolean} deterministic use deterministic names
52 * @param {ExportsInfo} exportsInfo exports info
53 * @param {boolean | undefined} isNamespace is namespace object
54 * @returns {void}
55 */
56const mangleExportsInfo = (deterministic, exportsInfo, isNamespace) => {
57 if (!canMangle(exportsInfo)) return;
58 /** @type {UsedNames} */
59 const usedNames = new Set();
60 /** @type {ExportInfo[]} */
61 const mangleableExports = [];
62
63 // Avoid to renamed exports that are not provided when
64 // 1. it's not a namespace export: non-provided exports can be found in prototype chain
65 // 2. there are other provided exports and deterministic mode is chosen:
66 // non-provided exports would break the determinism
67 let avoidMangleNonProvided = !isNamespace;
68 if (!avoidMangleNonProvided && deterministic) {
69 for (const exportInfo of exportsInfo.ownedExports) {
70 if (exportInfo.provided !== false) {
71 avoidMangleNonProvided = true;
72 break;
73 }
74 }
75 }
76 for (const exportInfo of exportsInfo.ownedExports) {
77 const name = exportInfo.name;
78 if (!exportInfo.hasUsedName()) {
79 if (
80 // Can the export be mangled?
81 exportInfo.canMangle !== true ||
82 // Never rename 1 char exports
83 (name.length === 1 && /^[a-z0-9_$]/i.test(name)) ||
84 // Don't rename 2 char exports in deterministic mode
85 (deterministic &&
86 name.length === 2 &&
87 /^[a-z_$][a-z0-9_$]|^[1-9][0-9]/i.test(name)) ||
88 // Don't rename exports that are not provided
89 (avoidMangleNonProvided && exportInfo.provided !== true)
90 ) {
91 exportInfo.setUsedName(name);
92 usedNames.add(name);
93 } else {
94 mangleableExports.push(exportInfo);
95 }
96 }
97 if (exportInfo.exportsInfoOwned) {
98 const used = exportInfo.getUsed(undefined);
99 if (
100 used === UsageState.OnlyPropertiesUsed ||
101 used === UsageState.Unused
102 ) {
103 mangleExportsInfo(
104 deterministic,
105 /** @type {ExportsInfo} */ (exportInfo.exportsInfo),
106 false
107 );
108 }
109 }
110 }
111 if (deterministic) {
112 assignDeterministicIds(
113 mangleableExports,
114 (e) => e.name,
115 comparator,
116 (e, id) => {
117 const name = numberToIdentifier(id);
118 const size = usedNames.size;
119 usedNames.add(name);
120 if (size === usedNames.size) return false;
121 e.setUsedName(name);
122 return true;
123 },
124 [
125 NUMBER_OF_IDENTIFIER_START_CHARS,
126 NUMBER_OF_IDENTIFIER_START_CHARS *
127 NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
128 ],
129 NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS,
130 usedNames.size
131 );
132 } else {
133 /** @type {ExportInfo[]} */
134 const usedExports = [];
135 /** @type {ExportInfo[]} */
136 const unusedExports = [];
137 for (const exportInfo of mangleableExports) {
138 if (exportInfo.getUsed(undefined) === UsageState.Unused) {
139 unusedExports.push(exportInfo);
140 } else {
141 usedExports.push(exportInfo);
142 }
143 }
144 usedExports.sort(comparator);
145 unusedExports.sort(comparator);
146 let i = 0;
147 for (const list of [usedExports, unusedExports]) {
148 for (const exportInfo of list) {
149 /** @type {string} */
150 let name;
151 do {
152 name = numberToIdentifier(i++);
153 } while (usedNames.has(name));
154 exportInfo.setUsedName(name);
155 }
156 }
157 }
158};
159
160const PLUGIN_NAME = "MangleExportsPlugin";
161
162class MangleExportsPlugin {
163 /**
164 * Creates an instance of MangleExportsPlugin.
165 * @param {boolean} deterministic use deterministic names
166 */
167 constructor(deterministic) {
168 /** @type {boolean} */
169 this._deterministic = deterministic;
170 }
171
172 /**
173 * Applies the plugin by registering its hooks on the compiler.
174 * @param {Compiler} compiler the compiler instance
175 * @returns {void}
176 */
177 apply(compiler) {
178 const { _deterministic: deterministic } = this;
179 compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
180 const moduleGraph = compilation.moduleGraph;
181 compilation.hooks.optimizeCodeGeneration.tap(PLUGIN_NAME, (modules) => {
182 if (compilation.moduleMemCaches) {
183 throw new Error(
184 "optimization.mangleExports can't be used with cacheUnaffected as export mangling is a global effect"
185 );
186 }
187 for (const module of modules) {
188 const isNamespace =
189 module.buildMeta && module.buildMeta.exportsType === "namespace";
190 const exportsInfo = moduleGraph.getExportsInfo(module);
191 mangleExportsInfo(deterministic, exportsInfo, isNamespace);
192 }
193 });
194 });
195 }
196}
197
198module.exports = MangleExportsPlugin;
Note: See TracBrowser for help on using the repository browser.