fix unsafe mutation in input picker getter (#6428)

* fix bad mutation

* remove unnecessary data structure for step args
This commit is contained in:
Guilhem
2025-08-20 23:40:14 +01:00
committed by GitHub
parent 58bc913dfc
commit 4b79e53f0d
5 changed files with 41 additions and 42 deletions
@@ -98,14 +98,11 @@
loadResourceTypes()
let args = $state(<Record<string, any>>{})
onMount(() => {
if (!testSteps) {
sendUserToast('testSteps module not initialized. Preview will not work.', true)
}
testSteps?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val)
args = testSteps?.getStepArgs(mod.id)
})
</script>
@@ -120,14 +117,17 @@
)}
data-arg={argName}
>
{#if typeof args.value == 'object' && schema?.properties?.[argName]}
{#if schema?.properties?.[argName]}
<ArgInput
{resourceTypes}
minW={false}
autofocus={autofocus && !focusArg && i == 0}
label={argName}
description={schema.properties[argName].description}
bind:value={args.value[argName]}
bind:value={
() => testSteps?.getStepInputArgs(mod.id, argName) ?? {},
(v) => testSteps?.setStepInputArgs(mod.id, argName, v)
}
type={schema.properties[argName].type}
oneOf={schema.properties[argName].oneOf}
required={schema?.required?.includes(argName)}
@@ -31,12 +31,12 @@
let stepHistoryLoader = getStepHistoryLoaderContext()
export function runTestWithStepArgs() {
runTest(testSteps.getStepArgs(mod.id)?.value)
runTest(testSteps.getStepArgs(mod.id))
}
export function loadArgsAndRunTest() {
testSteps?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val)
runTest(testSteps.getStepArgs(mod.id)?.value)
runTest(testSteps.getStepArgs(mod.id))
}
export async function runTest(args: any) {
@@ -20,7 +20,7 @@
testSteps?.updateStepArgs(id, flowStateStore?.val, flowStore?.val, previewArgs?.val)
})
const input = $derived(testSteps?.getStepArgs(id)?.value)
const input = $derived(testSteps?.getStepArgs(id))
</script>
<div class="p-4 pr-6 h-full overflow-y-auto">
@@ -6,34 +6,35 @@ import {
getStepPropPicker,
type PickableProperties
} from './previousResults'
import { evalValue, type ModuleArgs } from './utils'
import { evalValue } from './utils'
export class TestSteps {
#stepsEvaluated = $state<Record<string, ModuleArgs>>({})
#steps = $state<Record<string, { value: any }>>({})
#stepsEvaluated = $state<Record<string, Record<string, any>>>({})
#steps = $state<Record<string, Record<string, any>>>({})
constructor() { }
constructor() {}
setStepArgsManually(moduleId: string, args: Record<string, any>) {
if (!this.#steps[moduleId]) {
this.#steps[moduleId] = { value: {} }
}
this.#steps[moduleId].value = args
this.#steps[moduleId] = args
}
getStepArgs(moduleId: string): ModuleArgs {
let args = this.#steps[moduleId]
if (!args) {
this.#steps[moduleId] = { value: {} }
}
getStepArgs(moduleId: string): Record<string, any> | undefined {
return this.#steps[moduleId]
}
getStepInputArgs(moduleId: string, argName: string): any | undefined {
return this.#steps[moduleId]?.[argName]
}
setStepArgs(moduleId: string, args: Record<string, any>) {
this.#steps[moduleId] = args
}
setStepInputArgs(moduleId: string, argName: string, value: any) {
if (!this.#steps[moduleId]) {
this.#steps[moduleId] = { value: {} }
this.#steps[moduleId] = {}
}
this.#steps[moduleId].value = args
this.#steps[moduleId][argName] = value
}
getStepArg(moduleId: string, argName: string): any | undefined {
@@ -42,26 +43,26 @@ export class TestSteps {
setEvaluatedStepArg(moduleId: string, argName: string, value: any) {
if (!this.#steps[moduleId]) {
this.#steps[moduleId] = { value: {} }
this.#steps[moduleId] = {}
}
if (!this.#stepsEvaluated[moduleId]) {
this.#stepsEvaluated[moduleId] = { value: {} }
this.#stepsEvaluated[moduleId] = {}
}
this.#steps[moduleId].value[argName] = $state.snapshot(value)
this.#stepsEvaluated[moduleId].value[argName] = $state.snapshot(value)
this.#steps[moduleId][argName] = $state.snapshot(value)
this.#stepsEvaluated[moduleId][argName] = $state.snapshot(value)
}
isArgManuallySet(moduleId: string, argName: string): boolean {
return (
JSON.stringify(this.#steps[moduleId]?.value?.[argName]) !==
JSON.stringify(this.#stepsEvaluated[moduleId]?.value?.[argName])
JSON.stringify(this.#steps[moduleId]?.[argName]) !==
JSON.stringify(this.#stepsEvaluated[moduleId]?.[argName])
)
}
getManuallyEditedArgs(moduleId: string): string[] {
const manuallyEditedArgs: string[] = []
const moduleArgs = this.#steps[moduleId]?.value ?? {}
const moduleArgs = this.#steps[moduleId] ?? {}
Object.keys(moduleArgs).forEach((argName) => {
if (this.isArgManuallySet(moduleId, argName)) {
@@ -105,8 +106,8 @@ export class TestSteps {
const pickableProperties = stepPropPicker.pickableProperties
const argSnapshot = $state.snapshot(evalValue(argName, modules[0], pickableProperties, false))
this.#stepsEvaluated[moduleId].value[argName] = argSnapshot
this.#steps[moduleId].value[argName] = structuredClone(argSnapshot)
this.#stepsEvaluated[moduleId][argName] = argSnapshot
this.#steps[moduleId][argName] = structuredClone(argSnapshot)
}
initializeFromSchema(
@@ -124,21 +125,21 @@ export class TestSteps {
const manuallyEditedArgs = this.getManuallyEditedArgs(mod.id)
if (!this.#steps[mod.id]) {
this.#steps[mod.id] = { value: {} }
this.#steps[mod.id] = {}
}
if (!this.#stepsEvaluated[mod.id]) {
this.#stepsEvaluated[mod.id] = { value: {} }
this.#stepsEvaluated[mod.id] = {}
}
this.#stepsEvaluated[mod.id].value = $state.snapshot(args)
this.#stepsEvaluated[mod.id] = $state.snapshot(args)
// Preserve manually edited args
const argsSnapshot = $state.snapshot(args)
Object.keys(argsSnapshot).forEach((key) => {
if (manuallyEditedArgs.includes(key)) {
argsSnapshot[key] = this.#steps[mod.id]?.value?.[key]
argsSnapshot[key] = this.#steps[mod.id]?.[key]
}
})
this.#steps[mod.id].value = argsSnapshot
this.#steps[mod.id] = argsSnapshot
}
updateStepArgs(
@@ -177,11 +178,11 @@ export class TestSteps {
return
}
const nargs = {}
Object.keys(this.#stepsEvaluated[moduleId]?.value ?? {}).forEach((key) => {
Object.keys(this.#stepsEvaluated[moduleId] ?? {}).forEach((key) => {
if (keys.includes(key)) {
nargs[key] = this.#stepsEvaluated[moduleId]?.value?.[key]
nargs[key] = this.#stepsEvaluated[moduleId]?.[key]
}
})
this.#stepsEvaluated[moduleId].value = nargs
this.#stepsEvaluated[moduleId] = nargs
}
}
@@ -31,8 +31,6 @@ return ${eval_string}
}`
}
export type ModuleArgs = { value: Record<string, any> }
function make_context_evaluator(eval_string, context): (context) => any {
let template = create_context_function_template(eval_string, context)
let functor = Function(template)