src/vs/platform/actions/common/menuService.ts/Menu/constructor
class Menu:	constructor(
		private readonly _id: MenuId,
		private readonly _fireEventsForSubmenuChanges: boolean,
		@ICommandService private readonly _commandService: ICommandService,
		@IContextKeyService private readonly _contextKeyService: IContextKeyService,
		@IMenuService private readonly _menuService: IMenuService
	) {
		this._build();

		// Rebuild this menu whenever the menu registry reports an event for this MenuId.
		// This usually happen while code and extensions are loaded and affects the over
		// structure of the menu
		const rebuildMenuSoon = new RunOnceScheduler(() => {
			this._build();
			this._onDidChange.fire(this);
		}, 50);
		this._disposables.add(rebuildMenuSoon);
		this._disposables.add(MenuRegistry.onDidChangeMenu(e => {
			if (e.has(_id)) {
				rebuildMenuSoon.schedule();
			}
		}));

		// When context keys change we need to check if the menu also has changed. However,
		// we only do that when someone listens on this menu because (1) context key events are
		// firing often and (2) menu are often leaked
		const contextKeyListener = this._disposables.add(new DisposableStore());
		const startContextKeyListener = () => {
			const fireChangeSoon = new RunOnceScheduler(() => this._onDidChange.fire(this), 50);
			contextKeyListener.add(fireChangeSoon);
			contextKeyListener.add(_contextKeyService.onDidChangeContext(e => {
				if (e.affectsSome(this._contextKeys)) {
					fireChangeSoon.schedule();
				}
			}));
		};

		this._onDidChange = new Emitter({
			// start/stop context key listener
			onFirstListenerAdd: startContextKeyListener,
			onLastListenerRemove: contextKeyListener.clear.bind(contextKeyListener)
		});
		this.onDidChange = this._onDidChange.event;

	}