fix: clear a variable reference in a dyn-multiselect run-form slot

This commit is contained in:
AlexRV12
2026-09-04 17:50:16 +02:00
parent 734f62e84d
commit c3fae0014a
2 changed files with 18 additions and 9 deletions
+9 -5
View File
@@ -80,13 +80,17 @@ describe('coerceArgsToSchema', () => {
})
// Not merely unreadable: `MultiSelect` maps over the value as it renders, so anything
// else throws and takes the whole card down, Cancel with it.
it('empties a non-array in a dyn-multiselect slot', () => {
// else throws and takes the whole card down, Cancel with it. A reference is no
// exception — the widget draws before anything resolves — so this slot is the one
// place the reference rule above does not hold.
it('empties a non-array in a dyn-multiselect slot, reference included', () => {
const schema = { properties: { tags: { type: 'object', format: 'dynmultiselect-list' } } }
expect(coerceArgsToSchema({ tags: ['a'] }, schema).args).toEqual({ tags: ['a'] })
const { args, clearedKeys } = coerceArgsToSchema({ tags: { a: 1 } }, schema)
expect(args).toEqual({})
expect(clearedKeys).toEqual(['tags'])
for (const bad of [{ a: 1 }, '$var:u/admin/watchlist']) {
const { args, clearedKeys } = coerceArgsToSchema({ tags: bad }, schema)
expect(args).toEqual({})
expect(clearedKeys).toEqual(['tags'])
}
})
// Below the top the form has the same limitations as everywhere else in the product,
+9 -4
View File
@@ -50,9 +50,10 @@ export const resetKeysToast = (resetKeys: string[]): string =>
const SCALAR_TYPES = new Set(['string', 'number', 'integer', 'boolean'])
/**
* Declares an array even though its `type` says `object`, and the only slot where a
* mismatch is worse than unreadable: `MultiSelect` maps over the value as it renders,
* so anything else throws and takes the whole form down — Cancel with it.
* Declares an array even though its `type` says `object`, and a mismatch here throws
* rather than merely reading wrong: `MultiSelect` maps over the value as it renders, so
* anything else takes the whole form down — Cancel with it, and a reference included,
* since the widget draws before anything resolves.
*/
const declaresDynMultiselect = (prop: any) =>
typeof prop?.format === 'string' && prop.format.startsWith('dynmultiselect-')
@@ -125,7 +126,11 @@ export function coerceArgsToSchema(
const kept: Record<string, any> = Object.create(null)
for (const [key, value] of Object.entries(args ?? {})) {
const prop = Object.hasOwn(properties, key) ? properties[key] : undefined
if (prop === undefined || value == null || isReference(value)) {
if (
prop === undefined ||
value == null ||
(isReference(value) && !declaresDynMultiselect(prop))
) {
kept[key] = value
continue
}