fix: preserve correct parent references in explode merge anchor reconstruction (#2730)

When explode resolves merge anchors (<<:), items copied from the
alias target retained the original parent pointer instead of being
set to the enclosing node being reconstructed. This caused GetPath()
to return wrong paths for children of merge-anchored nodes, making
subsequent merge operations target the wrong LHS keys.

In fixedReconstructAliasedMap, set copied.Parent = node after copy.

In reconstructAliasedMap (non-spec path), replace AddChild (which
creates sequence-style numeric-index entries) with AddKeyValueChild
to properly reconstruct mapping key-value pairs. AddKeyValueChild
also correctly sets parent references via SetParent.
This commit is contained in:
Hani Harzallah
2026-08-03 13:07:34 +10:00
committed by GitHub
parent a0c6389b58
commit b7c9d01670
2 changed files with 31 additions and 2 deletions
+8 -2
View File
@@ -183,7 +183,9 @@ func fixedReconstructAliasedMap(node *CandidateNode) error {
})
for _, item := range itemsToAdd {
newContent = append(newContent, item.Copy())
copied := item.Copy()
copied.Parent = node
newContent = append(newContent, copied)
}
}
}
@@ -226,8 +228,12 @@ func reconstructAliasedMap(node *CandidateNode, context Context) error {
}
}
node.Content = make([]*CandidateNode, 0)
entries := make([]*CandidateNode, 0, newContent.Len())
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
node.AddChild(newEl.Value.(*CandidateNode))
entries = append(entries, newEl.Value.(*CandidateNode))
}
for i := 0; i < len(entries); i += 2 {
node.AddKeyValueChild(entries[i], entries[i+1])
}
return nil
}
@@ -234,6 +234,29 @@ var fixedAnchorOperatorScenarios = []expressionScenario{
"D0, P[], (!!map)::a:\n b: 42\nb: 42\n",
},
},
{
skipDoc: true,
description: "Merge after explode preserves correct parent references",
document: `opensearch: &opensearch-cluster
ip2geo:
enabled: false
opensearch-client:
<<: *opensearch-cluster
nodeGroup: client
opensearchJavaOpts: "-Xmx1024m -Xms1024m"`,
document2: `opensearch: &opensearch-cluster
ip2geo:
enabled: true
opensearch-client:
<<: *opensearch-cluster
opensearchJavaOpts: "-Xmx1536m -Xms1536m"`,
expression: `(select(fi == 0) | explode(.)) * (select(fi == 1) | explode(.))`,
expected: []string{
"D0, P[], (!!map)::opensearch:\n ip2geo:\n enabled: true\nopensearch-client:\n ip2geo:\n enabled: true\n nodeGroup: client\n opensearchJavaOpts: \"-Xmx1536m -Xms1536m\"\n",
},
},
}
var badAnchorOperatorScenarios = []expressionScenario{