function hotkeysMapBuild( map, userData ) {
	// always iterate the hotkeysConfig, even if building the user data, to make sure that
	// invalid user data does not pollute the hotkey map
	for ( const [ namespace, { actions } ] of Object.entries( hotkeysConfig ) ) {
		for ( const [ action, hotkeys ] of Object.entries( actions ) ) {
			const id = `${namespace}.${action}`;

			// initialize with default and empty user data
			// also resolve hotkey aliases
			const resolvedHotkeys = resolveHotkeyAlias( hotkeys );
			if ( !resolvedHotkeys ) { continue; }
			const [ defaultHotkeys, alias ] = resolvedHotkeys;
			const item = new HotkeysMapItem( defaultHotkeys, alias );
			map.set( id, item );

			// update with user data
			if (
				   userData
				&& hasOwnProperty.call( userData, namespace )
				&& hasOwnProperty.call( userData[ namespace ], action )
			) {
				const { primary, secondary } = userData[ namespace ][ action ];
				item.update([ primary, secondary ]);
			}
		}
	}

	// update user data of aliased hotkeys after everything has been resolved
	if ( userData ) {
		for ( const item of map.values() ) {
			if ( !item.alias ) { continue; }
			item.update( map.get( item.alias ) );
		}
	}
}
@params {HotkeysMap} map
@params {Object<string,Object<string,HotkeyUser[]>>?} userData