See a path token's head when walking for cycles
This commit is contained in:
@@ -202,6 +202,18 @@ func TestDifferentTailsUnderOneHeadShareTheRow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCycleThroughAPathTokenIsRejected(t *testing.T) {
|
||||||
|
// A path token is a render edge like any other, so a cycle routed through one
|
||||||
|
// must be caught at New. Reaching render would be fatal: the recursion never
|
||||||
|
// terminates, and a stack overflow cannot be recovered.
|
||||||
|
_, err := New([]string{writeData(t, map[string]string{
|
||||||
|
"a": `{"format":"{p.x}","p":{"format":"{x}","x":{"format":"{..a}"}}}`,
|
||||||
|
})})
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "reference cycle") {
|
||||||
|
t.Fatalf("New = %v, want the cycle through {p.x} rejected", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBoundPathIsReachableByFake(t *testing.T) {
|
func TestBoundPathIsReachableByFake(t *testing.T) {
|
||||||
// Binding changes how a format reads a sibling, not what List and Fake offer:
|
// Binding changes how a format reads a sibling, not what List and Fake offer:
|
||||||
// the sub-fields stay addressable on their own.
|
// the sub-fields stay addressable on their own.
|
||||||
|
|||||||
+4
-1
@@ -190,7 +190,10 @@ func renderEdges(n node) []renderEdge {
|
|||||||
case *template:
|
case *template:
|
||||||
var es []renderEdge
|
var es []renderEdge
|
||||||
for _, name := range append(fieldTokens(n.format), calcOperands(n.format)...) {
|
for _, name := range append(fieldTokens(n.format), calcOperands(n.format)...) {
|
||||||
if c, ok := n.fields[name]; ok {
|
// A path token renders its head, so the edge is to the head — over-
|
||||||
|
// approximating the sub-field it descends to, which is what keeps the
|
||||||
|
// cycle walk conservative rather than blind.
|
||||||
|
if c, ok := n.fields[splitArm(name).key]; ok {
|
||||||
es = append(es, renderEdge{c, name})
|
es = append(es, renderEdge{c, name})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user