goscript 0.0.25 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +259 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +201 -49
  8. package/compiler/compiler_test.go +53 -0
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +83 -0
  12. package/compiler/expr.go +1 -1
  13. package/compiler/protobuf.go +557 -0
  14. package/compiler/spec-struct.go +4 -0
  15. package/compiler/spec-value.go +11 -3
  16. package/compiler/spec.go +18 -1
  17. package/compiler/stmt-assign.go +35 -0
  18. package/compiler/type-assert.go +87 -0
  19. package/compiler/type.go +5 -2
  20. package/dist/gs/builtin/builtin.d.ts +19 -1
  21. package/dist/gs/builtin/builtin.js +85 -5
  22. package/dist/gs/builtin/builtin.js.map +1 -1
  23. package/dist/gs/builtin/channel.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +59 -26
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/cmp/index.js.map +1 -1
  28. package/dist/gs/context/context.d.ts +1 -1
  29. package/dist/gs/context/context.js +20 -11
  30. package/dist/gs/context/context.js.map +1 -1
  31. package/dist/gs/errors/errors.d.ts +7 -0
  32. package/dist/gs/errors/errors.js +190 -0
  33. package/dist/gs/errors/errors.js.map +1 -0
  34. package/dist/gs/errors/index.d.ts +1 -0
  35. package/dist/gs/errors/index.js +2 -0
  36. package/dist/gs/errors/index.js.map +1 -0
  37. package/dist/gs/internal/goarch/index.js +1 -1
  38. package/dist/gs/internal/goarch/index.js.map +1 -1
  39. package/dist/gs/io/index.d.ts +1 -0
  40. package/dist/gs/io/index.js +2 -0
  41. package/dist/gs/io/index.js.map +1 -0
  42. package/dist/gs/io/io.d.ts +107 -0
  43. package/dist/gs/io/io.js +385 -0
  44. package/dist/gs/io/io.js.map +1 -0
  45. package/dist/gs/iter/iter.js.map +1 -1
  46. package/dist/gs/math/bits/index.js +34 -32
  47. package/dist/gs/math/bits/index.js.map +1 -1
  48. package/dist/gs/runtime/runtime.d.ts +1 -0
  49. package/dist/gs/runtime/runtime.js +15 -18
  50. package/dist/gs/runtime/runtime.js.map +1 -1
  51. package/dist/gs/slices/slices.d.ts +1 -1
  52. package/dist/gs/slices/slices.js +1 -1
  53. package/dist/gs/slices/slices.js.map +1 -1
  54. package/dist/gs/strings/builder.d.ts +18 -0
  55. package/dist/gs/strings/builder.js +205 -0
  56. package/dist/gs/strings/builder.js.map +1 -0
  57. package/dist/gs/strings/clone.d.ts +1 -0
  58. package/dist/gs/strings/clone.js +16 -0
  59. package/dist/gs/strings/clone.js.map +1 -0
  60. package/dist/gs/strings/compare.d.ts +1 -0
  61. package/dist/gs/strings/compare.js +14 -0
  62. package/dist/gs/strings/compare.js.map +1 -0
  63. package/dist/gs/strings/index.d.ts +2 -0
  64. package/dist/gs/strings/index.js +3 -0
  65. package/dist/gs/strings/index.js.map +1 -0
  66. package/dist/gs/strings/iter.d.ts +8 -0
  67. package/dist/gs/strings/iter.js +160 -0
  68. package/dist/gs/strings/iter.js.map +1 -0
  69. package/dist/gs/strings/reader.d.ts +34 -0
  70. package/dist/gs/strings/reader.js +418 -0
  71. package/dist/gs/strings/reader.js.map +1 -0
  72. package/dist/gs/strings/replace.d.ts +106 -0
  73. package/dist/gs/strings/replace.js +1136 -0
  74. package/dist/gs/strings/replace.js.map +1 -0
  75. package/dist/gs/strings/search.d.ts +24 -0
  76. package/dist/gs/strings/search.js +169 -0
  77. package/dist/gs/strings/search.js.map +1 -0
  78. package/dist/gs/strings/strings.d.ts +47 -0
  79. package/dist/gs/strings/strings.js +418 -0
  80. package/dist/gs/strings/strings.js.map +1 -0
  81. package/dist/gs/stringslite/index.d.ts +1 -0
  82. package/dist/gs/stringslite/index.js +2 -0
  83. package/dist/gs/stringslite/index.js.map +1 -0
  84. package/dist/gs/stringslite/strings.d.ts +11 -0
  85. package/dist/gs/stringslite/strings.js +67 -0
  86. package/dist/gs/stringslite/strings.js.map +1 -0
  87. package/dist/gs/sync/index.d.ts +1 -0
  88. package/dist/gs/sync/index.js +2 -0
  89. package/dist/gs/sync/index.js.map +1 -0
  90. package/dist/gs/sync/sync.d.ts +79 -0
  91. package/dist/gs/sync/sync.js +392 -0
  92. package/dist/gs/sync/sync.js.map +1 -0
  93. package/dist/gs/time/time.js +7 -7
  94. package/dist/gs/time/time.js.map +1 -1
  95. package/dist/gs/unicode/index.d.ts +1 -0
  96. package/dist/gs/unicode/index.js +2 -0
  97. package/dist/gs/unicode/index.js.map +1 -0
  98. package/dist/gs/unicode/unicode.d.ts +105 -0
  99. package/dist/gs/unicode/unicode.js +332 -0
  100. package/dist/gs/unicode/unicode.js.map +1 -0
  101. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  102. package/dist/gs/unicode/utf8/index.js +3 -0
  103. package/dist/gs/unicode/utf8/index.js.map +1 -0
  104. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  105. package/dist/gs/unicode/utf8/utf8.js +196 -0
  106. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  107. package/dist/gs/unsafe/index.d.ts +1 -0
  108. package/dist/gs/unsafe/index.js +2 -0
  109. package/dist/gs/unsafe/index.js.map +1 -0
  110. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  111. package/dist/gs/unsafe/unsafe.js +44 -0
  112. package/dist/gs/unsafe/unsafe.js.map +1 -0
  113. package/go.mod +2 -1
  114. package/go.sum +6 -2
  115. package/gs/README.md +6 -0
  116. package/gs/builtin/builtin.ts +158 -0
  117. package/gs/builtin/channel.ts +683 -0
  118. package/gs/builtin/defer.ts +58 -0
  119. package/gs/builtin/index.ts +1 -0
  120. package/gs/builtin/io.ts +22 -0
  121. package/gs/builtin/map.ts +50 -0
  122. package/gs/builtin/slice.ts +1030 -0
  123. package/gs/builtin/type.ts +1106 -0
  124. package/gs/builtin/varRef.ts +25 -0
  125. package/gs/cmp/godoc.txt +8 -0
  126. package/gs/cmp/index.ts +29 -0
  127. package/gs/context/context.ts +401 -0
  128. package/gs/context/godoc.txt +69 -0
  129. package/gs/context/index.ts +1 -0
  130. package/gs/errors/errors.ts +223 -0
  131. package/gs/errors/godoc.txt +63 -0
  132. package/gs/errors/index.ts +1 -0
  133. package/gs/internal/goarch/godoc.txt +39 -0
  134. package/gs/internal/goarch/index.ts +18 -0
  135. package/gs/io/godoc.txt +61 -0
  136. package/gs/io/index.ts +1 -0
  137. package/gs/io/io.go +75 -0
  138. package/gs/io/io.ts +546 -0
  139. package/gs/iter/godoc.txt +203 -0
  140. package/gs/iter/index.ts +1 -0
  141. package/gs/iter/iter.ts +117 -0
  142. package/gs/math/bits/index.ts +356 -0
  143. package/gs/math/godoc.txt +76 -0
  144. package/gs/runtime/godoc.txt +331 -0
  145. package/gs/runtime/index.ts +1 -0
  146. package/gs/runtime/runtime.ts +178 -0
  147. package/gs/slices/godoc.txt +44 -0
  148. package/gs/slices/index.ts +1 -0
  149. package/gs/slices/slices.ts +22 -0
  150. package/gs/strings/builder.test.ts +121 -0
  151. package/gs/strings/builder.ts +223 -0
  152. package/gs/strings/clone.test.ts +43 -0
  153. package/gs/strings/clone.ts +17 -0
  154. package/gs/strings/compare.test.ts +84 -0
  155. package/gs/strings/compare.ts +13 -0
  156. package/gs/strings/godoc.txt +66 -0
  157. package/gs/strings/index.ts +2 -0
  158. package/gs/strings/iter.test.ts +343 -0
  159. package/gs/strings/iter.ts +171 -0
  160. package/gs/strings/reader.test.ts +243 -0
  161. package/gs/strings/reader.ts +451 -0
  162. package/gs/strings/replace.test.ts +181 -0
  163. package/gs/strings/replace.ts +1310 -0
  164. package/gs/strings/search.test.ts +214 -0
  165. package/gs/strings/search.ts +213 -0
  166. package/gs/strings/strings.test.ts +477 -0
  167. package/gs/strings/strings.ts +510 -0
  168. package/gs/stringslite/godoc.txt +17 -0
  169. package/gs/stringslite/index.ts +1 -0
  170. package/gs/stringslite/strings.ts +82 -0
  171. package/gs/sync/godoc.txt +21 -0
  172. package/gs/sync/index.ts +1 -0
  173. package/gs/sync/sync.go +64 -0
  174. package/gs/sync/sync.ts +449 -0
  175. package/gs/time/godoc.md +116 -0
  176. package/gs/time/godoc.txt +116 -0
  177. package/gs/time/index.ts +1 -0
  178. package/gs/time/time.ts +272 -0
  179. package/gs/unicode/godoc.txt +52 -0
  180. package/gs/unicode/index.ts +1 -0
  181. package/gs/unicode/unicode.go +38 -0
  182. package/gs/unicode/unicode.ts +418 -0
  183. package/gs/unicode/utf8/godoc.txt +22 -0
  184. package/gs/unicode/utf8/index.ts +2 -0
  185. package/gs/unicode/utf8/utf8.ts +227 -0
  186. package/gs/unsafe/godoc.txt +19 -0
  187. package/gs/unsafe/index.ts +1 -0
  188. package/gs/unsafe/unsafe.test.ts +68 -0
  189. package/gs/unsafe/unsafe.ts +77 -0
  190. package/package.json +6 -4
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import * as $ from '@goscript/builtin/builtin.js'
3
+ import { Builder } from './builder.js'
4
+
5
+ describe('strings/Builder', () => {
6
+ describe('Builder', () => {
7
+ it('should create empty builder', () => {
8
+ const b = new Builder()
9
+ expect(b.String()).toBe('')
10
+ expect(b.Len()).toBe(0)
11
+ expect(b.Cap()).toBe(0)
12
+ })
13
+
14
+ it('should write string', () => {
15
+ const b = new Builder()
16
+ const [n, err] = b.WriteString('hello')
17
+ expect(n).toBe(5)
18
+ expect(err).toBeNull()
19
+ expect(b.String()).toBe('hello')
20
+ expect(b.Len()).toBe(5)
21
+ })
22
+
23
+ it('should write bytes', () => {
24
+ const b = new Builder()
25
+ const bytes = new TextEncoder().encode('world')
26
+ const [n, err] = b.Write(bytes)
27
+ expect(n).toBe(bytes.length)
28
+ expect(err).toBeNull()
29
+ expect(b.String()).toBe('world')
30
+ })
31
+
32
+ it('should write byte', () => {
33
+ const b = new Builder()
34
+ const err = b.WriteByte(65) // 'A'
35
+ expect(err).toBeNull()
36
+ expect(b.String()).toBe('A')
37
+ expect(b.Len()).toBe(1)
38
+ })
39
+
40
+ it('should write rune', () => {
41
+ const b = new Builder()
42
+ const [n, err] = b.WriteRune(0x1f44d) // 👍
43
+ expect(err).toBeNull()
44
+ expect(n).toBeGreaterThan(0)
45
+ expect(b.String()).toBe('👍')
46
+ })
47
+
48
+ it('should grow capacity', () => {
49
+ const b = new Builder()
50
+ b.Grow(100)
51
+ // Should not throw - capacity is grown
52
+ expect(b.Cap()).toBeGreaterThanOrEqual(0)
53
+ })
54
+
55
+ it('should throw on negative grow', () => {
56
+ const b = new Builder()
57
+ expect(() => b.Grow(-1)).toThrow()
58
+ })
59
+
60
+ it('should reset builder', () => {
61
+ const b = new Builder()
62
+ b.WriteString('hello')
63
+ expect(b.Len()).toBe(5)
64
+
65
+ b.Reset()
66
+ expect(b.String()).toBe('')
67
+ expect(b.Len()).toBe(0)
68
+ })
69
+
70
+ it('should clone builder', () => {
71
+ const b = new Builder()
72
+ b.WriteString('hello')
73
+
74
+ const cloned = b.clone()
75
+ expect(cloned.String()).toBe('hello')
76
+ expect(cloned.Len()).toBe(5)
77
+
78
+ // Modify original
79
+ b.WriteString(' world')
80
+ expect(b.String()).toBe('hello world')
81
+ expect(cloned.String()).toBe('hello') // Should not change
82
+ })
83
+
84
+ it('should handle multiple writes', () => {
85
+ const b = new Builder()
86
+ b.WriteString('hello')
87
+ b.WriteString(' ')
88
+ b.WriteString('world')
89
+ expect(b.String()).toBe('hello world')
90
+ expect(b.Len()).toBe(11)
91
+ })
92
+
93
+ it('should handle empty writes', () => {
94
+ const b = new Builder()
95
+ const [n, err] = b.WriteString('')
96
+ expect(n).toBe(0)
97
+ expect(err).toBeNull()
98
+ expect(b.String()).toBe('')
99
+ })
100
+
101
+ it('should handle unicode correctly', () => {
102
+ const b = new Builder()
103
+ b.WriteString('Hello 世界')
104
+ expect(b.String()).toBe('Hello 世界')
105
+
106
+ // Write individual runes
107
+ const b2 = new Builder()
108
+ b2.WriteRune(0x4e16) // 世
109
+ b2.WriteRune(0x754c) // 界
110
+ expect(b2.String()).toBe('世界')
111
+ })
112
+
113
+ it('should maintain proper length with unicode', () => {
114
+ const b = new Builder()
115
+ const text = 'Hello 🌟'
116
+ b.WriteString(text)
117
+ expect(b.String()).toBe(text)
118
+ expect(b.Len()).toBe(text.length)
119
+ })
120
+ })
121
+ })
@@ -0,0 +1,223 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+
3
+ export class Builder {
4
+ private _content: string = ''
5
+ private _addr: Builder | null = null
6
+
7
+ constructor(init?: Partial<{}>) {
8
+ // Simple constructor - no complex initialization needed
9
+ }
10
+
11
+ public clone(): Builder {
12
+ const cloned = new Builder()
13
+ cloned._content = this._content
14
+ cloned._addr = this._addr
15
+ return cloned
16
+ }
17
+
18
+ private copyCheck(): void {
19
+ if (this._addr == null) {
20
+ this._addr = this
21
+ } else if (this._addr !== this) {
22
+ $.panic('strings: illegal use of non-zero Builder copied by value')
23
+ }
24
+ }
25
+
26
+ // String returns the accumulated string.
27
+ public String(): string {
28
+ return this._content
29
+ }
30
+
31
+ // Len returns the number of accumulated bytes; b.Len() == len(b.String()).
32
+ public Len(): number {
33
+ return this._content.length
34
+ }
35
+
36
+ // Cap returns the capacity of the builder's underlying byte slice. It is the
37
+ // total space allocated for the string being built and includes any bytes
38
+ // already written.
39
+ public Cap(): number {
40
+ // For simplicity, return the current length since JavaScript strings are dynamic
41
+ return this._content.length
42
+ }
43
+
44
+ // Reset resets the Builder to be empty.
45
+ public Reset(): void {
46
+ this._addr = null
47
+ this._content = ''
48
+ }
49
+
50
+ // Grow grows b's capacity, if necessary, to guarantee space for
51
+ // another n bytes. After Grow(n), at least n bytes can be written to b
52
+ // without another allocation. If n is negative, Grow panics.
53
+ public Grow(n: number): void {
54
+ this.copyCheck()
55
+ if (n < 0) {
56
+ $.panic('strings.Builder.Grow: negative count')
57
+ }
58
+ // JavaScript strings are dynamic, so no need to pre-allocate
59
+ }
60
+
61
+ // Write appends the contents of p to b's buffer.
62
+ // Write always returns len(p), nil.
63
+ public Write(p: Uint8Array): [number, $.GoError] {
64
+ this.copyCheck()
65
+ // Convert byte array to string
66
+ const str = new TextDecoder('utf-8').decode(p)
67
+ this._content += str
68
+ return [p.length, null]
69
+ }
70
+
71
+ // WriteByte appends the byte c to b's buffer.
72
+ // The returned error is always nil.
73
+ public WriteByte(c: number): $.GoError {
74
+ this.copyCheck()
75
+ this._content += String.fromCharCode(c)
76
+ return null
77
+ }
78
+
79
+ // WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer.
80
+ // It returns the length of r and a nil error.
81
+ public WriteRune(r: number): [number, $.GoError] {
82
+ this.copyCheck()
83
+ const str = String.fromCodePoint(r)
84
+ this._content += str
85
+ // Return the byte length of the UTF-8 encoding
86
+ const byteLength = new TextEncoder().encode(str).length
87
+ return [byteLength, null]
88
+ }
89
+
90
+ // WriteString appends the contents of s to b's buffer.
91
+ // It returns the length of s and a nil error.
92
+ public WriteString(s: string): [number, $.GoError] {
93
+ this.copyCheck()
94
+ this._content += s
95
+ return [s.length, null]
96
+ }
97
+
98
+ // Register this type with the runtime type system
99
+ static __typeInfo = $.registerStructType(
100
+ 'Builder',
101
+ new Builder(),
102
+ [
103
+ {
104
+ name: 'String',
105
+ args: [],
106
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
107
+ },
108
+ {
109
+ name: 'Len',
110
+ args: [],
111
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'number' } }],
112
+ },
113
+ {
114
+ name: 'Cap',
115
+ args: [],
116
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'number' } }],
117
+ },
118
+ { name: 'Reset', args: [], returns: [] },
119
+ {
120
+ name: 'Grow',
121
+ args: [{ name: 'n', type: { kind: $.TypeKind.Basic, name: 'number' } }],
122
+ returns: [],
123
+ },
124
+ {
125
+ name: 'Write',
126
+ args: [
127
+ {
128
+ name: 'p',
129
+ type: {
130
+ kind: $.TypeKind.Slice,
131
+ elemType: { kind: $.TypeKind.Basic, name: 'number' },
132
+ },
133
+ },
134
+ ],
135
+ returns: [
136
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
137
+ {
138
+ type: {
139
+ kind: $.TypeKind.Interface,
140
+ name: 'GoError',
141
+ methods: [
142
+ {
143
+ name: 'Error',
144
+ args: [],
145
+ returns: [
146
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
147
+ ],
148
+ },
149
+ ],
150
+ },
151
+ },
152
+ ],
153
+ },
154
+ {
155
+ name: 'WriteByte',
156
+ args: [{ name: 'c', type: { kind: $.TypeKind.Basic, name: 'number' } }],
157
+ returns: [
158
+ {
159
+ type: {
160
+ kind: $.TypeKind.Interface,
161
+ name: 'GoError',
162
+ methods: [
163
+ {
164
+ name: 'Error',
165
+ args: [],
166
+ returns: [
167
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
168
+ ],
169
+ },
170
+ ],
171
+ },
172
+ },
173
+ ],
174
+ },
175
+ {
176
+ name: 'WriteRune',
177
+ args: [{ name: 'r', type: { kind: $.TypeKind.Basic, name: 'number' } }],
178
+ returns: [
179
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
180
+ {
181
+ type: {
182
+ kind: $.TypeKind.Interface,
183
+ name: 'GoError',
184
+ methods: [
185
+ {
186
+ name: 'Error',
187
+ args: [],
188
+ returns: [
189
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
190
+ ],
191
+ },
192
+ ],
193
+ },
194
+ },
195
+ ],
196
+ },
197
+ {
198
+ name: 'WriteString',
199
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
200
+ returns: [
201
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
202
+ {
203
+ type: {
204
+ kind: $.TypeKind.Interface,
205
+ name: 'GoError',
206
+ methods: [
207
+ {
208
+ name: 'Error',
209
+ args: [],
210
+ returns: [
211
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
212
+ ],
213
+ },
214
+ ],
215
+ },
216
+ },
217
+ ],
218
+ },
219
+ ],
220
+ Builder,
221
+ {},
222
+ )
223
+ }
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { Clone } from './clone.js'
3
+
4
+ describe('strings/clone', () => {
5
+ describe('Clone', () => {
6
+ it('should return a copy of the string', () => {
7
+ expect(Clone('hello')).toBe('hello')
8
+ expect(Clone('world')).toBe('world')
9
+ })
10
+
11
+ it('should handle empty string', () => {
12
+ expect(Clone('')).toBe('')
13
+ })
14
+
15
+ it('should handle unicode strings', () => {
16
+ expect(Clone('Hello 世界')).toBe('Hello 世界')
17
+ expect(Clone('🌟⭐✨')).toBe('🌟⭐✨')
18
+ })
19
+
20
+ it('should handle strings with special characters', () => {
21
+ expect(Clone('Hello\nWorld\t!')).toBe('Hello\nWorld\t!')
22
+ expect(Clone('quotes"and\'stuff')).toBe('quotes"and\'stuff')
23
+ })
24
+
25
+ it('should handle long strings', () => {
26
+ const longString = 'a'.repeat(10000)
27
+ expect(Clone(longString)).toBe(longString)
28
+ })
29
+
30
+ it('should handle strings with null bytes', () => {
31
+ const stringWithNull = 'hello\0world'
32
+ expect(Clone(stringWithNull)).toBe(stringWithNull)
33
+ })
34
+
35
+ it('should create independent copy semantically', () => {
36
+ const original = 'test string'
37
+ const cloned = Clone(original)
38
+ expect(cloned).toBe(original)
39
+ // In JavaScript, strings are immutable, so this is the expected behavior
40
+ // The clone function maintains Go semantics where it guarantees a new allocation
41
+ })
42
+ })
43
+ })
@@ -0,0 +1,17 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+
3
+ // Clone returns a fresh copy of s.
4
+ // It guarantees to make a copy of s into a new allocation,
5
+ // which can be important when retaining only a small substring
6
+ // of a much larger string. Using Clone can help such programs
7
+ // use less memory. Of course, since using Clone makes a copy,
8
+ // overuse of Clone can make programs use more memory.
9
+ // Clone should typically be used only rarely, and only when
10
+ // profiling indicates that it is needed.
11
+ // For strings of length zero the string "" will be returned
12
+ // and no allocation is made.
13
+ export function Clone(s: string): string {
14
+ // In JavaScript, strings are immutable, so we can just return the string
15
+ // But to match Go semantics, we'll create a new string
16
+ return String(s)
17
+ }
@@ -0,0 +1,84 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { Compare } from './compare.js'
3
+
4
+ describe('strings/compare', () => {
5
+ describe('Compare', () => {
6
+ it('should return 0 for equal strings', () => {
7
+ expect(Compare('hello', 'hello')).toBe(0)
8
+ expect(Compare('', '')).toBe(0)
9
+ expect(Compare('world', 'world')).toBe(0)
10
+ })
11
+
12
+ it('should return -1 when first string is lexicographically smaller', () => {
13
+ expect(Compare('a', 'b')).toBe(-1)
14
+ expect(Compare('abc', 'abd')).toBe(-1)
15
+ expect(Compare('hello', 'world')).toBe(-1)
16
+ expect(Compare('', 'a')).toBe(-1)
17
+ })
18
+
19
+ it('should return 1 when first string is lexicographically larger', () => {
20
+ expect(Compare('b', 'a')).toBe(1)
21
+ expect(Compare('abd', 'abc')).toBe(1)
22
+ expect(Compare('world', 'hello')).toBe(1)
23
+ expect(Compare('a', '')).toBe(1)
24
+ })
25
+
26
+ it('should handle strings of different lengths', () => {
27
+ expect(Compare('abc', 'abcd')).toBe(-1)
28
+ expect(Compare('abcd', 'abc')).toBe(1)
29
+ expect(Compare('ab', 'abc')).toBe(-1)
30
+ expect(Compare('abc', 'ab')).toBe(1)
31
+ })
32
+
33
+ it('should handle case sensitivity', () => {
34
+ expect(Compare('a', 'A')).toBe(1) // lowercase > uppercase
35
+ expect(Compare('A', 'a')).toBe(-1)
36
+ expect(Compare('Hello', 'hello')).toBe(-1)
37
+ })
38
+
39
+ it('should handle unicode strings', () => {
40
+ expect(Compare('世界', '世界')).toBe(0)
41
+ expect(Compare('世', '界')).toBeLessThan(0)
42
+ expect(Compare('🌟', '⭐')).toBeGreaterThan(0)
43
+ })
44
+
45
+ it('should handle special characters', () => {
46
+ expect(Compare('!', '@')).toBe(-1)
47
+ expect(Compare('@', '!')).toBe(1)
48
+ expect(Compare('123', '456')).toBe(-1)
49
+ expect(Compare('9', '10')).toBe(1) // string comparison, not numeric
50
+ })
51
+
52
+ it('should handle strings with spaces', () => {
53
+ expect(Compare(' ', '')).toBe(1)
54
+ expect(Compare('', ' ')).toBe(-1)
55
+ expect(Compare('a b', 'ab')).toBe(-1) // space < 'b'
56
+ })
57
+
58
+ it('should handle mixed content', () => {
59
+ expect(Compare('abc123', 'abc456')).toBe(-1)
60
+ expect(Compare('Hello World', 'Hello world')).toBe(-1) // 'W' < 'w'
61
+ expect(Compare('test\n', 'test\t')).toBe(1) // '\n' > '\t' (10 > 9)
62
+ })
63
+
64
+ it('should be consistent with built-in comparison', () => {
65
+ const testCases = [
66
+ ['hello', 'world'],
67
+ ['abc', 'abc'],
68
+ ['a', 'b'],
69
+ ['', ''],
70
+ ['longer', 'short'],
71
+ ['123', '45'],
72
+ ]
73
+
74
+ testCases.forEach(([a, b]) => {
75
+ const compareResult = Compare(a, b)
76
+ const builtinResult =
77
+ a < b ? -1
78
+ : a > b ? 1
79
+ : 0
80
+ expect(compareResult).toBe(builtinResult)
81
+ })
82
+ })
83
+ })
84
+ })
@@ -0,0 +1,13 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+
3
+ // Compare returns an integer comparing two strings lexicographically.
4
+ // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
5
+ //
6
+ // Compare is included only for symmetry with package bytes.
7
+ // It is usually clearer and always faster to use the built-in
8
+ // string comparison operators ==, <, >, and so on.
9
+ export function Compare(a: string, b: string): number {
10
+ if (a < b) return -1
11
+ if (a > b) return 1
12
+ return 0
13
+ }
@@ -0,0 +1,66 @@
1
+ package strings // import "strings"
2
+
3
+ Package strings implements simple functions to manipulate UTF-8 encoded strings.
4
+
5
+ For information about UTF-8 strings in Go, see https://blog.golang.org/strings.
6
+
7
+ func Clone(s string) string
8
+ func Compare(a, b string) int
9
+ func Contains(s, substr string) bool
10
+ func ContainsAny(s, chars string) bool
11
+ func ContainsFunc(s string, f func(rune) bool) bool
12
+ func ContainsRune(s string, r rune) bool
13
+ func Count(s, substr string) int
14
+ func Cut(s, sep string) (before, after string, found bool)
15
+ func CutPrefix(s, prefix string) (after string, found bool)
16
+ func CutSuffix(s, suffix string) (before string, found bool)
17
+ func EqualFold(s, t string) bool
18
+ func Fields(s string) []string
19
+ func FieldsFunc(s string, f func(rune) bool) []string
20
+ func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string]
21
+ func FieldsSeq(s string) iter.Seq[string]
22
+ func HasPrefix(s, prefix string) bool
23
+ func HasSuffix(s, suffix string) bool
24
+ func Index(s, substr string) int
25
+ func IndexAny(s, chars string) int
26
+ func IndexByte(s string, c byte) int
27
+ func IndexFunc(s string, f func(rune) bool) int
28
+ func IndexRune(s string, r rune) int
29
+ func Join(elems []string, sep string) string
30
+ func LastIndex(s, substr string) int
31
+ func LastIndexAny(s, chars string) int
32
+ func LastIndexByte(s string, c byte) int
33
+ func LastIndexFunc(s string, f func(rune) bool) int
34
+ func Lines(s string) iter.Seq[string]
35
+ func Map(mapping func(rune) rune, s string) string
36
+ func Repeat(s string, count int) string
37
+ func Replace(s, old, new string, n int) string
38
+ func ReplaceAll(s, old, new string) string
39
+ func Split(s, sep string) []string
40
+ func SplitAfter(s, sep string) []string
41
+ func SplitAfterN(s, sep string, n int) []string
42
+ func SplitAfterSeq(s, sep string) iter.Seq[string]
43
+ func SplitN(s, sep string, n int) []string
44
+ func SplitSeq(s, sep string) iter.Seq[string]
45
+ func Title(s string) string
46
+ func ToLower(s string) string
47
+ func ToLowerSpecial(c unicode.SpecialCase, s string) string
48
+ func ToTitle(s string) string
49
+ func ToTitleSpecial(c unicode.SpecialCase, s string) string
50
+ func ToUpper(s string) string
51
+ func ToUpperSpecial(c unicode.SpecialCase, s string) string
52
+ func ToValidUTF8(s, replacement string) string
53
+ func Trim(s, cutset string) string
54
+ func TrimFunc(s string, f func(rune) bool) string
55
+ func TrimLeft(s, cutset string) string
56
+ func TrimLeftFunc(s string, f func(rune) bool) string
57
+ func TrimPrefix(s, prefix string) string
58
+ func TrimRight(s, cutset string) string
59
+ func TrimRightFunc(s string, f func(rune) bool) string
60
+ func TrimSpace(s string) string
61
+ func TrimSuffix(s, suffix string) string
62
+ type Builder struct{ ... }
63
+ type Reader struct{ ... }
64
+ func NewReader(s string) *Reader
65
+ type Replacer struct{ ... }
66
+ func NewReplacer(oldnew ...string) *Replacer
@@ -0,0 +1,2 @@
1
+ export * from './builder.js'
2
+ export * from './strings.js'