source: frontend/node_modules/webpack/lib/dependencies/CommonJsExportRequireDependency.js

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

Fix frontend appearance

  • Property mode set to 100644
File size: 13.6 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const Dependency = require("../Dependency");
9const { UsageState } = require("../ExportsInfo");
10const Template = require("../Template");
11const { equals } = require("../util/ArrayHelpers");
12const makeSerializable = require("../util/makeSerializable");
13const { propertyAccess } = require("../util/property");
14const {
15 ESM_MODULE_EXPORTS_NAME,
16 getRequireEsmModuleExportsAccess,
17 handleDependencyBase,
18 isRequireEsmModuleExportsModule
19} = require("./CommonJsDependencyHelpers");
20const ModuleDependency = require("./ModuleDependency");
21const processExportInfo = require("./processExportInfo");
22
23/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
24/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
25/** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
26/** @typedef {import("../Dependency").ReferencedExports} ReferencedExports */
27/** @typedef {import("../Dependency").TRANSITIVE} TRANSITIVE */
28/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
29/** @typedef {import("../ExportsInfo")} ExportsInfo */
30/** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
31/** @typedef {import("../ExportsInfo").ExportInfoName} ExportInfoName */
32/** @typedef {import("../Module")} Module */
33/** @typedef {import("../ModuleGraph")} ModuleGraph */
34/** @typedef {import("../javascript/JavascriptParser").Range} Range */
35/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
36/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
37/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
38/** @typedef {import("./CommonJsDependencyHelpers").CommonJSDependencyBaseKeywords} CommonJSDependencyBaseKeywords */
39
40const idsSymbol = /** @type {symbol} */ (
41 Symbol("CommonJsExportRequireDependency.ids")
42);
43
44const EMPTY_OBJECT = {};
45
46/** @typedef {Set<string>} Exports */
47/** @typedef {Set<string>} Checked */
48
49class CommonJsExportRequireDependency extends ModuleDependency {
50 /**
51 * Creates an instance of CommonJsExportRequireDependency.
52 * @param {Range} range range
53 * @param {Range | null} valueRange value range
54 * @param {CommonJSDependencyBaseKeywords} base base
55 * @param {ExportInfoName[]} names names
56 * @param {string} request request
57 * @param {ExportInfoName[]} ids ids
58 * @param {boolean} resultUsed true, when the result is used
59 */
60 constructor(range, valueRange, base, names, request, ids, resultUsed) {
61 super(request);
62 this.range = range;
63 this.valueRange = valueRange;
64 this.base = base;
65 this.names = names;
66 this.ids = ids;
67 this.resultUsed = resultUsed;
68 /** @type {undefined | boolean} */
69 this.asiSafe = undefined;
70 }
71
72 get type() {
73 return "cjs export require";
74 }
75
76 get category() {
77 return "commonjs";
78 }
79
80 /**
81 * Could affect referencing module.
82 * @returns {boolean | TRANSITIVE} true, when changes to the referenced module could affect the referencing module; TRANSITIVE, when changes to the referenced module could affect referencing modules of the referencing module
83 */
84 couldAffectReferencingModule() {
85 return Dependency.TRANSITIVE;
86 }
87
88 /**
89 * Returns the imported id.
90 * @param {ModuleGraph} moduleGraph the module graph
91 * @returns {ExportInfoName[]} the imported id
92 */
93 getIds(moduleGraph) {
94 return moduleGraph.getMeta(this)[idsSymbol] || this.ids;
95 }
96
97 /**
98 * Updates ids using the provided module graph.
99 * @param {ModuleGraph} moduleGraph the module graph
100 * @param {ExportInfoName[]} ids the imported ids
101 * @returns {void}
102 */
103 setIds(moduleGraph, ids) {
104 moduleGraph.getMeta(this)[idsSymbol] = ids;
105 }
106
107 /**
108 * Returns list of exports referenced by this dependency
109 * @param {ModuleGraph} moduleGraph module graph
110 * @param {RuntimeSpec} runtime the runtime for which the module is analysed
111 * @returns {ReferencedExports} referenced exports
112 */
113 getReferencedExports(moduleGraph, runtime) {
114 const ids = this.getIds(moduleGraph);
115 const importedModule = moduleGraph.getModule(this);
116 if (
117 importedModule &&
118 isRequireEsmModuleExportsModule(importedModule, moduleGraph)
119 ) {
120 // `require(esm)` unwraps the "module.exports" named export; any
121 // further property access lands on that value (which webpack does
122 // not model), so only the "module.exports" export is observable.
123 return [[ESM_MODULE_EXPORTS_NAME]];
124 }
125 const getFullResult = () => {
126 if (ids.length === 0) {
127 return Dependency.EXPORTS_OBJECT_REFERENCED;
128 }
129 return [
130 {
131 name: ids,
132 canMangle: false
133 }
134 ];
135 };
136 if (this.resultUsed) return getFullResult();
137 /** @type {ExportsInfo | undefined} */
138 let exportsInfo = moduleGraph.getExportsInfo(
139 /** @type {Module} */ (moduleGraph.getParentModule(this))
140 );
141 for (const name of this.names) {
142 const exportInfo =
143 /** @type {ExportInfo} */
144 (exportsInfo.getReadOnlyExportInfo(name));
145 const used = exportInfo.getUsed(runtime);
146 if (used === UsageState.Unused) return Dependency.NO_EXPORTS_REFERENCED;
147 if (used !== UsageState.OnlyPropertiesUsed) return getFullResult();
148 exportsInfo = exportInfo.exportsInfo;
149 if (!exportsInfo) return getFullResult();
150 }
151 if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
152 return getFullResult();
153 }
154 /** @type {RawReferencedExports} */
155 const referencedExports = [];
156 for (const exportInfo of exportsInfo.orderedExports) {
157 processExportInfo(
158 runtime,
159 referencedExports,
160 [...ids, exportInfo.name],
161 exportInfo,
162 false
163 );
164 }
165 return referencedExports.map((name) => ({
166 name,
167 canMangle: false
168 }));
169 }
170
171 /**
172 * Returns the exported names
173 * @param {ModuleGraph} moduleGraph module graph
174 * @returns {ExportsSpec | undefined} export names
175 */
176 getExports(moduleGraph) {
177 const importedModule = moduleGraph.getModule(this);
178 const esmUnwrap =
179 importedModule &&
180 isRequireEsmModuleExportsModule(importedModule, moduleGraph);
181 if (this.names.length === 1) {
182 const ids = this.getIds(moduleGraph);
183 const name = this.names[0];
184 const from = moduleGraph.getConnection(this);
185 if (!from) return;
186 const exportChain = esmUnwrap
187 ? [ESM_MODULE_EXPORTS_NAME, ...ids]
188 : ids.length === 0
189 ? null
190 : ids;
191 return {
192 exports: [
193 {
194 name,
195 from,
196 export: exportChain,
197 // we can't mangle names that are in an empty object
198 // because one could access the prototype property
199 // when export isn't set yet
200 canMangle: !(name in EMPTY_OBJECT) && false
201 }
202 ],
203 dependencies: [from.module]
204 };
205 } else if (this.names.length > 0) {
206 const name = this.names[0];
207 return {
208 exports: [
209 {
210 name,
211 // we can't mangle names that are in an empty object
212 // because one could access the prototype property
213 // when export isn't set yet
214 canMangle: !(name in EMPTY_OBJECT) && false
215 }
216 ],
217 dependencies: undefined
218 };
219 }
220 const from = moduleGraph.getConnection(this);
221 if (!from) return;
222 if (esmUnwrap) {
223 // Full re-export `module.exports = require("./esm")` of a module
224 // with a `"module.exports"` named export: the wrapping module's
225 // `module.exports` becomes the unwrapped value, whose own
226 // properties webpack cannot enumerate statically.
227 return {
228 exports: true,
229 canMangle: false,
230 dependencies: [from.module]
231 };
232 }
233 const reexportInfo = this.getStarReexports(
234 moduleGraph,
235 undefined,
236 from.module
237 );
238 const ids = this.getIds(moduleGraph);
239 if (reexportInfo) {
240 return {
241 exports: Array.from(
242 /** @type {Exports} */
243 (reexportInfo.exports),
244 (name) => ({
245 name,
246 from,
247 export: [...ids, name],
248 canMangle: !(name in EMPTY_OBJECT) && false
249 })
250 ),
251 // TODO handle deep reexports
252 dependencies: [from.module]
253 };
254 }
255 return {
256 exports: true,
257 from: ids.length === 0 ? from : undefined,
258 canMangle: false,
259 dependencies: [from.module]
260 };
261 }
262
263 /**
264 * Gets star reexports.
265 * @param {ModuleGraph} moduleGraph the module graph
266 * @param {RuntimeSpec} runtime the runtime
267 * @param {Module} importedModule the imported module (optional)
268 * @returns {{ exports?: Exports, checked?: Checked } | undefined} information
269 */
270 getStarReexports(
271 moduleGraph,
272 runtime,
273 importedModule = /** @type {Module} */ (moduleGraph.getModule(this))
274 ) {
275 /** @type {ExportsInfo | undefined} */
276 let importedExportsInfo = moduleGraph.getExportsInfo(importedModule);
277 const ids = this.getIds(moduleGraph);
278 if (ids.length > 0) {
279 importedExportsInfo = importedExportsInfo.getNestedExportsInfo(ids);
280 }
281 /** @type {ExportsInfo | undefined} */
282 let exportsInfo = moduleGraph.getExportsInfo(
283 /** @type {Module} */ (moduleGraph.getParentModule(this))
284 );
285 if (this.names.length > 0) {
286 exportsInfo = exportsInfo.getNestedExportsInfo(this.names);
287 }
288
289 const noExtraExports =
290 importedExportsInfo &&
291 importedExportsInfo.otherExportsInfo.provided === false;
292 const noExtraImports =
293 exportsInfo &&
294 exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused;
295
296 if (!noExtraExports && !noExtraImports) {
297 return;
298 }
299
300 const isNamespaceImport =
301 importedModule.getExportsType(moduleGraph, false) === "namespace";
302
303 /** @type {Exports} */
304 const exports = new Set();
305 /** @type {Checked} */
306 const checked = new Set();
307
308 if (noExtraImports) {
309 for (const exportInfo of /** @type {ExportsInfo} */ (exportsInfo)
310 .orderedExports) {
311 const name = exportInfo.name;
312 if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
313 if (name === "__esModule" && isNamespaceImport) {
314 exports.add(name);
315 } else if (importedExportsInfo) {
316 const importedExportInfo =
317 importedExportsInfo.getReadOnlyExportInfo(name);
318 if (importedExportInfo.provided === false) continue;
319 exports.add(name);
320 if (importedExportInfo.provided === true) continue;
321 checked.add(name);
322 } else {
323 exports.add(name);
324 checked.add(name);
325 }
326 }
327 } else if (noExtraExports) {
328 for (const importedExportInfo of /** @type {ExportsInfo} */ (
329 importedExportsInfo
330 ).orderedExports) {
331 const name = importedExportInfo.name;
332 if (importedExportInfo.provided === false) continue;
333 if (exportsInfo) {
334 const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
335 if (exportInfo.getUsed(runtime) === UsageState.Unused) continue;
336 }
337 exports.add(name);
338 if (importedExportInfo.provided === true) continue;
339 checked.add(name);
340 }
341 if (isNamespaceImport) {
342 exports.add("__esModule");
343 checked.delete("__esModule");
344 }
345 }
346
347 return { exports, checked };
348 }
349
350 /**
351 * Serializes this instance into the provided serializer context.
352 * @param {ObjectSerializerContext} context context
353 */
354 serialize(context) {
355 const { write } = context;
356 write(this.asiSafe);
357 write(this.range);
358 write(this.valueRange);
359 write(this.base);
360 write(this.names);
361 write(this.ids);
362 write(this.resultUsed);
363 super.serialize(context);
364 }
365
366 /**
367 * Restores this instance from the provided deserializer context.
368 * @param {ObjectDeserializerContext} context context
369 */
370 deserialize(context) {
371 const { read } = context;
372 this.asiSafe = read();
373 this.range = read();
374 this.valueRange = read();
375 this.base = read();
376 this.names = read();
377 this.ids = read();
378 this.resultUsed = read();
379 super.deserialize(context);
380 }
381}
382
383makeSerializable(
384 CommonJsExportRequireDependency,
385 "webpack/lib/dependencies/CommonJsExportRequireDependency"
386);
387
388CommonJsExportRequireDependency.Template = class CommonJsExportRequireDependencyTemplate extends (
389 ModuleDependency.Template
390) {
391 /**
392 * Applies the plugin by registering its hooks on the compiler.
393 * @param {Dependency} dependency the dependency for which the template should be applied
394 * @param {ReplaceSource} source the current replace source which can be modified
395 * @param {DependencyTemplateContext} templateContext the context object
396 * @returns {void}
397 */
398 apply(
399 dependency,
400 source,
401 {
402 module,
403 runtimeTemplate,
404 chunkGraph,
405 moduleGraph,
406 runtimeRequirements,
407 runtime
408 }
409 ) {
410 const dep = /** @type {CommonJsExportRequireDependency} */ (dependency);
411 const used = moduleGraph
412 .getExportsInfo(module)
413 .getUsedName(dep.names, runtime);
414
415 const [type, base] = handleDependencyBase(
416 dep.base,
417 module,
418 runtimeRequirements
419 );
420
421 const importedModule = moduleGraph.getModule(dep);
422 let requireExpr = runtimeTemplate.moduleExports({
423 module: importedModule,
424 chunkGraph,
425 request: dep.request,
426 weak: dep.weak,
427 runtimeRequirements
428 });
429 if (importedModule) {
430 const ids = dep.getIds(moduleGraph);
431 const esmRequireAccess = getRequireEsmModuleExportsAccess(
432 importedModule,
433 moduleGraph,
434 runtime
435 );
436 if (esmRequireAccess !== null) {
437 requireExpr += `${esmRequireAccess}${propertyAccess(ids)}`;
438 } else {
439 const usedImported = moduleGraph
440 .getExportsInfo(importedModule)
441 .getUsedName(ids, runtime);
442 if (usedImported) {
443 const comment = equals(usedImported, ids)
444 ? ""
445 : `${Template.toNormalComment(propertyAccess(ids))} `;
446 requireExpr += `${comment}${propertyAccess(usedImported)}`;
447 }
448 }
449 }
450
451 switch (type) {
452 case "expression":
453 source.replace(
454 dep.range[0],
455 dep.range[1] - 1,
456 used
457 ? `${base}${propertyAccess(used)} = ${requireExpr}`
458 : `/* unused reexport */ ${requireExpr}`
459 );
460 return;
461 case "Object.defineProperty":
462 throw new Error("TODO");
463 default:
464 throw new Error("Unexpected type");
465 }
466 }
467};
468
469module.exports = CommonJsExportRequireDependency;
470module.exports.idsSymbol = idsSymbol;
Note: See TracBrowser for help on using the repository browser.