goscript 0.2.3 → 0.2.4

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 (46) hide show
  1. package/compiler/lowering.go +57 -8
  2. package/compiler/override-registry_test.go +125 -0
  3. package/compiler/skeleton_test.go +49 -2
  4. package/dist/gs/compress/gzip/index.d.ts +41 -0
  5. package/dist/gs/compress/gzip/index.js +235 -0
  6. package/dist/gs/compress/gzip/index.js.map +1 -0
  7. package/dist/gs/io/fs/glob.js +1 -1
  8. package/dist/gs/io/fs/glob.js.map +1 -1
  9. package/dist/gs/io/fs/readlink.d.ts +1 -1
  10. package/dist/gs/io/fs/readlink.js +2 -2
  11. package/dist/gs/io/fs/readlink.js.map +1 -1
  12. package/dist/gs/io/fs/stat.d.ts +4 -2
  13. package/dist/gs/io/fs/stat.js +12 -73
  14. package/dist/gs/io/fs/stat.js.map +1 -1
  15. package/dist/gs/io/fs/sub.d.ts +2 -2
  16. package/dist/gs/io/fs/sub.js +7 -7
  17. package/dist/gs/io/fs/sub.js.map +1 -1
  18. package/dist/gs/io/fs/walk.js +1 -1
  19. package/dist/gs/io/fs/walk.js.map +1 -1
  20. package/dist/gs/net/http/index.d.ts +18 -14
  21. package/dist/gs/net/http/index.js +44 -23
  22. package/dist/gs/net/http/index.js.map +1 -1
  23. package/dist/gs/net/http/pprof/index.d.ts +5 -5
  24. package/dist/gs/net/http/pprof/index.js +21 -21
  25. package/dist/gs/net/http/pprof/index.js.map +1 -1
  26. package/gs/builtin/runtime-contract.test.ts +25 -0
  27. package/gs/compress/gzip/index.test.ts +86 -0
  28. package/gs/compress/gzip/index.ts +297 -0
  29. package/gs/compress/gzip/meta.json +6 -0
  30. package/gs/compress/gzip/parity.json +45 -0
  31. package/gs/embed/index.test.ts +1 -1
  32. package/gs/io/fs/glob.ts +1 -1
  33. package/gs/io/fs/meta.json +3 -0
  34. package/gs/io/fs/readlink.test.ts +2 -2
  35. package/gs/io/fs/readlink.ts +5 -2
  36. package/gs/io/fs/stat.test.ts +79 -0
  37. package/gs/io/fs/stat.ts +24 -10
  38. package/gs/io/fs/sub.test.ts +93 -0
  39. package/gs/io/fs/sub.ts +9 -9
  40. package/gs/io/fs/walk.ts +1 -1
  41. package/gs/net/http/index.test.ts +207 -2
  42. package/gs/net/http/index.ts +68 -37
  43. package/gs/net/http/meta.json +3 -1
  44. package/gs/net/http/pprof/index.test.ts +4 -4
  45. package/gs/net/http/pprof/index.ts +30 -27
  46. package/package.json +1 -1
package/gs/io/fs/walk.ts CHANGED
@@ -88,7 +88,7 @@ export async function WalkDir(
88
88
  root: string,
89
89
  fn: WalkDirFunc,
90
90
  ): Promise<$.GoError> {
91
- let [info, err] = Stat(fsys, root)
91
+ let [info, err] = await Stat(fsys, root)
92
92
  if (err != null) {
93
93
  err = await fn!(root, null, err)
94
94
  } else {
@@ -20,6 +20,7 @@ import {
20
20
  ErrServerClosed,
21
21
  File,
22
22
  FileServer,
23
+ FileServerFS,
23
24
  FileSystem,
24
25
  FS,
25
26
  Get,
@@ -192,6 +193,36 @@ describe('net/http override', () => {
192
193
  expect(protocols.String()).toBe('{HTTP1,UnencryptedHTTP2}')
193
194
  })
194
195
 
196
+ it('accepts pointer-wrapped headers from generated ResponseWriter methods', () => {
197
+ const header = varRef(new Header())
198
+
199
+ Header_Set(header, 'content-length', '12')
200
+ Header_Add(header, 'content-type', 'text/plain')
201
+
202
+ expect(Header_Get(header, 'Content-Length')).toBe('12')
203
+ expect(Array.from(Header_Values(header, 'Content-Type') ?? [])).toEqual([
204
+ 'text/plain',
205
+ ])
206
+
207
+ const cloned = Header_Clone(header)
208
+ Header_Del(header, 'Content-Type')
209
+
210
+ expect(Header_Get(header, 'Content-Type')).toBe('')
211
+ expect(Header_Get(cloned, 'Content-Type')).toBe('text/plain')
212
+ })
213
+
214
+ it('accepts interface-boxed named headers from generated interface calls', () => {
215
+ const header = $.namedValueInterfaceValue(new Header(), 'http.Header', {})
216
+
217
+ Header_Set(header, 'content-length', '12')
218
+ Header_Add(header, 'content-type', 'text/plain')
219
+
220
+ expect(Header_Get(header, 'Content-Length')).toBe('12')
221
+ expect(Array.from(Header_Values(header, 'Content-Type') ?? [])).toEqual([
222
+ 'text/plain',
223
+ ])
224
+ })
225
+
195
226
  it('validates outgoing request construction', () => {
196
227
  const [req, reqErr] = NewRequestWithContext(
197
228
  context.Background(),
@@ -1171,7 +1202,7 @@ describe('net/http override', () => {
1171
1202
  ])
1172
1203
  })
1173
1204
 
1174
- it('formats Set-Cookie headers for browser bootstrap routes', () => {
1205
+ it('formats Set-Cookie headers for browser bootstrap routes', async () => {
1175
1206
  const header = new Header()
1176
1207
  const writer: ResponseWriter = {
1177
1208
  Header: () => header,
@@ -1179,7 +1210,7 @@ describe('net/http override', () => {
1179
1210
  WriteHeader: () => undefined,
1180
1211
  }
1181
1212
 
1182
- SetCookie(
1213
+ await SetCookie(
1183
1214
  writer,
1184
1215
  new Cookie({
1185
1216
  Name: 'spacewave_local_capability',
@@ -1314,6 +1345,7 @@ describe('net/http override', () => {
1314
1345
  expect(opened).toEqual(['file.txt'])
1315
1346
  expect(writes).toEqual(['status:200', 'hello'])
1316
1347
  expect(Header_Get(header, 'Content-Length')).toBe('5')
1348
+ expect(Header_Get(header, 'Content-Type')).toBe('text/plain; charset=utf-8')
1317
1349
 
1318
1350
  writes.length = 0
1319
1351
  opened.length = 0
@@ -1399,6 +1431,179 @@ describe('net/http override', () => {
1399
1431
  expect(closeCalls).toEqual(['async.txt'])
1400
1432
  })
1401
1433
 
1434
+ it('serves files through FS adapters backed by async io/fs Open', async () => {
1435
+ const opened: string[] = []
1436
+ const root = {
1437
+ async Open(name: string) {
1438
+ opened.push(name)
1439
+ const data = $.stringToBytes('fs-adapter')
1440
+ let offset = 0
1441
+ return [
1442
+ {
1443
+ Close: async () => null,
1444
+ Read: async (p: $.Slice<number>) => {
1445
+ if (offset >= data.length) {
1446
+ return [0, io.EOF] as [number, $.GoError]
1447
+ }
1448
+ const n = Math.min(p?.length ?? 0, data.length - offset)
1449
+ p?.set(data.subarray(offset, offset + n), 0)
1450
+ offset += n
1451
+ return [n, null] as [number, $.GoError]
1452
+ },
1453
+ Stat: async () => [
1454
+ {
1455
+ Name: () => name,
1456
+ Size: () => data.length,
1457
+ Mode: () => 0,
1458
+ ModTime: () => new time.Time(),
1459
+ IsDir: () => false,
1460
+ Sys: () => null,
1461
+ },
1462
+ null,
1463
+ ],
1464
+ },
1465
+ null,
1466
+ ]
1467
+ },
1468
+ }
1469
+ const writes: string[] = []
1470
+ const header = new Header()
1471
+ const writer: ResponseWriter = {
1472
+ Header: () => header,
1473
+ Write: (p) => {
1474
+ writes.push(Buffer.from(p ?? []).toString('utf8'))
1475
+ return [p?.length ?? 0, null]
1476
+ },
1477
+ WriteHeader: (code) => writes.push(`status:${code}`),
1478
+ }
1479
+ const [req] = NewRequest(
1480
+ MethodGet,
1481
+ 'http://example.invalid/dir/fs-adapter.txt',
1482
+ null,
1483
+ )
1484
+
1485
+ await FileServerFS(root).ServeHTTP(writer, req)
1486
+
1487
+ expect(opened).toEqual(['dir/fs-adapter.txt'])
1488
+ expect(writes).toEqual(['status:200', 'fs-adapter'])
1489
+ expect(Header_Get(header, 'Content-Length')).toBe('10')
1490
+ })
1491
+
1492
+ it('serves files through async response writer adapters', async () => {
1493
+ const root = {
1494
+ async Open(name: string) {
1495
+ const data = $.stringToBytes('async-adapter')
1496
+ return [
1497
+ {
1498
+ Read: (p: $.Slice<number>) => {
1499
+ p?.set(data.subarray(0, p.length))
1500
+ return [data.length, io.EOF] as [number, $.GoError]
1501
+ },
1502
+ Close: async () => null,
1503
+ Stat: async () => [
1504
+ {
1505
+ Name: () => name,
1506
+ Size: () => data.length,
1507
+ Mode: () => 0,
1508
+ ModTime: () => new time.Time(),
1509
+ IsDir: () => false,
1510
+ Sys: () => null,
1511
+ },
1512
+ null,
1513
+ ],
1514
+ },
1515
+ null,
1516
+ ] as [File, $.GoError]
1517
+ },
1518
+ }
1519
+ const writes: string[] = []
1520
+ const header = new Header()
1521
+ const writer: ResponseWriter = {
1522
+ Header: async () => header,
1523
+ Write: async (p) => {
1524
+ writes.push(Buffer.from(p ?? []).toString('utf8'))
1525
+ return [p?.length ?? 0, null]
1526
+ },
1527
+ WriteHeader: async (code) => {
1528
+ writes.push(`status:${code}`)
1529
+ },
1530
+ }
1531
+ const [req] = NewRequest(
1532
+ MethodGet,
1533
+ 'http://example.invalid/async-adapter.txt',
1534
+ null,
1535
+ )
1536
+
1537
+ await FileServer(root).ServeHTTP(writer, req)
1538
+
1539
+ expect(writes).toEqual(['status:200', 'async-adapter'])
1540
+ expect(Header_Get(header, 'Content-Length')).toBe('13')
1541
+ })
1542
+
1543
+ it('writes file server headers before reading response bodies', async () => {
1544
+ let headerWritten = false
1545
+ let readSawHeader = false
1546
+ let offset = 0
1547
+ const data = $.stringToBytes('streamed-body')
1548
+ const root = {
1549
+ async Open(name: string) {
1550
+ return [
1551
+ {
1552
+ Close: async () => null,
1553
+ Read: async (p: $.Slice<number>) => {
1554
+ readSawHeader = headerWritten
1555
+ if (offset >= data.length) {
1556
+ return [0, io.EOF] as [number, $.GoError]
1557
+ }
1558
+ const n = Math.min(p?.length ?? 0, data.length - offset)
1559
+ p?.set(data.subarray(offset, offset + n), 0)
1560
+ offset += n
1561
+ return [n, null] as [number, $.GoError]
1562
+ },
1563
+ Seek: async () => [0, null] as [number, $.GoError],
1564
+ Readdir: async () => [null, null] as [null, $.GoError],
1565
+ Stat: async () => [
1566
+ {
1567
+ Name: () => name,
1568
+ Size: () => data.length,
1569
+ Mode: () => 0,
1570
+ ModTime: () => null as never,
1571
+ IsDir: () => false,
1572
+ Sys: () => null,
1573
+ },
1574
+ null,
1575
+ ],
1576
+ },
1577
+ null,
1578
+ ] as [File, $.GoError]
1579
+ },
1580
+ }
1581
+ const writes: string[] = []
1582
+ const header = new Header()
1583
+ const writer: ResponseWriter = {
1584
+ Header: () => header,
1585
+ Write: (p) => {
1586
+ writes.push(Buffer.from(p ?? []).toString('utf8'))
1587
+ return [p?.length ?? 0, null]
1588
+ },
1589
+ WriteHeader: (code) => {
1590
+ headerWritten = true
1591
+ writes.push(`status:${code}`)
1592
+ },
1593
+ }
1594
+ const [req] = NewRequest(
1595
+ MethodGet,
1596
+ 'http://example.invalid/streamed.mjs',
1597
+ null,
1598
+ )
1599
+
1600
+ await FileServer(root).ServeHTTP(writer, req)
1601
+
1602
+ expect(readSawHeader).toBe(true)
1603
+ expect(writes).toEqual(['status:200', 'streamed-body'])
1604
+ expect(Header_Get(header, 'Content-Type')).toBe('text/javascript; charset=utf-8')
1605
+ })
1606
+
1402
1607
  it('awaits ServeContent writes before returning', async () => {
1403
1608
  const writes: string[] = []
1404
1609
  const writer: ResponseWriter = {
@@ -4,6 +4,8 @@ import * as context from '@goscript/context/index.js'
4
4
  import * as errors from '@goscript/errors/index.js'
5
5
  import * as fs from '@goscript/io/fs/fs.js'
6
6
  import * as io from '@goscript/io/index.js'
7
+ import * as mime from '@goscript/mime/index.js'
8
+ import * as path from '@goscript/path/index.js'
7
9
  import * as strings from '@goscript/strings/index.js'
8
10
  import * as time from '@goscript/time/index.js'
9
11
 
@@ -248,6 +250,8 @@ export function StatusText(code: number): string {
248
250
  }
249
251
 
250
252
  export type Header = Map<string, $.Slice<string>>
253
+ type HeaderBox = { __goValue: HeaderValue }
254
+ type HeaderValue = Header | $.VarRef<Header> | HeaderBox
251
255
 
252
256
  export const Header = Map as {
253
257
  new (entries?: Iterable<readonly [string, $.Slice<string>]> | null): Header
@@ -257,48 +261,62 @@ export function CanonicalHeaderKey(s: string): string {
257
261
  return canonicalMIMEHeaderKey(s)
258
262
  }
259
263
 
260
- export function Header_Add(h: Header, key: string, value: string): void {
264
+ function headerMap(h: HeaderValue): Header {
265
+ let value: unknown = $.pointerValue(h as Header | $.VarRef<Header>)
266
+ while (
267
+ value !== null &&
268
+ value !== undefined &&
269
+ typeof value === 'object' &&
270
+ '__goValue' in value
271
+ ) {
272
+ value = $.pointerValue((value as HeaderBox).__goValue)
273
+ }
274
+ return value as Header
275
+ }
276
+
277
+ export function Header_Add(h: HeaderValue, key: string, value: string): void {
278
+ const headers = headerMap(h)
261
279
  key = canonicalMIMEHeaderKey(key)
262
- const values = Array.from(h.get(key) ?? [])
280
+ const values = Array.from(headers.get(key) ?? [])
263
281
  values.push(value)
264
- h.set(key, $.arrayToSlice(values))
282
+ headers.set(key, $.arrayToSlice(values))
265
283
  }
266
284
 
267
- export function Header_Del(h: Header, key: string): void {
268
- h.delete(canonicalMIMEHeaderKey(key))
285
+ export function Header_Del(h: HeaderValue, key: string): void {
286
+ headerMap(h).delete(canonicalMIMEHeaderKey(key))
269
287
  }
270
288
 
271
- export function Header_Get(h: Header, key: string): string {
272
- const values = h.get(canonicalMIMEHeaderKey(key))
289
+ export function Header_Get(h: HeaderValue, key: string): string {
290
+ const values = headerMap(h).get(canonicalMIMEHeaderKey(key))
273
291
  return values == null || values.length === 0 ? '' : String(values[0])
274
292
  }
275
293
 
276
- export function Header_Set(h: Header, key: string, value: string): void {
277
- h.set(canonicalMIMEHeaderKey(key), $.arrayToSlice([value]))
294
+ export function Header_Set(h: HeaderValue, key: string, value: string): void {
295
+ headerMap(h).set(canonicalMIMEHeaderKey(key), $.arrayToSlice([value]))
278
296
  }
279
297
 
280
- export function Header_Values(h: Header, key: string): $.Slice<string> {
281
- return h.get(canonicalMIMEHeaderKey(key)) ?? null
298
+ export function Header_Values(h: HeaderValue, key: string): $.Slice<string> {
299
+ return headerMap(h).get(canonicalMIMEHeaderKey(key)) ?? null
282
300
  }
283
301
 
284
- export function Header_Clone(h: Header): Header {
302
+ export function Header_Clone(h: HeaderValue): Header {
285
303
  const cloned = new Header()
286
- for (const [key, values] of h.entries()) {
304
+ for (const [key, values] of headerMap(h).entries()) {
287
305
  cloned.set(key, $.arrayToSlice(Array.from(values ?? [])))
288
306
  }
289
307
  return cloned
290
308
  }
291
309
 
292
- export function Header_Write(h: Header, w: io.Writer): $.GoError {
310
+ export function Header_Write(h: HeaderValue, w: io.Writer): $.GoError {
293
311
  return Header_WriteSubset(h, w, null)
294
312
  }
295
313
 
296
314
  export function Header_WriteSubset(
297
- h: Header,
315
+ h: HeaderValue,
298
316
  w: io.Writer,
299
317
  exclude: Map<string, boolean> | null,
300
318
  ): $.GoError {
301
- for (const [key, values] of h.entries()) {
319
+ for (const [key, values] of headerMap(h).entries()) {
302
320
  if (exclude?.get(key) === true) {
303
321
  continue
304
322
  }
@@ -615,15 +633,15 @@ function asciiLower(value: string): [string, boolean] {
615
633
  return [value.toLowerCase(), true]
616
634
  }
617
635
 
618
- export function SetCookie(
636
+ export async function SetCookie(
619
637
  w: ResponseWriter | null,
620
638
  cookie: Cookie | $.VarRef<Cookie> | null,
621
- ): void {
639
+ ): Promise<void> {
622
640
  const c = $.pointerValue<Cookie | null>(cookie)
623
641
  if (w == null || c == null) {
624
642
  return
625
643
  }
626
- Header_Add(w.Header(), 'Set-Cookie', c.String())
644
+ Header_Add(await w.Header(), 'Set-Cookie', c.String())
627
645
  }
628
646
 
629
647
  class memoryResponseWriter implements ResponseWriter {
@@ -694,9 +712,9 @@ function inProcessServerRequest(request: Request): Request {
694
712
  }
695
713
 
696
714
  export interface ResponseWriter {
697
- Header(): Header
698
- Write(p: $.Slice<number>): [number, $.GoError]
699
- WriteHeader(statusCode: number): void
715
+ Header(): Header | Promise<Header>
716
+ Write(p: $.Slice<number>): [number, $.GoError] | Promise<[number, $.GoError]>
717
+ WriteHeader(statusCode: number): void | Promise<void>
700
718
  }
701
719
 
702
720
  export class Request {
@@ -1491,7 +1509,7 @@ async function readFetchBody(
1491
1509
  type maybePromise<T> = T | Promise<T>
1492
1510
 
1493
1511
  export interface FileSystem {
1494
- Open(name: string): [File | null, $.GoError]
1512
+ Open(name: string): maybePromise<[File | null, $.GoError]>
1495
1513
  }
1496
1514
 
1497
1515
  export interface File extends io.Closer, io.Reader, io.Seeker {
@@ -1513,9 +1531,9 @@ interface fileServerFile {
1513
1531
 
1514
1532
  export function FS(fsys: fs.FS): FileSystem {
1515
1533
  return {
1516
- Open(name: string): [File | null, $.GoError] {
1534
+ async Open(name: string): Promise<[File | null, $.GoError]> {
1517
1535
  const cleaned = cleanFileServerPath(name)
1518
- const [file, err] = fsys?.Open(cleaned) ?? [null, fs.ErrInvalid]
1536
+ const [file, err] = (await fsys?.Open(cleaned)) ?? [null, fs.ErrInvalid]
1519
1537
  if (err != null || file == null) {
1520
1538
  return [null, err]
1521
1539
  }
@@ -1570,17 +1588,27 @@ export function FileServer(root: fileServerFileSystem | null): Handler {
1570
1588
  NotFound(w, req)
1571
1589
  return
1572
1590
  }
1573
- const [data, readErr] = await io.ReadAll(file as io.Reader)
1574
- if (readErr != null) {
1575
- Error(w, readErr.Error(), StatusInternalServerError)
1576
- return
1591
+ const header = await w.Header()
1592
+ if (Header_Get(header, 'Content-Type') === '') {
1593
+ const contentType = mime.TypeByExtension(
1594
+ path.Ext(info?.Name?.() || req.URL?.Path || ''),
1595
+ )
1596
+ if (contentType !== '') {
1597
+ Header_Set(header, 'Content-Type', contentType)
1598
+ }
1577
1599
  }
1578
1600
  if (info?.Size != null) {
1579
- Header_Set(w.Header(), 'Content-Length', String(info.Size()))
1601
+ Header_Set(header, 'Content-Length', String(info.Size()))
1580
1602
  }
1581
- w.WriteHeader(StatusOK)
1603
+ await w.WriteHeader(StatusOK)
1582
1604
  if (req.Method !== MethodHead) {
1583
- w.Write(data)
1605
+ const [, copyErr] = await io.Copy(
1606
+ w as unknown as io.Writer,
1607
+ file as io.Reader,
1608
+ )
1609
+ if (copyErr != null) {
1610
+ return
1611
+ }
1584
1612
  }
1585
1613
  } finally {
1586
1614
  await file.Close()
@@ -2131,7 +2159,7 @@ export function NotFoundHandler(): Handler {
2131
2159
  export function RedirectHandler(url: string, code: number): Handler {
2132
2160
  return {
2133
2161
  ServeHTTP(w, r) {
2134
- Redirect(w, r, url, code)
2162
+ return Redirect(w, r, url, code)
2135
2163
  },
2136
2164
  }
2137
2165
  }
@@ -2168,17 +2196,20 @@ export function NotFound(
2168
2196
  Error(w, '404 page not found', StatusNotFound)
2169
2197
  }
2170
2198
 
2171
- export function Redirect(
2199
+ export async function Redirect(
2172
2200
  w: ResponseWriter | null,
2173
2201
  _r: Request | $.VarRef<Request> | null,
2174
2202
  url: string,
2175
2203
  code: number,
2176
- ): void {
2177
- const header = w?.Header()
2204
+ ): Promise<void> {
2205
+ if (w == null) {
2206
+ return
2207
+ }
2208
+ const header = await w.Header()
2178
2209
  if (header != null) {
2179
2210
  Header_Set(header, 'Location', url)
2180
2211
  }
2181
- w?.WriteHeader(code)
2212
+ await w.WriteHeader(code)
2182
2213
  }
2183
2214
 
2184
2215
  export function ParseTime(text: string): [time.Time, $.GoError] {
@@ -4,7 +4,9 @@
4
4
  "Head": true,
5
5
  "Post": true,
6
6
  "PostForm": true,
7
- "ServeContent": true
7
+ "Redirect": true,
8
+ "ServeContent": true,
9
+ "SetCookie": true
8
10
  },
9
11
  "asyncMethods": {
10
12
  "Client.Do": true,
@@ -27,19 +27,19 @@ class writer implements ResponseWriter {
27
27
  }
28
28
 
29
29
  describe('net/http/pprof override', () => {
30
- it('serves the index text expected by debug handlers', () => {
30
+ it('serves the index text expected by debug handlers', async () => {
31
31
  const w = new writer()
32
32
 
33
- Index(w, null)
33
+ await Index(w, null)
34
34
 
35
35
  expect(Header_Get(w.Header(), 'Content-Type')).toContain('text/html')
36
36
  expect(w.String()).toContain('full goroutine stack dump')
37
37
  })
38
38
 
39
- it('serves named runtime profiles', () => {
39
+ it('serves named runtime profiles', async () => {
40
40
  const w = new writer()
41
41
 
42
- Handler('goroutine').ServeHTTP(w, null)
42
+ await Handler('goroutine').ServeHTTP(w, null)
43
43
 
44
44
  expect(Header_Get(w.Header(), 'Content-Type')).toContain('text/plain')
45
45
  expect(w.String()).toContain('goroutine profile')
@@ -2,82 +2,85 @@ import * as $ from '@goscript/builtin/index.js'
2
2
  import * as http from '@goscript/net/http/index.js'
3
3
  import * as pprof from '@goscript/runtime/pprof/index.js'
4
4
 
5
- function writeString(w: http.ResponseWriter | null, value: string): void {
6
- w?.Write($.stringToBytes(value))
5
+ async function writeString(
6
+ w: http.ResponseWriter | null,
7
+ value: string,
8
+ ): Promise<void> {
9
+ await w?.Write($.stringToBytes(value))
7
10
  }
8
11
 
9
- export function Index(
12
+ export async function Index(
10
13
  w: http.ResponseWriter | null,
11
14
  _r: http.Request | $.VarRef<http.Request> | null,
12
- ): void {
13
- const header = w?.Header()
15
+ ): Promise<void> {
16
+ const header = await w?.Header()
14
17
  if (header != null) {
15
18
  http.Header_Set(header, 'Content-Type', 'text/html; charset=utf-8')
16
19
  }
17
- writeString(
20
+ await writeString(
18
21
  w,
19
22
  '<html><body><a href="goroutine?debug=2">full goroutine stack dump</a></body></html>',
20
23
  )
21
24
  }
22
25
 
23
- export function Cmdline(
26
+ export async function Cmdline(
24
27
  w: http.ResponseWriter | null,
25
28
  _r: http.Request | $.VarRef<http.Request> | null,
26
- ): void {
27
- const header = w?.Header()
29
+ ): Promise<void> {
30
+ const header = await w?.Header()
28
31
  if (header != null) {
29
32
  http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
30
33
  }
31
- writeString(w, 'goscript')
34
+ await writeString(w, 'goscript')
32
35
  }
33
36
 
34
- export function Profile(
37
+ export async function Profile(
35
38
  w: http.ResponseWriter | null,
36
39
  _r: http.Request | $.VarRef<http.Request> | null,
37
- ): void {
38
- const header = w?.Header()
40
+ ): Promise<void> {
41
+ const header = await w?.Header()
39
42
  if (header != null) {
40
43
  http.Header_Set(header, 'Content-Type', 'application/octet-stream')
41
44
  }
42
- writeString(w, 'cpu profile\n')
45
+ await writeString(w, 'cpu profile\n')
43
46
  }
44
47
 
45
- export function Symbol(
48
+ export async function Symbol(
46
49
  w: http.ResponseWriter | null,
47
50
  _r: http.Request | $.VarRef<http.Request> | null,
48
- ): void {
49
- const header = w?.Header()
51
+ ): Promise<void> {
52
+ const header = await w?.Header()
50
53
  if (header != null) {
51
54
  http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
52
55
  }
53
- writeString(w, 'num_symbols: 0\n')
56
+ await writeString(w, 'num_symbols: 0\n')
54
57
  }
55
58
 
56
- export function Trace(
59
+ export async function Trace(
57
60
  w: http.ResponseWriter | null,
58
61
  _r: http.Request | $.VarRef<http.Request> | null,
59
- ): void {
60
- const header = w?.Header()
62
+ ): Promise<void> {
63
+ const header = await w?.Header()
61
64
  if (header != null) {
62
65
  http.Header_Set(header, 'Content-Type', 'application/octet-stream')
63
66
  }
64
- writeString(w, 'trace\n')
67
+ await writeString(w, 'trace\n')
65
68
  }
66
69
 
67
70
  export function Handler(name: string): http.Handler {
68
71
  return {
69
- ServeHTTP(w) {
70
- const header = w?.Header()
72
+ async ServeHTTP(w) {
73
+ const header = await w?.Header()
71
74
  if (header != null) {
72
75
  http.Header_Set(header, 'Content-Type', 'text/plain; charset=utf-8')
73
76
  }
74
77
  const profile = pprof.Lookup(name)
75
78
  if (profile == null) {
76
- http.NotFound(w, null)
79
+ await http.NotFound(w, null)
77
80
  return
78
81
  }
79
- writeString(w, `${name} profile\n`)
80
- profile.WriteTo(w, 1)
82
+ await writeString(w, `${name} profile\n`)
83
+ profile.WriteTo(w as unknown as any, 1)
81
84
  },
82
85
  }
83
86
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goscript",
3
3
  "description": "Go to TypeScript transpiler",
4
- "version": "0.2.3",
4
+ "version": "0.2.4",
5
5
  "author": {
6
6
  "name": "Aperture Robotics LLC.",
7
7
  "email": "support@aperture.us",