koumoul-dev / vuetify-jsonschema-form

Create beautiful and low-effort forms that output valid data. Published on npm as @koumoul/vjsf.
https://koumoul-dev.github.io/vuetify-jsonschema-form/latest/
MIT License
538 stars 154 forks source link

Page freeze if enum value is invalid #289

Closed mvandenburgh closed 2 years ago

mvandenburgh commented 2 years ago

The schema we're using with vjsf has an enum field RoleType. If RoleType isn't set to a valid value in the model, the browser page completely freezes.

Demo: https://codepen.io/mvandenburgh/pen/rNmragW Since the page freezes upon loading the model into vjsf, the model is empty initially and can be loaded by clicking the "Load Model" button. Correcting the model manually (see line 47 in that codepen) will cause vjsf to work correctly with no freezing.

I traced the freezing back to this watcher. Something seems to be constantly mutating the fullSchema variable and causing that watcher to execute infinitely.

albanm commented 2 years ago

Ok, this was a tough one ! Took me several hours to wrap my head around it but the fix is here https://github.com/koumoul-dev/vuetify-jsonschema-form/blob/master/lib/mixins/EditableArray.js#L269

Thanks for the detailed report, but the watcher was not the real culprit. It was simply called because the component instance was recreated, but it was not causing the loop.

Validation was the cause: array item is first considered valid as it is empty, then it is filled with a broken model from a oneOf, the error bubbles up, the array item is now in error and is re-rendered. All this is normal, but as well as being re-rendered it was also destroyed and recreated entirely, therefore empty again and considered valid. I had already encountered this pattern and it was simply mitigated by a $nextTick, but this mitigation didn't work when the error was nested (inside a oneOf in your case) and took more cycles to bubble up. Anyway I hope this fix is more robust.

albanm commented 2 years ago

A more stable implementation would be to use a separate validation tool (I need to have a look again at a PR for ajv integration) to validate array items before rendering them instead of first rendering, then waiting for form validation errors to bubble up.