openhab / openhab-webui

Web UIs of openHAB
Eclipse Public License 2.0
212 stars 232 forks source link

Repeater source array with methods freezes UI #2549

Open JustinGeorgi opened 3 weeks ago

JustinGeorgi commented 3 weeks ago

I'm on a recent snapshot (4038) and I've stumbled across a very strange bug. If the array methods available in the expression parser are applied to a repeater's loop source array in an expression, the UI completely freezes.

Here's what I mean. Let's start with a simple demo widget that works just fine:

uid: sort_works_general
props:
  parameterGroups: []
  parameters: []
tags: []
component: Label
config:
  text: =([4,2,3,1,5]).sort().toString()

This functions as expected. You can even use specialized sort functions:

uid: sort_works_special
props:
  parameterGroups: []
  parameters: []
tags: []
component: Label
config:
  text: =JSON.stringify(([{'alpha':'b','num':'2'},{'alpha':'c','num':'3'},{'alpha':'a','num':'1'}]).sort((x,y) => x.num - y.num))

Chaining works just fine too, you can easily tack a .reverse() on to either of those expressions with no ill effects. So, the array methods themselves are quite functional.

If we move to a repeater:

uid: sort_works_repeater
props:
  parameterGroups: []
  parameters: []
tags: []
component: oh-list-card
config:
  title: Array test
slots:
  default:
    - component: oh-repeater
      config:
        for: test
        sourceType: array
        in: 
          - 1.5
          - 3.5
          - 4
          - 0.5
        fragment: true
      slots:
        default:
          - component: oh-list-item
            config:
              title: =loop.test
              after: =([1.5,3.5,4,0.5]).sort().toString()

This gets the expected output: image

Now here's where it gets weird: If you replace the array in the after expression with loop.test_source (which should be identical), the entire page becomes fully unresponive and must be externally killed.

Even stranger, it's only in the child components! You can apply methods to the source array in the repeater's map property. This will correctly sort the output of the repeater:

uid: sort_works_repeater_map
props:
  parameterGroups: []
  parameters: []
tags: []
component: oh-list-card
config:
  title: Array test
slots:
  default:
    - component: oh-repeater
      config:
        for: test
        sourceType: array
        in: 
          - 1.5
          - 3.5
          - 4
          - 0.5
        fragment: true
        map: loop.test_source.sort()[loop.test_idx]
      slots:
        default:
          - component: oh-list-item
            config:
              title: =loop.test

image

This can be replicated in Chrome and Firefox. I also went back and checked a couple older images I still had lying around so I can confirm it goes back at least as far as 4.1M4. I honestly can't say that I remember with 100% certainty that this ever worked in the past, so I don't know whether this is some regression or has always been inherent to the repeater.