mangleExportsInfo = (deterministic, exportsInfo, isNamespace) => {
	if (!canMangle(exportsInfo)) return;
	const usedNames = new Set();
	/** @type {ExportInfo[]} */
	const mangleableExports = [];

	// Avoid to renamed exports that are not provided when
	// 1. it's not a namespace export: non-provided exports can be found in prototype chain
	// 2. there are other provided exports and deterministic mode is chosen:
	//    non-provided exports would break the determinism
	let avoidMangleNonProvided = !isNamespace;
	if (!avoidMangleNonProvided && deterministic) {
		for (const exportInfo of exportsInfo.ownedExports) {
			if (exportInfo.provided !== false) {
				avoidMangleNonProvided = true;
				break;
			}
		}
	}
	for (const exportInfo of exportsInfo.ownedExports) {
		const name = exportInfo.name;
		if (!exportInfo.hasUsedName()) {
			if (
				// Can the export be mangled?
				exportInfo.canMangle !== true ||
				// Never rename 1 char exports
				(name.length === 1 && /^[a-zA-Z0-9_$]/.test(name)) ||
				// Don't rename 2 char exports in deterministic mode
				(deterministic &&
					name.length === 2 &&
					/^[a-zA-Z_$][a-zA-Z0-9_$]|^[1-9][0-9]/.test(name)) ||
				// Don't rename exports that are not provided
				(avoidMangleNonProvided && exportInfo.provided !== true)
			) {
				exportInfo.setUsedName(name);
				usedNames.add(name);
			} else {
				mangleableExports.push(exportInfo);
			}
		}
		if (exportInfo.exportsInfoOwned) {
			const used = exportInfo.getUsed(undefined);
			if (
				used === UsageState.OnlyPropertiesUsed ||
				used === UsageState.Unused
			) {
				mangleExportsInfo(
					deterministic,
					/** @type {ExportsInfo} */ (exportInfo.exportsInfo),
					false
				);
			}
		}
	}
	if (deterministic) {
		assignDeterministicIds(
			mangleableExports,
			e => e.name,
			comparator,
			(e, id) => {
				const name = numberToIdentifier(id);
				const size = usedNames.size;
				usedNames.add(name);
				if (size === usedNames.size) return false;
				e.setUsedName(name);
				return true;
			},
			[
				NUMBER_OF_IDENTIFIER_START_CHARS,
				NUMBER_OF_IDENTIFIER_START_CHARS *
					NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
			],
			NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS,
			usedNames.size
		);
	} else {
		const usedExports = [];
		const unusedExports = [];
		for (const exportInfo of mangleableExports) {
			if (exportInfo.getUsed(undefined) === UsageState.Unused) {
				unusedExports.push(exportInfo);
			} else {
				usedExports.push(exportInfo);
			}
		}
		usedExports.sort(comparator);
		unusedExports.sort(comparator);
		let i = 0;
		for (const list of [usedExports, unusedExports]) {
			for (const exportInfo of list) {
				let name;
				do {
					name = numberToIdentifier(i++);
				} while (usedNames.has(name));
				exportInfo.setUsedName(name);
			}
		}
	}
}
@param {boolean} deterministic use deterministic names
@param {ExportsInfo} exportsInfo exports info
@param {boolean | undefined} isNamespace is namespace object
@returns {void}