gofront 1.7.0 → 1.8.0

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 (128) hide show
  1. package/README.md +13 -13
  2. package/package.json +8 -37
  3. package/src/backend/js/expressions.js +1341 -148
  4. package/src/backend/js/fmt-runtime.js +573 -0
  5. package/src/backend/js/index.js +375 -57
  6. package/src/backend/js/runtime.js +1460 -133
  7. package/src/backend/js/statements.js +900 -86
  8. package/src/backend/js/stdlib/bits.js +87 -14
  9. package/src/backend/js/stdlib/builder.js +41 -6
  10. package/src/backend/js/stdlib/bytes.js +253 -7
  11. package/src/backend/js/stdlib/errors.js +2 -1
  12. package/src/backend/js/stdlib/fmt.js +349 -10
  13. package/src/backend/js/stdlib/index.js +8 -3
  14. package/src/backend/js/stdlib/json.js +247 -52
  15. package/src/backend/js/stdlib/maps.js +0 -8
  16. package/src/backend/js/stdlib/math.js +17 -1
  17. package/src/backend/js/stdlib/simd.js +10 -0
  18. package/src/backend/js/stdlib/slices.js +36 -6
  19. package/src/backend/js/stdlib/strconv.js +10 -5
  20. package/src/backend/js/stdlib/strings.js +83 -4
  21. package/src/backend/js/stdlib/testing.js +7 -0
  22. package/src/backend/js/stdlib/time.js +79 -55
  23. package/src/backend/js/stdlib/unicode.js +1 -1
  24. package/src/backend/js/stdlib/utf8.js +1 -1
  25. package/src/backend/js/templ.js +38 -76
  26. package/src/backend/js/type-info.js +272 -0
  27. package/src/backend/shared/fmt-types.js +188 -0
  28. package/src/backend/wasm/boundary.js +436 -80
  29. package/src/backend/wasm/emit-builtins.js +303 -13
  30. package/src/backend/wasm/emit-exprs.js +1397 -203
  31. package/src/backend/wasm/emit-maps.js +61 -13
  32. package/src/backend/wasm/emit-stmts.js +1359 -164
  33. package/src/backend/wasm/emit.js +512 -77
  34. package/src/backend/wasm/encode.js +43 -13
  35. package/src/backend/wasm/globals.js +452 -0
  36. package/src/backend/wasm/index.js +194 -2489
  37. package/src/backend/wasm/method-expr.js +381 -0
  38. package/src/backend/wasm/module-emitter.js +2240 -0
  39. package/src/backend/wasm/monomorph.js +62 -4
  40. package/src/backend/wasm/prescan.js +397 -0
  41. package/src/backend/wasm/stdlib/bytes.js +1804 -127
  42. package/src/backend/wasm/stdlib/core.js +1574 -199
  43. package/src/backend/wasm/stdlib/index.js +0 -5
  44. package/src/backend/wasm/stdlib/io.js +1567 -150
  45. package/src/backend/wasm/stdlib/packages.js +2 -0
  46. package/src/backend/wasm/stdlib/simd.js +293 -28
  47. package/src/backend/wasm/stdlib/time.js +1041 -12
  48. package/src/backend/wasm/types.js +200 -15
  49. package/src/backend/wasm/variadic.js +93 -0
  50. package/src/backend/wasm/wat.js +47 -20
  51. package/src/{cli-core.js → cli/cli-core.js} +236 -10
  52. package/src/{test-runner.js → cli/test-runner.js} +332 -39
  53. package/src/{vendor.js → cli/vendor.js} +3 -4
  54. package/src/compiler.js +107 -269
  55. package/src/index.js +15 -169
  56. package/src/{lexer.js → lexer/lexer.js} +102 -55
  57. package/src/{tokens.js → lexer/tokens.js} +1 -0
  58. package/src/link/sourcemap.js +97 -0
  59. package/src/link/stdlib.js +515 -0
  60. package/src/link/wasm.js +294 -0
  61. package/src/lower/bounds.js +394 -0
  62. package/src/lower/boxing.js +1 -1
  63. package/src/lower/captures.js +176 -32
  64. package/src/lower/index.js +26 -18
  65. package/src/lower/json-codecs.js +1398 -0
  66. package/src/lower/ownership.js +22 -1
  67. package/src/lower/range.js +86 -1
  68. package/src/lower/reachability.js +132 -0
  69. package/src/parser/declarations.js +58 -13
  70. package/src/parser/expressions.js +29 -7
  71. package/src/parser/index.js +2 -1
  72. package/src/parser/statements.js +37 -22
  73. package/src/{templ-parser.js → parser/templ.js} +138 -15
  74. package/src/parser/types.js +69 -9
  75. package/src/resolver.js +22 -1
  76. package/src/typechecker/assignability.js +176 -17
  77. package/src/typechecker/const-fold.js +356 -0
  78. package/src/typechecker/constants.js +256 -0
  79. package/src/typechecker/expressions.js +931 -122
  80. package/src/typechecker/index.js +459 -67
  81. package/src/typechecker/init-order.js +330 -0
  82. package/src/typechecker/resolve.js +451 -56
  83. package/src/typechecker/statements.js +90 -9
  84. package/src/typechecker/stdlib/core.js +333 -55
  85. package/src/typechecker/stdlib/excluded.js +898 -0
  86. package/src/typechecker/stdlib/extended.js +322 -26
  87. package/src/typechecker/{stdlib.js → stdlib/index.js} +5 -5
  88. package/src/typechecker/stdlib/simd.js +65 -15
  89. package/src/typechecker/termination.js +1 -1
  90. package/src/typechecker/types.js +149 -25
  91. package/stdlib/bytes/iter.go +192 -0
  92. package/stdlib/bytes/search.go +240 -0
  93. package/stdlib/bytes/split.go +218 -0
  94. package/stdlib/cmp/cmp.go +65 -0
  95. package/stdlib/encoding/json/errors.go +31 -0
  96. package/stdlib/encoding/json/indent.go +71 -0
  97. package/stdlib/encoding/json/number.go +12 -0
  98. package/stdlib/encoding/json/stream.go +173 -0
  99. package/stdlib/errors/overlay.go +12 -0
  100. package/stdlib/hash/hash.go +53 -0
  101. package/stdlib/internal/jsonrt/dec.go +738 -0
  102. package/stdlib/internal/jsonrt/enc.go +366 -0
  103. package/stdlib/internal/jsonrt/indent.go +135 -0
  104. package/stdlib/internal/jsonrt/number.go +27 -0
  105. package/stdlib/internal/jsonrt/reader.go +73 -0
  106. package/stdlib/internal/jsonrt/scanner.go +649 -0
  107. package/stdlib/io/io.go +346 -0
  108. package/stdlib/iter/iter.go +18 -0
  109. package/stdlib/maps/iter.go +65 -0
  110. package/stdlib/math/extra.go +270 -0
  111. package/stdlib/slices/extra.go +73 -0
  112. package/stdlib/slices/iter.go +113 -0
  113. package/stdlib/sort/sort.go +561 -0
  114. package/stdlib/strconv/quote.go +341 -0
  115. package/stdlib/strings/extra.go +35 -0
  116. package/stdlib/strings/iter.go +122 -0
  117. package/stdlib/sync/extra.go +105 -0
  118. package/stdlib/unicode/unicode.go +112 -0
  119. package/stdlib/unicode/utf8/bytes.go +239 -0
  120. package/src/backend/wasm/const-fold.js +0 -205
  121. package/src/backend/wasm/emit-stdlib.js +0 -13
  122. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  123. /package/src/{colors.js → cli/colors.js} +0 -0
  124. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  125. /package/src/{minifier.js → cli/minifier.js} +0 -0
  126. /package/src/{project-config.js → cli/project-config.js} +0 -0
  127. /package/src/{pwa.js → cli/pwa.js} +0 -0
  128. /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
@@ -0,0 +1,240 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed bytes package: search and comparison members
6
+ // written in Go and merged into the bytes namespace. They work on byte
7
+ // offsets and decode UTF-8 as Go does, so an invalid sequence reads as
8
+ // (RuneError, 1).
9
+ package bytes
10
+
11
+ import "unicode"
12
+
13
+ // decodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and
14
+ // its width in bytes, as utf8.DecodeLastRune does: an invalid or incomplete
15
+ // encoding is (RuneError, 1) and p must not be empty.
16
+ func decodeLastRune(p []byte) (rune, int) {
17
+ end := len(p)
18
+ r := rune(p[end-1])
19
+ if r < runeSelf {
20
+ return r, 1
21
+ }
22
+ start := end - 1
23
+ lim := end - 4
24
+ if lim < 0 {
25
+ lim = 0
26
+ }
27
+ for start--; start >= lim; start-- {
28
+ if p[start]&0xC0 != 0x80 {
29
+ break
30
+ }
31
+ }
32
+ if start < 0 {
33
+ start = 0
34
+ }
35
+ r, size := decodeRune(p[start:end])
36
+ if start+size != end {
37
+ return runeError, 1
38
+ }
39
+ return r, size
40
+ }
41
+
42
+ // Compare returns an integer comparing two byte slices lexicographically.
43
+ // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
44
+ // A nil argument is equivalent to an empty slice.
45
+ func Compare(a, b []byte) int {
46
+ n := len(a)
47
+ if len(b) < n {
48
+ n = len(b)
49
+ }
50
+ for i := 0; i < n; i++ {
51
+ if a[i] != b[i] {
52
+ if a[i] < b[i] {
53
+ return -1
54
+ }
55
+ return 1
56
+ }
57
+ }
58
+ if len(a) < len(b) {
59
+ return -1
60
+ }
61
+ if len(a) > len(b) {
62
+ return 1
63
+ }
64
+ return 0
65
+ }
66
+
67
+ // EqualFold reports whether s and t, interpreted as UTF-8 strings,
68
+ // are equal under simple Unicode case-folding, which is a more general
69
+ // form of case-insensitivity.
70
+ func EqualFold(s, t []byte) bool {
71
+ for len(s) != 0 && len(t) != 0 {
72
+ var sr, tr rune
73
+ if s[0] < runeSelf {
74
+ sr, s = rune(s[0]), s[1:]
75
+ } else {
76
+ r, size := decodeRune(s)
77
+ sr, s = r, s[size:]
78
+ }
79
+ if t[0] < runeSelf {
80
+ tr, t = rune(t[0]), t[1:]
81
+ } else {
82
+ r, size := decodeRune(t)
83
+ tr, t = r, t[size:]
84
+ }
85
+ if tr == sr {
86
+ continue
87
+ }
88
+ if tr < sr {
89
+ tr, sr = sr, tr
90
+ }
91
+ if tr < runeSelf {
92
+ if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
93
+ continue
94
+ }
95
+ return false
96
+ }
97
+ r := unicode.SimpleFold(sr)
98
+ for r != sr && r < tr {
99
+ r = unicode.SimpleFold(r)
100
+ }
101
+ if r == tr {
102
+ continue
103
+ }
104
+ return false
105
+ }
106
+ return len(s) == len(t)
107
+ }
108
+
109
+ // IndexRune interprets s as a sequence of UTF-8-encoded code points.
110
+ // It returns the byte index of the first occurrence in s of the given rune.
111
+ // It returns -1 if rune is not present in s.
112
+ // If r is utf8.RuneError, it returns the first instance of any
113
+ // invalid UTF-8 byte sequence.
114
+ func IndexRune(s []byte, r rune) int {
115
+ if r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF) {
116
+ return -1
117
+ }
118
+ if r < runeSelf {
119
+ return IndexByte(s, int(r))
120
+ }
121
+ for i := 0; i < len(s); {
122
+ c, size := decodeRune(s[i:])
123
+ if c == r {
124
+ return i
125
+ }
126
+ i += size
127
+ }
128
+ return -1
129
+ }
130
+
131
+ // containsRuneIn reports whether chars contains r, treating an invalid sequence
132
+ // in chars as utf8.RuneError.
133
+ func containsRuneIn(chars string, r rune) bool {
134
+ for _, c := range chars {
135
+ if c == r {
136
+ return true
137
+ }
138
+ }
139
+ return false
140
+ }
141
+
142
+ // IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
143
+ // It returns the byte index of the first occurrence in s of any of the Unicode
144
+ // code points in chars. It returns -1 if chars is empty or if there is no code
145
+ // point in common.
146
+ func IndexAny(s []byte, chars string) int {
147
+ if len(chars) == 0 {
148
+ return -1
149
+ }
150
+ for i := 0; i < len(s); {
151
+ r, size := decodeRune(s[i:])
152
+ if containsRuneIn(chars, r) {
153
+ return i
154
+ }
155
+ i += size
156
+ }
157
+ return -1
158
+ }
159
+
160
+ // LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
161
+ // points. It returns the byte index of the last occurrence in s of any of
162
+ // the Unicode code points in chars. It returns -1 if chars is empty or if
163
+ // there is no code point in common.
164
+ func LastIndexAny(s []byte, chars string) int {
165
+ if len(chars) == 0 {
166
+ return -1
167
+ }
168
+ for i := len(s); i > 0; {
169
+ r, size := decodeLastRune(s[:i])
170
+ i -= size
171
+ if containsRuneIn(chars, r) {
172
+ return i
173
+ }
174
+ }
175
+ return -1
176
+ }
177
+
178
+ func indexFunc(s []byte, f func(rune) bool, truth bool) int {
179
+ for i := 0; i < len(s); {
180
+ r, size := decodeRune(s[i:])
181
+ if f(r) == truth {
182
+ return i
183
+ }
184
+ i += size
185
+ }
186
+ return -1
187
+ }
188
+
189
+ func lastIndexFunc(s []byte, f func(rune) bool, truth bool) int {
190
+ for i := len(s); i > 0; {
191
+ r, size := decodeLastRune(s[:i])
192
+ i -= size
193
+ if f(r) == truth {
194
+ return i
195
+ }
196
+ }
197
+ return -1
198
+ }
199
+
200
+ // IndexFunc interprets s as a sequence of UTF-8-encoded code points.
201
+ // It returns the byte index in s of the first Unicode
202
+ // code point satisfying f(c), or -1 if none do.
203
+ func IndexFunc(s []byte, f func(r rune) bool) int {
204
+ return indexFunc(s, f, true)
205
+ }
206
+
207
+ // LastIndexFunc interprets s as a sequence of UTF-8-encoded code points.
208
+ // It returns the byte index in s of the last Unicode
209
+ // code point satisfying f(c), or -1 if none do.
210
+ func LastIndexFunc(s []byte, f func(r rune) bool) int {
211
+ return lastIndexFunc(s, f, true)
212
+ }
213
+
214
+ // ContainsFunc reports whether any of the UTF-8-encoded code points
215
+ // in b satisfy f(c).
216
+ func ContainsFunc(b []byte, f func(rune) bool) bool {
217
+ return indexFunc(b, f, true) >= 0
218
+ }
219
+
220
+ // CutPrefix returns s without the provided leading prefix byte slice
221
+ // and reports whether it found the prefix.
222
+ // If s doesn't start with prefix, CutPrefix returns s, false.
223
+ // If prefix is the empty byte slice, CutPrefix returns s, true.
224
+ func CutPrefix(s, prefix []byte) (after []byte, found bool) {
225
+ if len(s) < len(prefix) || Compare(s[:len(prefix)], prefix) != 0 {
226
+ return s, false
227
+ }
228
+ return s[len(prefix):], true
229
+ }
230
+
231
+ // CutSuffix returns s without the provided ending suffix byte slice
232
+ // and reports whether it found the suffix.
233
+ // If s doesn't end with suffix, CutSuffix returns s, false.
234
+ // If suffix is the empty byte slice, CutSuffix returns s, true.
235
+ func CutSuffix(s, suffix []byte) (before []byte, found bool) {
236
+ if len(s) < len(suffix) || Compare(s[len(s)-len(suffix):], suffix) != 0 {
237
+ return s, false
238
+ }
239
+ return s[:len(s)-len(suffix)], true
240
+ }
@@ -0,0 +1,218 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed bytes package: splitting, trimming and
6
+ // case members written in Go and merged into the bytes namespace. Like Go's,
7
+ // the slices SplitAfter and SplitAfterN return alias the input and have their
8
+ // capacity clipped.
9
+ package bytes
10
+
11
+ import (
12
+ "errors"
13
+ "unicode"
14
+ )
15
+
16
+ // MinRead is the minimum slice size passed to a Read call by
17
+ // Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
18
+ // what is required to hold the contents of r, ReadFrom will not grow the
19
+ // underlying buffer.
20
+ const MinRead = 512
21
+
22
+ // ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
23
+ var ErrTooLarge = errors.New("bytes.Buffer: too large")
24
+
25
+ // runeCount returns the number of runes in p, counting each invalid byte as
26
+ // one rune as utf8.RuneCount does.
27
+ func runeCount(p []byte) int {
28
+ n := 0
29
+ for i := 0; i < len(p); n++ {
30
+ _, size := decodeRune(p[i:])
31
+ i += size
32
+ }
33
+ return n
34
+ }
35
+
36
+ // countSep counts the non-overlapping instances of sep in s; sep must not be
37
+ // empty.
38
+ func countSep(s, sep []byte) int {
39
+ n := 0
40
+ for {
41
+ i := index(s, sep)
42
+ if i < 0 {
43
+ return n
44
+ }
45
+ n++
46
+ s = s[i+len(sep):]
47
+ }
48
+ }
49
+
50
+ // explode splits s into a slice of UTF-8 sequences, one per Unicode code point
51
+ // (still slices of bytes), up to a maximum of n byte slices. Invalid UTF-8
52
+ // sequences are chopped into individual bytes.
53
+ func explode(s []byte, n int) [][]byte {
54
+ l := runeCount(s)
55
+ if n < 0 || n > l {
56
+ n = l
57
+ }
58
+ a := make([][]byte, n)
59
+ for i := 0; i < n-1; i++ {
60
+ _, size := decodeRune(s)
61
+ a[i] = s[:size:size]
62
+ s = s[size:]
63
+ }
64
+ if n > 0 {
65
+ a[n-1] = s[:len(s):len(s)]
66
+ }
67
+ return a
68
+ }
69
+
70
+ // genSplit splits s around sep, including sepSave bytes of sep in each
71
+ // subslice, into at most n subslices.
72
+ func genSplit(s, sep []byte, sepSave, n int) [][]byte {
73
+ if n == 0 {
74
+ return nil
75
+ }
76
+ if len(sep) == 0 {
77
+ return explode(s, n)
78
+ }
79
+ if n < 0 {
80
+ n = countSep(s, sep) + 1
81
+ }
82
+ if n > len(s)+1 {
83
+ n = len(s) + 1
84
+ }
85
+ a := make([][]byte, n)
86
+ n--
87
+ i := 0
88
+ for i < n {
89
+ m := index(s, sep)
90
+ if m < 0 {
91
+ break
92
+ }
93
+ a[i] = s[: m+sepSave : m+sepSave]
94
+ s = s[m+len(sep):]
95
+ i++
96
+ }
97
+ a[i] = s[:len(s):len(s)]
98
+ return a[:i+1]
99
+ }
100
+
101
+ // SplitAfter slices s into all subslices after each instance of sep and
102
+ // returns a slice of those subslices.
103
+ // If sep is empty, SplitAfter splits after each UTF-8 sequence.
104
+ // It is equivalent to SplitAfterN with a count of -1.
105
+ func SplitAfter(s, sep []byte) [][]byte {
106
+ return genSplit(s, sep, len(sep), -1)
107
+ }
108
+
109
+ // SplitAfterN slices s into subslices after each instance of sep and
110
+ // returns a slice of those subslices.
111
+ // The count determines the number of subslices to return:
112
+ // - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
113
+ // - n == 0: the result is nil (zero subslices);
114
+ // - n < 0: all subslices.
115
+ func SplitAfterN(s, sep []byte, n int) [][]byte {
116
+ return genSplit(s, sep, len(sep), n)
117
+ }
118
+
119
+ // Runes interprets s as a sequence of UTF-8-encoded code points.
120
+ // It returns a slice of runes (Unicode code points) equivalent to s.
121
+ func Runes(s []byte) []rune {
122
+ t := make([]rune, runeCount(s))
123
+ i := 0
124
+ for len(s) > 0 {
125
+ r, l := decodeRune(s)
126
+ t[i] = r
127
+ i++
128
+ s = s[l:]
129
+ }
130
+ return t
131
+ }
132
+
133
+ // isSeparator reports whether the rune could mark a word boundary.
134
+ func isSeparator(r rune) bool {
135
+ if r <= 0x7F {
136
+ switch {
137
+ case '0' <= r && r <= '9':
138
+ return false
139
+ case 'a' <= r && r <= 'z':
140
+ return false
141
+ case 'A' <= r && r <= 'Z':
142
+ return false
143
+ case r == '_':
144
+ return false
145
+ }
146
+ return true
147
+ }
148
+ if unicode.IsLetter(int(r)) || unicode.IsDigit(int(r)) {
149
+ return false
150
+ }
151
+ return unicode.IsSpace(int(r))
152
+ }
153
+
154
+ // appendRune appends the UTF-8 encoding of r to p, writing RuneError for a
155
+ // value that is not a valid code point.
156
+ // The continuation bytes mask a byte(r>>n) rather than r>>n: the JS backend
157
+ // drops the parentheses around a wrapped int32 shift in `x | r>>n&m`.
158
+ func appendRune(p []byte, r rune) []byte {
159
+ switch {
160
+ case r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF):
161
+ r = runeError
162
+ case r < 0x80:
163
+ return append(p, byte(r))
164
+ }
165
+ switch {
166
+ case r < 0x800:
167
+ return append(p, byte(0xC0|r>>6), byte(0x80|r&0x3F))
168
+ case r < 0x10000:
169
+ return append(p, byte(0xE0|r>>12), 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
170
+ }
171
+ return append(p, byte(0xF0|r>>18), 0x80|byte(r>>12)&0x3F, 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
172
+ }
173
+
174
+ // Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode
175
+ // letters that begin words mapped to their title case.
176
+ //
177
+ // Deprecated: The rule Title uses for word boundaries does not handle Unicode
178
+ // punctuation properly.
179
+ func Title(s []byte) []byte {
180
+ prev := rune(' ')
181
+ out := make([]byte, 0, len(s))
182
+ for i := 0; i < len(s); {
183
+ r, size := decodeRune(s[i:])
184
+ i += size
185
+ c := r
186
+ if isSeparator(prev) {
187
+ c = unicode.ToTitle(r)
188
+ }
189
+ prev = r
190
+ if c >= 0 {
191
+ out = appendRune(out, c)
192
+ }
193
+ }
194
+ return out
195
+ }
196
+
197
+ // TrimLeftFunc treats s as UTF-8-encoded bytes and returns a subslice of s by slicing off
198
+ // all leading UTF-8-encoded code points c that satisfy f(c).
199
+ func TrimLeftFunc(s []byte, f func(r rune) bool) []byte {
200
+ i := indexFunc(s, f, false)
201
+ if i == -1 {
202
+ return nil
203
+ }
204
+ return s[i:]
205
+ }
206
+
207
+ // TrimRightFunc returns a subslice of s by slicing off all trailing
208
+ // UTF-8-encoded code points c that satisfy f(c).
209
+ func TrimRightFunc(s []byte, f func(r rune) bool) []byte {
210
+ i := lastIndexFunc(s, f, false)
211
+ if i >= 0 && s[i] >= runeSelf {
212
+ _, wid := decodeRune(s[i:])
213
+ i += wid
214
+ } else {
215
+ i++
216
+ }
217
+ return s[0:i]
218
+ }
@@ -0,0 +1,65 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Package cmp provides types and functions related to comparing ordered
6
+ // values. Same API as Go's cmp package.
7
+ package cmp
8
+
9
+ // Ordered is a constraint that permits any ordered type: any type that
10
+ // supports the operators < <= >= >.
11
+ type Ordered interface {
12
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
13
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
14
+ ~float32 | ~float64 |
15
+ ~string
16
+ }
17
+
18
+ // Less reports whether x is less than y. A NaN is less than any non-NaN,
19
+ // and -0.0 is not less than 0.0.
20
+ func Less[T Ordered](x, y T) bool {
21
+ return (isNaNValue(x) && !isNaNValue(y)) || x < y
22
+ }
23
+
24
+ // Compare returns -1 if x is less than y, 0 if x equals y, and +1 if x is
25
+ // greater than y. A NaN is less than any non-NaN, a NaN equals a NaN, and
26
+ // -0.0 equals 0.0.
27
+ func Compare[T Ordered](x, y T) int {
28
+ xNaN := isNaNValue(x)
29
+ yNaN := isNaNValue(y)
30
+ if xNaN {
31
+ if yNaN {
32
+ return 0
33
+ }
34
+ return -1
35
+ }
36
+ if yNaN {
37
+ return +1
38
+ }
39
+ if x < y {
40
+ return -1
41
+ }
42
+ if x > y {
43
+ return +1
44
+ }
45
+ return 0
46
+ }
47
+
48
+ // isNaNValue reports whether x is a NaN without requiring the math package
49
+ // (named so it does not collide with the browser global isNaN until Task 0.9).
50
+ // This will always return false if T is not floating-point.
51
+ func isNaNValue[T Ordered](x T) bool {
52
+ return x != x
53
+ }
54
+
55
+ // Or returns the first of its arguments that is not equal to the zero
56
+ // value. If no argument is non-zero, it returns the zero value.
57
+ func Or[T comparable](vals ...T) T {
58
+ var zero T
59
+ for _, v := range vals {
60
+ if v != zero {
61
+ return v
62
+ }
63
+ }
64
+ return zero
65
+ }
@@ -0,0 +1,31 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package json
6
+
7
+ import (
8
+ "internal/jsonrt"
9
+ )
10
+
11
+ // A SyntaxError is a description of a JSON syntax error.
12
+ // [Unmarshal] will return a SyntaxError if the JSON can't be parsed.
13
+ type SyntaxError = jsonrt.SyntaxError
14
+
15
+ // An UnmarshalTypeError describes a JSON value that was not appropriate for
16
+ // a value of a specific Go type.
17
+ type UnmarshalTypeError = jsonrt.UnmarshalTypeError
18
+
19
+ // An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
20
+ type InvalidUnmarshalError = jsonrt.InvalidUnmarshalError
21
+
22
+ // An UnsupportedValueError is returned by Marshal when attempting to encode
23
+ // an unsupported value.
24
+ type UnsupportedValueError = jsonrt.UnsupportedValueError
25
+
26
+ // UnsupportedTypeError is returned by Marshal when attempting to encode an
27
+ // unsupported value type.
28
+ type UnsupportedTypeError = jsonrt.UnsupportedTypeError
29
+
30
+ // A MarshalerError represents an error from calling a MarshalJSON method.
31
+ type MarshalerError = jsonrt.MarshalerError
@@ -0,0 +1,71 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package json
6
+
7
+ import (
8
+ "bytes"
9
+ "internal/jsonrt"
10
+ )
11
+
12
+ var hexDigits = []byte("0123456789abcdef")
13
+
14
+ func escapeLen(src []byte, i int) int {
15
+ c := src[i]
16
+ if c == '<' || c == '>' || c == '&' {
17
+ return 1
18
+ }
19
+ if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && (src[i+2]&^1) == 0xA8 {
20
+ return 3
21
+ }
22
+ return 0
23
+ }
24
+
25
+ // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
26
+ // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
27
+ // so that the JSON will be safe to embed inside HTML <script> tags.
28
+ func HTMLEscape(dst *bytes.Buffer, src []byte) {
29
+ start := 0
30
+ for i := 0; i < len(src); {
31
+ n := escapeLen(src, i)
32
+ if n == 0 {
33
+ i++
34
+ continue
35
+ }
36
+ if start < i {
37
+ dst.Write(src[start:i])
38
+ }
39
+ if n == 1 {
40
+ c := src[i]
41
+ dst.Write([]byte{'\\', 'u', '0', '0', hexDigits[c>>4], hexDigits[c&0xF]})
42
+ i++
43
+ } else {
44
+ dst.Write([]byte{'\\', 'u', '2', '0', '2', hexDigits[src[i+2]&0xF]})
45
+ i += 3
46
+ }
47
+ start = i
48
+ }
49
+ if start < len(src) {
50
+ dst.Write(src[start:])
51
+ }
52
+ }
53
+
54
+ // Compact appends to dst the JSON-encoded src with
55
+ // insignificant space characters elided.
56
+ func Compact(dst *bytes.Buffer, src []byte) error {
57
+ b, err := jsonrt.AppendCompact(nil, src, false)
58
+ if len(b) > 0 {
59
+ dst.Write(b)
60
+ }
61
+ return err
62
+ }
63
+
64
+ // Indent appends to dst an indented form of the JSON-encoded src.
65
+ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
66
+ b, err := jsonrt.AppendIndent(nil, src, prefix, indent)
67
+ if len(b) > 0 {
68
+ dst.Write(b)
69
+ }
70
+ return err
71
+ }
@@ -0,0 +1,12 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package json
6
+
7
+ import (
8
+ "internal/jsonrt"
9
+ )
10
+
11
+ // A Number represents a JSON number literal.
12
+ type Number = jsonrt.Number