connectChunkGroups = (
	compilation,
	blocksWithNestedBlocks,
	blockConnections,
	maskByChunk
) => {
	const { chunkGraph } = compilation;

	/**
	 * Helper function to check if all modules of a chunk are available
	 * @param {ChunkGroup} chunkGroup the chunkGroup to scan
	 * @param {bigint} availableModules the comparator set
	 * @returns {boolean} return true if all modules of a chunk are available
	 */
	const areModulesAvailable = (chunkGroup, availableModules) => {
		for (const chunk of chunkGroup.chunks) {
			const chunkMask = /** @type {bigint} */ (maskByChunk.get(chunk));
			if ((chunkMask & availableModules) !== chunkMask) return false;
		}
		return true;
	};

	// For each edge in the basic chunk graph
	for (const [block, connections] of blockConnections) {
		// 1. Check if connection is needed
		// When none of the dependencies need to be connected
		// we can skip all of them
		// It's not possible to filter each item so it doesn't create inconsistent
		// connections and modules can only create one version
		// TODO maybe decide this per runtime
		if (
			// TODO is this needed?
			!blocksWithNestedBlocks.has(block) &&
			connections.every(({ chunkGroup, originChunkGroupInfo }) =>
				areModulesAvailable(
					chunkGroup,
					/** @type {bigint} */ (originChunkGroupInfo.resultingAvailableModules)
				)
			)
		) {
			continue;
		}

		// 2. Foreach edge
		for (let i = 0; i < connections.length; i++) {
			const { chunkGroup, originChunkGroupInfo } = connections[i];

			// 3. Connect block with chunk
			chunkGraph.connectBlockAndChunkGroup(block, chunkGroup);

			// 4. Connect chunk with parent
			connectChunkGroupParentAndChild(
				originChunkGroupInfo.chunkGroup,
				chunkGroup
			);
		}
	}
}
@param {Compilation} compilation the compilation
@param {BlocksWithNestedBlocks} blocksWithNestedBlocks flag for blocks that have nested blocks
@param {BlockConnections} blockConnections connection for blocks
@param {MaskByChunk} maskByChunk mapping from chunk to module mask