Bug? Apvts doesn't fully sync missing parameters on assignment

Hi there,

Let’s say I have an apvts with two parameters added:

std::make_unique<juce::AudioParameterFloat> (ParameterID("gain", 1), "Gain", 0.0f, 1.0f, 0.5f),
std::make_unique<juce::AudioParameterBool> (ParameterID("invertPhase", 1), "Invert Phase", false)

If I assign a new state to the apvts (such as in setStateInformation), my expectation was that the apvts synchronizes with parameters and adds any PARAM children to the ValueTree that might be missing.

It seems that the children are added, but with no value property. So the apvts ValueTree ends up in a surprising “half existing” state.

To reproduce:

    ValueTree mockIncomingState { "incoming" };
    mockIncomingState.copyPropertiesAndChildrenFrom(parameters.state, nullptr);
    mockIncomingState.removeChild(1, nullptr); // remove the boolean "invert phase" parameter
    parameters.state = mockIncomingState; // copy to apvts
    jassert(parameters.state.getChild(1).hasProperty("id"));
    jassert(parameters.state.getChild(1).hasProperty("value"));

An assertion happens on the last line. Is this a bug, or is there an incantation I’m missing to get the value to populate?

Looking at the parameter reconstruction after assignment, it seems like only the id is set, not the value.

flushParameterValuesToValueTree is then called, and I would have expected value to be populated, but this conditional returns false.

In my own code, I worked around the issue by avoiding apvts assignment and instead manually iterating over the existing PARAM children, using it as an allow list / source of “truth.”

That way, if the incoming state is missing PARAM children (for example, an older version of state before a new parameter was added), there’s no indeterminate “half” state.