source: imaps-frontend/node_modules/webpack/lib/optimize/MangleExportsPlugin.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

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