]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix "concurrent map iteration and map write" in pages from data
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 30 Jan 2025 17:34:50 +0000 (18:34 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 30 Jan 2025 18:57:09 +0000 (19:57 +0100)
Fixes #13254

common/maps/maps_test.go
common/maps/params.go
resources/page/pagemeta/page_frontmatter.go

index b4f9c5a3d8a5a65b8ef3b6879419821a558a8a04..40c8ac824fc6d2552f18621f4a9d2ec4ef0b2b03 100644 (file)
@@ -73,10 +73,14 @@ func TestPrepareParams(t *testing.T) {
        for i, test := range tests {
                t.Run(fmt.Sprint(i), func(t *testing.T) {
                        // PrepareParams modifies input.
+                       prepareClone := PrepareParamsClone(test.input)
                        PrepareParams(test.input)
                        if !reflect.DeepEqual(test.expected, test.input) {
                                t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input)
                        }
+                       if !reflect.DeepEqual(test.expected, prepareClone) {
+                               t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, prepareClone)
+                       }
                })
        }
 }
index a8cbba5555000fc4c92c866d9270cfe6de4dda09..819f796e4bab6228e9a0fa23ceae6eb3d5622662 100644 (file)
@@ -303,7 +303,7 @@ func toMergeStrategy(v any) ParamsMergeStrategy {
 }
 
 // PrepareParams
-// * makes all the keys in the given map lower cased and will do so
+// * makes all the keys in the given map lower cased and will do so recursively.
 // * This will modify the map given.
 // * Any nested map[interface{}]interface{}, map[string]interface{},map[string]string  will be converted to Params.
 // * Any _merge value will be converted to proper type and value.
@@ -343,3 +343,42 @@ func PrepareParams(m Params) {
                }
        }
 }
+
+// PrepareParamsClone is like PrepareParams, but it does not modify the input.
+func PrepareParamsClone(m Params) Params {
+       m2 := make(Params)
+       for k, v := range m {
+               var retyped bool
+               lKey := strings.ToLower(k)
+               if lKey == MergeStrategyKey {
+                       v = toMergeStrategy(v)
+                       retyped = true
+               } else {
+                       switch vv := v.(type) {
+                       case map[any]any:
+                               var p Params = cast.ToStringMap(v)
+                               v = PrepareParamsClone(p)
+                               retyped = true
+                       case map[string]any:
+                               var p Params = v.(map[string]any)
+                               v = PrepareParamsClone(p)
+                               retyped = true
+                       case map[string]string:
+                               p := make(Params)
+                               for k, v := range vv {
+                                       p[k] = v
+                               }
+                               v = p
+                               PrepareParams(p)
+                               retyped = true
+                       }
+               }
+
+               if retyped || k != lKey {
+                       m2[lKey] = v
+               } else {
+                       m2[k] = v
+               }
+       }
+       return m2
+}
index 21789909ec8056550334370c69f1dd5739a0bb6f..60ba0e00a04b7cdf496407215df8116d0741b3b8 100644 (file)
@@ -158,8 +158,11 @@ func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, lo
 
        if p.Params == nil {
                p.Params = make(maps.Params)
+       } else if pagesFromData {
+               p.Params = maps.PrepareParamsClone(p.Params)
+       } else {
+               maps.PrepareParams(p.Params)
        }
-       maps.PrepareParams(p.Params)
 
        if p.Content.Markup == "" && p.Content.MediaType == "" {
                if ext == "" {