goscript 0.2.1 → 0.2.3

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 (164) hide show
  1. package/compiler/gotest/runner.go +98 -0
  2. package/compiler/gotest/runner_test.go +45 -0
  3. package/compiler/gotest/testdata/browserapi/browserapi_test.go +36 -0
  4. package/compiler/lowering.go +227 -11
  5. package/compiler/override-registry_test.go +50 -0
  6. package/compiler/protobuf-ts-binding.go +155 -7
  7. package/compiler/protobuf-ts-binding_test.go +116 -2
  8. package/compiler/runtime-contract.go +2 -0
  9. package/compiler/runtime-contract_test.go +1 -0
  10. package/compiler/semantic-model.go +16 -0
  11. package/compiler/semantic-model_test.go +38 -0
  12. package/compiler/skeleton_test.go +477 -16
  13. package/compiler/typescript-emitter.go +4 -0
  14. package/dist/gs/builtin/builtin.js +7 -9
  15. package/dist/gs/builtin/builtin.js.map +1 -1
  16. package/dist/gs/builtin/defer.js +2 -2
  17. package/dist/gs/builtin/hostio.js +5 -5
  18. package/dist/gs/builtin/hostio.js.map +1 -1
  19. package/dist/gs/builtin/map.js +2 -1
  20. package/dist/gs/builtin/map.js.map +1 -1
  21. package/dist/gs/builtin/slice.d.ts +3 -0
  22. package/dist/gs/builtin/slice.js +39 -0
  23. package/dist/gs/builtin/slice.js.map +1 -1
  24. package/dist/gs/builtin/type.js +49 -0
  25. package/dist/gs/builtin/type.js.map +1 -1
  26. package/dist/gs/compress/zlib/index.js +5 -2
  27. package/dist/gs/compress/zlib/index.js.map +1 -1
  28. package/dist/gs/crypto/aes/index.d.ts +15 -0
  29. package/dist/gs/crypto/aes/index.js +57 -0
  30. package/dist/gs/crypto/aes/index.js.map +1 -0
  31. package/dist/gs/crypto/cipher/index.d.ts +41 -0
  32. package/dist/gs/crypto/cipher/index.js +255 -0
  33. package/dist/gs/crypto/cipher/index.js.map +1 -0
  34. package/dist/gs/crypto/ecdh/index.js +27 -8
  35. package/dist/gs/crypto/ecdh/index.js.map +1 -1
  36. package/dist/gs/crypto/ed25519/index.js +3 -3
  37. package/dist/gs/crypto/ed25519/index.js.map +1 -1
  38. package/dist/gs/crypto/rand/index.js +6 -3
  39. package/dist/gs/crypto/rand/index.js.map +1 -1
  40. package/dist/gs/embed/index.js +9 -3
  41. package/dist/gs/embed/index.js.map +1 -1
  42. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
  43. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +33 -0
  44. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  45. package/dist/gs/github.com/mr-tron/base58/base58/index.js +4 -1
  46. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -1
  47. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.d.ts +31 -0
  48. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js +117 -0
  49. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js.map +1 -0
  50. package/dist/gs/golang.org/x/crypto/scrypt/index.d.ts +2 -0
  51. package/dist/gs/golang.org/x/crypto/scrypt/index.js +39 -0
  52. package/dist/gs/golang.org/x/crypto/scrypt/index.js.map +1 -0
  53. package/dist/gs/hash/fnv/index.js +13 -5
  54. package/dist/gs/hash/fnv/index.js.map +1 -1
  55. package/dist/gs/io/fs/glob.d.ts +3 -3
  56. package/dist/gs/io/fs/glob.js +8 -8
  57. package/dist/gs/io/fs/glob.js.map +1 -1
  58. package/dist/gs/io/fs/readdir.d.ts +2 -2
  59. package/dist/gs/io/fs/readdir.js +13 -74
  60. package/dist/gs/io/fs/readdir.js.map +1 -1
  61. package/dist/gs/io/fs/sub.js +4 -4
  62. package/dist/gs/io/fs/sub.js.map +1 -1
  63. package/dist/gs/io/fs/walk.js +1 -1
  64. package/dist/gs/io/fs/walk.js.map +1 -1
  65. package/dist/gs/io/io.js +18 -2
  66. package/dist/gs/io/io.js.map +1 -1
  67. package/dist/gs/maps/iter.js.map +1 -1
  68. package/dist/gs/maps/maps.js.map +1 -1
  69. package/dist/gs/mime/index.js +5 -2
  70. package/dist/gs/mime/index.js.map +1 -1
  71. package/dist/gs/net/http/httptest/index.js +6 -3
  72. package/dist/gs/net/http/httptest/index.js.map +1 -1
  73. package/dist/gs/net/http/index.d.ts +16 -4
  74. package/dist/gs/net/http/index.js +236 -40
  75. package/dist/gs/net/http/index.js.map +1 -1
  76. package/dist/gs/net/http/pprof/index.js.map +1 -1
  77. package/dist/gs/reflect/iter.js +1 -1
  78. package/dist/gs/reflect/iter.js.map +1 -1
  79. package/dist/gs/reflect/type.d.ts +2 -0
  80. package/dist/gs/reflect/type.js +53 -21
  81. package/dist/gs/reflect/type.js.map +1 -1
  82. package/dist/gs/runtime/debug/index.js +2 -1
  83. package/dist/gs/runtime/debug/index.js.map +1 -1
  84. package/dist/gs/runtime/pprof/index.js.map +1 -1
  85. package/dist/gs/runtime/runtime.js +2 -2
  86. package/dist/gs/runtime/runtime.js.map +1 -1
  87. package/dist/gs/runtime/trace/index.js.map +1 -1
  88. package/dist/gs/slices/slices.d.ts +1 -1
  89. package/dist/gs/slices/slices.js +37 -4
  90. package/dist/gs/slices/slices.js.map +1 -1
  91. package/go.mod +2 -2
  92. package/go.sum +2 -0
  93. package/gs/builtin/builtin.ts +11 -14
  94. package/gs/builtin/defer.ts +2 -2
  95. package/gs/builtin/hostio.test.ts +8 -3
  96. package/gs/builtin/hostio.ts +5 -7
  97. package/gs/builtin/map.ts +4 -1
  98. package/gs/builtin/slice.test.ts +14 -0
  99. package/gs/builtin/slice.ts +64 -0
  100. package/gs/builtin/type.ts +72 -0
  101. package/gs/bytes/bytes.test.ts +14 -13
  102. package/gs/compress/zlib/index.test.ts +19 -5
  103. package/gs/compress/zlib/index.ts +16 -7
  104. package/gs/context/context.test.ts +3 -1
  105. package/gs/crypto/aes/index.test.ts +120 -0
  106. package/gs/crypto/aes/index.ts +76 -0
  107. package/gs/crypto/cipher/index.ts +345 -0
  108. package/gs/crypto/cipher/meta.json +6 -0
  109. package/gs/crypto/ecdh/index.test.ts +6 -2
  110. package/gs/crypto/ecdh/index.ts +49 -12
  111. package/gs/crypto/ed25519/index.ts +20 -7
  112. package/gs/crypto/rand/index.ts +6 -3
  113. package/gs/embed/index.test.ts +3 -3
  114. package/gs/embed/index.ts +9 -3
  115. package/gs/fmt/fmt.test.ts +29 -4
  116. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +126 -0
  117. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +46 -0
  118. package/gs/github.com/mr-tron/base58/base58/index.ts +9 -3
  119. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +2 -8
  120. package/gs/golang.org/x/crypto/chacha20poly1305/index.test.ts +91 -0
  121. package/gs/golang.org/x/crypto/chacha20poly1305/index.ts +245 -0
  122. package/gs/golang.org/x/crypto/scrypt/index.test.ts +81 -0
  123. package/gs/golang.org/x/crypto/scrypt/index.ts +54 -0
  124. package/gs/golang.org/x/crypto/scrypt/meta.json +5 -0
  125. package/gs/hash/fnv/index.test.ts +1 -8
  126. package/gs/hash/fnv/index.ts +27 -10
  127. package/gs/io/fs/glob.ts +13 -10
  128. package/gs/io/fs/meta.json +2 -0
  129. package/gs/io/fs/readdir.test.ts +63 -2
  130. package/gs/io/fs/readdir.ts +33 -30
  131. package/gs/io/fs/sub.ts +4 -4
  132. package/gs/io/fs/walk.ts +1 -1
  133. package/gs/io/io.test.ts +56 -1
  134. package/gs/io/io.ts +19 -2
  135. package/gs/maps/iter.ts +9 -9
  136. package/gs/maps/maps.ts +4 -4
  137. package/gs/math/bits/index.test.ts +10 -1
  138. package/gs/mime/index.test.ts +33 -15
  139. package/gs/mime/index.ts +9 -2
  140. package/gs/net/http/httptest/index.test.ts +17 -3
  141. package/gs/net/http/httptest/index.ts +8 -3
  142. package/gs/net/http/index.test.ts +645 -123
  143. package/gs/net/http/index.ts +548 -113
  144. package/gs/net/http/pprof/index.ts +24 -6
  145. package/gs/os/file_unix_js.test.ts +22 -0
  146. package/gs/reflect/iter.ts +4 -2
  147. package/gs/reflect/map.test.ts +56 -1
  148. package/gs/reflect/type.ts +76 -37
  149. package/gs/runtime/debug/index.test.ts +32 -4
  150. package/gs/runtime/debug/index.ts +5 -2
  151. package/gs/runtime/pprof/index.test.ts +7 -1
  152. package/gs/runtime/pprof/index.ts +5 -1
  153. package/gs/runtime/runtime.test.ts +7 -0
  154. package/gs/runtime/runtime.ts +2 -4
  155. package/gs/runtime/trace/index.test.ts +9 -1
  156. package/gs/runtime/trace/index.ts +5 -1
  157. package/gs/slices/meta.json +3 -0
  158. package/gs/slices/slices.test.ts +59 -21
  159. package/gs/slices/slices.ts +61 -20
  160. package/gs/strconv/complex.test.ts +17 -3
  161. package/gs/sync/atomic/doc_64.test.ts +2 -9
  162. package/gs/sync/sync.test.ts +18 -8
  163. package/gs/syscall/js/index.test.ts +9 -4
  164. package/package.json +13 -5
@@ -17,7 +17,11 @@ export type ReadDirFS =
17
17
  | ({
18
18
  // ReadDir reads the named directory
19
19
  // and returns a list of directory entries sorted by filename.
20
- ReadDir(name: string): [$.Slice<DirEntry>, $.GoError]
20
+ ReadDir(
21
+ name: string,
22
+ ):
23
+ | [$.Slice<DirEntry>, $.GoError]
24
+ | Promise<[$.Slice<DirEntry>, $.GoError]>
21
25
  } & FS)
22
26
 
23
27
  $.registerInterfaceType(
@@ -55,51 +59,50 @@ $.registerInterfaceType(
55
59
  // If fs implements [ReadDirFS], ReadDir calls fs.ReadDir.
56
60
  // Otherwise ReadDir calls fs.Open and uses ReadDir and Close
57
61
  // on the returned file.
58
- export function ReadDir(
62
+ export async function ReadDir(
59
63
  fsys: FS,
60
64
  name: string,
61
- ): [$.Slice<DirEntry>, $.GoError] {
62
- using __defer = new $.DisposableStack()
65
+ ): Promise<[$.Slice<DirEntry>, $.GoError]> {
63
66
  {
64
67
  let { value: fsysTyped, ok: ok } = $.typeAssert<ReadDirFS>(
65
68
  fsys,
66
69
  'ReadDirFS',
67
70
  )
68
71
  if (ok) {
69
- return fsysTyped!.ReadDir(name)
72
+ return await fsysTyped!.ReadDir(name)
70
73
  }
71
74
  }
72
75
 
73
- let [file, err] = fsys!.Open(name)
76
+ let [file, err] = await fsys!.Open(name)
74
77
  if (err != null) {
75
78
  return [null, err]
76
79
  }
77
- __defer.defer(() => {
78
- file!.Close()
79
- })
80
-
81
- let { value: dir, ok: ok } = $.typeAssert<ReadDirFile>(file, 'ReadDirFile')
82
- if (!ok) {
83
- return [
84
- null,
85
- new PathError({
86
- Err: errors.New('not implemented'),
87
- Op: 'readdir',
88
- Path: name,
89
- }),
90
- ]
91
- }
80
+ try {
81
+ let { value: dir, ok: ok } = $.typeAssert<ReadDirFile>(file, 'ReadDirFile')
82
+ if (!ok) {
83
+ return [
84
+ null,
85
+ new PathError({
86
+ Err: errors.New('not implemented'),
87
+ Op: 'readdir',
88
+ Path: name,
89
+ }),
90
+ ]
91
+ }
92
92
 
93
- let list: $.Slice<DirEntry>
94
- ;[list, err] = dir!.ReadDir(-1)
95
- if (list) {
96
- list.sort((a: DirEntry, b: DirEntry): number => {
97
- return $.pointerValue<Exclude<DirEntry, null>>(a)
98
- .Name()
99
- .localeCompare($.pointerValue<Exclude<DirEntry, null>>(b).Name())
100
- })
93
+ let list: $.Slice<DirEntry>
94
+ ;[list, err] = await dir!.ReadDir(-1)
95
+ if (list) {
96
+ list.sort((a: DirEntry, b: DirEntry): number => {
97
+ return $.pointerValue<Exclude<DirEntry, null>>(a)
98
+ .Name()
99
+ .localeCompare($.pointerValue<Exclude<DirEntry, null>>(b).Name())
100
+ })
101
+ }
102
+ return [list, err]
103
+ } finally {
104
+ await file!.Close()
101
105
  }
102
- return [list, err]
103
106
  }
104
107
 
105
108
  class dirInfo {
package/gs/io/fs/sub.ts CHANGED
@@ -164,14 +164,14 @@ class subFS {
164
164
  return [file, f!.fixErr(err)]
165
165
  }
166
166
 
167
- public ReadDir(name: string): [$.Slice<DirEntry>, $.GoError] {
167
+ public async ReadDir(name: string): Promise<[$.Slice<DirEntry>, $.GoError]> {
168
168
  const f = this
169
169
  let [full, err] = f!.fullName('read', name)
170
170
  if (err != null) {
171
171
  return [null, err]
172
172
  }
173
173
  let dir: $.Slice<DirEntry>
174
- ;[dir, err] = ReadDir(f!.fsys, full)
174
+ ;[dir, err] = await ReadDir(f!.fsys, full)
175
175
  return [dir, f!.fixErr(err)]
176
176
  }
177
177
 
@@ -186,7 +186,7 @@ class subFS {
186
186
  return [data, f!.fixErr(err)]
187
187
  }
188
188
 
189
- public Glob(pattern: string): [$.Slice<string>, $.GoError] {
189
+ public async Glob(pattern: string): Promise<[$.Slice<string>, $.GoError]> {
190
190
  const f = this
191
191
  {
192
192
  let [, err] = path.Match(pattern, '')
@@ -198,7 +198,7 @@ class subFS {
198
198
  return [$.arrayToSlice<string>(['.']), null]
199
199
  }
200
200
  let full = f!.dir + '/' + pattern
201
- let [list, err] = Glob(f!.fsys, full)
201
+ let [list, err] = await Glob(f!.fsys, full)
202
202
  for (let i = 0; i < $.len(list); i++) {
203
203
  const name = list![i]
204
204
  {
package/gs/io/fs/walk.ts CHANGED
@@ -39,7 +39,7 @@ export async function walkDir(
39
39
  }
40
40
  }
41
41
 
42
- let [dirs, err] = ReadDir(fsys, name)
42
+ let [dirs, err] = await ReadDir(fsys, name)
43
43
 
44
44
  // Second call, to report ReadDir error.
45
45
  if (err != null) {
package/gs/io/io.test.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  import * as $ from '@goscript/builtin/index.js'
2
- import { LimitedReader, MultiWriter, NopCloser, Pipe, TeeReader } from './index.js'
2
+ import {
3
+ LimitedReader,
4
+ MultiWriter,
5
+ NewSectionReader,
6
+ NopCloser,
7
+ Pipe,
8
+ TeeReader,
9
+ } from './index.js'
3
10
  import { describe, expect, test } from 'vitest'
4
11
 
5
12
  class sliceReader {
@@ -22,6 +29,15 @@ class captureWriter {
22
29
  }
23
30
  }
24
31
 
32
+ class syncReaderAt {
33
+ constructor(private data: Uint8Array) {}
34
+
35
+ ReadAt(p: $.Bytes, off: number): [number, $.GoError] {
36
+ const n = $.copy(p, this.data.subarray(off))
37
+ return [n, n < $.len(p) ? (new Error('EOF') as $.GoError) : null]
38
+ }
39
+ }
40
+
25
41
  describe('io override', () => {
26
42
  test('LimitedReader accepts generated struct-literal construction', async () => {
27
43
  const reader = new LimitedReader({
@@ -118,6 +134,45 @@ describe('io override', () => {
118
134
  expect(Buffer.from(chunks).toString('utf8')).toBe('abc')
119
135
  })
120
136
 
137
+ test('SectionReader preserves sync reads for sync ReaderAt', () => {
138
+ const reader = NewSectionReader(
139
+ new syncReaderAt($.stringToBytes('abcdef')),
140
+ 1,
141
+ 3,
142
+ )
143
+ const buf = new Uint8Array(4)
144
+
145
+ const result = reader.Read(buf)
146
+ expect(result).not.toBeInstanceOf(Promise)
147
+ const [n, err] = result
148
+
149
+ expect(err).toBeNull()
150
+ expect(n).toBe(3)
151
+ expect(Buffer.from(buf.subarray(0, n)).toString('utf8')).toBe('bcd')
152
+ })
153
+
154
+ test('SectionReader awaits async ReaderAt', async () => {
155
+ const reader = NewSectionReader(
156
+ {
157
+ async ReadAt(p: $.Bytes, off: number): Promise<[number, $.GoError]> {
158
+ await Promise.resolve()
159
+ const data = $.stringToBytes('abcdef')
160
+ const n = $.copy(p, data.subarray(off))
161
+ return [n, n < $.len(p) ? (new Error('EOF') as $.GoError) : null]
162
+ },
163
+ } as any,
164
+ 1,
165
+ 3,
166
+ )
167
+ const buf = new Uint8Array(4)
168
+
169
+ const [n, err] = await reader.Read(buf)
170
+
171
+ expect(err).toBeNull()
172
+ expect(n).toBe(3)
173
+ expect(Buffer.from(buf.subarray(0, n)).toString('utf8')).toBe('bcd')
174
+ })
175
+
121
176
  test('PipeReader waits for a later write', async () => {
122
177
  const [reader, writer] = Pipe()
123
178
  const buf = new Uint8Array(5)
package/gs/io/io.ts CHANGED
@@ -363,7 +363,15 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
363
363
  p = $.goSlice(p, 0, max)
364
364
  }
365
365
 
366
- const [n, err] = this.r.ReadAt(p, this.off)
366
+ const res = this.r.ReadAt(p, this.off) as any
367
+ if (res instanceof Promise) {
368
+ return res.then(([n, err]: [number, $.GoError]) => {
369
+ this.off += n
370
+ return [n, err]
371
+ }) as any
372
+ }
373
+
374
+ const [n, err] = res
367
375
  this.off += n
368
376
  return [n, err]
369
377
  }
@@ -400,7 +408,16 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
400
408
  off += this.base
401
409
  if (off + $.len(p) > this.limit) {
402
410
  p = $.goSlice(p, 0, this.limit - off)
403
- const [n, err] = this.r.ReadAt(p, off)
411
+ const res = this.r.ReadAt(p, off) as any
412
+ if (res instanceof Promise) {
413
+ return res.then(([n, err]: [number, $.GoError]) => {
414
+ if (err === null) {
415
+ return [n, EOF]
416
+ }
417
+ return [n, err]
418
+ }) as any
419
+ }
420
+ const [n, err] = res
404
421
  if (err === null) {
405
422
  return [n, EOF]
406
423
  }
package/gs/maps/iter.ts CHANGED
@@ -8,9 +8,9 @@ import * as iter from '@goscript/iter/index.js'
8
8
  export function All<K extends $.Comparable | null, V>(
9
9
  m: Map<K, V> | null,
10
10
  ): iter.Seq2<K, V> {
11
- return (_yield: ((p0: K, p1: V) => iter.YieldResult) | null):
12
- | void
13
- | globalThis.Promise<void> => iteratePairs(m?.entries() ?? [], _yield)
11
+ return (
12
+ _yield: ((p0: K, p1: V) => iter.YieldResult) | null,
13
+ ): void | globalThis.Promise<void> => iteratePairs(m?.entries() ?? [], _yield)
14
14
  }
15
15
 
16
16
  // Keys returns an iterator over keys in m.
@@ -19,9 +19,9 @@ export function All<K extends $.Comparable | null, V>(
19
19
  export function Keys<K extends $.Comparable | null, V>(
20
20
  m: Map<K, V> | null,
21
21
  ): iter.Seq<K> {
22
- return (_yield: ((p0: K) => iter.YieldResult) | null):
23
- | void
24
- | globalThis.Promise<void> => iterateValues(mapKeys(m), _yield)
22
+ return (
23
+ _yield: ((p0: K) => iter.YieldResult) | null,
24
+ ): void | globalThis.Promise<void> => iterateValues(mapKeys(m), _yield)
25
25
  }
26
26
 
27
27
  // Values returns an iterator over values in m.
@@ -30,9 +30,9 @@ export function Keys<K extends $.Comparable | null, V>(
30
30
  export function Values<K extends $.Comparable | null, V>(
31
31
  m: Map<K, V> | null,
32
32
  ): iter.Seq<V> {
33
- return (_yield: ((p0: V) => iter.YieldResult) | null):
34
- | void
35
- | globalThis.Promise<void> => iterateValues(mapValues(m), _yield)
33
+ return (
34
+ _yield: ((p0: V) => iter.YieldResult) | null,
35
+ ): void | globalThis.Promise<void> => iterateValues(mapValues(m), _yield)
36
36
  }
37
37
 
38
38
  // Insert adds the key-value pairs from seq to m.
package/gs/maps/maps.ts CHANGED
@@ -4,10 +4,10 @@ import * as _ from '@goscript/unsafe/index.js'
4
4
 
5
5
  // Equal reports whether two maps contain the same key/value pairs.
6
6
  // Values are compared using ==.
7
- export function Equal<K extends $.Comparable | null, V extends $.Comparable | null>(
8
- m1: Map<K, V>,
9
- m2: Map<K, V>,
10
- ): boolean {
7
+ export function Equal<
8
+ K extends $.Comparable | null,
9
+ V extends $.Comparable | null,
10
+ >(m1: Map<K, V>, m2: Map<K, V>): boolean {
11
11
  if ($.len(m1) != $.len(m2)) {
12
12
  return false
13
13
  }
@@ -1,6 +1,15 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
 
3
- import { Mul64, Rem, Rem32, Rem64, RotateLeft16, RotateLeft32, RotateLeft64, RotateLeft8 } from './index.js'
3
+ import {
4
+ Mul64,
5
+ Rem,
6
+ Rem32,
7
+ Rem64,
8
+ RotateLeft16,
9
+ RotateLeft32,
10
+ RotateLeft64,
11
+ RotateLeft8,
12
+ } from './index.js'
4
13
 
5
14
  describe('math/bits override', () => {
6
15
  it('returns the full 128-bit product from Mul64', () => {
@@ -22,14 +22,15 @@ describe('mime override', () => {
22
22
  expect(mediaType).toBe('text/plain')
23
23
  expect(params.get('charset')).toBe('utf-8')
24
24
  expect(params.get('format')).toBe('flowed')
25
- const [trailingMediaType, trailingParams, trailingErr] = ParseMediaType('text/plain;')
25
+ const [trailingMediaType, trailingParams, trailingErr] =
26
+ ParseMediaType('text/plain;')
26
27
  expect(trailingErr).toBeNull()
27
28
  expect(trailingMediaType).toBe('text/plain')
28
29
  expect(trailingParams.size).toBe(0)
29
30
 
30
- expect(
31
- FormatMediaType('text/plain', new Map([['charset', 'utf-8']])),
32
- ).toBe('text/plain; charset=utf-8')
31
+ expect(FormatMediaType('text/plain', new Map([['charset', 'utf-8']]))).toBe(
32
+ 'text/plain; charset=utf-8',
33
+ )
33
34
  expect(
34
35
  FormatMediaType('Attachment', new Map([['FileName', 'hello.txt']])),
35
36
  ).toBe('attachment; filename=hello.txt')
@@ -37,10 +38,13 @@ describe('mime override', () => {
37
38
  FormatMediaType('attachment', new Map([['filename', 'foo bar.txt']])),
38
39
  ).toBe('attachment; filename="foo bar.txt"')
39
40
  expect(
40
- FormatMediaType('text/plain', new Map([
41
- ['z', 'last'],
42
- ['a', 'first'],
43
- ])),
41
+ FormatMediaType(
42
+ 'text/plain',
43
+ new Map([
44
+ ['z', 'last'],
45
+ ['a', 'first'],
46
+ ]),
47
+ ),
44
48
  ).toBe('text/plain; a=first; z=last')
45
49
 
46
50
  const encoded = FormatMediaType(
@@ -51,13 +55,17 @@ describe('mime override', () => {
51
55
  const [, encodedParams, encodedErr] = ParseMediaType(encoded)
52
56
  expect(encodedErr).toBeNull()
53
57
  expect(encodedParams.get('filename')).toBe('résumé.txt')
54
- const [, pathParams, pathErr] = ParseMediaType('form-data; filename="C:\\dev\\go.txt"; quoted="a\\"b"')
58
+ const [, pathParams, pathErr] = ParseMediaType(
59
+ 'form-data; filename="C:\\dev\\go.txt"; quoted="a\\"b"',
60
+ )
55
61
  expect(pathErr).toBeNull()
56
62
  expect(pathParams.get('filename')).toBe('C:\\dev\\go.txt')
57
63
  expect(pathParams.get('quoted')).toBe('a"b')
58
64
 
59
65
  expect(TypeByExtension('.json')).toBe('application/json')
60
- expect(AddExtensionType('.goscript', 'text/plain; charset=utf-8')).toBeNull()
66
+ expect(
67
+ AddExtensionType('.goscript', 'text/plain; charset=utf-8'),
68
+ ).toBeNull()
61
69
  const [extensions, extensionErr] = ExtensionsByType('text/plain')
62
70
  expect(extensionErr).toBeNull()
63
71
  expect(extensions).toContain('.goscript')
@@ -66,10 +74,18 @@ describe('mime override', () => {
66
74
  it('reports invalid media parameters', () => {
67
75
  const [, , err] = ParseMediaType('text/plain; broken')
68
76
  expect(err).toBe(ErrInvalidMediaParameter)
69
- expect(ParseMediaType('text/plain; filename=foo bar')[2]).toBe(ErrInvalidMediaParameter)
70
- expect(ParseMediaType('text/plain; filename="unterminated')[2]).toBe(ErrInvalidMediaParameter)
71
- expect(ParseMediaType('text/plain; x=1; x=2')[2]).toBe(ErrInvalidMediaParameter)
72
- expect(ParseMediaType('text/plain; bad[]=x')[2]).toBe(ErrInvalidMediaParameter)
77
+ expect(ParseMediaType('text/plain; filename=foo bar')[2]).toBe(
78
+ ErrInvalidMediaParameter,
79
+ )
80
+ expect(ParseMediaType('text/plain; filename="unterminated')[2]).toBe(
81
+ ErrInvalidMediaParameter,
82
+ )
83
+ expect(ParseMediaType('text/plain; x=1; x=2')[2]).toBe(
84
+ ErrInvalidMediaParameter,
85
+ )
86
+ expect(ParseMediaType('text/plain; bad[]=x')[2]).toBe(
87
+ ErrInvalidMediaParameter,
88
+ )
73
89
  expect(ParseMediaType('text/plain; bad{}=x')[1].get('bad{}')).toBe('x')
74
90
  })
75
91
 
@@ -83,7 +99,9 @@ describe('mime override', () => {
83
99
  expect(qWord).toBe('hello world')
84
100
 
85
101
  const encodedQWord = WordEncoder_Encode(QEncoding, 'utf-8', 'héllo world')
86
- const [header, err] = new WordDecoder().DecodeHeader(`subject ${encodedQWord}`)
102
+ const [header, err] = new WordDecoder().DecodeHeader(
103
+ `subject ${encodedQWord}`,
104
+ )
87
105
  expect(err).toBeNull()
88
106
  expect(header).toBe('subject héllo world')
89
107
  })
package/gs/mime/index.ts CHANGED
@@ -52,7 +52,11 @@ export function FormatMediaType(
52
52
  param instanceof Map ?
53
53
  Array.from(param.entries())
54
54
  : Object.entries(param ?? {})
55
- entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
55
+ entries.sort(([a], [b]) =>
56
+ a < b ? -1
57
+ : a > b ? 1
58
+ : 0,
59
+ )
56
60
  for (const [key, value] of entries) {
57
61
  if (!isToken(key)) {
58
62
  return ''
@@ -92,7 +96,10 @@ export function ParseMediaType(
92
96
  if (key.endsWith('*')) {
93
97
  const decoded = decode2231Value(value)
94
98
  if (decoded !== null) {
95
- if (params.has(key.slice(0, -1)) && params.get(key.slice(0, -1)) !== decoded) {
99
+ if (
100
+ params.has(key.slice(0, -1)) &&
101
+ params.get(key.slice(0, -1)) !== decoded
102
+ ) {
96
103
  return ['', new Map(), ErrInvalidMediaParameter]
97
104
  }
98
105
  params.set(key.slice(0, -1), decoded)
@@ -47,20 +47,34 @@ describe('net/http/httptest override', () => {
47
47
  })
48
48
 
49
49
  it('exports request defaults and recorder compatibility helpers', () => {
50
- const req = NewRequestWithContext(context.Background(), '', 'https://example.invalid/path', null)
50
+ const req = NewRequestWithContext(
51
+ context.Background(),
52
+ '',
53
+ 'https://example.invalid/path',
54
+ null,
55
+ )
51
56
  expect(DefaultRemoteAddr).toBe('1.2.3.4')
52
57
  expect(req.Method).toBe(MethodGet)
53
58
  expect(req.Host).toBe('example.invalid')
54
59
  expect(req.RemoteAddr).toBe('192.0.2.1:1234')
55
60
  expect(req.TLS).not.toBeNull()
56
61
 
57
- const pathReq = NewRequestWithContext(context.Background(), MethodGet, '/local?x=1', null)
62
+ const pathReq = NewRequestWithContext(
63
+ context.Background(),
64
+ MethodGet,
65
+ '/local?x=1',
66
+ null,
67
+ )
58
68
  expect(pathReq.Host).toBe('example.com')
59
69
  expect(pathReq.RequestURI).toBe('/local?x=1')
60
70
  expect(pathReq.URL.Host).toBe('')
61
71
  expect(pathReq.URL.Scheme).toBe('')
62
72
 
63
- const bodyReq = NewTestRequest(MethodPost, '/body', bytes.NewReader($.stringToBytes('abc')))
73
+ const bodyReq = NewTestRequest(
74
+ MethodPost,
75
+ '/body',
76
+ bytes.NewReader($.stringToBytes('abc')),
77
+ )
64
78
  expect(bodyReq.ContentLength).toBe(3)
65
79
  const noBodyReq = NewTestRequest(MethodPost, '/empty', NoBody)
66
80
  expect(noBodyReq.ContentLength).toBe(0)
@@ -117,7 +117,11 @@ function requestBodyContentLength(body: io.Reader | null): number {
117
117
  if (value === http.NoBody) {
118
118
  return 0
119
119
  }
120
- if (value instanceof bytes.Buffer || value instanceof bytes.Reader || value instanceof strings.Reader) {
120
+ if (
121
+ value instanceof bytes.Buffer ||
122
+ value instanceof bytes.Reader ||
123
+ value instanceof strings.Reader
124
+ ) {
121
125
  return value.Len()
122
126
  }
123
127
  return -1
@@ -133,7 +137,8 @@ export class Server {
133
137
 
134
138
  constructor(init?: Partial<Server> & { Handler?: http.Handler | null }) {
135
139
  this.handler = init?.Handler ?? null
136
- this.ConfigValue = init?.ConfigValue ?? new http.Server({ Handler: this.handler })
140
+ this.ConfigValue =
141
+ init?.ConfigValue ?? new http.Server({ Handler: this.handler })
137
142
  this.URL = init?.URL ?? http.RegisterInProcessServer(this.handler)
138
143
  }
139
144
 
@@ -200,7 +205,7 @@ function serverRequest(request: http.Request): http.Request {
200
205
  const rawQuery = request.URL?.RawQuery ?? ''
201
206
  const query = rawQuery === '' ? '' : `?${rawQuery}`
202
207
  req.RequestURI = `${request.URL?.Path ?? '/'}${query}`
203
- req.Host = request.Host === '' ? request.URL?.Host ?? '' : request.Host
208
+ req.Host = request.Host === '' ? (request.URL?.Host ?? '') : request.Host
204
209
  if (req.URL?.clone != null) {
205
210
  req.URL = req.URL.clone()
206
211
  req.URL.Scheme = ''