Repository: CloudyKit/jet
Pull request #176 (2020-09-07 17:01:15)

fix fallthrough bug in getRanger - v3
Backports #148 to the v3 branch

tooolbox: Ping @sauerbraten 

Patch:
diff --git a/eval.go b/eval.go
index b4fe5ad..b26e739 100644
--- a/eval.go
+++ b/eval.go
@@ -1556,25 +1556,28 @@ func getRanger(v reflect.Value) Ranger {
 		return v.Interface().(Ranger)
 	}
 	k := tuP.Kind()
-	switch k {
-	case reflect.Ptr, reflect.Interface:
-		v = v.Elem()
-		k = v.Kind()
-		fallthrough
-	case reflect.Slice, reflect.Array:
-		sliceranger := pool_sliceRanger.Get().(*sliceRanger)
-		sliceranger.i = -1
-		sliceranger.len = v.Len()
-		sliceranger.v = v
-		return sliceranger
-	case reflect.Map:
-		mapranger := pool_mapRanger.Get().(*mapRanger)
-		*mapranger = mapRanger{v: v, keys: v.MapKeys(), len: v.Len()}
-		return mapranger
-	case reflect.Chan:
-		chanranger := pool_chanRanger.Get().(*chanRanger)
-		*chanranger = chanRanger{v: v}
-		return chanranger
+	for {
+		switch k {
+		case reflect.Ptr, reflect.Interface:
+			v = v.Elem()
+			k = v.Kind()
+			continue
+		case reflect.Slice, reflect.Array:
+			sliceranger := pool_sliceRanger.Get().(*sliceRanger)
+			sliceranger.i = -1
+			sliceranger.len = v.Len()
+			sliceranger.v = v
+			return sliceranger
+		case reflect.Map:
+			mapranger := pool_mapRanger.Get().(*mapRanger)
+			*mapranger = mapRanger{v: v, keys: v.MapKeys(), len: v.Len()}
+			return mapranger
+		case reflect.Chan:
+			chanranger := pool_chanRanger.Get().(*chanRanger)
+			*chanranger = chanRanger{v: v}
+			return chanranger
+		}
+		break
 	}
 	panic(fmt.Errorf("type %s is not rangeable", tuP))
 }


Test patch:
diff --git a/eval_test.go b/eval_test.go
index d9dc5f7..64a2144 100644
--- a/eval_test.go
+++ b/eval_test.go
@@ -285,12 +285,20 @@ func TestEvalRangeNode(t *testing.T) {
 		{"Joel Silva", "joelsilva@gmail.com"},
 		{"Luis Santana", "luis.santana@gmail.com"},
 	})
+	ages := map[string]int{
+		"Mario Santos": 25,
+		"Joel Silva":   35,
+		"Luis Santana": 45,
+	}
+	data.Set("ages", &ages)
 
 	const resultString = `<h1>Mario Santos<small>mario@gmail.com</small></h1><h1>Joel Silva<small>joelsilva@gmail.com</small></h1><h1>Luis Santana<small>luis.santana@gmail.com</small></h1>`
 	RunJetTest(t, data, nil, "Range_Expression", `{{range users}}<h1>{{.Name}}<small>{{.Email}}</small></h1>{{end}}`, resultString)
 	RunJetTest(t, data, nil, "Range_ExpressionValue", `{{range user:=users}}<h1>{{user.Name}}<small>{{user.Email}}</small></h1>{{end}}`, resultString)
 	var resultString2 = `<h1>0: Mario Santos<small>mario@gmail.com</small></h1><h1>Joel Silva<small>joelsilva@gmail.com</small></h1><h1>2: Luis Santana<small>luis.santana@gmail.com</small></h1>`
 	RunJetTest(t, data, nil, "Range_ExpressionValueIf", `{{range i, user:=users}}<h1>{{if i == 0 || i == 2}}{{i}}: {{end}}{{user.Name}}<small>{{user.Email}}</small></h1>{{end}}`, resultString2)
+	var resultString3 = `<ul><li>Mario Santos is 25 years old.</li><li>Joel Silva is 35 years old.</li><li>Luis Santana is 45 years old.</li></ul>`
+	RunJetTest(t, data, nil, "Range_ExpressionInterfaceMapValue", `<ul>{{range name, age:=ages}}<li>{{name}} is {{age}} years old.</li>{{end}}</ul>`, resultString3)
 }
 
 func TestEvalDefaultFuncs(t *testing.T) {