Preserve custom properties passed to MenuItem constructor #7498

Merged
merged 7 commits into from Oct 11, 2016

Projects

None yet

4 participants

@zeke
Member
zeke commented Oct 5, 2016

Fixes #7414

zeke added some commits Oct 5, 2016
@zeke zeke preserve custom properties passed to MenuItem constructor
16b3962
@zeke zeke remove unneeded new keyword
fdf3f6c
@zeke
Member
zeke commented Oct 5, 2016

Props to @jonathanGB for the code in this fix. #7414 (comment)

@jonathanGB

Glad it worked! :)

lib/browser/api/menu-item.js
- this.checked = options.checked
-
- this.submenu = options.submenu
+ Object.assign(this, options)
@MarshallOfSound
MarshallOfSound Oct 5, 2016 Member

This is scary for a few reasons. Mostly because what happens if the user does something silly like pass in overrideProperty as a property on the options object.

This would causes the overrideProperty method to be overriden (oh how ironic). Can we blacklist that method from being overriden 👍

@jonathanGB
jonathanGB Oct 6, 2016

@zeke What I propose is adding an "undesired" array of properties

var undesiredProperties = ['overrideProperty', 'overrideReadOnlyProperty' /* add more if necessary*/]

and just before calling .assign, delete the properties from options which are in that array, aka

undesiredProperties.forEach((undesiredProperty) => delete options[undesiredProperty])

Otherwise, an alternative would to either make methods like overrideProperty unwritable, or possibly put these customProperties inside another property like "custom" so passing properties like overrideProperty will not impact the existing method.

this.custom = Object.assign({}, getCustomProps(options))

In all cases, it'd be important to stay consistent between the handling of customProperties when using buildFromTemplate or through append

@MarshallOfSound
MarshallOfSound Oct 6, 2016 Member

and just before calling .assign, delete the properties from options which are in that array, aka

You don't want to mutate an object the user provided, it will most likely annoy them 😆

Just set options to Object.assign({}, options) before doing this

@jonathanGB
jonathanGB Oct 6, 2016

very good point haha. I derped.

@zeke
zeke Oct 6, 2016 Member

Good catch. Updated.

@zeke zeke sanitize MenuItem options
b7e078e
@kevinsawicki
Contributor

@zeke can this be removed now that we are doing this in the MenuItem constructor?

https://github.com/electron/electron/blob/2efb7a12cb24bb447bfa823f34eb3eb372cab630/lib/browser/api/menu.js#L298-L303

@zeke zeke remove duplicated prop copying
2cd10d3
lib/browser/api/menu-item.js
+ // Clone and sanitize the provided options
+ options = Object.assign({}, options)
+ delete options.overrideProperty
+ delete options.overrideReadOnlyProperty
@kevinsawicki
kevinsawicki Oct 10, 2016 Contributor

I don't think we want the options object to override any already defined instance properties or methods here, so maybe the hasOwnProperty guard that was previously used in Menu.buildFromTemplate is a better approach.

@zeke
zeke Oct 10, 2016 Member

I tried that technique, but because hasOwnProperty only checks the object itself, and doesn't walk up the prototype chain, it was still possible to override methods like overrideProperty. I just updated it to use !(key in this) as a check instead.

@zeke zeke inherit user-specific MenuItem properties more safely
b575055
spec/api-menu-spec.js
+ assert.equal(menu.items[0].customProp, 'foo')
+ assert.equal(menu.items[0].submenu.items[0].label, 'item 1')
+ assert.equal(menu.items[0].submenu.items[0].customProp, 'bar')
+ assert.notEqual(typeof menu.items[0].submenu.items[0].overrideProperty, 'string')
@kevinsawicki
kevinsawicki Oct 10, 2016 Contributor

Can we assert that it is a function instead? That way if we ever rename that function the spec will fail so we know to update it.

@zeke
zeke Oct 10, 2016 Member

I wrote it this way to avoid coupling the test to the underlying implementation, but I see your point. 👍

zeke added some commits Oct 10, 2016
@zeke zeke test that overrideProperty is not overwritten
bcce7af
@zeke zeke remove unused var
8aaf029
@kevinsawicki kevinsawicki self-assigned this Oct 11, 2016
@kevinsawicki
Contributor

Looks good to me, merge when 🚢

@zeke zeke merged commit d4a8a64 into master Oct 11, 2016

9 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
electron-linux-arm Build #4382775 succeeded in 66s
Details
electron-linux-ia32 Build #4382776 succeeded in 63s
Details
electron-linux-x64 Build #4382777 succeeded in 114s
Details
electron-mas-x64 Build #2590 succeeded in 9 min 8 sec
Details
electron-osx-x64 Build #2596 succeeded in 9 min 24 sec
Details
electron-win-ia32 Build #1685 succeeded in 8 min 1 sec
Details
electron-win-x64 Build #1660 succeeded in 8 min 0 sec
Details
@zeke zeke deleted the custom-props-in-menu-item-constructor branch Oct 11, 2016
@aluxian-huginn aluxian-huginn referenced this pull request in Aluxian/Messenger-for-Desktop Oct 20, 2016
Closed

Update dependency: electron v1.4.4 #885

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment