gofront 1.7.0 → 1.9.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 (194) hide show
  1. package/README.md +14 -14
  2. package/package.json +10 -38
  3. package/src/backend/js/expressions.js +2060 -389
  4. package/src/backend/js/index.js +586 -174
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +936 -1644
  7. package/src/backend/js/statements.js +1349 -132
  8. package/src/backend/js/stdlib/index.js +51 -94
  9. package/src/backend/js/templ.js +67 -118
  10. package/src/backend/js/type-info.js +436 -0
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +80 -0
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +753 -872
  15. package/src/backend/wasm/emit-builtins.js +914 -237
  16. package/src/backend/wasm/emit-exprs.js +1456 -195
  17. package/src/backend/wasm/emit-maps.js +78 -380
  18. package/src/backend/wasm/emit-stmts.js +1659 -214
  19. package/src/backend/wasm/emit.js +614 -88
  20. package/src/backend/wasm/encode.js +43 -13
  21. package/src/backend/wasm/globals.js +491 -0
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +406 -3195
  24. package/src/backend/wasm/method-expr.js +392 -0
  25. package/src/backend/wasm/module-emitter.js +1615 -0
  26. package/src/backend/wasm/monomorph.js +164 -9
  27. package/src/backend/wasm/natives.js +596 -0
  28. package/src/backend/wasm/prescan.js +249 -0
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -37
  31. package/src/backend/wasm/stdlib/simd.js +293 -28
  32. package/src/backend/wasm/types.js +260 -27
  33. package/src/backend/wasm/variadic.js +93 -0
  34. package/src/backend/wasm/wat.js +47 -20
  35. package/src/{cli-core.js → cli/cli-core.js} +241 -11
  36. package/src/{test-runner.js → cli/test-runner.js} +188 -122
  37. package/src/{vendor.js → cli/vendor.js} +3 -4
  38. package/src/compiler.js +202 -386
  39. package/src/index.js +15 -169
  40. package/src/{lexer.js → lexer/lexer.js} +203 -62
  41. package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
  42. package/src/{tokens.js → lexer/tokens.js} +2 -0
  43. package/src/link/sourcemap.js +97 -0
  44. package/src/link/stdlib.js +737 -0
  45. package/src/link/type-names.js +148 -0
  46. package/src/link/wasm.js +318 -0
  47. package/src/lower/bounds.js +547 -0
  48. package/src/lower/boxing.js +1 -1
  49. package/src/lower/captures.js +267 -64
  50. package/src/lower/embedding.js +32 -3
  51. package/src/lower/errors-as.js +196 -0
  52. package/src/lower/fmt-formatters.js +905 -0
  53. package/src/lower/functions.js +2 -0
  54. package/src/lower/gen-types.js +274 -0
  55. package/src/lower/index.js +33 -19
  56. package/src/lower/json-codecs.js +1379 -0
  57. package/src/lower/ownership.js +47 -8
  58. package/src/lower/range.js +86 -1
  59. package/src/lower/reachability.js +150 -0
  60. package/src/lower/walk.js +12 -0
  61. package/src/parser/declarations.js +83 -15
  62. package/src/parser/expressions.js +110 -18
  63. package/src/parser/index.js +2 -1
  64. package/src/parser/statements.js +38 -22
  65. package/src/{templ-parser.js → parser/templ.js} +179 -17
  66. package/src/parser/types.js +70 -9
  67. package/src/resolver.js +21 -1
  68. package/src/typechecker/assignability.js +291 -19
  69. package/src/typechecker/const-fold.js +399 -0
  70. package/src/typechecker/constants.js +282 -0
  71. package/src/typechecker/expressions.js +1220 -183
  72. package/src/typechecker/index.js +659 -92
  73. package/src/typechecker/init-order.js +426 -0
  74. package/src/typechecker/operand-text.js +40 -0
  75. package/src/typechecker/resolve.js +613 -62
  76. package/src/typechecker/statements.js +212 -20
  77. package/src/typechecker/stdlib/excluded.js +902 -0
  78. package/src/typechecker/stdlib/index.js +38 -0
  79. package/src/typechecker/stdlib/simd.js +65 -15
  80. package/src/typechecker/termination.js +11 -2
  81. package/src/typechecker/types.js +268 -514
  82. package/stdlib/bytes/buffer.go +479 -0
  83. package/stdlib/bytes/bytes.go +1010 -0
  84. package/stdlib/bytes/reader.go +161 -0
  85. package/stdlib/cmp/cmp.go +65 -0
  86. package/stdlib/context/context.go +115 -0
  87. package/stdlib/crypto/rand/rand.go +34 -0
  88. package/stdlib/crypto/sha256/sha256.go +249 -0
  89. package/stdlib/encoding/base64/base64.go +331 -0
  90. package/stdlib/encoding/binary/binary.go +332 -0
  91. package/stdlib/encoding/hex/hex.go +140 -0
  92. package/stdlib/encoding/json/errors.go +31 -0
  93. package/stdlib/encoding/json/indent.go +71 -0
  94. package/stdlib/encoding/json/json.go +62 -0
  95. package/stdlib/encoding/json/number.go +12 -0
  96. package/stdlib/encoding/json/stream.go +173 -0
  97. package/stdlib/errors/errors.go +174 -0
  98. package/stdlib/fmt/errors.go +110 -0
  99. package/stdlib/fmt/format.go +732 -0
  100. package/stdlib/fmt/print.go +1232 -0
  101. package/stdlib/gom/gom.go +293 -0
  102. package/stdlib/hash/hash.go +53 -0
  103. package/stdlib/html/html.go +251 -0
  104. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  105. package/stdlib/internal/jsonrt/dec.go +871 -0
  106. package/stdlib/internal/jsonrt/enc.go +516 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +658 -0
  111. package/stdlib/io/io.go +502 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/maps.go +131 -0
  114. package/stdlib/math/bits/bits.go +507 -0
  115. package/stdlib/math/extra.go +272 -0
  116. package/stdlib/math/math.go +439 -0
  117. package/stdlib/math/rand/rand.go +297 -0
  118. package/stdlib/os/os.go +93 -0
  119. package/stdlib/path/filepath/filepath.go +47 -0
  120. package/stdlib/path/path.go +394 -0
  121. package/stdlib/regexp/regexp.go +231 -0
  122. package/stdlib/slices/slices.go +526 -0
  123. package/stdlib/slices/sort.go +209 -0
  124. package/stdlib/slices/zsort_cmp.go +480 -0
  125. package/stdlib/slices/zsort_ordered.go +482 -0
  126. package/stdlib/sort/sort.go +500 -0
  127. package/stdlib/sort/zsort_func.go +480 -0
  128. package/stdlib/sort/zsort_iface.go +480 -0
  129. package/stdlib/strconv/float.go +1699 -0
  130. package/stdlib/strconv/isprint.go +752 -0
  131. package/stdlib/strconv/quote.go +526 -0
  132. package/stdlib/strconv/strconv.go +616 -0
  133. package/stdlib/strings/builder.go +95 -0
  134. package/stdlib/strings/reader.go +163 -0
  135. package/stdlib/strings/replacer.go +102 -0
  136. package/stdlib/strings/strings.go +807 -0
  137. package/stdlib/sync/sync.go +268 -0
  138. package/stdlib/testing/async_js.go +61 -0
  139. package/stdlib/testing/benchmark.go +297 -0
  140. package/stdlib/testing/testing.go +523 -0
  141. package/stdlib/time/duration.go +233 -0
  142. package/stdlib/time/format.go +745 -0
  143. package/stdlib/time/parse.go +790 -0
  144. package/stdlib/time/sleep_js.go +63 -0
  145. package/stdlib/time/time.go +834 -0
  146. package/stdlib/unicode/unicode.go +250 -0
  147. package/stdlib/unicode/utf8/utf8.go +464 -0
  148. package/src/backend/js/stdlib/base64.js +0 -12
  149. package/src/backend/js/stdlib/binary.js +0 -102
  150. package/src/backend/js/stdlib/bits.js +0 -46
  151. package/src/backend/js/stdlib/builder.js +0 -63
  152. package/src/backend/js/stdlib/bytes.js +0 -122
  153. package/src/backend/js/stdlib/errors.js +0 -44
  154. package/src/backend/js/stdlib/fmt.js +0 -178
  155. package/src/backend/js/stdlib/gom.js +0 -155
  156. package/src/backend/js/stdlib/hex.js +0 -17
  157. package/src/backend/js/stdlib/html.js +0 -20
  158. package/src/backend/js/stdlib/io.js +0 -137
  159. package/src/backend/js/stdlib/json.js +0 -972
  160. package/src/backend/js/stdlib/maps.js +0 -45
  161. package/src/backend/js/stdlib/math.js +0 -69
  162. package/src/backend/js/stdlib/os.js +0 -13
  163. package/src/backend/js/stdlib/path.js +0 -48
  164. package/src/backend/js/stdlib/rand.js +0 -32
  165. package/src/backend/js/stdlib/regexp.js +0 -54
  166. package/src/backend/js/stdlib/sha256.js +0 -12
  167. package/src/backend/js/stdlib/shared.js +0 -17
  168. package/src/backend/js/stdlib/simd.js +0 -24
  169. package/src/backend/js/stdlib/slices.js +0 -77
  170. package/src/backend/js/stdlib/sort.js +0 -30
  171. package/src/backend/js/stdlib/strconv.js +0 -74
  172. package/src/backend/js/stdlib/strings.js +0 -222
  173. package/src/backend/js/stdlib/sync.js +0 -13
  174. package/src/backend/js/stdlib/testing.js +0 -34
  175. package/src/backend/js/stdlib/time.js +0 -128
  176. package/src/backend/js/stdlib/unicode.js +0 -25
  177. package/src/backend/js/stdlib/utf8.js +0 -26
  178. package/src/backend/wasm/const-fold.js +0 -205
  179. package/src/backend/wasm/emit-stdlib.js +0 -13
  180. package/src/backend/wasm/stdlib/bytes.js +0 -5039
  181. package/src/backend/wasm/stdlib/core.js +0 -8903
  182. package/src/backend/wasm/stdlib/io.js +0 -2161
  183. package/src/backend/wasm/stdlib/packages.js +0 -2400
  184. package/src/backend/wasm/stdlib/pure.js +0 -720
  185. package/src/backend/wasm/stdlib/time.js +0 -1200
  186. package/src/typechecker/stdlib/core.js +0 -801
  187. package/src/typechecker/stdlib/extended.js +0 -914
  188. package/src/typechecker/stdlib.js +0 -22
  189. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  190. /package/src/{colors.js → cli/colors.js} +0 -0
  191. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  192. /package/src/{minifier.js → cli/minifier.js} +0 -0
  193. /package/src/{project-config.js → cli/project-config.js} +0 -0
  194. /package/src/{pwa.js → cli/pwa.js} +0 -0
@@ -0,0 +1,516 @@
1
+ // Copyright 2010 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ //go:build gofront
6
+
7
+ //gofront:target both
8
+
9
+ package jsonrt
10
+
11
+ import (
12
+ "encoding/base64"
13
+ "errors"
14
+ "math"
15
+ "sort"
16
+ "strconv"
17
+ "unicode/utf8"
18
+ )
19
+
20
+ // An UnsupportedValueError is returned by Marshal when attempting to encode
21
+ // an unsupported value.
22
+ type UnsupportedValueError struct {
23
+ Str string
24
+ }
25
+
26
+ func (e *UnsupportedValueError) Error() string {
27
+ return "json: unsupported value: " + e.Str
28
+ }
29
+
30
+ // UnsupportedTypeError is returned by Marshal when attempting to encode an
31
+ // unsupported value type.
32
+ type UnsupportedTypeError struct {
33
+ Type string
34
+ }
35
+
36
+ func (e *UnsupportedTypeError) Error() string {
37
+ return "json: unsupported type: " + e.Type
38
+ }
39
+
40
+ // A MarshalerError represents an error from calling a MarshalJSON method.
41
+ type MarshalerError struct {
42
+ Type string
43
+ Err error
44
+ sourceFunc string
45
+ }
46
+
47
+ func (e *MarshalerError) Error() string {
48
+ srcFunc := e.sourceFunc
49
+ if srcFunc == "" {
50
+ srcFunc = "MarshalJSON"
51
+ }
52
+ return "json: error calling " + srcFunc + " for type " + e.Type + ": " + e.Err.Error()
53
+ }
54
+
55
+ func (e *MarshalerError) Unwrap() error { return e.Err }
56
+
57
+ // Enc is the state of one Marshal call: the output so far and the first
58
+ // error. After an error every method does nothing.
59
+ //
60
+ // The output is buf[:n]; the rest of buf is room to grow into, so appending
61
+ // a byte is an index write rather than a new slice header.
62
+ type Enc struct {
63
+ buf []byte
64
+ n int
65
+ Err error
66
+ EscapeHTML bool
67
+ }
68
+
69
+ // NewEnc returns an encoder that escapes <, > and & like json.Marshal.
70
+ func NewEnc() *Enc {
71
+ return &Enc{buf: make([]byte, 256), EscapeHTML: true}
72
+ }
73
+
74
+ // Result returns the encoded bytes, or the first error.
75
+ func (e *Enc) Result() ([]byte, error) {
76
+ if e.Err != nil {
77
+ return nil, e.Err
78
+ }
79
+ return e.buf[:e.n], nil
80
+ }
81
+
82
+ // room makes sure k more bytes fit after the output.
83
+ func (e *Enc) room(k int) {
84
+ if e.n+k <= len(e.buf) {
85
+ return
86
+ }
87
+ nb := make([]byte, 2*len(e.buf)+k)
88
+ copy(nb, e.buf[:e.n])
89
+ e.buf = nb
90
+ }
91
+
92
+ // putBytes appends b to the output.
93
+ func (e *Enc) putBytes(b []byte) {
94
+ e.room(len(b))
95
+ copy(e.buf[e.n:], b)
96
+ e.n += len(b)
97
+ }
98
+
99
+ // putString appends the bytes of s to the output.
100
+ //
101
+ //gofront:native jsonrt.putString
102
+ func putString(e *Enc, s string) {
103
+ n := len(s)
104
+ e.room(n)
105
+ for i := 0; i < n; i++ {
106
+ e.buf[e.n+i] = s[i]
107
+ }
108
+ e.n += n
109
+ }
110
+
111
+ // putInt appends the decimal form of v.
112
+ //
113
+ //gofront:native jsonrt.putInt
114
+ func putInt(e *Enc, v int64) {
115
+ if v < 0 {
116
+ e.Byte('-')
117
+ putUint(e, uint64(-v))
118
+ return
119
+ }
120
+ putUint(e, uint64(v))
121
+ }
122
+
123
+ // putUint appends the decimal form of v.
124
+ //
125
+ //gofront:native jsonrt.putUint
126
+ func putUint(e *Enc, v uint64) {
127
+ n := 1
128
+ for t := v; t >= 10; t /= 10 {
129
+ n++
130
+ }
131
+ e.room(n)
132
+ for i := e.n + n - 1; i >= e.n; i-- {
133
+ e.buf[i] = byte('0' + v%10)
134
+ v /= 10
135
+ }
136
+ e.n += n
137
+ }
138
+
139
+ // putFloat appends a finite f in the format encoding/json uses: shortest
140
+ // digits that read back as a float of the given size, as if by ES6 number to
141
+ // string conversion (an exponent only below 1e-6 and from 1e21).
142
+ //
143
+ //gofront:native jsonrt.putFloat
144
+ func putFloat(e *Enc, f float64, bits int) {
145
+ var tmp [64]byte
146
+ b := tmp[:0]
147
+ format := floatFormat(f, bits)
148
+ if bits == 32 {
149
+ f = shortest32(f)
150
+ }
151
+ b = strconv.AppendFloat(b, f, format, -1, 64)
152
+ if format == 'e' {
153
+ b = cleanExponent(b)
154
+ }
155
+ e.putBytes(b)
156
+ }
157
+
158
+ // LooksFloat32 reports whether f, found in an interface, is more likely a
159
+ // float32 than a float64. Where a float32 and a float64 share one run-time
160
+ // representation (JavaScript numbers) a float64 that a float32 holds exactly
161
+ // is taken for one; elsewhere the interface tells them apart.
162
+ //
163
+ //gofront:native jsonrt.LooksFloat32
164
+ func LooksFloat32(f float64) bool {
165
+ return false
166
+ }
167
+
168
+ // putQuoted appends s as a quoted JSON string.
169
+ //
170
+ //gofront:native jsonrt.putQuoted
171
+ func putQuoted(e *Enc, s string) {
172
+ n := len(s)
173
+ for i := 0; i < n; i++ {
174
+ c := s[i]
175
+ if c < 0x20 || c >= utf8.RuneSelf || c == '"' || c == '\\' || (e.EscapeHTML && (c == '<' || c == '>' || c == '&')) {
176
+ e.putBytes(AppendString(nil, []byte(s), e.EscapeHTML))
177
+ return
178
+ }
179
+ }
180
+ e.room(n + 2)
181
+ e.buf[e.n] = '"'
182
+ for i := 0; i < n; i++ {
183
+ e.buf[e.n+1+i] = s[i]
184
+ }
185
+ e.buf[e.n+n+1] = '"'
186
+ e.n += n + 2
187
+ }
188
+
189
+ // Fail records the first error.
190
+ func (e *Enc) Fail(err error) {
191
+ if e.Err == nil {
192
+ e.Err = err
193
+ }
194
+ }
195
+
196
+ // FailType records an unsupported-type error.
197
+ func (e *Enc) FailType(typ string) {
198
+ e.Fail(&UnsupportedTypeError{typ})
199
+ }
200
+
201
+ // encoders are the dynamic encoders every package with generated codecs
202
+ // registers at start-up: each encodes the values of its own package's types
203
+ // and reports whether it knew the value.
204
+ type encoderList struct {
205
+ fns []func(*Enc, any) bool
206
+ }
207
+
208
+ var encoders = &encoderList{}
209
+
210
+ // RegisterEncoder adds a package's dynamic encoder. Each target fills its own
211
+ // list from the package initializers it runs, so the list is built through a local.
212
+ func RegisterEncoder(f func(*Enc, any) bool) bool {
213
+ list := encoders
214
+ list.fns = append(list.fns, f)
215
+ return true
216
+ }
217
+
218
+ // EncodeDynamic encodes v with the first registered encoder that knows its
219
+ // type, and fails the encoding when none does.
220
+ func (e *Enc) EncodeDynamic(v any) {
221
+ for _, f := range encoders.fns {
222
+ if f(e, v) {
223
+ return
224
+ }
225
+ }
226
+ e.FailType("unsupported dynamic type")
227
+ }
228
+
229
+ // Lit appends s, which is already valid JSON text.
230
+ func (e *Enc) Lit(s string) {
231
+ putString(e, s)
232
+ }
233
+
234
+ // Byte appends one byte of JSON punctuation.
235
+ func (e *Enc) Byte(c byte) {
236
+ if e.n == len(e.buf) {
237
+ e.room(1)
238
+ }
239
+ e.buf[e.n] = c
240
+ e.n++
241
+ }
242
+
243
+ // Null appends null.
244
+ func (e *Enc) Null() {
245
+ putString(e, "null")
246
+ }
247
+
248
+ // Number appends the literal representation of a Number.
249
+ func (e *Enc) Number(v string) {
250
+ if e.Err != nil {
251
+ return
252
+ }
253
+ if v == "" {
254
+ e.Byte('0')
255
+ return
256
+ }
257
+ if !isValidNumber(v) {
258
+ e.Fail(fmt.Errorf("json: invalid number literal %q", v))
259
+ return
260
+ }
261
+ putString(e, v)
262
+ }
263
+
264
+ func isValidNumber(s string) bool {
265
+ if len(s) == 0 {
266
+ return false
267
+ }
268
+ first := s[0]
269
+ if first != '-' && (first < '0' || first > '9') {
270
+ return false
271
+ }
272
+ return CheckValid([]byte(s)) == nil
273
+ }
274
+
275
+ // Bool appends true or false.
276
+ func (e *Enc) Bool(v bool) {
277
+ if v {
278
+ putString(e, "true")
279
+ } else {
280
+ putString(e, "false")
281
+ }
282
+ }
283
+
284
+ // Int appends a signed integer.
285
+ func (e *Enc) Int(v int64) {
286
+ putInt(e, v)
287
+ }
288
+
289
+ // Uint appends an unsigned integer.
290
+ func (e *Enc) Uint(v uint64) {
291
+ putUint(e, v)
292
+ }
293
+
294
+ // Float appends a floating-point number in the format encoding/json uses.
295
+ func (e *Enc) Float(f float64, bits int) {
296
+ if e.Err != nil {
297
+ return
298
+ }
299
+ if math.IsInf(f, 0) || math.IsNaN(f) {
300
+ e.Fail(&UnsupportedValueError{strconv.FormatFloat(f, 'g', -1, bits)})
301
+ return
302
+ }
303
+ if f == 0 && math.Signbit(f) {
304
+ putString(e, "-0")
305
+ return
306
+ }
307
+ putFloat(e, f, bits)
308
+ }
309
+
310
+ // floatFormat picks 'e' or 'f' as if by ES6 number to string conversion.
311
+ func floatFormat(f float64, bits int) byte {
312
+ abs := math.Abs(f)
313
+ if abs == 0 {
314
+ return 'f'
315
+ }
316
+ if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
317
+ return 'e'
318
+ }
319
+ return 'f'
320
+ }
321
+
322
+ // cleanExponent turns a trailing e-09 into e-9.
323
+ func cleanExponent(b []byte) []byte {
324
+ n := len(b)
325
+ if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
326
+ b[n-2] = b[n-1]
327
+ b = b[:n-1]
328
+ }
329
+ return b
330
+ }
331
+
332
+ // shortest32 returns the float64 whose shortest decimal form is the shortest
333
+ // one that reads back as the same float32 (strconv's 32-bit formatting).
334
+ func shortest32(f float64) float64 {
335
+ want := float32(f)
336
+ for p := 0; p < 9; p++ {
337
+ s := strconv.FormatFloat(f, 'e', p, 64)
338
+ g, _ := strconv.ParseFloat(s, 32)
339
+ if float32(g) == want {
340
+ h, _ := strconv.ParseFloat(s, 64)
341
+ return h
342
+ }
343
+ }
344
+ return f
345
+ }
346
+
347
+ // Str appends a quoted, escaped string.
348
+ func (e *Enc) Str(s string) {
349
+ putQuoted(e, s)
350
+ }
351
+
352
+ // QStr appends a string for the ,string tag option: the quoted form of the
353
+ // quoted form.
354
+ func (e *Enc) QStr(s string) {
355
+ inner := AppendString(nil, []byte(s), e.EscapeHTML)
356
+ e.putBytes(AppendString(nil, inner, false))
357
+ }
358
+
359
+ // Key appends the separator for member n of an object (a comma when n > 0)
360
+ // and the member name, a plain name that needs no escaping.
361
+ func (e *Enc) Key(n int, name string) {
362
+ if n > 0 {
363
+ e.Byte(',')
364
+ }
365
+ e.Byte('"')
366
+ putString(e, name)
367
+ e.Byte('"')
368
+ e.Byte(':')
369
+ }
370
+
371
+ // KeyStr is Key for a member name that may need escaping.
372
+ func (e *Enc) KeyStr(n int, name string) {
373
+ if n > 0 {
374
+ e.Byte(',')
375
+ }
376
+ putQuoted(e, name)
377
+ e.Byte(':')
378
+ }
379
+
380
+ // Bytes appends a []byte as a base64 string, or null for a nil slice.
381
+ func (e *Enc) Bytes(v []byte) {
382
+ if v == nil {
383
+ e.Null()
384
+ return
385
+ }
386
+ e.Byte('"')
387
+ putString(e, base64.StdEncoding.EncodeToString(v))
388
+ e.Byte('"')
389
+ }
390
+
391
+ // Raw appends a json.RawMessage: validated and compacted, null when empty.
392
+ func (e *Enc) Raw(v []byte) {
393
+ if v == nil {
394
+ e.Null()
395
+ return
396
+ }
397
+ e.Marshaled(v, nil, "json.RawMessage")
398
+ }
399
+
400
+ // Marshaled appends the result of a MarshalJSON call: validated and
401
+ // compacted, or the call's error wrapped like Go does.
402
+ func (e *Enc) Marshaled(out []byte, err error, typ string) {
403
+ if e.Err != nil {
404
+ return
405
+ }
406
+ if err == nil {
407
+ var b []byte
408
+ b, err = AppendCompact(nil, out, e.EscapeHTML)
409
+ if err == nil {
410
+ e.putBytes(b)
411
+ return
412
+ }
413
+ }
414
+ e.Fail(&MarshalerError{typ, err, "MarshalJSON"})
415
+ }
416
+
417
+ // TextMarshaled appends the result of a MarshalText call as a JSON string, or
418
+ // the call's error wrapped like Go does.
419
+ func (e *Enc) TextMarshaled(out []byte, err error, typ string) {
420
+ if e.Err != nil {
421
+ return
422
+ }
423
+ if err != nil {
424
+ e.Fail(&MarshalerError{typ, err, "MarshalText"})
425
+ return
426
+ }
427
+ e.Str(string(out))
428
+ }
429
+
430
+ // SortStrings sorts map keys.
431
+ func SortStrings(a []string) {
432
+ sort.Strings(a)
433
+ }
434
+
435
+ // IntKey and UintKey format integer map keys.
436
+ func IntKey(v int64) string {
437
+ return strconv.FormatInt(v, 10)
438
+ }
439
+
440
+ func UintKey(v uint64) string {
441
+ return strconv.FormatUint(v, 10)
442
+ }
443
+
444
+ // appendEscaped appends the escape sequence for the ASCII byte b.
445
+ func appendEscaped(dst []byte, b byte) []byte {
446
+ switch b {
447
+ case '\\', '"':
448
+ dst = append(dst, '\\')
449
+ dst = append(dst, b)
450
+ case '\b':
451
+ dst = append(dst, '\\', 'b')
452
+ case '\f':
453
+ dst = append(dst, '\\', 'f')
454
+ case '\n':
455
+ dst = append(dst, '\\', 'n')
456
+ case '\r':
457
+ dst = append(dst, '\\', 'r')
458
+ case '\t':
459
+ dst = append(dst, '\\', 't')
460
+ default:
461
+ // This encodes bytes < 0x20 except for \b, \f, \n, \r and \t.
462
+ // If escapeHTML is set, it also escapes <, >, and &
463
+ // because they can lead to security holes when
464
+ // user-controlled strings are rendered into JSON
465
+ // and served to some browsers.
466
+ dst = append(dst, '\\', 'u', '0', '0', hexDigits[b>>4], hexDigits[b&0xF])
467
+ }
468
+ return dst
469
+ }
470
+
471
+ // AppendString appends src as a quoted JSON string.
472
+ func AppendString(dst, src []byte, escapeHTML bool) []byte {
473
+ dst = append(dst, '"')
474
+ start := 0
475
+ for i := 0; i < len(src); {
476
+ if b := src[i]; b < utf8.RuneSelf {
477
+ if b >= 0x20 && b != '"' && b != '\\' && (!escapeHTML || (b != '<' && b != '>' && b != '&')) {
478
+ i++
479
+ continue
480
+ }
481
+ dst = append(dst, src[start:i]...)
482
+ dst = appendEscaped(dst, b)
483
+ i++
484
+ start = i
485
+ continue
486
+ }
487
+ c, size := utf8.DecodeRune(src[i:])
488
+ if c == utf8.RuneError && size == 1 {
489
+ dst = append(dst, src[start:i]...)
490
+ dst = appendStr(dst, `�`)
491
+ i += size
492
+ start = i
493
+ continue
494
+ }
495
+ // U+2028 is LINE SEPARATOR.
496
+ // U+2029 is PARAGRAPH SEPARATOR.
497
+ // They are both technically valid characters in JSON strings,
498
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
499
+ // and can lead to security holes there. It is valid JSON to
500
+ // escape them, so we do so unconditionally.
501
+ // See https://en.wikipedia.org/wiki/JSON#Safety.
502
+ if c == '
' || c == '
' {
503
+ dst = append(dst, src[start:i]...)
504
+ dst = append(dst, '\\', 'u', '2', '0', '2', hexDigits[c&0xF])
505
+ i += size
506
+ start = i
507
+ continue
508
+ }
509
+ i += size
510
+ }
511
+ dst = append(dst, src[start:]...)
512
+ dst = append(dst, '"')
513
+ return dst
514
+ }
515
+
516
+ var errNilTarget = errors.New("json: Unmarshal(nil)")
@@ -0,0 +1,135 @@
1
+ // Copyright 2010 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ //go:build gofront
6
+
7
+ //gofront:target both
8
+
9
+ package jsonrt
10
+
11
+ var hexDigits = []byte("0123456789abcdef")
12
+
13
+ func appendStr(dst []byte, s string) []byte {
14
+ for i := 0; i < len(s); i++ {
15
+ dst = append(dst, s[i])
16
+ }
17
+ return dst
18
+ }
19
+
20
+ // compactEscape escapes the byte at src[i] when escape is set and it is <, >
21
+ // or & or begins U+2028/U+2029 (E2 80 A8 and E2 80 A9). It returns the grown
22
+ // dst and the new start of the pending unescaped run.
23
+ func compactEscape(dst, src []byte, i, start int, escape bool) ([]byte, int) {
24
+ c := src[i]
25
+ if !escape {
26
+ return dst, start
27
+ }
28
+ if c == '<' || c == '>' || c == '&' {
29
+ dst = append(dst, src[start:i]...)
30
+ dst = append(dst, '\\', 'u', '0', '0', hexDigits[c>>4], hexDigits[c&0xF])
31
+ return dst, i + 1
32
+ }
33
+ if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
34
+ dst = append(dst, src[start:i]...)
35
+ dst = append(dst, '\\', 'u', '2', '0', '2', hexDigits[src[i+2]&0xF])
36
+ return dst, i + 3
37
+ }
38
+ return dst, start
39
+ }
40
+
41
+ // AppendCompact appends to dst the JSON-encoded src with insignificant space
42
+ // characters elided. With escape, <, >, & and U+2028/U+2029 are escaped too.
43
+ func AppendCompact(dst, src []byte, escape bool) ([]byte, error) {
44
+ origLen := len(dst)
45
+ scan := newScanner()
46
+ start := 0
47
+ for i, c := range src {
48
+ dst, start = compactEscape(dst, src, i, start, escape)
49
+ v := scan.step(scan, c)
50
+ if v >= scanSkipSpace {
51
+ if v == scanError {
52
+ break
53
+ }
54
+ if start < i {
55
+ dst = append(dst, src[start:i]...)
56
+ }
57
+ start = i + 1
58
+ }
59
+ }
60
+ if scan.eof() == scanError {
61
+ return dst[:origLen], scan.err
62
+ }
63
+ if start < len(src) {
64
+ dst = append(dst, src[start:]...)
65
+ }
66
+ return dst, nil
67
+ }
68
+
69
+ func appendNewline(dst []byte, prefix, indent string, depth int) []byte {
70
+ dst = append(dst, '\n')
71
+ dst = appendStr(dst, prefix)
72
+ for i := 0; i < depth; i++ {
73
+ dst = appendStr(dst, indent)
74
+ }
75
+ return dst
76
+ }
77
+
78
+ // AppendIndent appends to dst an indented form of the JSON-encoded src.
79
+ func AppendIndent(dst, src []byte, prefix, indent string) ([]byte, error) {
80
+ origLen := len(dst)
81
+ scan := newScanner()
82
+ needIndent := false
83
+ depth := 0
84
+ for _, c := range src {
85
+ scan.bytes++
86
+ v := scan.step(scan, c)
87
+ if v == scanSkipSpace {
88
+ continue
89
+ }
90
+ if v == scanError {
91
+ break
92
+ }
93
+ if needIndent && v != scanEndObject && v != scanEndArray {
94
+ needIndent = false
95
+ depth++
96
+ dst = appendNewline(dst, prefix, indent, depth)
97
+ }
98
+
99
+ // Emit semantically uninteresting bytes
100
+ // (in particular, punctuation in strings) unmodified.
101
+ if v == scanContinue {
102
+ dst = append(dst, c)
103
+ continue
104
+ }
105
+
106
+ // Add spacing around real punctuation.
107
+ switch c {
108
+ case '{', '[':
109
+ // delay indent so that empty object and array are formatted as {} and [].
110
+ needIndent = true
111
+ dst = append(dst, c)
112
+ case ',':
113
+ dst = append(dst, c)
114
+ dst = appendNewline(dst, prefix, indent, depth)
115
+ case ':':
116
+ dst = append(dst, c)
117
+ dst = append(dst, ' ')
118
+ case '}', ']':
119
+ if needIndent {
120
+ // suppress indent in empty object/array
121
+ needIndent = false
122
+ } else {
123
+ depth--
124
+ dst = appendNewline(dst, prefix, indent, depth)
125
+ }
126
+ dst = append(dst, c)
127
+ default:
128
+ dst = append(dst, c)
129
+ }
130
+ }
131
+ if scan.eof() == scanError {
132
+ return dst[:origLen], scan.err
133
+ }
134
+ return dst, nil
135
+ }
@@ -0,0 +1,27 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ package jsonrt
6
+
7
+ import (
8
+ "strconv"
9
+ )
10
+
11
+ // A Number represents a JSON number literal.
12
+ type Number string
13
+
14
+ // String returns the literal text of the number.
15
+ func (n Number) String() string { return string(n) }
16
+
17
+ // Float64 returns the number as a float64.
18
+ func (n Number) Float64() (float64, error) {
19
+ v, err := strconv.ParseFloat(string(n), 64)
20
+ return v, err
21
+ }
22
+
23
+ // Int64 returns the number as an int64.
24
+ func (n Number) Int64() (int64, error) {
25
+ v, err := strconv.ParseInt(string(n), 10, 64)
26
+ return v, err
27
+ }