1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const Dependency = require("../Dependency");
|
9 | const { UsageState } = require("../ExportsInfo");
|
10 | const Template = require("../Template");
|
11 | const { equals } = require("../util/ArrayHelpers");
|
12 | const makeSerializable = require("../util/makeSerializable");
|
13 | const propertyAccess = require("../util/propertyAccess");
|
14 | const { handleDependencyBase } = require("./CommonJsDependencyHelpers");
|
15 | const ModuleDependency = require("./ModuleDependency");
|
16 | const processExportInfo = require("./processExportInfo");
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | const idsSymbol = Symbol("CommonJsExportRequireDependency.ids");
|
28 |
|
29 | const EMPTY_OBJECT = {};
|
30 |
|
31 | class CommonJsExportRequireDependency extends ModuleDependency {
|
32 | constructor(range, valueRange, base, names, request, ids, resultUsed) {
|
33 | super(request);
|
34 | this.range = range;
|
35 | this.valueRange = valueRange;
|
36 | this.base = base;
|
37 | this.names = names;
|
38 | this.ids = ids;
|
39 | this.resultUsed = resultUsed;
|
40 | this.asiSafe = undefined;
|
41 | }
|
42 |
|
43 | get type() {
|
44 | return "cjs export require";
|
45 | }
|
46 |
|
47 | |
48 |
|
49 |
|
50 | couldAffectReferencingModule() {
|
51 | return Dependency.TRANSITIVE;
|
52 | }
|
53 |
|
54 | |
55 |
|
56 |
|
57 |
|
58 | getIds(moduleGraph) {
|
59 | return moduleGraph.getMeta(this)[idsSymbol] || this.ids;
|
60 | }
|
61 |
|
62 | |
63 |
|
64 |
|
65 |
|
66 |
|
67 | setIds(moduleGraph, ids) {
|
68 | moduleGraph.getMeta(this)[idsSymbol] = ids;
|
69 | }
|
70 |
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | getReferencedExports(moduleGraph, runtime) {
|
78 | const ids = this.getIds(moduleGraph);
|
79 | const getFullResult = () => {
|
80 | if (ids.length === 0) {
|
81 | return Dependency.EXPORTS_OBJECT_REFERENCED;
|
82 | } else {
|
83 | return [
|
84 | {
|
85 | name: ids,
|
86 | canMangle: false
|
87 | }
|
88 | ];
|
89 | }
|
90 | };
|
91 | if (this.resultUsed) return getFullResult();
|
92 | let exportsInfo = moduleGraph.getExportsInfo(
|
93 | moduleGraph.getParentModule(this)
|
94 | );
|
95 | for (const name of this.names) {
|
96 | const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
|
97 | const used = exportInfo.getUsed(runtime);
|
98 | if (used === UsageState.Unused) return Dependency.NO_EXPORTS_REFERENCED;
|
99 | if (used !== UsageState.OnlyPropertiesUsed) return getFullResult();
|
100 | exportsInfo = exportInfo.exportsInfo;
|
101 | if (!exportsInfo) return getFullResult();
|
102 | }
|
103 | if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
|
104 | return getFullResult();
|
105 | }
|
106 |
|
107 | const referencedExports = [];
|
108 | for (const exportInfo of exportsInfo.orderedExports) {
|
109 | processExportInfo(
|
110 | runtime,
|
111 | referencedExports,
|
112 | ids.concat(exportInfo.name),
|
113 | exportInfo,
|
114 | false
|
115 | );
|
116 | }
|
117 | return referencedExports.map(name => ({
|
118 | name,
|
119 | canMangle: false
|
120 | }));
|
121 | }
|
122 |
|
123 | |
124 |
|
125 |
|
126 |
|
127 |
|
128 | getExports(moduleGraph) {
|
129 | const ids = this.getIds(moduleGraph);
|
130 | if (this.names.length === 1) {
|
131 | const name = this.names[0];
|
132 | const from = moduleGraph.getConnection(this);
|
133 | if (!from) return;
|
134 | return {
|
135 | exports: [
|
136 | {
|
137 | name,
|
138 | from,
|
139 | export: ids.length === 0 ? null : ids,
|
140 |
|
141 |
|
142 |
|
143 | canMangle: !(name in EMPTY_OBJECT) && false
|
144 | }
|
145 | ],
|
146 | dependencies: [from.module]
|
147 | };
|
148 | } else if (this.names.length > 0) {
|
149 | const name = this.names[0];
|
150 | return {
|
151 | exports: [
|
152 | {
|
153 | name,
|
154 |
|
155 |
|
156 |
|
157 | canMangle: !(name in EMPTY_OBJECT) && false
|
158 | }
|
159 | ],
|
160 | dependencies: undefined
|
161 | };
|
162 | } else {
|
163 | const from = moduleGraph.getConnection(this);
|
164 | if (!from) return;
|
165 | const reexportInfo = this.getStarReexports(
|
166 | moduleGraph,
|
167 | undefined,
|
168 | from.module
|
169 | );
|
170 | if (reexportInfo) {
|
171 | return {
|
172 | exports: Array.from(reexportInfo.exports, name => {
|
173 | return {
|
174 | name,
|
175 | from,
|
176 | export: ids.concat(name),
|
177 | canMangle: !(name in EMPTY_OBJECT) && false
|
178 | };
|
179 | }),
|
180 |
|
181 | dependencies: [from.module]
|
182 | };
|
183 | } else {
|
184 | return {
|
185 | exports: true,
|
186 | from: ids.length === 0 ? from : undefined,
|
187 | canMangle: false,
|
188 | dependencies: [from.module]
|
189 | };
|
190 | }
|
191 | }
|
192 | }
|
193 |
|
194 | |
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | getStarReexports(
|
201 | moduleGraph,
|
202 | runtime,
|
203 | importedModule = moduleGraph.getModule(this)
|
204 | ) {
|
205 | let importedExportsInfo = moduleGraph.getExportsInfo(importedModule);
|
206 | const ids = this.getIds(moduleGraph);
|
207 | if (ids.length > 0)
|
208 | importedExportsInfo = importedExportsInfo.getNestedExportsInfo(ids);
|
209 | let exportsInfo = moduleGraph.getExportsInfo(
|
210 | moduleGraph.getParentModule(this)
|
211 | );
|
212 | if (this.names.length > 0)
|
213 | exportsInfo = exportsInfo.getNestedExportsInfo(this.names);
|
214 |
|
215 | const noExtraExports =
|
216 | importedExportsInfo &&
|
217 | importedExportsInfo.otherExportsInfo.provided === false;
|
218 | const noExtraImports =
|
219 | exportsInfo &&
|
220 | exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused;
|
221 |
|
222 | if (!noExtraExports && !noExtraImports) {
|
223 | return;
|
224 | }
|
225 |
|
226 | const isNamespaceImport =
|
227 | importedModule.getExportsType(moduleGraph, false) === "namespace";
|
228 |
|
229 |
|
230 | const exports = new Set();
|
231 |
|
232 | const checked = new Set();
|
233 |
|
234 | if (noExtraImports) {
|
235 | for (const exportInfo of exportsInfo.orderedExports) {
|
236 | const name = exportInfo.name;
|
237 | if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
|
238 | if (name === "__esModule" && isNamespaceImport) {
|
239 | exports.add(name);
|
240 | } else if (importedExportsInfo) {
|
241 | const importedExportInfo =
|
242 | importedExportsInfo.getReadOnlyExportInfo(name);
|
243 | if (importedExportInfo.provided === false) continue;
|
244 | exports.add(name);
|
245 | if (importedExportInfo.provided === true) continue;
|
246 | checked.add(name);
|
247 | } else {
|
248 | exports.add(name);
|
249 | checked.add(name);
|
250 | }
|
251 | }
|
252 | } else if (noExtraExports) {
|
253 | for (const importedExportInfo of importedExportsInfo.orderedExports) {
|
254 | const name = importedExportInfo.name;
|
255 | if (importedExportInfo.provided === false) continue;
|
256 | if (exportsInfo) {
|
257 | const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
|
258 | if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
|
259 | }
|
260 | exports.add(name);
|
261 | if (importedExportInfo.provided === true) continue;
|
262 | checked.add(name);
|
263 | }
|
264 | if (isNamespaceImport) {
|
265 | exports.add("__esModule");
|
266 | checked.delete("__esModule");
|
267 | }
|
268 | }
|
269 |
|
270 | return { exports, checked };
|
271 | }
|
272 |
|
273 | serialize(context) {
|
274 | const { write } = context;
|
275 | write(this.asiSafe);
|
276 | write(this.range);
|
277 | write(this.valueRange);
|
278 | write(this.base);
|
279 | write(this.names);
|
280 | write(this.ids);
|
281 | write(this.resultUsed);
|
282 | super.serialize(context);
|
283 | }
|
284 |
|
285 | deserialize(context) {
|
286 | const { read } = context;
|
287 | this.asiSafe = read();
|
288 | this.range = read();
|
289 | this.valueRange = read();
|
290 | this.base = read();
|
291 | this.names = read();
|
292 | this.ids = read();
|
293 | this.resultUsed = read();
|
294 | super.deserialize(context);
|
295 | }
|
296 | }
|
297 |
|
298 | makeSerializable(
|
299 | CommonJsExportRequireDependency,
|
300 | "webpack/lib/dependencies/CommonJsExportRequireDependency"
|
301 | );
|
302 |
|
303 | CommonJsExportRequireDependency.Template = class CommonJsExportRequireDependencyTemplate extends (
|
304 | ModuleDependency.Template
|
305 | ) {
|
306 | |
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 | apply(
|
313 | dependency,
|
314 | source,
|
315 | {
|
316 | module,
|
317 | runtimeTemplate,
|
318 | chunkGraph,
|
319 | moduleGraph,
|
320 | runtimeRequirements,
|
321 | runtime
|
322 | }
|
323 | ) {
|
324 | const dep = (dependency);
|
325 | const used = moduleGraph
|
326 | .getExportsInfo(module)
|
327 | .getUsedName(dep.names, runtime);
|
328 |
|
329 | const [type, base] = handleDependencyBase(
|
330 | dep.base,
|
331 | module,
|
332 | runtimeRequirements
|
333 | );
|
334 |
|
335 | const importedModule = moduleGraph.getModule(dep);
|
336 | let requireExpr = runtimeTemplate.moduleExports({
|
337 | module: importedModule,
|
338 | chunkGraph,
|
339 | request: dep.request,
|
340 | weak: dep.weak,
|
341 | runtimeRequirements
|
342 | });
|
343 | if (importedModule) {
|
344 | const ids = dep.getIds(moduleGraph);
|
345 | const usedImported = moduleGraph
|
346 | .getExportsInfo(importedModule)
|
347 | .getUsedName(ids, runtime);
|
348 | if (usedImported) {
|
349 | const comment = equals(usedImported, ids)
|
350 | ? ""
|
351 | : Template.toNormalComment(propertyAccess(ids)) + " ";
|
352 | requireExpr += `${comment}${propertyAccess(usedImported)}`;
|
353 | }
|
354 | }
|
355 |
|
356 | switch (type) {
|
357 | case "expression":
|
358 | source.replace(
|
359 | dep.range[0],
|
360 | dep.range[1] - 1,
|
361 | used
|
362 | ? `${base}${propertyAccess(used)} = ${requireExpr}`
|
363 | : `/* unused reexport */ ${requireExpr}`
|
364 | );
|
365 | return;
|
366 | case "Object.defineProperty":
|
367 | throw new Error("TODO");
|
368 | default:
|
369 | throw new Error("Unexpected type");
|
370 | }
|
371 | }
|
372 | };
|
373 |
|
374 | module.exports = CommonJsExportRequireDependency;
|