processModule = (module, runtime, forceSideEffects) => {
						/** @type {Map<Module, (string[] | ReferencedExport)[] | Map<string, string[] | ReferencedExport>>} */
						const map = new Map();

						/** @type {ArrayQueue<DependenciesBlock>} */
						const queue = new ArrayQueue();
						queue.enqueue(module);
						for (;;) {
							const block = queue.dequeue();
							if (block === undefined) break;
							for (const b of block.blocks) {
								if (
									!this.global &&
									b.groupOptions &&
									b.groupOptions.entryOptions
								) {
									processModule(
										b,
										b.groupOptions.entryOptions.runtime || undefined,
										true
									);
								} else {
									queue.enqueue(b);
								}
							}
							for (const dep of block.dependencies) {
								const connection = moduleGraph.getConnection(dep);
								if (!connection || !connection.module) {
									continue;
								}
								const activeState = connection.getActiveState(runtime);
								if (activeState === false) continue;
								const { module } = connection;
								if (activeState === ModuleGraphConnection.TRANSITIVE_ONLY) {
									processModule(module, runtime, false);
									continue;
								}
								const oldReferencedExports = map.get(module);
								if (oldReferencedExports === EXPORTS_OBJECT_REFERENCED) {
									continue;
								}
								const referencedExports =
									compilation.getDependencyReferencedExports(dep, runtime);
								if (
									oldReferencedExports === undefined ||
									oldReferencedExports === NO_EXPORTS_REFERENCED ||
									referencedExports === EXPORTS_OBJECT_REFERENCED
								) {
									map.set(module, referencedExports);
								} else if (
									oldReferencedExports !== undefined &&
									referencedExports === NO_EXPORTS_REFERENCED
								) {
									continue;
								} else {
									let exportsMap;
									if (Array.isArray(oldReferencedExports)) {
										exportsMap = new Map();
										for (const item of oldReferencedExports) {
											if (Array.isArray(item)) {
												exportsMap.set(item.join("\n"), item);
											} else {
												exportsMap.set(item.name.join("\n"), item);
											}
										}
										map.set(module, exportsMap);
									} else {
										exportsMap = oldReferencedExports;
									}
									for (const item of referencedExports) {
										if (Array.isArray(item)) {
											const key = item.join("\n");
											const oldItem = exportsMap.get(key);
											if (oldItem === undefined) {
												exportsMap.set(key, item);
											}
											// if oldItem is already an array we have to do nothing
											// if oldItem is an ReferencedExport object, we don't have to do anything
											// as canMangle defaults to true for arrays
										} else {
											const key = item.name.join("\n");
											const oldItem = exportsMap.get(key);
											if (oldItem === undefined || Array.isArray(oldItem)) {
												exportsMap.set(key, item);
											} else {
												exportsMap.set(key, {
													name: item.name,
													canMangle: item.canMangle && oldItem.canMangle
												});
											}
										}
									}
								}
							}
						}

						for (const [module, referencedExports] of map) {
							if (Array.isArray(referencedExports)) {
								processReferencedModule(
									module,
									referencedExports,
									runtime,
									forceSideEffects
								);
							} else {
								processReferencedModule(
									module,
									Array.from(referencedExports.values()),
									runtime,
									forceSideEffects
								);
							}
						}
					}
@param {DependenciesBlock} module the module
@param {RuntimeSpec} runtime part of which runtime
@param {boolean} forceSideEffects always apply side effects
@returns {void}