From e1825f3e42a4bc0453dbded0f9206561fcb78b50 Mon Sep 17 00:00:00 2001
From: molon <3739161+molon@users.noreply.github.com>
Date: Wed, 28 Sep 2022 13:26:58 +0800
Subject: [PATCH 1/2] fix frozeWithCacheReuse

---
 adapter.go                        |  8 ++++----
 config.go                         | 24 +++++++++++++++---------
 extension_tests/extension_test.go | 20 +++++++++++++++++---
 3 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/adapter.go b/adapter.go
index 92d2cc4a..ba960ae8 100644
--- a/adapter.go
+++ b/adapter.go
@@ -100,7 +100,7 @@ func (adapter *Decoder) Buffered() io.Reader {
 func (adapter *Decoder) UseNumber() {
 	cfg := adapter.iter.cfg.configBeforeFrozen
 	cfg.UseNumber = true
-	adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions)
+	adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg)
 }
 
 // DisallowUnknownFields causes the Decoder to return an error when the destination
@@ -109,7 +109,7 @@ func (adapter *Decoder) UseNumber() {
 func (adapter *Decoder) DisallowUnknownFields() {
 	cfg := adapter.iter.cfg.configBeforeFrozen
 	cfg.DisallowUnknownFields = true
-	adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions)
+	adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg)
 }
 
 // NewEncoder same as json.NewEncoder
@@ -134,14 +134,14 @@ func (adapter *Encoder) Encode(val interface{}) error {
 func (adapter *Encoder) SetIndent(prefix, indent string) {
 	config := adapter.stream.cfg.configBeforeFrozen
 	config.IndentionStep = len(indent)
-	adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions)
+	adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg)
 }
 
 // SetEscapeHTML escape html by default, set to false to disable
 func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
 	config := adapter.stream.cfg.configBeforeFrozen
 	config.EscapeHTML = escapeHTML
-	adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions)
+	adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg)
 }
 
 // Valid reports whether data is a valid JSON encoding.
diff --git a/config.go b/config.go
index 2adcdc3b..6de4d51e 100644
--- a/config.go
+++ b/config.go
@@ -113,16 +113,16 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
 
 var cfgCache = concurrent.NewMap()
 
-func getFrozenConfigFromCache(cfg Config) *frozenConfig {
-	obj, found := cfgCache.Load(cfg)
+func getFrozenConfigFromCache(key interface{}) *frozenConfig {
+	obj, found := cfgCache.Load(key)
 	if found {
 		return obj.(*frozenConfig)
 	}
 	return nil
 }
 
-func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
-	cfgCache.Store(cfg, frozenConfig)
+func addFrozenConfigToCache(key interface{}, frozenConfig *frozenConfig) {
+	cfgCache.Store(key, frozenConfig)
 }
 
 // Froze forge API from config
@@ -166,16 +166,22 @@ func (cfg Config) Froze() API {
 	return api
 }
 
-func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig {
-	api := getFrozenConfigFromCache(cfg)
+type configKey struct {
+	Config
+	cause *frozenConfig
+}
+
+func (cfg Config) frozeWithCacheReuse(cause *frozenConfig) *frozenConfig {
+	key := configKey{cfg, cause}
+	api := getFrozenConfigFromCache(key)
 	if api != nil {
 		return api
 	}
 	api = cfg.Froze().(*frozenConfig)
-	for _, extension := range extraExtensions {
+	for _, extension := range cause.extraExtensions {
 		api.RegisterExtension(extension)
 	}
-	addFrozenConfigToCache(cfg, api)
+	addFrozenConfigToCache(key, api)
 	return api
 }
 
@@ -317,7 +323,7 @@ func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]
 	}
 	newCfg := cfg.configBeforeFrozen
 	newCfg.IndentionStep = len(indent)
-	return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v)
+	return newCfg.frozeWithCacheReuse(cfg).Marshal(v)
 }
 
 func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
diff --git a/extension_tests/extension_test.go b/extension_tests/extension_test.go
index 836db5bc..26fd9b12 100644
--- a/extension_tests/extension_test.go
+++ b/extension_tests/extension_test.go
@@ -1,13 +1,14 @@
 package test
 
 import (
-	"github.com/json-iterator/go"
-	"github.com/modern-go/reflect2"
-	"github.com/stretchr/testify/require"
 	"reflect"
 	"strconv"
 	"testing"
 	"unsafe"
+
+	jsoniter "github.com/json-iterator/go"
+	"github.com/modern-go/reflect2"
+	"github.com/stretchr/testify/require"
 )
 
 type TestObject1 struct {
@@ -59,6 +60,19 @@ func Test_customize_map_key_encoder(t *testing.T) {
 	m = map[int]int{}
 	should.NoError(cfg.UnmarshalFromString(output, &m))
 	should.Equal(map[int]int{1: 2}, m)
+
+	b, err := cfg.MarshalIndent(m, "", "  ")
+	should.NoError(err)
+	should.Equal(`{
+  "2": 2
+}`, string(b))
+
+	cfg = jsoniter.Config{}.Froze() // without testMapKeyExtension
+	b, err = cfg.MarshalIndent(m, "", "  ")
+	should.NoError(err)
+	should.Equal(`{
+  "1": 2
+}`, string(b))
 }
 
 type testMapKeyExtension struct {

From e1382e8d150328ec3d9f5e02b3e7642b1d306983 Mon Sep 17 00:00:00 2001
From: molon <3739161+molon@users.noreply.github.com>
Date: Wed, 28 Sep 2022 13:36:44 +0800
Subject: [PATCH 2/2] getFrozenConfigFromCache use cfgKey instead of
 interface{}

---
 config.go | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/config.go b/config.go
index 6de4d51e..7cd22a4c 100644
--- a/config.go
+++ b/config.go
@@ -113,7 +113,12 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
 
 var cfgCache = concurrent.NewMap()
 
-func getFrozenConfigFromCache(key interface{}) *frozenConfig {
+type cfgKey struct {
+	Config
+	cause *frozenConfig
+}
+
+func getFrozenConfigFromCache(key cfgKey) *frozenConfig {
 	obj, found := cfgCache.Load(key)
 	if found {
 		return obj.(*frozenConfig)
@@ -121,7 +126,7 @@ func getFrozenConfigFromCache(key interface{}) *frozenConfig {
 	return nil
 }
 
-func addFrozenConfigToCache(key interface{}, frozenConfig *frozenConfig) {
+func addFrozenConfigToCache(key cfgKey, frozenConfig *frozenConfig) {
 	cfgCache.Store(key, frozenConfig)
 }
 
@@ -166,13 +171,8 @@ func (cfg Config) Froze() API {
 	return api
 }
 
-type configKey struct {
-	Config
-	cause *frozenConfig
-}
-
 func (cfg Config) frozeWithCacheReuse(cause *frozenConfig) *frozenConfig {
-	key := configKey{cfg, cause}
+	key := cfgKey{cfg, cause}
 	api := getFrozenConfigFromCache(key)
 	if api != nil {
 		return api