* [pve-devel] [PATCH manager/widget-toolkit 0/3] ui: avoid UI bugs due to shared extra request params @ 2024-04-03 9:10 Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 1/3] ui: pool members: avoid setting request parameter for all edit windows Friedrich Weber ` (2 more replies) 0 siblings, 3 replies; 12+ messages in thread From: Friedrich Weber @ 2024-04-03 9:10 UTC (permalink / raw) To: pve-devel Currently, `Proxmox.window.Edit` initializes `extraRequestParams` to an object that, if not overwritten, is shared between all instances of subclasses. This bears the danger of modifying the shared object in a subclass instead of overwriting it, which affects all edit windows of the current session and can cause hard-to-catch UI bugs [1] - Patch 1/3 fixes such an UI bug. - Patch 2/3 (optional) fixes other occurrences of the pattern from 1/3, which are not buggy at the moment, but may become in the future. - Patch 3/3 (optional) changes `Proxmox.window.Edit` to make this class of bugs less likely in the future. Changes from v1: - Patch 1/3: avoid unnecessary quotes - Patch 2/3 + 3/3 are new [1] https://lists.proxmox.com/pipermail/pve-devel/2024-March/062179.html manager: Friedrich Weber (2): ui: pool members: avoid setting request parameter for all edit windows ui: pool members: avoid sharing object for extra request parameters www/manager6/grid/PoolMembers.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) widget-toolkit: Friedrich Weber (1): window: edit: avoid shared object for extra request params src/window/Edit.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) Summary over all repositories: 2 files changed, 10 insertions(+), 0 deletions(-) -- Generated by git-murpp 0.5.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [pve-devel] [PATCH manager 1/3] ui: pool members: avoid setting request parameter for all edit windows 2024-04-03 9:10 [pve-devel] [PATCH manager/widget-toolkit 0/3] ui: avoid UI bugs due to shared extra request params Friedrich Weber @ 2024-04-03 9:10 ` Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 2/3] ui: pool members: avoid sharing object for extra request parameters Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params Friedrich Weber 2 siblings, 0 replies; 12+ messages in thread From: Friedrich Weber @ 2024-04-03 9:10 UTC (permalink / raw) To: pve-devel Currently, after adding a storage to a pool, opening any edit window will send a GET request with a superfluous `poolid` parameter and cause a parameter verification error in the GUI. This breaks all edit windows of the current session. A workaround is to reload the current browser session. This happens because the `PVE.pool.AddStorage` component inadvertently adds `poolid` to an `extraRequestParams` object that is shared by all instances of `Proxmox.window.Edit`, affecting all edit windows in the current session. Fix this by instead creating a new object that is local to the component. Fixes: cd731902b7a724b1ab747276f9c6343734f1d8cb Signed-off-by: Friedrich Weber <f.weber@proxmox.com> --- Notes: changes since v1: - remove unnecessary quotes (thx Stefan) www/manager6/grid/PoolMembers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/manager6/grid/PoolMembers.js b/www/manager6/grid/PoolMembers.js index 75f20cab..af6af1bd 100644 --- a/www/manager6/grid/PoolMembers.js +++ b/www/manager6/grid/PoolMembers.js @@ -123,7 +123,7 @@ Ext.define('PVE.pool.AddStorage', { me.isAdd = true; me.url = "/pools/"; me.method = 'PUT'; - me.extraRequestParams.poolid = me.pool; + me.extraRequestParams = { poolid: me.pool }; Ext.apply(me, { subject: gettext('Storage'), -- 2.39.2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [pve-devel] [PATCH manager 2/3] ui: pool members: avoid sharing object for extra request parameters 2024-04-03 9:10 [pve-devel] [PATCH manager/widget-toolkit 0/3] ui: avoid UI bugs due to shared extra request params Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 1/3] ui: pool members: avoid setting request parameter for all edit windows Friedrich Weber @ 2024-04-03 9:10 ` Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params Friedrich Weber 2 siblings, 0 replies; 12+ messages in thread From: Friedrich Weber @ 2024-04-03 9:10 UTC (permalink / raw) To: pve-devel Currently, all instances of `PVE.pool.AddVM` in a session share the same `extraRequestParams` object. Right now, this does not cause any problems because only one window can be active at a time, and all relevant keys are always overwritten. Still, in order to avoid hard-to-catch bugs due to the shared object in the future, create a new `extraRequestParams` object for each instance of `PVE.pool.AddVM`. Signed-off-by: Friedrich Weber <f.weber@proxmox.com> --- Notes: new in v2 www/manager6/grid/PoolMembers.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/www/manager6/grid/PoolMembers.js b/www/manager6/grid/PoolMembers.js index af6af1bd..4ffcde7f 100644 --- a/www/manager6/grid/PoolMembers.js +++ b/www/manager6/grid/PoolMembers.js @@ -6,10 +6,6 @@ Ext.define('PVE.pool.AddVM', { isAdd: true, isCreate: true, - extraRequestParams: { - 'allow-move': 1, - }, - initComponent: function() { var me = this; @@ -19,7 +15,10 @@ Ext.define('PVE.pool.AddVM', { me.url = '/pools/'; me.method = 'PUT'; - me.extraRequestParams.poolid = me.pool; + me.extraRequestParams = { + 'allow-move': 1, + poolid: me.pool, + }; var vmsField = Ext.create('Ext.form.field.Text', { name: 'vms', -- 2.39.2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-03 9:10 [pve-devel] [PATCH manager/widget-toolkit 0/3] ui: avoid UI bugs due to shared extra request params Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 1/3] ui: pool members: avoid setting request parameter for all edit windows Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 2/3] ui: pool members: avoid sharing object for extra request parameters Friedrich Weber @ 2024-04-03 9:10 ` Friedrich Weber 2024-04-04 8:22 ` Stefan Sterz 2 siblings, 1 reply; 12+ messages in thread From: Friedrich Weber @ 2024-04-03 9:10 UTC (permalink / raw) To: pve-devel Currently, `Proxmox.window.Edit` initializes `extraRequestParams` to an object that, if not overwritten, is shared between all instances of subclasses. This bears the danger of modifying the shared object in a subclass instead of overwriting it, which affects all edit windows of the current session and can cause hard-to-catch UI bugs [1]. To avoid such bugs in the future, initialize `extraRequestParams` to `undefined` instead, which forces subclasses to initialize their own objects. Note that bugs of the same kind can still happen if a subclass initializes `extraRequestParams` to an empty shared object and inadvertently modifies it, but at least they will be limited to that particular subclass. [1] https://lists.proxmox.com/pipermail/pve-devel/2024-March/062179.html Signed-off-by: Friedrich Weber <f.weber@proxmox.com> --- Notes: With patch 2/3 applied, I think all occurrences of `extraRequestParams` in PVE/PBS create their own object (PMG does not seem to use `extraRequestParams`), so this patch should not break anything, and if it does, it should be quite noticeable. new in v2 src/window/Edit.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/window/Edit.js b/src/window/Edit.js index d4a2b551..27cd8d01 100644 --- a/src/window/Edit.js +++ b/src/window/Edit.js @@ -9,7 +9,7 @@ Ext.define('Proxmox.window.Edit', { // to submit extra params on load and submit, useful, e.g., if not all ID // parameters are included in the URL - extraRequestParams: {}, + extraRequestParams: undefined, resizable: false, @@ -80,7 +80,9 @@ Ext.define('Proxmox.window.Edit', { let me = this; let values = {}; - Ext.apply(values, me.extraRequestParams); + if (me.extraRequestParams) { + Ext.apply(values, me.extraRequestParams); + } let form = me.formPanel.getForm(); @@ -209,7 +211,7 @@ Ext.define('Proxmox.window.Edit', { waitMsgTarget: me, }, options); - if (Object.keys(me.extraRequestParams).length > 0) { + if (me.extraRequestParams && Object.keys(me.extraRequestParams).length > 0) { let params = newopts.params || {}; Ext.applyIf(params, me.extraRequestParams); newopts.params = params; -- 2.39.2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-03 9:10 ` [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params Friedrich Weber @ 2024-04-04 8:22 ` Stefan Sterz 2024-04-04 9:01 ` Friedrich Weber 0 siblings, 1 reply; 12+ messages in thread From: Stefan Sterz @ 2024-04-04 8:22 UTC (permalink / raw) To: Proxmox VE development discussion On Wed Apr 3, 2024 at 11:10 AM CEST, Friedrich Weber wrote: > Currently, `Proxmox.window.Edit` initializes `extraRequestParams` to > an object that, if not overwritten, is shared between all instances of > subclasses. This bears the danger of modifying the shared object in a > subclass instead of overwriting it, which affects all edit windows of > the current session and can cause hard-to-catch UI bugs [1]. > > To avoid such bugs in the future, initialize `extraRequestParams` to > `undefined` instead, which forces subclasses to initialize their own > objects. > > Note that bugs of the same kind can still happen if a subclass > initializes `extraRequestParams` to an empty shared object and > inadvertently modifies it, but at least they will be limited to that > particular subclass. > > [1] https://lists.proxmox.com/pipermail/pve-devel/2024-March/062179.html > > Signed-off-by: Friedrich Weber <f.weber@proxmox.com> > --- > > Notes: > With patch 2/3 applied, I think all occurrences of > `extraRequestParams` in PVE/PBS create their own object (PMG does not > seem to use `extraRequestParams`), so this patch should not break > anything, and if it does, it should be quite noticeable. > > new in v2 > > src/window/Edit.js | 8 +++++--- > 1 file changed, 5 insertions(+), 3 deletions(-) > > diff --git a/src/window/Edit.js b/src/window/Edit.js > index d4a2b551..27cd8d01 100644 > --- a/src/window/Edit.js > +++ b/src/window/Edit.js > @@ -9,7 +9,7 @@ Ext.define('Proxmox.window.Edit', { > > // to submit extra params on load and submit, useful, e.g., if not all ID > // parameters are included in the URL > - extraRequestParams: {}, > + extraRequestParams: undefined, > > resizable: false, > > @@ -80,7 +80,9 @@ Ext.define('Proxmox.window.Edit', { > let me = this; > > let values = {}; > - Ext.apply(values, me.extraRequestParams); > + if (me.extraRequestParams) { > + Ext.apply(values, me.extraRequestParams); > + } > > let form = me.formPanel.getForm(); > > @@ -209,7 +211,7 @@ Ext.define('Proxmox.window.Edit', { > waitMsgTarget: me, > }, options); > > - if (Object.keys(me.extraRequestParams).length > 0) { > + if (me.extraRequestParams && Object.keys(me.extraRequestParams).length > 0) { > let params = newopts.params || {}; > Ext.applyIf(params, me.extraRequestParams); > newopts.params = params; i did a quick an dirty test and using a constructor like this seems to rule out this class of bug completelly: ```js constructor: function(conf) { let me = this; me.extraRequestParams = {}; me.initConfig(conf); me.callParent(); }, ``` basically it configures the edit window as usual, but overwrites the `extraRequestParams` object for each instance with a new empty object. so there are no more shared objects :) could you check whether that also fixes the other instances? [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 8:22 ` Stefan Sterz @ 2024-04-04 9:01 ` Friedrich Weber 2024-04-04 9:23 ` Stefan Sterz 0 siblings, 1 reply; 12+ messages in thread From: Friedrich Weber @ 2024-04-04 9:01 UTC (permalink / raw) To: Proxmox VE development discussion, Stefan Sterz On 04/04/2024 10:22, Stefan Sterz wrote: > On Wed Apr 3, 2024 at 11:10 AM CEST, Friedrich Weber wrote: >> Currently, `Proxmox.window.Edit` initializes `extraRequestParams` to >> an object that, if not overwritten, is shared between all instances of >> subclasses. This bears the danger of modifying the shared object in a >> subclass instead of overwriting it, which affects all edit windows of >> the current session and can cause hard-to-catch UI bugs [1]. >> >> To avoid such bugs in the future, initialize `extraRequestParams` to >> `undefined` instead, which forces subclasses to initialize their own >> objects. >> >> Note that bugs of the same kind can still happen if a subclass >> initializes `extraRequestParams` to an empty shared object and >> inadvertently modifies it, but at least they will be limited to that >> particular subclass. >> >> [1] https://lists.proxmox.com/pipermail/pve-devel/2024-March/062179.html >> >> Signed-off-by: Friedrich Weber <f.weber@proxmox.com> >> --- >> >> Notes: >> With patch 2/3 applied, I think all occurrences of >> `extraRequestParams` in PVE/PBS create their own object (PMG does not >> seem to use `extraRequestParams`), so this patch should not break >> anything, and if it does, it should be quite noticeable. >> >> new in v2 >> >> src/window/Edit.js | 8 +++++--- >> 1 file changed, 5 insertions(+), 3 deletions(-) >> >> diff --git a/src/window/Edit.js b/src/window/Edit.js >> index d4a2b551..27cd8d01 100644 >> --- a/src/window/Edit.js >> +++ b/src/window/Edit.js >> @@ -9,7 +9,7 @@ Ext.define('Proxmox.window.Edit', { >> >> // to submit extra params on load and submit, useful, e.g., if not all ID >> // parameters are included in the URL >> - extraRequestParams: {}, >> + extraRequestParams: undefined, >> >> resizable: false, >> >> @@ -80,7 +80,9 @@ Ext.define('Proxmox.window.Edit', { >> let me = this; >> >> let values = {}; >> - Ext.apply(values, me.extraRequestParams); >> + if (me.extraRequestParams) { >> + Ext.apply(values, me.extraRequestParams); >> + } >> >> let form = me.formPanel.getForm(); >> >> @@ -209,7 +211,7 @@ Ext.define('Proxmox.window.Edit', { >> waitMsgTarget: me, >> }, options); >> >> - if (Object.keys(me.extraRequestParams).length > 0) { >> + if (me.extraRequestParams && Object.keys(me.extraRequestParams).length > 0) { >> let params = newopts.params || {}; >> Ext.applyIf(params, me.extraRequestParams); >> newopts.params = params; > > i did a quick an dirty test and using a constructor like this seems to > rule out this class of bug completelly: > > ```js > constructor: function(conf) { > let me = this; > me.extraRequestParams = {}; > me.initConfig(conf); > me.callParent(); > }, > ``` > > basically it configures the edit window as usual, but overwrites the > `extraRequestParams` object for each instance with a new empty object. > so there are no more shared objects :) could you check whether that also > fixes the other instances? > > [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor Nifty, didn't think about a constructor solution. Such a general solution would be way more elegant, thanks for suggesting it! However, this particular constructor seems to break the pattern of defining `extraRequestParams` in the subclass properties, as done by `PVE.Pool.AddVM` [1]. With the constructor above, the API request done by `AddVM` seems to be missing the `allow-move` parameter. Looks like once `PVE.Pool.AddVM` is instantiated and the constructor is called, `extraRequestParams` with `allow-move` is only defined in `me.__proto__`, so `me.extraRequestParams = {}` essentially shadows it with an empty object, losing the `allow-move`. Do you have an idea how to fix this? Maybe making a copy of `extraRequestParams` would work (I suppose the overhead of creating a new object for all edit window (subclass) instances is negligible). [1] https://git.proxmox.com/?p=pve-manager.git;a=blob;f=www/manager6/grid/PoolMembers.js;h=75f20cab;hb=4b06efb5#l9 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 9:01 ` Friedrich Weber @ 2024-04-04 9:23 ` Stefan Sterz 2024-04-04 10:10 ` Friedrich Weber 0 siblings, 1 reply; 12+ messages in thread From: Stefan Sterz @ 2024-04-04 9:23 UTC (permalink / raw) To: Friedrich Weber, Proxmox VE development discussion -- >8 snip 8< -- > > > > i did a quick an dirty test and using a constructor like this seems to > > rule out this class of bug completelly: > > > > ```js > > constructor: function(conf) { > > let me = this; > > me.extraRequestParams = {}; > > me.initConfig(conf); > > me.callParent(); > > }, > > ``` > > > > basically it configures the edit window as usual, but overwrites the > > `extraRequestParams` object for each instance with a new empty object. > > so there are no more shared objects :) could you check whether that also > > fixes the other instances? > > > > [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor > > Nifty, didn't think about a constructor solution. Such a general > solution would be way more elegant, thanks for suggesting it! > > However, this particular constructor seems to break the pattern of > defining `extraRequestParams` in the subclass properties, as done by > `PVE.Pool.AddVM` [1]. With the constructor above, the API request done > by `AddVM` seems to be missing the `allow-move` parameter. > > Looks like once `PVE.Pool.AddVM` is instantiated and the constructor is > called, `extraRequestParams` with `allow-move` is only defined in > `me.__proto__`, so `me.extraRequestParams = {}` essentially shadows it > with an empty object, losing the `allow-move`. > not sure what you mean by that, if an `PVE.Pool.AddVM` is instantiated, the `extraRequestParams` is already set, so it isn't just in `__proto__` for me. but yeah, the problem is correct as `me.extraRequestParams = {}` overwrites the field. > Do you have an idea how to fix this? Maybe making a copy of > `extraRequestParams` would work (I suppose the overhead of creating a > new object for all edit window (subclass) instances is negligible). > > [1] > https://git.proxmox.com/?p=pve-manager.git;a=blob;f=www/manager6/grid/PoolMembers.js;h=75f20cab;hb=4b06efb5#l9 this worked for me, can you confirm that this also does what it should for you? ```js extraRequestParams: undefined, constructor: function(conf) { let me = this; if (!me.extraRequestParams) { me.extraRequestParams = {}; } me.initConfig(conf); me.callParent(); }, ``` ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 9:23 ` Stefan Sterz @ 2024-04-04 10:10 ` Friedrich Weber 2024-04-04 10:54 ` Stefan Sterz 2024-04-04 10:59 ` Thomas Lamprecht 0 siblings, 2 replies; 12+ messages in thread From: Friedrich Weber @ 2024-04-04 10:10 UTC (permalink / raw) To: Stefan Sterz, Proxmox VE development discussion On 04/04/2024 11:23, Stefan Sterz wrote: > -- >8 snip 8< -- >>> >>> i did a quick an dirty test and using a constructor like this seems to >>> rule out this class of bug completelly: >>> >>> ```js >>> constructor: function(conf) { >>> let me = this; >>> me.extraRequestParams = {}; >>> me.initConfig(conf); >>> me.callParent(); >>> }, >>> ``` >>> >>> basically it configures the edit window as usual, but overwrites the >>> `extraRequestParams` object for each instance with a new empty object. >>> so there are no more shared objects :) could you check whether that also >>> fixes the other instances? >>> >>> [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor >> >> Nifty, didn't think about a constructor solution. Such a general >> solution would be way more elegant, thanks for suggesting it! >> >> However, this particular constructor seems to break the pattern of >> defining `extraRequestParams` in the subclass properties, as done by >> `PVE.Pool.AddVM` [1]. With the constructor above, the API request done >> by `AddVM` seems to be missing the `allow-move` parameter. >> >> Looks like once `PVE.Pool.AddVM` is instantiated and the constructor is >> called, `extraRequestParams` with `allow-move` is only defined in >> `me.__proto__`, so `me.extraRequestParams = {}` essentially shadows it >> with an empty object, losing the `allow-move`. >> > > not sure what you mean by that, if an `PVE.Pool.AddVM` is instantiated, > the `extraRequestParams` is already set, so it isn't just in `__proto__` > for me. but yeah, the problem is correct as `me.extraRequestParams = {}` > overwrites the field. I agree it doesn't matter here, but just for completeness, I meant that if I set a breakpoint before line 2, so before the overwrite: ```js constructor: function(conf) { let me = this; => me.extraRequestParams = {}; me.initConfig(conf); me.callParent(); }, ``` ... `extraRequestParams` is not a property of `me`, but inherited from its prototype: ``` >> me.extraRequestParams Object { "allow-move": 1 } >> "extraRequestParams" in me true >> Object.hasOwn(me, "extraRequestParams") false ``` Doesn't make a difference for the overwrite, though. >> Do you have an idea how to fix this? Maybe making a copy of >> `extraRequestParams` would work (I suppose the overhead of creating a >> new object for all edit window (subclass) instances is negligible). >> >> [1] >> https://git.proxmox.com/?p=pve-manager.git;a=blob;f=www/manager6/grid/PoolMembers.js;h=75f20cab;hb=4b06efb5#l9 > > this worked for me, can you confirm that this also does what it should > for you? > > ```js > extraRequestParams: undefined, > > constructor: function(conf) { > let me = this; > if (!me.extraRequestParams) { > me.extraRequestParams = {}; > } > me.initConfig(conf); > me.callParent(); > }, > ``` It works in the sense that it fixes the bug mentioned in my patch 1/3, and fixes the lost `allow-move` issue from the previous constructor. But with this constructor, all instances of `AddVM` share the same `extraRequestParams` (the body of the `if` never gets executed for `AddVM` instances), which is the condition that my patch 2/3 tries to avoid (even though it is currently not buggy). Maybe we could do: ```js extraRequestParams: {}, constructor: function(conf) { let me = this; me.extraRequestParams = Ext.clone(me.extraRequestParams); me.initConfig(conf); me.callParent(); }, ``` ... which, if I'm not missing anything, *should* cover everything (with the cost of allocating unnecessary empty objects)? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 10:10 ` Friedrich Weber @ 2024-04-04 10:54 ` Stefan Sterz 2024-04-04 11:04 ` Stefan Sterz 2024-04-04 10:59 ` Thomas Lamprecht 1 sibling, 1 reply; 12+ messages in thread From: Stefan Sterz @ 2024-04-04 10:54 UTC (permalink / raw) To: Friedrich Weber, Proxmox VE development discussion On Thu Apr 4, 2024 at 12:10 PM CEST, Friedrich Weber wrote: > On 04/04/2024 11:23, Stefan Sterz wrote: > > -- >8 snip 8< -- > >>> > >>> i did a quick an dirty test and using a constructor like this seems to > >>> rule out this class of bug completelly: > >>> > >>> ```js > >>> constructor: function(conf) { > >>> let me = this; > >>> me.extraRequestParams = {}; > >>> me.initConfig(conf); > >>> me.callParent(); > >>> }, > >>> ``` > >>> > >>> basically it configures the edit window as usual, but overwrites the > >>> `extraRequestParams` object for each instance with a new empty object. > >>> so there are no more shared objects :) could you check whether that also > >>> fixes the other instances? > >>> > >>> [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor > >> > >> Nifty, didn't think about a constructor solution. Such a general > >> solution would be way more elegant, thanks for suggesting it! > >> > >> However, this particular constructor seems to break the pattern of > >> defining `extraRequestParams` in the subclass properties, as done by > >> `PVE.Pool.AddVM` [1]. With the constructor above, the API request done > >> by `AddVM` seems to be missing the `allow-move` parameter. > >> > >> Looks like once `PVE.Pool.AddVM` is instantiated and the constructor is > >> called, `extraRequestParams` with `allow-move` is only defined in > >> `me.__proto__`, so `me.extraRequestParams = {}` essentially shadows it > >> with an empty object, losing the `allow-move`. > >> > > > > not sure what you mean by that, if an `PVE.Pool.AddVM` is instantiated, > > the `extraRequestParams` is already set, so it isn't just in `__proto__` > > for me. but yeah, the problem is correct as `me.extraRequestParams = {}` > > overwrites the field. > > I agree it doesn't matter here, but just for completeness, I meant that > if I set a breakpoint before line 2, so before the overwrite: > > ```js > constructor: function(conf) { > let me = this; > => me.extraRequestParams = {}; > me.initConfig(conf); > me.callParent(); > }, > ``` > > ... `extraRequestParams` is not a property of `me`, but inherited from > its prototype: > > ``` > >> me.extraRequestParams > Object { "allow-move": 1 } > >> "extraRequestParams" in me > true > >> Object.hasOwn(me, "extraRequestParams") > false > ``` > > Doesn't make a difference for the overwrite, though. > ah yeah, that makes sense, but yeah, it doesn't really matter here i suppose. > >> Do you have an idea how to fix this? Maybe making a copy of > >> `extraRequestParams` would work (I suppose the overhead of creating a > >> new object for all edit window (subclass) instances is negligible). > >> > >> [1] > >> https://git.proxmox.com/?p=pve-manager.git;a=blob;f=www/manager6/grid/PoolMembers.js;h=75f20cab;hb=4b06efb5#l9 > > > > this worked for me, can you confirm that this also does what it should > > for you? > > > > ```js > > extraRequestParams: undefined, > > > > constructor: function(conf) { > > let me = this; > > if (!me.extraRequestParams) { > > me.extraRequestParams = {}; > > } > > me.initConfig(conf); > > me.callParent(); > > }, > > ``` > > It works in the sense that it fixes the bug mentioned in my patch 1/3, > and fixes the lost `allow-move` issue from the previous constructor. But > with this constructor, all instances of `AddVM` share the same > `extraRequestParams` (the body of the `if` never gets executed for > `AddVM` instances), which is the condition that my patch 2/3 tries to > avoid (even though it is currently not buggy). > > Maybe we could do: > > ```js > extraRequestParams: {}, > > constructor: function(conf) { > let me = this; > me.extraRequestParams = Ext.clone(me.extraRequestParams); > me.initConfig(conf); > me.callParent(); > }, > ``` > > ... which, if I'm not missing anything, *should* cover everything (with > the cost of allocating unnecessary empty objects)? yeah looks good to me. cloning shouldn't cost too much here. if we are really worried we could check whether the object is empty, clone it in that case and assign an empty object otherwise. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 10:54 ` Stefan Sterz @ 2024-04-04 11:04 ` Stefan Sterz 0 siblings, 0 replies; 12+ messages in thread From: Stefan Sterz @ 2024-04-04 11:04 UTC (permalink / raw) To: Proxmox VE development discussion, Friedrich Weber On Thu Apr 4, 2024 at 12:54 PM CEST, Stefan Sterz wrote: > On Thu Apr 4, 2024 at 12:10 PM CEST, Friedrich Weber wrote: > > On 04/04/2024 11:23, Stefan Sterz wrote: > > > -- >8 snip 8< -- > > >>> > > >>> i did a quick an dirty test and using a constructor like this seems to > > >>> rule out this class of bug completelly: > > >>> > > >>> ```js > > >>> constructor: function(conf) { > > >>> let me = this; > > >>> me.extraRequestParams = {}; > > >>> me.initConfig(conf); > > >>> me.callParent(); > > >>> }, > > >>> ``` > > >>> > > >>> basically it configures the edit window as usual, but overwrites the > > >>> `extraRequestParams` object for each instance with a new empty object. > > >>> so there are no more shared objects :) could you check whether that also > > >>> fixes the other instances? > > >>> > > >>> [1]: https://docs-devel.sencha.com/extjs/7.0.0/classic/Ext.window.Window.html#method-constructor > > >> > > >> Nifty, didn't think about a constructor solution. Such a general > > >> solution would be way more elegant, thanks for suggesting it! > > >> > > >> However, this particular constructor seems to break the pattern of > > >> defining `extraRequestParams` in the subclass properties, as done by > > >> `PVE.Pool.AddVM` [1]. With the constructor above, the API request done > > >> by `AddVM` seems to be missing the `allow-move` parameter. > > >> > > >> Looks like once `PVE.Pool.AddVM` is instantiated and the constructor is > > >> called, `extraRequestParams` with `allow-move` is only defined in > > >> `me.__proto__`, so `me.extraRequestParams = {}` essentially shadows it > > >> with an empty object, losing the `allow-move`. > > >> > > > > > > not sure what you mean by that, if an `PVE.Pool.AddVM` is instantiated, > > > the `extraRequestParams` is already set, so it isn't just in `__proto__` > > > for me. but yeah, the problem is correct as `me.extraRequestParams = {}` > > > overwrites the field. > > > > I agree it doesn't matter here, but just for completeness, I meant that > > if I set a breakpoint before line 2, so before the overwrite: > > > > ```js > > constructor: function(conf) { > > let me = this; > > => me.extraRequestParams = {}; > > me.initConfig(conf); > > me.callParent(); > > }, > > ``` > > > > ... `extraRequestParams` is not a property of `me`, but inherited from > > its prototype: > > > > ``` > > >> me.extraRequestParams > > Object { "allow-move": 1 } > > >> "extraRequestParams" in me > > true > > >> Object.hasOwn(me, "extraRequestParams") > > false > > ``` > > > > Doesn't make a difference for the overwrite, though. > > > > ah yeah, that makes sense, but yeah, it doesn't really matter here i > suppose. > > > >> Do you have an idea how to fix this? Maybe making a copy of > > >> `extraRequestParams` would work (I suppose the overhead of creating a > > >> new object for all edit window (subclass) instances is negligible). > > >> > > >> [1] > > >> https://git.proxmox.com/?p=pve-manager.git;a=blob;f=www/manager6/grid/PoolMembers.js;h=75f20cab;hb=4b06efb5#l9 > > > > > > this worked for me, can you confirm that this also does what it should > > > for you? > > > > > > ```js > > > extraRequestParams: undefined, > > > > > > constructor: function(conf) { > > > let me = this; > > > if (!me.extraRequestParams) { > > > me.extraRequestParams = {}; > > > } > > > me.initConfig(conf); > > > me.callParent(); > > > }, > > > ``` > > > > It works in the sense that it fixes the bug mentioned in my patch 1/3, > > and fixes the lost `allow-move` issue from the previous constructor. But > > with this constructor, all instances of `AddVM` share the same > > `extraRequestParams` (the body of the `if` never gets executed for > > `AddVM` instances), which is the condition that my patch 2/3 tries to > > avoid (even though it is currently not buggy). > > > > Maybe we could do: > > > > ```js > > extraRequestParams: {}, > > > > constructor: function(conf) { > > let me = this; > > me.extraRequestParams = Ext.clone(me.extraRequestParams); > > me.initConfig(conf); > > me.callParent(); > > }, > > ``` > > > > ... which, if I'm not missing anything, *should* cover everything (with > > the cost of allocating unnecessary empty objects)? > > yeah looks good to me. cloning shouldn't cost too much here. if we are > really worried we could check whether the object is empty, clone > it in that case and assign an empty object otherwise. > i just looked through the code for `Ext.clone` [1], if i'm not mistaken in modern browsers (which we restrict ourselves to anyway, mostly), this basically returns an empty object anyway, we would skip a few assignments and checks, but i doubt performance would improve to the point where adding such a check makes sense. [1]: https://docs.sencha.com/extjs/7.0.0/modern/src/Ext.js.html#Ext-method-clone > > _______________________________________________ > pve-devel mailing list > pve-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 10:10 ` Friedrich Weber 2024-04-04 10:54 ` Stefan Sterz @ 2024-04-04 10:59 ` Thomas Lamprecht 2024-04-04 11:28 ` Friedrich Weber 1 sibling, 1 reply; 12+ messages in thread From: Thomas Lamprecht @ 2024-04-04 10:59 UTC (permalink / raw) To: Proxmox VE development discussion, Friedrich Weber, Stefan Sterz Am 04/04/2024 um 12:10 schrieb Friedrich Weber: > Maybe we could do: > > ```js > extraRequestParams: {}, > > constructor: function(conf) { > let me = this; > me.extraRequestParams = Ext.clone(me.extraRequestParams); > me.initConfig(conf); > me.callParent(); > }, > ``` > > ... which, if I'm not missing anything, *should* cover everything (with > the cost of allocating unnecessary empty objects)? > yeah, I just wanted to suggest something like that, albeit I first had the (a few times used): me.extraRequestParams = Ext.apply({}, me.extraRequestParams ?? {}); pattern in mind. Mostly an slight performance improvement as we can assume that this is either undefined or an object, while Ext.clone checks for all different types (in a legacy browser compat way). Albeit nowadays one might be even better off to use something like the spread operator: me.extraRequestParams = { ...(me.extraRequestParams ?? {}) }; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals Or maybe even nicer, the Object.assign operator, that does not throw if the sources are null or undefined: me.extraRequestParams = Object.assign({}, me.extraRequestParams); https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign But all those are implementation details (of which I probably would prefer the Object.assign one the most, albeit no hard feelings), in general your proposed solution seems to be the best one, w.r.t sane new usage and backward compat. btw. hasn't the `submitOptions` config object the same issue? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params 2024-04-04 10:59 ` Thomas Lamprecht @ 2024-04-04 11:28 ` Friedrich Weber 0 siblings, 0 replies; 12+ messages in thread From: Friedrich Weber @ 2024-04-04 11:28 UTC (permalink / raw) To: Thomas Lamprecht, Proxmox VE development discussion, Stefan Sterz On 04/04/2024 12:59, Thomas Lamprecht wrote: > Am 04/04/2024 um 12:10 schrieb Friedrich Weber: >> Maybe we could do: >> >> ```js >> extraRequestParams: {}, >> >> constructor: function(conf) { >> let me = this; >> me.extraRequestParams = Ext.clone(me.extraRequestParams); >> me.initConfig(conf); >> me.callParent(); >> }, >> ``` >> >> ... which, if I'm not missing anything, *should* cover everything (with >> the cost of allocating unnecessary empty objects)? >> > > > yeah, I just wanted to suggest something like that, albeit I first had the > (a few times used): > > me.extraRequestParams = Ext.apply({}, me.extraRequestParams ?? {}); > > pattern in mind. Mostly an slight performance improvement as we can assume > that this is either undefined or an object, while Ext.clone checks for all > different types (in a legacy browser compat way). > > Albeit nowadays one might be even better off to use something like the > spread operator: > > me.extraRequestParams = { ...(me.extraRequestParams ?? {}) }; > > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals > > Or maybe even nicer, the Object.assign operator, that does not throw if > the sources are null or undefined: > > me.extraRequestParams = Object.assign({}, me.extraRequestParams); > > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign > > But all those are implementation details (of which I probably would prefer > the Object.assign one the most, albeit no hard feelings), in general your > proposed solution seems to be the best one, w.r.t sane new usage and > backward compat. I agree `Object.assign` looks like the nicest solution, and seeing that we already use it in our codebase, I'll go for this one. > btw. hasn't the `submitOptions` config object the same issue? You're right, `submitOptions` also has the potential for the same class of bugs. The current usages of `submitOptions` look unproblematic. But since we go for a more general fix for `extraRequestParams` anyway, let's handle `submitOptions` similarly. I'll send a v3 (just noticed I forgot the `v2` in the subject for this one). Thank you and sterzy for your suggestions! ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-04-04 11:28 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-04-03 9:10 [pve-devel] [PATCH manager/widget-toolkit 0/3] ui: avoid UI bugs due to shared extra request params Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 1/3] ui: pool members: avoid setting request parameter for all edit windows Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH manager 2/3] ui: pool members: avoid sharing object for extra request parameters Friedrich Weber 2024-04-03 9:10 ` [pve-devel] [PATCH widget-toolkit 3/3] window: edit: avoid shared object for extra request params Friedrich Weber 2024-04-04 8:22 ` Stefan Sterz 2024-04-04 9:01 ` Friedrich Weber 2024-04-04 9:23 ` Stefan Sterz 2024-04-04 10:10 ` Friedrich Weber 2024-04-04 10:54 ` Stefan Sterz 2024-04-04 11:04 ` Stefan Sterz 2024-04-04 10:59 ` Thomas Lamprecht 2024-04-04 11:28 ` Friedrich Weber
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox