Skip to content

Commit

Permalink
Fix "concurrent map iteration and map write" in pages from data
Browse files Browse the repository at this point in the history
Fixes #13254
  • Loading branch information
bep committed Jan 30, 2025
1 parent 33b46d8 commit 329b234
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
4 changes: 4 additions & 0 deletions common/maps/maps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
})
}
}
Expand Down
41 changes: 40 additions & 1 deletion common/maps/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
5 changes: 4 additions & 1 deletion resources/page/pagemeta/page_frontmatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 == "" {
Expand Down

0 comments on commit 329b234

Please sign in to comment.