Fix the cyclic reference in menu delegate (#11967)

* Fix the cyclic reference in menu delegate

* Fix menu tests due to delegate change
This commit is contained in:
Cheng Zhao 2018-02-21 01:11:35 +09:00 committed by Charles Kerr
parent e1b81b8a62
commit dc62e51ba4
6 changed files with 61 additions and 43 deletions

View file

@ -11,36 +11,39 @@ let groupIdIndex = 0
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
// Menu Delegate.
// This object should hold no reference to |Menu| to avoid cyclic reference.
const delegate = {
isCommandIdChecked: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].checked : undefined,
isCommandIdEnabled: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].enabled : undefined,
isCommandIdVisible: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
const command = menu.commandsMap[id]
if (!command) return
if (command.accelerator) return command.accelerator
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
},
executeCommand: (menu, event, id) => {
const command = menu.commandsMap[id]
if (!command) return
command.click(event, BrowserWindow.getFocusedWindow(), webContents.getFocusedWebContents())
},
menuWillShow: (menu) => {
// Ensure radio groups have at least one menu item seleted
for (const id in menu.groupsMap) {
const found = menu.groupsMap[id].find(item => item.checked) || null
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true)
}
}
}
/* Instance Methods */
Menu.prototype._init = function () {
this.commandsMap = {}
this.groupsMap = {}
this.items = []
this.delegate = {
isCommandIdChecked: id => this.commandsMap[id] ? this.commandsMap[id].checked : undefined,
isCommandIdEnabled: id => this.commandsMap[id] ? this.commandsMap[id].enabled : undefined,
isCommandIdVisible: id => this.commandsMap[id] ? this.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (id, useDefaultAccelerator) => {
const command = this.commandsMap[id]
if (!command) return
if (command.accelerator) return command.accelerator
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
},
getIconForCommandId: id => this.commandsMap[id] ? this.commandsMap[id].icon : undefined,
executeCommand: (event, id) => {
const command = this.commandsMap[id]
if (!command) return
command.click(event, BrowserWindow.getFocusedWindow(), webContents.getFocusedWebContents())
},
menuWillShow: () => {
// Ensure radio groups have at least one menu item seleted
for (const id in this.groupsMap) {
const found = this.groupsMap[id].find(item => item.checked) || null
if (!found) v8Util.setHiddenValue(this.groupsMap[id][0], 'checked', true)
}
}
}
this.delegate = delegate
}
Menu.prototype.popup = function (window, x, y, positioningItem) {
@ -150,7 +153,7 @@ Menu.prototype.insert = function (pos, item) {
}
Menu.prototype._callMenuWillShow = function () {
if (this.delegate) this.delegate.menuWillShow()
if (this.delegate) this.delegate.menuWillShow(this)
this.items.forEach(item => {
if (item.submenu) item.submenu._callMenuWillShow()
})