getMode = (moduleGraph, dep, runtimeKey) => {
	const importedModule = moduleGraph.getModule(dep);

	if (!importedModule) {
		const mode = new ExportMode("missing");

		mode.userRequest = dep.userRequest;

		return mode;
	}

	const name = dep.name;
	const runtime = keyToRuntime(runtimeKey);
	const parentModule = /** @type {Module} */ (moduleGraph.getParentModule(dep));
	const exportsInfo = moduleGraph.getExportsInfo(parentModule);

	if (
		name
			? exportsInfo.getUsed(name, runtime) === UsageState.Unused
			: exportsInfo.isUsed(runtime) === false
	) {
		const mode = new ExportMode("unused");

		mode.name = name || "*";

		return mode;
	}

	const importedExportsType = importedModule.getExportsType(
		moduleGraph,
		/** @type {BuildMeta} */
		(parentModule.buildMeta).strictHarmonyModule
	);

	const ids = dep.getIds(moduleGraph);

	// Special handling for reexporting the default export
	// from non-namespace modules
	if (name && ids.length > 0 && ids[0] === "default") {
		switch (importedExportsType) {
			case "dynamic": {
				const mode = new ExportMode("reexport-dynamic-default");

				mode.name = name;

				return mode;
			}
			case "default-only":
			case "default-with-named": {
				const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
				const mode = new ExportMode("reexport-named-default");

				mode.name = name;
				mode.partialNamespaceExportInfo = exportInfo;

				return mode;
			}
		}
	}

	// reexporting with a fixed name
	if (name) {
		let mode;
		const exportInfo = exportsInfo.getReadOnlyExportInfo(name);

		if (ids.length > 0) {
			// export { name as name }
			switch (importedExportsType) {
				case "default-only":
					mode = new ExportMode("reexport-undefined");
					mode.name = name;
					break;
				default:
					mode = new ExportMode("normal-reexport");
					mode.items = [
						new NormalReexportItem(name, ids, exportInfo, false, false)
					];
					break;
			}
		} else {
			// export * as name
			switch (importedExportsType) {
				case "default-only":
					mode = new ExportMode("reexport-fake-namespace-object");
					mode.name = name;
					mode.partialNamespaceExportInfo = exportInfo;
					mode.fakeType = 0;
					break;
				case "default-with-named":
					mode = new ExportMode("reexport-fake-namespace-object");
					mode.name = name;
					mode.partialNamespaceExportInfo = exportInfo;
					mode.fakeType = 2;
					break;
				case "dynamic":
				default:
					mode = new ExportMode("reexport-namespace-object");
					mode.name = name;
					mode.partialNamespaceExportInfo = exportInfo;
			}
		}

		return mode;
	}

	// Star reexporting
	const { ignoredExports, exports, checked, hidden } = dep.getStarReexports(
		moduleGraph,
		runtime,
		exportsInfo,
		importedModule
	);
	if (!exports) {
		// We have too few info about the modules
		// Delegate the logic to the runtime code

		const mode = new ExportMode("dynamic-reexport");
		mode.ignored = ignoredExports;
		mode.hidden = hidden;

		return mode;
	}

	if (exports.size === 0) {
		const mode = new ExportMode("empty-star");
		mode.hidden = hidden;

		return mode;
	}

	const mode = new ExportMode("normal-reexport");

	mode.items = Array.from(
		exports,
		exportName =>
			new NormalReexportItem(
				exportName,
				[exportName],
				exportsInfo.getReadOnlyExportInfo(exportName),
				/** @type {Set<string>} */
				(checked).has(exportName),
				false
			)
	);
	if (hidden !== undefined) {
		for (const exportName of hidden) {
			mode.items.push(
				new NormalReexportItem(
					exportName,
					[exportName],
					exportsInfo.getReadOnlyExportInfo(exportName),
					false,
					true
				)
			);
		}
	}

	return mode;
}
@param {ModuleGraph} moduleGraph the module graph
@param {HarmonyExportImportedSpecifierDependency} dep the dependency
@param {string} runtimeKey the runtime key
@returns {ExportMode} the export mode