@@ -73,3 +73,48 @@ func Clone(s string) string {
73
73
// memory overheads and simply return the string as-is.
74
74
return s
75
75
}
76
+
77
+ // Repeat is the go1.19 implementation of strings.Repeat.
78
+ //
79
+ // In the go1.20 implementation, the function was changed to use chunks that
80
+ // are 8KB in size to improve speed and cache access. This change is faster
81
+ // when running native Go code. However, for GopherJS, the change is much
82
+ // slower than the go1.19 implementation.
83
+ //
84
+ // The go1.20 change made tests like encoding/pem TestCVE202224675 take
85
+ // significantly longer to run for GopherJS.
86
+ // go1.19 concatenates 24 times and the test takes about 8 seconds.
87
+ // go1.20 concatenates about 15000 times and can take over a hour.
88
+ //
89
+ // We can't use `js.InternalObject(s).Call("repeat", count).String()`
90
+ // because JS performs additional UTF-8 escapes meaning tests like
91
+ // hash/adler32 TestGolden will fail because the wrong input is created.
92
+ func Repeat (s string , count int ) string {
93
+ if count == 0 {
94
+ return ""
95
+ }
96
+
97
+ // Since we cannot return an error on overflow,
98
+ // we should panic if the repeat will generate
99
+ // an overflow.
100
+ // See Issue golang.org/issue/16237
101
+ if count < 0 {
102
+ panic ("strings: negative Repeat count" )
103
+ } else if len (s )* count / count != len (s ) {
104
+ panic ("strings: Repeat count causes overflow" )
105
+ }
106
+
107
+ n := len (s ) * count
108
+ var b Builder
109
+ b .Grow (n )
110
+ b .WriteString (s )
111
+ for b .Len () < n {
112
+ if b .Len () <= n / 2 {
113
+ b .WriteString (b .String ())
114
+ } else {
115
+ b .WriteString (b .String ()[:n - b .Len ()])
116
+ break
117
+ }
118
+ }
119
+ return b .String ()
120
+ }
0 commit comments