luci-base: prevent tools.widgets.ZoneSelect tracebacks
authorPaul Donald <[email protected]>
Wed, 23 Apr 2025 12:04:12 +0000 (14:04 +0200)
committerPaul Donald <[email protected]>
Wed, 23 Apr 2025 12:26:37 +0000 (14:26 +0200)
follow-up fix for 0be4ad51a0bea3e1e3e6cd7d646e11ec6c722540

It seems to have been this way for a while, for zone selections
involving the 'any' ('*') choice. firewall forwards.js has no
'this.allowany;' property on the widgets, so the any choice is absent,
leading to a traceback, caused by the 'src' widget, even though
this code block operates on the 'dst' value. Certain combinations of
'src' and 'dst' also triggered tracebacks.

This might not be the correct behaviour for this widget, but it does
prevent tracebacks caused by null values.

Signed-off-by: Paul Donald <[email protected]>
(cherry picked from commit aa6924cd4ce64cc6e4ced50b0603f9f34b3e619c)

modules/luci-base/htdocs/luci-static/resources/tools/widgets.js

index ab777ba428e1f4dd3b47b382ef068dbbfccf9843..4fc7d923b955b80b97ed1db85f4cf58dcf1db86b 100644 (file)
@@ -177,26 +177,27 @@ var CBIZoneSelect = form.ListValue.extend({
                                                emptyval.parentNode.removeChild(emptyval);
                                }
                                else {
-                                       var anyval = node.querySelector('[data-value="*"]'),
-                                           emptyval = node.querySelector('[data-value=""]');
+                                       const anyval = node.querySelector('[data-value="*"]') || '';
+                                       const emptyval = node.querySelector('[data-value=""]') || '';
 
-                                       if (emptyval == null) {
+                                       if (emptyval == null && anyval) {
                                                emptyval = anyval.cloneNode(true);
                                                emptyval.removeAttribute('display');
                                                emptyval.removeAttribute('selected');
                                                emptyval.setAttribute('data-value', '');
                                        }
 
-                                       if (opt[0].allowlocal)
+                                       if (opt[0]?.allowlocal && emptyval)
                                                L.dom.content(emptyval.querySelector('span'), [
                                                        E('strong', _('Device')), E('span', ' (%s)'.format(_('input')))
                                                ]);
+                                       if (opt[0]?.allowany && anyval && emptyval) {
+                                               L.dom.content(anyval.querySelector('span'), [
+                                                       E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
+                                               ]);
 
-                                       L.dom.content(anyval.querySelector('span'), [
-                                               E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
-                                       ]);
-
-                                       anyval.parentNode.insertBefore(emptyval, anyval);
+                                               anyval.parentNode.insertBefore(emptyval, anyval);
+                                       }
                                }
 
                        }, this));